From d47f91d76a12d3827c53a83ea58c24775f70a30c Mon Sep 17 00:00:00 2001 From: Farshid Tavakolizadeh Date: Tue, 11 Oct 2022 14:52:16 +0200 Subject: [PATCH] refactor(snap): Use snapctl and log packages (#4187) Signed-off-by: Farshid Tavakolizadeh --- snap/local/helper-go/configure.go | 141 +++++++++++++----------------- snap/local/helper-go/install.go | 89 +++++++------------ snap/local/helper-go/main.go | 4 - snap/local/helper-go/options.go | 52 +++++------ 4 files changed, 114 insertions(+), 172 deletions(-) diff --git a/snap/local/helper-go/configure.go b/snap/local/helper-go/configure.go index be3ff140a2..b626391c2c 100644 --- a/snap/local/helper-go/configure.go +++ b/snap/local/helper-go/configure.go @@ -26,6 +26,8 @@ import ( "strings" hooks "github.com/canonical/edgex-snap-hooks/v2" + "github.com/canonical/edgex-snap-hooks/v2/log" + "github.com/canonical/edgex-snap-hooks/v2/snapctl" ) const ( // iota is reset to 0 @@ -99,7 +101,7 @@ func getOptServices() []string { func isDisableAllowed(s string) error { for _, v := range getRequiredServices() { if s == v { - return fmt.Errorf("edgexfoundry:configure: can't disable required service: %s", s) + return fmt.Errorf("can't disable required service: %s", s) } } return nil @@ -112,23 +114,23 @@ func handleSingleService(name, state string) error { switch state { case OFF: - hooks.Debug("edgexfoundry:configure: state: off") - if err := cli.Stop(name, true); err != nil { + log.Debugf("%s state: off", name) + if err := snapctl.Stop(hooks.SnapName + "." + name).Disable().Run(); err != nil { return err } - if err := cli.SetConfig(name, OFF); err != nil { + if err := snapctl.Set(name, OFF).Run(); err != nil { return err } case ON: - hooks.Debug("edgexfoundry:configure: state: on") - if err := cli.Start(name, true); err != nil { + log.Debugf("%s state: on", name) + if err := snapctl.Start(hooks.SnapName + "." + name).Enable().Run(); err != nil { return err } - if err := cli.SetConfig(name, ON); err != nil { + if err := snapctl.Set(name, ON).Run(); err != nil { return err } default: - return fmt.Errorf("edgexfoundry:configure: invalid state %s for service: %s", state, name) + return fmt.Errorf("invalid state %s for service: %s", state, name) } return nil @@ -194,12 +196,12 @@ func rmConsulAclFile() error { } func disableSecretStoreAndRestart() error { - hooks.Info(fmt.Sprintf("edgexfoundry:configure: disabling secret store")) + log.Info("disabling secret store") // if consul_acls.json doesn't exist, then secret-store has already been // disabled, so just return if !consulAclFileExists() { - hooks.Info(fmt.Sprintf("edgexfoundry:configure: secret store is already disabled")) + log.Info("secret store is already disabled") return nil } @@ -222,7 +224,7 @@ func disableSecretStoreAndRestart() error { // snap config option for each service to be needlessly set to "off" // then back to "on"; re-factor handleServices/handleSingleService for _, s := range getEdgeXRefServices() { - if err := cli.Stop(s, false); err != nil { + if err := snapctl.Stop(hooks.SnapName + "." + s).Run(); err != nil { return err } } @@ -231,18 +233,18 @@ func disableSecretStoreAndRestart() error { // TODO - kuiper will be stopped, but not restarted because // additional re-configuration may be needed. for _, s := range getKuiperServices() { - if err := cli.Stop(s, false); err != nil { + if err := snapctl.Stop(hooks.SnapName + "." + s).Run(); err != nil { return err } } // stop redis - if err := cli.Stop("redis", false); err != nil { + if err := snapctl.Stop(hooks.SnapName + "." + "redis").Run(); err != nil { return err } // stop consul - if err := cli.Stop("consul", false); err != nil { + if err := snapctl.Stop(hooks.SnapName + "." + "consul").Run(); err != nil { return err } @@ -258,7 +260,7 @@ func disableSecretStoreAndRestart() error { // - start required services for _, s := range getRequiredServices() { - if err := cli.Start(s, false); err != nil { + if err := snapctl.Start(hooks.SnapName + "." + s).Run(); err != nil { return err } } @@ -266,7 +268,7 @@ func disableSecretStoreAndRestart() error { // Now check config status of the optional EdgeX // services and restart where necessary for _, s := range getEdgeXRefServices() { - status, err := cli.Config(s) + status, err := snapctl.Get(s).Run() if err != nil { return err } @@ -277,7 +279,7 @@ func disableSecretStoreAndRestart() error { // part of the enabledServices (i.e. services // always started), then also start it if status == ON || (status == "" && strings.HasPrefix(s, "core-")) { - if err := cli.Start(s, false); err != nil { + if err := snapctl.Start(hooks.SnapName + "." + s).Run(); err != nil { return err } } @@ -310,12 +312,12 @@ func handleAllServices(deferStartup bool) error { for _, s := range hooks.Services { var serviceList []string - status, err := cli.Config(s) + status, err := snapctl.Get(s).Run() if err != nil { return err } - hooks.Debug(fmt.Sprintf("edgexfoundry:configure: service: %s status: %s", s, status)) + log.Debugf("service: %s status: %s", s, status) err = applyConfigOptions(s) if err != nil { @@ -339,7 +341,7 @@ func handleAllServices(deferStartup bool) error { switch sType { case kuiperService: - hooks.Debug("edgexfoundry:configure: kuiper") + log.Debug("kuiper") switch status { case ON, OFF: @@ -349,11 +351,11 @@ func handleAllServices(deferStartup bool) error { // configuration has been specified; no-op continue default: - return fmt.Errorf("edgexfoundry:configure: invalid value for kuiper: %s", status) + return fmt.Errorf("invalid value for kuiper: %s", status) } case secProxyService: - hooks.Debug("edgexfoundry:configure: proxy") + log.Debug("proxy") switch status { case ON: @@ -363,9 +365,7 @@ func handleAllServices(deferStartup bool) error { // does not automatically handle enabling the secret-store // if/when the proxy is dynamically enabled. if !secretStoreActive { - err = fmt.Errorf("edgexfoundry:configure security-proxy=on not allowed;" + - "secret-store=off") - return err + return fmt.Errorf("security-proxy=on not allowed when secret-store is off") } fallthrough @@ -376,15 +376,15 @@ func handleAllServices(deferStartup bool) error { // configuration has been specified; no-op continue default: - return fmt.Errorf("edgexfoundry:configure: invalid value for security-proxy: %s", status) + return fmt.Errorf("invalid value for security-proxy: %s", status) } case secStoreService: - hooks.Debug("edgexfoundry:configure: secretstore") + log.Debug("secretstore") switch status { case ON: - return fmt.Errorf("edgexfoundry:configure security-secret-store=on not allowed") + return fmt.Errorf("security-secret-store=on not allowed") case OFF: // TODO - this var is used by the secProxyCase to ensure that the // secret store is active when the proxy is being enabled at runtime. @@ -402,11 +402,11 @@ func handleAllServices(deferStartup bool) error { // configuration has been specified; no-op continue default: - return fmt.Errorf("edgexfoundry:configure: invalid value for security-secret-store: %s", status) + return fmt.Errorf("invalid value for security-secret-store: %s", status) } default: - hooks.Debug("edgexfoundry:configure: other service") + log.Debugf("other service: %s", s) // default case for all other services switch status { @@ -422,11 +422,11 @@ func handleAllServices(deferStartup bool) error { // configuration has been specified; no-op continue default: - return fmt.Errorf("edgexfoundry:configure: invalid value for %s: %s", s, status) + return fmt.Errorf("invalid value for %s: %s", s, status) } } - hooks.Debug(fmt.Sprintf("edgexfoundry:configure calling handleServices: %v", serviceList)) + log.Debugf("calling handleServices: %v", serviceList) if err = handleServices(serviceList, status); err != nil { return err } @@ -438,7 +438,7 @@ func handleAllServices(deferStartup bool) error { func checkCoreConfig(services []string) ([]string, error) { // walk thru the list of default services for _, s := range getCoreDefaultServices() { - status, err := cli.Config(s) + status, err := snapctl.Get(s).Run() if err != nil { return nil, err } @@ -449,7 +449,7 @@ func checkCoreConfig(services []string) ([]string, error) { case ON, UNSET: services = append(services, s) default: - err = fmt.Errorf("edgexfoundry:configure: invalid value: %s for %s", status, s) + err = fmt.Errorf("invalid value: %s for %s", status, s) return nil, err } } @@ -459,7 +459,7 @@ func checkCoreConfig(services []string) ([]string, error) { func checkOptConfig(services []string) ([]string, error) { // walk thru the list of default services for _, s := range getOptServices() { - status, err := cli.Config(s) + status, err := snapctl.Get(s).Run() if err != nil { return nil, err } @@ -470,7 +470,7 @@ func checkOptConfig(services []string) ([]string, error) { case ON: services = append(services, s) default: - err = fmt.Errorf("edgexfoundry:configure: invalid value: %s for %s", status, s) + err = fmt.Errorf("invalid value: %s for %s", status, s) return nil, err } } @@ -479,7 +479,7 @@ func checkOptConfig(services []string) ([]string, error) { func checkSecurityConfig(services []string) ([]string, error) { - status, err := cli.Config("security-secret-store") + status, err := snapctl.Get("security-secret-store").Run() if err != nil { return nil, err } @@ -492,12 +492,12 @@ func checkSecurityConfig(services []string) ([]string, error) { // default behavior services = append(services, getSecretStoreServices()...) default: - err = fmt.Errorf("edgexfoundry:configure: invalid setting for security-secret-store: %s", status) + err = fmt.Errorf("invalid setting for security-secret-store: %s", status) return nil, err } // check secret-proxy - status, err = cli.Config("security-proxy") + status, err = snapctl.Get("security-proxy").Run() if err != nil { return nil, err } @@ -509,48 +509,35 @@ func checkSecurityConfig(services []string) ([]string, error) { // default behavior services = append(services, getProxyServices()...) default: - err = fmt.Errorf("edgexfoundry:configure: invalid setting for security-proxy: %s", status) + err = fmt.Errorf("invalid setting for security-proxy: %s", status) return nil, err } return services, nil } func configure() { + log.SetComponentName("configure") + // process the EdgeX >=2.2 app options - processAppOptions() + if err := processAppOptions(); err != nil { + log.Fatalf("error processing app options: %v", err) + } - var debug = false var err error var startServices []string - status, err := cli.Config("debug") - if err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:configure: can't read value of 'debug': %v", err)) - os.Exit(1) - } - if status == "true" { - debug = true - } - - if err = hooks.Init(debug, "edgexfoundry"); err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:configure: initialization failure: %v", err)) - os.Exit(1) - } - hooks.Info("edgexfoundry:configure: started") + log.Info("Started") - val, err := cli.Config("install-mode") + installMode, err := snapctl.Get("install-mode").Run() if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: reading 'install-mode': %v", err)) - os.Exit(1) + log.Fatalf("error reading 'install-mode': %v", err) } - - deferStartup := (val == "defer-startup") - hooks.Info(fmt.Sprintf("edgexfoundry:configure: deferStartup=%v", deferStartup)) + log.Info("install-mode=%s", installMode) + deferStartup := (installMode == "defer-startup") // handle per service configuration and enable/disable services if err = handleAllServices(deferStartup); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: error handling services: %v", err)) - os.Exit(1) + log.Fatalf("error handling services: %v", err) } // Handle deferred startup of services disabled in the install hook. @@ -562,7 +549,7 @@ func configure() { // before the config hook runs), leaving the duplication means less // re-factoring if/when snapd adds a new hook. if deferStartup { - hooks.Info(fmt.Sprintf("edgexfoundry:configure install-mode=defer-startup; starting disabled services")) + log.Info("install-mode=defer-startup; starting disabled services") // add required services startServices = append(startServices, getRequiredServices()...) @@ -570,8 +557,7 @@ func configure() { // check security configuration startServices, err = checkSecurityConfig(startServices) if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: security config error; %v", err)) - os.Exit(1) + log.Fatalf("security service config error: %v", err) } // TODO: don't support kuiper until it's possible to share @@ -581,26 +567,25 @@ func configure() { // check core services startServices, err = checkCoreConfig(startServices) if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: core config error; %v", err)) - os.Exit(1) + log.Fatalf("core service config error: %v", err) } // check optional services startServices, err = checkOptConfig(startServices) if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: optional config error; %v", err)) - os.Exit(1) + log.Fatalf("optional service config error: %v", err) } - // NOTE - the services will be started after the configure hook finishes - if err = cli.StartMultiple(true, startServices...); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure failure starting/enabling services: %v", err)) - os.Exit(1) + for i, s := range startServices { + startServices[i] = hooks.SnapName + "." + s + } + // NOTE: the services will be scheduled to start by snapd after the configure hook exits + if err = snapctl.Start(startServices...).Enable().Run(); err != nil { + log.Fatalf("error starting/enabling services: %v", err) } - if err = cli.UnsetConfig("install-mode"); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install un-setting 'install'; %v", err)) - os.Exit(1) + if err = snapctl.Unset("install-mode").Run(); err != nil { + log.Fatalf("error un-setting 'install'; %v", err) } } } diff --git a/snap/local/helper-go/install.go b/snap/local/helper-go/install.go index 16ef2157ae..dad1a348a2 100644 --- a/snap/local/helper-go/install.go +++ b/snap/local/helper-go/install.go @@ -19,7 +19,6 @@ package main import ( - "fmt" "io/ioutil" "os" "os/exec" @@ -27,6 +26,8 @@ import ( "strings" hooks "github.com/canonical/edgex-snap-hooks/v2" + "github.com/canonical/edgex-snap-hooks/v2/log" + "github.com/canonical/edgex-snap-hooks/v2/snapctl" ) const secretStoreAddTokensCfg = "env.security-secret-store.add-secretstore-tokens" @@ -95,23 +96,10 @@ func getServicesWithConfig() []string { "sys-mgmt-agent", "app-service-configurable"} } -// TODO: re-factor to get this list from snapd using snapctl -func getAllServices() []string { - return []string{"consul", "redis", "postgres", - "kong-daemon", "vault", "security-secretstore-setup", - "security-proxy-setup", "security-bootstrapper-redis", - "security-consul-bootstrapper", "core-command", - "core-data", "core-metadata", "support-notifications", - "support-scheduler", "sys-mgmt-agent", - "kuiper", "app-service-configurable"} -} - // installConfFiles copies service configuration.toml files from $SNAP to $SNAP_DATA func installConfFiles() error { var err error - // TODO: should we continue to do this, since config overrides are - // the preferred way to make configuration changes now? for _, v := range getServicesWithConfig() { destDir := hooks.SnapDataConf + "/" srcDir := hooks.SnapConf + "/" @@ -183,11 +171,11 @@ func installSecretStore() error { // ADD_REGISTRY_ACL_ROLES // We do not have access to the snap configuration in the install hook, // so this just sets the values to the default list of services - if err = cli.SetConfig(secretStoreAddTokensCfg, strings.Join(secretStoreTokens, ",")); err != nil { + if err = snapctl.Set(secretStoreAddTokensCfg, strings.Join(secretStoreTokens, ",")).Run(); err != nil { return err } - if err = cli.SetConfig(secretStoreAddKnownSecretsCfg, strings.Join(secretStoreKnownSecrets, ",")); err != nil { + if err = snapctl.Set(secretStoreAddKnownSecretsCfg, strings.Join(secretStoreKnownSecrets, ",")).Run(); err != nil { return err } @@ -233,7 +221,7 @@ func installConsul() error { // using the same list of services as used in ADD_KNOWN_SECRETS // We do not have access to the snap configuration in the install hook, // so this just sets the values to the default list of services - if err = cli.SetConfig(consulAddRegistryACLRolesCfg, strings.Join(secretStoreTokens, ",")); err != nil { + if err = snapctl.Set(consulAddRegistryACLRolesCfg, strings.Join(secretStoreTokens, ",")).Run(); err != nil { return err } @@ -324,67 +312,52 @@ func installRedis() error { } func install() { - var debug = false - var err error - - status, err := cli.Config("debug") - if err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:install: can't read value of 'debug': %v", err)) - os.Exit(1) - } - if status == "true" { - debug = true - } - - if err = hooks.Init(debug, "edgexfoundry"); err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:install: initialization failure: %v", err)) - os.Exit(1) + log.SetComponentName("install") - } + var err error if err = installConfFiles(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install: %v", err)) - os.Exit(1) + log.Fatalf("Error installing config files: %v", err) } if err = installKuiper(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install: %v", err)) - os.Exit(1) + log.Fatalf("Error installing eKuiper: %v", err) } if err = installSecretStore(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install: %v", err)) - os.Exit(1) + log.Fatalf("Error installing secret store: %v", err) } if err = installConsul(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install: %v", err)) - os.Exit(1) + log.Fatalf("Error installing consul: %v", err) } if err = installProxy(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install %v", err)) - os.Exit(1) + log.Fatalf("Error installing proxy: %v", err) } if err = installRedis(); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install %v", err)) - os.Exit(1) - } - - // Stop and disable all *enabled* services as they will be - // re-enabled in the configure hook if the config option - // 'install-mode=defer-startup'. - for _, s := range getAllServices() { - hooks.Info(fmt.Sprintf("edgexfoundry:install disabling service: %s", s)) - if err = cli.Stop(s, true); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install can't disable: %s; %v", s, err)) - os.Exit(1) + log.Fatalf("Error installing redis: %v", err) + } + + // Stop and disable all services as they will be + // re-enabled in the configure hook if install-mode=defer-startup and + // they have their state set to "on". + var services []string + if serviceMap, err := snapctl.Services().Run(); err != nil { + log.Fatalf("Error getting list of services: %v", err) + } else { + for k := range serviceMap { + services = append(services, k) } } - if err = cli.SetConfig("install-mode", "defer-startup"); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:install setting 'install-mode'; %v", err)) - os.Exit(1) + log.Infof("Disabling all services: %v", services) + if err = snapctl.Stop(services...).Disable().Run(); err != nil { + log.Fatalf("Error disabling services: %v", err) + } + + if err = snapctl.Set("install-mode", "defer-startup").Run(); err != nil { + log.Fatalf("Error setting 'install-mode'; %v", err) } } diff --git a/snap/local/helper-go/main.go b/snap/local/helper-go/main.go index 3d77c974dc..d2319ccfef 100644 --- a/snap/local/helper-go/main.go +++ b/snap/local/helper-go/main.go @@ -18,12 +18,8 @@ package main import ( "os" - - hooks "github.com/canonical/edgex-snap-hooks/v2" ) -var cli *hooks.CtlCli = hooks.NewSnapCtl() - func main() { subCommand := os.Args[1] switch subCommand { diff --git a/snap/local/helper-go/options.go b/snap/local/helper-go/options.go index 3e5586d344..702e1d763e 100644 --- a/snap/local/helper-go/options.go +++ b/snap/local/helper-go/options.go @@ -22,17 +22,19 @@ import ( "os" hooks "github.com/canonical/edgex-snap-hooks/v2" - app_options "github.com/canonical/edgex-snap-hooks/v2/options" + "github.com/canonical/edgex-snap-hooks/v2/log" + opt "github.com/canonical/edgex-snap-hooks/v2/options" + "github.com/canonical/edgex-snap-hooks/v2/snapctl" ) func applyConfigOptions(service string) error { - envJSON, err := cli.Config(hooks.EnvConfig + "." + service) + envJSON, err := snapctl.Get(hooks.EnvConfig + "." + service).Run() if err != nil { return fmt.Errorf("failed to read config options for %s: %v", service, err) } if envJSON != "" { - hooks.Debug(fmt.Sprintf("edgexfoundry:configure-options: service: %s envJSON: %s", service, envJSON)) + log.Debugf("service: %s envJSON: %s", service, envJSON) if err := hooks.HandleEdgeXConfig(service, envJSON, nil); err != nil { return err } @@ -46,37 +48,24 @@ func options() { service := flagset.String("service", "", "Handle config options of a single service only") flagset.Parse(os.Args[2:]) - fmt.Println("Configuring options for service: " + *service) + log.SetComponentName("options") - debug, err := cli.Config("debug") - if err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:configure-options: can't read value of 'debug': %v", err)) - os.Exit(1) - } - - if err = hooks.Init(debug == "true", "edgexfoundry"); err != nil { - fmt.Println(fmt.Sprintf("edgexfoundry:configure-options: initialization failure: %v", err)) - os.Exit(1) - } - - hooks.Info("edgexfoundry:configure-options: handling config options for a single service: " + *service) + log.Info("Configuring options for " + *service) // process the EdgeX >=2.2 snap options - err = app_options.ProcessAppCustomOptions(*service) - if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure-options: could not process custom options: %v", err)) - os.Exit(1) + if err := opt.ProcessAppCustomOptions(*service); err != nil { + log.Fatalf("Could not process custom options: %v", err) } // process the legacy snap options if err := applyConfigOptions(*service); err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure-options: error handling config options for %s: %v", *service, err)) - os.Exit(1) + log.Fatalf("Error handling config options for %s: %v", *service, err) } } -func processAppOptions() { - err := app_options.ProcessAppConfig( +func processAppOptions() error { + log.Info("Processing config options") + err := opt.ProcessConfig( "core-data", "core-metadata", "core-command", @@ -89,8 +78,7 @@ func processAppOptions() { "sys-mgmt-agent", ) if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure could not process config options: %v", err)) - os.Exit(1) + return fmt.Errorf("could not process config options: %v", err) } // After installation, the configure hook initiates the deferred startup of services, @@ -100,18 +88,18 @@ func processAppOptions() { // The following options should not be processed within the configure hook during // the initial installation (install-mode=defer-startup). They should be processed // only on follow-up calls to the configure hook (i.e. when snap set/unset is called) - installMode, err := hooks.NewSnapCtl().Config("install-mode") // this set in the install hook + installMode, err := snapctl.Get("install-mode").Run() // this set in the install hook if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure failed to read 'install-mode': %s", err)) - os.Exit(1) + return fmt.Errorf("failed to read 'install-mode': %s", err) } if installMode != "defer-startup" { - err = app_options.ProcessAppCustomOptions( + err = opt.ProcessAppCustomOptions( "secrets-config", // also processed in security-proxy-post-setup.sh ) if err != nil { - hooks.Error(fmt.Sprintf("edgexfoundry:configure: could not process custom options: %v", err)) - os.Exit(1) + return fmt.Errorf("could not process custom options: %v", err) } } + + return nil }