From 0ae88002b464b6ad39bc5ad241707001d959329e Mon Sep 17 00:00:00 2001 From: bupd Date: Mon, 10 Jun 2024 00:39:31 +0530 Subject: [PATCH 1/2] add system `config get` command This command fetches and stores the system config in the harbor config file. Signed-off-by: bupd --- cmd/harbor/root/cmd.go | 1 + cmd/harbor/root/config.go | 52 +++++++++++++++++++++++++++++++++++++++ pkg/api/config_handler.go | 24 ++++++++++++++++++ pkg/utils/config.go | 34 +++++++++++++++++++++++-- 4 files changed, 109 insertions(+), 2 deletions(-) create mode 100644 cmd/harbor/root/config.go create mode 100644 pkg/api/config_handler.go diff --git a/cmd/harbor/root/cmd.go b/cmd/harbor/root/cmd.go index 6e474b28..5e9d4ae8 100644 --- a/cmd/harbor/root/cmd.go +++ b/cmd/harbor/root/cmd.go @@ -101,6 +101,7 @@ harbor help root.AddCommand( versionCommand(), LoginCommand(), + ConfigCommand(), project.Project(), registry.Registry(), repositry.Repository(), diff --git a/cmd/harbor/root/config.go b/cmd/harbor/root/config.go new file mode 100644 index 00000000..337a032b --- /dev/null +++ b/cmd/harbor/root/config.go @@ -0,0 +1,52 @@ +package root + +import ( + "context" + "fmt" + "log" + + "github.com/goharbor/go-client/pkg/harbor" + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/user" + "github.com/goharbor/harbor-cli/pkg/api" + "github.com/goharbor/harbor-cli/pkg/utils" + "github.com/goharbor/harbor-cli/pkg/views/login" + "github.com/spf13/cobra" +) + +func ConfigCommand() *cobra.Command { + cmd := &cobra.Command{ + Use: "config", + Short: "Manage system configurations", + Long: "Manage system configurations", + Example: `harbor config get`, + } + + cmd.AddCommand( + GetConfigCmd(), + ) + + return cmd +} + +// Get System configuration command +func GetConfigCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "get", + Short: "get system configurations", + Example: `harbor config get`, + Run: func(cmd *cobra.Command, args []string) { + res, err := api.GetConfiguration() + if err != nil { + log.Fatalf("Error getting configuration: %v", err) + } + + if err = utils.AddConfigToConfigFile(res.Payload, utils.DefaultConfigPath); err != nil { + log.Fatalf("failed to store the credential: %v", err) + } + + utils.PrintPayloadInJSONFormat(res.Payload) + }, + } + + return cmd +} diff --git a/pkg/api/config_handler.go b/pkg/api/config_handler.go new file mode 100644 index 00000000..688171dc --- /dev/null +++ b/pkg/api/config_handler.go @@ -0,0 +1,24 @@ +package api + +import ( + "github.com/goharbor/go-client/pkg/sdk/v2.0/client/configure" + "github.com/goharbor/harbor-cli/pkg/utils" +) + +// GetConfigurationResponse of the system +func GetConfiguration() (*configure.GetConfigurationsOK, error) { + ctx, client, err := utils.ContextWithClient() + if err != nil { + return nil, err + } + + response, err := client.Configure.GetConfigurations( + ctx, + &configure.GetConfigurationsParams{}, + ) + if err != nil { + return nil, err + } + + return response, nil +} diff --git a/pkg/utils/config.go b/pkg/utils/config.go index 1bab413f..7299f953 100644 --- a/pkg/utils/config.go +++ b/pkg/utils/config.go @@ -5,6 +5,7 @@ import ( "os" "path/filepath" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" "github.com/spf13/viper" ) @@ -16,8 +17,9 @@ type Credential struct { } type HarborConfig struct { - CurrentCredentialName string `yaml:"current-credential-name"` - Credentials []Credential `yaml:"credentials"` + CurrentCredentialName string `yaml:"current-credential-name"` + Credentials []Credential `yaml:"credentials"` + Configurations models.ConfigurationsResponse `yaml:"config"` } var ( @@ -78,7 +80,35 @@ func AddCredentialsToConfigFile(credential Credential, configPath string) error return err } return nil +} + +// Adds system configuration to the config file. +func AddConfigToConfigFile(config *models.ConfigurationsResponse, configPath string) error { + if _, err := os.Stat(configPath); os.IsNotExist(err) { + return err + } + + viper.SetConfigFile(configPath) + err := viper.ReadInConfig() + if err != nil { + return err + } + + c := HarborConfig{} + err = viper.Unmarshal(&c) + if err != nil { + return err + } + + c.Configurations = *config + viper.Set("config", c.Configurations) + err = viper.WriteConfig() + if err != nil { + return err + } + + return nil } func GetCredentials(credentialName string) (Credential, error) { From a4fa7c338f9fbf82e0ba6dd4872fb5a7de109ade Mon Sep 17 00:00:00 2001 From: bupd Date: Mon, 10 Jun 2024 02:59:07 +0530 Subject: [PATCH 2/2] add system config `update` command Signed-off-by: bupd --- cmd/harbor/root/cmd.go | 2 +- cmd/harbor/root/config.go | 34 ++++++++++--- pkg/api/config_handler.go | 19 +++++++ pkg/utils/config.go | 28 +++++++++-- pkg/views/config/update/view.go | 89 +++++++++++++++++++++++++++++++++ 5 files changed, 158 insertions(+), 14 deletions(-) create mode 100644 pkg/views/config/update/view.go diff --git a/cmd/harbor/root/cmd.go b/cmd/harbor/root/cmd.go index 5e9d4ae8..d5850ae0 100644 --- a/cmd/harbor/root/cmd.go +++ b/cmd/harbor/root/cmd.go @@ -101,7 +101,7 @@ harbor help root.AddCommand( versionCommand(), LoginCommand(), - ConfigCommand(), + ConfigCommand(), project.Project(), registry.Registry(), repositry.Repository(), diff --git a/cmd/harbor/root/config.go b/cmd/harbor/root/config.go index 337a032b..b0cd8335 100644 --- a/cmd/harbor/root/config.go +++ b/cmd/harbor/root/config.go @@ -1,15 +1,9 @@ package root import ( - "context" - "fmt" - "log" - - "github.com/goharbor/go-client/pkg/harbor" - "github.com/goharbor/go-client/pkg/sdk/v2.0/client/user" "github.com/goharbor/harbor-cli/pkg/api" "github.com/goharbor/harbor-cli/pkg/utils" - "github.com/goharbor/harbor-cli/pkg/views/login" + log "github.com/sirupsen/logrus" "github.com/spf13/cobra" ) @@ -23,6 +17,7 @@ func ConfigCommand() *cobra.Command { cmd.AddCommand( GetConfigCmd(), + UpdateConfigCmd(), ) return cmd @@ -41,7 +36,7 @@ func GetConfigCmd() *cobra.Command { } if err = utils.AddConfigToConfigFile(res.Payload, utils.DefaultConfigPath); err != nil { - log.Fatalf("failed to store the credential: %v", err) + log.Fatalf("failed to store the configuration: %v", err) } utils.PrintPayloadInJSONFormat(res.Payload) @@ -50,3 +45,26 @@ func GetConfigCmd() *cobra.Command { return cmd } + +func UpdateConfigCmd() *cobra.Command { + cmd := &cobra.Command{ + Use: "update", + Short: "update system configurations", + Example: `harbor config update`, + Run: func(cmd *cobra.Command, args []string) { + config, err := utils.GetConfigurations() + if err != nil { + log.Fatalf("failed to get config from file: %v", err) + } + + err = api.UpdateConfiguration(config) + if err != nil { + log.Fatalf("failed to update config: %v", err) + } + + log.Infof("Configuration updated successfully.") + }, + } + + return cmd +} diff --git a/pkg/api/config_handler.go b/pkg/api/config_handler.go index 688171dc..0ff24bf5 100644 --- a/pkg/api/config_handler.go +++ b/pkg/api/config_handler.go @@ -2,6 +2,7 @@ package api import ( "github.com/goharbor/go-client/pkg/sdk/v2.0/client/configure" + "github.com/goharbor/go-client/pkg/sdk/v2.0/models" "github.com/goharbor/harbor-cli/pkg/utils" ) @@ -22,3 +23,21 @@ func GetConfiguration() (*configure.GetConfigurationsOK, error) { return response, nil } + +// Update Configuration of the system +func UpdateConfiguration(config *models.Configurations) error { + ctx, client, err := utils.ContextWithClient() + if err != nil { + return err + } + + _, err = client.Configure.UpdateConfigurations( + ctx, + &configure.UpdateConfigurationsParams{Configurations: config}, + ) + if err != nil { + return err + } + + return nil +} diff --git a/pkg/utils/config.go b/pkg/utils/config.go index 7299f953..dce7e0a1 100644 --- a/pkg/utils/config.go +++ b/pkg/utils/config.go @@ -6,6 +6,7 @@ import ( "path/filepath" "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + "github.com/goharbor/harbor-cli/pkg/views/config/update" "github.com/spf13/viper" ) @@ -17,9 +18,9 @@ type Credential struct { } type HarborConfig struct { - CurrentCredentialName string `yaml:"current-credential-name"` - Credentials []Credential `yaml:"credentials"` - Configurations models.ConfigurationsResponse `yaml:"config"` + CurrentCredentialName string `yaml:"current-credential-name"` + Credentials []Credential `yaml:"credentials"` + Configurations models.Configurations `yaml:"config"` } var ( @@ -82,7 +83,6 @@ func AddCredentialsToConfigFile(credential Credential, configPath string) error return nil } -// Adds system configuration to the config file. func AddConfigToConfigFile(config *models.ConfigurationsResponse, configPath string) error { if _, err := os.Stat(configPath); os.IsNotExist(err) { return err @@ -100,7 +100,10 @@ func AddConfigToConfigFile(config *models.ConfigurationsResponse, configPath str return err } - c.Configurations = *config + // convert ConfigurationsResponse to Configurations + configurations := update.ConvertToConfigurations(config, "", "") + + c.Configurations = *configurations viper.Set("config", c.Configurations) err = viper.WriteConfig() @@ -111,6 +114,21 @@ func AddConfigToConfigFile(config *models.ConfigurationsResponse, configPath str return nil } +func GetConfigurations() (*models.Configurations, error) { + err := viper.ReadInConfig() + if err != nil { + return &models.Configurations{}, err + } + + c := HarborConfig{} + err = viper.Unmarshal(&c) + if err != nil { + return &models.Configurations{}, err + } + + return &c.Configurations, nil +} + func GetCredentials(credentialName string) (Credential, error) { err := viper.ReadInConfig() if err != nil { diff --git a/pkg/views/config/update/view.go b/pkg/views/config/update/view.go new file mode 100644 index 00000000..165d239a --- /dev/null +++ b/pkg/views/config/update/view.go @@ -0,0 +1,89 @@ +package update + +import "github.com/goharbor/go-client/pkg/sdk/v2.0/models" + +// Function to convert ConfigurationsResponse to Configurations +func ConvertToConfigurations( + resp *models.ConfigurationsResponse, + ldapSearchPassword string, + oidcClientSecret string, +) *models.Configurations { + return &models.Configurations{ + AuditLogForwardEndpoint: getStringValue(resp.AuditLogForwardEndpoint), + AuthMode: getStringValue(resp.AuthMode), + BannerMessage: getStringValue(resp.BannerMessage), + HTTPAuthproxyAdminGroups: getStringValue(resp.HTTPAuthproxyAdminGroups), + HTTPAuthproxyAdminUsernames: getStringValue(resp.HTTPAuthproxyAdminUsernames), + HTTPAuthproxyEndpoint: getStringValue(resp.HTTPAuthproxyEndpoint), + HTTPAuthproxyServerCertificate: getStringValue(resp.HTTPAuthproxyServerCertificate), + HTTPAuthproxySkipSearch: getBoolValue(resp.HTTPAuthproxySkipSearch), + HTTPAuthproxyTokenreviewEndpoint: getStringValue(resp.HTTPAuthproxyTokenreviewEndpoint), + HTTPAuthproxyVerifyCert: getBoolValue(resp.HTTPAuthproxyVerifyCert), + LdapBaseDn: getStringValue(resp.LdapBaseDn), + LdapFilter: getStringValue(resp.LdapFilter), + LdapGroupAdminDn: getStringValue(resp.LdapGroupAdminDn), + LdapGroupAttributeName: getStringValue(resp.LdapGroupAttributeName), + LdapGroupBaseDn: getStringValue(resp.LdapGroupBaseDn), + LdapGroupMembershipAttribute: getStringValue(resp.LdapGroupMembershipAttribute), + LdapGroupSearchFilter: getStringValue(resp.LdapGroupSearchFilter), + LdapGroupSearchScope: getInt64Value(resp.LdapGroupSearchScope), + LdapScope: getInt64Value(resp.LdapScope), + LdapSearchDn: getStringValue(resp.LdapSearchDn), + LdapSearchPassword: &ldapSearchPassword, + LdapTimeout: getInt64Value(resp.LdapTimeout), + LdapUID: getStringValue(resp.LdapUID), + LdapURL: getStringValue(resp.LdapURL), + LdapVerifyCert: getBoolValue(resp.LdapVerifyCert), + NotificationEnable: getBoolValue(resp.NotificationEnable), + OIDCAdminGroup: getStringValue(resp.OIDCAdminGroup), + OIDCAutoOnboard: getBoolValue(resp.OIDCAutoOnboard), + OIDCClientID: getStringValue(resp.OIDCClientID), + OIDCClientSecret: &oidcClientSecret, + OIDCEndpoint: getStringValue(resp.OIDCEndpoint), + OIDCExtraRedirectParms: getStringValue(resp.OIDCExtraRedirectParms), + OIDCGroupFilter: getStringValue(resp.OIDCGroupFilter), + OIDCGroupsClaim: getStringValue(resp.OIDCGroupsClaim), + OIDCName: getStringValue(resp.OIDCName), + OIDCScope: getStringValue(resp.OIDCScope), + OIDCUserClaim: getStringValue(resp.OIDCUserClaim), + OIDCVerifyCert: getBoolValue(resp.OIDCVerifyCert), + PrimaryAuthMode: getBoolValue(resp.PrimaryAuthMode), + ProjectCreationRestriction: getStringValue(resp.ProjectCreationRestriction), + QuotaPerProjectEnable: getBoolValue(resp.QuotaPerProjectEnable), + ReadOnly: getBoolValue(resp.ReadOnly), + RobotNamePrefix: getStringValue(resp.RobotNamePrefix), + RobotTokenDuration: getInt64Value(resp.RobotTokenDuration), + ScannerSkipUpdatePulltime: getBoolValue(resp.ScannerSkipUpdatePulltime), + SelfRegistration: getBoolValue(resp.SelfRegistration), + SessionTimeout: getInt64Value(resp.SessionTimeout), + SkipAuditLogDatabase: getBoolValue(resp.SkipAuditLogDatabase), + StoragePerProject: getInt64Value(resp.StoragePerProject), + TokenExpiration: getInt64Value(resp.TokenExpiration), + UaaClientID: getStringValue(resp.UaaClientID), + UaaClientSecret: getStringValue(resp.UaaClientSecret), + UaaEndpoint: getStringValue(resp.UaaEndpoint), + UaaVerifyCert: getBoolValue(resp.UaaVerifyCert), + } +} + +// Helper functions to extract values from configuration items +func getStringValue(item *models.StringConfigItem) *string { + if item != nil { + return &item.Value + } + return nil +} + +func getBoolValue(item *models.BoolConfigItem) *bool { + if item != nil { + return &item.Value + } + return nil +} + +func getInt64Value(item *models.IntegerConfigItem) *int64 { + if item != nil { + return &item.Value + } + return nil +}