Skip to content
This repository has been archived by the owner on Jun 29, 2022. It is now read-only.

cli/cmd: cleanups part 2 #1015

Merged
merged 15 commits into from
Oct 16, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 17 additions & 10 deletions cli/cmd/cluster-apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,16 @@ func runClusterApply(cmd *cobra.Command, args []string) {

//nolint:funlen
func clusterApply(contextLogger *log.Entry) error {
c := initialize(contextLogger)
c, err := initialize(contextLogger)
if err != nil {
return fmt.Errorf("initializing: %w", err)
}

exists, err := clusterExists(c.terraformExecutor)
if err != nil {
return fmt.Errorf("checking if cluster exists: %w", err)
}

exists := clusterExists(contextLogger, &c.terraformExecutor)
if exists && !confirm {
// TODO: We could plan to a file and use it when installing.
if err := c.terraformExecutor.Plan(); err != nil {
Expand Down Expand Up @@ -122,7 +129,9 @@ func clusterApply(contextLogger *log.Entry) error {
}

for _, c := range charts {
cu.upgradeComponent(c.Name, c.Namespace)
if err := cu.upgradeComponent(c.Name, c.Namespace); err != nil {
return fmt.Errorf("upgrading controlplane component %q: %w", c.Name, err)
}
}
}

Expand All @@ -136,17 +145,15 @@ func clusterApply(contextLogger *log.Entry) error {
return nil
}

componentsToApply := []string{}
for _, component := range c.lokomotiveConfig.RootConfig.Components {
componentsToApply = append(componentsToApply, component.Name)
componentObjects, err := componentNamesToObjects(selectComponentNames(nil, *c.lokomotiveConfig.RootConfig))
if err != nil {
return fmt.Errorf("getting component objects: %w", err)
}

contextLogger.Println("Applying component configuration")

if len(componentsToApply) > 0 {
if err := applyComponents(c.lokomotiveConfig, kubeconfig, componentsToApply...); err != nil {
return fmt.Errorf("applying component configuration: %v", err)
}
if err := applyComponents(c.lokomotiveConfig, kubeconfig, componentObjects); err != nil {
return fmt.Errorf("applying component configuration: %v", err)
}

return nil
Expand Down
12 changes: 10 additions & 2 deletions cli/cmd/cluster-destroy.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,9 +48,17 @@ func runClusterDestroy(cmd *cobra.Command, args []string) {
}

func clusterDestroy(contextLogger *log.Entry) error {
c := initialize(contextLogger)
c, err := initialize(contextLogger)
if err != nil {
return fmt.Errorf("initializing: %w", err)
}

exists, err := clusterExists(c.terraformExecutor)
if err != nil {
return fmt.Errorf("checking if cluster exists: %w", err)
}

if !clusterExists(contextLogger, &c.terraformExecutor) {
if !exists {
contextLogger.Println("Cluster already destroyed, nothing to do")

return nil
Expand Down
62 changes: 31 additions & 31 deletions cli/cmd/cluster.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,10 +52,10 @@ type cluster struct {

// initialize does common initialization actions between cluster operations
// and returns created objects to the caller for further use.
func initialize(contextLogger *log.Entry) *cluster {
func initialize(contextLogger *log.Entry) (*cluster, error) {
lokoConfig, diags := getLokoConfig()
if diags.HasErrors() {
contextLogger.Fatal(diags)
return nil, diags
}

p, diags := getConfiguredPlatform(lokoConfig, true)
Expand All @@ -64,7 +64,7 @@ func initialize(contextLogger *log.Entry) *cluster {
contextLogger.Error(diagnostic.Error())
}

contextLogger.Fatal("Errors found while loading cluster configuration")
return nil, fmt.Errorf("loading platform configuration")
}

// Get the configured backend for the cluster. Backend types currently supported: local, s3.
Expand All @@ -74,7 +74,7 @@ func initialize(contextLogger *log.Entry) *cluster {
contextLogger.Error(diagnostic.Error())
}

contextLogger.Fatal("Errors found while loading cluster configuration")
return nil, fmt.Errorf("loading backend configuration")
}

// Use a local backend if no backend is configured.
Expand All @@ -84,41 +84,44 @@ func initialize(contextLogger *log.Entry) *cluster {

assetDir, err := homedir.Expand(p.Meta().AssetDir)
if err != nil {
contextLogger.Fatalf("Error expanding path: %v", err)
return nil, fmt.Errorf("expanding path %q: %v", p.Meta().AssetDir, err)
}

// Validate backend configuration.
if err = b.Validate(); err != nil {
contextLogger.Fatalf("Failed to validate backend configuration: %v", err)
return nil, fmt.Errorf("validating backend configuration: %v", err)
}

ex := initializeTerraform(contextLogger, p, b)
ex, err := initializeTerraform(p, b)
if err != nil {
return nil, fmt.Errorf("initializing Terraform: %w", err)
}

return &cluster{
terraformExecutor: *ex,
platform: p,
lokomotiveConfig: lokoConfig,
assetDir: assetDir,
}
}, nil
}

// initializeTerraform initialized Terraform directory using given backend and platform
// and returns configured executor.
func initializeTerraform(contextLogger *log.Entry, p platform.Platform, b backend.Backend) *terraform.Executor {
func initializeTerraform(p platform.Platform, b backend.Backend) (*terraform.Executor, error) {
assetDir, err := homedir.Expand(p.Meta().AssetDir)
if err != nil {
contextLogger.Fatalf("Error expanding path: %v", err)
return nil, fmt.Errorf("expanding path %q: %w", p.Meta().AssetDir, err)
}

// Render backend configuration.
renderedBackend, err := b.Render()
if err != nil {
contextLogger.Fatalf("Failed to render backend configuration file: %v", err)
return nil, fmt.Errorf("rendering backend configuration: %w", err)
}

// Configure Terraform directory, module and backend.
if err := terraform.Configure(assetDir, renderedBackend); err != nil {
contextLogger.Fatalf("Failed to configure Terraform : %v", err)
return nil, fmt.Errorf("configuring Terraform: %w", err)
}

conf := terraform.Config{
Expand All @@ -128,31 +131,31 @@ func initializeTerraform(contextLogger *log.Entry, p platform.Platform, b backen

ex, err := terraform.NewExecutor(conf)
if err != nil {
contextLogger.Fatalf("Failed to create Terraform executor: %v", err)
return nil, fmt.Errorf("creating Terraform executor: %w", err)
}

if err := p.Initialize(ex); err != nil {
contextLogger.Fatalf("Failed to initialize Platform: %v", err)
return nil, fmt.Errorf("initializing Platform: %w", err)
}

if err := ex.Init(); err != nil {
contextLogger.Fatalf("Failed to initialize Terraform: %v", err)
return nil, fmt.Errorf("running 'terraform init': %w", err)
}

return ex
return ex, nil
}

// clusterExists determines if cluster has already been created by getting all
// outputs from the Terraform. If there is any output defined, it means 'terraform apply'
// run at least once.
func clusterExists(contextLogger *log.Entry, ex *terraform.Executor) bool {
func clusterExists(ex terraform.Executor) (bool, error) {
o := map[string]interface{}{}

if err := ex.Output("", &o); err != nil {
contextLogger.Fatalf("Failed to check if cluster exists: %v", err)
return false, fmt.Errorf("getting Terraform output: %w", err)
}

return len(o) != 0
return len(o) != 0, nil
}

type controlplaneUpdater struct {
Expand Down Expand Up @@ -189,30 +192,25 @@ func (c controlplaneUpdater) getControlplaneValues(name string) (map[string]inte
return values, nil
}

func (c controlplaneUpdater) upgradeComponent(component, namespace string) {
contextLogger := c.contextLogger.WithFields(log.Fields{
"action": "controlplane-upgrade",
"component": component,
})

func (c controlplaneUpdater) upgradeComponent(component, namespace string) error {
actionConfig, err := util.HelmActionConfig(namespace, c.kubeconfig)
if err != nil {
contextLogger.Fatalf("Failed initializing helm: %v", err)
return fmt.Errorf("initializing Helm action: %w", err)
}

helmChart, err := c.getControlplaneChart(component)
if err != nil {
contextLogger.Fatalf("Loading chart from assets failed: %v", err)
return fmt.Errorf("loading chart from assets: %w", err)
}

values, err := c.getControlplaneValues(component)
if err != nil {
contextLogger.Fatalf("Failed to get kubernetes values.yaml from Terraform: %v", err)
return fmt.Errorf("getting chart values from Terraform: %w", err)
}

exists, err := util.ReleaseExists(*actionConfig, component)
if err != nil {
contextLogger.Fatalf("Failed checking if controlplane component is installed: %v", err)
return fmt.Errorf("checking if controlplane component is installed: %w", err)
}

if !exists {
Expand All @@ -227,7 +225,7 @@ func (c controlplaneUpdater) upgradeComponent(component, namespace string) {
if _, err := install.Run(helmChart, values); err != nil {
fmt.Println("Failed!")

contextLogger.Fatalf("Installing controlplane component failed: %v", err)
return fmt.Errorf("installing controlplane component: %w", err)
}

fmt.Println("Done.")
Expand All @@ -242,8 +240,10 @@ func (c controlplaneUpdater) upgradeComponent(component, namespace string) {
if _, err := update.Run(component, helmChart, values); err != nil {
fmt.Println("Failed!")

contextLogger.Fatalf("Updating chart failed: %v", err)
return fmt.Errorf("updating controlplane component: %w", err)
}

fmt.Println("Done.")

return nil
}
42 changes: 25 additions & 17 deletions cli/cmd/component-apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,38 +61,45 @@ func runApply(cmd *cobra.Command, args []string) {
log.SetLevel(log.DebugLevel)
}

if err := componentApply(contextLogger, args); err != nil {
contextLogger.Fatalf("Applying components failed: %v", err)
}
}

// componentApply implements 'lokoctl component apply' separated from CLI
// dependencies.
func componentApply(contextLogger *log.Entry, componentsList []string) error {
lokoConfig, diags := getLokoConfig()
if diags.HasErrors() {
contextLogger.Fatal(diags)
return diags
}

componentsToApply := args
if len(componentsToApply) == 0 {
for _, component := range lokoConfig.RootConfig.Components {
componentsToApply = append(componentsToApply, component.Name)
}
componentObjects, err := componentNamesToObjects(selectComponentNames(componentsList, *lokoConfig.RootConfig))
if err != nil {
return fmt.Errorf("getting component objects: %w", err)
}

kubeconfig, err := getKubeconfig(contextLogger, lokoConfig, false)
if err != nil {
contextLogger.Debugf("Error in finding kubeconfig file: %s", err)
contextLogger.Fatal("Suitable kubeconfig file not found. Did you run 'lokoctl cluster apply' ?")

return fmt.Errorf("suitable kubeconfig file not found. Did you run 'lokoctl cluster apply' ?")
}

if err := applyComponents(lokoConfig, kubeconfig, componentsToApply...); err != nil {
contextLogger.Fatal(err)
if err := applyComponents(lokoConfig, kubeconfig, componentObjects); err != nil {
return fmt.Errorf("applying components: %w", err)
}

return nil
}

func applyComponents(lokoConfig *config.Config, kubeconfig []byte, componentNames ...string) error {
for _, componentName := range componentNames {
// applyComponents reads the configuration of given components and applies them to the cluster pointer
// by given kubeconfig file content.
func applyComponents(lokoConfig *config.Config, kubeconfig []byte, componentObjects []components.Component) error {
for _, component := range componentObjects {
componentName := component.Metadata().Name
fmt.Printf("Applying component '%s'...\n", componentName)

component, err := components.Get(componentName)
if err != nil {
return err
}

componentConfigBody := lokoConfig.LoadComponentConfigBody(componentName)

if diags := component.LoadConfig(componentConfigBody, lokoConfig.EvalContext); diags.HasErrors() {
Expand All @@ -101,10 +108,11 @@ func applyComponents(lokoConfig *config.Config, kubeconfig []byte, componentName
}

if err := util.InstallComponent(component, kubeconfig); err != nil {
return err
return fmt.Errorf("installing component %q: %w", componentName, err)
}

fmt.Printf("Successfully applied component '%s' configuration!\n", componentName)
}

return nil
}
Loading