mirror of https://github.com/status-im/consul.git
Add CLI support for json (#18991)
* add cli support for json format * add tests for json parsing * make owner and id pointers. * add copyright header * remove print --------- Co-authored-by: Poonam Jadhav <poonam.jadhav@hashicorp.com>
This commit is contained in:
parent
11d6b0df45
commit
d3bb5ff21a
|
@ -4,9 +4,12 @@
|
|||
package resource
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
"google.golang.org/protobuf/encoding/protojson"
|
||||
"google.golang.org/protobuf/types/known/anypb"
|
||||
"net/http"
|
||||
"strings"
|
||||
|
||||
|
@ -17,14 +20,87 @@ import (
|
|||
"github.com/hashicorp/consul/proto-public/pbresource"
|
||||
)
|
||||
|
||||
type OuterResource struct {
|
||||
ID *ID `json:"id"`
|
||||
Owner *ID `json:"owner"`
|
||||
Generation string `json:"generation"`
|
||||
Version string `json:"version"`
|
||||
Metadata map[string]any `json:"metadata"`
|
||||
Data map[string]any `json:"data"`
|
||||
}
|
||||
|
||||
type Tenancy struct {
|
||||
Namespace string `json:"namespace"`
|
||||
Partition string `json:"partition"`
|
||||
PeerName string `json:"peerName"`
|
||||
}
|
||||
type Type struct {
|
||||
Group string `json:"group"`
|
||||
GroupVersion string `json:"groupVersion"`
|
||||
Kind string `json:"kind"`
|
||||
}
|
||||
type ID struct {
|
||||
Name string `json:"name"`
|
||||
Tenancy Tenancy `json:"tenancy"`
|
||||
Type Type `json:"type"`
|
||||
UID string `json:"uid"`
|
||||
}
|
||||
|
||||
func parseJson(js string) (*pbresource.Resource, error) {
|
||||
|
||||
parsedResource := new(pbresource.Resource)
|
||||
|
||||
var outerResource OuterResource
|
||||
|
||||
if err := json.Unmarshal([]byte(js), &outerResource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if outerResource.ID == nil {
|
||||
return nil, fmt.Errorf("\"id\" field need to be provided")
|
||||
}
|
||||
|
||||
typ := pbresource.Type{
|
||||
Kind: outerResource.ID.Type.Kind,
|
||||
Group: outerResource.ID.Type.Group,
|
||||
GroupVersion: outerResource.ID.Type.GroupVersion,
|
||||
}
|
||||
|
||||
reg, ok := consul.NewTypeRegistry().Resolve(&typ)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("invalid type %v", parsedResource)
|
||||
}
|
||||
data := reg.Proto.ProtoReflect().New().Interface()
|
||||
anyProtoMsg, err := anypb.New(data)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
outerResource.Data["@type"] = anyProtoMsg.TypeUrl
|
||||
|
||||
marshal, err := json.Marshal(outerResource)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := protojson.Unmarshal(marshal, parsedResource); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return parsedResource, nil
|
||||
}
|
||||
|
||||
func ParseResourceFromFile(filePath string) (*pbresource.Resource, error) {
|
||||
data, err := helpers.LoadDataSourceNoRaw(filePath, nil)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to load data: %v", err)
|
||||
}
|
||||
parsedResource, err := resourcehcl.Unmarshal([]byte(data), consul.NewTypeRegistry())
|
||||
var parsedResource *pbresource.Resource
|
||||
parsedResource, err = resourcehcl.Unmarshal([]byte(data), consul.NewTypeRegistry())
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to decode resource from input file: %v", err)
|
||||
parsedResource, err = parseJson(data)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("Failed to decode resource from input file: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
return parsedResource, nil
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
// Copyright (c) HashiCorp, Inc.
|
||||
// SPDX-License-Identifier: BUSL-1.1
|
||||
|
||||
package resource
|
||||
|
||||
import (
|
||||
"github.com/stretchr/testify/require"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func Test_parseJson(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
js string
|
||||
wantErr bool
|
||||
}{
|
||||
{"valid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"generation\": \"01HAYWBPV1KMT2KWECJ6CEWDQ0\",\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\",\n \"peerName\": \"local\"\n },\n \"type\": {\n \"group\": \"demo\",\n \"groupVersion\": \"v2\",\n \"kind\": \"Artist\"\n },\n \"uid\": \"01HAYWBPV1KMT2KWECJ4NW88S1\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n },\n \"version\": \"18\"\n}", false},
|
||||
{"invalid resource", "{\n \"data\": {\n \"genre\": \"GENRE_METAL\",\n \"name\": \"Korn\"\n },\n \"id\": {\n \"name\": \"korn\",\n \"tenancy\": {\n \"namespace\": \"default\",\n \"partition\": \"default\",\n \"peerName\": \"local\"\n },\n \"type\": \"\"\n },\n \"metadata\": {\n \"foo\": \"bar\"\n }\n}\n", true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, err := parseJson(tt.js)
|
||||
if tt.wantErr {
|
||||
require.Error(t, err)
|
||||
require.Nil(t, got)
|
||||
} else {
|
||||
require.NoError(t, err)
|
||||
require.NotNil(t, got)
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue