-
Notifications
You must be signed in to change notification settings - Fork 5
/
update.go
152 lines (119 loc) · 5.02 KB
/
update.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
package manipcli
import (
"context"
"encoding/json"
"fmt"
"time"
"github.com/ghodss/yaml"
"github.com/spf13/cobra"
"github.com/spf13/viper"
"go.aporeto.io/elemental"
"go.aporeto.io/manipulate"
)
// generateUpdateCommandForIdentity generates the command to update an object based on its identity.
func generateUpdateCommandForIdentity(identity elemental.Identity, modelManager elemental.ModelManager, manipulatorMaker ManipulatorMaker, options ...cmdOption) (*cobra.Command, error) {
cfg := &cmdConfig{}
for _, opt := range options {
opt(cfg)
}
cmd := &cobra.Command{
Use: fmt.Sprintf("%s <id-or-name>", identity.Name),
Aliases: []string{identity.Category},
Short: "Update an existing " + identity.Name,
Args: cobra.ExactArgs(1),
RunE: func(cmd *cobra.Command, args []string) error {
fParam := viper.GetStringSlice("param")
fTrackingID := viper.GetString(flagTrackingID)
fOutput := viper.GetString(flagOutput)
fFormatTypeColumn := viper.GetStringSlice(formatTypeColumn)
fOutputTemplate := viper.GetString(flagOutputTemplate)
fForce := viper.GetBool(flagForce)
manipulator, err := manipulatorMaker()
if err != nil {
return fmt.Errorf("unable to make manipulator: %w", err)
}
parameters, err := parametersToURLValues(fParam)
if err != nil {
return fmt.Errorf("unable to convert parameters to url values: %w", err)
}
options := []manipulate.ContextOption{
manipulate.ContextOptionTracking(fTrackingID, "cli"),
manipulate.ContextOptionParameters(parameters),
manipulate.ContextOptionFields(fFormatTypeColumn),
manipulate.ContextOptionOverride(fForce),
}
retrieveCtx, retrieveCancel := context.WithTimeout(cmd.Context(), 20*time.Second)
defer retrieveCancel()
mctx := manipulate.NewContext(retrieveCtx, options...)
identifiable, err := retrieveObjectByIDOrByName(mctx, manipulator, identity, args[0], modelManager)
if err != nil {
return fmt.Errorf("unable to retrieve %s: %w", identity.Name, err)
}
if viper.GetBool(flagInteractive) {
data, err := openInEditor(identifiable, viper.GetString(flagEditor), cmd.Short, true, false, false)
if err != nil {
return fmt.Errorf("unable to open editor %s: %w", viper.GetString(flagEditor), err)
}
if data == nil {
return fmt.Errorf("empty data")
}
if err := json.Unmarshal(data, identifiable); err != nil {
return fmt.Errorf("unable to unmarshall: %w", err)
}
} else if viper.IsSet(flagInputValues) || viper.IsSet(flagInputData) || viper.IsSet(flagInputFile) || viper.IsSet(flagInputURL) {
data, err := readData(false)
if err != nil {
return fmt.Errorf("unable to read data: %w", err)
}
if data != nil {
data, err = yaml.YAMLToJSON(data)
if err != nil {
return err
}
}
if err := json.Unmarshal(data, identifiable); err != nil {
return fmt.Errorf("unable to unmarshall: %w", err)
}
} else {
if err := readViperFlags(identifiable, modelManager, cfg.argumentsPrefix); err != nil {
return fmt.Errorf("unable to read flags: %w", err)
}
}
updateCtx, updateCancel := context.WithTimeout(cmd.Context(), 20*time.Second)
defer updateCancel()
mctx = manipulate.NewContext(updateCtx, options...)
if err := manipulator.Update(mctx, identifiable); err != nil {
return fmt.Errorf("unable to update %s: %w", identity.Name, err)
}
outputType := fOutput
if fOutput == flagOutputDefault {
outputType = flagOutputNone
}
result, err := formatObjects(
prepareOutputFormat(outputType, formatTypeHash, fFormatTypeColumn, fOutputTemplate),
false,
identifiable,
)
if err != nil {
return fmt.Errorf("unable to format output: %w", err)
}
fmt.Fprint(cmd.OutOrStdout(), result)
return nil
},
}
cmd.Flags().BoolP(flagForce, "", false, "Force modification of protected object")
cmd.Flags().String(flagInputValues, "", "Optional path to file containing templating values")
cmd.Flags().StringP(flagInputData, "d", "", "Data of the request body in the JSON format.")
cmd.Flags().StringP(flagInputFile, "f", "", "Optional file to read the data from. Set `-` to read from stdin")
cmd.Flags().StringP(flagInputURL, "u", "", "Optional url where to read the data from. If you don't set it, stdin or --file will used")
cmd.Flags().StringSlice(flagInputSet, nil, "Set a value to in the imported data in case it is a Go template.")
cmd.Flags().Bool(flagPrint, false, "If set will print the raw data. Only works for --file and --url")
cmd.Flags().Bool(flagRender, false, "If set will render and print the data. Only works for --file and --url")
cmd.Flags().BoolP(flagInteractive, "i", false, "Set to create the object in the given --editor.")
cmd.Flags().StringP(flagEditor, "", "", "Choose the editor when using --interactive.")
identifiable := modelManager.IdentifiableFromString(identity.Name)
if err := setViperFlags(cmd, identifiable, modelManager, cfg.argumentsPrefix); err != nil {
return nil, fmt.Errorf("unable to set flags for %s: %w", identity.Name, err)
}
return cmd, nil
}