go.ligato.io/vpp-agent/v3@v3.5.0/cmd/agentctl/commands/generate.go (about) 1 // Copyright (c) 2019 Cisco and/or its affiliates. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); 4 // you may not use this file except in compliance with the License. 5 // You may obtain a copy of the License at: 6 // 7 // http://www.apache.org/licenses/LICENSE-2.0 8 // 9 // Unless required by applicable law or agreed to in writing, software 10 // distributed under the License is distributed on an "AS IS" BASIS, 11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 // See the License for the specific language governing permissions and 13 // limitations under the License. 14 15 package commands 16 17 import ( 18 "context" 19 "fmt" 20 "strings" 21 22 "github.com/ghodss/yaml" 23 "github.com/sirupsen/logrus" 24 "github.com/spf13/cobra" 25 "google.golang.org/protobuf/encoding/protojson" 26 "google.golang.org/protobuf/encoding/prototext" 27 28 "go.ligato.io/vpp-agent/v3/cmd/agentctl/api/types" 29 agentcli "go.ligato.io/vpp-agent/v3/cmd/agentctl/cli" 30 ) 31 32 const defaultIndent = " " 33 34 func NewGenerateCommand(cli agentcli.Cli) *cobra.Command { 35 var ( 36 opts GenerateOptions 37 ) 38 cmd := &cobra.Command{ 39 Use: "generate MODEL", 40 Aliases: []string{"gen"}, 41 Short: "Generate config samples", 42 Args: cobra.ExactArgs(1), 43 RunE: func(cmd *cobra.Command, args []string) error { 44 opts.Model = args[0] 45 return runGenerate(cli, opts) 46 }, 47 } 48 flags := cmd.Flags() 49 flags.StringVarP(&opts.Format, "format", "f", "json", 50 "Output formats: json, yaml") 51 flags.BoolVar(&opts.OneLine, "oneline", false, 52 "Print output as single line (only json format)") 53 return cmd 54 } 55 56 type GenerateOptions struct { 57 Model string 58 Format string 59 OneLine bool 60 } 61 62 func runGenerate(cli agentcli.Cli, opts GenerateOptions) error { 63 ctx, cancel := context.WithCancel(context.Background()) 64 defer cancel() 65 66 allModels, err := cli.Client().ModelList(ctx, types.ModelListOptions{ 67 Class: "config", 68 }) 69 if err != nil { 70 return err 71 } 72 73 modelList := filterModelsByRefs(allModels, []string{opts.Model}) 74 75 if len(modelList) == 0 { 76 return fmt.Errorf("no model found for: %s", opts.Model) 77 } 78 79 logrus.Debugf("models: %+v", modelList) 80 model := modelList[0] 81 82 valueType := protoMessageType(model.ProtoName) 83 if valueType == nil { 84 return fmt.Errorf("unknown proto message defined for: %s", model.ProtoName) 85 } 86 modelInstance := valueType.New().Interface() 87 88 var out string 89 90 switch strings.ToLower(opts.Format) { 91 case "j", "json": 92 m := protojson.MarshalOptions{ 93 UseEnumNumbers: false, 94 EmitUnpopulated: true, 95 AllowPartial: true, 96 Indent: defaultIndent, 97 UseProtoNames: true, 98 Resolver: nil, 99 } 100 if opts.OneLine { 101 m.Indent = "" 102 } 103 b, err := m.Marshal(modelInstance) 104 if err != nil { 105 return fmt.Errorf("encoding to json failed: %v", err) 106 } 107 out = string(b) 108 case "y", "yaml": 109 m := protojson.MarshalOptions{ 110 UseEnumNumbers: false, 111 AllowPartial: true, 112 EmitUnpopulated: true, 113 Indent: defaultIndent, 114 UseProtoNames: true, 115 Resolver: nil, 116 } 117 if opts.OneLine { 118 m.Indent = "" 119 } 120 b, err := m.Marshal(modelInstance) 121 if err != nil { 122 return fmt.Errorf("encoding to json failed: %v", err) 123 } 124 b, err = yaml.JSONToYAML(b) 125 if err != nil { 126 return fmt.Errorf("encoding to yaml failed: %v", err) 127 } 128 out = string(b) 129 case "p", "proto": 130 m := prototext.MarshalOptions{ 131 AllowPartial: true, 132 Indent: " ", 133 Resolver: nil, 134 } 135 b, err := m.Marshal(modelInstance) 136 if err != nil { 137 return fmt.Errorf("encoding to proto text failed: %v", err) 138 } 139 out = string(b) 140 default: 141 return fmt.Errorf("unknown format: %s", opts.Format) 142 } 143 144 fmt.Fprintf(cli.Out(), "%s\n", out) 145 return nil 146 }