diff --git a/api/user/agent/agents_test.go b/api/user/agent/agents_test.go index 3d46c92..60f9949 100644 --- a/api/user/agent/agents_test.go +++ b/api/user/agent/agents_test.go @@ -36,9 +36,9 @@ func TestGetAgents(t *testing.T) { t.Fatal(err) } viper.AutomaticEnv() - + err = viper.Unmarshal(&cliConfig) - + if err != nil { fmt.Printf("Unable to decode into map, %v", err) } diff --git a/cli/commands/agent/install.go b/cli/commands/agent/install.go index 8279316..b9a8703 100644 --- a/cli/commands/agent/install.go +++ b/cli/commands/agent/install.go @@ -1,9 +1,12 @@ package agent import ( + `bytes` "fmt" "os" + `os/exec` + `github.com/fatih/color` "github.com/pkg/errors" "github.com/spf13/cobra" "github.com/spf13/viper" @@ -63,7 +66,6 @@ func getCredentials(cmd *cobra.Command) (cli.Cli, error) { return cli.Cli{}, err } - delete(viper.AllSettings(), "interactive") if !isInteractive { // get cli config for authentication err = viper.Unmarshal(&cliConfig) @@ -108,20 +110,24 @@ func installAgentCmd(cmd *cobra.Command, _ []string) error { // early cut if bad credentials if cliConfig.UserAPIToken == "" { - return errors.Errorf(`empty user api token during installation. Please check out documentation. + return errors.Errorf( + `empty user api token during installation. Please check out documentation. If you haven't set up your cli, you can set it up during installation: $ strixeye agent install --interactive -`) +`, + ) } // early cut if bad agent id if cliConfig.AgentID == "" { - return errors.Errorf(`empty agent id in configuration. Please check out documentation. + return errors.Errorf( + `empty agent id in configuration. Please check out documentation. If you haven't set up your cli, you can set it up during installation: $ strixeye agent install --interactive -`) } - +`, + ) + } // get agent config from remote. agentConfig, err := agent.GetAgentConfig(cliConfig) @@ -141,6 +147,11 @@ func installAgentCmd(cmd *cobra.Command, _ []string) error { return err } + err = loginToDocker(agentConfig, cliConfig) + if err != nil { + return err + } + // create necessary directories and files. err = createPaths(agentConfig) if errors.Is(err, os.ErrExist) { @@ -175,6 +186,7 @@ func installAgentCmd(cmd *cobra.Command, _ []string) error { cliConfig.UserAPIToken, agentConfig.Token, versions.Manager, cliConfig.DownloadDomain, ) + if err != nil { return err } @@ -213,3 +225,36 @@ func createPaths(agentInformation agent2.AgentInformation) error { return nil } + +// loginToDocker is necessary because StrixEye images are kept in a secure registry. +func loginToDocker(agentConfig agent2.AgentInformation, cliConfig cli.Cli) error { + testRefStr := fmt.Sprintf("%s/%s", cliConfig.DockerRegistry, "hello-world") + + cmd := exec.Command("docker", "pull", testRefStr) + + var outBuffer bytes.Buffer + cmd.Stdout = &outBuffer + + err := cmd.Run() + + if err != nil { + color.Red( + ` +Docker can not fetch test image from StrixEye registry. +If you haven't logged in to Strixeye Docker Registry yet, you need to login to StrixEye registry at %s. + +Here is a direct command you can execute: + +$ docker login --username strixeye --password %s %s + +If you don't want to show credentials in your history, following is a custom command you can use. +Logging in to a docker registry is a basic procedure that is documented by docker as well. https://docs.docker.com/engine/reference/commandline/login/ + +$ strixeye agent show-token | docker login --username strixeye --password-stdin $(strixeye agent show-registry) +`, cliConfig.DockerRegistry, agentConfig.Token, cliConfig.DockerRegistry, + ) + return err + } + + return nil +} diff --git a/cli/commands/agent/install_test.go b/cli/commands/agent/install_test.go new file mode 100644 index 0000000..cc59db8 --- /dev/null +++ b/cli/commands/agent/install_test.go @@ -0,0 +1,83 @@ +package agent + +import ( + "encoding/json" + "os" + "testing" + + "github.com/sirupsen/logrus" + "github.com/spf13/viper" + "github.com/usestrix/cli/domain/agent" + "github.com/usestrix/cli/domain/cli" +) + +/* + Created by aomerk at 6/26/21 for project connector +*/ + +/* + INSERT FILE DESCRIPTION HERE +*/ + +// global constants for file +const () + +// global variables (not cool) for this file +var () + +func Test_loginToDocker(t *testing.T) { + // setup test environment + var ( + err error + cliConfig cli.Cli + agentConfig agent.AgentInformation + ) + + // get good keys + viper.SetConfigFile("../../../.env") + // Try to read from file, but use env variables if non exists. it's fine + err = viper.ReadInConfig() + if err != nil { + logrus.Fatal(err) + } + viper.AutomaticEnv() + err = viper.Unmarshal(&cliConfig) + + agentBytes, err := os.ReadFile("../../../test/agent-info.json") + if err != nil { + logrus.Fatal(err) + } + + err = json.Unmarshal(agentBytes, &agentConfig) + if err != nil { + logrus.Fatal(err) + } + + type args struct { + agentConfig agent.AgentInformation + cliConfig cli.Cli + } + tests := []struct { + name string + args args + wantErr bool + }{ + { + name: "pull successfully", + args: args{ + agentConfig: agentConfig, + cliConfig: cliConfig, + }, + wantErr: false, + }, + } + for _, tt := range tests { + t.Run( + tt.name, func(t *testing.T) { + if err := loginToDocker(tt.args.agentConfig, tt.args.cliConfig); (err != nil) != tt.wantErr { + t.Errorf("loginToDocker() error = %v, wantErr %v", err, tt.wantErr) + } + }, + ) + } +}