diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 979b3d4..3868492 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,9 +15,9 @@ jobs: - name: Check out code into the Go module directory uses: actions/checkout@v2 - name: Run tests - run: go test -race `go list ./... | grep -v cmd/analyze/code-samples | grep -v cmd/configuration | grep -v utils/httpRequest` -coverprofile cover.out.tmp + run: go test -race `go list ./... | grep -v cmd/feature_experimentation/analyze | grep -v cmd/feature_experimentation/resource` -coverprofile cover.out.tmp - name: Removes mocks from tests - run: cat cover.out.tmp | grep -v "mock_\|cmd/analyze/code-samples-example|cmd/configuration|utils/httpRequest" > cover.out + run: cat cover.out.tmp | grep -v "mock_\|cmd/feature_experimentation/analyze" | grep -v "mock_\|cmd/feature_experimentation/resource" > cover.out - uses: codecov/codecov-action@v2 with: file: ./cover.out diff --git a/Makefile b/Makefile index bd32835..864c969 100644 --- a/Makefile +++ b/Makefile @@ -4,7 +4,7 @@ build: test: SHELL:=/bin/bash test: mkdir -p coverage - go test -v -race `go list ./... | grep -v cmd/analyze/code-samples` -coverprofile coverage/cover.out.tmp - cat coverage/cover.out.tmp | grep -v "mock_\|cmd/analyze/code-samples" > coverage/cover.out + go test -v -race `go list ./... | grep -v cmd/feature_experimentation/analyze | grep -v cmd/feature_experimentation/resource` -coverprofile coverage/cover.out.tmp + cat coverage/cover.out.tmp | grep -v "mock_\|cmd/feature_experimentation/analyze" | grep -v "mock_\|cmd/feature_experimentation/resource" > coverage/cover.out go tool cover -html=coverage/cover.out -o coverage/cover.html go tool cover -func=coverage/cover.out \ No newline at end of file diff --git a/cmd/configuration/configuration.go b/cmd/configuration/configuration.go deleted file mode 100644 index 4f3f554..0000000 --- a/cmd/configuration/configuration.go +++ /dev/null @@ -1,25 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import "github.com/spf13/cobra" - -var ( - ConfigurationName string - ConfigurationClientID string - ConfigurationClientSecret string - ConfigurationAccountID string - ConfigurationAccountEnvID string -) - -// ConfigurationCmd represents the configuration command -var ConfigurationCmd = &cobra.Command{ - Use: "configuration [create|edit|get|list|delete|use]", - Aliases: []string{"conf"}, - Short: "Manage your CLI configurations", - Long: `Manage your CLI configurations in your account`, - Run: func(cmd *cobra.Command, args []string) { - cmd.Help() - }, -} diff --git a/cmd/configuration/configuration_test.go b/cmd/configuration/configuration_test.go deleted file mode 100644 index 525b9f8..0000000 --- a/cmd/configuration/configuration_test.go +++ /dev/null @@ -1,87 +0,0 @@ -package configuration - -import ( - "encoding/json" - "testing" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - mockfunction "github.com/flagship-io/flagship/utils/mock_function" - "github.com/jarcoal/httpmock" - "github.com/stretchr/testify/assert" -) - -func TestMain(m *testing.M) { - - httpmock.Activate() - defer httpmock.DeactivateAndReset() - - mockfunction.InitMockConfiguration() - - m.Run() -} - -var testConfiguration models.Configuration -var testConfigurationList []models.Configuration - -func TestConfigurationCommand(t *testing.T) { - output, _ := utils.ExecuteCommand(ConfigurationCmd) - assert.Contains(t, output, "Manage your CLI configurations in your account") -} - -func TestConfigurationHelpCommand(t *testing.T) { - output, _ := utils.ExecuteCommand(ConfigurationCmd, "--help") - assert.Contains(t, output, "Manage your CLI configurations in your account") -} - -func TestConfigurationCreateCommand(t *testing.T) { - - failOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "create") - - assert.Contains(t, failOutput, "Configuration not created") - - successOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "create", "--name=test_configuration", "-i=testConfigurationClientID", "-s=testConfigurationClientSecret", "-a=testConfigurationAccountID", "-e=testConfigurationAccountEnvID") - assert.Equal(t, "Configuration created successfully\n", successOutput) - -} - -func TestConfigurationDeleteCommand(t *testing.T) { - config.CreateConfigurationFile(mockfunction.TestConfiguration.Name, mockfunction.TestConfiguration.ClientID, mockfunction.TestConfiguration.ClientSecret, mockfunction.TestConfiguration.AccountID, mockfunction.TestConfiguration.AccountEnvironmentID) - - failOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "delete") - assert.Contains(t, failOutput, "Error: required flag(s) \"name\" not set") - - successOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "delete", "--name=test_configuration") - assert.Equal(t, "Configuration deleted successfully\n", successOutput) -} - -func TestConfigurationListCommand(t *testing.T) { - config.CreateConfigurationFile(mockfunction.TestConfiguration.Name, mockfunction.TestConfiguration.ClientID, mockfunction.TestConfiguration.ClientSecret, mockfunction.TestConfiguration.AccountID, mockfunction.TestConfiguration.AccountEnvironmentID) - - output, _ := utils.ExecuteCommand(ConfigurationCmd, "list") - - err := json.Unmarshal([]byte(output), &testConfigurationList) - - assert.Nil(t, err) - - byt, err := json.Marshal(mockfunction.TestConfiguration) - - assert.Nil(t, err) - - assert.Contains(t, output, string(byt)) -} - -func TestConfigurationGetCommand(t *testing.T) { - config.CreateConfigurationFile(mockfunction.TestConfiguration.Name, mockfunction.TestConfiguration.ClientID, mockfunction.TestConfiguration.ClientSecret, mockfunction.TestConfiguration.AccountID, mockfunction.TestConfiguration.AccountEnvironmentID) - - failOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "get") - assert.Contains(t, failOutput, "Error: required flag(s) \"name\" not set") - - successOutput, _ := utils.ExecuteCommand(ConfigurationCmd, "get", "--name=test_configuration") - err := json.Unmarshal([]byte(successOutput), &testConfiguration) - - assert.Nil(t, err) - - assert.Equal(t, mockfunction.TestConfiguration, testConfiguration) -} diff --git a/cmd/configuration/create.go b/cmd/configuration/create.go deleted file mode 100644 index e0dc546..0000000 --- a/cmd/configuration/create.go +++ /dev/null @@ -1,70 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "fmt" - "log" - "slices" - - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var ( - credentialsFile string -) - -// createCmd represents the create command -var createCmd = &cobra.Command{ - Use: "create [-n | --name=] [-i | --client-id=] [-s | --client-secret=] [-a | --account-id=] [-e | --account-environment-id=]", - Short: "Create a configuration", - Long: `Create a configuration based on the credentials`, - Run: func(cmd *cobra.Command, args []string) { - - existingConfigurationsName, err := config.GetConfigurationsName() - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - if credentialsFile != "" { - config.ReadCredentialsFromFile(credentialsFile) - if slices.Contains(existingConfigurationsName, viper.GetString("name")) { - fmt.Fprintln(cmd.OutOrStdout(), "Configuration name already exists") - return - } - config.CreateConfigurationFile(viper.GetString("name"), viper.GetString("client_id"), viper.GetString("client_secret"), viper.GetString("account_id"), viper.GetString("account_environment_id")) - fmt.Fprintln(cmd.OutOrStdout(), "Configuration created successfully") - return - } - if ConfigurationName != "" && ConfigurationClientID != "" && ConfigurationClientSecret != "" && ConfigurationAccountID != "" && ConfigurationAccountEnvID != "" { - - if slices.Contains(existingConfigurationsName, ConfigurationName) { - fmt.Fprintln(cmd.OutOrStdout(), "Configuration name already exists") - return - } - - config.CreateConfigurationFile(ConfigurationName, ConfigurationClientID, ConfigurationClientSecret, ConfigurationAccountID, ConfigurationAccountEnvID) - fmt.Fprintln(cmd.OutOrStdout(), "Configuration created successfully") - return - } - - fmt.Fprintln(cmd.OutOrStdout(), "Configuration not created, required fields (name, client ID, client secret, account ID, account environment ID)") - - }, -} - -func init() { - - createCmd.Flags().StringVarP(&ConfigurationName, "name", "n", "", "configuration name") - createCmd.Flags().StringVarP(&ConfigurationClientID, "client-id", "i", "", "client ID of a configuration") - createCmd.Flags().StringVarP(&ConfigurationClientSecret, "client-secret", "s", "", "client secret of a configuration") - createCmd.Flags().StringVarP(&ConfigurationAccountID, "account-id", "a", "", "account ID of a configuration") - createCmd.Flags().StringVarP(&ConfigurationAccountEnvID, "account-environment-id", "e", "", "account environment ID of a configuration") - - createCmd.Flags().StringVarP(&credentialsFile, "path", "p", "", "config file to create") - - ConfigurationCmd.AddCommand(createCmd) -} diff --git a/cmd/configuration/current.go b/cmd/configuration/current.go deleted file mode 100644 index 88fb266..0000000 --- a/cmd/configuration/current.go +++ /dev/null @@ -1,62 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "log" - "os" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "gopkg.in/yaml.v2" -) - -// currentCmd represents current command -var currentCmd = &cobra.Command{ - Use: "current", - Short: "Get current configuration", - Long: `Get current configuration`, - Run: func(cmd *cobra.Command, args []string) { - var configurationYaml models.ConfigurationYaml - var configuration models.Configuration - var v = viper.New() - - configFilepath := config.SetPathForConfigName(".cli") - v.SetConfigFile(configFilepath) - - err := v.MergeInConfig() - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - configurationName := v.GetString("current_used_configuration") - - yamlFile, err := os.ReadFile(config.SetPathForConfigName(configurationName)) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - // Unmarshal the YAML data into the struct - err = yaml.Unmarshal(yamlFile, &configurationYaml) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - configuration.Name = configurationYaml.Name - configuration.ClientID = configurationYaml.ClientID - configuration.ClientSecret = configurationYaml.ClientSecret - configuration.AccountID = configurationYaml.AccountID - configuration.AccountEnvironmentID = configurationYaml.AccountEnvironmentID - - utils.FormatItem([]string{"Name", "ClientID", "ClientSecret", "AccountID", "AccountEnvironmentID"}, configuration, viper.GetString("output_format"), cmd.OutOrStdout()) - - }, -} - -func init() { - ConfigurationCmd.AddCommand(currentCmd) -} diff --git a/cmd/configuration/delete.go b/cmd/configuration/delete.go deleted file mode 100644 index 653124a..0000000 --- a/cmd/configuration/delete.go +++ /dev/null @@ -1,39 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "fmt" - "log" - "os" - - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" -) - -// deleteCmd represents delete command -var deleteCmd = &cobra.Command{ - Use: "delete [-n | --name=]", - Short: "Delete a configuration", - Long: `Delete a configuration`, - Run: func(cmd *cobra.Command, args []string) { - - config.CheckFlagshipHomeDirectory() - - if err := os.Remove(config.SetPathForConfigName(ConfigurationName)); err != nil { - log.Fatal(err) - } - - fmt.Fprintln(cmd.OutOrStdout(), "Configuration deleted successfully") - }, -} - -func init() { - deleteCmd.Flags().StringVarP(&ConfigurationName, "name", "n", "", "name of the configuration you want to delete") - - if err := deleteCmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("error occurred: %v", err) - } - ConfigurationCmd.AddCommand(deleteCmd) -} diff --git a/cmd/configuration/edit.go b/cmd/configuration/edit.go deleted file mode 100644 index 09d8d15..0000000 --- a/cmd/configuration/edit.go +++ /dev/null @@ -1,87 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "fmt" - "log" - "slices" - - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var ( - newConfigurationName string -) - -// editCmd represents the edit command -var editCmd = &cobra.Command{ - Use: "edit [-n | --name=] [-i | --client-id=] [-s | --client-secret=] [-a | --account-id=] [-e | --account-environment-id=]", - Short: "Edit a configuration", - Long: `Edit a configuration`, - Run: func(cmd *cobra.Command, args []string) { - existingConfigurationsName, err := config.GetConfigurationsName() - - if err != nil { - log.Fatalf("error occurred : %s", err) - } - - if !slices.Contains(existingConfigurationsName, ConfigurationName) { - fmt.Fprintln(cmd.OutOrStdout(), "Configuration doesn't exists") - return - - } - - if slices.Contains(existingConfigurationsName, newConfigurationName) { - fmt.Fprintln(cmd.OutOrStdout(), "Configuration already exists") - return - } - - config.ReadCredentialsFromFile(config.SetPathForConfigName(ConfigurationName)) - - if newConfigurationName == "" { - newConfigurationName = viper.GetString("name") - } - if ConfigurationClientID == "" { - ConfigurationClientID = viper.GetString("client_id") - } - if ConfigurationClientSecret == "" { - ConfigurationClientSecret = viper.GetString("client_secret") - } - if ConfigurationAccountID == "" { - ConfigurationAccountID = viper.GetString("account_id") - } - if ConfigurationAccountEnvID == "" { - ConfigurationAccountEnvID = viper.GetString("account_environment_id") - } - - if newConfigurationName == "" && ConfigurationClientID == "" && ConfigurationClientSecret == "" && ConfigurationAccountID == "" && ConfigurationAccountEnvID == "" { - log.Fatal("required new name or client-id or client-secret or account-id or account-env-id") - return - } - - config.EditConfigurationFile(ConfigurationName, newConfigurationName, ConfigurationClientID, ConfigurationClientSecret, ConfigurationAccountID, ConfigurationAccountEnvID) - - fmt.Fprintln(cmd.OutOrStdout(), "Configuration edited successfully") - }, -} - -func init() { - - editCmd.Flags().StringVarP(&ConfigurationName, "name", "n", "", "name of the configuration you want to edit") - - editCmd.Flags().StringVarP(&newConfigurationName, "new-name", "", "", "new name for the configuration you want to edit") - editCmd.Flags().StringVarP(&ConfigurationClientID, "client-id", "i", "", "client ID configuration") - editCmd.Flags().StringVarP(&ConfigurationClientSecret, "client-secret", "s", "", "client secret of a configuration") - editCmd.Flags().StringVarP(&ConfigurationAccountID, "account-id", "a", "", "account ID of a configuration") - editCmd.Flags().StringVarP(&ConfigurationAccountEnvID, "account-environment-id", "e", "", "account environment ID of a configuration") - - if err := editCmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("error occurred: %v", err) - } - - ConfigurationCmd.AddCommand(editCmd) -} diff --git a/cmd/configuration/get.go b/cmd/configuration/get.go deleted file mode 100644 index db4b69e..0000000 --- a/cmd/configuration/get.go +++ /dev/null @@ -1,56 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "log" - "os" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "gopkg.in/yaml.v2" -) - -// getCmd represents get command -var getCmd = &cobra.Command{ - Use: "get [-n | --name=]", - Short: "Get a configuration", - Long: `Get a configuration`, - Run: func(cmd *cobra.Command, args []string) { - var configurationYaml models.ConfigurationYaml - var configuration models.Configuration - - yamlFile, err := os.ReadFile(config.SetPathForConfigName(ConfigurationName)) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - // Unmarshal the YAML data into the struct - err = yaml.Unmarshal(yamlFile, &configurationYaml) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - configuration.Name = configurationYaml.Name - configuration.ClientID = configurationYaml.ClientID - configuration.ClientSecret = configurationYaml.ClientSecret - configuration.AccountID = configurationYaml.AccountID - configuration.AccountEnvironmentID = configurationYaml.AccountEnvironmentID - - utils.FormatItem([]string{"Name", "ClientID", "ClientSecret", "AccountID", "AccountEnvironmentID"}, configuration, viper.GetString("output_format"), cmd.OutOrStdout()) - - }, -} - -func init() { - getCmd.Flags().StringVarP(&ConfigurationName, "name", "n", "", "name of the configuration you want to display") - - if err := getCmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("error occurred: %v", err) - } - ConfigurationCmd.AddCommand(getCmd) -} diff --git a/cmd/configuration/list.go b/cmd/configuration/list.go deleted file mode 100644 index 01c6828..0000000 --- a/cmd/configuration/list.go +++ /dev/null @@ -1,60 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "log" - "os" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/cobra" - "github.com/spf13/viper" - "gopkg.in/yaml.v2" -) - -// listCmd represents the list command -var listCmd = &cobra.Command{ - Use: "list", - Short: "List all configurations", - Long: `List all configurations`, - Run: func(cmd *cobra.Command, args []string) { - - var configurations []models.Configuration - existingConfigurationsName, nil := config.GetConfigurationsName() - - for _, fileName := range existingConfigurationsName { - if fileName != "" { - var configurationYaml models.ConfigurationYaml - var configuration models.Configuration - yamlFile, err := os.ReadFile(config.SetPathForConfigName(fileName)) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - - // Unmarshal the YAML data into the struct - err = yaml.Unmarshal(yamlFile, &configurationYaml) - if err != nil { - log.Fatalf("error occurred: %s", err) - } - if configurationYaml.Name != "" { - configuration.Name = configurationYaml.Name - configuration.ClientID = configurationYaml.ClientID - configuration.ClientSecret = configurationYaml.ClientSecret - configuration.AccountID = configurationYaml.AccountID - configuration.AccountEnvironmentID = configurationYaml.AccountEnvironmentID - configurations = append(configurations, configuration) - } - } - } - - utils.FormatItem([]string{"Name", "ClientID", "ClientSecret", "AccountID", "AccountEnvironmentID"}, configurations, viper.GetString("output_format"), cmd.OutOrStdout()) - - }, -} - -func init() { - ConfigurationCmd.AddCommand(listCmd) -} diff --git a/cmd/configuration/use.go b/cmd/configuration/use.go deleted file mode 100644 index 4ff6b22..0000000 --- a/cmd/configuration/use.go +++ /dev/null @@ -1,69 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com -*/ -package configuration - -import ( - "fmt" - "log" - "slices" - - "github.com/flagship-io/flagship/utils/config" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -var ( - grantType string - scope string - expiration int -) - -// useCmd represents use command -var useCmd = &cobra.Command{ - Use: "use [-n | --name=] [--grant-type=] [--scope=] [--expiration=]", - Short: "Use a configuration", - Long: `Use an already created configuration`, - Run: func(cmd *cobra.Command, args []string) { - existingConfigurationsName, err := config.GetConfigurationsName() - if err != nil { - log.Fatalf("error occurred: %s", err) - } - if !slices.Contains(existingConfigurationsName, ConfigurationName) { - fmt.Fprintln(cmd.OutOrStdout(), "Configuration doesn't exists") - return - } - - config.SelectConfiguration(ConfigurationName) - config.SetOptionalsDefault(grantType, scope, expiration) - - token, err := httprequest.HTTPCreateToken(viper.GetString("client_id"), viper.GetString("client_secret"), grantType, scope, expiration) - if err != nil { - log.Fatalf("%s", err) - return - } - - if token == "" { - log.Fatal("client_id or client_secret not valid") - return - } else { - config.WriteToken(ConfigurationName, token) - fmt.Fprintln(cmd.OutOrStdout(), "Token generated successfully") - } - - fmt.Fprintln(cmd.OutOrStdout(), "Configuration selected successfully") - }, -} - -func init() { - useCmd.Flags().StringVarP(&ConfigurationName, "name", "n", "", "name of the configuration you want to display") - useCmd.Flags().StringVarP(&grantType, "grant-type", "", config.GrantType, "grant type of the token, DEFAULT value is client_credentials") - useCmd.Flags().StringVarP(&scope, "scope", "", config.Scope, "scope of the token, DEFAULT value is *") - useCmd.Flags().IntVarP(&expiration, "expiration", "", config.Expiration, "expiration time in second of the token, DEFAULT value is 86400") - - if err := useCmd.MarkFlagRequired("name"); err != nil { - log.Fatalf("error occurred: %v", err) - } - ConfigurationCmd.AddCommand(useCmd) -} diff --git a/cmd/feature_experimentation/account/account.go b/cmd/feature_experimentation/account/account.go new file mode 100644 index 0000000..ca816c4 --- /dev/null +++ b/cmd/feature_experimentation/account/account.go @@ -0,0 +1,21 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import "github.com/spf13/cobra" + +var ( + Username string + AccountID string +) + +// AccountCmd represents the account command +var AccountCmd = &cobra.Command{ + Use: "account [use|current]", + Short: "Manage your CLI authentication", + Long: `Manage your CLI authentication`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/feature_experimentation/account/account_test.go b/cmd/feature_experimentation/account/account_test.go new file mode 100644 index 0000000..8256c48 --- /dev/null +++ b/cmd/feature_experimentation/account/account_test.go @@ -0,0 +1,60 @@ +package account + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_fe.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_fe.APIToken() + + m.Run() +} + +var testAccount models.AccountJSON + +func TestAccountCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountCmd) + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account [use|current]") +} + +func TestAccountHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountCmd, "--help") + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account [use|current]") +} + +func TestAccountUseCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AccountCmd, "use") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(AccountCmd, "use", "-i=account_id") + assert.Equal(t, "Account ID set to : account_id\n", successOutput) +} + +func TestAccountCurrentCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AccountCmd, "current") + + err := json.Unmarshal([]byte(output), &testAccount) + + assert.Nil(t, err) + + assert.Equal(t, feature_experimentation.TestAccount.AccountID, testAccount.AccountID) +} diff --git a/cmd/feature_experimentation/account/current.go b/cmd/feature_experimentation/account/current.go new file mode 100644 index 0000000..95e6823 --- /dev/null +++ b/cmd/feature_experimentation/account/current.go @@ -0,0 +1,54 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// getCmd represents the list command +var currentCmd = &cobra.Command{ + Use: "current", + Short: "Get current running auth credential", + Long: `Get current running auth credential`, + Run: func(cmd *cobra.Command, args []string) { + + var accountYaml models.AccountYaml + var account models.AccountJSON + + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + account.CurrentUsedCredential = accountYaml.CurrentUsedCredential + account.AccountID = accountYaml.AccountID + + utils.FormatItem([]string{"CurrentUsedCredential", "AccountID"}, account, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + AccountCmd.AddCommand(currentCmd) +} diff --git a/cmd/feature_experimentation/account/use.go b/cmd/feature_experimentation/account/use.go new file mode 100644 index 0000000..14312d9 --- /dev/null +++ b/cmd/feature_experimentation/account/use.go @@ -0,0 +1,43 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import ( + "fmt" + "log" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" +) + +// getCmd represents the list command +var useCmd = &cobra.Command{ + Use: "use", + Short: "get an auth credential", + Long: `list an auth credential`, + Run: func(cmd *cobra.Command, args []string) { + if AccountID == "" { + fmt.Fprintln(cmd.OutOrStderr(), "required flag account-id") + return + } + + err := config.SetAccountID(utils.FEATURE_EXPERIMENTATION, AccountID) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Account ID set to : "+AccountID) + + }, +} + +func init() { + useCmd.Flags().StringVarP(&AccountID, "id", "i", "", "account id of the credentials you want to manage") + + if err := useCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + AccountCmd.AddCommand(useCmd) +} diff --git a/cmd/feature_experimentation/account_environment/account_environment.go b/cmd/feature_experimentation/account_environment/account_environment.go new file mode 100644 index 0000000..c3bda6d --- /dev/null +++ b/cmd/feature_experimentation/account_environment/account_environment.go @@ -0,0 +1,21 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package accountenvironment + +import "github.com/spf13/cobra" + +var ( + Username string + AccountEnvironmentID string +) + +// AccountEnvironmentCmd represents the account environment command +var AccountEnvironmentCmd = &cobra.Command{ + Use: "account-environment [use|list|current]", + Short: "Manage your CLI authentication", + Long: `Manage your CLI authentication`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/feature_experimentation/account_environment/account_environment_test.go b/cmd/feature_experimentation/account_environment/account_environment_test.go new file mode 100644 index 0000000..c7980a3 --- /dev/null +++ b/cmd/feature_experimentation/account_environment/account_environment_test.go @@ -0,0 +1,73 @@ +package accountenvironment + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + models_fe "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_fe.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_fe.APIAccountEnvironment() + + m.Run() +} + +var testAccount models.AccountJSON +var testAccountEnvironment models_fe.AccountEnvironmentFE +var testAccountEnvironmentList []models_fe.AccountEnvironmentFE + +func TestAccountEnvironmentCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountEnvironmentCmd) + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account-environment [use|list|current]") +} + +func TestAccountEnvironmentHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountEnvironmentCmd, "--help") + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account-environment [use|list|current]") +} + +func TestAccountEnvironmentUseCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AccountEnvironmentCmd, "use") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(AccountEnvironmentCmd, "use", "--id=account_environment_id") + assert.Equal(t, "Account Environment ID set to : account_environment_id\n", successOutput) +} + +func TestAccountEnvironmentCurrentCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AccountEnvironmentCmd, "current") + + err := json.Unmarshal([]byte(output), &testAccount) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_fe.TestAccountEnvironment.Id, testAccount.AccountEnvironmentID) +} + +func TestAccountEnvironmentListCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AccountEnvironmentCmd, "list") + + err := json.Unmarshal([]byte(output), &testAccountEnvironmentList) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_fe.TestAccountEnvironmentList, testAccountEnvironmentList) +} diff --git a/cmd/feature_experimentation/account_environment/current.go b/cmd/feature_experimentation/account_environment/current.go new file mode 100644 index 0000000..9098995 --- /dev/null +++ b/cmd/feature_experimentation/account_environment/current.go @@ -0,0 +1,54 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package accountenvironment + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// getCmd represents the list command +var currentCmd = &cobra.Command{ + Use: "current", + Short: "current an auth credential", + Long: `current an auth credential`, + Run: func(cmd *cobra.Command, args []string) { + + var accountYaml models.AccountYaml + var account models.AccountJSON + + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + account.CurrentUsedCredential = accountYaml.CurrentUsedCredential + account.AccountEnvironmentID = accountYaml.AccountEnvironmentID + + utils.FormatItem([]string{"CurrentUsedCredential", "AccountEnvironmentID"}, account, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + AccountEnvironmentCmd.AddCommand(currentCmd) +} diff --git a/cmd/feature_experimentation/account_environment/list.go b/cmd/feature_experimentation/account_environment/list.go new file mode 100644 index 0000000..be412a1 --- /dev/null +++ b/cmd/feature_experimentation/account_environment/list.go @@ -0,0 +1,34 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package accountenvironment + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var accountID string + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "list all account environment id associated to your account", + Long: `list all account environment id associated to your account`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.AccountEnvironmentFERequester.HTTPListAccountEnvironment(accountID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Environment", "IsMain", "Panic", "SingleAssignment"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + listCmd.Flags().StringVarP(&accountID, "account-id", "a", "", "account id of the credentials you want to list") + AccountEnvironmentCmd.AddCommand(listCmd) +} diff --git a/cmd/feature_experimentation/account_environment/use.go b/cmd/feature_experimentation/account_environment/use.go new file mode 100644 index 0000000..090ddba --- /dev/null +++ b/cmd/feature_experimentation/account_environment/use.go @@ -0,0 +1,43 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package accountenvironment + +import ( + "fmt" + "log" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" +) + +// getCmd represents the list command +var useCmd = &cobra.Command{ + Use: "use", + Short: "use a specific account envrionment id", + Long: `use a specific account envrionment id`, + Run: func(cmd *cobra.Command, args []string) { + if AccountEnvironmentID == "" { + fmt.Fprintln(cmd.OutOrStderr(), "required flag account-id or account-environment-id") + return + } + + err := config.SetAccountEnvID(utils.FEATURE_EXPERIMENTATION, AccountEnvironmentID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Account Environment ID set to : "+AccountEnvironmentID) + + }, +} + +func init() { + useCmd.Flags().StringVarP(&AccountEnvironmentID, "id", "i", "", "account env id of the credentials you want to manage") + + if err := useCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + AccountEnvironmentCmd.AddCommand(useCmd) +} diff --git a/cmd/analyze/analyze.go b/cmd/feature_experimentation/analyze/analyze.go similarity index 87% rename from cmd/analyze/analyze.go rename to cmd/feature_experimentation/analyze/analyze.go index 902542f..fc52891 100644 --- a/cmd/analyze/analyze.go +++ b/cmd/feature_experimentation/analyze/analyze.go @@ -1,12 +1,11 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package analyze import ( "github.com/flagship-io/codebase-analyzer/pkg/config" - "github.com/flagship-io/flagship/cmd/analyze/flag" + "github.com/flagship-io/flagship/cmd/feature_experimentation/analyze/flag" "github.com/spf13/cobra" ) diff --git a/cmd/analyze/code-samples/README.md b/cmd/feature_experimentation/analyze/code-samples/README.md similarity index 100% rename from cmd/analyze/code-samples/README.md rename to cmd/feature_experimentation/analyze/code-samples/README.md diff --git a/cmd/analyze/code-samples/flagship/flutter/sample.dart b/cmd/feature_experimentation/analyze/code-samples/flagship/flutter/sample.dart similarity index 100% rename from cmd/analyze/code-samples/flagship/flutter/sample.dart rename to cmd/feature_experimentation/analyze/code-samples/flagship/flutter/sample.dart diff --git a/cmd/analyze/code-samples/flagship/go/SDK_V2/sample.go b/cmd/feature_experimentation/analyze/code-samples/flagship/go/SDK_V2/sample.go similarity index 100% rename from cmd/analyze/code-samples/flagship/go/SDK_V2/sample.go rename to cmd/feature_experimentation/analyze/code-samples/flagship/go/SDK_V2/sample.go diff --git a/cmd/analyze/code-samples/flagship/ios/SDK_V2/sample.m b/cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V2/sample.m similarity index 100% rename from cmd/analyze/code-samples/flagship/ios/SDK_V2/sample.m rename to cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V2/sample.m diff --git a/cmd/analyze/code-samples/flagship/ios/SDK_V2/sample.swift b/cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V2/sample.swift similarity index 100% rename from cmd/analyze/code-samples/flagship/ios/SDK_V2/sample.swift rename to cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V2/sample.swift diff --git a/cmd/analyze/code-samples/flagship/ios/SDK_V3/sample.m b/cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V3/sample.m similarity index 100% rename from cmd/analyze/code-samples/flagship/ios/SDK_V3/sample.m rename to cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V3/sample.m diff --git a/cmd/analyze/code-samples/flagship/ios/SDK_V3/sample.swift b/cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V3/sample.swift similarity index 100% rename from cmd/analyze/code-samples/flagship/ios/SDK_V3/sample.swift rename to cmd/feature_experimentation/analyze/code-samples/flagship/ios/SDK_V3/sample.swift diff --git a/cmd/analyze/code-samples/flagship/java/SDK_V2/sample.java b/cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V2/sample.java similarity index 100% rename from cmd/analyze/code-samples/flagship/java/SDK_V2/sample.java rename to cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V2/sample.java diff --git a/cmd/analyze/code-samples/flagship/java/SDK_V2/sample.kt b/cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V2/sample.kt similarity index 100% rename from cmd/analyze/code-samples/flagship/java/SDK_V2/sample.kt rename to cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V2/sample.kt diff --git a/cmd/analyze/code-samples/flagship/java/SDK_V3/sample.java b/cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V3/sample.java similarity index 100% rename from cmd/analyze/code-samples/flagship/java/SDK_V3/sample.java rename to cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V3/sample.java diff --git a/cmd/analyze/code-samples/flagship/java/SDK_V3/sample.kt b/cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V3/sample.kt similarity index 100% rename from cmd/analyze/code-samples/flagship/java/SDK_V3/sample.kt rename to cmd/feature_experimentation/analyze/code-samples/flagship/java/SDK_V3/sample.kt diff --git a/cmd/analyze/code-samples/flagship/js/SDK_V2/sample.js b/cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V2/sample.js similarity index 100% rename from cmd/analyze/code-samples/flagship/js/SDK_V2/sample.js rename to cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V2/sample.js diff --git a/cmd/analyze/code-samples/flagship/js/SDK_V2/sample.ts b/cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V2/sample.ts similarity index 100% rename from cmd/analyze/code-samples/flagship/js/SDK_V2/sample.ts rename to cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V2/sample.ts diff --git a/cmd/analyze/code-samples/flagship/js/SDK_V3/sample.js b/cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V3/sample.js similarity index 100% rename from cmd/analyze/code-samples/flagship/js/SDK_V3/sample.js rename to cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V3/sample.js diff --git a/cmd/analyze/code-samples/flagship/js/SDK_V3/sample.ts b/cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V3/sample.ts similarity index 100% rename from cmd/analyze/code-samples/flagship/js/SDK_V3/sample.ts rename to cmd/feature_experimentation/analyze/code-samples/flagship/js/SDK_V3/sample.ts diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V1/sample.cs b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.cs similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V1/sample.cs rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.cs diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V1/sample.fs b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.fs similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V1/sample.fs rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.fs diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V1/sample.vb b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.vb similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V1/sample.vb rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V1/sample.vb diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V3/sample.cs b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.cs similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V3/sample.cs rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.cs diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V3/sample.fs b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.fs similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V3/sample.fs rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.fs diff --git a/cmd/analyze/code-samples/flagship/net/SDK_V3/sample.vb b/cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.vb similarity index 100% rename from cmd/analyze/code-samples/flagship/net/SDK_V3/sample.vb rename to cmd/feature_experimentation/analyze/code-samples/flagship/net/SDK_V3/sample.vb diff --git a/cmd/analyze/code-samples/flagship/php/SDK_V1/sample.php b/cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V1/sample.php similarity index 100% rename from cmd/analyze/code-samples/flagship/php/SDK_V1/sample.php rename to cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V1/sample.php diff --git a/cmd/analyze/code-samples/flagship/php/SDK_V2/sample.php b/cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V2/sample.php similarity index 100% rename from cmd/analyze/code-samples/flagship/php/SDK_V2/sample.php rename to cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V2/sample.php diff --git a/cmd/analyze/code-samples/flagship/php/SDK_V3/sample.php b/cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V3/sample.php similarity index 100% rename from cmd/analyze/code-samples/flagship/php/SDK_V3/sample.php rename to cmd/feature_experimentation/analyze/code-samples/flagship/php/SDK_V3/sample.php diff --git a/cmd/analyze/code-samples/flagship/python/SDK_V2/sample.py b/cmd/feature_experimentation/analyze/code-samples/flagship/python/SDK_V2/sample.py similarity index 100% rename from cmd/analyze/code-samples/flagship/python/SDK_V2/sample.py rename to cmd/feature_experimentation/analyze/code-samples/flagship/python/SDK_V2/sample.py diff --git a/cmd/analyze/code-samples/flagship/react/SDK_V2/sample.jsx b/cmd/feature_experimentation/analyze/code-samples/flagship/react/SDK_V2/sample.jsx similarity index 100% rename from cmd/analyze/code-samples/flagship/react/SDK_V2/sample.jsx rename to cmd/feature_experimentation/analyze/code-samples/flagship/react/SDK_V2/sample.jsx diff --git a/cmd/analyze/code-samples/flagship/react/SDK_V3/sample.jsx b/cmd/feature_experimentation/analyze/code-samples/flagship/react/SDK_V3/sample.jsx similarity index 100% rename from cmd/analyze/code-samples/flagship/react/SDK_V3/sample.jsx rename to cmd/feature_experimentation/analyze/code-samples/flagship/react/SDK_V3/sample.jsx diff --git a/cmd/analyze/code-samples/launchDarkly/flutter/sample-LD.dart b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/flutter/sample-LD.dart similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/flutter/sample-LD.dart rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/flutter/sample-LD.dart diff --git a/cmd/analyze/code-samples/launchDarkly/go/sample-LD.go b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/go/sample-LD.go similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/go/sample-LD.go rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/go/sample-LD.go diff --git a/cmd/analyze/code-samples/launchDarkly/ios/sample-LD.m b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/ios/sample-LD.m similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/ios/sample-LD.m rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/ios/sample-LD.m diff --git a/cmd/analyze/code-samples/launchDarkly/ios/sample-LD.swift b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/ios/sample-LD.swift similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/ios/sample-LD.swift rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/ios/sample-LD.swift diff --git a/cmd/analyze/code-samples/launchDarkly/java/sample-LD.java b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/java/sample-LD.java similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/java/sample-LD.java rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/java/sample-LD.java diff --git a/cmd/analyze/code-samples/launchDarkly/java/sample-LD.kt b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/java/sample-LD.kt similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/java/sample-LD.kt rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/java/sample-LD.kt diff --git a/cmd/analyze/code-samples/launchDarkly/js/sample-LD.js b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/js/sample-LD.js similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/js/sample-LD.js rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/js/sample-LD.js diff --git a/cmd/analyze/code-samples/launchDarkly/js/sample-LD.ts b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/js/sample-LD.ts similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/js/sample-LD.ts rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/js/sample-LD.ts diff --git a/cmd/analyze/code-samples/launchDarkly/net/sample-LD.cs b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/net/sample-LD.cs similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/net/sample-LD.cs rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/net/sample-LD.cs diff --git a/cmd/analyze/code-samples/launchDarkly/php/sample-LD.php b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/php/sample-LD.php similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/php/sample-LD.php rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/php/sample-LD.php diff --git a/cmd/analyze/code-samples/launchDarkly/python/sample-LD.py b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/python/sample-LD.py similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/python/sample-LD.py rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/python/sample-LD.py diff --git a/cmd/analyze/code-samples/launchDarkly/react/sample-LD.jsx b/cmd/feature_experimentation/analyze/code-samples/launchDarkly/react/sample-LD.jsx similarity index 100% rename from cmd/analyze/code-samples/launchDarkly/react/sample-LD.jsx rename to cmd/feature_experimentation/analyze/code-samples/launchDarkly/react/sample-LD.jsx diff --git a/cmd/analyze/code-samples/optimizely/go/sample-OPT.go b/cmd/feature_experimentation/analyze/code-samples/optimizely/go/sample-OPT.go similarity index 100% rename from cmd/analyze/code-samples/optimizely/go/sample-OPT.go rename to cmd/feature_experimentation/analyze/code-samples/optimizely/go/sample-OPT.go diff --git a/cmd/analyze/code-samples/optimizely/ios/sample-OPT.m b/cmd/feature_experimentation/analyze/code-samples/optimizely/ios/sample-OPT.m similarity index 100% rename from cmd/analyze/code-samples/optimizely/ios/sample-OPT.m rename to cmd/feature_experimentation/analyze/code-samples/optimizely/ios/sample-OPT.m diff --git a/cmd/analyze/code-samples/optimizely/ios/sample-OPT.swift b/cmd/feature_experimentation/analyze/code-samples/optimizely/ios/sample-OPT.swift similarity index 100% rename from cmd/analyze/code-samples/optimizely/ios/sample-OPT.swift rename to cmd/feature_experimentation/analyze/code-samples/optimizely/ios/sample-OPT.swift diff --git a/cmd/analyze/code-samples/optimizely/java/sample-OPT.java b/cmd/feature_experimentation/analyze/code-samples/optimizely/java/sample-OPT.java similarity index 100% rename from cmd/analyze/code-samples/optimizely/java/sample-OPT.java rename to cmd/feature_experimentation/analyze/code-samples/optimizely/java/sample-OPT.java diff --git a/cmd/analyze/code-samples/optimizely/java/sample-OPT.kt b/cmd/feature_experimentation/analyze/code-samples/optimizely/java/sample-OPT.kt similarity index 100% rename from cmd/analyze/code-samples/optimizely/java/sample-OPT.kt rename to cmd/feature_experimentation/analyze/code-samples/optimizely/java/sample-OPT.kt diff --git a/cmd/analyze/code-samples/optimizely/js/sample-OPT.js b/cmd/feature_experimentation/analyze/code-samples/optimizely/js/sample-OPT.js similarity index 100% rename from cmd/analyze/code-samples/optimizely/js/sample-OPT.js rename to cmd/feature_experimentation/analyze/code-samples/optimizely/js/sample-OPT.js diff --git a/cmd/analyze/code-samples/optimizely/js/sample-OPT.ts b/cmd/feature_experimentation/analyze/code-samples/optimizely/js/sample-OPT.ts similarity index 100% rename from cmd/analyze/code-samples/optimizely/js/sample-OPT.ts rename to cmd/feature_experimentation/analyze/code-samples/optimizely/js/sample-OPT.ts diff --git a/cmd/analyze/code-samples/optimizely/net/sample-OPT.cs b/cmd/feature_experimentation/analyze/code-samples/optimizely/net/sample-OPT.cs similarity index 100% rename from cmd/analyze/code-samples/optimizely/net/sample-OPT.cs rename to cmd/feature_experimentation/analyze/code-samples/optimizely/net/sample-OPT.cs diff --git a/cmd/analyze/code-samples/optimizely/php/sample-OPT.php b/cmd/feature_experimentation/analyze/code-samples/optimizely/php/sample-OPT.php similarity index 100% rename from cmd/analyze/code-samples/optimizely/php/sample-OPT.php rename to cmd/feature_experimentation/analyze/code-samples/optimizely/php/sample-OPT.php diff --git a/cmd/analyze/code-samples/optimizely/python/sample-OPT.py b/cmd/feature_experimentation/analyze/code-samples/optimizely/python/sample-OPT.py similarity index 100% rename from cmd/analyze/code-samples/optimizely/python/sample-OPT.py rename to cmd/feature_experimentation/analyze/code-samples/optimizely/python/sample-OPT.py diff --git a/cmd/analyze/code-samples/optimizely/react/sample-OPT.jsx b/cmd/feature_experimentation/analyze/code-samples/optimizely/react/sample-OPT.jsx similarity index 100% rename from cmd/analyze/code-samples/optimizely/react/sample-OPT.jsx rename to cmd/feature_experimentation/analyze/code-samples/optimizely/react/sample-OPT.jsx diff --git a/cmd/analyze/code-samples/split/go/sample-SPLIT.go b/cmd/feature_experimentation/analyze/code-samples/split/go/sample-SPLIT.go similarity index 100% rename from cmd/analyze/code-samples/split/go/sample-SPLIT.go rename to cmd/feature_experimentation/analyze/code-samples/split/go/sample-SPLIT.go diff --git a/cmd/analyze/code-samples/split/java/sample-SPLIT.java b/cmd/feature_experimentation/analyze/code-samples/split/java/sample-SPLIT.java similarity index 100% rename from cmd/analyze/code-samples/split/java/sample-SPLIT.java rename to cmd/feature_experimentation/analyze/code-samples/split/java/sample-SPLIT.java diff --git a/cmd/analyze/code-samples/split/java/sample-SPLIT.kt b/cmd/feature_experimentation/analyze/code-samples/split/java/sample-SPLIT.kt similarity index 100% rename from cmd/analyze/code-samples/split/java/sample-SPLIT.kt rename to cmd/feature_experimentation/analyze/code-samples/split/java/sample-SPLIT.kt diff --git a/cmd/analyze/code-samples/split/js/sample-SPLIT.js b/cmd/feature_experimentation/analyze/code-samples/split/js/sample-SPLIT.js similarity index 100% rename from cmd/analyze/code-samples/split/js/sample-SPLIT.js rename to cmd/feature_experimentation/analyze/code-samples/split/js/sample-SPLIT.js diff --git a/cmd/analyze/code-samples/split/js/sample-SPLIT.ts b/cmd/feature_experimentation/analyze/code-samples/split/js/sample-SPLIT.ts similarity index 100% rename from cmd/analyze/code-samples/split/js/sample-SPLIT.ts rename to cmd/feature_experimentation/analyze/code-samples/split/js/sample-SPLIT.ts diff --git a/cmd/analyze/code-samples/split/net/sample-SPLIT.cs b/cmd/feature_experimentation/analyze/code-samples/split/net/sample-SPLIT.cs similarity index 100% rename from cmd/analyze/code-samples/split/net/sample-SPLIT.cs rename to cmd/feature_experimentation/analyze/code-samples/split/net/sample-SPLIT.cs diff --git a/cmd/analyze/code-samples/split/php/sample-SPLIT.php b/cmd/feature_experimentation/analyze/code-samples/split/php/sample-SPLIT.php similarity index 100% rename from cmd/analyze/code-samples/split/php/sample-SPLIT.php rename to cmd/feature_experimentation/analyze/code-samples/split/php/sample-SPLIT.php diff --git a/cmd/analyze/code-samples/split/python/sample-SPLIT.py b/cmd/feature_experimentation/analyze/code-samples/split/python/sample-SPLIT.py similarity index 100% rename from cmd/analyze/code-samples/split/python/sample-SPLIT.py rename to cmd/feature_experimentation/analyze/code-samples/split/python/sample-SPLIT.py diff --git a/cmd/analyze/code-samples/vwo/go/sample-VWO.go b/cmd/feature_experimentation/analyze/code-samples/vwo/go/sample-VWO.go similarity index 100% rename from cmd/analyze/code-samples/vwo/go/sample-VWO.go rename to cmd/feature_experimentation/analyze/code-samples/vwo/go/sample-VWO.go diff --git a/cmd/analyze/code-samples/vwo/java/sample-VWO.java b/cmd/feature_experimentation/analyze/code-samples/vwo/java/sample-VWO.java similarity index 100% rename from cmd/analyze/code-samples/vwo/java/sample-VWO.java rename to cmd/feature_experimentation/analyze/code-samples/vwo/java/sample-VWO.java diff --git a/cmd/analyze/code-samples/vwo/java/sample-VWO.kt b/cmd/feature_experimentation/analyze/code-samples/vwo/java/sample-VWO.kt similarity index 100% rename from cmd/analyze/code-samples/vwo/java/sample-VWO.kt rename to cmd/feature_experimentation/analyze/code-samples/vwo/java/sample-VWO.kt diff --git a/cmd/analyze/code-samples/vwo/js/sample-VWO.js b/cmd/feature_experimentation/analyze/code-samples/vwo/js/sample-VWO.js similarity index 100% rename from cmd/analyze/code-samples/vwo/js/sample-VWO.js rename to cmd/feature_experimentation/analyze/code-samples/vwo/js/sample-VWO.js diff --git a/cmd/analyze/code-samples/vwo/js/sample-VWO.ts b/cmd/feature_experimentation/analyze/code-samples/vwo/js/sample-VWO.ts similarity index 100% rename from cmd/analyze/code-samples/vwo/js/sample-VWO.ts rename to cmd/feature_experimentation/analyze/code-samples/vwo/js/sample-VWO.ts diff --git a/cmd/analyze/code-samples/vwo/net/sample-VWO.cs b/cmd/feature_experimentation/analyze/code-samples/vwo/net/sample-VWO.cs similarity index 100% rename from cmd/analyze/code-samples/vwo/net/sample-VWO.cs rename to cmd/feature_experimentation/analyze/code-samples/vwo/net/sample-VWO.cs diff --git a/cmd/analyze/code-samples/vwo/php/sample-VWO.php b/cmd/feature_experimentation/analyze/code-samples/vwo/php/sample-VWO.php similarity index 100% rename from cmd/analyze/code-samples/vwo/php/sample-VWO.php rename to cmd/feature_experimentation/analyze/code-samples/vwo/php/sample-VWO.php diff --git a/cmd/analyze/code-samples/vwo/python/sample-VWO.py b/cmd/feature_experimentation/analyze/code-samples/vwo/python/sample-VWO.py similarity index 100% rename from cmd/analyze/code-samples/vwo/python/sample-VWO.py rename to cmd/feature_experimentation/analyze/code-samples/vwo/python/sample-VWO.py diff --git a/cmd/analyze/flag/create.go b/cmd/feature_experimentation/analyze/flag/create.go similarity index 94% rename from cmd/analyze/flag/create.go rename to cmd/feature_experimentation/analyze/flag/create.go index b21c510..6de7d6b 100644 --- a/cmd/analyze/flag/create.go +++ b/cmd/feature_experimentation/analyze/flag/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -14,8 +13,8 @@ import ( "github.com/fatih/color" "github.com/flagship-io/codebase-analyzer/pkg/handler" - "github.com/flagship-io/flagship/models" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + models "github.com/flagship-io/flagship/models/feature_experimentation" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/rodaine/table" "github.com/spf13/cobra" "golang.org/x/exp/slices" @@ -118,7 +117,7 @@ func flagCreatedTable(cmd *cobra.Command, listedFlags []models.Flag) error { return err_ } - createdFlags, errCreatedFlags := httprequest.HTTPCreateFlag(string(multipleflagRequestJSON)) + createdFlags, errCreatedFlags := httprequest.FlagRequester.HTTPCreateFlag(string(multipleflagRequestJSON)) if errCreatedFlags != nil { return errCreatedFlags @@ -130,7 +129,7 @@ func flagCreatedTable(cmd *cobra.Command, listedFlags []models.Flag) error { return err_json } - listExistingFlags, errListFlag := httprequest.HTTPListFlag() + listExistingFlags, errListFlag := httprequest.FlagRequester.HTTPListFlag() if errListFlag != nil { log.Fatalf("error occurred when listing existing flag: %s", errListFlag) } @@ -181,7 +180,7 @@ var createCmd = &cobra.Command{ PreRunConfiguration() }, Run: func(cmd *cobra.Command, args []string) { - listedExistingFlags, errListFlag := httprequest.HTTPListFlag() + listedExistingFlags, errListFlag := httprequest.FlagRequester.HTTPListFlag() if errListFlag != nil { log.Fatalf("error occurred when listing existing flag: %s", errListFlag) } diff --git a/cmd/analyze/flag/example-regex.json b/cmd/feature_experimentation/analyze/flag/example-regex.json similarity index 100% rename from cmd/analyze/flag/example-regex.json rename to cmd/feature_experimentation/analyze/flag/example-regex.json diff --git a/cmd/analyze/flag/flag.go b/cmd/feature_experimentation/analyze/flag/flag.go similarity index 96% rename from cmd/analyze/flag/flag.go rename to cmd/feature_experimentation/analyze/flag/flag.go index e1e805e..9ebdebd 100644 --- a/cmd/analyze/flag/flag.go +++ b/cmd/feature_experimentation/analyze/flag/flag.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -64,8 +63,8 @@ func PreRunConfiguration() { } FSConfig = &cbaConfig.Config{ - FlagshipAPIURL: utils.GetHost(), - FlagshipAuthAPIURL: utils.GetHostAuth(), + FlagshipAPIURL: utils.GetFeatureExperimentationHost(), + FlagshipAuthAPIURL: utils.GetHostFeatureExperimentationAuth(), FlagshipAPIToken: viper.GetString("token"), FlagshipAccountID: viper.GetString("account_id"), FlagshipEnvironmentID: viper.GetString("account_environment_id"), diff --git a/cmd/analyze/flag/list.go b/cmd/feature_experimentation/analyze/flag/list.go similarity index 96% rename from cmd/analyze/flag/list.go rename to cmd/feature_experimentation/analyze/flag/list.go index 243d4b9..54bf520 100644 --- a/cmd/analyze/flag/list.go +++ b/cmd/feature_experimentation/analyze/flag/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -12,8 +11,8 @@ import ( "github.com/fatih/color" "github.com/flagship-io/codebase-analyzer/pkg/handler" - "github.com/flagship-io/flagship/models" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + models "github.com/flagship-io/flagship/models/feature_experimentation" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/kyokomi/emoji/v2" "github.com/rodaine/table" "github.com/spf13/cobra" @@ -172,7 +171,7 @@ var listCmd = &cobra.Command{ return } - listExistingFlags, errListFlag := httprequest.HTTPListFlag() + listExistingFlags, errListFlag := httprequest.FlagRequester.HTTPListFlag() if errListFlag != nil { log.Fatalf("error occurred when listing existing flag: %s", errListFlag) } diff --git a/cmd/analyze/flag/predefined-regexes/launchdarkly-regexes.json b/cmd/feature_experimentation/analyze/flag/predefined-regexes/launchdarkly-regexes.json similarity index 100% rename from cmd/analyze/flag/predefined-regexes/launchdarkly-regexes.json rename to cmd/feature_experimentation/analyze/flag/predefined-regexes/launchdarkly-regexes.json diff --git a/cmd/analyze/flag/predefined-regexes/optimizely-regexes.json b/cmd/feature_experimentation/analyze/flag/predefined-regexes/optimizely-regexes.json similarity index 100% rename from cmd/analyze/flag/predefined-regexes/optimizely-regexes.json rename to cmd/feature_experimentation/analyze/flag/predefined-regexes/optimizely-regexes.json diff --git a/cmd/analyze/flag/predefined-regexes/split-regexes.json b/cmd/feature_experimentation/analyze/flag/predefined-regexes/split-regexes.json similarity index 100% rename from cmd/analyze/flag/predefined-regexes/split-regexes.json rename to cmd/feature_experimentation/analyze/flag/predefined-regexes/split-regexes.json diff --git a/cmd/analyze/flag/predefined-regexes/template-regexes.json b/cmd/feature_experimentation/analyze/flag/predefined-regexes/template-regexes.json similarity index 100% rename from cmd/analyze/flag/predefined-regexes/template-regexes.json rename to cmd/feature_experimentation/analyze/flag/predefined-regexes/template-regexes.json diff --git a/cmd/analyze/flag/predefined-regexes/vwo-regexes.json b/cmd/feature_experimentation/analyze/flag/predefined-regexes/vwo-regexes.json similarity index 100% rename from cmd/analyze/flag/predefined-regexes/vwo-regexes.json rename to cmd/feature_experimentation/analyze/flag/predefined-regexes/vwo-regexes.json diff --git a/cmd/feature_experimentation/auth/auth.go b/cmd/feature_experimentation/auth/auth.go new file mode 100644 index 0000000..1f07ce2 --- /dev/null +++ b/cmd/feature_experimentation/auth/auth.go @@ -0,0 +1,24 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import "github.com/spf13/cobra" + +var ( + Username string + ClientID string + ClientSecret string + AccountId string +) + +// AuthCmd represents the auth command +var AuthCmd = &cobra.Command{ + Use: "authentication [login|get|list|delete]", + Aliases: []string{"auth"}, + Short: "Manage your CLI authentication for feature experimentation", + Long: `Manage your CLI authentication for feature experimentation`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/feature_experimentation/auth/auth_test.go b/cmd/feature_experimentation/auth/auth_test.go new file mode 100644 index 0000000..3fbfb5b --- /dev/null +++ b/cmd/feature_experimentation/auth/auth_test.go @@ -0,0 +1,84 @@ +package auth + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_fe.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_fe.APIToken() + + m.Run() +} + +var testAuth models.Auth +var testAuthList []models.Auth + +func TestAuthCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AuthCmd) + assert.Contains(t, output, "Manage your CLI authentication for feature experimentation\n\nUsage:\n authentication [login|get|list|delete]") +} + +func TestAuthHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AuthCmd, "--help") + assert.Contains(t, output, "Manage your CLI authentication for feature experimentation\n\nUsage:\n authentication [login|get|list|delete]") +} + +func TestAuthLoginCommand(t *testing.T) { + successOutput, _ := utils.ExecuteCommand(AuthCmd, "login", "-u=test_auth", "-i=testAuthClientID", "-s=testAuthClientSecret", "-a=account_id") + assert.Equal(t, "Credential created successfully\n", successOutput) +} + +func TestAuthListCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AuthCmd, "list") + + err := json.Unmarshal([]byte(output), &testAuthList) + + assert.Nil(t, err) + + byt, err := json.Marshal(feature_experimentation.TestAuth) + + assert.Nil(t, err) + + assert.Contains(t, output, string(byt)) +} + +func TestAuthGetCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AuthCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"username\" not set") + + successOutput, _ := utils.ExecuteCommand(AuthCmd, "get", "--username=test_auth") + err := json.Unmarshal([]byte(successOutput), &testAuth) + + assert.Nil(t, err) + + assert.Equal(t, feature_experimentation.TestAuth, testAuth) +} + +func TestAuthDeleteCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AuthCmd, "delete") + assert.Contains(t, failOutput, "Error: required flag(s) \"username\" not set") + + output, _ := utils.ExecuteCommand(AuthCmd, "delete", "--username=test_auth") + + assert.Contains(t, output, "Credential deleted successfully") +} diff --git a/cmd/feature_experimentation/auth/current.go b/cmd/feature_experimentation/auth/current.go new file mode 100644 index 0000000..6923635 --- /dev/null +++ b/cmd/feature_experimentation/auth/current.go @@ -0,0 +1,52 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// currentCmd represents the current command +var currentCmd = &cobra.Command{ + Use: "current", + Short: "Get current running auth credential for feature experimentation", + Long: `Get current running auth credential for feature experimentation`, + Run: func(cmd *cobra.Command, args []string) { + var accountYaml models.AccountYaml + var account models.AccountJSON + + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + account.CurrentUsedCredential = accountYaml.CurrentUsedCredential + + utils.FormatItem([]string{"CurrentUsedCredential"}, account, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + AuthCmd.AddCommand(currentCmd) +} diff --git a/cmd/feature_experimentation/auth/delete.go b/cmd/feature_experimentation/auth/delete.go new file mode 100644 index 0000000..775e2d8 --- /dev/null +++ b/cmd/feature_experimentation/auth/delete.go @@ -0,0 +1,48 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "fmt" + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" +) + +// deleteCmd represents delete command +var deleteCmd = &cobra.Command{ + Use: "delete [-u | --username=]", + Short: "Delete an auth", + Long: `Delete an auth`, + Run: func(cmd *cobra.Command, args []string) { + + _, err := config.CheckABTastyHomeDirectory() + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + if err := os.Remove(credPath); err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential deleted successfully") + }, +} + +func init() { + deleteCmd.Flags().StringVarP(&Username, "username", "u", "", "username of the credentials you want to delete") + + if err := deleteCmd.MarkFlagRequired("username"); err != nil { + log.Fatalf("error occurred: %v", err) + } + AuthCmd.AddCommand(deleteCmd) +} diff --git a/cmd/feature_experimentation/auth/get.go b/cmd/feature_experimentation/auth/get.go new file mode 100644 index 0000000..26e9267 --- /dev/null +++ b/cmd/feature_experimentation/auth/get.go @@ -0,0 +1,63 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// getCmd represents the list command +var getCmd = &cobra.Command{ + Use: "get", + Short: "get an auth credential for feature experimentation", + Long: `get an auth credential for feature experimentation`, + Run: func(cmd *cobra.Command, args []string) { + + var authYaml models.AuthYaml + var auth models.Auth + + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &authYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + auth.Username = authYaml.Username + auth.ClientID = authYaml.ClientID + auth.ClientSecret = authYaml.ClientSecret + auth.Token = authYaml.Token + auth.RefreshToken = authYaml.RefreshToken + + utils.FormatItem([]string{"Username", "ClientID", "ClientSecret", "Token", "RefreshToken"}, auth, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + getCmd.Flags().StringVarP(&Username, "username", "u", "", "username of the credentials you want to display") + + if err := getCmd.MarkFlagRequired("username"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + AuthCmd.AddCommand(getCmd) +} diff --git a/cmd/feature_experimentation/auth/list.go b/cmd/feature_experimentation/auth/list.go new file mode 100644 index 0000000..e4709e9 --- /dev/null +++ b/cmd/feature_experimentation/auth/list.go @@ -0,0 +1,69 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "list all auth", + Long: `list all auth`, + Run: func(cmd *cobra.Command, args []string) { + + var auths []models.Auth + existingAuths, err := config.GetUsernames(utils.FEATURE_EXPERIMENTATION) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + for _, fileName := range existingAuths { + if fileName != "" { + var authYaml models.AuthYaml + var auth models.Auth + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, fileName) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &authYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + if authYaml.Username != "" { + auth.Username = authYaml.Username + auth.ClientID = authYaml.ClientID + auth.ClientSecret = authYaml.ClientSecret + auth.Token = authYaml.Token + auth.RefreshToken = authYaml.RefreshToken + auths = append(auths, auth) + } + } + } + + utils.FormatItem([]string{"Username", "ClientID", "ClientSecret", "Token"}, auths, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + + AuthCmd.AddCommand(listCmd) +} diff --git a/cmd/feature_experimentation/auth/login.go b/cmd/feature_experimentation/auth/login.go new file mode 100644 index 0000000..82028ef --- /dev/null +++ b/cmd/feature_experimentation/auth/login.go @@ -0,0 +1,157 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "fmt" + "log" + "slices" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/spf13/cobra" +) + +var ( + credentialsFile string +) + +func checkSingleFlag(bool1, bool2 bool) bool { + count := 0 + if bool1 { + count++ + } + if bool2 { + count++ + } + + return count == 1 +} + +// createCmd represents the create command +var loginCmd = &cobra.Command{ + Use: "login [--credential-file] | [-u | --username=] [-i | --client-id=] [-s | --client-secret=] [-a | --account-id=]", + Short: "login", + Long: `login`, + Run: func(cmd *cobra.Command, args []string) { + if !checkSingleFlag(credentialsFile != "", Username != "") { + fmt.Fprintf(cmd.OutOrStderr(), "error occurred: %s", "1 flag is required. (username, credential-file)") + return + } + + if credentialsFile != "" { + v, err := config.ReadCredentialsFromFile(credentialsFile) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if v.GetString("username") == "" || v.GetString("client_id") == "" || v.GetString("client_secret") == "" || v.GetString("account_id") == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (username, client ID, client secret, account id)") + return + } + authenticationResponse, err := common.HTTPCreateTokenFE(v.GetString("client_id"), v.GetString("client_secret"), v.GetString("account_id")) + if err != nil { + fmt.Fprintf(cmd.OutOrStderr(), "error occurred: %s", err) + return + } + + err = config.CreateAuthFile(utils.FEATURE_EXPERIMENTATION, v.GetString("username"), v.GetString("client_id"), v.GetString("client_secret"), authenticationResponse) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SelectAuth(utils.FEATURE_EXPERIMENTATION, v.GetString("username")) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.FEATURE_EXPERIMENTATION, v.GetString("account_id")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + if v.GetString("account_environment_id") != "" { + err := config.SetAccountEnvID(utils.FEATURE_EXPERIMENTATION, v.GetString("account_environment_id")) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential created successfully") + return + } + + if Username != "" { + existingCredentials, err := config.GetUsernames(utils.FEATURE_EXPERIMENTATION) + if err != nil { + fmt.Fprintf(cmd.OutOrStderr(), "error occurred: %s", err) + return + } + + if slices.Contains(existingCredentials, Username) { + if AccountId != "" { + err := config.SelectAuth(utils.FEATURE_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.FEATURE_EXPERIMENTATION, AccountId) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential changed successfully to "+Username) + return + } + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (account id)") + return + } + + if ClientID == "" || ClientSecret == "" || AccountId == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (username, client ID, client secret, account id)") + return + } + authenticationResponse, err := common.HTTPCreateTokenFE(ClientID, ClientSecret, AccountId) + if err != nil { + fmt.Fprintln(cmd.OutOrStderr(), err) + return + } + + if authenticationResponse.AccessToken == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, client_id or client_secret not valid") + return + } + + err = config.CreateAuthFile(utils.FEATURE_EXPERIMENTATION, Username, ClientID, ClientSecret, authenticationResponse) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SelectAuth(utils.FEATURE_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.FEATURE_EXPERIMENTATION, AccountId) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential created successfully") + } + + }, +} + +func init() { + + loginCmd.Flags().StringVarP(&Username, "username", "u", "", "auth username") + loginCmd.Flags().StringVarP(&ClientID, "client-id", "i", "", "client ID of an auth") + loginCmd.Flags().StringVarP(&ClientSecret, "client-secret", "s", "", "client secret of an auth") + loginCmd.Flags().StringVarP(&AccountId, "account-id", "a", "", "account id of an auth") + + loginCmd.Flags().StringVarP(&credentialsFile, "credential-file", "p", "", "config file to create") + AuthCmd.AddCommand(loginCmd) +} diff --git a/cmd/campaign/campaign.go b/cmd/feature_experimentation/campaign/campaign.go similarity index 99% rename from cmd/campaign/campaign.go rename to cmd/feature_experimentation/campaign/campaign.go index 85c0dce..470216f 100644 --- a/cmd/campaign/campaign.go +++ b/cmd/feature_experimentation/campaign/campaign.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign diff --git a/cmd/campaign/campaign_test.go b/cmd/feature_experimentation/campaign/campaign_test.go similarity index 88% rename from cmd/campaign/campaign_test.go rename to cmd/feature_experimentation/campaign/campaign_test.go index 1703ba6..57c2b51 100644 --- a/cmd/campaign/campaign_test.go +++ b/cmd/feature_experimentation/campaign/campaign_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,12 +19,14 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APICampaign() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APICampaign() + m.Run() } -var testCampaign models.Campaign -var testCampaignList []models.Campaign +var testCampaign models.CampaignFE +var testCampaignList []models.CampaignFE func TestCampaignCommand(t *testing.T) { output, _ := utils.ExecuteCommand(CampaignCmd) @@ -44,7 +49,7 @@ func TestCampaignGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestCampaign, testCampaign) + assert.Equal(t, mockfunction_fe.TestCampaign, testCampaign) } func TestCampaignListCommand(t *testing.T) { @@ -55,7 +60,7 @@ func TestCampaignListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestCampaignlist, testCampaignList) + assert.Equal(t, mockfunction_fe.TestCampaignlist, testCampaignList) } func TestCampaignCreateCommand(t *testing.T) { @@ -69,7 +74,7 @@ func TestCampaignCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestCampaign, testCampaign) + assert.Equal(t, mockfunction_fe.TestCampaign, testCampaign) } func TestCampaignEditCommand(t *testing.T) { @@ -83,7 +88,7 @@ func TestCampaignEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestCampaignEdit, testCampaign) + assert.Equal(t, mockfunction_fe.TestCampaignEdit, testCampaign) } func TestCampaignDeleteCommand(t *testing.T) { diff --git a/cmd/campaign/create.go b/cmd/feature_experimentation/campaign/create.go similarity index 81% rename from cmd/campaign/create.go rename to cmd/feature_experimentation/campaign/create.go index 25d501a..6d30fb8 100644 --- a/cmd/campaign/create.go +++ b/cmd/feature_experimentation/campaign/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [-d | --data-raw=]", Short: "Create a campaign", - Long: `Create a campaign in your project`, + Long: `Create a campaign`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPCreateCampaign(DataRaw) + body, err := httprequest.CampaignFERequester.HTTPCreateCampaign(DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/campaign/delete.go b/cmd/feature_experimentation/campaign/delete.go similarity index 81% rename from cmd/campaign/delete.go rename to cmd/feature_experimentation/campaign/delete.go index 4a3cf42..c0589c5 100644 --- a/cmd/campaign/delete.go +++ b/cmd/feature_experimentation/campaign/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-i | --id=]", Short: "Delete a campaign", - Long: `Delete a campaign in your project`, + Long: `Delete a campaign`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteCampaign(CampaignID) + err := httprequest.CampaignFERequester.HTTPDeleteCampaign(CampaignID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/campaign/edit.go b/cmd/feature_experimentation/campaign/edit.go similarity index 84% rename from cmd/campaign/edit.go rename to cmd/feature_experimentation/campaign/edit.go index d72ac82..12cd681 100644 --- a/cmd/campaign/edit.go +++ b/cmd/feature_experimentation/campaign/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-i | --id=] [ -d | --data-raw=]", Short: "Edit a campaign", - Long: `Edit a campaign in your project`, + Long: `Edit a campaign`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditCampaign(CampaignID, DataRaw) + body, err := httprequest.CampaignFERequester.HTTPEditCampaign(CampaignID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/campaign/get.go b/cmd/feature_experimentation/campaign/get.go similarity index 83% rename from cmd/campaign/get.go rename to cmd/feature_experimentation/campaign/get.go index 27f264b..8a09aa6 100644 --- a/cmd/campaign/get.go +++ b/cmd/feature_experimentation/campaign/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [-i | --id=]", Short: "Get a campaign", - Long: `Get a campaign in your project`, + Long: `Get a campaign`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetCampaign(CampaignID) + body, err := httprequest.CampaignFERequester.HTTPGetCampaign(CampaignID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/campaign/list.go b/cmd/feature_experimentation/campaign/list.go similarity index 83% rename from cmd/campaign/list.go rename to cmd/feature_experimentation/campaign/list.go index 76d2930..d8a3060 100644 --- a/cmd/campaign/list.go +++ b/cmd/feature_experimentation/campaign/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -19,7 +18,7 @@ var listCmd = &cobra.Command{ Short: "List all campaigns", Long: `List all campaigns`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListCampaign() + body, err := httprequest.CampaignFERequester.HTTPListCampaign() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/campaign/switch.go b/cmd/feature_experimentation/campaign/switch.go similarity index 87% rename from cmd/campaign/switch.go rename to cmd/feature_experimentation/campaign/switch.go index 60a2c29..53cccf4 100644 --- a/cmd/campaign/switch.go +++ b/cmd/feature_experimentation/campaign/switch.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package campaign @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,12 +15,12 @@ import ( var SwitchCmd = &cobra.Command{ Use: "switch [-i | --id=] [-s | --status=]", Short: "Switch a campaign state", - Long: `Switch a campaign state in your project`, + Long: `Switch a campaign state`, Run: func(cmd *cobra.Command, args []string) { if !(Status == "active" || Status == "paused" || Status == "interrupted") { fmt.Fprintln(cmd.OutOrStdout(), "Status can only have 3 values: active or paused or interrupted") } else { - err := httprequest.HTTPSwitchCampaign(CampaignID, Status) + err := httprequest.CampaignFERequester.HTTPSwitchCampaign(CampaignID, Status) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/feature_experimentation/feature_experimentation.go b/cmd/feature_experimentation/feature_experimentation.go new file mode 100644 index 0000000..c453f47 --- /dev/null +++ b/cmd/feature_experimentation/feature_experimentation.go @@ -0,0 +1,95 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package feature_experimentation + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/cmd/feature_experimentation/account" + accountenvironment "github.com/flagship-io/flagship/cmd/feature_experimentation/account_environment" + "github.com/flagship-io/flagship/cmd/feature_experimentation/analyze" + "github.com/flagship-io/flagship/cmd/feature_experimentation/auth" + "github.com/flagship-io/flagship/cmd/feature_experimentation/campaign" + "github.com/flagship-io/flagship/cmd/feature_experimentation/flag" + "github.com/flagship-io/flagship/cmd/feature_experimentation/goal" + "github.com/flagship-io/flagship/cmd/feature_experimentation/panic" + "github.com/flagship-io/flagship/cmd/feature_experimentation/project" + "github.com/flagship-io/flagship/cmd/feature_experimentation/resource" + targetingkey "github.com/flagship-io/flagship/cmd/feature_experimentation/targeting_key" + "github.com/flagship-io/flagship/cmd/feature_experimentation/token" + "github.com/flagship-io/flagship/cmd/feature_experimentation/user" + "github.com/flagship-io/flagship/cmd/feature_experimentation/variation" + variationgroup "github.com/flagship-io/flagship/cmd/feature_experimentation/variation_group" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/flagship-io/flagship/utils/http_request" + "github.com/flagship-io/flagship/utils/http_request/common" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// FeatureExperimentationCmd represents the feature experimentation command +var FeatureExperimentationCmd = &cobra.Command{ + Use: "feature-experimentation [auth|account|account-environment|project|campaign|flag|goal|targeting-key|variation-group|variation]", + Aliases: []string{"feature-experimentation", "feature-exp", "fe", "feat-exp"}, + Short: "Manage resources related to the feature experimentation product", + Long: `Manage resources related to the feature experimentation product in your account`, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + initConfig() + }, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func addSubCommandPalettes() { + FeatureExperimentationCmd.AddCommand(campaign.CampaignCmd) + FeatureExperimentationCmd.AddCommand(project.ProjectCmd) + FeatureExperimentationCmd.AddCommand(panic.PanicCmd) + FeatureExperimentationCmd.AddCommand(user.UserCmd) + FeatureExperimentationCmd.AddCommand(variationgroup.VariationGroupCmd) + FeatureExperimentationCmd.AddCommand(variation.VariationCmd) + FeatureExperimentationCmd.AddCommand(flag.FlagCmd) + FeatureExperimentationCmd.AddCommand(goal.GoalCmd) + FeatureExperimentationCmd.AddCommand(targetingkey.TargetingKeyCmd) + FeatureExperimentationCmd.AddCommand(analyze.AnalyzeCmd) + FeatureExperimentationCmd.AddCommand(resource.ResourceCmd) + FeatureExperimentationCmd.AddCommand(auth.AuthCmd) + FeatureExperimentationCmd.AddCommand(account.AccountCmd) + FeatureExperimentationCmd.AddCommand(token.TokenCmd) + FeatureExperimentationCmd.AddCommand(accountenvironment.AccountEnvironmentCmd) +} + +func init() { + addSubCommandPalettes() +} + +func initConfig() { + v := viper.New() + homeDir, _ := os.UserHomeDir() + var requestConfig = common.RequestConfig{Product: utils.FEATURE_EXPERIMENTATION} + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.FEATURE_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + if v.GetString("current_used_credential") != "" { + vL, err := config.ReadAuth(utils.FEATURE_EXPERIMENTATION, v.GetString("current_used_credential")) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + v.MergeConfigMap(vL.AllSettings()) + } + + v.Unmarshal(&requestConfig) + common.Init(requestConfig) + resource.Init(requestConfig) + viper.MergeConfigMap(v.AllSettings()) + + r := &http_request.ResourceRequester + + r.Init(&requestConfig) + return + +} diff --git a/cmd/feature_experimentation/feature_experimentation_test.go b/cmd/feature_experimentation/feature_experimentation_test.go new file mode 100644 index 0000000..93369c3 --- /dev/null +++ b/cmd/feature_experimentation/feature_experimentation_test.go @@ -0,0 +1,29 @@ +package feature_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_fe.InitMockAuth() + + m.Run() +} + +func TestAccountCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(FeatureExperimentationCmd) + assert.Contains(t, output, "Manage resources related to the feature experimentation product") +} + +func TestAccountHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(FeatureExperimentationCmd, "--help") + assert.Contains(t, output, "Manage resources related to the feature experimentation product") +} diff --git a/cmd/flag/create.go b/cmd/feature_experimentation/flag/create.go similarity index 89% rename from cmd/flag/create.go rename to cmd/feature_experimentation/flag/create.go index 961816a..d4338ce 100644 --- a/cmd/flag/create.go +++ b/cmd/feature_experimentation/flag/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -9,8 +8,8 @@ import ( "fmt" "log" - "github.com/flagship-io/flagship/models" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + models "github.com/flagship-io/flagship/models/feature_experimentation" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -18,7 +17,7 @@ import ( var createCmd = &cobra.Command{ Use: "create [--name --type --default-value --description --predefined-values | -d | --data-raw ]", Short: "Create a flag", - Long: `Create a flag in your account`, + Long: `Create a flag`, Run: func(cmd *cobra.Command, args []string) { var data string var predefinedValues_ []string @@ -48,7 +47,7 @@ var createCmd = &cobra.Command{ data = string(data_) } - body, err := httprequest.HTTPCreateFlag(data) + body, err := httprequest.FlagRequester.HTTPCreateFlag(data) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/flag/delete.go b/cmd/feature_experimentation/flag/delete.go similarity index 81% rename from cmd/flag/delete.go rename to cmd/feature_experimentation/flag/delete.go index 49be244..6a0f18f 100644 --- a/cmd/flag/delete.go +++ b/cmd/feature_experimentation/flag/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-i | --id=]", Short: "Delete a flag", - Long: `Delete a flag in your account`, + Long: `Delete a flag`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteFlag(FlagID) + err := httprequest.FlagRequester.HTTPDeleteFlag(FlagID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/flag/edit.go b/cmd/feature_experimentation/flag/edit.go similarity index 85% rename from cmd/flag/edit.go rename to cmd/feature_experimentation/flag/edit.go index 62fe98a..8d07b76 100644 --- a/cmd/flag/edit.go +++ b/cmd/feature_experimentation/flag/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-i | --id=] [-d | --data-raw ]", Short: "Edit a flag", - Long: `Edit a flag in your account`, + Long: `Edit a flag`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditFlag(FlagID, DataRaw) + body, err := httprequest.FlagRequester.HTTPEditFlag(FlagID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/flag/flag.go b/cmd/feature_experimentation/flag/flag.go similarity index 92% rename from cmd/flag/flag.go rename to cmd/feature_experimentation/flag/flag.go index 96875d4..5935bdf 100644 --- a/cmd/flag/flag.go +++ b/cmd/feature_experimentation/flag/flag.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -22,7 +21,7 @@ var ( var FlagCmd = &cobra.Command{ Use: "flag [create|edit|get|list|delete|usage]", Short: "Manage your flags", - Long: `Manage your flags in your account`, + Long: `Manage your flags`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, diff --git a/cmd/flag/flag_test.go b/cmd/feature_experimentation/flag/flag_test.go similarity index 77% rename from cmd/flag/flag_test.go rename to cmd/feature_experimentation/flag/flag_test.go index f709252..9849f3a 100644 --- a/cmd/flag/flag_test.go +++ b/cmd/feature_experimentation/flag/flag_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIFlag() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIFlag() m.Run() } @@ -25,12 +29,12 @@ var testFlagList []models.Flag func TestFlagCommand(t *testing.T) { output, _ := utils.ExecuteCommand(FlagCmd) - assert.Contains(t, output, "Manage your flags in your account") + assert.Contains(t, output, "Manage your flags") } func TestFlagHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(FlagCmd, "--help") - assert.Contains(t, output, "Manage your flags in your account") + assert.Contains(t, output, "Manage your flags") } func TestFlagGetCommand(t *testing.T) { @@ -44,7 +48,7 @@ func TestFlagGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestFlag, testFlag) + assert.Equal(t, mockfunction_fe.TestFlag, testFlag) } func TestFlagListCommand(t *testing.T) { @@ -55,7 +59,7 @@ func TestFlagListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestFlagList, testFlagList) + assert.Equal(t, mockfunction_fe.TestFlagList, testFlagList) } func TestFlagCreateCommand(t *testing.T) { @@ -66,7 +70,7 @@ func TestFlagCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestFlag, testFlag) + assert.Equal(t, mockfunction_fe.TestFlag, testFlag) } func TestFlagEditCommand(t *testing.T) { @@ -80,7 +84,7 @@ func TestFlagEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestFlagEdit, testFlag) + assert.Equal(t, mockfunction_fe.TestFlagEdit, testFlag) } func TestFlagDeleteCommand(t *testing.T) { diff --git a/cmd/flag/get.go b/cmd/feature_experimentation/flag/get.go similarity index 84% rename from cmd/flag/get.go rename to cmd/feature_experimentation/flag/get.go index 5ce80f0..9e419d2 100644 --- a/cmd/flag/get.go +++ b/cmd/feature_experimentation/flag/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [-i | --id=]", Short: "Get a flag", - Long: `Get a flag in your account`, + Long: `Get a flag`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetFlag(FlagID) + body, err := httprequest.FlagRequester.HTTPGetFlag(FlagID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/flag/list.go b/cmd/feature_experimentation/flag/list.go similarity index 79% rename from cmd/flag/list.go rename to cmd/feature_experimentation/flag/list.go index 6e75fa5..36d1106 100644 --- a/cmd/flag/list.go +++ b/cmd/feature_experimentation/flag/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package flag @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list", Short: "List all flags", - Long: `List all flags in your account`, + Long: `List all flags`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListFlag() + body, err := httprequest.FlagRequester.HTTPListFlag() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/goal/create.go b/cmd/feature_experimentation/goal/create.go similarity index 82% rename from cmd/goal/create.go rename to cmd/feature_experimentation/goal/create.go index cdc0d64..084b74a 100644 --- a/cmd/goal/create.go +++ b/cmd/feature_experimentation/goal/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [-d | --data-raw ]", Short: "Create a goal", - Long: `Create a goal in your account`, + Long: `Create a goal`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPCreateGoal(DataRaw) + body, err := httprequest.GoalRequester.HTTPCreateGoal(DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/goal/delete.go b/cmd/feature_experimentation/goal/delete.go similarity index 81% rename from cmd/goal/delete.go rename to cmd/feature_experimentation/goal/delete.go index 09a1f61..776037f 100644 --- a/cmd/goal/delete.go +++ b/cmd/feature_experimentation/goal/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-i | --id=]", Short: "Delete a flag", - Long: `Delete a flag in your account`, + Long: `Delete a flag`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteGoal(GoalID) + err := httprequest.GoalRequester.HTTPDeleteGoal(GoalID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/goal/edit.go b/cmd/feature_experimentation/goal/edit.go similarity index 85% rename from cmd/goal/edit.go rename to cmd/feature_experimentation/goal/edit.go index d5166be..0636e13 100644 --- a/cmd/goal/edit.go +++ b/cmd/feature_experimentation/goal/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-i | --id=] [-d | --data-raw ]", Short: "Edit a goal", - Long: `Edit a goal in your account`, + Long: `Edit a goal`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditGoal(GoalID, DataRaw) + body, err := httprequest.GoalRequester.HTTPEditGoal(GoalID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/goal/get.go b/cmd/feature_experimentation/goal/get.go similarity index 84% rename from cmd/goal/get.go rename to cmd/feature_experimentation/goal/get.go index c59533e..673afda 100644 --- a/cmd/goal/get.go +++ b/cmd/feature_experimentation/goal/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [-i | --id=]", Short: "Get a goal", - Long: `Get a goal in your account`, + Long: `Get a goal`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetGoal(GoalID) + body, err := httprequest.GoalRequester.HTTPGetGoal(GoalID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/goal/goal.go b/cmd/feature_experimentation/goal/goal.go similarity index 88% rename from cmd/goal/goal.go rename to cmd/feature_experimentation/goal/goal.go index 9cbfe12..3cb6a66 100644 --- a/cmd/goal/goal.go +++ b/cmd/feature_experimentation/goal/goal.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -17,7 +16,7 @@ var ( var GoalCmd = &cobra.Command{ Use: "goal [create|edit|get|list|delete]", Short: "Manage your goals", - Long: `Manage your goals in your account`, + Long: `Manage your goals`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, diff --git a/cmd/goal/goal_test.go b/cmd/feature_experimentation/goal/goal_test.go similarity index 78% rename from cmd/goal/goal_test.go rename to cmd/feature_experimentation/goal/goal_test.go index eba3da4..4dfd296 100644 --- a/cmd/goal/goal_test.go +++ b/cmd/feature_experimentation/goal/goal_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,9 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIGoal() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIGoal() + m.Run() } @@ -25,12 +30,12 @@ var testGoalList []models.Goal func TestGoalCommand(t *testing.T) { output, _ := utils.ExecuteCommand(GoalCmd) - assert.Contains(t, output, "Manage your goals in your account") + assert.Contains(t, output, "Manage your goals") } func TestGoalHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(GoalCmd, "--help") - assert.Contains(t, output, "Manage your goals in your account") + assert.Contains(t, output, "Manage your goals") } func TestGoalGetCommand(t *testing.T) { @@ -44,7 +49,7 @@ func TestGoalGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestGoal, testGoal) + assert.Equal(t, mockfunction_fe.TestGoal, testGoal) } func TestGoalListCommand(t *testing.T) { @@ -55,7 +60,7 @@ func TestGoalListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestGoalList, testGoalList) + assert.Equal(t, mockfunction_fe.TestGoalList, testGoalList) } func TestGoalCreateCommand(t *testing.T) { @@ -70,7 +75,7 @@ func TestGoalCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestGoal, testGoal) + assert.Equal(t, mockfunction_fe.TestGoal, testGoal) } func TestGoalEditCommand(t *testing.T) { @@ -84,7 +89,7 @@ func TestGoalEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestGoalEdit, testGoal) + assert.Equal(t, mockfunction_fe.TestGoalEdit, testGoal) } func TestGoalDeleteCommand(t *testing.T) { diff --git a/cmd/goal/list.go b/cmd/feature_experimentation/goal/list.go similarity index 79% rename from cmd/goal/list.go rename to cmd/feature_experimentation/goal/list.go index 0a4db47..2631a82 100644 --- a/cmd/goal/list.go +++ b/cmd/feature_experimentation/goal/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package goal @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list", Short: "List all goals", - Long: `List all goals in your account`, + Long: `List all goals`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListGoal() + body, err := httprequest.GoalRequester.HTTPListGoal() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/panic/panic.go b/cmd/feature_experimentation/panic/panic.go similarity index 84% rename from cmd/panic/panic.go rename to cmd/feature_experimentation/panic/panic.go index dcfd0bc..65705f2 100644 --- a/cmd/panic/panic.go +++ b/cmd/feature_experimentation/panic/panic.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package panic @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -18,13 +17,13 @@ var panicStatus string var PanicCmd = &cobra.Command{ Use: "panic", Short: "Manage panic mode", - Long: `Manage panic mode in your account`, + Long: `Manage panic mode`, Run: func(cmd *cobra.Command, args []string) { if !(panicStatus == "on" || panicStatus == "off") { fmt.Fprintln(cmd.OutOrStdout(), "Status can only have 2 values: on or off ") return } - _, err := httprequest.HTTPUpdatePanic(panicStatus) + _, err := httprequest.PanicRequester.HTTPUpdatePanic(panicStatus) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/panic/panic_test.go b/cmd/feature_experimentation/panic/panic_test.go similarity index 77% rename from cmd/panic/panic_test.go rename to cmd/feature_experimentation/panic/panic_test.go index f4f0272..fcea42e 100644 --- a/cmd/panic/panic_test.go +++ b/cmd/feature_experimentation/panic/panic_test.go @@ -4,7 +4,9 @@ import ( "testing" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -14,7 +16,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIPanic() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIPanic() m.Run() } diff --git a/cmd/project/create.go b/cmd/feature_experimentation/project/create.go similarity index 78% rename from cmd/project/create.go rename to cmd/feature_experimentation/project/create.go index 8e59a90..3147b3c 100644 --- a/cmd/project/create.go +++ b/cmd/feature_experimentation/project/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -9,8 +8,8 @@ import ( "fmt" "log" - "github.com/flagship-io/flagship/models" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + models "github.com/flagship-io/flagship/models/feature_experimentation" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -18,7 +17,7 @@ import ( var createCmd = &cobra.Command{ Use: "create [-n | --name=]", Short: "Create a project", - Long: `Create a project in your account`, + Long: `Create a project`, Run: func(cmd *cobra.Command, args []string) { projectRequest := models.Project{ Name: ProjectName, @@ -29,7 +28,7 @@ var createCmd = &cobra.Command{ log.Fatalf("error occurred: %s", err) } - body, err := httprequest.HTTPCreateProject(projectRequestJSON) + body, err := httprequest.ProjectRequester.HTTPCreateProject(projectRequestJSON) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/project/delete.go b/cmd/feature_experimentation/project/delete.go similarity index 81% rename from cmd/project/delete.go rename to cmd/feature_experimentation/project/delete.go index ab7f60d..f5f6dcf 100644 --- a/cmd/project/delete.go +++ b/cmd/feature_experimentation/project/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-i | --id=]", Short: "Delete a project", - Long: `Delete a project in your account`, + Long: `Delete a project`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteProject(ProjectId) + err := httprequest.ProjectRequester.HTTPDeleteProject(ProjectId) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/project/edit.go b/cmd/feature_experimentation/project/edit.go similarity index 81% rename from cmd/project/edit.go rename to cmd/feature_experimentation/project/edit.go index 3025a7b..dcd05b7 100644 --- a/cmd/project/edit.go +++ b/cmd/feature_experimentation/project/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -9,8 +8,8 @@ import ( "fmt" "log" - "github.com/flagship-io/flagship/models" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + models "github.com/flagship-io/flagship/models/feature_experimentation" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -18,7 +17,7 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-i | --id=] [-n | --name=]", Short: "Edit a project", - Long: `Edit a project in your account`, + Long: `Edit a project`, Run: func(cmd *cobra.Command, args []string) { projectRequest := models.Project{ Name: ProjectName, @@ -29,7 +28,7 @@ var editCmd = &cobra.Command{ log.Fatalf("error occurred: %s", err) } - body, err := httprequest.HTTPEditProject(ProjectId, projectRequestJSON) + body, err := httprequest.ProjectRequester.HTTPEditProject(ProjectId, projectRequestJSON) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/project/get.go b/cmd/feature_experimentation/project/get.go similarity index 83% rename from cmd/project/get.go rename to cmd/feature_experimentation/project/get.go index d5fdf57..08eb5a1 100644 --- a/cmd/project/get.go +++ b/cmd/feature_experimentation/project/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [-i | --id=]", Short: "Get a project", - Long: `Get a project in your account`, + Long: `Get a project`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetProject(ProjectId) + body, err := httprequest.ProjectRequester.HTTPGetProject(ProjectId) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/project/list.go b/cmd/feature_experimentation/project/list.go similarity index 78% rename from cmd/project/list.go rename to cmd/feature_experimentation/project/list.go index b8fafdc..a727399 100644 --- a/cmd/project/list.go +++ b/cmd/feature_experimentation/project/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list", Short: "List all projects", - Long: `List all projects in your account`, + Long: `List all projects`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListProject() + body, err := httprequest.ProjectRequester.HTTPListProject() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/project/project.go b/cmd/feature_experimentation/project/project.go similarity index 100% rename from cmd/project/project.go rename to cmd/feature_experimentation/project/project.go diff --git a/cmd/project/project_test.go b/cmd/feature_experimentation/project/project_test.go similarity index 83% rename from cmd/project/project_test.go rename to cmd/feature_experimentation/project/project_test.go index 4d3e707..7242801 100644 --- a/cmd/project/project_test.go +++ b/cmd/feature_experimentation/project/project_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIProject() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIProject() m.Run() } @@ -45,7 +49,7 @@ func TestProjectGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestProject, testProject) + assert.Equal(t, mockfunction_fe.TestProject, testProject) } func TestProjectListCommand(t *testing.T) { @@ -56,7 +60,7 @@ func TestProjectListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestProjectList, testProjectList) + assert.Equal(t, mockfunction_fe.TestProjectList, testProjectList) } func TestProjectCreateCommand(t *testing.T) { @@ -70,7 +74,7 @@ func TestProjectCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestProject, testProject) + assert.Equal(t, mockfunction_fe.TestProject, testProject) } func TestProjectEditCommand(t *testing.T) { @@ -84,7 +88,7 @@ func TestProjectEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestProjectEdit, testProject) + assert.Equal(t, mockfunction_fe.TestProjectEdit, testProject) } func TestProjectDeleteCommand(t *testing.T) { diff --git a/cmd/project/switch.go b/cmd/feature_experimentation/project/switch.go similarity index 87% rename from cmd/project/switch.go rename to cmd/feature_experimentation/project/switch.go index 7670c44..fb8b68f 100644 --- a/cmd/project/switch.go +++ b/cmd/feature_experimentation/project/switch.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package project @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,14 +15,14 @@ import ( var switchCmd = &cobra.Command{ Use: "switch [-i | --id=] [-s | --status=]", Short: "switch a project state", - Long: `switch a project state in your account`, + Long: `switch a project state`, Run: func(cmd *cobra.Command, args []string) { if !(ProjectStatus == "active" || ProjectStatus == "paused" || ProjectStatus == "interrupted") { fmt.Fprintln(cmd.OutOrStdout(), "Status can only have 3 values: active or paused or interrupted") return } - err := httprequest.HTTPSwitchProject(ProjectId, ProjectStatus) + err := httprequest.ProjectRequester.HTTPSwitchProject(ProjectId, ProjectStatus) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/feature_experimentation/resource/load.go b/cmd/feature_experimentation/resource/load.go new file mode 100644 index 0000000..b89b9cb --- /dev/null +++ b/cmd/feature_experimentation/resource/load.go @@ -0,0 +1,507 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com + +*/ + +package resource + +import ( + "context" + "encoding/json" + "fmt" + "log" + "os" + "strings" + + "github.com/d5/tengo/v2" + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var ( + resourceFile string + outputFile string + inputParams string + inputParamsFile string +) + +var inputParamsMap map[string]interface{} + +type Data interface { + Save(data string) ([]byte, error) + Delete(id string) error +} + +type ProjectData struct { + *models.Project +} + +type ResourceData struct { + Id string `json:"id"` +} + +func (f *ProjectData) Save(data string) ([]byte, error) { + return http_request.ProjectRequester.HTTPCreateProject([]byte(data)) +} + +func (f *ProjectData) Delete(id string) error { + return http_request.ProjectRequester.HTTPDeleteProject(id) +} + +type CampaignData struct { + Id string `json:"id,omitempty"` + ProjectId string `json:"project_id"` + Name string `json:"name"` + Description string `json:"description"` + Type string `json:"type,omitempty"` + VariationGroups []VariationGroupData `json:"variation_groups"` +} + +func (f *CampaignData) Save(data string) ([]byte, error) { + return http_request.CampaignFERequester.HTTPCreateCampaign(data) +} + +func (f *CampaignData) Delete(id string) error { + return http_request.CampaignFERequester.HTTPDeleteCampaign(id) +} + +type FlagData struct { + *models.Flag +} + +func (f *FlagData) Save(data string) ([]byte, error) { + return http_request.FlagRequester.HTTPCreateFlag(data) +} + +func (f *FlagData) Delete(id string) error { + return http_request.FlagRequester.HTTPDeleteFlag(id) +} + +type GoalData struct { + *models.Goal +} + +func (f *GoalData) Save(data string) ([]byte, error) { + return http_request.GoalRequester.HTTPCreateGoal(data) +} + +func (f *GoalData) Delete(id string) error { + return http_request.GoalRequester.HTTPDeleteGoal(id) +} + +type TargetingKeysData struct { + *models.TargetingKey +} + +func (f *TargetingKeysData) Save(data string) ([]byte, error) { + return http_request.TargetingKeyRequester.HTTPCreateTargetingKey(data) +} + +func (f *TargetingKeysData) Delete(id string) error { + return http_request.TargetingKeyRequester.HTTPDeleteTargetingKey(id) +} + +type VariationGroupData struct { + *models.VariationGroup +} + +type VariationData struct { + *models.VariationFE +} + +type ResourceType int + +const ( + Project ResourceType = iota + Flag + TargetingKey + Goal + Campaign + VariationGroup + Variation +) + +var resourceTypeMap = map[string]ResourceType{ + "project": Project, + "flag": Flag, + "targeting_key": TargetingKey, + "goal": Goal, + "campaign": Campaign, + "variation_group": VariationGroup, + "variation": Variation, +} + +type Resource struct { + Name ResourceType + Data Data + ResourceVariable string + Method string +} + +var cred common.RequestConfig + +func Init(credL common.RequestConfig) { + cred = credL +} + +type ResourceCmdStruct struct { + Name string `json:"name,omitempty"` + ResourceVariable string `json:"resource_variable,omitempty"` + Response string `json:"response,omitempty"` + Method string `json:"method,omitempty"` + Error string `json:"error,omitempty"` +} + +func UnmarshalConfig(filePath string) ([]Resource, error) { + var config struct { + Resources []struct { + Name string + Data json.RawMessage + ResourceVariable string + Method string + } + } + + bytes, err := os.ReadFile(resourceFile) + + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if err := json.Unmarshal(bytes, &config); err != nil { + return nil, err + } + + var resources []Resource + for _, r := range config.Resources { + name, ok := resourceTypeMap[r.Name] + if !ok { + return nil, fmt.Errorf("invalid resource name: %s", r.Name) + } + + var data Data = nil + var err error = nil + + switch name { + + case Project: + projectData := ProjectData{} + err = json.Unmarshal(r.Data, &projectData) + data = &projectData + + case Flag: + flagData := FlagData{} + err = json.Unmarshal(r.Data, &flagData) + data = &flagData + + case TargetingKey: + targetingKeyData := TargetingKeysData{} + err = json.Unmarshal(r.Data, &targetingKeyData) + data = &targetingKeyData + + case Campaign: + campaignData := CampaignData{} + err = json.Unmarshal(r.Data, &campaignData) + data = &campaignData + + case Goal: + goalData := GoalData{} + err = json.Unmarshal(r.Data, &goalData) + data = &goalData + } + + if err != nil { + return nil, err + } + + resources = append(resources, Resource{Name: name, Data: data, ResourceVariable: r.ResourceVariable, Method: r.Method}) + } + + return resources, nil +} + +var gResources []Resource + +// LoadCmd represents the load command +var loadCmd = &cobra.Command{ + Use: "load [--file=]", + Short: "Load your resources", + Long: `Load your resources`, + Run: func(cmd *cobra.Command, args []string) { + var params []byte + + if !utils.CheckSingleFlag(inputParams != "", inputParamsFile != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (input-params, input-params-file)") + } + + if inputParams != "" { + params = []byte(inputParams) + + } + + if inputParamsFile != "" { + fileContent, err := os.ReadFile(inputParamsFile) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + params = fileContent + } + + err := json.Unmarshal(params, &inputParamsMap) + if err != nil { + fmt.Fprintf(cmd.OutOrStderr(), "Error: %s", err) + return + } + + jsonBytes := ScriptResource(cmd, gResources, inputParamsMap) + if outputFile != "" { + os.WriteFile(outputFile, jsonBytes, os.ModePerm) + fmt.Fprintf(cmd.OutOrStdout(), "File created at %s\n", outputFile) + return + } + if viper.GetString("output_format") == "json" { + fmt.Fprintf(cmd.OutOrStdout(), "%s", string(jsonBytes)) + } + + }, +} + +func init() { + cobra.OnInitialize(initResource) + + loadCmd.Flags().StringVarP(&resourceFile, "file", "", "", "resource file that contains your resource") + + if err := loadCmd.MarkFlagRequired("file"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + loadCmd.Flags().StringVarP(&outputFile, "output-file", "", "", "result of the command that contains all resource informations") + + loadCmd.Flags().StringVarP(&inputParams, "input-params", "", "", "params to replace resource loader file") + loadCmd.Flags().StringVarP(&inputParamsFile, "input-params-file", "", "", "file that contains params to replace resource loader file") + + ResourceCmd.AddCommand(loadCmd) +} + +func initResource() { + + // Use config file from the flag. + var err error + if resourceFile != "" { + gResources, err = UnmarshalConfig(resourceFile) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + } +} + +func ScriptResource(cmd *cobra.Command, resources []Resource, inputParamsMap map[string]interface{}) []byte { + + resourceVariables := make(map[string]interface{}) + var loadResultJSON []string + var loadResultOutputFile []ResourceCmdStruct + + for _, resource := range resources { + var response []byte + var resultOutputFile ResourceCmdStruct + var resourceData map[string]interface{} + var responseData interface{} + var url = "" + var resourceName = "" + const color = "\033[0;33m" + const colorNone = "\033[0m" + + data, err := json.Marshal(resource.Data) + if err != nil { + fmt.Fprintf(os.Stderr, "error occurred marshal data: %v\n", err) + } + + var httpMethod string = "POST" + + if resource.Method == "delete" { + httpMethod = "DELETE" + } + + switch resource.Name { + case Project: + url = "/projects" + resourceName = "Project" + case Flag: + url = "/flags" + resourceName = "Flag" + case TargetingKey: + url = "/targeting_keys" + resourceName = "Targeting Key" + case Goal: + url = "/goals" + resourceName = "Goal" + case VariationGroup: + url = "/variation_groups" + resourceName = "Variation Group" + case Variation: + url = "/variations" + resourceName = "Variation" + case Campaign: + url = "/campaigns" + resourceName = "Campaign" + } + + err = json.Unmarshal(data, &resourceData) + + if err != nil { + fmt.Fprintf(os.Stderr, "error occurred unmarshall resourceData: %v\n", err) + } + + if inputParamsMap != nil { + for k, vInterface := range resourceData { + v, ok := vInterface.(string) + if ok { + if strings.Contains(v, "$") { + vTrim := strings.Trim(v, "$") + vTrimL := strings.Split(vTrim, ".") + value, err := getNestedValue(inputParamsMap, vTrimL) + if err != nil { + fmt.Fprintf(os.Stderr, "Error: %s\n", err) + } + + if value != nil { + resourceData[k] = value + } + } + } + } + } + + for k, vInterface := range resourceData { + v, ok := vInterface.(string) + if ok { + if strings.Contains(v, "$") { + vTrim := strings.Trim(v, "$") + for k_, variable := range resourceVariables { + script, _ := tengo.Eval(context.Background(), vTrim, map[string]interface{}{ + k_: variable, + }) + if script == nil { + continue + } + resourceData[k] = script.(string) + } + } + } + } + + dataResource, err := json.Marshal(resourceData) + if err != nil { + log.Fatalf("error occurred http call: %v\n", err) + } + + if httpMethod == "POST" { + if resource.Name == Project || resource.Name == TargetingKey || resource.Name == Flag { + response, err = common.HTTPRequest[ResourceData](httpMethod, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+cred.AccountID+url, dataResource) + } + + if resource.Name == Goal || resource.Name == Campaign { + response, err = common.HTTPRequest[ResourceData](httpMethod, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+cred.AccountID+"/account_environments/"+cred.AccountEnvironmentID+url, dataResource) + } + + resultOutputFile = ResourceCmdStruct{ + Name: resourceName, + Response: string(response), + ResourceVariable: resource.ResourceVariable, + Method: httpMethod, + } + + if err != nil { + resultOutputFile.Error = err.Error() + } + + loadResultOutputFile = append(loadResultOutputFile, resultOutputFile) + } + + if httpMethod == "DELETE" { + if resource.Name == Project || resource.Name == TargetingKey || resource.Name == Flag { + _, err = common.HTTPRequest[ResourceData](httpMethod, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+cred.AccountID+url+"/"+fmt.Sprintf("%s", resourceData["id"]), nil) + } + + if resource.Name == Goal || resource.Name == Campaign { + _, err = common.HTTPRequest[ResourceData](httpMethod, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+cred.AccountID+"/account_environments/"+cred.AccountEnvironmentID+url+"/"+fmt.Sprintf("%s", resourceData["id"]), nil) + } + + if err == nil && viper.GetString("output_format") != "json" { + response = []byte("The id: " + fmt.Sprintf("%v", resourceData["id"]) + " deleted successfully") + } + } + + if err != nil { + fmt.Fprintf(cmd.OutOrStdout(), "%s - %s: %s %s\n", color, resourceName, colorNone, err.Error()) + continue + } + + if viper.GetString("output_format") != "json" { + fmt.Fprintf(cmd.OutOrStdout(), "%s - %s: %s %s\n", color, resourceName, colorNone, string(response)) + } + + if httpMethod != "DELETE" { + err = json.Unmarshal(response, &responseData) + + if err != nil { + fmt.Fprintf(os.Stderr, "error occurred unmarshal responseData: %v\n", err) + } + + if responseData == nil { + fmt.Fprintf(os.Stderr, "error occurred not response data: %s\n", string(response)) + continue + } + + resourceVariables[resource.ResourceVariable] = responseData + } + + loadResultJSON = append(loadResultJSON, string(response)) + } + + var jsonBytes []byte + var jsonString any + + if outputFile != "" { + jsonString = loadResultOutputFile + } else { + jsonString = loadResultJSON + } + + jsonBytes, err := json.Marshal(jsonString) + + if err != nil { + log.Fatalf("Error marshaling struct: %v", err) + } + + return jsonBytes +} + +func getNestedValue(data map[string]interface{}, path []string) (interface{}, error) { + if len(path) == 0 { + return nil, fmt.Errorf("empty path") + } + + current := data + for i, key := range path { + value, ok := current[key] + if !ok { + continue + } + if i == len(path)-1 { + return value, nil + } + next, ok := value.(map[string]interface{}) + if !ok { + return nil, fmt.Errorf("value at key '%s' is not an object", key) + } + current = next + } + + return nil, nil +} diff --git a/cmd/resource/loadResource.json b/cmd/feature_experimentation/resource/loadResource.json similarity index 57% rename from cmd/resource/loadResource.json rename to cmd/feature_experimentation/resource/loadResource.json index a11ad46..80a1fef 100644 --- a/cmd/resource/loadResource.json +++ b/cmd/feature_experimentation/resource/loadResource.json @@ -60,8 +60,61 @@ ] } }, + { + "name": "campaign", + "resourceVariable": "c2", + "method": "create", + "data": { + "project_id": "$p1.id", + "name": "Resource loader Campaign to delete", + "description": "Loaded from resource loader", + "type": "ab", + "variation_groups": [ + { + "variations": [ + { + "name": "Original", + "reference": true, + "allocation": 50, + "modifications": { + "type": "FLAG", + "value": { + "color": "red" + } + } + }, + { + "name": "Variation 1", + "reference": false, + "allocation": 50, + "modifications": { + "type": "FLAG", + "value": { + "color": "blue" + } + } + } + ], + "targeting": { + "targeting_groups": [ + { + "targetings": [ + { + "operator": "EQUALS", + "key": "device", + "value": "firefox" + } + ] + } + ] + } + } + ] + } + }, { "name": "flag", + "method": "create", "resourceVariable": "f1", "data": { "name": "flag_created_with_resource_loader", @@ -72,6 +125,7 @@ }, { "name": "goal", + "method": "create", "resourceVariable": "g1", "data": { "type": "screenview", @@ -82,12 +136,21 @@ }, { "name": "targeting_key", + "method": "create", "resourceVariable": "t1", "data": { "type": "string", "name": "targeting_key_created_with_resource_loader", "description": "Loaded from resource loader" } + }, + { + "name": "campaign", + "resourceVariable": "c8", + "method": "delete", + "data": { + "id": "$c2.id" + } } ] } \ No newline at end of file diff --git a/cmd/resource/resource.go b/cmd/feature_experimentation/resource/resource.go similarity index 92% rename from cmd/resource/resource.go rename to cmd/feature_experimentation/resource/resource.go index 82566d5..6534ecb 100644 --- a/cmd/resource/resource.go +++ b/cmd/feature_experimentation/resource/resource.go @@ -9,10 +9,6 @@ import ( "github.com/spf13/cobra" ) -var ( - resourceFile string -) - // ResourceCmd represents the resource command var ResourceCmd = &cobra.Command{ Use: "resource [load]", diff --git a/cmd/targeting_key/create.go b/cmd/feature_experimentation/targeting_key/create.go similarity index 81% rename from cmd/targeting_key/create.go rename to cmd/feature_experimentation/targeting_key/create.go index f874b28..cfffd69 100644 --- a/cmd/targeting_key/create.go +++ b/cmd/feature_experimentation/targeting_key/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [-d | --data-raw ]", Short: "Create a targeting key", - Long: `Create a targeting key in your account`, + Long: `Create a targeting key`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPCreateTargetingKey(DataRaw) + body, err := httprequest.TargetingKeyRequester.HTTPCreateTargetingKey(DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/targeting_key/delete.go b/cmd/feature_experimentation/targeting_key/delete.go similarity index 80% rename from cmd/targeting_key/delete.go rename to cmd/feature_experimentation/targeting_key/delete.go index fd80589..bc07e15 100644 --- a/cmd/targeting_key/delete.go +++ b/cmd/feature_experimentation/targeting_key/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-i | --id=]", Short: "Delete a targeting key", - Long: `Delete a targeting key in your account`, + Long: `Delete a targeting key`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteTargetingKey(TargetingKeyID) + err := httprequest.TargetingKeyRequester.HTTPDeleteTargetingKey(TargetingKeyID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/targeting_key/edit.go b/cmd/feature_experimentation/targeting_key/edit.go similarity index 84% rename from cmd/targeting_key/edit.go rename to cmd/feature_experimentation/targeting_key/edit.go index da1359d..36d0bbc 100644 --- a/cmd/targeting_key/edit.go +++ b/cmd/feature_experimentation/targeting_key/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-i | --id=] [-d | --data-raw ]", Short: "Edit a targeting key", - Long: `Edit a targeting key in your account`, + Long: `Edit a targeting key`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditTargetingKey(TargetingKeyID, DataRaw) + body, err := httprequest.TargetingKeyRequester.HTTPEditTargetingKey(TargetingKeyID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/targeting_key/get.go b/cmd/feature_experimentation/targeting_key/get.go similarity index 82% rename from cmd/targeting_key/get.go rename to cmd/feature_experimentation/targeting_key/get.go index d403433..4ccfa8c 100644 --- a/cmd/targeting_key/get.go +++ b/cmd/feature_experimentation/targeting_key/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [-i | --id=]", Short: "Get a targeting key", - Long: `Get a targeting key in your account`, + Long: `Get a targeting key`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetTargetingKey(TargetingKeyID) + body, err := httprequest.TargetingKeyRequester.HTTPGetTargetingKey(TargetingKeyID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/targeting_key/list.go b/cmd/feature_experimentation/targeting_key/list.go similarity index 77% rename from cmd/targeting_key/list.go rename to cmd/feature_experimentation/targeting_key/list.go index 8aee9fc..34ae103 100644 --- a/cmd/targeting_key/list.go +++ b/cmd/feature_experimentation/targeting_key/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list", Short: "List all targeting keys", - Long: `List all targeting keys in your account`, + Long: `List all targeting keys`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListTargetingKey() + body, err := httprequest.TargetingKeyRequester.HTTPListTargetingKey() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/targeting_key/targeting_key.go b/cmd/feature_experimentation/targeting_key/targeting_key.go similarity index 88% rename from cmd/targeting_key/targeting_key.go rename to cmd/feature_experimentation/targeting_key/targeting_key.go index e685edc..f1b3dd4 100644 --- a/cmd/targeting_key/targeting_key.go +++ b/cmd/feature_experimentation/targeting_key/targeting_key.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package targetingkey @@ -16,7 +15,7 @@ var TargetingKeyCmd = &cobra.Command{ Use: "targeting-key [create|edit|get|list|delete]", Aliases: []string{"tk"}, Short: "Manage your targeting keys", - Long: `Manage your targeting keys in your account`, + Long: `Manage your targeting keys`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, diff --git a/cmd/targeting_key/targeting_key_test.go b/cmd/feature_experimentation/targeting_key/targeting_key_test.go similarity index 78% rename from cmd/targeting_key/targeting_key_test.go rename to cmd/feature_experimentation/targeting_key/targeting_key_test.go index 55b3226..6bb704b 100644 --- a/cmd/targeting_key/targeting_key_test.go +++ b/cmd/feature_experimentation/targeting_key/targeting_key_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APITargetingKey() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APITargetingKey() m.Run() } @@ -26,12 +30,12 @@ var testTargetingKeyList []models.TargetingKey func TestTargetingKeyCommand(t *testing.T) { output, _ := utils.ExecuteCommand(TargetingKeyCmd) - assert.Contains(t, output, "Manage your targeting keys in your account") + assert.Contains(t, output, "Manage your targeting keys") } func TestTargetingKeyHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(TargetingKeyCmd, "--help") - assert.Contains(t, output, "Manage your targeting keys in your account") + assert.Contains(t, output, "Manage your targeting keys") } func TestTargetingKeyGetCommand(t *testing.T) { @@ -45,7 +49,7 @@ func TestTargetingKeyGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestTargetingKey, testTargetingKey) + assert.Equal(t, mockfunction_fe.TestTargetingKey, testTargetingKey) } func TestTargetingKeyListCommand(t *testing.T) { @@ -56,7 +60,7 @@ func TestTargetingKeyListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestTargetingKeyList, testTargetingKeyList) + assert.Equal(t, mockfunction_fe.TestTargetingKeyList, testTargetingKeyList) } func TestTargetingKeyCreateCommand(t *testing.T) { @@ -70,7 +74,7 @@ func TestTargetingKeyCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestTargetingKey, testTargetingKey) + assert.Equal(t, mockfunction_fe.TestTargetingKey, testTargetingKey) } func TestTargetingKeyEditCommand(t *testing.T) { @@ -84,7 +88,7 @@ func TestTargetingKeyEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestTargetingKeyEdit, testTargetingKey) + assert.Equal(t, mockfunction_fe.TestTargetingKeyEdit, testTargetingKey) } func TestTargetingKeyDeleteCommand(t *testing.T) { diff --git a/cmd/token/info.go b/cmd/feature_experimentation/token/info.go similarity index 52% rename from cmd/token/info.go rename to cmd/feature_experimentation/token/info.go index 3031c07..f3af226 100644 --- a/cmd/token/info.go +++ b/cmd/feature_experimentation/token/info.go @@ -1,15 +1,13 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package token import ( - "fmt" "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -20,15 +18,12 @@ var infoCmd = &cobra.Command{ Short: "Get the information related to your token", Long: `Get the information related to your token`, Run: func(cmd *cobra.Command, args []string) { - if viper.GetString("token") != "" { - body, err := httprequest.HTTPCheckToken(viper.GetString("token")) - if err != nil { - log.Fatalf("error occurred: %v", err) - } - utils.FormatItem([]string{"ClientID", "AccountID", "ExpiresIn", "Scope"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) - } else { - fmt.Fprintln(cmd.OutOrStdout(), "Token required") + body, err := common.HTTPCheckTokenFE() + if err != nil { + log.Fatalf("error occurred: %v", err) } + utils.FormatItem([]string{"ClientID", "AccountID", "ExpiresIn", "Scope"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + }, } diff --git a/cmd/token/token.go b/cmd/feature_experimentation/token/token.go similarity index 100% rename from cmd/token/token.go rename to cmd/feature_experimentation/token/token.go diff --git a/cmd/feature_experimentation/token/token_test.go b/cmd/feature_experimentation/token/token_test.go new file mode 100644 index 0000000..15204a6 --- /dev/null +++ b/cmd/feature_experimentation/token/token_test.go @@ -0,0 +1,47 @@ +package token + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +var testToken models.Token + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIToken() + m.Run() +} + +func TestTokenCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(TokenCmd) + assert.Contains(t, output, "Manage your token\n") +} + +func TestTokenHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(TokenCmd, "--help") + assert.Contains(t, output, "Manage your token\n") +} + +func TestTokenInfoCommand(t *testing.T) { + successOutput, _ := utils.ExecuteCommand(TokenCmd, "info") + err := json.Unmarshal([]byte(successOutput), &testToken) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_fe.TestToken, testToken) + +} diff --git a/cmd/user/create.go b/cmd/feature_experimentation/user/create.go similarity index 81% rename from cmd/user/create.go rename to cmd/feature_experimentation/user/create.go index 8f14f0e..4416a4e 100644 --- a/cmd/user/create.go +++ b/cmd/feature_experimentation/user/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package user @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [-d | --data ]", Short: "Create a user with right", - Long: `Create a user with right in your account`, + Long: `Create a user with right`, Run: func(cmd *cobra.Command, args []string) { - _, err := httprequest.HTTPBatchUpdateUsers(DataRaw) + _, err := httprequest.UserRequester.HTTPBatchUpdateUsers(DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/user/delete.go b/cmd/feature_experimentation/user/delete.go similarity index 81% rename from cmd/user/delete.go rename to cmd/feature_experimentation/user/delete.go index 48408e1..533a421 100644 --- a/cmd/user/delete.go +++ b/cmd/feature_experimentation/user/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package user @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [-e | --email ]", Short: "Delete a user", - Long: `Delete a user in your account`, + Long: `Delete a user`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteUsers(UserEmail) + err := httprequest.UserRequester.HTTPDeleteUsers(UserEmail) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/user/edit.go b/cmd/feature_experimentation/user/edit.go similarity index 81% rename from cmd/user/edit.go rename to cmd/feature_experimentation/user/edit.go index ff4afc1..4aec696 100644 --- a/cmd/user/edit.go +++ b/cmd/feature_experimentation/user/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package user @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [-d | --data-raw=]", Short: "Edit a user with right", - Long: `Edit a user with right in your account`, + Long: `Edit a user with right`, Run: func(cmd *cobra.Command, args []string) { - _, err := httprequest.HTTPBatchUpdateUsers(DataRaw) + _, err := httprequest.UserRequester.HTTPBatchUpdateUsers(DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/user/list.go b/cmd/feature_experimentation/user/list.go similarity index 78% rename from cmd/user/list.go rename to cmd/feature_experimentation/user/list.go index 40626a9..2732972 100644 --- a/cmd/user/list.go +++ b/cmd/feature_experimentation/user/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package user @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list", Short: "List all users", - Long: `List all users in your account`, + Long: `List all users`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListUsers() + body, err := httprequest.UserRequester.HTTPListUsers() if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/user/user.go b/cmd/feature_experimentation/user/user.go similarity index 100% rename from cmd/user/user.go rename to cmd/feature_experimentation/user/user.go diff --git a/cmd/user/user_test.go b/cmd/feature_experimentation/user/user_test.go similarity index 84% rename from cmd/user/user_test.go rename to cmd/feature_experimentation/user/user_test.go index 29b6bf2..0639efc 100644 --- a/cmd/user/user_test.go +++ b/cmd/feature_experimentation/user/user_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,9 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIUser() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIUser() + m.Run() } @@ -40,7 +45,7 @@ func TestUserListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestUserList, testUserList) + assert.Equal(t, mockfunction_fe.TestUserList, testUserList) } func TestUserCreateCommand(t *testing.T) { diff --git a/cmd/variation/create.go b/cmd/feature_experimentation/variation/create.go similarity index 80% rename from cmd/variation/create.go rename to cmd/feature_experimentation/variation/create.go index a1c9bdd..29e5cfd 100644 --- a/cmd/variation/create.go +++ b/cmd/feature_experimentation/variation/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [--campaign-id=] [--variation-group-id=] [-d | --data-raw ]", Short: "Create a variation", - Long: `Create a variation in your variation group`, + Long: `Create a variation`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPCreateVariation(CampaignID, VariationGroupID, DataRaw) + body, err := httprequest.VariationFERequester.HTTPCreateVariation(CampaignID, VariationGroupID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation/delete.go b/cmd/feature_experimentation/variation/delete.go similarity index 73% rename from cmd/variation/delete.go rename to cmd/feature_experimentation/variation/delete.go index 1c7e0b5..1ea13e3 100644 --- a/cmd/variation/delete.go +++ b/cmd/feature_experimentation/variation/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [--campaign-id=] [--variation-group-id=] [-i | --id=]", Short: "Delete a variation", - Long: `Delete a variation in your variation group`, + Long: `Delete a variation`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteVariation(CampaignID, VariationGroupID, VariationID) + err := httprequest.VariationFERequester.HTTPDeleteVariation(CampaignID, VariationGroupID, VariationID) if err != nil { log.Fatalf("error occurred: %v", err) } @@ -31,7 +30,7 @@ func init() { deleteCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the variation you want to delete") if err := deleteCmd.MarkFlagRequired("id"); err != nil { - fmt.Println(err) + fmt.Fprintf(deleteCmd.OutOrStderr(), "error occurred: %s", err) } VariationCmd.AddCommand(deleteCmd) } diff --git a/cmd/variation/edit.go b/cmd/feature_experimentation/variation/edit.go similarity index 83% rename from cmd/variation/edit.go rename to cmd/feature_experimentation/variation/edit.go index ca5cb59..3105155 100644 --- a/cmd/variation/edit.go +++ b/cmd/feature_experimentation/variation/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [--campaign-id=] [--variation-group-id=] [-i | --id=] [-d | --data-raw=]", Short: "Edit a variation", - Long: `Edit a variation in your variation group`, + Long: `Edit a variation`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditVariation(CampaignID, VariationGroupID, VariationID, DataRaw) + body, err := httprequest.VariationFERequester.HTTPEditVariation(CampaignID, VariationGroupID, VariationID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation/get.go b/cmd/feature_experimentation/variation/get.go similarity index 81% rename from cmd/variation/get.go rename to cmd/feature_experimentation/variation/get.go index a29d2fa..431ec6c 100644 --- a/cmd/variation/get.go +++ b/cmd/feature_experimentation/variation/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [--campaign-id=] [--variation-group-id=] [-i | --id=]", Short: "Get a variation", - Long: `Get a variation in your variation group`, + Long: `Get a variation`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetVariation(CampaignID, VariationGroupID, VariationID) + body, err := httprequest.VariationFERequester.HTTPGetVariation(CampaignID, VariationGroupID, VariationID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation/list.go b/cmd/feature_experimentation/variation/list.go similarity index 77% rename from cmd/variation/list.go rename to cmd/feature_experimentation/variation/list.go index cdff25b..1a5e3c8 100644 --- a/cmd/variation/list.go +++ b/cmd/feature_experimentation/variation/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list [--campaign-id=] [--variation-group-id=]", Short: "List all variations", - Long: `List all variations in your variation group`, + Long: `List all variations`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListVariation(CampaignID, VariationGroupID) + body, err := httprequest.VariationFERequester.HTTPListVariation(CampaignID, VariationGroupID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation/variation.go b/cmd/feature_experimentation/variation/variation.go similarity index 94% rename from cmd/variation/variation.go rename to cmd/feature_experimentation/variation/variation.go index 6f46c26..8727e0f 100644 --- a/cmd/variation/variation.go +++ b/cmd/feature_experimentation/variation/variation.go @@ -22,7 +22,7 @@ var ( var VariationCmd = &cobra.Command{ Use: "variation [create|edit|get|list|delete]", Short: "Manage your variations", - Long: `Manage your variations in your variation group`, + Long: `Manage your variations`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, diff --git a/cmd/variation/variation_test.go b/cmd/feature_experimentation/variation/variation_test.go similarity index 81% rename from cmd/variation/variation_test.go rename to cmd/feature_experimentation/variation/variation_test.go index 35413c2..73b135c 100644 --- a/cmd/variation/variation_test.go +++ b/cmd/feature_experimentation/variation/variation_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,25 +19,26 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIVariation() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIVariation() m.Run() } -var testVariation models.Variation -var testVariationList []models.Variation +var testVariation models.VariationFE +var testVariationList []models.VariationFE func TestVariationCommand(t *testing.T) { output, _ := utils.ExecuteCommand(VariationCmd) assert.Contains(t, output, "Error: required flag(s) \"campaign-id\", \"variation-group-id\" not set") output1, _ := utils.ExecuteCommand(VariationCmd, "--campaign-id=campaignID", "--variation-group-id=variationGroupID") - assert.Contains(t, output1, "Manage your variations in your variation group") + assert.Contains(t, output1, "Manage your variations") } func TestVariationHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(VariationCmd, "--help") - assert.Contains(t, output, "Manage your variations in your variation group") + assert.Contains(t, output, "Manage your variations") } func TestVariationGetCommand(t *testing.T) { @@ -48,7 +52,7 @@ func TestVariationGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariation, testVariation) + assert.Equal(t, mockfunction_fe.TestVariation, testVariation) } func TestVariationListCommand(t *testing.T) { @@ -59,7 +63,7 @@ func TestVariationListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationList, testVariationList) + assert.Equal(t, mockfunction_fe.TestVariationList, testVariationList) } func TestVariationCreateCommand(t *testing.T) { @@ -73,7 +77,7 @@ func TestVariationCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariation, testVariation) + assert.Equal(t, mockfunction_fe.TestVariation, testVariation) } func TestVariationEditCommand(t *testing.T) { @@ -87,7 +91,7 @@ func TestVariationEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationEdit, testVariation) + assert.Equal(t, mockfunction_fe.TestVariationEdit, testVariation) } func TestVariationDeleteCommand(t *testing.T) { diff --git a/cmd/variation_group/create.go b/cmd/feature_experimentation/variation_group/create.go similarity index 80% rename from cmd/variation_group/create.go rename to cmd/feature_experimentation/variation_group/create.go index 4417e59..a30d67c 100644 --- a/cmd/variation_group/create.go +++ b/cmd/feature_experimentation/variation_group/create.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation_group @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var createCmd = &cobra.Command{ Use: "create [--campaign-id=] [-d | --data-raw ]", Short: "Create a variation group", - Long: `Create a variation group in your campaign`, + Long: `Create a variation group`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPCreateVariationGroup(CampaignID, DataRaw) + body, err := httprequest.VariationGroupRequester.HTTPCreateVariationGroup(CampaignID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation_group/delete.go b/cmd/feature_experimentation/variation_group/delete.go similarity index 73% rename from cmd/variation_group/delete.go rename to cmd/feature_experimentation/variation_group/delete.go index 47d6c5b..cc8d771 100644 --- a/cmd/variation_group/delete.go +++ b/cmd/feature_experimentation/variation_group/delete.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation_group @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var deleteCmd = &cobra.Command{ Use: "delete [--campaign-id=] [-i | --id ]", Short: "Delete a variation group", - Long: `Delete a variation group in your campaign`, + Long: `Delete a variation group`, Run: func(cmd *cobra.Command, args []string) { - err := httprequest.HTTPDeleteVariationGroup(CampaignID, VariationGroupID) + err := httprequest.VariationGroupRequester.HTTPDeleteVariationGroup(CampaignID, VariationGroupID) if err != nil { log.Fatalf("error occurred: %v", err) } @@ -31,7 +30,7 @@ func init() { deleteCmd.Flags().StringVarP(&VariationGroupID, "id", "i", "", "id of the variation group you want to delete") if err := deleteCmd.MarkFlagRequired("id"); err != nil { - fmt.Println(err) + fmt.Fprintf(deleteCmd.OutOrStderr(), "error occurred: %s", err) } VariationGroupCmd.AddCommand(deleteCmd) } diff --git a/cmd/variation_group/edit.go b/cmd/feature_experimentation/variation_group/edit.go similarity index 83% rename from cmd/variation_group/edit.go rename to cmd/feature_experimentation/variation_group/edit.go index 30496d7..940d092 100644 --- a/cmd/variation_group/edit.go +++ b/cmd/feature_experimentation/variation_group/edit.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation_group @@ -8,7 +7,7 @@ import ( "fmt" "log" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" ) @@ -16,9 +15,9 @@ import ( var editCmd = &cobra.Command{ Use: "edit [--campaign-id=] [-i | --id ] [-d | --data-raw ]", Short: "Edit a variation group", - Long: `Edit a variation group in your campaign`, + Long: `Edit a variation group`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPEditVariationGroup(CampaignID, VariationGroupID, DataRaw) + body, err := httprequest.VariationGroupRequester.HTTPEditVariationGroup(CampaignID, VariationGroupID, DataRaw) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation_group/get.go b/cmd/feature_experimentation/variation_group/get.go similarity index 81% rename from cmd/variation_group/get.go rename to cmd/feature_experimentation/variation_group/get.go index b65fdb4..76274c9 100644 --- a/cmd/variation_group/get.go +++ b/cmd/feature_experimentation/variation_group/get.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation_group @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var getCmd = &cobra.Command{ Use: "get [--campaign-id=] [-i | --id ]", Short: "Get a variation group", - Long: `Get a variation group in your campaign`, + Long: `Get a variation group`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPGetVariationGroup(CampaignID, VariationGroupID) + body, err := httprequest.VariationGroupRequester.HTTPGetVariationGroup(CampaignID, VariationGroupID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation_group/list.go b/cmd/feature_experimentation/variation_group/list.go similarity index 76% rename from cmd/variation_group/list.go rename to cmd/feature_experimentation/variation_group/list.go index 9341556..d211fd5 100644 --- a/cmd/variation_group/list.go +++ b/cmd/feature_experimentation/variation_group/list.go @@ -1,6 +1,5 @@ /* Copyright © 2022 Flagship Team flagship@abtasty.com - */ package variation_group @@ -8,7 +7,7 @@ import ( "log" "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + httprequest "github.com/flagship-io/flagship/utils/http_request" "github.com/spf13/cobra" "github.com/spf13/viper" ) @@ -17,9 +16,9 @@ import ( var listCmd = &cobra.Command{ Use: "list [--campaign-id=]", Short: "List all variation groups", - Long: `List all variation groups in your campaign`, + Long: `List all variation groups`, Run: func(cmd *cobra.Command, args []string) { - body, err := httprequest.HTTPListVariationGroup(CampaignID) + body, err := httprequest.VariationGroupRequester.HTTPListVariationGroup(CampaignID) if err != nil { log.Fatalf("error occurred: %v", err) } diff --git a/cmd/variation_group/variation_group.go b/cmd/feature_experimentation/variation_group/variation_group.go similarity index 93% rename from cmd/variation_group/variation_group.go rename to cmd/feature_experimentation/variation_group/variation_group.go index 0da0de2..b44ba50 100644 --- a/cmd/variation_group/variation_group.go +++ b/cmd/feature_experimentation/variation_group/variation_group.go @@ -22,7 +22,7 @@ var VariationGroupCmd = &cobra.Command{ Use: "variation-group [create|edit|get|list|delete]", Aliases: []string{"vg"}, Short: "Manage your variation groups", - Long: `Manage your variation groups in your campaign`, + Long: `Manage your variation groups`, Run: func(cmd *cobra.Command, args []string) { cmd.Help() }, diff --git a/cmd/variation_group/variation_group_test.go b/cmd/feature_experimentation/variation_group/variation_group_test.go similarity index 82% rename from cmd/variation_group/variation_group_test.go rename to cmd/feature_experimentation/variation_group/variation_group_test.go index 6bde561..1062743 100644 --- a/cmd/variation_group/variation_group_test.go +++ b/cmd/feature_experimentation/variation_group/variation_group_test.go @@ -4,9 +4,12 @@ import ( "encoding/json" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_fe "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -16,7 +19,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIVariationGroup() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_fe.APIVariationGroup() m.Run() } @@ -29,12 +33,12 @@ func TestVariationGroupCommand(t *testing.T) { assert.Contains(t, output, "Error: required flag(s) \"campaign-id\" not set") output1, _ := utils.ExecuteCommand(VariationGroupCmd, "--campaign-id=campaignID") - assert.Contains(t, output1, "Manage your variation groups in your campaign") + assert.Contains(t, output1, "Manage your variation groups") } func TestVariationGroupHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(VariationGroupCmd, "--help") - assert.Contains(t, output, "Manage your variation groups in your campaign") + assert.Contains(t, output, "Manage your variation groups") } func TestVariationGroupGetCommand(t *testing.T) { @@ -48,7 +52,7 @@ func TestVariationGroupGetCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationGroup, testVariationGroup) + assert.Equal(t, mockfunction_fe.TestVariationGroup, testVariationGroup) } func TestVariationGroupListCommand(t *testing.T) { @@ -59,7 +63,7 @@ func TestVariationGroupListCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationGroupList, testVariationGroupList) + assert.Equal(t, mockfunction_fe.TestVariationGroupList, testVariationGroupList) } func TestVariationGroupCreateCommand(t *testing.T) { @@ -73,7 +77,7 @@ func TestVariationGroupCreateCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationGroup, testVariationGroup) + assert.Equal(t, mockfunction_fe.TestVariationGroup, testVariationGroup) } func TestVariationGroupEditCommand(t *testing.T) { @@ -87,7 +91,7 @@ func TestVariationGroupEditCommand(t *testing.T) { assert.Nil(t, err) - assert.Equal(t, mockfunction.TestVariationGroupEdit, testVariationGroup) + assert.Equal(t, mockfunction_fe.TestVariationGroupEdit, testVariationGroup) } func TestVariationGroupDeleteCommand(t *testing.T) { diff --git a/cmd/info/info.go b/cmd/info/info.go deleted file mode 100644 index 83fc9bd..0000000 --- a/cmd/info/info.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com - -*/ -package info - -import ( - "fmt" - - "github.com/fatih/color" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -// InfoCmd represents the info command -var InfoCmd = &cobra.Command{ - Use: "info", - Short: "Show informations related to your Flagship CLI", - Long: `Show informations like account environment id, account id and client id your Flagship CLI runs on`, - Run: func(cmd *cobra.Command, args []string) { - - yellow := color.New(color.FgYellow).SprintFunc() - - fmt.Fprintf(cmd.OutOrStdout(), "%s: %s\n", yellow("Account ID"), viper.GetString("account_id")) - fmt.Fprintf(cmd.OutOrStdout(), "%s: %s\n", yellow("Account environment ID"), viper.GetString("account_environment_id")) - fmt.Fprintf(cmd.OutOrStdout(), "%s: %s\n", yellow("Client ID"), viper.GetString("client_id")) - fmt.Fprintf(cmd.OutOrStdout(), "%s: %d (in second)\n", yellow("Token expiration"), viper.GetInt("expiration")) - fmt.Fprintf(cmd.OutOrStdout(), "%s: %s\n", yellow("Token scope"), viper.GetString("scope")) - }, -} diff --git a/cmd/resource/load.go b/cmd/resource/load.go deleted file mode 100644 index 2428b7d..0000000 --- a/cmd/resource/load.go +++ /dev/null @@ -1,317 +0,0 @@ -/* -Copyright © 2022 Flagship Team flagship@abtasty.com - -*/ - -package resource - -import ( - "context" - "encoding/json" - "fmt" - "log" - "net/http" - "os" - "strings" - - "github.com/d5/tengo/v2" - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" - "github.com/spf13/cobra" - "github.com/spf13/viper" -) - -type Data interface { - Save(data string) ([]byte, error) -} - -type ProjectData struct { - *models.Project -} - -type ResourceData struct { - Id string `json:"id"` -} - -func (f *ProjectData) Save(data string) ([]byte, error) { - return httprequest.HTTPCreateProject([]byte(data)) -} - -type CampaignData struct { - Id string `json:"id,omitempty"` - ProjectId string `json:"project_id"` - Name string `json:"name"` - Description string `json:"description"` - Type string `json:"type"` - VariationGroups []VariationGroupData `json:"variation_groups"` -} - -func (f *CampaignData) Save(data string) ([]byte, error) { - return httprequest.HTTPCreateCampaign(data) -} - -type FlagData struct { - *models.Flag -} - -func (f *FlagData) Save(data string) ([]byte, error) { - return httprequest.HTTPCreateFlag(data) -} - -type GoalData struct { - *models.Goal -} - -func (f *GoalData) Save(data string) ([]byte, error) { - return httprequest.HTTPCreateGoal(data) -} - -type TargetingKeysData struct { - *models.TargetingKey -} - -func (f *TargetingKeysData) Save(data string) ([]byte, error) { - return httprequest.HTTPCreateTargetingKey(data) -} - -type VariationGroupData struct { - *models.VariationGroup -} - -type VariationData struct { - *models.Variation -} - -type ResourceType int - -const ( - Project ResourceType = iota - Flag - TargetingKey - Goal - Campaign - VariationGroup - Variation -) - -var resourceTypeMap = map[string]ResourceType{ - "project": Project, - "flag": Flag, - "targeting_key": TargetingKey, - "goal": Goal, - "campaign": Campaign, - "variation_group": VariationGroup, - "variation": Variation, -} - -type Resource struct { - Name ResourceType - Data Data - ResourceVariable string -} - -func UnmarshalConfig(filePath string) ([]Resource, error) { - var config struct { - Resources []struct { - Name string - Data json.RawMessage - ResourceVariable string - } - } - - bytes, err := os.ReadFile(resourceFile) - - if err != nil { - log.Fatalf("error occurred: %v", err) - } - - if err := json.Unmarshal(bytes, &config); err != nil { - return nil, err - } - - var resources []Resource - for _, r := range config.Resources { - name, ok := resourceTypeMap[r.Name] - if !ok { - return nil, fmt.Errorf("invalid resource name: %s", r.Name) - } - - var data Data = nil - var err error = nil - - switch name { - - case Project: - projectData := ProjectData{} - err = json.Unmarshal(r.Data, &projectData) - data = &projectData - - case Flag: - flagData := FlagData{} - err = json.Unmarshal(r.Data, &flagData) - data = &flagData - - case TargetingKey: - targetingKeyData := TargetingKeysData{} - err = json.Unmarshal(r.Data, &targetingKeyData) - data = &targetingKeyData - - case Campaign: - campaignData := CampaignData{} - err = json.Unmarshal(r.Data, &campaignData) - data = &campaignData - - case Goal: - goalData := GoalData{} - err = json.Unmarshal(r.Data, &goalData) - data = &goalData - } - - if err != nil { - return nil, err - } - - resources = append(resources, Resource{Name: name, Data: data, ResourceVariable: r.ResourceVariable}) - } - - return resources, nil -} - -var gResources []Resource - -// LoadCmd represents the load command -var loadCmd = &cobra.Command{ - Use: "load [--file=]", - Short: "Load your resources", - Long: `Load your resources`, - Run: func(cmd *cobra.Command, args []string) { - ScriptResource(gResources) - }, -} - -func init() { - cobra.OnInitialize(initResource) - - loadCmd.Flags().StringVarP(&resourceFile, "file", "", "", "resource file that contains your resource") - - if err := loadCmd.MarkFlagRequired("file"); err != nil { - log.Fatalf("error occurred: %v", err) - } - - ResourceCmd.AddCommand(loadCmd) -} - -func initResource() { - - // Use config file from the flag. - var err error - if resourceFile != "" { - gResources, err = UnmarshalConfig(resourceFile) - if err != nil { - log.Fatalf("error occurred: %v", err) - } - } -} - -func ScriptResource(resources []Resource) { - - resourceVariables := make(map[string]interface{}) - - for _, resource := range resources { - var response []byte - var resourceData map[string]interface{} - var responseData interface{} - var url = "" - var resourceName = "" - const color = "\033[0;33m" - const colorNone = "\033[0m" - - data, err := json.Marshal(resource.Data) - if err != nil { - fmt.Printf("error occurred marshal data: %v\n", err) - } - - switch resource.Name { - case Project: - url = "/projects" - resourceName = "Project" - case Flag: - url = "/flags" - resourceName = "Flag" - case TargetingKey: - url = "/targeting_keys" - resourceName = "Targeting Key" - case Goal: - url = "/goals" - resourceName = "Goal" - case VariationGroup: - url = "/variation_groups" - resourceName = "Variation Group" - case Variation: - url = "/variations" - resourceName = "Variation" - case Campaign: - url = "/campaigns" - resourceName = "Campaign" - } - - err = json.Unmarshal(data, &resourceData) - - if err != nil { - fmt.Printf("error occurred unmarshall resourceData: %v\n", err) - } - - for k, vInterface := range resourceData { - v, ok := vInterface.(string) - if ok { - if strings.Contains(v, "$") { - vTrim := strings.Trim(v, "$") - for k_, variable := range resourceVariables { - script, _ := tengo.Eval(context.Background(), vTrim, map[string]interface{}{ - k_: variable, - }) - if script == nil { - continue - } - resourceData[k] = script.(string) - } - } - - } - - } - - dataResource, err := json.Marshal(resourceData) - if err != nil { - log.Fatalf("error occurred http call: %v\n", err) - } - - if resource.Name == Project || resource.Name == TargetingKey || resource.Name == Flag { - response, err = httprequest.HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+url, dataResource) - } - - if resource.Name == Goal || resource.Name == Campaign { - response, err = httprequest.HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+url, dataResource) - } - - if err != nil { - log.Fatalf("error occurred http call: %v\n", err) - } - - fmt.Fprintf(os.Stdout, "%s - %s: %s %s\n", color, resourceName, colorNone, string(response)) - - err = json.Unmarshal(response, &responseData) - - if err != nil { - fmt.Printf("error occurred unmarshal responseData: %v\n", err) - } - - if responseData == nil { - fmt.Println("error occurred not response data: " + string(response)) - continue - } - - resourceVariables[resource.ResourceVariable] = responseData - } -} diff --git a/cmd/root.go b/cmd/root.go index 3aec8bf..810e631 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -6,33 +6,18 @@ package cmd import ( "os" - "github.com/flagship-io/flagship/cmd/analyze" - "github.com/flagship-io/flagship/cmd/campaign" - "github.com/flagship-io/flagship/cmd/configuration" - "github.com/flagship-io/flagship/cmd/flag" - "github.com/flagship-io/flagship/cmd/goal" - "github.com/flagship-io/flagship/cmd/info" - "github.com/flagship-io/flagship/cmd/panic" - "github.com/flagship-io/flagship/cmd/project" - "github.com/flagship-io/flagship/cmd/resource" - targetingkey "github.com/flagship-io/flagship/cmd/targeting_key" - "github.com/flagship-io/flagship/cmd/token" - "github.com/flagship-io/flagship/cmd/user" - "github.com/flagship-io/flagship/cmd/variation" - "github.com/flagship-io/flagship/cmd/variation_group" + "github.com/flagship-io/flagship/cmd/feature_experimentation" + "github.com/flagship-io/flagship/cmd/web_experimentation" + "github.com/flagship-io/flagship/cmd/version" "github.com/flagship-io/flagship/utils/config" - httprequest "github.com/flagship-io/flagship/utils/httpRequest" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/spf13/cobra" "github.com/spf13/viper" ) -var ( - cfgFile string - cmdToken string - outputFormat string -) +var outputFormat string // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ @@ -59,54 +44,26 @@ func Execute() { } func addSubCommandPalettes() { - rootCmd.AddCommand(campaign.CampaignCmd) - rootCmd.AddCommand(project.ProjectCmd) - rootCmd.AddCommand(configuration.ConfigurationCmd) - rootCmd.AddCommand(panic.PanicCmd) - rootCmd.AddCommand(user.UserCmd) - rootCmd.AddCommand(variation_group.VariationGroupCmd) - rootCmd.AddCommand(variation.VariationCmd) - rootCmd.AddCommand(flag.FlagCmd) - rootCmd.AddCommand(goal.GoalCmd) - rootCmd.AddCommand(targetingkey.TargetingKeyCmd) rootCmd.AddCommand(version.VersionCmd) - rootCmd.AddCommand(token.TokenCmd) - rootCmd.AddCommand(analyze.AnalyzeCmd) - rootCmd.AddCommand(resource.ResourceCmd) - rootCmd.AddCommand(info.InfoCmd) + rootCmd.AddCommand(feature_experimentation.FeatureExperimentationCmd) + rootCmd.AddCommand(web_experimentation.WebExperimentationCmd) } + func init() { cobra.OnInitialize(initConfig) - rootCmd.PersistentFlags().StringVarP(&cmdToken, "token", "t", "", "access token to manage flagship resources") rootCmd.PersistentFlags().StringVarP(&outputFormat, "output-format", "f", config.OutputFormat, "output format for the get and list subcommands for flagship resources. Only 3 format are possible: table, json, json-pretty") - rootCmd.PersistentFlags().StringVarP(&httprequest.UserAgent, "user-agent", "u", config.DefaultUserAgent, "custom user agent") + rootCmd.PersistentFlags().StringVarP(&common.UserAgent, "user-agent", "", config.DefaultUserAgent, "custom user agent") - viper.BindPFlag("token", rootCmd.PersistentFlags().Lookup("token")) viper.BindPFlag("output_format", rootCmd.PersistentFlags().Lookup("output-format")) - rootCmd.PersistentFlags().StringVarP(&cfgFile, "config", "c", "", "config file that contains your credentials (default is $HOME/.flagship/credentials.yaml)") - addSubCommandPalettes() } // initConfig reads in config file and ENV variables if set. func initConfig() { - if cfgFile != "" { - // Use config file from the flag. - viper.SetConfigFile(cfgFile) - viper.MergeInConfig() - return - } // Find home directory. - homeDir, err := os.UserHomeDir() + _, err := config.CheckABTastyHomeDirectory() cobra.CheckErr(err) - // Search config in home directory with name ".flagship" (without extension). - viper.SetConfigFile(homeDir + "/.flagship/configurations/.cli.yaml") - viper.MergeInConfig() - if viper.GetString("current_used_configuration") != "" { - config.ReadConfiguration(viper.GetString("current_used_configuration")) - } - } diff --git a/cmd/web_experimentation/account/account.go b/cmd/web_experimentation/account/account.go new file mode 100644 index 0000000..4b8de07 --- /dev/null +++ b/cmd/web_experimentation/account/account.go @@ -0,0 +1,21 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import "github.com/spf13/cobra" + +var ( + Username string + AccountID string +) + +// AccountCmd represents the account command +var AccountCmd = &cobra.Command{ + Use: "account [use|list|current]", + Short: "Manage your CLI authentication", + Long: `Manage your CLI authentication`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/web_experimentation/account/account_test.go b/cmd/web_experimentation/account/account_test.go new file mode 100644 index 0000000..b14b066 --- /dev/null +++ b/cmd/web_experimentation/account/account_test.go @@ -0,0 +1,73 @@ +package account + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + models_we "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APIAccount() + + m.Run() +} + +var testAccount models.AccountJSON +var testAccounts []models_we.AccountWE + +func TestAccountCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountCmd) + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account [use|list|current]") +} + +func TestAccountHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountCmd, "--help") + assert.Contains(t, output, "Manage your CLI authentication\n\nUsage:\n account [use|list|current]") +} + +func TestAccountUseCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AccountCmd, "use") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(AccountCmd, "use", "-i=account_id") + assert.Equal(t, "Account ID set to : account_id\n", successOutput) +} + +func TestAccountCurrentCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AccountCmd, "current") + + err := json.Unmarshal([]byte(output), &testAccount) + + assert.Nil(t, err) + + assert.Equal(t, web_experimentation.TestAccount.AccountID, testAccount.AccountID) +} + +func TestAccountListCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AccountCmd, "list") + + err := json.Unmarshal([]byte(output), &testAccounts) + + assert.Nil(t, err) + + assert.Equal(t, web_experimentation.TestAccountGlobalCode.Id, testAccounts[0].Id) +} diff --git a/cmd/web_experimentation/account/current.go b/cmd/web_experimentation/account/current.go new file mode 100644 index 0000000..9d0c192 --- /dev/null +++ b/cmd/web_experimentation/account/current.go @@ -0,0 +1,54 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// getCmd represents the list command +var currentCmd = &cobra.Command{ + Use: "current", + Short: "current an auth credential", + Long: `current an auth credential`, + Run: func(cmd *cobra.Command, args []string) { + + var accountYaml models.AccountYaml + var account models.AccountJSON + + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + account.CurrentUsedCredential = accountYaml.CurrentUsedCredential + account.AccountID = accountYaml.AccountID + + utils.FormatItem([]string{"CurrentUsedCredential", "AccountID"}, account, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + AccountCmd.AddCommand(currentCmd) +} diff --git a/cmd/web_experimentation/account/list.go b/cmd/web_experimentation/account/list.go new file mode 100644 index 0000000..5aef9a8 --- /dev/null +++ b/cmd/web_experimentation/account/list.go @@ -0,0 +1,33 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "list all auth", + Long: `list all auth`, + Run: func(cmd *cobra.Command, args []string) { + + body, err := httprequest.AccountWERequester.HTTPListAccount() + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Name", "Identifier", "Role"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + + AccountCmd.AddCommand(listCmd) +} diff --git a/cmd/web_experimentation/account/use.go b/cmd/web_experimentation/account/use.go new file mode 100644 index 0000000..8a2af14 --- /dev/null +++ b/cmd/web_experimentation/account/use.go @@ -0,0 +1,43 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account + +import ( + "fmt" + "log" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" +) + +// getCmd represents the list command +var useCmd = &cobra.Command{ + Use: "use", + Short: "get an auth credential", + Long: `list an auth credential`, + Run: func(cmd *cobra.Command, args []string) { + if AccountID == "" { + fmt.Fprintln(cmd.OutOrStdout(), "required flag account-id") + return + } + + err := config.SetAccountID(utils.WEB_EXPERIMENTATION, AccountID) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Account ID set to : "+AccountID) + + }, +} + +func init() { + useCmd.Flags().StringVarP(&AccountID, "id", "i", "", "account id of the credentials you want to manage") + + if err := useCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + AccountCmd.AddCommand(useCmd) +} diff --git a/cmd/web_experimentation/account_global_code/account_global_code.go b/cmd/web_experimentation/account_global_code/account_global_code.go new file mode 100644 index 0000000..666df0e --- /dev/null +++ b/cmd/web_experimentation/account_global_code/account_global_code.go @@ -0,0 +1,59 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account_global_code + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var WorkingDir string +var AccountID string + +// AccountGlobalCodeCmd represents the account global code command +var AccountGlobalCodeCmd = &cobra.Command{ + Use: "account-global-code [get|push]", + Short: "Get account global code", + Aliases: []string{"agc"}, + Long: `Get account global code`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + cobra.OnInitialize(initConfig) + cobra.OnInitialize(initGlobalCodeDir) + AccountGlobalCodeCmd.PersistentFlags().StringVarP(&WorkingDir, "working-dir", "", utils.DefaultGlobalCodeWorkingDir(), "Directory where the file will be generated and pushed from") + +} + +func initConfig() { + v := viper.New() + + homeDir, _ := os.UserHomeDir() + + v.BindPFlag("working_dir", AccountGlobalCodeCmd.PersistentFlags().Lookup("working-dir")) + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + + err := v.WriteConfig() + if err != nil { + log.Fatalf("error occurred: %s", err) + } + viper.MergeConfigMap(v.AllSettings()) +} + +func initGlobalCodeDir() { + _, err := config.CheckWorkingDirectory(viper.GetString("working_dir")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } +} diff --git a/cmd/web_experimentation/account_global_code/account_global_code_test.go b/cmd/web_experimentation/account_global_code/account_global_code_test.go new file mode 100644 index 0000000..7635c5b --- /dev/null +++ b/cmd/web_experimentation/account_global_code/account_global_code_test.go @@ -0,0 +1,58 @@ +package account_global_code + +import ( + "encoding/json" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APIAccount() + + m.Run() +} + +func TestAccountGlobalCodeCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountGlobalCodeCmd) + assert.Contains(t, output, "Get account global code") +} + +func TestAccountGlobalCodeHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(AccountGlobalCodeCmd, "--help") + assert.Contains(t, output, "Get account global code") +} + +func TestAccountGlobalCodeGetCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(AccountGlobalCodeCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(AccountGlobalCodeCmd, "get", "-i=account_id") + assert.Equal(t, "console.log(\"test\")\n", successOutput) +} + +func TestAccountGlobalCodePushCommand(t *testing.T) { + var testAccount models.AccountWE + + failOutput, _ := utils.ExecuteCommand(AccountGlobalCodeCmd, "push") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(AccountGlobalCodeCmd, "push", "-i=account_id", "--code=console.log(\"test\")") + err := json.Unmarshal([]byte(successOutput), &testAccount) + + assert.Nil(t, err) + assert.Equal(t, mockfunction_we.TestAccountGlobalCode, testAccount) +} diff --git a/cmd/web_experimentation/account_global_code/get.go b/cmd/web_experimentation/account_global_code/get.go new file mode 100644 index 0000000..6cd5017 --- /dev/null +++ b/cmd/web_experimentation/account_global_code/get.go @@ -0,0 +1,53 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account_global_code + +import ( + "fmt" + "log" + + "github.com/flagship-io/flagship/utils/config" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var createFile bool +var override bool + +// getCmd represents get command +var getCmd = &cobra.Command{ + Use: "get [-i | --id ]", + Short: "Get account global code", + Long: `Get account global code`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.AccountGlobalCodeRequester.HTTPGetAccountGlobalCode(AccountID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if createFile { + accountCodeDir, err := config.AccountGlobalCodeDirectory(viper.GetString("working_dir"), AccountID, body, override) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + fmt.Fprintln(cmd.OutOrStdout(), "Account code file generated successfully: ", accountCodeDir) + return + } + + fmt.Fprintln(cmd.OutOrStdout(), body) + }, +} + +func init() { + getCmd.Flags().StringVarP(&AccountID, "id", "i", "", "id of the global code account you want to display") + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getCmd.Flags().BoolVarP(&createFile, "create-file", "", false, "create a file that contains account global code") + getCmd.Flags().BoolVarP(&override, "override", "", false, "override existing account global code file") + + AccountGlobalCodeCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/account_global_code/push.go b/cmd/web_experimentation/account_global_code/push.go new file mode 100644 index 0000000..ac0ad9d --- /dev/null +++ b/cmd/web_experimentation/account_global_code/push.go @@ -0,0 +1,63 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package account_global_code + +import ( + "fmt" + "log" + "os" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +var code string +var filePath string + +// pushCmd represents push command +var pushCmd = &cobra.Command{ + Use: "push [-i | --id ]", + Short: "Push account global code", + Long: `push account global code`, + Run: func(cmd *cobra.Command, args []string) { + var codeByte []byte + + if !utils.CheckSingleFlag(filePath != "", code != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (file, code)") + } + + if filePath != "" { + fileContent, err := os.ReadFile(filePath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + codeByte = fileContent + } + + if code != "" { + codeByte = []byte(code) + } + + body, err := httprequest.AccountGlobalCodeRequester.HTTPPushAccountGlobalCode(AccountID, codeByte) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + }, +} + +func init() { + pushCmd.Flags().StringVarP(&AccountID, "id", "i", "", "id of the global code account") + if err := pushCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushCmd.Flags().StringVarP(&code, "code", "c", "", "new code to push in the account") + pushCmd.Flags().StringVarP(&filePath, "file", "", "", "file that contains new code to push in the account") + + AccountGlobalCodeCmd.AddCommand(pushCmd) +} diff --git a/cmd/web_experimentation/auth/auth.go b/cmd/web_experimentation/auth/auth.go new file mode 100644 index 0000000..cb5f9bd --- /dev/null +++ b/cmd/web_experimentation/auth/auth.go @@ -0,0 +1,23 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import "github.com/spf13/cobra" + +var ( + ClientID string + ClientSecret string + Username string +) + +// AuthCmd represents the auth command +var AuthCmd = &cobra.Command{ + Use: "authentication [login|get|list|delete]", + Aliases: []string{"auth"}, + Short: "Manage your CLI authentication for web experimentation", + Long: `Manage your CLI authentication for web experimentation`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/web_experimentation/auth/auth_test.go b/cmd/web_experimentation/auth/auth_test.go new file mode 100644 index 0000000..d3abe2c --- /dev/null +++ b/cmd/web_experimentation/auth/auth_test.go @@ -0,0 +1,95 @@ +package auth + +import ( + "encoding/json" + "testing" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APIToken() + + m.Run() +} + +var testAuth models.Auth +var testAuthList []models.Auth + +func TestAuthCommand(t *testing.T) { + output, err := utils.ExecuteCommand(AuthCmd) + + assert.Nil(t, err) + assert.Contains(t, output, "Manage your CLI authentication for web experimentation\n\nUsage:\n authentication [login|get|list|delete]") +} + +func TestAuthHelpCommand(t *testing.T) { + output, err := utils.ExecuteCommand(AuthCmd, "--help") + + assert.Nil(t, err) + assert.Contains(t, output, "Manage your CLI authentication for web experimentation\n\nUsage:\n authentication [login|get|list|delete]") +} + +func TestAuthLoginCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AuthCmd, "login", "-u=test_auth", "--client-id=CI", "--client-secret=CS") + + assert.Equal(t, "Error while login, required fields (username, client ID, client secret, account id)\n", failOutput) + + successOutput, err := utils.ExecuteCommand(AuthCmd, "login", "-u=test_auth", "--client-id=CI", "--client-secret=CS", "--account-id=AI") + + assert.Nil(t, err) + assert.Equal(t, "Credential created successfully\n", successOutput) +} + +func TestAuthListCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(AuthCmd, "list") + + err := json.Unmarshal([]byte(output), &testAuthList) + + assert.Nil(t, err) + + byt, err := json.Marshal(web_experimentation.TestAuth) + + assert.Nil(t, err) + + assert.Contains(t, output, string(byt)) +} + +func TestAuthGetCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AuthCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"username\" not set") + + successOutput, _ := utils.ExecuteCommand(AuthCmd, "get", "--username=test_auth") + err := json.Unmarshal([]byte(successOutput), &testAuth) + + assert.Nil(t, err) + + assert.Equal(t, web_experimentation.TestAuth, testAuth) +} + +func TestAuthDeleteCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(AuthCmd, "delete") + assert.Contains(t, failOutput, "Error: required flag(s) \"username\" not set") + + output, _ := utils.ExecuteCommand(AuthCmd, "delete", "--username=test_auth") + + assert.Contains(t, output, "Credential deleted successfully") +} diff --git a/cmd/web_experimentation/auth/current.go b/cmd/web_experimentation/auth/current.go new file mode 100644 index 0000000..2856ca7 --- /dev/null +++ b/cmd/web_experimentation/auth/current.go @@ -0,0 +1,52 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// currentCmd represents the current command +var currentCmd = &cobra.Command{ + Use: "current", + Short: "Get current running auth credential for web experimentation", + Long: `Get current running auth credential for web experimentation`, + Run: func(cmd *cobra.Command, args []string) { + var accountYaml models.AccountYaml + var account models.AccountJSON + + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + account.CurrentUsedCredential = accountYaml.CurrentUsedCredential + + utils.FormatItem([]string{"CurrentUsedCredential"}, account, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + AuthCmd.AddCommand(currentCmd) +} diff --git a/cmd/web_experimentation/auth/delete.go b/cmd/web_experimentation/auth/delete.go new file mode 100644 index 0000000..9f5390d --- /dev/null +++ b/cmd/web_experimentation/auth/delete.go @@ -0,0 +1,48 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "fmt" + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" +) + +// deleteCmd represents delete command +var deleteCmd = &cobra.Command{ + Use: "delete [-u | --username=]", + Short: "Delete an auth", + Long: `Delete an auth`, + Run: func(cmd *cobra.Command, args []string) { + + _, err := config.CheckABTastyHomeDirectory() + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if err := os.Remove(credPath); err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential deleted successfully") + }, +} + +func init() { + deleteCmd.Flags().StringVarP(&Username, "username", "u", "", "username of the credentials you want to delete") + + if err := deleteCmd.MarkFlagRequired("username"); err != nil { + log.Fatalf("error occurred: %v", err) + } + AuthCmd.AddCommand(deleteCmd) +} diff --git a/cmd/web_experimentation/auth/get.go b/cmd/web_experimentation/auth/get.go new file mode 100644 index 0000000..72f0e40 --- /dev/null +++ b/cmd/web_experimentation/auth/get.go @@ -0,0 +1,62 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// getCmd represents the list command +var getCmd = &cobra.Command{ + Use: "get", + Short: "get an auth credential for web experimentation", + Long: `get an auth credential for web experimentation`, + Run: func(cmd *cobra.Command, args []string) { + + var authYaml models.AuthYaml + var auth models.Auth + + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &authYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + auth.Username = authYaml.Username + auth.ClientID = authYaml.ClientID + auth.ClientSecret = authYaml.ClientSecret + auth.Token = authYaml.Token + + utils.FormatItem([]string{"Username", "Token"}, auth, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + getCmd.Flags().StringVarP(&Username, "username", "u", "", "username of the credentials you want to display") + + if err := getCmd.MarkFlagRequired("username"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + AuthCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/auth/list.go b/cmd/web_experimentation/auth/list.go new file mode 100644 index 0000000..dde2fa7 --- /dev/null +++ b/cmd/web_experimentation/auth/list.go @@ -0,0 +1,69 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "list all auth", + Long: `list all auth`, + Run: func(cmd *cobra.Command, args []string) { + + var auths []models.Auth + existingAuths, err := config.GetUsernames(utils.WEB_EXPERIMENTATION) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + for _, fileName := range existingAuths { + if fileName != "" { + var authYaml models.AuthYaml + var auth models.Auth + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, fileName) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + yamlFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(yamlFile, &authYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + if authYaml.Username != "" { + auth.Username = authYaml.Username + auth.ClientID = authYaml.ClientID + auth.ClientSecret = authYaml.ClientSecret + auth.Token = authYaml.Token + auth.RefreshToken = authYaml.RefreshToken + auths = append(auths, auth) + } + } + } + + utils.FormatItem([]string{"Username", "Token"}, auths, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + + AuthCmd.AddCommand(listCmd) +} diff --git a/cmd/web_experimentation/auth/login.go b/cmd/web_experimentation/auth/login.go new file mode 100644 index 0000000..10e2c34 --- /dev/null +++ b/cmd/web_experimentation/auth/login.go @@ -0,0 +1,141 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package auth + +import ( + "fmt" + "log" + "slices" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/spf13/cobra" +) + +var ( + credentialsFile string + accountId string +) + +// createCmd represents the create command +var loginCmd = &cobra.Command{ + Use: "login [--credential-file] | [-u | --username=] [-i | --client-id=] [-s | --client-secret=] [-a | --account-id=]", + Short: "login", + Long: `login`, + Run: func(cmd *cobra.Command, args []string) { + if !utils.CheckSingleFlag(credentialsFile != "", Username != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (browser, username)") + } + + if credentialsFile != "" { + v, err := config.ReadCredentialsFromFile(credentialsFile) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if v.GetString("username") == "" || v.GetString("client_id") == "" || v.GetString("client_secret") == "" || v.GetString("account_id") == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (username, client ID, client secret, account id)") + return + } + + authenticationResponse, err := common.HTTPCreateTokenWE(v.GetString("client_id"), v.GetString("client_secret"), v.GetString("account_id")) + if err != nil { + fmt.Fprintf(cmd.OutOrStderr(), "error occurred: %s", err) + return + } + + err = config.CreateAuthFile(utils.WEB_EXPERIMENTATION, v.GetString("username"), v.GetString("client_id"), v.GetString("client_secret"), authenticationResponse) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SelectAuth(utils.WEB_EXPERIMENTATION, v.GetString("username")) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.WEB_EXPERIMENTATION, v.GetString("account_id")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential created successfully") + return + } + + if Username != "" { + existingCredentials, err := config.GetUsernames(utils.WEB_EXPERIMENTATION) + if err != nil { + fmt.Fprintf(cmd.OutOrStderr(), "error occurred: %s", err) + return + } + + if slices.Contains(existingCredentials, Username) { + if accountId != "" { + err := config.SelectAuth(utils.WEB_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.WEB_EXPERIMENTATION, accountId) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential changed successfully to "+Username) + return + } + + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (account id)") + return + } + + if ClientID == "" || ClientSecret == "" || accountId == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, required fields (username, client ID, client secret, account id)") + return + } + + authenticationResponse, err := common.HTTPCreateTokenWE(ClientID, ClientSecret, accountId) + if err != nil { + fmt.Fprintln(cmd.OutOrStderr(), err) + return + } + + if authenticationResponse.AccessToken == "" { + fmt.Fprintln(cmd.OutOrStderr(), "Error while login, client_id or client_secret not valid") + return + } + + err = config.CreateAuthFile(utils.WEB_EXPERIMENTATION, Username, ClientID, ClientSecret, authenticationResponse) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SelectAuth(utils.WEB_EXPERIMENTATION, Username) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + err = config.SetAccountID(utils.WEB_EXPERIMENTATION, accountId) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Credential created successfully") + } + }, +} + +func init() { + + loginCmd.Flags().StringVarP(&Username, "username", "u", "", "username") + + loginCmd.Flags().StringVarP(&ClientID, "client-id", "i", "", "client ID of an auth") + loginCmd.Flags().StringVarP(&ClientSecret, "client-secret", "s", "", "client secret of an auth") + loginCmd.Flags().StringVarP(&accountId, "account-id", "a", "", "account id of an auth") + loginCmd.Flags().StringVarP(&credentialsFile, "credential-file", "p", "", "config file to create") + + AuthCmd.AddCommand(loginCmd) +} diff --git a/cmd/web_experimentation/campaign/campaign.go b/cmd/web_experimentation/campaign/campaign.go new file mode 100644 index 0000000..d88ea02 --- /dev/null +++ b/cmd/web_experimentation/campaign/campaign.go @@ -0,0 +1,24 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign + +import ( + "github.com/spf13/cobra" +) + +var ( + CampaignID string + Status string + DataRaw string +) + +// campaignCmd represents the campaign command +var CampaignCmd = &cobra.Command{ + Use: "campaign [get|list|delete|switch]", + Short: "Manage your campaigns", + Long: `Manage your campaigns`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/web_experimentation/campaign/campaign_test.go b/cmd/web_experimentation/campaign/campaign_test.go new file mode 100644 index 0000000..c70d6fb --- /dev/null +++ b/cmd/web_experimentation/campaign/campaign_test.go @@ -0,0 +1,74 @@ +package campaign + +import ( + "encoding/json" + "strconv" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_we.APICampaign() + + m.Run() +} + +var testCampaign models.CampaignWE +var testCampaignList []models.CampaignWE + +func TestCampaignCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(CampaignCmd) + assert.Contains(t, output, "Manage your campaigns") +} + +func TestCampaignHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(CampaignCmd, "--help") + assert.Contains(t, output, "Manage your campaigns") +} + +func TestCampaignGetCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(CampaignCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(CampaignCmd, "get", "--id="+strconv.Itoa(100000)) + + err := json.Unmarshal([]byte(successOutput), &testCampaign) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestCampaign, testCampaign) +} + +func TestCampaignListCommand(t *testing.T) { + + output, _ := utils.ExecuteCommand(CampaignCmd, "list") + + err := json.Unmarshal([]byte(output), &testCampaignList) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestCampaignList, testCampaignList) +} + +func TestCampaignDeleteCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(CampaignCmd, "delete") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(CampaignCmd, "delete", "--id=100000") + assert.Equal(t, "Campaign deleted\n", successOutput) +} diff --git a/cmd/web_experimentation/campaign/delete.go b/cmd/web_experimentation/campaign/delete.go new file mode 100644 index 0000000..52ce855 --- /dev/null +++ b/cmd/web_experimentation/campaign/delete.go @@ -0,0 +1,36 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign + +import ( + "fmt" + "log" + + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +// deleteCmd represents delete command +var deleteCmd = &cobra.Command{ + Use: "delete [-i | --id=]", + Short: "Delete a campaign", + Long: `Delete a campaign`, + Run: func(cmd *cobra.Command, args []string) { + err := httprequest.CampaignWERequester.HTTPDeleteCampaign(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Campaign deleted") + }, +} + +func init() { + deleteCmd.Flags().StringVarP(&CampaignID, "id", "i", "", "id of the campaign you want to delete") + + if err := deleteCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + CampaignCmd.AddCommand(deleteCmd) +} diff --git a/cmd/web_experimentation/campaign/get.go b/cmd/web_experimentation/campaign/get.go new file mode 100644 index 0000000..4a3df36 --- /dev/null +++ b/cmd/web_experimentation/campaign/get.go @@ -0,0 +1,37 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// getCmd represents get command +var getCmd = &cobra.Command{ + Use: "get [-i | --id ]", + Short: "Get a campaign", + Long: `Get a campaign`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.CampaignWERequester.HTTPGetCampaign(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Name", "Description", "Type", "State", "Url"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + getCmd.Flags().StringVarP(&CampaignID, "id", "i", "", "id of the campaign you want to display") + + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + CampaignCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/campaign/list.go b/cmd/web_experimentation/campaign/list.go new file mode 100644 index 0000000..8e458dc --- /dev/null +++ b/cmd/web_experimentation/campaign/list.go @@ -0,0 +1,31 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list", + Short: "List all campaigns", + Long: `List all campaigns`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.CampaignWERequester.HTTPListCampaign() + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Name", "Description", "Type", "State", "Url"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + CampaignCmd.AddCommand(listCmd) +} diff --git a/cmd/web_experimentation/campaign_global_code/campaign_global_code.go b/cmd/web_experimentation/campaign_global_code/campaign_global_code.go new file mode 100644 index 0000000..2aa1d34 --- /dev/null +++ b/cmd/web_experimentation/campaign_global_code/campaign_global_code.go @@ -0,0 +1,58 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign_global_code + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var WorkingDir string +var CampaignID string + +// CampaignGlobalCodeCmd represents the campaign global code command +var CampaignGlobalCodeCmd = &cobra.Command{ + Use: "campaign-global-code [get|push]", + Short: "Get campaign global code", + Aliases: []string{"cgc"}, + Long: `Get campaign global code`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + cobra.OnInitialize(initConfig) + cobra.OnInitialize(initGlobalCodeDir) + CampaignGlobalCodeCmd.PersistentFlags().StringVarP(&WorkingDir, "working-dir", "", utils.DefaultGlobalCodeWorkingDir(), "Directory where the file will be generated and pushed from") +} + +func initConfig() { + v := viper.New() + + homeDir, _ := os.UserHomeDir() + + v.BindPFlag("working_dir", CampaignGlobalCodeCmd.PersistentFlags().Lookup("working-dir")) + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + + err := v.WriteConfig() + if err != nil { + log.Fatalf("error occurred: %s", err) + } + viper.MergeConfigMap(v.AllSettings()) +} + +func initGlobalCodeDir() { + _, err := config.CheckWorkingDirectory(viper.GetString("working_dir")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } +} diff --git a/cmd/web_experimentation/campaign_global_code/campaign_global_code_test.go b/cmd/web_experimentation/campaign_global_code/campaign_global_code_test.go new file mode 100644 index 0000000..cdc957f --- /dev/null +++ b/cmd/web_experimentation/campaign_global_code/campaign_global_code_test.go @@ -0,0 +1,58 @@ +package campaign_global_code + +import ( + "encoding/json" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APICampaign() + + m.Run() +} + +func TestCampaignGlobalCodeCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd) + assert.Contains(t, output, "Get campaign global code") +} + +func TestCampaignGlobalCodeHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd, "--help") + assert.Contains(t, output, "Get campaign global code") +} + +func TestCampaignGlobalCodeGetCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd, "get", "-i=100000") + assert.Equal(t, "console.log(\"Hello World!\")\n", successOutput) +} + +func TestCampaignGlobalCodePushCommand(t *testing.T) { + var testCampaign models.CampaignWE + + failOutput, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd, "push") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(CampaignGlobalCodeCmd, "push", "-i=100000", "--code=console.log(\"Hello Earth!\")") + err := json.Unmarshal([]byte(successOutput), &testCampaign) + + assert.Nil(t, err) + assert.Equal(t, mockfunction_we.TestCampaign, testCampaign) +} diff --git a/cmd/web_experimentation/campaign_global_code/get.go b/cmd/web_experimentation/campaign_global_code/get.go new file mode 100644 index 0000000..9106db8 --- /dev/null +++ b/cmd/web_experimentation/campaign_global_code/get.go @@ -0,0 +1,98 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign_global_code + +import ( + "fmt" + "log" + "strconv" + + "github.com/flagship-io/flagship/utils/config" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var createFile bool +var createSubFiles bool +var override bool + +// getCmd represents get command +var getCmd = &cobra.Command{ + Use: "get [-i | --id ]", + Short: "Get campaign global code", + Long: `Get campaign global code`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.CampaignGlobalCodeRequester.HTTPGetCampaignGlobalCode(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if createFile { + campaignCodeDir, err := config.CampaignGlobalCodeDirectory(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, body, override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + fmt.Fprintln(cmd.OutOrStdout(), "Campaign code file generated successfully: ", campaignCodeDir) + return + } + + if createSubFiles { + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + _, err = config.CampaignGlobalCodeDirectory(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, body, override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.Type == "customScriptNew" && modification.Selector == "" { + _, err := config.VariationGlobalCodeDirectoryJS(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, strconv.Itoa(modification.VariationID), modification.Value, override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + continue + } + + if modification.Type == "addCSS" && modification.Selector == "" { + _, err := config.VariationGlobalCodeDirectoryCSS(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, strconv.Itoa(modification.VariationID), modification.Value, override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + continue + } + + fileCode := config.AddHeaderSelectorComment(modification.Selector, modification.Value) + config.ModificationCodeDirectory(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, strconv.Itoa(modification.VariationID), strconv.Itoa(modification.Id), modification.Selector, fileCode, override) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Sub files code generated successfully: "+viper.GetString("working_dir")+"/abtasty") + return + } + + fmt.Fprintln(cmd.OutOrStdout(), body) + }, +} + +func init() { + getCmd.Flags().StringVarP(&CampaignID, "id", "i", "", "id of the global code campaign you want to display") + + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + getCmd.Flags().BoolVarP(&createFile, "create-file", "", false, "create a file that contains campaign global code") + getCmd.Flags().BoolVarP(&createSubFiles, "create-subfiles", "", false, "create a file that contains campaign and variations global code") + + getCmd.Flags().BoolVarP(&override, "override", "", false, "override existing campaign global code file") + + CampaignGlobalCodeCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/campaign_global_code/push.go b/cmd/web_experimentation/campaign_global_code/push.go new file mode 100644 index 0000000..637cebb --- /dev/null +++ b/cmd/web_experimentation/campaign_global_code/push.go @@ -0,0 +1,63 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package campaign_global_code + +import ( + "fmt" + "log" + "os" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +var code string +var filePath string + +// pushCmd represents push command +var pushCmd = &cobra.Command{ + Use: "push [-i | --id ]", + Short: "push campaign global code", + Long: `push campaign global code`, + Run: func(cmd *cobra.Command, args []string) { + var codeByte []byte + + if !utils.CheckSingleFlag(filePath != "", code != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (file, code)") + } + + if filePath != "" { + fileContent, err := os.ReadFile(filePath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + codeByte = fileContent + } + + if code != "" { + codeByte = []byte(code) + } + + body, err := httprequest.CampaignGlobalCodeRequester.HTTPPushCampaignGlobalCode(CampaignID, codeByte) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + }, +} + +func init() { + pushCmd.Flags().StringVarP(&CampaignID, "id", "i", "", "id of the global code campaign") + if err := pushCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushCmd.Flags().StringVarP(&code, "code", "c", "", "new code to push in the campaign") + pushCmd.Flags().StringVarP(&filePath, "file", "", "", "file that contains new code to push in the campaign") + + CampaignGlobalCodeCmd.AddCommand(pushCmd) +} diff --git a/cmd/web_experimentation/modification/delete.go b/cmd/web_experimentation/modification/delete.go new file mode 100644 index 0000000..44bd1d0 --- /dev/null +++ b/cmd/web_experimentation/modification/delete.go @@ -0,0 +1,37 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification + +import ( + "fmt" + "log" + + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +// deleteCmd represents delete command +var deleteCmd = &cobra.Command{ + Use: "delete [-i | --id=] [--campaign-id ]", + Short: "Delete a modification", + Long: `Delete a modification`, + Run: func(cmd *cobra.Command, args []string) { + err := httprequest.ModificationRequester.HTTPDeleteModification(CampaignID, ModificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + fmt.Fprintln(cmd.OutOrStdout(), "Modification deleted") + + }, +} + +func init() { + deleteCmd.Flags().IntVarP(&ModificationID, "id", "i", 0, "id of the modification you want to delete") + + if err := deleteCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + ModificationCmd.AddCommand(deleteCmd) +} diff --git a/cmd/web_experimentation/modification/get.go b/cmd/web_experimentation/modification/get.go new file mode 100644 index 0000000..2f43dd5 --- /dev/null +++ b/cmd/web_experimentation/modification/get.go @@ -0,0 +1,37 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// getCmd represents get command +var getCmd = &cobra.Command{ + Use: "get [-i | --id ] [--campaign-id ]", + Short: "Get a modification", + Long: `Get a modification`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.ModificationRequester.HTTPGetModification(CampaignID, ModificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Name", "Type", "VariationID", "Selector", "Engine", "Value"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + getCmd.Flags().IntVarP(&ModificationID, "id", "i", 0, "id of the modification you want to display") + + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + ModificationCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/modification/list.go b/cmd/web_experimentation/modification/list.go new file mode 100644 index 0000000..f6e4e78 --- /dev/null +++ b/cmd/web_experimentation/modification/list.go @@ -0,0 +1,31 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// listCmd represents the list command +var listCmd = &cobra.Command{ + Use: "list [--campaign-id ]", + Short: "List all modifications", + Long: `List all modifications of a campaign`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.ModificationRequester.HTTPListModification(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + utils.FormatItem([]string{"Id", "Name", "Type", "VariationID", "Selector", "Engine", "Value"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + ModificationCmd.AddCommand(listCmd) +} diff --git a/cmd/web_experimentation/modification/modification.go b/cmd/web_experimentation/modification/modification.go new file mode 100644 index 0000000..c824cb7 --- /dev/null +++ b/cmd/web_experimentation/modification/modification.go @@ -0,0 +1,35 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification + +import ( + "log" + + "github.com/spf13/cobra" +) + +var ( + CampaignID int + ModificationID int + Status string + DataRaw string +) + +// modificationCmd represents the modification command +var ModificationCmd = &cobra.Command{ + Use: "modification [get|list|delete]", + Short: "Manage your modifications", + Long: `Manage your modifications`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + ModificationCmd.PersistentFlags().IntVarP(&CampaignID, "campaign-id", "", 0, "id of the campaign where you want to manage your modifications") + + if err := ModificationCmd.MarkPersistentFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } +} diff --git a/cmd/web_experimentation/modification/modification_test.go b/cmd/web_experimentation/modification/modification_test.go new file mode 100644 index 0000000..8fb7a37 --- /dev/null +++ b/cmd/web_experimentation/modification/modification_test.go @@ -0,0 +1,75 @@ +package modification + +import ( + "encoding/json" + "strconv" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_we.APIModification() + + m.Run() +} + +var testModification []models.Modification +var testModificationList []models.Modification + +func TestModificationCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(ModificationCmd) + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\" not set") + + successOutput, _ := utils.ExecuteCommand(ModificationCmd, "--campaign-id="+strconv.Itoa(100000)) + assert.Contains(t, successOutput, "Manage your modifications") +} + +func TestModificationHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(ModificationCmd, "--help") + assert.Contains(t, output, "Manage your modifications") +} + +func TestModificationGetCommand(t *testing.T) { + + failOutput, err := utils.ExecuteCommand(ModificationCmd, "get", "--campaign-id="+strconv.Itoa(100000)) + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(ModificationCmd, "get", "--id="+strconv.Itoa(120003), "--campaign-id="+strconv.Itoa(100000)) + + err = json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + + assert.Equal(t, []models.Modification{mockfunction_we.TestElementModification}, testModification) +} + +func TestModificationListCommand(t *testing.T) { + + output, err := utils.ExecuteCommand(ModificationCmd, "list", "--campaign-id="+strconv.Itoa(100000)) + err = json.Unmarshal([]byte(output), &testModificationList) + + assert.Nil(t, err) + assert.Equal(t, []models.Modification{mockfunction_we.TestModificationsJS, mockfunction_we.TestModificationsCSS}, testModificationList) +} + +func TestModificationDeleteCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(ModificationCmd, "delete") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(ModificationCmd, "delete", "--campaign-id=100000", "--id=120003") + assert.Equal(t, "Modification deleted\n", successOutput) +} diff --git a/cmd/web_experimentation/modification_code/get.go b/cmd/web_experimentation/modification_code/get.go new file mode 100644 index 0000000..d48e2df --- /dev/null +++ b/cmd/web_experimentation/modification_code/get.go @@ -0,0 +1,84 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification_code + +import ( + "fmt" + "log" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils/config" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var override bool + +// getCmd represents get command +var getCmd = &cobra.Command{ + Use: "get [-i | --id ] [--campaign-id ]", + Short: "Get modification code", + Long: `Get modification code`, + Run: func(cmd *cobra.Command, args []string) { + var modif *web_experimentation.Modification + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + modificationID, err := strconv.Atoi(ModificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPGetModification(campaignID, modificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.Type == "customScriptNew" && modification.Selector != "" { + modif = &modification + } + } + + if modif == nil { + log.Fatalf("error occurred: no modification found") + } + + if CreateFile { + fileCode := config.AddHeaderSelectorComment(modif.Selector, modif.Value) + modificationCodeDir, err := config.ModificationCodeDirectory(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, strconv.Itoa(modif.VariationID), ModificationID, modif.Selector, fileCode, override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "modification code file generated successfully: ", modificationCodeDir) + return + } + + fmt.Fprintln(cmd.OutOrStdout(), string(modif.Value)) + }, +} + +func init() { + getCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the campaign") + + if err := getCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getCmd.Flags().StringVarP(&ModificationID, "id", "i", "", "id of the modification code you want to display") + + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getCmd.Flags().BoolVarP(&CreateFile, "create-file", "", false, "create a file that contains modification global code") + getCmd.Flags().BoolVarP(&override, "override", "", false, "override existing modification code file") + + ModificationCodeCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/modification_code/modification_code.go b/cmd/web_experimentation/modification_code/modification_code.go new file mode 100644 index 0000000..acd3c53 --- /dev/null +++ b/cmd/web_experimentation/modification_code/modification_code.go @@ -0,0 +1,60 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification_code + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var WorkingDir string +var CampaignID string +var ModificationID string +var CreateFile bool + +// ModificationCodeCmd represents the variation global code command +var ModificationCodeCmd = &cobra.Command{ + Use: "modification-code [get|push]", + Short: "Get modification code", + Aliases: []string{"mc"}, + Long: `Get modification code`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + cobra.OnInitialize(initConfig) + cobra.OnInitialize(initGlobalCodeDir) + ModificationCodeCmd.PersistentFlags().StringVarP(&WorkingDir, "working-dir", "", utils.DefaultGlobalCodeWorkingDir(), "Directory where the file will be generated and pushed from") +} + +func initConfig() { + v := viper.New() + + homeDir, _ := os.UserHomeDir() + + v.BindPFlag("working_dir", ModificationCodeCmd.PersistentFlags().Lookup("working-dir")) + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + + err := v.WriteConfig() + if err != nil { + log.Fatalf("error occurred: %s", err) + } + viper.MergeConfigMap(v.AllSettings()) +} + +func initGlobalCodeDir() { + _, err := config.CheckWorkingDirectory(viper.GetString("working_dir")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } +} diff --git a/cmd/web_experimentation/modification_code/modification_code_test.go b/cmd/web_experimentation/modification_code/modification_code_test.go new file mode 100644 index 0000000..fada57e --- /dev/null +++ b/cmd/web_experimentation/modification_code/modification_code_test.go @@ -0,0 +1,62 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ + +package modification_code + +import ( + "encoding/json" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APIModification() + + m.Run() +} + +func TestModificationCodeCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(ModificationCodeCmd) + assert.Contains(t, output, "Get modification code") +} + +func TestModificationCodeHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(ModificationCodeCmd, "--help") + assert.Contains(t, output, "Get modification code") +} + +func TestModificationCodeGetCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(ModificationCodeCmd, "get") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\n") + + successOutput, _ := utils.ExecuteCommand(ModificationCodeCmd, "get", "-i=120003", "--campaign-id=100000") + assert.Equal(t, "console.log(\"test modification\")\n", successOutput) +} + +func TestModificationCodePushCommand(t *testing.T) { + var testModification models.Modification + + failOutput, _ := utils.ExecuteCommand(ModificationCodeCmd, "push") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\" not set") + + successOutput, _ := utils.ExecuteCommand(ModificationCodeCmd, "push", "-i=120003", "--campaign-id=100000", "--code=console.log(\"test modification\")") + err := json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + assert.Equal(t, mockfunction_we.TestElementModification, testModification) +} diff --git a/cmd/web_experimentation/modification_code/push.go b/cmd/web_experimentation/modification_code/push.go new file mode 100644 index 0000000..09f04c6 --- /dev/null +++ b/cmd/web_experimentation/modification_code/push.go @@ -0,0 +1,135 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package modification_code + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +var code string +var filePath string +var selector string +var variationID string + +// pushCmd represents get command +var pushCmd = &cobra.Command{ + Use: "push [-i | --id ] [--campaign-id ]", + Short: "push modification code", + Long: `push modification code`, + Run: func(cmd *cobra.Command, args []string) { + var codeByte []byte + + if !utils.CheckSingleFlag(filePath != "", code != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (file, code)") + } + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if filePath != "" { + fileContent, err := os.ReadFile(filePath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + codeByte = fileContent + } + + if code != "" { + codeByte = []byte(code) + } + + if ModificationID == "" { + if variationID == "" && selector == "" { + log.Fatalf("error occurred: Flag variation-id and selector are required.") + } + + variationID_, err := strconv.Atoi(variationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + modificationToPush := web_experimentation.ModificationCodeCreateStruct{ + InputType: "modification", + Name: "", + Value: string(codeByte), + Selector: selector, + Type: "customScriptNew", + Engine: "", + VariationID: variationID_, + } + + body, err := httprequest.ModificationRequester.HTTPCreateModification(campaignID, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + return + } + + modificationID, err := strconv.Atoi(ModificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + modificationList, err := httprequest.ModificationRequester.HTTPGetModification(campaignID, modificationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + if len(modificationList) == 0 { + log.Fatalf("error occurred: Modification not found.") + } + + modification := modificationList[0] + + selector_ := modification.Selector + if selector != "" { + selector_ = selector + } + + modificationToPush := web_experimentation.ModificationCodeEditStruct{ + InputType: "modification", + Name: modification.Name, + Value: string(codeByte), + Selector: selector_, + Type: modification.Type, + Engine: modification.Engine, + } + + body, err := httprequest.ModificationRequester.HTTPEditModification(campaignID, modification.Id, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + }, +} + +func init() { + pushCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the campaign") + + if err := pushCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushCmd.Flags().StringVarP(&ModificationID, "id", "i", "", "id of the modification code") + pushCmd.Flags().StringVarP(&variationID, "variation-id", "", "", "id of the variation") + pushCmd.Flags().StringVarP(&code, "code", "c", "", "new code to push in the modification") + pushCmd.Flags().StringVarP(&selector, "selector", "", "", "new selector to push in the modification") + pushCmd.Flags().StringVarP(&filePath, "file", "", "", "file that contains new code to push in the modification") + + ModificationCodeCmd.AddCommand(pushCmd) +} diff --git a/cmd/web_experimentation/token/info.go b/cmd/web_experimentation/token/info.go new file mode 100644 index 0000000..3bb3d67 --- /dev/null +++ b/cmd/web_experimentation/token/info.go @@ -0,0 +1,72 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package token + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" + "gopkg.in/yaml.v2" +) + +// infoCmd represents the info command +var infoCmd = &cobra.Command{ + Use: "info", + Short: "Get the information related to your token", + Long: `Get the information related to your token`, + Run: func(cmd *cobra.Command, args []string) { + var accountYaml models.AccountYaml + var credYaml models.AuthYaml + + // Home account + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, utils.HOME_CLI) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + homeFile, err := os.ReadFile(credPath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + err = yaml.Unmarshal(homeFile, &accountYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Current Cred + credPathCurr, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, accountYaml.CurrentUsedCredential) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + currentCredFile, err := os.ReadFile(credPathCurr) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + // Unmarshal the YAML data into the struct + err = yaml.Unmarshal(currentCredFile, &credYaml) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + body := models.Token{ + ClientID: credYaml.ClientID, + AccountID: accountYaml.AccountID, + Scope: credYaml.Scope, + } + utils.FormatItem([]string{"ClientID", "AccountID", "Scope"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + TokenCmd.AddCommand(infoCmd) +} diff --git a/cmd/web_experimentation/token/token.go b/cmd/web_experimentation/token/token.go new file mode 100644 index 0000000..32ba720 --- /dev/null +++ b/cmd/web_experimentation/token/token.go @@ -0,0 +1,20 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com + +*/ + +package token + +import ( + "github.com/spf13/cobra" +) + +// TokenCmd represents the token command +var TokenCmd = &cobra.Command{ + Use: "token [info]", + Short: "Manage your token", + Long: `Manage your token`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} diff --git a/cmd/token/token_test.go b/cmd/web_experimentation/token/token_test.go similarity index 71% rename from cmd/token/token_test.go rename to cmd/web_experimentation/token/token_test.go index 4268d3e..63dadfd 100644 --- a/cmd/token/token_test.go +++ b/cmd/web_experimentation/token/token_test.go @@ -1,12 +1,14 @@ package token import ( - "encoding/json" "testing" "github.com/flagship-io/flagship/models" "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" "github.com/stretchr/testify/assert" ) @@ -18,7 +20,8 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() - mockfunction.APIToken() + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_we.APIToken() m.Run() } @@ -31,13 +34,3 @@ func TestTokenHelpCommand(t *testing.T) { output, _ := utils.ExecuteCommand(TokenCmd, "--help") assert.Contains(t, output, "Manage your token\n") } - -func TestTokenInfoCommand(t *testing.T) { - output, _ := utils.ExecuteCommand(TokenCmd, "info") - - err := json.Unmarshal([]byte(output), &testToken) - - assert.Nil(t, err) - - assert.Equal(t, mockfunction.TestToken, testToken) -} diff --git a/cmd/web_experimentation/variation/delete.go b/cmd/web_experimentation/variation/delete.go new file mode 100644 index 0000000..8d60ede --- /dev/null +++ b/cmd/web_experimentation/variation/delete.go @@ -0,0 +1,37 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation + +import ( + "fmt" + "log" + + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +// deleteCmd represents delete command +var deleteCmd = &cobra.Command{ + Use: "delete [-i | --id=] [--campaign-id ]", + Short: "Delete a variation", + Long: `Delete a variation`, + Run: func(cmd *cobra.Command, args []string) { + err := httprequest.VariationWERequester.HTTPDeleteVariation(CampaignID, VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + fmt.Fprintln(cmd.OutOrStdout(), "Variation deleted") + + }, +} + +func init() { + deleteCmd.Flags().IntVarP(&VariationID, "id", "i", 0, "id of the variation you want to delete") + + if err := deleteCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + VariationCmd.AddCommand(deleteCmd) +} diff --git a/cmd/web_experimentation/variation/get.go b/cmd/web_experimentation/variation/get.go new file mode 100644 index 0000000..876f4c4 --- /dev/null +++ b/cmd/web_experimentation/variation/get.go @@ -0,0 +1,38 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation + +import ( + "log" + + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// getCmd represents the get command +var getCmd = &cobra.Command{ + Use: "get [--test-id=] [-i= | --id=]", + Short: "Get a variation", + Long: `Get a variation`, + Run: func(cmd *cobra.Command, args []string) { + body, err := httprequest.VariationWERequester.HTTPGetVariation(CampaignID, VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + utils.FormatItem([]string{"Id", "Name", "Description", "Type", "Traffic"}, body, viper.GetString("output_format"), cmd.OutOrStdout()) + + }, +} + +func init() { + getCmd.Flags().IntVarP(&VariationID, "id", "i", 0, "id of the variation you want to display") + + if err := getCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + VariationCmd.AddCommand(getCmd) +} diff --git a/cmd/web_experimentation/variation/variation.go b/cmd/web_experimentation/variation/variation.go new file mode 100644 index 0000000..e55735c --- /dev/null +++ b/cmd/web_experimentation/variation/variation.go @@ -0,0 +1,35 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com + +*/ + +package variation + +import ( + "log" + + "github.com/spf13/cobra" +) + +var ( + CampaignID int + VariationID int +) + +// VariationCmd represents the variation command +var VariationCmd = &cobra.Command{ + Use: "variation [get|delete]", + Short: "Manage your variation", + Long: `Manage your variation`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + VariationCmd.PersistentFlags().IntVarP(&CampaignID, "campaign-id", "", 0, "id of the campaign where you want to manage your variation") + + if err := VariationCmd.MarkPersistentFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } +} diff --git a/cmd/web_experimentation/variation/variation_test.go b/cmd/web_experimentation/variation/variation_test.go new file mode 100644 index 0000000..359a5bb --- /dev/null +++ b/cmd/web_experimentation/variation/variation_test.go @@ -0,0 +1,61 @@ +package variation + +import ( + "encoding/json" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + mockfunction.SetMock(&http_request.ResourceRequester) + mockfunction_we.APIVariation() + + m.Run() +} + +var testVariation models.VariationWE + +func TestVariationCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(VariationCmd) + assert.Contains(t, output, "Error: required flag(s) \"campaign-id\" not set") + + output1, _ := utils.ExecuteCommand(VariationCmd, "--campaign-id=100000") + assert.Contains(t, output1, "Manage your variation") + +} + +func TestVariationHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(VariationCmd, "--help") + assert.Contains(t, output, "Manage your variation") +} + +func TestVariationGetCommand(t *testing.T) { + + successOutput, _ := utils.ExecuteCommand(VariationCmd, "get", "-i=110000", "--campaign-id=100000") + + err := json.Unmarshal([]byte(successOutput), &testVariation) + + assert.Nil(t, err) + assert.Equal(t, mockfunction_we.TestVariation, testVariation) +} + +func TestVariationDeleteCommand(t *testing.T) { + + failOutput, _ := utils.ExecuteCommand(VariationCmd, "delete") + assert.Contains(t, failOutput, "Error: required flag(s) \"id\" not set") + + successOutput, _ := utils.ExecuteCommand(VariationCmd, "delete", "--campaign-id=100000", "--id=110000") + assert.Equal(t, "Variation deleted\n", successOutput) +} diff --git a/cmd/web_experimentation/variation_global_code/get-css.go b/cmd/web_experimentation/variation_global_code/get-css.go new file mode 100644 index 0000000..837765c --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/get-css.go @@ -0,0 +1,76 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "fmt" + "log" + "strconv" + + "github.com/flagship-io/flagship/utils/config" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// getCSSCmd represents get command +var getCSSCmd = &cobra.Command{ + Use: "get-css [-i | --id ] [--campaign-id ]", + Short: "Get variation global css code", + Long: `Get variation global css code`, + Run: func(cmd *cobra.Command, args []string) { + var cssCode string + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.VariationID == variationID && modification.Type == "addCSS" && modification.Selector == "" { + cssCode = modification.Value + } + } + + if CreateFile { + campaignCodeDir, err := config.VariationGlobalCodeDirectoryCSS(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, VariationID, cssCode, Override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), "Variation code file generated successfully: ", campaignCodeDir) + return + } + + fmt.Fprintln(cmd.OutOrStdout(), cssCode) + }, +} + +func init() { + getCSSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + + if err := getCSSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getCSSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + + if err := getCSSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getCSSCmd.Flags().BoolVarP(&CreateFile, "create-file", "", false, "create a file that contains variation global code") + getCSSCmd.Flags().BoolVarP(&Override, "override", "", false, "override existing variation global code file") + + VariationGlobalCodeCmd.AddCommand(getCSSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/get-js.go b/cmd/web_experimentation/variation_global_code/get-js.go new file mode 100644 index 0000000..e6f711a --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/get-js.go @@ -0,0 +1,76 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "fmt" + "log" + "strconv" + + "github.com/flagship-io/flagship/utils/config" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// getJsCmd represents get command +var getJSCmd = &cobra.Command{ + Use: "get-js [-i | --id ] [--campaign-id ]", + Short: "Get variation global js code", + Long: `Get variation global js code`, + Run: func(cmd *cobra.Command, args []string) { + var jsCode string + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.VariationID == variationID && modification.Type == "customScriptNew" && modification.Selector == "" { + jsCode = modification.Value + } + } + + if CreateFile { + variationCodeDir, err := config.VariationGlobalCodeDirectoryJS(viper.GetString("working_dir"), httprequest.CampaignGlobalCodeRequester.AccountID, CampaignID, VariationID, jsCode, Override) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + fmt.Fprintln(cmd.OutOrStdout(), "Variation code file generated successfully: ", variationCodeDir) + return + } + + fmt.Fprintln(cmd.OutOrStdout(), jsCode) + }, +} + +func init() { + getJSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + + if err := getJSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getJSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + + if err := getJSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + getJSCmd.Flags().BoolVarP(&CreateFile, "create-file", "", false, "create a file that contains variation global code") + getJSCmd.Flags().BoolVarP(&Override, "override", "", false, "override existing variation global code file") + + VariationGlobalCodeCmd.AddCommand(getJSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/info-css.go b/cmd/web_experimentation/variation_global_code/info-css.go new file mode 100644 index 0000000..8105fc1 --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/info-css.go @@ -0,0 +1,64 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "log" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// infoCSSCmd represents info-css command +var infoCSSCmd = &cobra.Command{ + Use: "info-css [-i | --id ] [--campaign-id ]", + Short: "Get variation global css code info", + Long: `Get variation global css code info `, + Run: func(cmd *cobra.Command, args []string) { + var modif web_experimentation.Modification + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.VariationID == variationID && modification.Type == "addCSS" && modification.Selector == "" { + modif = modification + } + } + + utils.FormatItem([]string{"Id", "Name", "Type", "VariationID", "Selector", "Engine", "Value"}, modif, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + infoCSSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + + if err := infoCSSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + infoCSSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + + if err := infoCSSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + VariationGlobalCodeCmd.AddCommand(infoCSSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/info-js.go b/cmd/web_experimentation/variation_global_code/info-js.go new file mode 100644 index 0000000..5f395ee --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/info-js.go @@ -0,0 +1,64 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "log" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// infoJSCmd represents info-js command +var infoJSCmd = &cobra.Command{ + Use: "info-js [-i | --id ] [--campaign-id ]", + Short: "Get variation global js code info", + Long: `Get variation global js code info `, + Run: func(cmd *cobra.Command, args []string) { + var modif web_experimentation.Modification + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + body, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range body { + if modification.VariationID == variationID && modification.Type == "customScriptNew" && modification.Selector == "" { + modif = modification + } + } + + utils.FormatItem([]string{"Id", "Name", "Type", "VariationID", "Selector", "Engine", "Value"}, modif, viper.GetString("output_format"), cmd.OutOrStdout()) + }, +} + +func init() { + infoJSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + + if err := infoJSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + infoJSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + + if err := infoJSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + VariationGlobalCodeCmd.AddCommand(infoJSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/push-css.go b/cmd/web_experimentation/variation_global_code/push-css.go new file mode 100644 index 0000000..cd4f432 --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/push-css.go @@ -0,0 +1,117 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +var cssCode string +var cssFilePath string + +// pushCSSCmd represents push command +var pushCSSCmd = &cobra.Command{ + Use: "push-css [-i | --id ] [--campaign-id ]", + Short: "push variation global css code", + Long: `push variation global css code`, + Run: func(cmd *cobra.Command, args []string) { + var modificationId int + var codeByte []byte + + if !utils.CheckSingleFlag(cssFilePath != "", cssCode != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (file, code)") + } + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + modifList, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range modifList { + if modification.VariationID == variationID && modification.Type == "addCSS" && modification.Selector == "" { + modificationId = modification.Id + } + } + + if cssFilePath != "" { + fileContent, err := os.ReadFile(cssFilePath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + codeByte = fileContent + } + + if cssCode != "" { + codeByte = []byte(cssCode) + } + + if modificationId == 0 { + modificationToPush := web_experimentation.ModificationCodeCreateStruct{ + InputType: "modification", + Name: "", + Value: string(codeByte), + Selector: "", + Type: "addCSS", + Engine: "", + VariationID: variationID, + } + + body, err := httprequest.ModificationRequester.HTTPCreateModification(campaignID, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + return + } + + modificationToPush := web_experimentation.ModificationCodeEditStruct{ + InputType: "modification", + Value: string(codeByte), + } + + body, err := httprequest.ModificationRequester.HTTPEditModification(campaignID, modificationId, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + }, +} + +func init() { + pushCSSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + if err := pushCSSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushCSSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + if err := pushCSSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushCSSCmd.Flags().StringVarP(&cssCode, "code", "c", "", "new code to push in the variation") + pushCSSCmd.Flags().StringVarP(&cssFilePath, "file", "", "", "file that contains new code to push in the variation") + + VariationGlobalCodeCmd.AddCommand(pushCSSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/push-js.go b/cmd/web_experimentation/variation_global_code/push-js.go new file mode 100644 index 0000000..b205b1a --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/push-js.go @@ -0,0 +1,117 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "fmt" + "log" + "os" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + httprequest "github.com/flagship-io/flagship/utils/http_request" + "github.com/spf13/cobra" +) + +var jsCode string +var jsFilePath string + +// pushJsCmd represents push command +var pushJSCmd = &cobra.Command{ + Use: "push-js [-i | --id ] [--campaign-id ]", + Short: "push variation global js code", + Long: `push variation global js code`, + Run: func(cmd *cobra.Command, args []string) { + var modificationId int + var codeByte []byte + + if !utils.CheckSingleFlag(jsFilePath != "", jsCode != "") { + log.Fatalf("error occurred: %s", "1 flag is required. (file, code)") + } + + campaignID, err := strconv.Atoi(CampaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + variationID, err := strconv.Atoi(VariationID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + modifList, err := httprequest.ModificationRequester.HTTPListModification(campaignID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + for _, modification := range modifList { + if modification.VariationID == variationID && modification.Type == "customScriptNew" && modification.Selector == "" { + modificationId = modification.Id + } + } + + if jsFilePath != "" { + fileContent, err := os.ReadFile(jsFilePath) + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + codeByte = fileContent + } + + if jsCode != "" { + codeByte = []byte(jsCode) + } + + if modificationId == 0 { + modificationToPush := web_experimentation.ModificationCodeCreateStruct{ + InputType: "modification", + Name: "", + Value: string(codeByte), + Selector: "", + Type: "customScriptNew", + Engine: "", + VariationID: variationID, + } + + body, err := httprequest.ModificationRequester.HTTPCreateModification(campaignID, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + return + } + + modificationToPush := web_experimentation.ModificationCodeEditStruct{ + InputType: "modification", + Value: string(codeByte), + } + + body, err := httprequest.ModificationRequester.HTTPEditModification(campaignID, modificationId, modificationToPush) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + fmt.Fprintln(cmd.OutOrStdout(), string(body)) + }, +} + +func init() { + pushJSCmd.Flags().StringVarP(&CampaignID, "campaign-id", "", "", "id of the global code campaign you want to display") + if err := pushJSCmd.MarkFlagRequired("campaign-id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushJSCmd.Flags().StringVarP(&VariationID, "id", "i", "", "id of the global code variation you want to display") + if err := pushJSCmd.MarkFlagRequired("id"); err != nil { + log.Fatalf("error occurred: %v", err) + } + + pushJSCmd.Flags().StringVarP(&jsCode, "code", "c", "", "new code to push in the variation") + pushJSCmd.Flags().StringVarP(&jsFilePath, "file", "", "", "file that contains new code to push in the variation") + + VariationGlobalCodeCmd.AddCommand(pushJSCmd) +} diff --git a/cmd/web_experimentation/variation_global_code/variation_global_code.go b/cmd/web_experimentation/variation_global_code/variation_global_code.go new file mode 100644 index 0000000..d6d4df9 --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/variation_global_code.go @@ -0,0 +1,61 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package variation_global_code + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +var WorkingDir string +var CampaignID string +var VariationID string +var CreateFile bool +var Override bool + +// VariationGlobalCodeCmd represents the variation global code command +var VariationGlobalCodeCmd = &cobra.Command{ + Use: "variation-global-code [get-js | get-css]", + Short: "Get variation global code", + Aliases: []string{"vgc"}, + Long: `Get variation global code`, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func init() { + cobra.OnInitialize(initConfig) + cobra.OnInitialize(initGlobalCodeDir) + VariationGlobalCodeCmd.PersistentFlags().StringVarP(&WorkingDir, "working-dir", "", utils.DefaultGlobalCodeWorkingDir(), "Directory where the file will be generated and pushed from") +} + +func initConfig() { + v := viper.New() + + homeDir, _ := os.UserHomeDir() + + v.BindPFlag("working_dir", VariationGlobalCodeCmd.PersistentFlags().Lookup("working-dir")) + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + + err := v.WriteConfig() + if err != nil { + log.Fatalf("error occurred: %s", err) + } + viper.MergeConfigMap(v.AllSettings()) +} + +func initGlobalCodeDir() { + _, err := config.CheckWorkingDirectory(viper.GetString("working_dir")) + if err != nil { + log.Fatalf("error occurred: %s", err) + } +} diff --git a/cmd/web_experimentation/variation_global_code/variation_global_code_test.go b/cmd/web_experimentation/variation_global_code/variation_global_code_test.go new file mode 100644 index 0000000..bb30224 --- /dev/null +++ b/cmd/web_experimentation/variation_global_code/variation_global_code_test.go @@ -0,0 +1,108 @@ +package variation_global_code + +import ( + "encoding/json" + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + mockfunction.SetMock(&http_request.ResourceRequester) + + mockfunction_we.APIModification() + + m.Run() +} + +var testModification models.Modification + +func TestVariationGlobalCodeCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(VariationGlobalCodeCmd) + assert.Contains(t, output, "Get variation global code") +} + +func TestVariationGlobalCodeHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "--help") + assert.Contains(t, output, "Get variation global code") +} + +func TestVariationGlobalCodeGetJSCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "get-js") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "get-js", "-i=110000", "--campaign-id=100000") + assert.Equal(t, "console.log(\"test modification\")\n", successOutput) +} + +func TestVariationGlobalCodeGetCSSCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "get-css") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "get-css", "-i=110000", "--campaign-id=100000") + assert.Equal(t, ".id{\"color\": \"black\"}\n", successOutput) +} + +func TestVariationGlobalCodeInfoCSSCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "info-css") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "info-css", "-i=110000", "--campaign-id=100000") + + err := json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestModificationsCSS, testModification) +} + +func TestVariationGlobalCodeInfoJSCommand(t *testing.T) { + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "info-js") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "info-js", "-i=110000", "--campaign-id=100000") + + err := json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestModificationsJS, testModification) +} + +func TestVariationGlobalCodePushJSCommand(t *testing.T) { + var testModification models.Modification + + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "push-js") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "push-js", "-i=110000", "--campaign-id=100000", "--code=console.log(\"test modification\")") + err := json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + assert.Equal(t, mockfunction_we.TestModificationsJS, testModification) +} + +func TestVariationGlobalCodePushCSSCommand(t *testing.T) { + var testModification models.Modification + + failOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "push-css") + assert.Contains(t, failOutput, "Error: required flag(s) \"campaign-id\", \"id\" not set\nUsage") + + successOutput, _ := utils.ExecuteCommand(VariationGlobalCodeCmd, "push-css", "-i=110000", "--campaign-id=100000", "--code=.id{\"color\": \"black\"}") + err := json.Unmarshal([]byte(successOutput), &testModification) + + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestModificationsCSS, testModification) +} diff --git a/cmd/web_experimentation/web_experimentation.go b/cmd/web_experimentation/web_experimentation.go new file mode 100644 index 0000000..7efc957 --- /dev/null +++ b/cmd/web_experimentation/web_experimentation.go @@ -0,0 +1,83 @@ +/* +Copyright © 2022 Flagship Team flagship@abtasty.com +*/ +package web_experimentation + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/cmd/web_experimentation/account" + "github.com/flagship-io/flagship/cmd/web_experimentation/account_global_code" + "github.com/flagship-io/flagship/cmd/web_experimentation/auth" + "github.com/flagship-io/flagship/cmd/web_experimentation/campaign" + campaign_global_code "github.com/flagship-io/flagship/cmd/web_experimentation/campaign_global_code" + "github.com/flagship-io/flagship/cmd/web_experimentation/modification" + "github.com/flagship-io/flagship/cmd/web_experimentation/modification_code" + "github.com/flagship-io/flagship/cmd/web_experimentation/token" + "github.com/flagship-io/flagship/cmd/web_experimentation/variation" + variation_global_code "github.com/flagship-io/flagship/cmd/web_experimentation/variation_global_code" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" + "github.com/flagship-io/flagship/utils/http_request" + "github.com/flagship-io/flagship/utils/http_request/common" + + "github.com/spf13/cobra" + "github.com/spf13/viper" +) + +// WebExperimentationCmd represents the web experimentation command +var WebExperimentationCmd = &cobra.Command{ + Use: "web-experimentation [auth|account|campaign|global-code|variation]", + Aliases: []string{"web-experimentation", "web-exp", "we"}, + Short: "Manage resources related to the web experimentation product", + Long: `Manage resources related to the web experimentation product`, + PersistentPreRun: func(cmd *cobra.Command, args []string) { + initConfig() + }, + Run: func(cmd *cobra.Command, args []string) { + cmd.Help() + }, +} + +func addSubCommandPalettes() { + WebExperimentationCmd.AddCommand(campaign.CampaignCmd) + WebExperimentationCmd.AddCommand(variation.VariationCmd) + WebExperimentationCmd.AddCommand(auth.AuthCmd) + WebExperimentationCmd.AddCommand(account.AccountCmd) + WebExperimentationCmd.AddCommand(campaign_global_code.CampaignGlobalCodeCmd) + WebExperimentationCmd.AddCommand(account_global_code.AccountGlobalCodeCmd) + WebExperimentationCmd.AddCommand(variation_global_code.VariationGlobalCodeCmd) + WebExperimentationCmd.AddCommand(modification_code.ModificationCodeCmd) + WebExperimentationCmd.AddCommand(token.TokenCmd) + WebExperimentationCmd.AddCommand(modification.ModificationCmd) +} + +func init() { + addSubCommandPalettes() +} + +func initConfig() { + v := viper.New() + homeDir, _ := os.UserHomeDir() + var requestConfig = common.RequestConfig{Product: utils.WEB_EXPERIMENTATION} + + v.SetConfigFile(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION + "/.cli.yaml") + v.MergeInConfig() + if v.GetString("current_used_credential") != "" { + vL, err := config.ReadAuth(utils.WEB_EXPERIMENTATION, v.GetString("current_used_credential")) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + + v.MergeConfigMap(vL.AllSettings()) + } + + v.Unmarshal(&requestConfig) + common.Init(requestConfig) + + r := &http_request.ResourceRequester + + r.Init(&requestConfig) + return +} diff --git a/cmd/web_experimentation/web_experimentation_test.go b/cmd/web_experimentation/web_experimentation_test.go new file mode 100644 index 0000000..4265ff5 --- /dev/null +++ b/cmd/web_experimentation/web_experimentation_test.go @@ -0,0 +1,29 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/jarcoal/httpmock" + "github.com/stretchr/testify/assert" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + defer mockfunction_we.InitMockAuth() + + m.Run() +} + +func TestAccountCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(WebExperimentationCmd) + assert.Contains(t, output, "Manage resources related to the web experimentation product") +} + +func TestAccountHelpCommand(t *testing.T) { + output, _ := utils.ExecuteCommand(WebExperimentationCmd, "--help") + assert.Contains(t, output, "Manage resources related to the web experimentation product") +} diff --git a/go.mod b/go.mod index 609459c..c2f5bfa 100644 --- a/go.mod +++ b/go.mod @@ -3,12 +3,11 @@ module github.com/flagship-io/flagship go 1.18 require ( + github.com/d5/tengo/v2 v2.13.0 github.com/flagship-io/codebase-analyzer v0.8.0 github.com/kyokomi/emoji/v2 v2.2.12 - github.com/d5/tengo/v2 v2.13.0 github.com/rodaine/table v1.1.0 github.com/sirupsen/logrus v1.9.0 - github.com/spf13/cobra v1.5.0 github.com/spf13/viper v1.12.0 github.com/stretchr/testify v1.8.1 @@ -43,6 +42,6 @@ require ( golang.org/x/sys v0.3.0 // indirect golang.org/x/text v0.5.0 // indirect gopkg.in/ini.v1 v1.66.4 // indirect - gopkg.in/yaml.v2 v2.4.0 // indirect + gopkg.in/yaml.v2 v2.4.0 gopkg.in/yaml.v3 v3.0.1 // indirect ) diff --git a/models/auth.go b/models/auth.go new file mode 100644 index 0000000..100521d --- /dev/null +++ b/models/auth.go @@ -0,0 +1,31 @@ +package models + +type Auth struct { + Username string `json:"username"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` + Token string `json:"token"` + RefreshToken string `json:"refresh_token"` + Scope string `json:"scope"` +} + +type AuthYaml struct { + Username string `yaml:"username"` + ClientID string `yaml:"client_id"` + ClientSecret string `yaml:"client_secret"` + Token string `yaml:"token"` + RefreshToken string `yaml:"refresh_token"` + Scope string `yaml:"scope"` +} + +type AccountYaml struct { + CurrentUsedCredential string `yaml:"current_used_credential"` + AccountID string `yaml:"account_id"` + AccountEnvironmentID string `yaml:"account_environment_id"` +} + +type AccountJSON struct { + CurrentUsedCredential string `json:"current_used_credential"` + AccountID string `json:"account_id"` + AccountEnvironmentID string `json:"account_environment_id"` +} diff --git a/models/configuration.go b/models/configuration.go deleted file mode 100644 index e17e5d0..0000000 --- a/models/configuration.go +++ /dev/null @@ -1,17 +0,0 @@ -package models - -type Configuration struct { - Name string `json:"name"` - ClientID string `json:"client_id"` - ClientSecret string `json:"client_secret"` - AccountID string `json:"account_id"` - AccountEnvironmentID string `json:"account_environment_id"` -} - -type ConfigurationYaml struct { - Name string `yaml:"name"` - ClientID string `yaml:"client_id"` - ClientSecret string `yaml:"client_secret"` - AccountID string `yaml:"account_id"` - AccountEnvironmentID string `yaml:"account_environment_id"` -} diff --git a/models/feature_experimentation/account_environment.go b/models/feature_experimentation/account_environment.go new file mode 100644 index 0000000..3579380 --- /dev/null +++ b/models/feature_experimentation/account_environment.go @@ -0,0 +1,9 @@ +package feature_experimentation + +type AccountEnvironmentFE struct { + Id string `json:"id,omitempty"` + Environment string `json:"environment"` + IsMain bool `json:"is_main"` + Panic bool `json:"panic"` + SingleAssignment bool `json:"single_assignment"` +} diff --git a/models/analyze.go b/models/feature_experimentation/analyze.go similarity index 92% rename from models/analyze.go rename to models/feature_experimentation/analyze.go index 688b02b..56673dc 100644 --- a/models/analyze.go +++ b/models/feature_experimentation/analyze.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type FlagAnalyzed struct { LineNumber int `json:"LineNumber"` diff --git a/models/campaign.go b/models/feature_experimentation/campaign.go similarity index 86% rename from models/campaign.go rename to models/feature_experimentation/campaign.go index 04cbfa6..3b1e197 100644 --- a/models/campaign.go +++ b/models/feature_experimentation/campaign.go @@ -1,6 +1,6 @@ -package models +package feature_experimentation -type Campaign struct { +type CampaignFE struct { Id string `json:"id,omitempty"` ProjectId string `json:"project_id"` Name string `json:"name"` @@ -17,6 +17,6 @@ type Scheduler struct { TimeZone string `json:"timezone"` } -type CampaignSwitchRequest struct { +type CampaignFESwitchRequest struct { State string `json:"state"` } diff --git a/models/flag.go b/models/feature_experimentation/flag.go similarity index 94% rename from models/flag.go rename to models/feature_experimentation/flag.go index 7983069..0c07bdf 100644 --- a/models/flag.go +++ b/models/feature_experimentation/flag.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type Flag struct { Id string `json:"id,omitempty"` diff --git a/models/goal.go b/models/feature_experimentation/goal.go similarity index 85% rename from models/goal.go rename to models/feature_experimentation/goal.go index 5a58933..da79adc 100644 --- a/models/goal.go +++ b/models/feature_experimentation/goal.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type Goal struct { Id string `json:"id,omitempty"` diff --git a/models/panic.go b/models/feature_experimentation/panic.go similarity index 64% rename from models/panic.go rename to models/feature_experimentation/panic.go index 6868b19..d82a73a 100644 --- a/models/panic.go +++ b/models/feature_experimentation/panic.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type PanicRequest struct { Panic string `json:"panic"` diff --git a/models/project.go b/models/feature_experimentation/project.go similarity index 82% rename from models/project.go rename to models/feature_experimentation/project.go index 55ddbf1..3690c14 100644 --- a/models/project.go +++ b/models/feature_experimentation/project.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type Project struct { Id string `json:"id,omitempty"` diff --git a/models/targeting_key.go b/models/feature_experimentation/targeting_key.go similarity index 84% rename from models/targeting_key.go rename to models/feature_experimentation/targeting_key.go index 1c8fc16..1da8a98 100644 --- a/models/targeting_key.go +++ b/models/feature_experimentation/targeting_key.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type TargetingKey struct { Id string `json:"id,omitempty"` diff --git a/models/user.go b/models/feature_experimentation/user.go similarity index 71% rename from models/user.go rename to models/feature_experimentation/user.go index c695f0e..c35c918 100644 --- a/models/user.go +++ b/models/feature_experimentation/user.go @@ -1,4 +1,4 @@ -package models +package feature_experimentation type User struct { Email string `json:"email"` diff --git a/models/variation.go b/models/feature_experimentation/variation.go similarity index 85% rename from models/variation.go rename to models/feature_experimentation/variation.go index 7969924..21bf137 100644 --- a/models/variation.go +++ b/models/feature_experimentation/variation.go @@ -1,6 +1,6 @@ -package models +package feature_experimentation -type Variation struct { +type VariationFE struct { Id string `json:"id,omitempty"` Name string `json:"name"` Reference bool `json:"reference"` diff --git a/models/variation_group.go b/models/feature_experimentation/variation_group.go similarity index 60% rename from models/variation_group.go rename to models/feature_experimentation/variation_group.go index 8107596..28ebb94 100644 --- a/models/variation_group.go +++ b/models/feature_experimentation/variation_group.go @@ -1,10 +1,10 @@ -package models +package feature_experimentation type VariationGroup struct { - Id string `json:"id,omitempty"` - Name string `json:"name,omitempty"` - Variations *[]Variation `json:"variations"` - Targeting Targeting `json:"targeting"` + Id string `json:"id,omitempty"` + Name string `json:"name,omitempty"` + Variations *[]VariationFE `json:"variations"` + Targeting Targeting `json:"targeting"` } type Targeting struct { diff --git a/models/token.go b/models/token.go index b3136e9..b3e5c37 100644 --- a/models/token.go +++ b/models/token.go @@ -1,5 +1,29 @@ package models +type MfaRequestWE struct { + MfaToken string `json:"mfa_token"` + MfaMethods []string `json:"mfa_methods"` +} + +type MultiFactorMethodRequestWE struct { + MfaToken string `json:"token"` + MfaMethod string `json:"mfa_method"` + GrantType string `json:"grant_type"` +} + +type MultiFactorRequestWE struct { + MfaToken string `json:"token"` + MfaMethod string `json:"mfa_method"` + GrantType string `json:"grant_type"` + Code string `json:"code"` +} + +type MultiFactorMethodResponseWE struct { + MfaToken string `json:"token"` + MfaMethod string `json:"mfa_method"` + GrantType string `json:"grant_type"` +} + type Token struct { ClientID string `json:"client_id"` AccountID string `json:"account"` @@ -10,11 +34,39 @@ type Token struct { type TokenResponse struct { AccessToken string `json:"access_token"` RefreshToken string `json:"refresh_token"` + Scope string `json:"scope"` } -type TokenRequest struct { +type ClientCredentialsRequest struct { GrantType string `json:"grant_type"` - Scope string `json:"scope"` + Scope string `json:"scope,omitempty"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` +} + +type AuthorizationCodeRequest struct { + GrantType string `json:"grant_type"` + Code string `json:"code"` ClientID string `json:"client_id"` ClientSecret string `json:"client_secret"` } + +type PasswordRequest struct { + GrantType string `json:"grant_type"` + Username string `json:"username"` + Password string `json:"password"` + ClientID string `json:"client_id"` + ClientSecret string `json:"client_secret"` +} + +type RefreshTokenRequestFE struct { + GrantType string `json:"grant_type"` + ClientID string `json:"client_id"` + RefreshToken string `json:"refresh_token"` +} +type RefreshTokenRequestWE struct { + GrantType string `json:"grant_type"` + ClientID string `json:"client_id"` + RefreshToken string `json:"refresh_token"` + ClientSecret string `json:"client_secret"` +} diff --git a/models/web_experimentation/account.go b/models/web_experimentation/account.go new file mode 100644 index 0000000..e805253 --- /dev/null +++ b/models/web_experimentation/account.go @@ -0,0 +1,14 @@ +package web_experimentation + +type AccountWE struct { + Id int `json:"id,omitempty"` + Name string `json:"name"` + Identifier string `json:"identifier"` + Role string `json:"role"` + GlobalCode GlobalCode_ `json:"global_code"` +} + +type GlobalCode_ struct { + OnDomReady bool `json:"on_dom_ready"` + Value string `json:"value"` +} diff --git a/models/web_experimentation/campaign.go b/models/web_experimentation/campaign.go new file mode 100644 index 0000000..37ba55a --- /dev/null +++ b/models/web_experimentation/campaign.go @@ -0,0 +1,34 @@ +package web_experimentation + +type CampaignWE struct { + Id int `json:"id,omitempty"` + Name string `json:"name"` + Url string `json:"url"` + Description string `json:"description"` + Type string `json:"type"` + SubType string `json:"sub_type"` + State string `json:"state"` + Traffic *Traffic `json:"traffic"` + Variations *[]VariationWE `json:"variations"` + SubTests *[]CampaignWE `json:"sub_tests"` + CreatingDate DateTemplate `json:"created_at"` + Labels []string `json:"labels"` + LastPlayTimestamp DateTemplate `json:"last_play"` + LastPauseTimestamp DateTemplate `json:"last_pause"` + GlobalCodeCampaign string `json:"global_code"` + SourceCode string `json:"source_code"` +} + +type Traffic struct { + Value int `json:"value"` + LastIncreasedTraffic string `json:"last_increased_traffic"` + Visitors int `json:"visitors"` + OriginalVisitors int `json:"original_visitors"` + VisitorsLimit int `json:"visitors_limit"` +} + +type DateTemplate struct { + ReadableDate string `json:"readable_date"` + Timestamp int `json:"timestamp"` + Pattern string `json:"pattern"` +} diff --git a/models/web_experimentation/global-code.go b/models/web_experimentation/global-code.go new file mode 100644 index 0000000..f409519 --- /dev/null +++ b/models/web_experimentation/global-code.go @@ -0,0 +1,30 @@ +package web_experimentation + +type GlobalCode struct { + Id int `json:"id,omitempty"` + Code string `json:"code"` + CreatedAt DateTemplate `json:"created_at"` +} + +type GlobalCodeStr struct { + GlobalCode string `json:"global_code"` +} + +type ModificationCodeEditStruct struct { + InputType string `json:"input_type"` + Name string `json:"name,omitempty"` + Value string `json:"value,omitempty"` + Selector string `json:"selector,omitempty"` + Type string `json:"type,omitempty"` + Engine string `json:"engine,omitempty"` +} + +type ModificationCodeCreateStruct struct { + InputType string `json:"input_type"` + Name string `json:"name"` + Value string `json:"value"` + Selector string `json:"selector"` + Type string `json:"type"` + Engine string `json:"engine"` + VariationID int `json:"variation_id"` +} diff --git a/models/web_experimentation/variation.go b/models/web_experimentation/variation.go new file mode 100644 index 0000000..4573a8e --- /dev/null +++ b/models/web_experimentation/variation.go @@ -0,0 +1,50 @@ +package web_experimentation + +type VariationWE struct { + Id int `json:"id,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + Type string `json:"type"` + Traffic int `json:"traffic"` + VisualEditor bool `json:"visual_editor"` + CodeEditor bool `json:"code_editor"` + Components *[]Component `json:"components"` +} + +type Component struct { + Id int `json:"id,omitempty"` + Name string `json:"name"` + Description string `json:"description"` + Tags []string `json:"tags"` + Js string `json:"js"` + Css string `json:"css"` + Html string `json:"html"` + Form string `json:"form"` + Options string `json:"options"` +} + +type Modification struct { + Id int `json:"id"` + Name string `json:"name"` + Type string `json:"type"` + Value string `json:"value"` + VariationID int `json:"variation_id"` + Selector string `json:"selector"` + Engine string `json:"engine"` + UpdatedBy UpdatedBy_ `json:"updated_by"` + UpdatedAt DateTemplate `json:"updated_at"` +} + +type UpdatedBy_ struct { + Id int `json:"id"` + Email string `json:"email"` +} + +type ModificationWE struct { + GlobalModifications []Modification `json:"global_modifications"` + Modifications []Modification `json:"modifications"` +} + +type ModificationDataWE struct { + Data ModificationWE `json:"_data"` +} diff --git a/utils/config/config.go b/utils/config/config.go index 709a4d0..9936589 100644 --- a/utils/config/config.go +++ b/utils/config/config.go @@ -1,187 +1,209 @@ package config import ( - "bytes" - "encoding/json" "errors" "fmt" - "log" "os" "path/filepath" "regexp" - "github.com/spf13/cobra" + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" "github.com/spf13/viper" ) -type Config struct { - *viper.Viper -} - -var v = viper.New() +func CheckABTastyHomeDirectory() (string, error) { + homeDir, err := os.UserHomeDir() -func Unset(key string) error { - configMap := viper.AllSettings() - delete(configMap, key) - encodedConfig, _ := json.MarshalIndent(configMap, "", " ") - err := viper.ReadConfig(bytes.NewReader(encodedConfig)) - if err != nil { - return err + if _, err := os.Stat(homeDir + "/.flagship/credentials/" + utils.FEATURE_EXPERIMENTATION); errors.Is(err, os.ErrNotExist) { + err := os.MkdirAll(homeDir+"/.flagship/credentials/"+utils.FEATURE_EXPERIMENTATION, os.ModePerm) + if err != nil { + return "", err + } } - viper.WriteConfig() - return nil -} -func CheckFlagshipHomeDirectory() string { - homeDir, err := os.UserHomeDir() - cobra.CheckErr(err) - - if _, err := os.Stat(homeDir + "/.flagship/configurations"); errors.Is(err, os.ErrNotExist) { - err := os.MkdirAll(homeDir+"/.flagship/configurations", os.ModePerm) + if _, err := os.Stat(homeDir + "/.flagship/credentials/" + utils.WEB_EXPERIMENTATION); errors.Is(err, os.ErrNotExist) { + err := os.MkdirAll(homeDir+"/.flagship/credentials/"+utils.WEB_EXPERIMENTATION, os.ModePerm) if err != nil { - log.Fatal(err) + return "", err } } - return homeDir + return homeDir, err } -func SetPathForConfigName(fileName string) string { - homeDir := CheckFlagshipHomeDirectory() +func CredentialPath(product, username string) (string, error) { + homeDir, err := CheckABTastyHomeDirectory() + if err != nil { + return "", err + } - filepath, err := filepath.Abs(homeDir + "/.flagship/configurations/" + fileName + ".yaml") + filepath, err := filepath.Abs(homeDir + "/.flagship/credentials/" + product + "/" + username + ".yaml") if err != nil { - log.Fatalf("error occured: %v", err) + return "", err } - return filepath + return filepath, nil } -func GetConfigurationsName() ([]string, error) { - homeDir := CheckFlagshipHomeDirectory() - r := regexp.MustCompile(`(?P[^/]+)\.yaml`) +func GetUsernames(product string) ([]string, error) { + homeDir, err := CheckABTastyHomeDirectory() + if err != nil { + return nil, err + } + + r := regexp.MustCompile(`(?P[^/]+)\.yaml`) var fileNames []string - f, err := os.Open(homeDir + "/.flagship/configurations") + f, err := os.Open(homeDir + "/.flagship/credentials/" + product) if err != nil { - fmt.Println(err) + fmt.Fprintf(os.Stderr, "error occurred: %s", err) return nil, err } files, err := f.Readdir(0) if err != nil { - fmt.Println(err) + fmt.Fprintf(os.Stderr, "error occurred: %s", err) return nil, err } for _, v := range files { match := r.FindStringSubmatch(v.Name()) - configurationName := r.SubexpIndex("ConfigurationName") + userName := r.SubexpIndex("Username") if len(match) == 0 { - log.Fatalln("Error: File not found") + err := errors.New("Error: File not found") + return nil, err } - if match[configurationName] == ".cli" { - continue - } - - fileNames = append(fileNames, match[configurationName]) + fileNames = append(fileNames, match[userName]) } return fileNames, nil } -func SetOptionalsDefault(grantType, scope string, expiration int) { - viper.Set("grant_type", grantType) - viper.Set("scope", scope) - viper.Set("expiration", expiration) -} - -func CreateConfigurationFile(configurationName, clientId, clientSecret, accountId, accountEnvId string) { - filepath := SetPathForConfigName(configurationName) +func CreateAuthFile(product, username, clientId, clientSecret string, authenticationResponse models.TokenResponse) error { + v := viper.New() + filepath, err := CredentialPath(product, username) + if err != nil { + return err + } - v.Set("name", configurationName) + v.Set("username", username) v.Set("client_id", clientId) v.Set("client_secret", clientSecret) - v.Set("account_id", accountId) - v.Set("account_environment_id", accountEnvId) + v.Set("token", authenticationResponse.AccessToken) + v.Set("refresh_token", authenticationResponse.RefreshToken) + v.Set("scope", authenticationResponse.Scope) - err := v.WriteConfigAs(filepath) + err = v.WriteConfigAs(filepath) if err != nil { - log.Fatalf("error occurred: %v", err) + return err } + return nil } -func SelectConfiguration(configurationName string) { - filepath := SetPathForConfigName(".cli") - v.Set("current_used_configuration", configurationName) - - err := v.WriteConfigAs(filepath) +func ReadAuth(product, AuthName string) (*viper.Viper, error) { + v := viper.New() + configFilepath, err := CredentialPath(product, AuthName) if err != nil { - log.Fatalf("error occurred: %v", err) + return nil, err } - ReadConfiguration(configurationName) + if _, err := os.Stat(configFilepath); errors.Is(err, os.ErrNotExist) { + fmt.Fprintf(os.Stderr, "error occurred: %v \n", err) + } + v.SetConfigFile(configFilepath) + v.MergeInConfig() + return v, nil } -func ReadConfiguration(configurationName string) { - configFilepath := SetPathForConfigName(configurationName) - viper.SetConfigFile(configFilepath) - viper.MergeInConfig() -} +func SelectAuth(product, AuthName string) error { + var v = viper.New() -func EditConfigurationFile(configurationName, newName, clientId, clientSecret, accountId, accountEnvId string) { - filepath := SetPathForConfigName(configurationName) + filepath, err := CredentialPath(product, utils.HOME_CLI) + if err != nil { + return err + } - v.Set("name", newName) - v.Set("client_id", clientId) - v.Set("client_secret", clientSecret) - v.Set("account_id", accountId) - v.Set("account_environment_id", accountEnvId) + v.Set("current_used_credential", AuthName) - err := v.WriteConfigAs(filepath) + err = v.WriteConfigAs(filepath) if err != nil { - log.Fatalf("error occurred: %v", err) + return err } - e := os.Rename(filepath, SetPathForConfigName(newName)) - if e != nil { - log.Fatal(e) - } + return nil } -func ReadCredentialsFromFile(configurationFile string) { - viper.SetConfigFile(configurationFile) - err := viper.MergeInConfig() +func SetAccountID(product, accountID string) error { + var v = viper.New() + configFilepath, err := CredentialPath(product, utils.HOME_CLI) if err != nil { - log.Fatalf("error occurred: %v", err) + return err } + + v.SetConfigFile(configFilepath) + v.MergeInConfig() + + v.Set("account_id", accountID) + + err = v.WriteConfigAs(configFilepath) + if err != nil { + return err + } + + return nil } -func WriteToken(configurationName, token string) { - configFilepath := SetPathForConfigName(configurationName) +func SetAccountEnvID(product, accountEnvID string) error { + var v = viper.New() + configFilepath, err := CredentialPath(product, utils.HOME_CLI) + if err != nil { + return err + } + + v.SetConfigFile(configFilepath) + v.MergeInConfig() - viper.SetConfigFile(configFilepath) - err := viper.MergeInConfig() + v.Set("account_environment_id", accountEnvID) + + err = v.WriteConfigAs(configFilepath) if err != nil { - log.Fatalf("error occurred: %v", err) + return err } - viper.Set("token", token) - viper.Set("current_used_configuration", nil) - Unset("current_used_configuration") + return nil +} - err = viper.WriteConfigAs(configFilepath) +func ReadCredentialsFromFile(AuthFile string) (*viper.Viper, error) { + var v = viper.New() + v.SetConfigFile(AuthFile) + err := v.MergeInConfig() if err != nil { - log.Fatalf("error occurred: %v", err) + return nil, err } + + return v, nil } -func SetViperMock() { - viper.GetViper().Set("account_id", "account_id") - viper.GetViper().Set("account_environment_id", "account_environment_id") - viper.GetViper().Set("client_id", "client_id") - viper.GetViper().Set("client_secret", "client_secret") - viper.GetViper().Set("token", "token") - viper.GetViper().Set("output_format", "json") +func RewriteToken(product, AuthName string, authenticationResponse models.TokenResponse) error { + v := viper.New() + configFilepath, err := CredentialPath(product, AuthName) + if err != nil { + return err + } + + v.SetConfigFile(configFilepath) + + v.MergeInConfig() + v.Set("token", authenticationResponse.AccessToken) + v.Set("refresh_token", authenticationResponse.RefreshToken) + v.Set("scope", authenticationResponse.Scope) + + err = v.WriteConfigAs(configFilepath) + if err != nil { + return err + } + + return nil } diff --git a/utils/config/config_global_code.go b/utils/config/config_global_code.go new file mode 100644 index 0000000..df57973 --- /dev/null +++ b/utils/config/config_global_code.go @@ -0,0 +1,201 @@ +package config + +import ( + "errors" + "fmt" + "os" +) + +func CheckWorkingDirectory(workingDir string) (string, error) { + + if _, err := os.Stat(workingDir); errors.Is(err, os.ErrNotExist) { + if err != nil { + return "", err + } + } + + return workingDir, nil +} + +func CheckGlobalCodeDirectory(workingDir string) (string, error) { + wd, err := CheckWorkingDirectory(workingDir) + if err != nil { + return "", err + } + + gcWorkingDir := wd + "/abtasty" + + err = os.MkdirAll(gcWorkingDir, os.ModePerm) + if err != nil { + return "", err + } + + return gcWorkingDir, nil +} + +func AccountGlobalCodeDirectory(workingDir, accountID, code string, override bool) (string, error) { + + gcWorkingDir, err := CheckGlobalCodeDirectory(workingDir) + if err != nil { + return "", err + } + + accountCodeDir := gcWorkingDir + "/" + accountID + + err = os.MkdirAll(accountCodeDir, os.ModePerm) + if err != nil { + return "", err + } + + jsFilePath := accountCodeDir + "/accountGlobalCode.js" + if _, err := os.Stat(jsFilePath); err == nil { + if !override { + fmt.Fprintln(os.Stderr, "File already exists: "+jsFilePath) + return jsFilePath, nil + } + } + + err = os.WriteFile(jsFilePath, []byte(code), os.ModePerm) + if err != nil { + return "", err + } + + fmt.Fprintln(os.Stdout, "File created: "+jsFilePath) + return jsFilePath, nil +} + +func CampaignGlobalCodeDirectory(workingDir, accountID, campaignID, code string, override bool) (string, error) { + gcWorkingDir, err := CheckGlobalCodeDirectory(workingDir) + if err != nil { + return "", err + } + + accountCodeDir := gcWorkingDir + "/" + accountID + campaignCodeDir := accountCodeDir + "/" + campaignID + + err = os.MkdirAll(campaignCodeDir, os.ModePerm) + if err != nil { + return "", err + } + + jsFilePath := campaignCodeDir + "/campaignGlobalCode.js" + if _, err := os.Stat(jsFilePath); err == nil { + if !override { + fmt.Fprintln(os.Stderr, "File already exists: "+jsFilePath) + return jsFilePath, nil + } + } + + err = os.WriteFile(jsFilePath, []byte(code), os.ModePerm) + if err != nil { + return "", err + } + + fmt.Fprintln(os.Stdout, "File created: "+jsFilePath) + return jsFilePath, nil +} + +func VariationGlobalCodeDirectoryJS(workingDir, accountID, campaignID, variationID, code string, override bool) (string, error) { + gcWorkingDir, err := CheckGlobalCodeDirectory(workingDir) + if err != nil { + return "", err + } + + accountCodeDir := gcWorkingDir + "/" + accountID + campaignCodeDir := accountCodeDir + "/" + campaignID + variationCodeDir := campaignCodeDir + "/" + variationID + + err = os.MkdirAll(variationCodeDir, os.ModePerm) + if err != nil { + return "", err + } + + jsFilePath := variationCodeDir + "/variationGlobalCode.js" + if _, err := os.Stat(jsFilePath); err == nil { + if !override { + fmt.Fprintln(os.Stderr, "File already exists: "+jsFilePath) + return jsFilePath, nil + } + } + + err = os.WriteFile(jsFilePath, []byte(code), os.ModePerm) + if err != nil { + return "", err + } + + fmt.Fprintln(os.Stdout, "File created: "+jsFilePath) + return jsFilePath, nil +} + +func VariationGlobalCodeDirectoryCSS(workingDir, accountID, campaignID, variationID, code string, override bool) (string, error) { + gcWorkingDir, err := CheckGlobalCodeDirectory(workingDir) + if err != nil { + return "", err + } + + accountCodeDir := gcWorkingDir + "/" + accountID + campaignCodeDir := accountCodeDir + "/" + campaignID + variationCodeDir := campaignCodeDir + "/" + variationID + + err = os.MkdirAll(variationCodeDir, os.ModePerm) + if err != nil { + return "", err + } + + filePath := variationCodeDir + "/variationGlobalCode.css" + if _, err := os.Stat(filePath); err == nil { + if !override { + fmt.Fprintln(os.Stderr, "File already exists: "+filePath) + return filePath, nil + } + } + + err = os.WriteFile(filePath, []byte(code), os.ModePerm) + if err != nil { + return "", err + } + + fmt.Fprintln(os.Stdout, "File created: "+filePath) + return filePath, nil +} + +func ModificationCodeDirectory(workingDir, accountID, campaignID, variationID, modificationID, selector string, code []byte, override bool) (string, error) { + gcWorkingDir, err := CheckGlobalCodeDirectory(workingDir) + if err != nil { + return "", err + } + + accountCodeDir := gcWorkingDir + "/" + accountID + campaignCodeDir := accountCodeDir + "/" + campaignID + variationCodeDir := campaignCodeDir + "/" + variationID + elementCodeDir := variationCodeDir + "/" + modificationID + + err = os.MkdirAll(elementCodeDir, os.ModePerm) + if err != nil { + return "", err + } + + jsFilePath := elementCodeDir + "/element.js" + if _, err := os.Stat(jsFilePath); err == nil { + if !override { + fmt.Fprintln(os.Stderr, "File already exists: "+jsFilePath) + return jsFilePath, nil + } + } + + err = os.WriteFile(jsFilePath, code, os.ModePerm) + if err != nil { + return "", err + } + + fmt.Fprintln(os.Stdout, "File created: "+jsFilePath) + return jsFilePath, nil +} + +func AddHeaderSelectorComment(selector, code string) []byte { + selectorComment := "/* Selector: " + selector + " */\n" + headerComment := []byte(selectorComment) + + fileCode := append(headerComment, []byte(code)...) + return fileCode +} diff --git a/utils/config/config_global_code_test.go b/utils/config/config_global_code_test.go new file mode 100644 index 0000000..b508454 --- /dev/null +++ b/utils/config/config_global_code_test.go @@ -0,0 +1,323 @@ +package config + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +type TestStruct struct { + name string + workingDir string + want string + code string + accountID string + campaignID string + variationID string + modificationID string + selector string + wantErr bool +} + +var ( + mockAccountID = "123456" + mockCampaignID = "100000" + mockVariationID = "200000" + mockModificationID = "300000" + mockSelector = "document.querySelector('main')" +) + +func TestCheckWorkingDirectory(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + want: currentDir, + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CheckWorkingDirectory(tt.workingDir) + if (err != nil) != tt.wantErr { + t.Errorf("CheckWorkingDirectory() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckWorkingDirectory() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCheckGlobalCodeDirectory(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + want: currentDir + "/abtasty", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := CheckGlobalCodeDirectory(tt.workingDir) + if (err != nil) != tt.wantErr { + t.Errorf("CheckGlobalCodeDirectory() error = %v, wantErr %v", err, tt.wantErr) + return + } + if got != tt.want { + t.Errorf("CheckGlobalCodeDirectory() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestAccountGlobalCodeDirectory(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: mockAccountID, + want: currentDir + "/abtasty/" + mockAccountID + "/accountGlobalCode.js", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: mockAccountID, + want: "", + wantErr: true, + }, + } + + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, err := AccountGlobalCodeDirectory(tt.workingDir, tt.accountID, tt.code, true) + if (err != nil) != tt.wantErr { + t.Errorf("AccountGlobalCodeDirectory() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("AccountGlobalCodeDirectory() = %v, want %v", got, tt.want) + } + }) + } +} + +func TestCampaignGlobalCodeDirectory(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: "123456", + campaignID: "100000", + want: currentDir + "/abtasty/" + mockAccountID + "/" + mockCampaignID + "/campaignGlobalCode.js", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: "123456", + campaignID: "100000", + want: "", + wantErr: true, + }, + } + + for i, tt := range tests { + if i == 0 { + t.Run(tt.name, func(t *testing.T) { + got, err := CampaignGlobalCodeDirectory(tt.workingDir, tt.accountID, tt.campaignID, tt.code, true) + if (err != nil) != tt.wantErr { + t.Errorf("CampaignGlobalCodeDirectory() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("CampaignGlobalCodeDirectory() = %v, want %v", got, tt.want) + } + }) + + } + } +} + +func TestVariationGlobalCodeDirectoryJS(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + want: currentDir + "/abtasty/" + mockAccountID + "/" + mockCampaignID + "/" + mockVariationID + "/variationGlobalCode.js", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + code: "console.log('Hello, World!')", // Content of JavaScript file + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + want: "", + wantErr: true, + }, + } + + for i, tt := range tests { + if i == 0 { + t.Run(tt.name, func(t *testing.T) { + got, err := VariationGlobalCodeDirectoryJS(tt.workingDir, tt.accountID, tt.campaignID, tt.variationID, tt.code, true) + if (err != nil) != tt.wantErr { + t.Errorf("VariationGlobalCodeDirectoryJS() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("VariationGlobalCodeDirectoryJS() = %v, want %v", got, tt.want) + } + }) + + } + } +} + +func TestVariationGlobalCodeDirectoryCSS(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + code: ".id{ \"color\" : black}", + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + want: currentDir + "/abtasty/" + mockAccountID + "/" + mockCampaignID + "/" + mockVariationID + "/variationGlobalCode.css", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + code: ".id{ \"color\" : black}", + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + want: "", + wantErr: true, + }, + } + + for i, tt := range tests { + if i == 0 { + t.Run(tt.name, func(t *testing.T) { + got, err := VariationGlobalCodeDirectoryCSS(tt.workingDir, tt.accountID, tt.campaignID, tt.variationID, tt.code, true) + if (err != nil) != tt.wantErr { + t.Errorf("VariationGlobalCodeDirectoryCSS() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("VariationGlobalCodeDirectoryCSS() = %v, want %v", got, tt.want) + } + }) + + } + } +} + +func TestModificationCodeDirectory(t *testing.T) { + currentDir, err := os.Getwd() + if err != nil { + t.Fatalf("Failed to get current working directory: %v", err) + } + + tests := []TestStruct{ + { + name: "ExistingDirectory", + workingDir: currentDir, + code: "console.log('Hello, World!')", + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + modificationID: mockModificationID, + selector: mockSelector, + want: currentDir + "/abtasty/" + mockAccountID + "/" + mockCampaignID + "/" + mockVariationID + "/" + mockModificationID + "/element.js", + wantErr: false, + }, + { + name: "NonExistingDirectory", + workingDir: "/path/to/nonexistent/directory", + code: "console.log('Hello, World!')", + accountID: mockAccountID, + campaignID: mockCampaignID, + variationID: mockVariationID, + modificationID: mockModificationID, + selector: mockSelector, + want: "", + wantErr: true, + }, + } + + for i, tt := range tests { + if i == 0 { + t.Run(tt.name, func(t *testing.T) { + got, err := ModificationCodeDirectory(tt.workingDir, tt.accountID, tt.campaignID, tt.variationID, tt.modificationID, tt.selector, []byte(tt.code), true) + if (err != nil) != tt.wantErr { + t.Errorf("ModificationCodeDirectory() error = %v, wantErr %v", err, tt.wantErr) + } + if got != tt.want { + t.Errorf("ModificationCodeDirectory() = %v, want %v", got, tt.want) + } + }) + + } + } +} + +func TestAddHeaderSelectorComment(t *testing.T) { + fileCode := AddHeaderSelectorComment("example selector", "console.log('Hello World !')") + fileContent := []byte("/* Selector: example selector */\nconsole.log('Hello World !')") + assert.Equal(t, fileContent, fileCode) +} diff --git a/utils/config/config_test.go b/utils/config/config_test.go new file mode 100644 index 0000000..3738c39 --- /dev/null +++ b/utils/config/config_test.go @@ -0,0 +1,279 @@ +package config + +import ( + "errors" + "fmt" + "log" + "os" + "testing" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/stretchr/testify/assert" +) + +var ( + product = "test_product" + username = "test_user" + clientID = "client_id" + clientSecret = "client_secret" + accessToken = "access_token" + refreshToken = "refresh_token" + scope = "scope" + accountID = "account_id" + accountEnvID = "account_environment_id" +) +var authResponse = models.TokenResponse{ + AccessToken: accessToken, + RefreshToken: refreshToken, + Scope: scope, +} + +func TestMain(m *testing.M) { + + currentDir, err := os.Getwd() + if err != nil { + log.Fatalf("Failed to get current working directory: %v", err) + } + + homeDir, err := os.UserHomeDir() + if err != nil { + log.Fatalf("Failed to get user home directory: %v", err) + } + + if _, err := os.Stat(homeDir + "/.flagship/credentials/" + product); errors.Is(err, os.ErrNotExist) { + os.MkdirAll(homeDir+"/.flagship/credentials/"+product, os.ModePerm) + } + + defer os.RemoveAll(currentDir + "/abtasty") + defer os.RemoveAll(homeDir + "/.flagship/credentials/" + product) + + m.Run() +} + +func TestCheckABTastyHomeDirectory(t *testing.T) { + homeDir, err := os.UserHomeDir() + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + abtastyHome, err := CheckABTastyHomeDirectory() + if err != nil { + t.Errorf("CheckABTastyHomeDirectory() error = %v", err) + } + + assert.Equal(t, homeDir, abtastyHome) + assert.Equal(t, homeDir+"/.flagship/credentials/"+utils.FEATURE_EXPERIMENTATION, abtastyHome+"/.flagship/credentials/"+utils.FEATURE_EXPERIMENTATION) + assert.Equal(t, homeDir+"/.flagship/credentials/"+utils.WEB_EXPERIMENTATION, abtastyHome+"/.flagship/credentials/"+utils.WEB_EXPERIMENTATION) + assert.Equal(t, homeDir+"/.flagship/credentials/"+product, abtastyHome+"/.flagship/credentials/"+product) + +} + +func TestCredentialPath(t *testing.T) { + + homeDir, err := os.UserHomeDir() + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + filepath, err := CredentialPath(product, username) + if err != nil { + t.Errorf("CredentialPath() error = %v", err) + } + + expectedPath := homeDir + "/.flagship/credentials/" + product + "/" + username + ".yaml" + assert.Equal(t, expectedPath, filepath) + +} + +func TestGetUsernames(t *testing.T) { + + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Errorf("GetUsernames() error = %v", err) + } + + fileNames, err := GetUsernames(product) + if err != nil { + t.Errorf("GetUsernames() error = %v", err) + } + + if len(fileNames) != 1 || fileNames[0] != "test_user" { + t.Errorf("GetUsernames() returned unexpected file names: %v", fileNames) + } +} + +func TestCreateAuthFile(t *testing.T) { + + homeDir, err := os.UserHomeDir() + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + err = CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + fileContent, err := os.ReadFile(homeDir + "/.flagship/credentials/" + product + "/" + username + ".yaml") + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + expectedContent := fmt.Sprintf(`client_id: %s +client_secret: %s +refresh_token: %s +scope: %s +token: %s +username: %s +`, clientID, clientSecret, refreshToken, scope, accessToken, username) + + assert.Equal(t, expectedContent, string(fileContent)) + +} + +func TestReadAuth(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + v, err := ReadAuth(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, v.GetString("client_id"), clientID) + assert.Equal(t, v.GetString("client_secret"), clientSecret) + assert.Equal(t, v.GetString("username"), username) + assert.Equal(t, v.GetString("token"), authResponse.AccessToken) + assert.Equal(t, v.GetString("refresh_token"), authResponse.RefreshToken) +} + +func TestSelectAuth(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + err = SelectAuth(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + filepath, err := CredentialPath(product, utils.HOME_CLI) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + yamlFile, err := os.ReadFile(filepath) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, string(yamlFile), "current_used_credential: test_user\n") +} + +func TestSetAccountID(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + err = SelectAuth(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + err = SetAccountID(product, accountID) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + filepath, err := CredentialPath(product, utils.HOME_CLI) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + yamlFile, err := os.ReadFile(filepath) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, string(yamlFile), "account_id: account_id\ncurrent_used_credential: test_user\n") +} + +func TestSetAccountEnvironmentID(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + err = SelectAuth(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + err = SetAccountEnvID(product, accountEnvID) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + filepath, err := CredentialPath(product, utils.HOME_CLI) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + yamlFile, err := os.ReadFile(filepath) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, string(yamlFile), "account_environment_id: account_environment_id\ncurrent_used_credential: test_user\n") +} + +func TestReadCredentialsFromFile(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + filepath, err := CredentialPath(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + v, err := ReadCredentialsFromFile(filepath) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, v.GetString("client_id"), clientID) + assert.Equal(t, v.GetString("client_secret"), clientSecret) + assert.Equal(t, v.GetString("username"), username) + assert.Equal(t, v.GetString("token"), authResponse.AccessToken) + assert.Equal(t, v.GetString("refresh_token"), authResponse.RefreshToken) +} + +func TestRewriteToken(t *testing.T) { + err := CreateAuthFile(product, username, clientID, clientSecret, models.TokenResponse{}) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + err = RewriteToken(product, username, authResponse) + if err != nil { + t.Fatalf("Failed to get user home directory: %v", err) + } + + v, err := ReadAuth(product, username) + if err != nil { + t.Fatalf("Failed to read file: %v", err) + } + + assert.Equal(t, v.GetString("client_id"), clientID) + assert.Equal(t, v.GetString("client_secret"), clientSecret) + assert.Equal(t, v.GetString("username"), username) + assert.Equal(t, v.GetString("token"), authResponse.AccessToken) + assert.Equal(t, v.GetString("refresh_token"), authResponse.RefreshToken) +} diff --git a/utils/config/default.go b/utils/config/default.go index ff2791f..291f696 100644 --- a/utils/config/default.go +++ b/utils/config/default.go @@ -5,7 +5,7 @@ import "github.com/flagship-io/flagship/cmd/version" const ( OutputFormat = "table" GrantType = "client_credentials" - Expiration = 86400 + Expiration = 43200 Scope = "*" ClientID = "clientID" ClientSecret = "clientSecret" diff --git a/utils/const.go b/utils/const.go index 1061db5..362adfe 100644 --- a/utils/const.go +++ b/utils/const.go @@ -1,19 +1,51 @@ package utils -import "os" +import ( + "log" + "os" +) -func GetHost() string { - if os.Getenv("STAGING") == "true" { +func GetFeatureExperimentationHost() string { + if os.Getenv("FS_STAGING") == "true" { return "https://staging-api.flagship.io" } return "https://api.flagship.io" } -func GetHostAuth() string { - if os.Getenv("STAGING") == "true" { +func GetWebExperimentationHost() string { + if os.Getenv("FS_STAGING") == "true" { + return "https://staging-api.abtasty.com/api" + } + + return "https://api.abtasty.com/api" +} + +func GetHostFeatureExperimentationAuth() string { + if os.Getenv("FS_STAGING") == "true" { return "https://staging-auth.flagship.io" } return "https://auth.flagship.io" } + +func GetHostWebExperimentationAuth() string { + if os.Getenv("FS_STAGING") == "true" { + return "https://staging-api-auth.abtasty.com" + } + + return "https://api-auth.abtasty.com" +} + +func DefaultGlobalCodeWorkingDir() string { + wdDir, err := os.Getwd() + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + return wdDir +} + +const FEATURE_EXPERIMENTATION = "fe" +const WEB_EXPERIMENTATION = "we" +const HOME_CLI = ".cli" diff --git a/utils/format.go b/utils/format.go index 1bc00ca..4b5fc15 100644 --- a/utils/format.go +++ b/utils/format.go @@ -23,7 +23,7 @@ func FormatItem[T any](columns []string, item T, outputFormat string, w io.Write if outputFormat == "json" { projectJSON, err := json.Marshal(item) if err != nil { - log.Fatalf("%s\n", err) + log.Fatalf("error occurred: %s", err) } fmt.Fprintln(w, string(projectJSON)) return @@ -32,7 +32,7 @@ func FormatItem[T any](columns []string, item T, outputFormat string, w io.Write if outputFormat == "json-pretty" { projectJSON, err := json.MarshalIndent(item, "", " ") if err != nil { - log.Fatalf("%s\n", err) + log.Fatalf("error occurred: %s", err) } fmt.Fprintln(w, string(projectJSON)) return diff --git a/utils/functions.go b/utils/functions.go index f5c1932..67e769c 100644 --- a/utils/functions.go +++ b/utils/functions.go @@ -3,11 +3,12 @@ package utils import ( "bytes" "fmt" + "os" "github.com/spf13/cobra" ) -type HTTPListResponse[T any] struct { +type HTTPListResponseFE[T any] struct { Items []T `json:"items"` CurrentItemsCount int `json:"current_items_count"` CurrentPage int `json:"current_page"` @@ -16,6 +17,18 @@ type HTTPListResponse[T any] struct { LastPage int `json:"last_page"` } +type HTTPListResponseWE[T any] struct { + Data []T `json:"_data"` + Pagination Pagination `json:"_pagination"` +} + +type Pagination struct { + Total int `json:"_total"` + Pages int `json:"_pages"` + Page int `json:"_page"` + MaxPerPage int `json:"_max_per_page"` +} + func ExecuteCommand(cmd *cobra.Command, args ...string) (output string, err error) { buf := new(bytes.Buffer) cmd.SetOut(buf) @@ -24,8 +37,21 @@ func ExecuteCommand(cmd *cobra.Command, args ...string) (output string, err erro err = cmd.Execute() if err != nil { - fmt.Println(err) + fmt.Fprintf(os.Stderr, "error occurred: %s", err) + } return buf.String(), err } + +func CheckSingleFlag(bool1, bool2 bool) bool { + count := 0 + if bool1 { + count++ + } + if bool2 { + count++ + } + + return count == 1 +} diff --git a/utils/functions_test.go b/utils/functions_test.go new file mode 100644 index 0000000..6d286d0 --- /dev/null +++ b/utils/functions_test.go @@ -0,0 +1,26 @@ +package utils + +import ( + "fmt" + "testing" + + "github.com/spf13/cobra" +) + +func TestExecuteCommand(t *testing.T) { + mockCmd := &cobra.Command{ + Run: func(cmd *cobra.Command, args []string) { + fmt.Fprintln(cmd.OutOrStdout(), "Hello, World!") + }, + } + + output, err := ExecuteCommand(mockCmd) + if err != nil { + t.Errorf("ExecuteCommand() error = %v", err) + } + + expectedOutput := "Hello, World!\n" + if output != expectedOutput { + t.Errorf("ExecuteCommand() returned unexpected output. Got: %s, Want: %s", output, expectedOutput) + } +} diff --git a/utils/httpRequest/campaign.go b/utils/httpRequest/campaign.go deleted file mode 100644 index c19c55f..0000000 --- a/utils/httpRequest/campaign.go +++ /dev/null @@ -1,45 +0,0 @@ -package httprequest - -import ( - "encoding/json" - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListCampaign() ([]models.Campaign, error) { - return HTTPGetAllPages[models.Campaign](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns") -} - -func HTTPGetCampaign(id string) (models.Campaign, error) { - return HTTPGetItem[models.Campaign](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns/" + id) -} - -func HTTPCreateCampaign(data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns", []byte(data)) -} - -func HTTPEditCampaign(id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+id, []byte(data)) -} - -func HTTPSwitchCampaign(id, state string) error { - campaignSwitchRequest := models.CampaignSwitchRequest{ - State: state, - } - - campaignSwitchRequestJSON, err := json.Marshal(campaignSwitchRequest) - if err != nil { - return err - } - - _, err = HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+id+"/toggle", campaignSwitchRequestJSON) - return err -} - -func HTTPDeleteCampaign(id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+id, nil) - return err -} diff --git a/utils/httpRequest/flag.go b/utils/httpRequest/flag.go deleted file mode 100644 index 51561c9..0000000 --- a/utils/httpRequest/flag.go +++ /dev/null @@ -1,30 +0,0 @@ -package httprequest - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListFlag() ([]models.Flag, error) { - return HTTPGetAllPages[models.Flag](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/flags") -} - -func HTTPGetFlag(id string) (models.Flag, error) { - return HTTPGetItem[models.Flag](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/flags/" + id) -} - -func HTTPCreateFlag(data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags", []byte(data)) -} - -func HTTPEditFlag(id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags/"+id, []byte(data)) -} - -func HTTPDeleteFlag(id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags/"+id, nil) - return err -} diff --git a/utils/httpRequest/goal.go b/utils/httpRequest/goal.go deleted file mode 100644 index 58fbf40..0000000 --- a/utils/httpRequest/goal.go +++ /dev/null @@ -1,30 +0,0 @@ -package httprequest - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListGoal() ([]models.Goal, error) { - return HTTPGetAllPages[models.Goal](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/goals") -} - -func HTTPGetGoal(id string) (models.Goal, error) { - return HTTPGetItem[models.Goal](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/goals/" + id) -} - -func HTTPCreateGoal(data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals", []byte(data)) -} - -func HTTPEditGoal(id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals/"+id, []byte(data)) -} - -func HTTPDeleteGoal(id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals/"+id, nil) - return err -} diff --git a/utils/httpRequest/panic.go b/utils/httpRequest/panic.go deleted file mode 100644 index 6a62740..0000000 --- a/utils/httpRequest/panic.go +++ /dev/null @@ -1,19 +0,0 @@ -package httprequest - -import ( - "encoding/json" - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPUpdatePanic(panicStatus string) ([]byte, error) { - panicRequestJSON, err := json.Marshal(models.PanicRequest{Panic: panicStatus}) - if err != nil { - return nil, err - } - resp, err := HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/panic", panicRequestJSON) - return resp, err -} diff --git a/utils/httpRequest/panic_test.go b/utils/httpRequest/panic_test.go deleted file mode 100644 index 432bb47..0000000 --- a/utils/httpRequest/panic_test.go +++ /dev/null @@ -1,14 +0,0 @@ -package httprequest - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestHTTPUpdatePanic(t *testing.T) { - - _, err := HTTPUpdatePanic("active") - - assert.Nil(t, err) -} diff --git a/utils/httpRequest/project.go b/utils/httpRequest/project.go deleted file mode 100644 index 3aa0d3e..0000000 --- a/utils/httpRequest/project.go +++ /dev/null @@ -1,45 +0,0 @@ -package httprequest - -import ( - "encoding/json" - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListProject() ([]models.Project, error) { - return HTTPGetAllPages[models.Project](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/projects") -} - -func HTTPGetProject(id string) (models.Project, error) { - return HTTPGetItem[models.Project](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/projects/" + id) -} - -func HTTPCreateProject(data []byte) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects", data) -} - -func HTTPEditProject(id string, data []byte) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+id, data) -} - -func HTTPSwitchProject(id, state string) error { - projectRequest := models.ProjectSwitchRequest{ - State: state, - } - - projectRequestJSON, err := json.Marshal(projectRequest) - if err != nil { - return err - } - - _, err = HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+id+"/toggle", projectRequestJSON) - return err -} - -func HTTPDeleteProject(id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+id, nil) - return err -} diff --git a/utils/httpRequest/request.go b/utils/httpRequest/request.go deleted file mode 100644 index de469d0..0000000 --- a/utils/httpRequest/request.go +++ /dev/null @@ -1,158 +0,0 @@ -package httprequest - -import ( - "bytes" - "compress/gzip" - "encoding/json" - "fmt" - "io" - "log" - "net/http" - "os" - "strings" - "time" - - "github.com/flagship-io/flagship/utils/config" - "github.com/spf13/viper" -) - -var UserAgent string - -func regenerateToken(configName string) { - gt := viper.GetString("grant_type") - sc := viper.GetString("scope") - ex := viper.GetInt("expiration") - - if gt == "" { - gt = config.GrantType - } - - if sc == "" { - sc = config.Scope - } - - if ex == 0 { - ex = config.Expiration - } - - token, err := HTTPCreateToken(viper.GetString("client_id"), viper.GetString("client_secret"), gt, sc, ex) - - if err != nil { - log.Fatalf("%s", err) - } - if token == "" { - log.Fatal("client_id or client_secret not valid") - } else { - fmt.Fprintln(os.Stdout, "Token generated successfully") - config.WriteToken(configName, token) - } -} - -var c = http.Client{Timeout: time.Duration(10) * time.Second} -var counter = false - -type PageResult struct { - Items json.RawMessage `json:"items"` - TotalCount int `json:"total_count"` -} - -func HTTPRequest(method string, resource string, body []byte) ([]byte, error) { - var bodyIO io.Reader = nil - if body != nil { - bodyIO = bytes.NewBuffer(body) - } - - req, err := http.NewRequest(method, resource, bodyIO) - if err != nil { - log.Panicf("error occurred on request creation: %v", err) - } - - if !strings.Contains(resource, "token") && viper.GetString("account_id") == "" && viper.GetString("account_environment_id") == "" { - log.Fatalf("account_id or account_environment_id required, Please configure your CLI") - } - - if strings.Contains(resource, "token") && viper.GetString("client_id") == "" && viper.GetString("client_secret") == "" { - log.Fatalf("client_id or client_secret required, Please configure your CLI") - } - - if !strings.Contains(resource, "token") && viper.GetString("token") == "" { - regenerateToken(viper.GetString("current_used_configuration")) - } - - req.Header.Add("Accept", `*/*`) - req.Header.Add("Authorization", "Bearer "+viper.GetString("token")) - req.Header.Add("Accept-Encoding", `gzip, deflate, br`) - req.Header.Set("User-Agent", UserAgent) - - if body != nil { - req.Header.Add("Content-Type", `application/json`) - } - - resp, err := c.Do(req) - if err != nil { - return nil, err - } - defer resp.Body.Close() - - var reader io.ReadCloser - switch resp.Header.Get("Content-Encoding") { - case "gzip": - reader, err = gzip.NewReader(resp.Body) - if err != nil { - return nil, err - } - defer reader.Close() - default: - reader = resp.Body - } - respBody, err := io.ReadAll(reader) - if err != nil { - return nil, err - } - - if (resp.StatusCode == 403 || resp.StatusCode == 401) && !counter { - counter = true - regenerateToken(viper.GetString("current_used_configuration")) - return HTTPRequest(method, resource, body) - } - return respBody, err -} - -func HTTPGetItem[T any](resource string) (T, error) { - var result T - respBody, err := HTTPRequest(http.MethodGet, resource, nil) - if err != nil { - return result, err - } - err = json.Unmarshal(respBody, &result) - return result, err -} - -func HTTPGetAllPages[T any](resource string) ([]T, error) { - currentPage := 1 - results := []T{} - for { - respBody, err := HTTPRequest(http.MethodGet, fmt.Sprintf("%s?_page=%d&_max_per_page=100", resource, currentPage), nil) - if err != nil { - return nil, err - } - pageResult := &PageResult{} - err = json.Unmarshal(respBody, pageResult) - if err != nil { - return nil, err - } - - typedItems := []T{} - err = json.Unmarshal(pageResult.Items, &typedItems) - if err != nil { - return nil, err - } - results = append(results, typedItems...) - - if len(results) >= pageResult.TotalCount || len(pageResult.Items) == 0 { - break - } - currentPage++ - } - return results, nil -} diff --git a/utils/httpRequest/request_test.go b/utils/httpRequest/request_test.go deleted file mode 100644 index b458d9f..0000000 --- a/utils/httpRequest/request_test.go +++ /dev/null @@ -1,62 +0,0 @@ -package httprequest - -import ( - "encoding/json" - "net/http" - "testing" - - "github.com/spf13/viper" - "github.com/stretchr/testify/assert" -) - -type TestRequest struct { - Name string `json:"name"` -} - -func TestHTTPRequestGet(t *testing.T) { - - var result TestRequest - - testRequest := TestRequest{ - Name: "TestName", - } - testRequestJson, _ := json.Marshal(testRequest) - - respBody, err := HTTPRequest(http.MethodGet, "serverURLGet", testRequestJson) - - assert.NotNil(t, respBody) - assert.Nil(t, err) - - json.Unmarshal(respBody, &result) - - assert.Equal(t, "TestName", result.Name) -} - -func TestHTTPGetItem(t *testing.T) { - - result, err := HTTPGetItem[TestRequest]("serverURLGet") - - assert.Nil(t, err) - assert.NotNil(t, result) - - assert.Equal(t, "TestName", result.Name) -} - -func TestHTTPGetAllPages(t *testing.T) { - - result, err := HTTPGetAllPages[TestRequest]("serverURLList") - - assert.Nil(t, err) - assert.NotNil(t, result) - - assert.Equal(t, "TestName", result[0].Name) - assert.Equal(t, "TestName1", result[1].Name) -} - -func TestRegenerateToken(t *testing.T) { - - regenerateToken("test_configuration") - - assert.Equal(t, viper.IsSet("token"), true) - assert.Equal(t, viper.GetString("token"), "access_token") -} diff --git a/utils/httpRequest/targeting_key.go b/utils/httpRequest/targeting_key.go deleted file mode 100644 index 269011e..0000000 --- a/utils/httpRequest/targeting_key.go +++ /dev/null @@ -1,30 +0,0 @@ -package httprequest - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListTargetingKey() ([]models.TargetingKey, error) { - return HTTPGetAllPages[models.TargetingKey](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/targeting_keys") -} - -func HTTPGetTargetingKey(id string) (models.TargetingKey, error) { - return HTTPGetItem[models.TargetingKey](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/targeting_keys/" + id) -} - -func HTTPCreateTargetingKey(data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys", []byte(data)) -} - -func HTTPEditTargetingKey(id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys/"+id, []byte(data)) -} - -func HTTPDeleteTargetingKey(id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys/"+id, nil) - return err -} diff --git a/utils/httpRequest/token.go b/utils/httpRequest/token.go deleted file mode 100644 index 151378b..0000000 --- a/utils/httpRequest/token.go +++ /dev/null @@ -1,41 +0,0 @@ -package httprequest - -import ( - "encoding/json" - "net/http" - "strconv" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPCreateToken(client_id, client_secret, grant_type, scope string, expiration int) (string, error) { - var authenticationResponse models.TokenResponse - authRequest := models.TokenRequest{ - ClientID: client_id, - ClientSecret: client_secret, - Scope: scope, - GrantType: grant_type, - } - authRequestJSON, err := json.Marshal(authRequest) - if err != nil { - return "", err - } - - respBody, err := HTTPRequest(http.MethodPost, utils.GetHostAuth()+"/"+viper.GetString("account_id")+"/token?expires_in="+strconv.Itoa(expiration), authRequestJSON) - if err != nil { - return "", err - } - - err = json.Unmarshal(respBody, &authenticationResponse) - if err != nil { - return "", err - } - - return authenticationResponse.AccessToken, err -} - -func HTTPCheckToken(token string) (models.Token, error) { - return HTTPGetItem[models.Token](utils.GetHostAuth() + "/token?access_token=" + token) -} diff --git a/utils/httpRequest/token_test.go b/utils/httpRequest/token_test.go deleted file mode 100644 index 697a523..0000000 --- a/utils/httpRequest/token_test.go +++ /dev/null @@ -1,29 +0,0 @@ -package httprequest - -import ( - "testing" - - "github.com/stretchr/testify/assert" -) - -func TestHTTPCheckToken(t *testing.T) { - - respBody, err := HTTPCheckToken("token") - - assert.NotNil(t, respBody) - assert.Nil(t, err) - - assert.Equal(t, "client_id", respBody.ClientID) - assert.Equal(t, "account_id", respBody.AccountID) - assert.Equal(t, 0, respBody.ExpiresIn) - assert.Equal(t, "*", respBody.Scope) -} - -func TestHTTPCreateToken(t *testing.T) { - respBody, err := HTTPCreateToken("client_id", "client_secret", "client_credentials", "*", 86400) - - assert.NotNil(t, respBody) - assert.Nil(t, err) - - assert.Equal(t, "access_token", respBody) -} diff --git a/utils/httpRequest/user.go b/utils/httpRequest/user.go deleted file mode 100644 index bbe1bf8..0000000 --- a/utils/httpRequest/user.go +++ /dev/null @@ -1,23 +0,0 @@ -package httprequest - -import ( - "net/http" - "net/url" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListUsers() ([]models.User, error) { - return HTTPGetAllPages[models.User](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/users") -} - -func HTTPBatchUpdateUsers(data string) ([]byte, error) { - return HTTPRequest(http.MethodPut, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/users", []byte(data)) -} - -func HTTPDeleteUsers(email string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/users?emails[]="+url.QueryEscape(email), nil) - return err -} diff --git a/utils/httpRequest/variation.go b/utils/httpRequest/variation.go deleted file mode 100644 index 5a6da0e..0000000 --- a/utils/httpRequest/variation.go +++ /dev/null @@ -1,30 +0,0 @@ -package httprequest - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListVariation(campaignID, variationGroupID string) ([]models.Variation, error) { - return HTTPGetAllPages[models.Variation](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns/" + campaignID + "/variation_groups/" + variationGroupID + "/variations") -} - -func HTTPGetVariation(campaignID, variationGroupID, id string) (models.Variation, error) { - return HTTPGetItem[models.Variation](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns/" + campaignID + "/variation_groups/" + variationGroupID + "/variations/" + id) -} - -func HTTPCreateVariation(campaignID, variationGroupID, data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", []byte(data)) -} - -func HTTPEditVariation(campaignID, variationGroupID, id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+id, []byte(data)) -} - -func HTTPDeleteVariation(campaignID, variationGroupID, id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+id, nil) - return err -} diff --git a/utils/httpRequest/variation_group.go b/utils/httpRequest/variation_group.go deleted file mode 100644 index f8d3e98..0000000 --- a/utils/httpRequest/variation_group.go +++ /dev/null @@ -1,30 +0,0 @@ -package httprequest - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/spf13/viper" -) - -func HTTPListVariationGroup(campaignID string) ([]models.VariationGroup, error) { - return HTTPGetAllPages[models.VariationGroup](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns/" + campaignID + "/variation_groups") -} - -func HTTPGetVariationGroup(campaignID, id string) (models.VariationGroup, error) { - return HTTPGetItem[models.VariationGroup](utils.GetHost() + "/v1/accounts/" + viper.GetString("account_id") + "/account_environments/" + viper.GetString("account_environment_id") + "/campaigns/" + campaignID + "/variation_groups/" + id) -} - -func HTTPCreateVariationGroup(campaignID, data string) ([]byte, error) { - return HTTPRequest(http.MethodPost, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups", []byte(data)) -} - -func HTTPEditVariationGroup(campaignID, id, data string) ([]byte, error) { - return HTTPRequest(http.MethodPatch, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+id, []byte(data)) -} - -func HTTPDeleteVariationGroup(campaignID, id string) error { - _, err := HTTPRequest(http.MethodDelete, utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+id, nil) - return err -} diff --git a/utils/http_request/common/request.go b/utils/http_request/common/request.go new file mode 100644 index 0000000..d6b2196 --- /dev/null +++ b/utils/http_request/common/request.go @@ -0,0 +1,260 @@ +package common + +import ( + "bytes" + "compress/gzip" + "encoding/json" + "errors" + "fmt" + "io" + "log" + "net/http" + "reflect" + "regexp" + "strings" + "time" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" +) + +var UserAgent string + +var c = http.Client{Timeout: time.Duration(10) * time.Second} +var counter = false + +type PageResultFE struct { + Items json.RawMessage `json:"items"` + TotalCount int `json:"total_count"` +} + +type ResourceRequest struct { + AccountID string `mapstructure:"account_id"` + AccountEnvironmentID string `mapstructure:"account_environment_id"` +} + +func (c *ResourceRequest) Init(cL *RequestConfig) { + c.AccountEnvironmentID = cL.AccountEnvironmentID + c.AccountID = cL.AccountID +} + +type PageResultWE struct { + Data json.RawMessage `json:"_data"` + Pagination PaginationWE `json:"_pagination"` +} + +type PaginationWE struct { + Total int `json:"_total"` + Pages int `json:"_pages"` + Page int `json:"_page"` + MaxPerPage int `json:"_max_per_page"` +} + +type RequestConfig struct { + Product string + Username string `mapstructure:"username"` + ClientID string `mapstructure:"client_id"` + ClientSecret string `mapstructure:"client_secret"` + AccountID string `mapstructure:"account_id"` + AccountEnvironmentID string `mapstructure:"account_environment_id"` + Token string `mapstructure:"token"` + Scope string `mapstructure:"scope"` + RefreshToken string `mapstructure:"refresh_token"` + CurrentUsedCredential string `mapstructure:"current_used_credential"` + OutputFormat string `mapstructure:"output_format"` +} + +var cred RequestConfig + +func Init(credL RequestConfig) { + cred = credL +} + +func regenerateToken(product, configName string) { + var authenticationResponse models.TokenResponse + var err error + + if product == utils.FEATURE_EXPERIMENTATION { + authenticationResponse, err = HTTPRefreshTokenFE(cred.ClientID, cred.RefreshToken) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + } else { + authenticationResponse, err = HTTPCreateTokenWE(cred.ClientID, cred.ClientSecret, cred.AccountID) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + } + + if authenticationResponse.AccessToken == "" { + log.Fatal("client_id or client_secret not valid") + } + + cred.RefreshToken = authenticationResponse.RefreshToken + cred.Token = authenticationResponse.AccessToken + err = config.RewriteToken(product, configName, authenticationResponse) + if err != nil { + log.Fatalf("error occurred: %v", err) + } + +} + +func HTTPRequest[T any](method string, url string, body []byte) ([]byte, error) { + var bodyIO io.Reader = nil + if body != nil { + bodyIO = bytes.NewBuffer(body) + } + + var resource T + + resourceType := reflect.TypeOf(resource) + + if resourceType == reflect.TypeOf(feature_experimentation.Goal{}) || resourceType == reflect.TypeOf(feature_experimentation.CampaignFE{}) { + if cred.AccountID == "" || cred.AccountEnvironmentID == "" { + log.Fatalf("account_id or account_environment_id required, Please authenticate your CLI") + } + } + + req, err := http.NewRequest(method, url, bodyIO) + if err != nil { + log.Panicf("error occurred on request creation: %v", err) + } + + if cred.Product == utils.FEATURE_EXPERIMENTATION { + if (cred.Username == "" || cred.AccountID == "") && resourceType != reflect.TypeOf(models.Token{}) { + log.Fatalf("username and account_id required, Please authenticate your CLI") + } + // for resource loader + if resourceType.String() == "resource.ResourceData" && !strings.Contains(url, "token") && (cred.AccountID == "" || cred.AccountEnvironmentID == "") { + log.Fatalf("account_id or account_environment_id required, Please authenticate your CLI") + } + + /* if strings.Contains(url, "token") && cred.ClientID == "" && cred.ClientSecret == "" { + log.Fatalf("client_id or client_secret required, Please authenticate your CLI") + } */ + } + + if cred.Product == utils.WEB_EXPERIMENTATION { + if resourceType != reflect.TypeOf(web_experimentation.AccountWE{}) && !strings.Contains(url, "token") && cred.AccountID == "" { + log.Fatalf("username, account_id required, Please authenticate your CLI") + } + } + + if !strings.Contains(url, "token") && cred.Token == "" { + regenerateToken(cred.Product, cred.CurrentUsedCredential) + } + + req.Header.Add("Accept", `*/*`) + req.Header.Add("Authorization", "Bearer "+cred.Token) + req.Header.Add("Accept-Encoding", `gzip, deflate, br`) + req.Header.Add("Content-Type", "application/json") + req.Header.Set("User-Agent", UserAgent) + + resp, err := c.Do(req) + if err != nil { + return nil, err + } + defer resp.Body.Close() + + var reader io.ReadCloser + switch resp.Header.Get("Content-Encoding") { + case "gzip": + reader, err = gzip.NewReader(resp.Body) + if err != nil { + return nil, err + } + defer reader.Close() + default: + reader = resp.Body + } + + respBody, err := io.ReadAll(reader) + if err != nil { + return nil, err + } + + if (resp.StatusCode == 401) && !counter { + counter = true + regenerateToken(cred.Product, cred.CurrentUsedCredential) + return HTTPRequest[T](method, url, body) + } + + match, _ := regexp.MatchString("4\\d\\d|5\\d\\d", resp.Status) + if match { + err := errors.New(string(respBody)) + return nil, err + } + + return respBody, err +} + +func HTTPGetItem[T any](resource string) (T, error) { + var result T + respBody, err := HTTPRequest[T](http.MethodGet, resource, nil) + if err != nil { + return result, err + } + err = json.Unmarshal(respBody, &result) + return result, err +} + +func HTTPGetAllPagesFE[T any](resource string) ([]T, error) { + currentPage := 1 + results := []T{} + for { + respBody, err := HTTPRequest[T](http.MethodGet, fmt.Sprintf("%s?_page=%d&_max_per_page=100", resource, currentPage), nil) + if err != nil { + return nil, err + } + pageResult := &PageResultFE{} + err = json.Unmarshal(respBody, pageResult) + if err != nil { + return nil, err + } + + typedItems := []T{} + err = json.Unmarshal(pageResult.Items, &typedItems) + if err != nil { + return nil, err + } + results = append(results, typedItems...) + + if len(results) >= pageResult.TotalCount || len(pageResult.Items) == 0 { + break + } + currentPage++ + } + return results, nil +} + +func HTTPGetAllPagesWE[T any](resource string) ([]T, error) { + currentPage := 1 + results := []T{} + for { + respBody, err := HTTPRequest[T](http.MethodGet, fmt.Sprintf("%s?_page=%d&_max_per_page=100", resource, currentPage), nil) + if err != nil { + return nil, err + } + pageResult := &PageResultWE{} + err = json.Unmarshal(respBody, pageResult) + if err != nil { + return nil, err + } + + typedItems := []T{} + err = json.Unmarshal(pageResult.Data, &typedItems) + if err != nil { + return nil, err + } + results = append(results, typedItems...) + + if len(results) >= pageResult.Pagination.Total || len(pageResult.Data) == 0 { + break + } + currentPage++ + } + return results, nil +} diff --git a/utils/http_request/common/token.go b/utils/http_request/common/token.go new file mode 100644 index 0000000..8487492 --- /dev/null +++ b/utils/http_request/common/token.go @@ -0,0 +1,216 @@ +package common + +import ( + "encoding/json" + "net/http" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" +) + +func HTTPRefreshTokenFE(client_id, refresh_token string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + authRequest := models.RefreshTokenRequestFE{ + ClientID: client_id, + GrantType: "refresh_token", + RefreshToken: refresh_token, + } + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.Token](http.MethodPost, utils.GetHostFeatureExperimentationAuth()+"/"+cred.AccountID+"/token", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} + +/* func HTTPRefreshTokenWE(client_id, client_secret, refresh_token string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + authRequest := models.RefreshTokenRequestWE{ + ClientID: client_id, + GrantType: "refresh_token", + RefreshToken: refresh_token, + ClientSecret: client_secret, + } + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.TokenWE](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1"+"/token", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} */ + +func HTTPCreateTokenFE(clientId, clientSecret, accountId string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + authRequest := models.ClientCredentialsRequest{ + ClientID: clientId, + ClientSecret: clientSecret, + Scope: "*", + GrantType: "client_credentials", + } + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.Token](http.MethodPost, utils.GetHostFeatureExperimentationAuth()+"/"+accountId+"/token?expires_in=43200", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} + +func HTTPCreateTokenWE(clientId, clientSecret, accountId string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + authRequest := models.ClientCredentialsRequest{ + ClientID: clientId, + ClientSecret: clientSecret, + GrantType: "client_credentials", + } + + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.Token](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1/token", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} + +/* func HTTPCreateTokenWEAuthorizationCode(client_id, client_secret, code string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + authRequest := models.AuthorizationCodeRequest{ + ClientID: client_id, + ClientSecret: client_secret, + GrantType: "authorization_code", + Code: code, + } + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.TokenWE](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1/token", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} */ + +/* func HTTPCreateTokenWEPassword(client_id, client_secret, username, password, mfaCode string) (models.TokenResponse, error) { + var authenticationResponse models.TokenResponse + var mfaResponse models.MfaRequestWE + var mfmResponse models.MfaRequestWE + + authRequest := models.PasswordRequest{ + ClientID: client_id, + ClientSecret: client_secret, + GrantType: "password", + Username: username, + Password: password, + } + authRequestJSON, err := json.Marshal(authRequest) + if err != nil { + return models.TokenResponse{}, err + } + + mfaRespBody, err := HTTPRequest[models.MfaRequestWE](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1/token", authRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(mfaRespBody, &mfaResponse) + if err != nil { + return models.TokenResponse{}, err + } + + mfmRequest := models.MultiFactorMethodRequestWE{ + GrantType: "multi_factor_methods", + MfaToken: mfaResponse.MfaToken, + MfaMethod: "totp", + } + + mfmRequestJSON, err := json.Marshal(mfmRequest) + if err != nil { + return models.TokenResponse{}, err + } + + mfmRespBody, err := HTTPRequest[models.MfaRequestWE](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1/token", mfmRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(mfmRespBody, &mfmResponse) + if err != nil { + return models.TokenResponse{}, err + } + + mfRequest := models.MultiFactorRequestWE{ + GrantType: "multi_factor", + MfaToken: mfmResponse.MfaToken, + MfaMethod: "totp", + Code: mfaCode, + } + + mfRequestJSON, err := json.Marshal(mfRequest) + if err != nil { + return models.TokenResponse{}, err + } + + respBody, err := HTTPRequest[models.MfaRequestWE](http.MethodPost, utils.GetHostWebExperimentationAuth()+"/v1/token", mfRequestJSON) + if err != nil { + return models.TokenResponse{}, err + } + + err = json.Unmarshal(respBody, &authenticationResponse) + if err != nil { + return models.TokenResponse{}, err + } + + return authenticationResponse, err +} +*/ + +func HTTPCheckTokenFE() (models.Token, error) { + return HTTPGetItem[models.Token](utils.GetHostFeatureExperimentationAuth() + "/token?access_token=" + cred.Token) +} diff --git a/utils/http_request/feature_experimentation/account_environment.go b/utils/http_request/feature_experimentation/account_environment.go new file mode 100644 index 0000000..2891513 --- /dev/null +++ b/utils/http_request/feature_experimentation/account_environment.go @@ -0,0 +1,23 @@ +package feature_experimentation + +import ( + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type AccountEnvironmentFERequester struct { + *common.ResourceRequest +} + +func (a *AccountEnvironmentFERequester) HTTPListAccountEnvironment(accountID string) ([]models.AccountEnvironmentFE, error) { + if accountID == "" { + accountID = a.AccountID + } + + return common.HTTPGetAllPagesFE[models.AccountEnvironmentFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + accountID + "/account_environments") +} + +func (a *AccountEnvironmentFERequester) HTTPGetAccountEnvironment(id string) (models.AccountEnvironmentFE, error) { + return common.HTTPGetItem[models.AccountEnvironmentFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + a.AccountID + "/account_environments/" + id) +} diff --git a/utils/http_request/feature_experimentation/account_environment_test.go b/utils/http_request/feature_experimentation/account_environment_test.go new file mode 100644 index 0000000..b5c6f09 --- /dev/null +++ b/utils/http_request/feature_experimentation/account_environment_test.go @@ -0,0 +1,39 @@ +package feature_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/stretchr/testify/assert" +) + +var accountEnvironmentFERequester = AccountEnvironmentFERequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + +func TestHTTPGetAccountEnvironment(t *testing.T) { + respBody, err := accountEnvironmentFERequester.HTTPGetAccountEnvironment("account_environment_id") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, "account_environment_id", respBody.Id) + assert.Equal(t, "account_environment_name", respBody.Environment) + assert.Equal(t, true, respBody.IsMain) + assert.Equal(t, false, respBody.SingleAssignment) +} + +func TestHTTPListAccountEnvironment(t *testing.T) { + respBody, err := accountEnvironmentFERequester.HTTPListAccountEnvironment("account_id") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, "account_environment_id", respBody[0].Id) + assert.Equal(t, "account_environment_name", respBody[0].Environment) + assert.Equal(t, true, respBody[0].IsMain) + assert.Equal(t, false, respBody[0].SingleAssignment) + + assert.Equal(t, "account_environment_id1", respBody[1].Id) + assert.Equal(t, "account_environment_name1", respBody[1].Environment) + assert.Equal(t, true, respBody[1].IsMain) + assert.Equal(t, false, respBody[1].SingleAssignment) +} diff --git a/utils/http_request/feature_experimentation/campaign.go b/utils/http_request/feature_experimentation/campaign.go new file mode 100644 index 0000000..9c6bb05 --- /dev/null +++ b/utils/http_request/feature_experimentation/campaign.go @@ -0,0 +1,49 @@ +package feature_experimentation + +import ( + "encoding/json" + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type CampaignFERequester struct { + *common.ResourceRequest +} + +func (c *CampaignFERequester) HTTPListCampaign() ([]models.CampaignFE, error) { + return common.HTTPGetAllPagesFE[models.CampaignFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + c.AccountID + "/account_environments/" + c.AccountEnvironmentID + "/campaigns") +} + +func (c *CampaignFERequester) HTTPGetCampaign(id string) (models.CampaignFE, error) { + return common.HTTPGetItem[models.CampaignFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + c.AccountID + "/account_environments/" + c.AccountEnvironmentID + "/campaigns/" + id) +} + +func (c *CampaignFERequester) HTTPCreateCampaign(data string) ([]byte, error) { + return common.HTTPRequest[models.CampaignFE](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+c.AccountID+"/account_environments/"+c.AccountEnvironmentID+"/campaigns", []byte(data)) +} + +func (c *CampaignFERequester) HTTPEditCampaign(id, data string) ([]byte, error) { + return common.HTTPRequest[models.CampaignFE](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+c.AccountID+"/account_environments/"+c.AccountEnvironmentID+"/campaigns/"+id, []byte(data)) +} + +func (c *CampaignFERequester) HTTPSwitchCampaign(id, state string) error { + campaignSwitchRequest := models.CampaignFESwitchRequest{ + State: state, + } + + campaignSwitchRequestJSON, err := json.Marshal(campaignSwitchRequest) + if err != nil { + return err + } + + _, err = common.HTTPRequest[models.CampaignFE](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+c.AccountID+"/account_environments/"+c.AccountEnvironmentID+"/campaigns/"+id+"/toggle", campaignSwitchRequestJSON) + return err +} + +func (c *CampaignFERequester) HTTPDeleteCampaign(id string) error { + _, err := common.HTTPRequest[models.CampaignFE](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+c.AccountID+"/account_environments/"+c.AccountEnvironmentID+"/campaigns/"+id, nil) + return err +} diff --git a/utils/httpRequest/campaign_test.go b/utils/http_request/feature_experimentation/campaign_test.go similarity index 87% rename from utils/httpRequest/campaign_test.go rename to utils/http_request/feature_experimentation/campaign_test.go index 2a8545c..e87c0ba 100644 --- a/utils/httpRequest/campaign_test.go +++ b/utils/http_request/feature_experimentation/campaign_test.go @@ -1,14 +1,16 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) -func TestHTTPGetCampaign(t *testing.T) { +var campaignRequester = CampaignFERequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} - respBody, err := HTTPGetCampaign("testCampaignID") +func TestHTTPGetCampaign(t *testing.T) { + respBody, err := campaignRequester.HTTPGetCampaign("testCampaignID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -21,8 +23,7 @@ func TestHTTPGetCampaign(t *testing.T) { } func TestHTTPListCampaign(t *testing.T) { - - respBody, err := HTTPListCampaign() + respBody, err := campaignRequester.HTTPListCampaign() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -43,7 +44,7 @@ func TestHTTPListCampaign(t *testing.T) { func TestHTTPCreateCampaign(t *testing.T) { dataCampaign := "{\"project_id\":\"testProjectID\",\"name\":\"testCampaignName\",\"description\":\"testCampaignDescription\",\"type\":\"toggle\",\"variation_groups\":[{\"name\":\"variationGroupName\",\"variations\":[{\"name\":\"My variation 1\",\"allocation\":50,\"reference\":true,\"modifications\":{\"value\":{\"color\":\"blue\"}}},{\"name\":\"My variation 2\",\"allocation\":50,\"reference\":false,\"modifications\":{\"value\":{\"color\":\"red\"}}}],\"targeting\":{\"targeting_groups\":[{\"targetings\":[{\"operator\":\"CONTAINS\",\"key\":\"isVIP\",\"value\":\"true\"}]}]}}],\"scheduler\":{\"start_date\":\"2022-02-01 10:00:00\",\"stop_date\":\"2022-02-02 08:00:00\",\"timezone\":\"Europe/Paris\"}}" - respBody, err := HTTPCreateCampaign(dataCampaign) + respBody, err := campaignRequester.HTTPCreateCampaign(dataCampaign) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -55,7 +56,7 @@ func TestHTTPEditCampaign(t *testing.T) { dataCampaign := "{\"project_id\":\"testProjectID1\",\"name\":\"testCampaignName1\",\"description\":\"testCampaignDescription1\",\"type\":\"toggle\",\"variation_groups\":[{\"name\":\"variationGroupName\",\"variations\":[{\"name\":\"My variation 1\",\"allocation\":50,\"reference\":true,\"modifications\":{\"value\":{\"color\":\"blue\"}}},{\"name\":\"My variation 2\",\"allocation\":50,\"reference\":false,\"modifications\":{\"value\":{\"color\":\"red\"}}}],\"targeting\":{\"targeting_groups\":[{\"targetings\":[{\"operator\":\"CONTAINS\",\"key\":\"isVIP\",\"value\":\"true\"}]}]}}],\"scheduler\":{\"start_date\":\"2022-02-01 10:00:00\",\"stop_date\":\"2022-02-02 08:00:00\",\"timezone\":\"Europe/Paris\"}}" - respBody, err := HTTPEditCampaign("testCampaignID", dataCampaign) + respBody, err := campaignRequester.HTTPEditCampaign("testCampaignID", dataCampaign) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -65,14 +66,14 @@ func TestHTTPEditCampaign(t *testing.T) { func TestHTTPDeleteCampaign(t *testing.T) { - err := HTTPDeleteCampaign("testCampaignID") + err := campaignRequester.HTTPDeleteCampaign("testCampaignID") assert.Nil(t, err) } func TestHTTPSwitchCampaign(t *testing.T) { - err := HTTPSwitchCampaign("testCampaignID", "active") + err := campaignRequester.HTTPSwitchCampaign("testCampaignID", "active") assert.Nil(t, err) } diff --git a/utils/http_request/feature_experimentation/flag.go b/utils/http_request/feature_experimentation/flag.go new file mode 100644 index 0000000..e42e979 --- /dev/null +++ b/utils/http_request/feature_experimentation/flag.go @@ -0,0 +1,34 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type FlagRequester struct { + *common.ResourceRequest +} + +func (f *FlagRequester) HTTPListFlag() ([]models.Flag, error) { + return common.HTTPGetAllPagesFE[models.Flag](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + f.AccountID + "/flags") +} + +func (f *FlagRequester) HTTPGetFlag(id string) (models.Flag, error) { + return common.HTTPGetItem[models.Flag](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + f.AccountID + "/flags/" + id) +} + +func (f *FlagRequester) HTTPCreateFlag(data string) ([]byte, error) { + return common.HTTPRequest[models.Flag](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+f.AccountID+"/flags", []byte(data)) +} + +func (f *FlagRequester) HTTPEditFlag(id, data string) ([]byte, error) { + return common.HTTPRequest[models.Flag](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+f.AccountID+"/flags/"+id, []byte(data)) +} + +func (f *FlagRequester) HTTPDeleteFlag(id string) error { + _, err := common.HTTPRequest[models.Flag](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+f.AccountID+"/flags/"+id, nil) + return err +} diff --git a/utils/httpRequest/flag_test.go b/utils/http_request/feature_experimentation/flag_test.go similarity index 73% rename from utils/httpRequest/flag_test.go rename to utils/http_request/feature_experimentation/flag_test.go index eee3b61..ad26314 100644 --- a/utils/httpRequest/flag_test.go +++ b/utils/http_request/feature_experimentation/flag_test.go @@ -1,14 +1,17 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) +var flagRequester = FlagRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + func TestHTTPGetFlag(t *testing.T) { - respBody, err := HTTPGetFlag("testFlagID") + respBody, err := flagRequester.HTTPGetFlag("testFlagID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -19,7 +22,7 @@ func TestHTTPGetFlag(t *testing.T) { func TestHTTPListFlag(t *testing.T) { - respBody, err := HTTPListFlag() + respBody, err := flagRequester.HTTPListFlag() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -35,7 +38,7 @@ func TestHTTPCreateFlag(t *testing.T) { data := "{\"name\":\"testFlagName\", \"type\":\"string\", \"description\":\"testFlagDescription\", \"source\":\"cli\"}" - respBody, err := HTTPCreateFlag(data) + respBody, err := flagRequester.HTTPCreateFlag(data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -47,7 +50,7 @@ func TestHTTPEditFlag(t *testing.T) { data := "{\"name\":\"testFlagName1\",\"type\":\"string\",\"description\":\"testFlagDescription1\",\"source\":\"cli\"}" - respBody, err := HTTPEditFlag("testFlagID", data) + respBody, err := flagRequester.HTTPEditFlag("testFlagID", data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -57,7 +60,7 @@ func TestHTTPEditFlag(t *testing.T) { func TestHTTPDeleteFlag(t *testing.T) { - err := HTTPDeleteFlag("testFlagID") + err := flagRequester.HTTPDeleteFlag("testFlagID") assert.Nil(t, err) } diff --git a/utils/http_request/feature_experimentation/goal.go b/utils/http_request/feature_experimentation/goal.go new file mode 100644 index 0000000..6e301ec --- /dev/null +++ b/utils/http_request/feature_experimentation/goal.go @@ -0,0 +1,34 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type GoalRequester struct { + *common.ResourceRequest +} + +func (g *GoalRequester) HTTPListGoal() ([]models.Goal, error) { + return common.HTTPGetAllPagesFE[models.Goal](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + g.AccountID + "/account_environments/" + g.AccountEnvironmentID + "/goals") +} + +func (g *GoalRequester) HTTPGetGoal(id string) (models.Goal, error) { + return common.HTTPGetItem[models.Goal](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + g.AccountID + "/account_environments/" + g.AccountEnvironmentID + "/goals/" + id) +} + +func (g *GoalRequester) HTTPCreateGoal(data string) ([]byte, error) { + return common.HTTPRequest[models.Flag](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+g.AccountID+"/account_environments/"+g.AccountEnvironmentID+"/goals", []byte(data)) +} + +func (g *GoalRequester) HTTPEditGoal(id, data string) ([]byte, error) { + return common.HTTPRequest[models.Flag](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+g.AccountID+"/account_environments/"+g.AccountEnvironmentID+"/goals/"+id, []byte(data)) +} + +func (g *GoalRequester) HTTPDeleteGoal(id string) error { + _, err := common.HTTPRequest[models.Flag](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+g.AccountID+"/account_environments/"+g.AccountEnvironmentID+"/goals/"+id, nil) + return err +} diff --git a/utils/httpRequest/goal_test.go b/utils/http_request/feature_experimentation/goal_test.go similarity index 72% rename from utils/httpRequest/goal_test.go rename to utils/http_request/feature_experimentation/goal_test.go index c51acb6..bb0752b 100644 --- a/utils/httpRequest/goal_test.go +++ b/utils/http_request/feature_experimentation/goal_test.go @@ -1,14 +1,17 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) +var goalRequester = GoalRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + func TestHTTPGetGoal(t *testing.T) { - respBody, err := HTTPGetGoal("testGoalID") + respBody, err := goalRequester.HTTPGetGoal("testGoalID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -19,7 +22,7 @@ func TestHTTPGetGoal(t *testing.T) { func TestHTTPListGoal(t *testing.T) { - respBody, err := HTTPListGoal() + respBody, err := goalRequester.HTTPListGoal() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -35,7 +38,7 @@ func TestHTTPCreateGoal(t *testing.T) { data := "{\"label\":\"testGoalLabel\", \"type\":\"screenview\", \"operator\":\"contains\", \"value\":\"VIP\"}" - respBody, err := HTTPCreateGoal(data) + respBody, err := goalRequester.HTTPCreateGoal(data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -47,7 +50,7 @@ func TestHTTPEditGoal(t *testing.T) { data := "{\"label\":\"testGoalLabel\", \"type\":\"screenview\", \"operator\":\"contains\", \"value\":\"VIP\"}" - respBody, err := HTTPEditGoal("testGoalID", data) + respBody, err := goalRequester.HTTPEditGoal("testGoalID", data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -57,7 +60,7 @@ func TestHTTPEditGoal(t *testing.T) { func TestHTTPDeleteGoal(t *testing.T) { - err := HTTPDeleteGoal("testGoalID") + err := goalRequester.HTTPDeleteGoal("testGoalID") assert.Nil(t, err) } diff --git a/utils/httpRequest/main_test.go b/utils/http_request/feature_experimentation/main_test.go similarity index 65% rename from utils/httpRequest/main_test.go rename to utils/http_request/feature_experimentation/main_test.go index 191d18e..74a2d5b 100644 --- a/utils/httpRequest/main_test.go +++ b/utils/http_request/feature_experimentation/main_test.go @@ -1,9 +1,13 @@ -package httprequest +package feature_experimentation import ( "testing" - mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/http_request/common" + mockfunction "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + + mockfunction_ "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" ) @@ -12,16 +16,19 @@ func TestMain(m *testing.M) { httpmock.Activate() defer httpmock.DeactivateAndReset() + common.Init(mockfunction_.Auth) + mockfunction.APIProject() mockfunction.APICampaign() + mockfunction.APIAccountEnvironment() mockfunction.APIFlag() mockfunction.APIGoal() mockfunction.APITargetingKey() mockfunction.APIVariationGroup() mockfunction.APIVariation() - mockfunction.APIToken() mockfunction.APIUser() mockfunction.APIPanic() - mockfunction.Request() + mockfunction.APIToken() + m.Run() } diff --git a/utils/http_request/feature_experimentation/panic.go b/utils/http_request/feature_experimentation/panic.go new file mode 100644 index 0000000..79ce6f4 --- /dev/null +++ b/utils/http_request/feature_experimentation/panic.go @@ -0,0 +1,23 @@ +package feature_experimentation + +import ( + "encoding/json" + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type PanicRequester struct { + *common.ResourceRequest +} + +func (p *PanicRequester) HTTPUpdatePanic(panicStatus string) ([]byte, error) { + panicRequestJSON, err := json.Marshal(models.PanicRequest{Panic: panicStatus}) + if err != nil { + return nil, err + } + resp, err := common.HTTPRequest[models.PanicRequest](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+p.AccountID+"/account_environments/"+p.AccountEnvironmentID+"/panic", panicRequestJSON) + return resp, err +} diff --git a/utils/http_request/feature_experimentation/panic_test.go b/utils/http_request/feature_experimentation/panic_test.go new file mode 100644 index 0000000..3f725d7 --- /dev/null +++ b/utils/http_request/feature_experimentation/panic_test.go @@ -0,0 +1,17 @@ +package feature_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/stretchr/testify/assert" +) + +var panicRequester = PanicRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + +func TestHTTPUpdatePanic(t *testing.T) { + + _, err := panicRequester.HTTPUpdatePanic("active") + + assert.Nil(t, err) +} diff --git a/utils/http_request/feature_experimentation/project.go b/utils/http_request/feature_experimentation/project.go new file mode 100644 index 0000000..594683e --- /dev/null +++ b/utils/http_request/feature_experimentation/project.go @@ -0,0 +1,49 @@ +package feature_experimentation + +import ( + "encoding/json" + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type ProjectRequester struct { + *common.ResourceRequest +} + +func (p *ProjectRequester) HTTPListProject() ([]models.Project, error) { + return common.HTTPGetAllPagesFE[models.Project](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + p.AccountID + "/projects") +} + +func (p *ProjectRequester) HTTPGetProject(id string) (models.Project, error) { + return common.HTTPGetItem[models.Project](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + p.AccountID + "/projects/" + id) +} + +func (p *ProjectRequester) HTTPCreateProject(data []byte) ([]byte, error) { + return common.HTTPRequest[models.Project](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+p.AccountID+"/projects", data) +} + +func (p *ProjectRequester) HTTPEditProject(id string, data []byte) ([]byte, error) { + return common.HTTPRequest[models.Project](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+p.AccountID+"/projects/"+id, data) +} + +func (p *ProjectRequester) HTTPSwitchProject(id, state string) error { + projectRequest := models.ProjectSwitchRequest{ + State: state, + } + + projectRequestJSON, err := json.Marshal(projectRequest) + if err != nil { + return err + } + + _, err = common.HTTPRequest[models.Project](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+p.AccountID+"/projects/"+id+"/toggle", projectRequestJSON) + return err +} + +func (p *ProjectRequester) HTTPDeleteProject(id string) error { + _, err := common.HTTPRequest[models.Project](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+p.AccountID+"/projects/"+id, nil) + return err +} diff --git a/utils/httpRequest/project_test.go b/utils/http_request/feature_experimentation/project_test.go similarity index 67% rename from utils/httpRequest/project_test.go rename to utils/http_request/feature_experimentation/project_test.go index 685d0f6..c8b8348 100644 --- a/utils/httpRequest/project_test.go +++ b/utils/http_request/feature_experimentation/project_test.go @@ -1,17 +1,20 @@ -package httprequest +package feature_experimentation import ( "encoding/json" "log" "testing" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) +var projectRequester = ProjectRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + func TestHTTPGetProject(t *testing.T) { - respBody, err := HTTPGetProject("testProjectID") + respBody, err := projectRequester.HTTPGetProject("testProjectID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -22,7 +25,7 @@ func TestHTTPGetProject(t *testing.T) { func TestHTTPListProject(t *testing.T) { - respBody, err := HTTPListProject() + respBody, err := projectRequester.HTTPListProject() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -42,7 +45,7 @@ func TestHTTPCreateProject(t *testing.T) { if err != nil { log.Fatalf("error occurred: %s", err) } - respBody, err := HTTPCreateProject(projectRequestJSON) + respBody, err := projectRequester.HTTPCreateProject(projectRequestJSON) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -58,7 +61,7 @@ func TestHTTPEditProject(t *testing.T) { if err != nil { log.Fatalf("error occurred: %s", err) } - respBody, err := HTTPEditProject("testProjectID", projectRequestJSON) + respBody, err := projectRequester.HTTPEditProject("testProjectID", projectRequestJSON) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -68,14 +71,14 @@ func TestHTTPEditProject(t *testing.T) { func TestHTTPDeleteProject(t *testing.T) { - err := HTTPDeleteProject("testProjectID") + err := projectRequester.HTTPDeleteProject("testProjectID") assert.Nil(t, err) } func TestHTTPSwitchProject(t *testing.T) { - err := HTTPSwitchProject("testProjectID", "active") + err := projectRequester.HTTPSwitchProject("testProjectID", "active") assert.Nil(t, err) } diff --git a/utils/http_request/feature_experimentation/targeting_key.go b/utils/http_request/feature_experimentation/targeting_key.go new file mode 100644 index 0000000..c105f48 --- /dev/null +++ b/utils/http_request/feature_experimentation/targeting_key.go @@ -0,0 +1,34 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type TargetingKeyRequester struct { + *common.ResourceRequest +} + +func (t *TargetingKeyRequester) HTTPListTargetingKey() ([]models.TargetingKey, error) { + return common.HTTPGetAllPagesFE[models.TargetingKey](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + t.AccountID + "/targeting_keys") +} + +func (t *TargetingKeyRequester) HTTPGetTargetingKey(id string) (models.TargetingKey, error) { + return common.HTTPGetItem[models.TargetingKey](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + t.AccountID + "/targeting_keys/" + id) +} + +func (t *TargetingKeyRequester) HTTPCreateTargetingKey(data string) ([]byte, error) { + return common.HTTPRequest[models.TargetingKey](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+t.AccountID+"/targeting_keys", []byte(data)) +} + +func (t *TargetingKeyRequester) HTTPEditTargetingKey(id, data string) ([]byte, error) { + return common.HTTPRequest[models.TargetingKey](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+t.AccountID+"/targeting_keys/"+id, []byte(data)) +} + +func (t *TargetingKeyRequester) HTTPDeleteTargetingKey(id string) error { + _, err := common.HTTPRequest[models.TargetingKey](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+t.AccountID+"/targeting_keys/"+id, nil) + return err +} diff --git a/utils/httpRequest/targeting_key_test.go b/utils/http_request/feature_experimentation/targeting_key_test.go similarity index 67% rename from utils/httpRequest/targeting_key_test.go rename to utils/http_request/feature_experimentation/targeting_key_test.go index 50ca5f8..81e0c52 100644 --- a/utils/httpRequest/targeting_key_test.go +++ b/utils/http_request/feature_experimentation/targeting_key_test.go @@ -1,14 +1,17 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) +var targetingKeyRequester = TargetingKeyRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + func TestHTTPGetTargetingKey(t *testing.T) { - respBody, err := HTTPGetTargetingKey("testTargetingKeyID") + respBody, err := targetingKeyRequester.HTTPGetTargetingKey("testTargetingKeyID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -19,7 +22,7 @@ func TestHTTPGetTargetingKey(t *testing.T) { func TestHTTPListTargetingKey(t *testing.T) { - respBody, err := HTTPListTargetingKey() + respBody, err := targetingKeyRequester.HTTPListTargetingKey() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -35,7 +38,7 @@ func TestHTTPCreateTargetingKey(t *testing.T) { data := "{\"name\":\"testTargetingKeyName\", \"type\":\"string\", \"description\":\"testTargetingKeyDescription\"}" - respBody, err := HTTPCreateTargetingKey(data) + respBody, err := targetingKeyRequester.HTTPCreateTargetingKey(data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -45,7 +48,7 @@ func TestHTTPCreateTargetingKey(t *testing.T) { func TestHTTPEditTargetingKey(t *testing.T) { - respBody, err := HTTPEditTargetingKey("testTargetingKeyID", "testTargetingKeyName") + respBody, err := targetingKeyRequester.HTTPEditTargetingKey("testTargetingKeyID", "testTargetingKeyName") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -55,7 +58,7 @@ func TestHTTPEditTargetingKey(t *testing.T) { func TestHTTPDeleteTargetingKey(t *testing.T) { - err := HTTPDeleteTargetingKey("testTargetingKeyID") + err := targetingKeyRequester.HTTPDeleteTargetingKey("testTargetingKeyID") assert.Nil(t, err) } diff --git a/utils/http_request/feature_experimentation/user.go b/utils/http_request/feature_experimentation/user.go new file mode 100644 index 0000000..bbe919b --- /dev/null +++ b/utils/http_request/feature_experimentation/user.go @@ -0,0 +1,27 @@ +package feature_experimentation + +import ( + "net/http" + "net/url" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type UserRequester struct { + *common.ResourceRequest +} + +func (u *UserRequester) HTTPListUsers() ([]models.User, error) { + return common.HTTPGetAllPagesFE[models.User](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + u.AccountID + "/account_environments/" + u.AccountEnvironmentID + "/users") +} + +func (u *UserRequester) HTTPBatchUpdateUsers(data string) ([]byte, error) { + return common.HTTPRequest[models.User](http.MethodPut, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+u.AccountID+"/account_environments/"+u.AccountEnvironmentID+"/users", []byte(data)) +} + +func (u *UserRequester) HTTPDeleteUsers(email string) error { + _, err := common.HTTPRequest[models.User](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+u.AccountID+"/account_environments/"+u.AccountEnvironmentID+"/users?emails[]="+url.QueryEscape(email), nil) + return err +} diff --git a/utils/httpRequest/user_test.go b/utils/http_request/feature_experimentation/user_test.go similarity index 61% rename from utils/httpRequest/user_test.go rename to utils/http_request/feature_experimentation/user_test.go index 113aef7..983fc91 100644 --- a/utils/httpRequest/user_test.go +++ b/utils/http_request/feature_experimentation/user_test.go @@ -1,14 +1,17 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) +var userRequester = UserRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} + func TestHTTPListUsers(t *testing.T) { - respBody, err := HTTPListUsers() + respBody, err := userRequester.HTTPListUsers() assert.NotNil(t, respBody) assert.Nil(t, err) @@ -24,14 +27,14 @@ func TestHTTPBatchUpdateUsers(t *testing.T) { data := "[{\"email\":\"example@abtasty.com\",\"role\":\"ADMIN\"},{\"email\":\"example1@abtasty.com\",\"role\":\"VIEWER\"}]" - _, err := HTTPBatchUpdateUsers(data) + _, err := userRequester.HTTPBatchUpdateUsers(data) assert.Nil(t, err) } func TestHTTPDeleteUser(t *testing.T) { - err := HTTPDeleteUsers("example@abtasty.com") + err := userRequester.HTTPDeleteUsers("example@abtasty.com") assert.Nil(t, err) } diff --git a/utils/http_request/feature_experimentation/variation.go b/utils/http_request/feature_experimentation/variation.go new file mode 100644 index 0000000..b3b1869 --- /dev/null +++ b/utils/http_request/feature_experimentation/variation.go @@ -0,0 +1,34 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type VariationFERequester struct { + *common.ResourceRequest +} + +func (v *VariationFERequester) HTTPListVariation(campaignID, variationGroupID string) ([]models.VariationFE, error) { + return common.HTTPGetAllPagesFE[models.VariationFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + v.AccountID + "/account_environments/" + v.AccountEnvironmentID + "/campaigns/" + campaignID + "/variation_groups/" + variationGroupID + "/variations") +} + +func (v *VariationFERequester) HTTPGetVariation(campaignID, variationGroupID, id string) (models.VariationFE, error) { + return common.HTTPGetItem[models.VariationFE](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + v.AccountID + "/account_environments/" + v.AccountEnvironmentID + "/campaigns/" + campaignID + "/variation_groups/" + variationGroupID + "/variations/" + id) +} + +func (v *VariationFERequester) HTTPCreateVariation(campaignID, variationGroupID, data string) ([]byte, error) { + return common.HTTPRequest[models.VariationFE](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+v.AccountID+"/account_environments/"+v.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", []byte(data)) +} + +func (v *VariationFERequester) HTTPEditVariation(campaignID, variationGroupID, id, data string) ([]byte, error) { + return common.HTTPRequest[models.VariationFE](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+v.AccountID+"/account_environments/"+v.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+id, []byte(data)) +} + +func (v *VariationFERequester) HTTPDeleteVariation(campaignID, variationGroupID, id string) error { + _, err := common.HTTPRequest[models.VariationFE](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+v.AccountID+"/account_environments/"+v.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+id, nil) + return err +} diff --git a/utils/http_request/feature_experimentation/variation_group.go b/utils/http_request/feature_experimentation/variation_group.go new file mode 100644 index 0000000..067dd98 --- /dev/null +++ b/utils/http_request/feature_experimentation/variation_group.go @@ -0,0 +1,34 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type VariationGroupRequester struct { + *common.ResourceRequest +} + +func (vg *VariationGroupRequester) HTTPListVariationGroup(campaignID string) ([]models.VariationGroup, error) { + return common.HTTPGetAllPagesFE[models.VariationGroup](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + vg.AccountID + "/account_environments/" + vg.AccountEnvironmentID + "/campaigns/" + campaignID + "/variation_groups") +} + +func (vg *VariationGroupRequester) HTTPGetVariationGroup(campaignID, id string) (models.VariationGroup, error) { + return common.HTTPGetItem[models.VariationGroup](utils.GetFeatureExperimentationHost() + "/v1/accounts/" + vg.AccountID + "/account_environments/" + vg.AccountEnvironmentID + "/campaigns/" + campaignID + "/variation_groups/" + id) +} + +func (vg *VariationGroupRequester) HTTPCreateVariationGroup(campaignID, data string) ([]byte, error) { + return common.HTTPRequest[models.VariationGroup](http.MethodPost, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+vg.AccountID+"/account_environments/"+vg.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups", []byte(data)) +} + +func (vg *VariationGroupRequester) HTTPEditVariationGroup(campaignID, id, data string) ([]byte, error) { + return common.HTTPRequest[models.VariationGroup](http.MethodPatch, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+vg.AccountID+"/account_environments/"+vg.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+id, []byte(data)) +} + +func (vg *VariationGroupRequester) HTTPDeleteVariationGroup(campaignID, id string) error { + _, err := common.HTTPRequest[models.VariationGroup](http.MethodDelete, utils.GetFeatureExperimentationHost()+"/v1/accounts/"+vg.AccountID+"/account_environments/"+vg.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+id, nil) + return err +} diff --git a/utils/httpRequest/variation_group_test.go b/utils/http_request/feature_experimentation/variation_group_test.go similarity index 76% rename from utils/httpRequest/variation_group_test.go rename to utils/http_request/feature_experimentation/variation_group_test.go index 2616e9d..36ef802 100644 --- a/utils/httpRequest/variation_group_test.go +++ b/utils/http_request/feature_experimentation/variation_group_test.go @@ -1,16 +1,18 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) var CampaignID = "campaignID" +var variationGroupRequester = VariationGroupRequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} func TestHTTPGetVariationGroup(t *testing.T) { - respBody, err := HTTPGetVariationGroup(CampaignID, "testVariationGroupID") + respBody, err := variationGroupRequester.HTTPGetVariationGroup(CampaignID, "testVariationGroupID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -21,7 +23,7 @@ func TestHTTPGetVariationGroup(t *testing.T) { func TestHTTPListVariationGroup(t *testing.T) { - respBody, err := HTTPListVariationGroup(CampaignID) + respBody, err := variationGroupRequester.HTTPListVariationGroup(CampaignID) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -37,7 +39,7 @@ func TestHTTPCreateVariationGroup(t *testing.T) { data := "{\"name\":\"testVariationGroupName\",\"variations\":[{\"name\":\"My variation 1\",\"reference\":true,\"allocation\":50,\"modifications\":{\"type\":\"string\",\"value\":\"isVIP\"}}],\"targeting\":{\"targeting_groups\":[{\"targetings\":[{\"operator\":\"CONTAINS\",\"key\":\"isVIP\",\"value\":true}]}]}}" - respBody, err := HTTPCreateVariationGroup(CampaignID, data) + respBody, err := variationGroupRequester.HTTPCreateVariationGroup(CampaignID, data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -49,7 +51,7 @@ func TestHTTPEditVariationGroup(t *testing.T) { data := "{\"name\":\"testVariationGroupName1\",\"variations\":[{\"name\":\"My variation 1\",\"reference\":true,\"allocation\":50,\"modifications\":{\"type\":\"string\",\"value\":\"isVIP\"}}],\"targeting\":{\"targeting_groups\":[{\"targetings\":[{\"operator\":\"CONTAINS\",\"key\":\"isVIP\",\"value\":true}]}]}}" - respBody, err := HTTPEditVariationGroup(CampaignID, "testVariationGroupID", data) + respBody, err := variationGroupRequester.HTTPEditVariationGroup(CampaignID, "testVariationGroupID", data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -59,7 +61,7 @@ func TestHTTPEditVariationGroup(t *testing.T) { func TestHTTPDeleteVariationGroup(t *testing.T) { - err := HTTPDeleteVariationGroup(CampaignID, "testVariationGroupID") + err := variationGroupRequester.HTTPDeleteVariationGroup(CampaignID, "testVariationGroupID") assert.Nil(t, err) } diff --git a/utils/httpRequest/variation_test.go b/utils/http_request/feature_experimentation/variation_test.go similarity index 70% rename from utils/httpRequest/variation_test.go rename to utils/http_request/feature_experimentation/variation_test.go index f8f0708..83a4224 100644 --- a/utils/httpRequest/variation_test.go +++ b/utils/http_request/feature_experimentation/variation_test.go @@ -1,16 +1,18 @@ -package httprequest +package feature_experimentation import ( "testing" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/stretchr/testify/assert" ) var variationGroupID = "variationGroupID" +var variationRequester = VariationFERequester{&common.ResourceRequest{AccountID: "account_id", AccountEnvironmentID: "account_environment_id"}} func TestHTTPGetVariation(t *testing.T) { - respBody, err := HTTPGetVariation(CampaignID, variationGroupID, "testVariationID") + respBody, err := variationRequester.HTTPGetVariation(CampaignID, variationGroupID, "testVariationID") assert.NotNil(t, respBody) assert.Nil(t, err) @@ -21,7 +23,7 @@ func TestHTTPGetVariation(t *testing.T) { func TestHTTPListVariation(t *testing.T) { - respBody, err := HTTPListVariation(CampaignID, variationGroupID) + respBody, err := variationRequester.HTTPListVariation(CampaignID, variationGroupID) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -41,7 +43,7 @@ func TestHTTPCreateVariation(t *testing.T) { data := "{\"name\":\"testVariationName\",\"reference\":true,\"allocation\":50,\"modifications\":{\"type\":\"string\",\"value\":\"isVIP\"}}" - respBody, err := HTTPCreateVariation(CampaignID, variationGroupID, data) + respBody, err := variationRequester.HTTPCreateVariation(CampaignID, variationGroupID, data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -53,7 +55,7 @@ func TestHTTPEditVariation(t *testing.T) { data := "{\"name\":\"testVariationName1\",\"reference\":false,\"allocation\":80,\"modifications\":{\"type\":\"string\",\"value\":\"isVIP1\"}}" - respBody, err := HTTPEditVariation(CampaignID, variationGroupID, "testVariationID", data) + respBody, err := variationRequester.HTTPEditVariation(CampaignID, variationGroupID, "testVariationID", data) assert.NotNil(t, respBody) assert.Nil(t, err) @@ -63,7 +65,7 @@ func TestHTTPEditVariation(t *testing.T) { func TestHTTPDeleteVariation(t *testing.T) { - err := HTTPDeleteVariation(CampaignID, variationGroupID, "testVariationID") + err := variationRequester.HTTPDeleteVariation(CampaignID, variationGroupID, "testVariationID") assert.Nil(t, err) } diff --git a/utils/http_request/main.go b/utils/http_request/main.go new file mode 100644 index 0000000..efa69e1 --- /dev/null +++ b/utils/http_request/main.go @@ -0,0 +1,35 @@ +package http_request + +import ( + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/flagship-io/flagship/utils/http_request/feature_experimentation" + "github.com/flagship-io/flagship/utils/http_request/web_experimentation" +) + +type HTTPResource interface { + Init(*common.RequestConfig) +} + +var ResourceRequester common.ResourceRequest + +var HTTPResources = []HTTPResource{&ResourceRequester} + +// feature experimentation +var CampaignFERequester feature_experimentation.CampaignFERequester = feature_experimentation.CampaignFERequester{ResourceRequest: &ResourceRequester} +var AccountEnvironmentFERequester feature_experimentation.AccountEnvironmentFERequester = feature_experimentation.AccountEnvironmentFERequester{ResourceRequest: &ResourceRequester} +var FlagRequester feature_experimentation.FlagRequester = feature_experimentation.FlagRequester{ResourceRequest: &ResourceRequester} +var GoalRequester feature_experimentation.GoalRequester = feature_experimentation.GoalRequester{ResourceRequest: &ResourceRequester} +var ProjectRequester feature_experimentation.ProjectRequester = feature_experimentation.ProjectRequester{ResourceRequest: &ResourceRequester} +var UserRequester feature_experimentation.UserRequester = feature_experimentation.UserRequester{ResourceRequest: &ResourceRequester} +var TargetingKeyRequester feature_experimentation.TargetingKeyRequester = feature_experimentation.TargetingKeyRequester{ResourceRequest: &ResourceRequester} +var VariationGroupRequester feature_experimentation.VariationGroupRequester = feature_experimentation.VariationGroupRequester{ResourceRequest: &ResourceRequester} +var VariationFERequester feature_experimentation.VariationFERequester = feature_experimentation.VariationFERequester{ResourceRequest: &ResourceRequester} +var PanicRequester feature_experimentation.PanicRequester = feature_experimentation.PanicRequester{ResourceRequest: &ResourceRequester} + +// web experimentation +var CampaignWERequester web_experimentation.CampaignWERequester = web_experimentation.CampaignWERequester{ResourceRequest: &ResourceRequester} +var AccountWERequester web_experimentation.AccountWERequester = web_experimentation.AccountWERequester{ResourceRequest: &ResourceRequester} +var VariationWERequester web_experimentation.VariationWERequester = web_experimentation.VariationWERequester{ResourceRequest: &ResourceRequester} +var CampaignGlobalCodeRequester web_experimentation.CampaignGlobalCodeRequester = web_experimentation.CampaignGlobalCodeRequester{ResourceRequest: &ResourceRequester} +var AccountGlobalCodeRequester web_experimentation.AccountGlobalCodeRequester = web_experimentation.AccountGlobalCodeRequester{ResourceRequest: &ResourceRequester} +var ModificationRequester web_experimentation.ModificationRequester = web_experimentation.ModificationRequester{ResourceRequest: &ResourceRequester} diff --git a/utils/http_request/main_test.go b/utils/http_request/main_test.go new file mode 100644 index 0000000..26ecbe9 --- /dev/null +++ b/utils/http_request/main_test.go @@ -0,0 +1,22 @@ +package http_request + +import ( + "testing" + + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/flagship-io/flagship/utils/mock_function/feature_experimentation" + "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + + "github.com/jarcoal/httpmock" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + feature_experimentation.APIToken() + web_experimentation.APIToken() + mockfunction.Request() + m.Run() +} diff --git a/utils/http_request/web_experimentation/account-global-code.go b/utils/http_request/web_experimentation/account-global-code.go new file mode 100644 index 0000000..e4b676e --- /dev/null +++ b/utils/http_request/web_experimentation/account-global-code.go @@ -0,0 +1,32 @@ +package web_experimentation + +import ( + "encoding/json" + "net/http" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type AccountGlobalCodeRequester struct { + *common.ResourceRequest +} + +func (a *AccountGlobalCodeRequester) HTTPGetAccountGlobalCode(id string) (string, error) { + resp, err := common.HTTPGetItem[models.AccountWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + id) + return resp.GlobalCode.Value, err +} + +func (a *AccountGlobalCodeRequester) HTTPPushAccountGlobalCode(id string, code []byte) ([]byte, error) { + var gc = models.GlobalCodeStr{ + GlobalCode: string(code), + } + + data, err := json.Marshal(gc) + if err != nil { + return nil, err + } + + return common.HTTPRequest[models.AccountWE](http.MethodPatch, utils.GetWebExperimentationHost()+"/v1/accounts/"+a.AccountID, []byte(data)) +} diff --git a/utils/http_request/web_experimentation/account-global-code_test.go b/utils/http_request/web_experimentation/account-global-code_test.go new file mode 100644 index 0000000..40ad021 --- /dev/null +++ b/utils/http_request/web_experimentation/account-global-code_test.go @@ -0,0 +1,21 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/stretchr/testify/assert" +) + +var accountGlobalCodeRequester = AccountGlobalCodeRequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPAccountGlobalCode(t *testing.T) { + + respBody, err := accountGlobalCodeRequester.HTTPGetAccountGlobalCode("account_id") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, "console.log(\"test\")", respBody) + +} diff --git a/utils/http_request/web_experimentation/account.go b/utils/http_request/web_experimentation/account.go new file mode 100644 index 0000000..ba2b4e2 --- /dev/null +++ b/utils/http_request/web_experimentation/account.go @@ -0,0 +1,15 @@ +package web_experimentation + +import ( + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type AccountWERequester struct { + *common.ResourceRequest +} + +func (a *AccountWERequester) HTTPListAccount() ([]models.AccountWE, error) { + return common.HTTPGetAllPagesWE[models.AccountWE](utils.GetWebExperimentationHost() + "/v1/accounts") +} diff --git a/utils/http_request/web_experimentation/account_test.go b/utils/http_request/web_experimentation/account_test.go new file mode 100644 index 0000000..d46a6b4 --- /dev/null +++ b/utils/http_request/web_experimentation/account_test.go @@ -0,0 +1,24 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/stretchr/testify/assert" +) + +var accountWERequester = AccountWERequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPListAccount(t *testing.T) { + + respBody, err := accountWERequester.HTTPListAccount() + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, 100000, respBody[0].Id) + assert.Equal(t, "account_name", respBody[0].Name) + assert.Equal(t, "account_identifier", respBody[0].Identifier) + assert.Equal(t, "account_role", respBody[0].Role) + +} diff --git a/utils/http_request/web_experimentation/campaign-global-code.go b/utils/http_request/web_experimentation/campaign-global-code.go new file mode 100644 index 0000000..f2660a8 --- /dev/null +++ b/utils/http_request/web_experimentation/campaign-global-code.go @@ -0,0 +1,37 @@ +package web_experimentation + +import ( + "encoding/json" + "net/http" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type CampaignGlobalCodeRequester struct { + *common.ResourceRequest +} + +func (c *CampaignGlobalCodeRequester) HTTPGetCampaignGlobalCode(id string) (string, error) { + resp, err := common.HTTPGetItem[models.CampaignWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + c.AccountID + "/tests/" + id) + return resp.GlobalCodeCampaign, err +} + +func (c *CampaignGlobalCodeRequester) HTTPPushCampaignGlobalCode(id string, code []byte) ([]byte, error) { + var gc = models.GlobalCodeStr{ + GlobalCode: string(code), + } + + data, err := json.Marshal(gc) + if err != nil { + return nil, err + } + + return common.HTTPRequest[models.CampaignWE](http.MethodPatch, utils.GetWebExperimentationHost()+"/v1/accounts/"+c.AccountID+"/tests/"+id, []byte(data)) +} + +func (c *CampaignGlobalCodeRequester) HTTPGetCampaignGlobalCodeInfo(id string) (models.CampaignWE, error) { + resp, err := common.HTTPGetItem[models.CampaignWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + c.AccountID + "/tests/" + id) + return resp, err +} diff --git a/utils/http_request/web_experimentation/campaign-global-code_test.go b/utils/http_request/web_experimentation/campaign-global-code_test.go new file mode 100644 index 0000000..db4522f --- /dev/null +++ b/utils/http_request/web_experimentation/campaign-global-code_test.go @@ -0,0 +1,32 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + mockfunction_we "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/stretchr/testify/assert" +) + +var campaignGlobalCodeRequester = CampaignGlobalCodeRequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPCampaignGlobalCode(t *testing.T) { + + respBody, err := campaignGlobalCodeRequester.HTTPGetCampaignGlobalCode("100000") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, "console.log(\"Hello World!\")", respBody) + +} + +func TestHTTPCampaignGlobalCodeInfo(t *testing.T) { + + respBody, err := campaignGlobalCodeRequester.HTTPGetCampaignGlobalCodeInfo("100000") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, mockfunction_we.TestCampaign, respBody) +} diff --git a/utils/http_request/web_experimentation/campaign.go b/utils/http_request/web_experimentation/campaign.go new file mode 100644 index 0000000..41b11e7 --- /dev/null +++ b/utils/http_request/web_experimentation/campaign.go @@ -0,0 +1,27 @@ +package web_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type CampaignWERequester struct { + *common.ResourceRequest +} + +func (t *CampaignWERequester) HTTPListCampaign() ([]models.CampaignWE, error) { + return common.HTTPGetAllPagesWE[models.CampaignWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + t.AccountID + "/tests") +} + +func (t *CampaignWERequester) HTTPGetCampaign(id string) (models.CampaignWE, error) { + return common.HTTPGetItem[models.CampaignWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + t.AccountID + "/tests/" + id) +} + +func (t *CampaignWERequester) HTTPDeleteCampaign(id string) error { + _, err := common.HTTPRequest[models.CampaignWE](http.MethodDelete, utils.GetWebExperimentationHost()+"/v1/accounts/"+t.AccountID+"/tests/"+id, nil) + + return err +} diff --git a/utils/http_request/web_experimentation/campaign_test.go b/utils/http_request/web_experimentation/campaign_test.go new file mode 100644 index 0000000..f9a3753 --- /dev/null +++ b/utils/http_request/web_experimentation/campaign_test.go @@ -0,0 +1,53 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/stretchr/testify/assert" +) + +var campaignRequester = CampaignWERequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPGetCampaign(t *testing.T) { + + respBody, err := campaignRequester.HTTPGetCampaign("100000") + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, 100000, respBody.Id) + assert.Equal(t, "testCampaignName", respBody.Name) + assert.Equal(t, "console.log(\"Hello World!\")", respBody.GlobalCodeCampaign) + assert.Equal(t, "testCampaignDescription", respBody.Description) + assert.Equal(t, "ab", respBody.Type) + +} + +func TestHTTPListCampaign(t *testing.T) { + + respBody, err := campaignRequester.HTTPListCampaign() + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, 100000, respBody[0].Id) + assert.Equal(t, "testCampaignName", respBody[0].Name) + assert.Equal(t, "console.log(\"Hello World!\")", respBody[0].GlobalCodeCampaign) + assert.Equal(t, "testCampaignDescription", respBody[0].Description) + assert.Equal(t, "ab", respBody[0].Type) + + assert.Equal(t, 100001, respBody[1].Id) + assert.Equal(t, "testCampaignName1", respBody[1].Name) + assert.Equal(t, "console.log(\"Hello Earth!\")", respBody[1].GlobalCodeCampaign) + assert.Equal(t, "testCampaignDescription1", respBody[1].Description) + assert.Equal(t, "ab", respBody[1].Type) + +} + +func TestHTTPDeleteCampaign(t *testing.T) { + + err := campaignRequester.HTTPDeleteCampaign("100000") + + assert.Nil(t, err) +} diff --git a/utils/http_request/web_experimentation/main_test.go b/utils/http_request/web_experimentation/main_test.go new file mode 100644 index 0000000..e438783 --- /dev/null +++ b/utils/http_request/web_experimentation/main_test.go @@ -0,0 +1,28 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + mockfunction "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + + mockfunction_ "github.com/flagship-io/flagship/utils/mock_function" + + "github.com/jarcoal/httpmock" +) + +func TestMain(m *testing.M) { + + httpmock.Activate() + defer httpmock.DeactivateAndReset() + + common.Init(mockfunction_.Auth) + + mockfunction.APICampaign() + mockfunction.APIModification() + mockfunction.APIVariation() + mockfunction.APIAccount() + mockfunction.APIToken() + + m.Run() +} diff --git a/utils/http_request/web_experimentation/modification.go b/utils/http_request/web_experimentation/modification.go new file mode 100644 index 0000000..882db4b --- /dev/null +++ b/utils/http_request/web_experimentation/modification.go @@ -0,0 +1,49 @@ +package web_experimentation + +import ( + "encoding/json" + "net/http" + "strconv" + + "github.com/flagship-io/flagship/models/web_experimentation" + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type ModificationRequester struct { + *common.ResourceRequest +} + +func (m *ModificationRequester) HTTPListModification(campaignID int) ([]models.Modification, error) { + resp, err := common.HTTPGetItem[models.ModificationDataWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + m.AccountID + "/tests/" + strconv.Itoa(campaignID) + "/modifications") + return resp.Data.Modifications, err +} + +func (m *ModificationRequester) HTTPGetModification(campaignID int, id int) ([]models.Modification, error) { + resp, err := common.HTTPGetItem[models.ModificationDataWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + m.AccountID + "/tests/" + strconv.Itoa(campaignID) + "/modifications?ids=" + strconv.Itoa(id)) + return resp.Data.Modifications, err +} + +func (m *ModificationRequester) HTTPEditModification(campaignID int, id int, modificationData web_experimentation.ModificationCodeEditStruct) ([]byte, error) { + data, err := json.Marshal(modificationData) + if err != nil { + return nil, err + } + + return common.HTTPRequest[models.ModificationDataWE](http.MethodPatch, utils.GetWebExperimentationHost()+"/v1/accounts/"+m.AccountID+"/tests/"+strconv.Itoa(campaignID)+"/modifications/"+strconv.Itoa(id), data) +} + +func (m *ModificationRequester) HTTPCreateModification(campaignID int, modificationData web_experimentation.ModificationCodeCreateStruct) ([]byte, error) { + data, err := json.Marshal(modificationData) + if err != nil { + return nil, err + } + + return common.HTTPRequest[models.ModificationDataWE](http.MethodPost, utils.GetWebExperimentationHost()+"/v1/accounts/"+m.AccountID+"/tests/"+strconv.Itoa(campaignID)+"/modifications", data) +} + +func (m *ModificationRequester) HTTPDeleteModification(campaignID int, id int) error { + _, err := common.HTTPRequest[models.ModificationDataWE](http.MethodDelete, utils.GetWebExperimentationHost()+"/v1/accounts/"+m.AccountID+"/tests/"+strconv.Itoa(campaignID)+"/modifications/"+strconv.Itoa(id)+"?input_type=modification", nil) + return err +} diff --git a/utils/http_request/web_experimentation/modification_test.go b/utils/http_request/web_experimentation/modification_test.go new file mode 100644 index 0000000..0c6058e --- /dev/null +++ b/utils/http_request/web_experimentation/modification_test.go @@ -0,0 +1,41 @@ +package web_experimentation + +import ( + "testing" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/stretchr/testify/assert" +) + +var modificationRequester = ModificationRequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPListModification(t *testing.T) { + + respBody, err := modificationRequester.HTTPListModification(100000) + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, web_experimentation.TestModifications.Data.Modifications, respBody) + +} + +func TestHTTPGetModification(t *testing.T) { + + respBody, err := modificationRequester.HTTPGetModification(100000, 120003) + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, []models.Modification{web_experimentation.TestModification.Data.Modifications[0]}, respBody) + +} + +func TestHTTPDeleteModification(t *testing.T) { + + err := modificationRequester.HTTPDeleteModification(100000, 120003) + + assert.Nil(t, err) +} diff --git a/utils/http_request/web_experimentation/variation.go b/utils/http_request/web_experimentation/variation.go new file mode 100644 index 0000000..1b991d4 --- /dev/null +++ b/utils/http_request/web_experimentation/variation.go @@ -0,0 +1,23 @@ +package web_experimentation + +import ( + "net/http" + "strconv" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/http_request/common" +) + +type VariationWERequester struct { + *common.ResourceRequest +} + +func (v *VariationWERequester) HTTPGetVariation(testID, id int) (models.VariationWE, error) { + return common.HTTPGetItem[models.VariationWE](utils.GetWebExperimentationHost() + "/v1/accounts/" + v.AccountID + "/tests/" + strconv.Itoa(testID) + "/variations/" + strconv.Itoa(id)) +} + +func (v *VariationWERequester) HTTPDeleteVariation(testID, id int) error { + _, err := common.HTTPRequest[models.VariationWE](http.MethodDelete, utils.GetWebExperimentationHost()+"/v1/accounts/"+v.AccountID+"/tests/"+strconv.Itoa(testID)+"/variations/"+strconv.Itoa(id), nil) + return err +} diff --git a/utils/http_request/web_experimentation/variation_test.go b/utils/http_request/web_experimentation/variation_test.go new file mode 100644 index 0000000..fe6fa3f --- /dev/null +++ b/utils/http_request/web_experimentation/variation_test.go @@ -0,0 +1,29 @@ +package web_experimentation + +import ( + "testing" + + "github.com/flagship-io/flagship/utils/http_request/common" + "github.com/flagship-io/flagship/utils/mock_function/web_experimentation" + "github.com/stretchr/testify/assert" +) + +var variationRequester = VariationWERequester{&common.ResourceRequest{AccountID: "account_id"}} + +func TestHTTPGetVariation(t *testing.T) { + + respBody, err := variationRequester.HTTPGetVariation(100000, 110000) + + assert.NotNil(t, respBody) + assert.Nil(t, err) + + assert.Equal(t, web_experimentation.TestVariation, respBody) + +} + +func TestHTTPDeleteVariation(t *testing.T) { + + err := variationRequester.HTTPDeleteVariation(100000, 110000) + + assert.Nil(t, err) +} diff --git a/utils/mock_function/configuration.go b/utils/mock_function/configuration.go deleted file mode 100644 index eb5aba4..0000000 --- a/utils/mock_function/configuration.go +++ /dev/null @@ -1,21 +0,0 @@ -package mockfunction - -import ( - "os" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils/config" -) - -var TestConfiguration = models.Configuration{ - Name: "test_configuration", - ClientID: "testConfigurationClientID", - ClientSecret: "testConfigurationClientSecret", - AccountID: "testConfigurationAccountID", - AccountEnvironmentID: "testConfigurationAccountEnvID", -} - -func InitMockConfiguration() { - config.SetViperMock() - os.Remove(config.SetPathForConfigName("test_configuration")) -} diff --git a/utils/mock_function/feature_experimentation/account.go b/utils/mock_function/feature_experimentation/account.go new file mode 100644 index 0000000..72636ef --- /dev/null +++ b/utils/mock_function/feature_experimentation/account.go @@ -0,0 +1,11 @@ +package feature_experimentation + +import ( + "github.com/flagship-io/flagship/models" +) + +var TestAccount = models.AccountJSON{ + CurrentUsedCredential: "test_auth", + AccountID: "account_id", + AccountEnvironmentID: "account_environment_id", +} diff --git a/utils/mock_function/feature_experimentation/account_environment.go b/utils/mock_function/feature_experimentation/account_environment.go new file mode 100644 index 0000000..99ae801 --- /dev/null +++ b/utils/mock_function/feature_experimentation/account_environment.go @@ -0,0 +1,56 @@ +package feature_experimentation + +import ( + "net/http" + + models_fe "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestAccountEnvironment = models_fe.AccountEnvironmentFE{ + Id: "account_environment_id", + Environment: "account_environment_name", + IsMain: true, + Panic: false, + SingleAssignment: false, +} + +var TestAccountEnvironment1 = models_fe.AccountEnvironmentFE{ + Id: "account_environment_id1", + Environment: "account_environment_name1", + IsMain: true, + Panic: false, + SingleAssignment: false, +} + +var TestAccountEnvironmentList = []models_fe.AccountEnvironmentFE{ + TestAccountEnvironment, TestAccountEnvironment1, +} + +func APIAccountEnvironment() { + + resp := utils.HTTPListResponseFE[models_fe.AccountEnvironmentFE]{ + Items: TestAccountEnvironmentList, + CurrentItemsCount: 2, + CurrentPage: 1, + TotalCount: 2, + ItemsPerPage: 10, + LastPage: 1, + } + + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, resp) + return resp, nil + }, + ) + + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+TestAccountEnvironment.Id, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestAccountEnvironment) + return resp, nil + }, + ) +} diff --git a/utils/mock_function/feature_experimentation/auth.go b/utils/mock_function/feature_experimentation/auth.go new file mode 100644 index 0000000..233d3cd --- /dev/null +++ b/utils/mock_function/feature_experimentation/auth.go @@ -0,0 +1,27 @@ +package feature_experimentation + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" +) + +var TestAuth = models.Auth{ + Username: "test_auth", + ClientID: "testAuthClientID", + ClientSecret: "testAuthClientSecret", + Token: "testAccessToken", + RefreshToken: "testRefreshToken", +} + +func InitMockAuth() { + credPath, err := config.CredentialPath(utils.FEATURE_EXPERIMENTATION, "test_auth") + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + os.Remove(credPath) +} diff --git a/utils/mock_function/campaign.go b/utils/mock_function/feature_experimentation/campaign.go similarity index 62% rename from utils/mock_function/campaign.go rename to utils/mock_function/feature_experimentation/campaign.go index e06feec..da5e06e 100644 --- a/utils/mock_function/campaign.go +++ b/utils/mock_function/feature_experimentation/campaign.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var scheduler = models.Scheduler{ @@ -32,7 +31,7 @@ var targetingTest = models.Targeting{ TargetingGroups: targetingGroupsTest, } -var variationTest = []models.Variation{ +var variationTest = []models.VariationFE{ { Name: "My variation 1", Reference: true, @@ -61,7 +60,7 @@ var variationGroupsTest = []models.VariationGroup{ }, } -var TestCampaign = models.Campaign{ +var TestCampaign = models.CampaignFE{ Id: "testCampaignID", Name: "testCampaignName", ProjectId: "testProjectID", @@ -71,7 +70,7 @@ var TestCampaign = models.Campaign{ Scheduler: scheduler, } -var TestCampaign1 = models.Campaign{ +var TestCampaign1 = models.CampaignFE{ Id: "testCampaignID1", Name: "testCampaignName1", ProjectId: "testProjectID1", @@ -81,7 +80,7 @@ var TestCampaign1 = models.Campaign{ Scheduler: scheduler, } -var TestCampaignEdit = models.Campaign{ +var TestCampaignEdit = models.CampaignFE{ Id: "testCampaignID", Name: "testCampaignName1", ProjectId: "testProjectID1", @@ -91,15 +90,14 @@ var TestCampaignEdit = models.Campaign{ Scheduler: scheduler, } -var TestCampaignlist = []models.Campaign{ +var TestCampaignlist = []models.CampaignFE{ TestCampaign, TestCampaign1, } func APICampaign() { - config.SetViperMock() - resp := utils.HTTPListResponse[models.Campaign]{ + resp := utils.HTTPListResponseFE[models.CampaignFE]{ Items: TestCampaignlist, CurrentItemsCount: 2, CurrentPage: 1, @@ -108,42 +106,42 @@ func APICampaign() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+TestCampaign.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+TestCampaign.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestCampaign) return resp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestCampaign) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+TestCampaign.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+TestCampaign.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestCampaignEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+TestCampaign.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+TestCampaign.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+TestCampaign.Id+"/toggle", + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+TestCampaign.Id+"/toggle", func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(200, ""), nil }, diff --git a/utils/mock_function/flag.go b/utils/mock_function/feature_experimentation/flag.go similarity index 62% rename from utils/mock_function/flag.go rename to utils/mock_function/feature_experimentation/flag.go index 8b209e1..e370996 100644 --- a/utils/mock_function/flag.go +++ b/utils/mock_function/feature_experimentation/flag.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestFlag = models.Flag{ @@ -40,9 +39,8 @@ var TestFlagList = []models.Flag{ } func APIFlag() { - config.SetViperMock() - resp := utils.HTTPListResponse[models.Flag]{ + resp := utils.HTTPListResponseFE[models.Flag]{ Items: TestFlagList, CurrentItemsCount: 2, CurrentPage: 1, @@ -51,35 +49,35 @@ func APIFlag() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags/"+TestFlag.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/flags/"+TestFlag.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestFlag) return resp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/flags", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/flags", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestFlag) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags/"+TestFlag.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/flags/"+TestFlag.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestFlagEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/flags/"+TestFlag.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/flags/"+TestFlag.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, diff --git a/utils/mock_function/goal.go b/utils/mock_function/feature_experimentation/goal.go similarity index 54% rename from utils/mock_function/goal.go rename to utils/mock_function/feature_experimentation/goal.go index 4164a5b..8320f56 100644 --- a/utils/mock_function/goal.go +++ b/utils/mock_function/feature_experimentation/goal.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestGoal = models.Goal{ @@ -40,9 +39,8 @@ var TestGoalList = []models.Goal{ } func APIGoal() { - config.SetViperMock() - resp := utils.HTTPListResponse[models.Goal]{ + resp := utils.HTTPListResponseFE[models.Goal]{ Items: TestGoalList, CurrentItemsCount: 2, CurrentPage: 1, @@ -51,35 +49,35 @@ func APIGoal() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals/"+TestGoal.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/goals/"+TestGoal.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestGoal) return resp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/goals", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/goals", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestGoal) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals/"+TestGoal.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/goals/"+TestGoal.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestGoalEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/goals/"+TestGoal.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/goals/"+TestGoal.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, diff --git a/utils/mock_function/feature_experimentation/panic.go b/utils/mock_function/feature_experimentation/panic.go new file mode 100644 index 0000000..0854c26 --- /dev/null +++ b/utils/mock_function/feature_experimentation/panic.go @@ -0,0 +1,19 @@ +package feature_experimentation + +import ( + "net/http" + + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +func APIPanic() { + + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/panic", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, "") + return resp, nil + }, + ) +} diff --git a/utils/mock_function/project.go b/utils/mock_function/feature_experimentation/project.go similarity index 56% rename from utils/mock_function/project.go rename to utils/mock_function/feature_experimentation/project.go index 73aa169..3f849e6 100644 --- a/utils/mock_function/project.go +++ b/utils/mock_function/feature_experimentation/project.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestProject = models.Project{ @@ -31,10 +30,7 @@ var TestProjectList = []models.Project{ } func APIProject() { - - config.SetViperMock() - - resp := utils.HTTPListResponse[models.Project]{ + resp := utils.HTTPListResponseFE[models.Project]{ Items: TestProjectList, CurrentItemsCount: 2, CurrentPage: 1, @@ -43,42 +39,42 @@ func APIProject() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+TestProject.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects/"+TestProject.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestProject) return resp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestProject) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+TestProject.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects/"+TestProject.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestProjectEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+TestProject.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects/"+TestProject.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/projects/"+TestProject.Id+"/toggle", + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/projects/"+TestProject.Id+"/toggle", func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(200, ""), nil }, diff --git a/utils/mock_function/targeting_key.go b/utils/mock_function/feature_experimentation/targeting_key.go similarity index 62% rename from utils/mock_function/targeting_key.go rename to utils/mock_function/feature_experimentation/targeting_key.go index 2901747..baa1fe5 100644 --- a/utils/mock_function/targeting_key.go +++ b/utils/mock_function/feature_experimentation/targeting_key.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestTargetingKey = models.TargetingKey{ @@ -38,9 +37,7 @@ var TestTargetingKeyList = []models.TargetingKey{ func APITargetingKey() { - config.SetViperMock() - - resp := utils.HTTPListResponse[models.TargetingKey]{ + resp := utils.HTTPListResponseFE[models.TargetingKey]{ Items: TestTargetingKeyList, CurrentItemsCount: 2, CurrentPage: 1, @@ -49,35 +46,35 @@ func APITargetingKey() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys/"+TestTargetingKey.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/targeting_keys/"+TestTargetingKey.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestTargetingKey) return resp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/targeting_keys", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/targeting_keys", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestTargetingKey) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys/"+TestTargetingKey.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/targeting_keys/"+TestTargetingKey.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestTargetingKeyEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/targeting_keys/"+TestTargetingKey.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/targeting_keys/"+TestTargetingKey.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, diff --git a/utils/mock_function/feature_experimentation/token.go b/utils/mock_function/feature_experimentation/token.go new file mode 100644 index 0000000..fa992d9 --- /dev/null +++ b/utils/mock_function/feature_experimentation/token.go @@ -0,0 +1,41 @@ +package feature_experimentation + +import ( + "net/http" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestToken = models.Token{ + ClientID: "client_id", + AccountID: "account_id", + ExpiresIn: 0, + Scope: "scope", +} + +func APIToken() { + + token := "access_token" + + testAuthenticationResponse := models.TokenResponse{ + AccessToken: "testAccessToken", + RefreshToken: "testRefreshToken", + } + + httpmock.RegisterResponder("GET", utils.GetHostFeatureExperimentationAuth()+"/token?access_token="+token, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestToken) + return resp, nil + }, + ) + + httpmock.RegisterResponder("POST", utils.GetHostFeatureExperimentationAuth()+"/"+mockfunction.Auth.AccountID+"/token?expires_in=43200", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, testAuthenticationResponse) + return resp, nil + }, + ) +} diff --git a/utils/mock_function/user.go b/utils/mock_function/feature_experimentation/user.go similarity index 50% rename from utils/mock_function/user.go rename to utils/mock_function/feature_experimentation/user.go index 826abb8..f1db504 100644 --- a/utils/mock_function/user.go +++ b/utils/mock_function/feature_experimentation/user.go @@ -1,14 +1,13 @@ -package mockfunction +package feature_experimentation import ( "net/http" "net/url" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestUserList = []models.User{ @@ -23,11 +22,10 @@ var TestUserList = []models.User{ } func APIUser() { - config.SetViperMock() email := "example@abtasty.com" - resp := utils.HTTPListResponse[models.User]{ + resp := utils.HTTPListResponseFE[models.User]{ Items: TestUserList, CurrentItemsCount: 2, CurrentPage: 1, @@ -36,21 +34,21 @@ func APIUser() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/users", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/users", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, resp) return resp, nil }, ) - httpmock.RegisterResponder("PUT", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/users", + httpmock.RegisterResponder("PUT", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/users", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(204, "") return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/users?emails[]="+url.QueryEscape(email), + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/users?emails[]="+url.QueryEscape(email), func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(204, "") return resp, nil diff --git a/utils/mock_function/feature_experimentation/variation.go b/utils/mock_function/feature_experimentation/variation.go new file mode 100644 index 0000000..1f7a382 --- /dev/null +++ b/utils/mock_function/feature_experimentation/variation.go @@ -0,0 +1,98 @@ +package feature_experimentation + +import ( + "net/http" + + models "github.com/flagship-io/flagship/models/feature_experimentation" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestVariation = models.VariationFE{ + Id: "testVariationID", + Name: "testVariationName", + Reference: true, + Allocation: 50, + Modifications: models.Modification{ + Type: "string", + Value: "isVIP", + }, +} + +var TestVariation1 = models.VariationFE{ + Id: "testVariationID1", + Name: "testVariationName1", + Reference: false, + Allocation: 80, + Modifications: models.Modification{ + Type: "string", + Value: "isVIP1", + }, +} + +var TestVariationEdit = models.VariationFE{ + Id: "testVariationID", + Name: "testVariationName1", + Reference: false, + Allocation: 80, + Modifications: models.Modification{ + Type: "string", + Value: "isVIP1", + }, +} + +var TestVariationList = []models.VariationFE{ + TestVariation, + TestVariation1, +} + +func APIVariation() { + + campaignID := "campaignID" + variationGroupID := "variationGroupID" + + resp := utils.HTTPListResponseFE[models.VariationFE]{ + Items: TestVariationList, + CurrentItemsCount: 2, + CurrentPage: 1, + TotalCount: 2, + ItemsPerPage: 10, + LastPage: 1, + } + + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestVariation) + return resp, nil + }, + ) + + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, resp) + return resp, nil + }, + ) + + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestVariation) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestVariationEdit) + return resp, nil + }, + ) + + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, + func(req *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(204, ""), nil + }, + ) + +} diff --git a/utils/mock_function/variation_group.go b/utils/mock_function/feature_experimentation/variation_group.go similarity index 58% rename from utils/mock_function/variation_group.go rename to utils/mock_function/feature_experimentation/variation_group.go index fc8cdb3..8a8b160 100644 --- a/utils/mock_function/variation_group.go +++ b/utils/mock_function/feature_experimentation/variation_group.go @@ -1,13 +1,12 @@ -package mockfunction +package feature_experimentation import ( "net/http" - "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/feature_experimentation" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var targetingGroups = []models.TargetingGroup{ @@ -22,7 +21,7 @@ var targetingGroups = []models.TargetingGroup{ }, } -var variations = []models.Variation{ +var variations = []models.VariationFE{ { Name: "My variation 1", Reference: true, @@ -66,11 +65,9 @@ var TestVariationGroupList = []models.VariationGroup{ func APIVariationGroup() { - config.SetViperMock() - campaignID := "campaignID" - resp := utils.HTTPListResponse[models.VariationGroup]{ + resp := utils.HTTPListResponseFE[models.VariationGroup]{ Items: TestVariationGroupList, CurrentItemsCount: 2, CurrentPage: 1, @@ -79,35 +76,35 @@ func APIVariationGroup() { LastPage: 1, } - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, func(req *http.Request) (*http.Response, error) { mockResp, _ := httpmock.NewJsonResponse(200, TestVariationGroup) return mockResp, nil }, ) - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups", + httpmock.RegisterResponder("GET", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups", func(req *http.Request) (*http.Response, error) { mockResp, _ := httpmock.NewJsonResponse(200, resp) return mockResp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups", + httpmock.RegisterResponder("POST", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestVariationGroup) return resp, nil }, ) - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, + httpmock.RegisterResponder("PATCH", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestVariationGroupEdit) return resp, nil }, ) - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, + httpmock.RegisterResponder("DELETE", utils.GetFeatureExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/account_environments/"+mockfunction.Auth.AccountEnvironmentID+"/campaigns/"+campaignID+"/variation_groups/"+TestVariationGroup.Id, func(req *http.Request) (*http.Response, error) { return httpmock.NewStringResponse(204, ""), nil }, diff --git a/utils/mock_function/panic.go b/utils/mock_function/panic.go deleted file mode 100644 index f1f3e54..0000000 --- a/utils/mock_function/panic.go +++ /dev/null @@ -1,21 +0,0 @@ -package mockfunction - -import ( - "net/http" - - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - "github.com/jarcoal/httpmock" - "github.com/spf13/viper" -) - -func APIPanic() { - config.SetViperMock() - - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/panic", - func(req *http.Request) (*http.Response, error) { - resp, _ := httpmock.NewJsonResponse(200, "") - return resp, nil - }, - ) -} diff --git a/utils/mock_function/request.go b/utils/mock_function/request.go index c5f26a3..c5c7fcc 100644 --- a/utils/mock_function/request.go +++ b/utils/mock_function/request.go @@ -4,16 +4,33 @@ import ( "net/http" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" + "github.com/flagship-io/flagship/utils/http_request/common" "github.com/jarcoal/httpmock" + "github.com/spf13/viper" ) type TestRequest struct { Name string `json:"name"` } +var Auth = common.RequestConfig{ + Username: "test_auth", + ClientID: "client_id", + ClientSecret: "client_secret", + AccountID: "account_id", + AccountEnvironmentID: "account_environment_id", + Token: "access_token", +} + +func SetMock(c *common.ResourceRequest) { + viper.GetViper().Set("output_format", "json") + common.Init(Auth) + + r := c + r.Init(&Auth) +} + func Request() { - config.SetViperMock() testRequest := TestRequest{ Name: "TestName", @@ -25,7 +42,7 @@ func Request() { testRequestList := []TestRequest{testRequest, testRequest1} - resp := utils.HTTPListResponse[TestRequest]{ + resp := utils.HTTPListResponseFE[TestRequest]{ Items: testRequestList, CurrentItemsCount: 2, CurrentPage: 1, diff --git a/utils/mock_function/variation.go b/utils/mock_function/variation.go deleted file mode 100644 index 57c6dd8..0000000 --- a/utils/mock_function/variation.go +++ /dev/null @@ -1,101 +0,0 @@ -package mockfunction - -import ( - "net/http" - - "github.com/flagship-io/flagship/models" - "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" - "github.com/jarcoal/httpmock" - "github.com/spf13/viper" -) - -var TestVariation = models.Variation{ - Id: "testVariationID", - Name: "testVariationName", - Reference: true, - Allocation: 50, - Modifications: models.Modification{ - Type: "string", - Value: "isVIP", - }, -} - -var TestVariation1 = models.Variation{ - Id: "testVariationID1", - Name: "testVariationName1", - Reference: false, - Allocation: 80, - Modifications: models.Modification{ - Type: "string", - Value: "isVIP1", - }, -} - -var TestVariationEdit = models.Variation{ - Id: "testVariationID", - Name: "testVariationName1", - Reference: false, - Allocation: 80, - Modifications: models.Modification{ - Type: "string", - Value: "isVIP1", - }, -} - -var TestVariationList = []models.Variation{ - TestVariation, - TestVariation1, -} - -func APIVariation() { - - config.SetViperMock() - - campaignID := "campaignID" - variationGroupID := "variationGroupID" - - resp := utils.HTTPListResponse[models.Variation]{ - Items: TestVariationList, - CurrentItemsCount: 2, - CurrentPage: 1, - TotalCount: 2, - ItemsPerPage: 10, - LastPage: 1, - } - - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, - func(req *http.Request) (*http.Response, error) { - resp, _ := httpmock.NewJsonResponse(200, TestVariation) - return resp, nil - }, - ) - - httpmock.RegisterResponder("GET", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", - func(req *http.Request) (*http.Response, error) { - resp, _ := httpmock.NewJsonResponse(200, resp) - return resp, nil - }, - ) - - httpmock.RegisterResponder("POST", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations", - func(req *http.Request) (*http.Response, error) { - resp, _ := httpmock.NewJsonResponse(200, TestVariation) - return resp, nil - }, - ) - - httpmock.RegisterResponder("PATCH", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, - func(req *http.Request) (*http.Response, error) { - resp, _ := httpmock.NewJsonResponse(200, TestVariationEdit) - return resp, nil - }, - ) - - httpmock.RegisterResponder("DELETE", utils.GetHost()+"/v1/accounts/"+viper.GetString("account_id")+"/account_environments/"+viper.GetString("account_environment_id")+"/campaigns/"+campaignID+"/variation_groups/"+variationGroupID+"/variations/"+TestVariation.Id, - func(req *http.Request) (*http.Response, error) { - return httpmock.NewStringResponse(204, ""), nil - }, - ) - -} diff --git a/utils/mock_function/web_experimentation/account.go b/utils/mock_function/web_experimentation/account.go new file mode 100644 index 0000000..23002e6 --- /dev/null +++ b/utils/mock_function/web_experimentation/account.go @@ -0,0 +1,65 @@ +package web_experimentation + +import ( + "net/http" + + models_ "github.com/flagship-io/flagship/models" + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + "github.com/jarcoal/httpmock" +) + +var TestAccount = models_.AccountJSON{ + CurrentUsedCredential: "test_auth", + AccountID: "account_id", + AccountEnvironmentID: "account_environment_id", +} + +var TestGlobalCode = models.GlobalCode_{ + OnDomReady: true, + Value: "console.log(\"test\")", +} + +var accountID = "account_id" + +var TestAccountGlobalCode = models.AccountWE{ + Id: 100000, + Name: "account_name", + Identifier: "account_identifier", + Role: "account_role", + GlobalCode: TestGlobalCode, +} + +func APIAccount() { + + resp := utils.HTTPListResponseWE[models.AccountWE]{ + Data: []models.AccountWE{TestAccountGlobalCode}, + Pagination: utils.Pagination{ + Total: 1, + Pages: 2, + MaxPerPage: 10, + Page: 1, + }, + } + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+accountID, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestAccountGlobalCode) + return resp, nil + }, + ) + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, resp) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetWebExperimentationHost()+"/v1/accounts/"+accountID, + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestAccountGlobalCode) + return resp, nil + }, + ) +} diff --git a/utils/mock_function/web_experimentation/auth.go b/utils/mock_function/web_experimentation/auth.go new file mode 100644 index 0000000..48c5224 --- /dev/null +++ b/utils/mock_function/web_experimentation/auth.go @@ -0,0 +1,26 @@ +package web_experimentation + +import ( + "log" + "os" + + "github.com/flagship-io/flagship/models" + "github.com/flagship-io/flagship/utils" + "github.com/flagship-io/flagship/utils/config" +) + +var TestAuth = models.Auth{ + Username: "test_auth", + ClientID: "CI", + ClientSecret: "CS", + Token: "testAccessToken", +} + +func InitMockAuth() { + credPath, err := config.CredentialPath(utils.WEB_EXPERIMENTATION, "test_auth") + if err != nil { + log.Fatalf("error occurred: %s", err) + } + + os.Remove(credPath) +} diff --git a/utils/mock_function/web_experimentation/campaign.go b/utils/mock_function/web_experimentation/campaign.go new file mode 100644 index 0000000..4943d19 --- /dev/null +++ b/utils/mock_function/web_experimentation/campaign.go @@ -0,0 +1,72 @@ +package web_experimentation + +import ( + "net/http" + "strconv" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestCampaign = models.CampaignWE{ + Id: 100000, + Name: "testCampaignName", + Description: "testCampaignDescription", + Type: "ab", + GlobalCodeCampaign: "console.log(\"Hello World!\")", +} + +var TestCampaign1 = models.CampaignWE{ + Id: 100001, + Name: "testCampaignName1", + Description: "testCampaignDescription1", + Type: "ab", + GlobalCodeCampaign: "console.log(\"Hello Earth!\")", +} + +var TestCampaignList = []models.CampaignWE{ + TestCampaign, + TestCampaign1, +} + +func APICampaign() { + + respList := utils.HTTPListResponseWE[models.CampaignWE]{ + Data: TestCampaignList, + Pagination: utils.Pagination{ + Total: 1, + Pages: 2, + MaxPerPage: 10, + Page: 1, + }, + } + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestCampaign) + return resp, nil + }, + ) + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, respList) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestCampaign) + return resp, nil + }, + ) + + httpmock.RegisterResponder("DELETE", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id), + func(req *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(204, ""), nil + }, + ) +} diff --git a/utils/mock_function/web_experimentation/modification.go b/utils/mock_function/web_experimentation/modification.go new file mode 100644 index 0000000..bc7010f --- /dev/null +++ b/utils/mock_function/web_experimentation/modification.go @@ -0,0 +1,99 @@ +package web_experimentation + +import ( + "net/http" + "strconv" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestModificationsJS = models.Modification{ + Id: 120001, + Name: "modification", + Value: "console.log(\"test modification\")", + VariationID: 110000, + Type: "customScriptNew", +} + +var TestModificationsCSS = models.Modification{ + Id: 120002, + Name: "modification", + Value: ".id{\"color\": \"black\"}", + VariationID: 110000, + Type: "addCSS", +} + +var TestElementModification = models.Modification{ + Id: 120003, + Name: "modification", + Value: "console.log(\"test modification\")", + VariationID: 110000, + Selector: "document.querySelector()", + Type: "customScriptNew", +} + +var TestData = models.ModificationWE{ + GlobalModifications: []models.Modification{}, + Modifications: []models.Modification{TestModificationsJS, TestModificationsCSS}, +} + +var TestModifData = models.ModificationWE{ + GlobalModifications: []models.Modification{}, + Modifications: []models.Modification{TestElementModification}, +} + +var TestModifications = models.ModificationDataWE{ + Data: TestData, +} + +var TestModification = models.ModificationDataWE{ + Data: TestModifData, +} + +func APIModification() { + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications", + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestModifications) + return resp, nil + }, + ) + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications?ids="+strconv.Itoa(TestElementModification.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestModification) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications/"+strconv.Itoa(TestElementModification.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestElementModification) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications/"+strconv.Itoa(TestModificationsJS.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestModificationsJS) + return resp, nil + }, + ) + + httpmock.RegisterResponder("PATCH", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications/"+strconv.Itoa(TestModificationsCSS.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestModificationsCSS) + return resp, nil + }, + ) + + httpmock.RegisterResponder("DELETE", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/modifications/"+strconv.Itoa(TestElementModification.Id), + func(req *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(204, ""), nil + + }, + ) +} diff --git a/utils/mock_function/token.go b/utils/mock_function/web_experimentation/token.go similarity index 55% rename from utils/mock_function/token.go rename to utils/mock_function/web_experimentation/token.go index 967369a..1ee894f 100644 --- a/utils/mock_function/token.go +++ b/utils/mock_function/web_experimentation/token.go @@ -1,42 +1,36 @@ -package mockfunction +package web_experimentation import ( "net/http" - "strconv" "github.com/flagship-io/flagship/models" "github.com/flagship-io/flagship/utils" - "github.com/flagship-io/flagship/utils/config" "github.com/jarcoal/httpmock" - "github.com/spf13/viper" ) var TestToken = models.Token{ ClientID: "client_id", AccountID: "account_id", - ExpiresIn: 0, - Scope: "*", + ExpiresIn: 10, + Scope: "scope", } func APIToken() { - config.SetViperMock() token := "token" - tokenExpiration := 86400 testAuthenticationResponse := models.TokenResponse{ - AccessToken: "access_token", - RefreshToken: "refresh_token", + AccessToken: "testAccessToken", } - httpmock.RegisterResponder("GET", utils.GetHostAuth()+"/token?access_token="+token, + httpmock.RegisterResponder("GET", utils.GetHostWebExperimentationAuth()+"/v1/token?access_token="+token, func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, TestToken) return resp, nil }, ) - httpmock.RegisterResponder("POST", utils.GetHostAuth()+"/"+viper.GetString("account_id")+"/token?expires_in="+strconv.Itoa(tokenExpiration), + httpmock.RegisterResponder("POST", utils.GetHostWebExperimentationAuth()+"/v1/token", func(req *http.Request) (*http.Response, error) { resp, _ := httpmock.NewJsonResponse(200, testAuthenticationResponse) return resp, nil diff --git a/utils/mock_function/web_experimentation/variation.go b/utils/mock_function/web_experimentation/variation.go new file mode 100644 index 0000000..9ac7f6a --- /dev/null +++ b/utils/mock_function/web_experimentation/variation.go @@ -0,0 +1,34 @@ +package web_experimentation + +import ( + "net/http" + "strconv" + + models "github.com/flagship-io/flagship/models/web_experimentation" + "github.com/flagship-io/flagship/utils" + mockfunction "github.com/flagship-io/flagship/utils/mock_function" + "github.com/jarcoal/httpmock" +) + +var TestVariation = models.VariationWE{ + Id: 110000, + Name: "testVariationName", + Description: "testVariationDescription", +} + +func APIVariation() { + + httpmock.RegisterResponder("GET", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/variations/"+strconv.Itoa(TestVariation.Id), + func(req *http.Request) (*http.Response, error) { + resp, _ := httpmock.NewJsonResponse(200, TestVariation) + return resp, nil + }, + ) + + httpmock.RegisterResponder("DELETE", utils.GetWebExperimentationHost()+"/v1/accounts/"+mockfunction.Auth.AccountID+"/tests/"+strconv.Itoa(TestCampaign.Id)+"/variations/"+strconv.Itoa(TestVariation.Id), + func(req *http.Request) (*http.Response, error) { + return httpmock.NewStringResponse(204, ""), nil + }, + ) + +}