diff --git a/cmd/root/device/config.go b/cmd/root/device/config.go index 98d2e416..f5694dc1 100644 --- a/cmd/root/device/config.go +++ b/cmd/root/device/config.go @@ -18,6 +18,9 @@ type DeviceConfig struct { disconnect *cobra.Command status *cobra.Command jita *cobra.Command + config *cobra.Command + configGet *cobra.Command + configSet *cobra.Command } func NewDeviceConfig() *DeviceConfig { @@ -27,6 +30,9 @@ func NewDeviceConfig() *DeviceConfig { disconnect: disconnectCmd, status: statusCmd, jita: jitaCmd, + config: configCmd, + configGet: configGetCmd, + configSet: configSetCmd, } } @@ -36,6 +42,9 @@ func (d DeviceConfig) InitCmds(root *cobra.Command) { d.device.AddCommand(d.disconnect) d.device.AddCommand(d.status) d.device.AddCommand(d.jita) + d.device.AddCommand(d.config) + d.config.AddCommand(d.configGet) + d.config.AddCommand(d.configSet) d.status.Flags().BoolP(QuietFlag, QuietFlagShort, false, "Reduce verbosity.") viper.BindPFlag(QuietFlag, d.status.Flag(QuietFlag)) d.status.Flags().StringP(OutputFlag, OutputFlagShort, "", "Output format") diff --git a/cmd/root/device/config_cmd.go b/cmd/root/device/config_cmd.go new file mode 100644 index 00000000..26175995 --- /dev/null +++ b/cmd/root/device/config_cmd.go @@ -0,0 +1,16 @@ +package device + +import ( + "fmt" + + "github.com/spf13/cobra" +) + +var configCmd = &cobra.Command{ + Use: "config [command]", + Short: "Adjust or view the naisdevice configuration", + Example: `nais device config set autoconnect true`, + RunE: func(command *cobra.Command, args []string) error { + return fmt.Errorf("missing required command") + }, +} diff --git a/cmd/root/device/config_get_cmd.go b/cmd/root/device/config_get_cmd.go new file mode 100644 index 00000000..69943dbd --- /dev/null +++ b/cmd/root/device/config_get_cmd.go @@ -0,0 +1,36 @@ +package device + +import ( + "fmt" + + "github.com/nais/device/pkg/pb" + "github.com/spf13/cobra" +) + +var configGetCmd = &cobra.Command{ + Use: "get", + Short: "Gets the current configuration", + Example: `nais device config get`, + RunE: func(command *cobra.Command, args []string) error { + // workaround https://github.com/spf13/cobra/issues/340 + command.SilenceUsage = true + + connection, err := agentConnection() + if err != nil { + return formatGrpcError(err) + } + + client := pb.NewDeviceAgentClient(connection) + defer connection.Close() + + configResponse, err := client.GetAgentConfiguration(command.Context(), &pb.GetAgentConfigurationRequest{}) + if err != nil { + return formatGrpcError(err) + } + + fmt.Printf("AutoConnect:\t%v\n", configResponse.Config.AutoConnect) + fmt.Printf("CertRenewal:\t%v\n", configResponse.Config.CertRenewal) + + return nil + }, +} diff --git a/cmd/root/device/config_set_cmd.go b/cmd/root/device/config_set_cmd.go new file mode 100644 index 00000000..37a1bbf1 --- /dev/null +++ b/cmd/root/device/config_set_cmd.go @@ -0,0 +1,83 @@ +package device + +import ( + "fmt" + "strconv" + "strings" + + "github.com/nais/device/pkg/pb" + "github.com/spf13/cobra" +) + +var configSetCmd = &cobra.Command{ + Use: "set [setting] [value]", + Short: "Sets a configuration value", + Example: `nais device config set AutoConnect true`, + ValidArgsFunction: validSettings, + RunE: func(command *cobra.Command, args []string) error { + if len(args) != 2 { + return fmt.Errorf("missing required arguments: setting, value") + } + // workaround https://github.com/spf13/cobra/issues/340 + command.SilenceUsage = true + + setting := strings.TrimSpace(args[0]) + valueString := strings.TrimSpace(args[1]) + + value, err := strconv.ParseBool(valueString) + if err != nil { + return fmt.Errorf("Parsing setting as boolean value: %v", err) + } + + connection, err := agentConnection() + if err != nil { + return formatGrpcError(err) + } + + client := pb.NewDeviceAgentClient(connection) + defer connection.Close() + + // we have to fetch the agent configuration and mutate it in here. :( + // SetAgentConfiguration on the agent's side replaces its config with the payload we send + configResponse, err := client.GetAgentConfiguration(command.Context(), &pb.GetAgentConfigurationRequest{}) + if err != nil { + return formatGrpcError(err) + } + + switch strings.ToLower(setting) { + case "autoconnect": + configResponse.Config.AutoConnect = value + case "certrenewal": + configResponse.Config.CertRenewal = value + default: + return fmt.Errorf("Setting must be one of [autoconnect, certrenewal]") + } + + setConfigRequest := &pb.SetAgentConfigurationRequest{Config: configResponse.Config} + _, err = client.SetAgentConfiguration(command.Context(), setConfigRequest) + if err != nil { + return formatGrpcError(err) + } + + return nil + }, +} + +func validSettings(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { + if len(args) != 0 { + return nil, cobra.ShellCompDirectiveNoFileComp + } + + ret := make([]string, 0) + + // one could make something based on `pb.AgentConfiguration{}` + // and reflect and find the public parameters and put that into `ret`.. but... maybe not + allowedList := []string{"AutoConnect", "CertRenewal"} + for _, allowed := range allowedList { + if strings.Contains(strings.ToLower(allowed), strings.ToLower(toComplete)) { + ret = append(ret, allowed) + } + } + + return ret, cobra.ShellCompDirectiveNoFileComp +} diff --git a/cmd/root/device/jita.go b/cmd/root/device/jita.go index be320898..0b56cb19 100644 --- a/cmd/root/device/jita.go +++ b/cmd/root/device/jita.go @@ -11,9 +11,9 @@ import ( ) var jitaCmd = &cobra.Command{ - Use: "jita", + Use: "jita [gateway]", Short: "Connects to a JITA gateway", - Example: `nais device jita [gateway]`, + Example: `nais device jita postgres-prod`, ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) { if len(args) != 0 { return nil, cobra.ShellCompDirectiveNoFileComp diff --git a/cmd/root/device/status_cmd.go b/cmd/root/device/status_cmd.go index afc772bf..fd8adc06 100644 --- a/cmd/root/device/status_cmd.go +++ b/cmd/root/device/status_cmd.go @@ -11,9 +11,9 @@ import ( ) var statusCmd = &cobra.Command{ - Use: "status", + Use: "status [flags]", Short: "Shows the status of your naisdevice", - Example: `nais device status [-q|--quiet]`, + Example: `nais device status -q | nais device status -o yaml`, RunE: func(command *cobra.Command, args []string) error { // workaround https://github.com/spf13/cobra/issues/340 command.SilenceUsage = true