From 5d83122b17c4f599c22251d70783f9e4649a1f75 Mon Sep 17 00:00:00 2001
From: Drew Walters <andrew.walters@att.com>
Date: Mon, 10 Feb 2020 17:44:40 -0600
Subject: [PATCH] [#6] Add config init subcommand

This change introduces logic for the config init subcommand, which
generates an airshipctl configuration file with default values. The
default values are extracted from constants and change when the source
code is updated.

Closes #6

Change-Id: I452e26bc5a924f0cdcd3153a9b124d23e2e5b1f0
Signed-off-by: Drew Walters <andrew.walters@att.com>
---
 .gitignore                                    |  1 +
 cmd/config/init.go                            | 12 +++--
 cmd/config/init_test.go                       |  6 +--
 ...ig-init.golden => config-init-help.golden} |  4 +-
 pkg/config/config.go                          | 20 +++++++-
 pkg/config/constants.go                       | 10 ++++
 pkg/config/utils.go                           | 49 ++++++++++++++++---
 7 files changed, 85 insertions(+), 17 deletions(-)
 rename cmd/config/testdata/TestConfigInitGoldenOutput/{config-init.golden => config-init-help.golden} (53%)

diff --git a/.gitignore b/.gitignore
index efe3b790b..4dbe546fa 100644
--- a/.gitignore
+++ b/.gitignore
@@ -8,6 +8,7 @@ bin/
 
 # Test binary, build wiith `go test -c`
 *.test
+*.example
 
 # Output of the go coverage tool
 *.out
diff --git a/cmd/config/init.go b/cmd/config/init.go
index f381c3579..31f5c8b70 100644
--- a/cmd/config/init.go
+++ b/cmd/config/init.go
@@ -1,4 +1,4 @@
-/*l
+/*
 Copyright 2014 The Kubernetes Authors.
 
 Licensed under the Apache License, Version 2.0 (the "License");
@@ -20,7 +20,6 @@ import (
 	"github.com/spf13/cobra"
 
 	"opendev.org/airship/airshipctl/pkg/environment"
-	"opendev.org/airship/airshipctl/pkg/errors"
 )
 
 var (
@@ -33,7 +32,14 @@ func NewCmdConfigInit(rootSettings *environment.AirshipCTLSettings) *cobra.Comma
 		Use:   "init",
 		Short: configInitLong,
 		RunE: func(cmd *cobra.Command, args []string) error {
-			return errors.ErrNotImplemented{}
+			c := rootSettings.Config()
+
+			err := c.PersistConfig()
+			if err != nil {
+				return err
+			}
+
+			return nil
 		},
 	}
 
diff --git a/cmd/config/init_test.go b/cmd/config/init_test.go
index 0ce36c2de..ca9c919cf 100644
--- a/cmd/config/init_test.go
+++ b/cmd/config/init_test.go
@@ -19,17 +19,15 @@ package config
 import (
 	"testing"
 
-	"opendev.org/airship/airshipctl/pkg/errors"
 	"opendev.org/airship/airshipctl/testutil"
 )
 
 func TestConfigInit(t *testing.T) {
 	cmdTests := []*testutil.CmdTest{
 		{
-			Name:    "config-init",
-			CmdLine: "",
+			Name:    "config-init-help",
+			CmdLine: "-h",
 			Cmd:     NewCmdConfigInit(nil),
-			Error:   errors.ErrNotImplemented{},
 		},
 	}
 
diff --git a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init.golden b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden
similarity index 53%
rename from cmd/config/testdata/TestConfigInitGoldenOutput/config-init.golden
rename to cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden
index 319f291f4..6303793da 100644
--- a/cmd/config/testdata/TestConfigInitGoldenOutput/config-init.golden
+++ b/cmd/config/testdata/TestConfigInitGoldenOutput/config-init-help.golden
@@ -1,7 +1,7 @@
-Error: Not implemented
+Generate initial configuration files for airshipctl
+
 Usage:
   init [flags]
 
 Flags:
   -h, --help   help for init
-
diff --git a/pkg/config/config.go b/pkg/config/config.go
index 18a2e72b9..4f3bc6db4 100644
--- a/pkg/config/config.go
+++ b/pkg/config/config.go
@@ -82,7 +82,25 @@ func (c *Config) loadKubeConfig(kubeConfigPath string) error {
 	// If I can read from the file, load from it
 	var err error
 	if _, err = os.Stat(kubeConfigPath); os.IsNotExist(err) {
-		c.kubeConfig = clientcmdapi.NewConfig()
+		// Default kubeconfig matching Airship target cluster
+		c.kubeConfig = &clientcmdapi.Config{
+			Clusters: map[string]*clientcmdapi.Cluster{
+				AirshipDefaultContext: {
+					Server: "https://172.17.0.1:6443",
+				},
+			},
+			AuthInfos: map[string]*clientcmdapi.AuthInfo{
+				"admin": {
+					Username: "airship-admin",
+				},
+			},
+			Contexts: map[string]*clientcmdapi.Context{
+				AirshipDefaultContext: {
+					Cluster:  AirshipDefaultContext,
+					AuthInfo: "admin",
+				},
+			},
+		}
 		return nil
 	} else if err != nil {
 		return err
diff --git a/pkg/config/constants.go b/pkg/config/constants.go
index 936c238d1..fd4369631 100644
--- a/pkg/config/constants.go
+++ b/pkg/config/constants.go
@@ -27,6 +27,16 @@ const (
 
 	AirshipConfigEnv     = "AIRSHIPCONFIG"
 	AirshipKubeConfigEnv = "AIRSHIP_KUBECONFIG"
+
+	AirshipDefaultContext              = "default"
+	AirshipDefaultManifest             = "default"
+	AirshipDefaultManifestRepo         = "treasuremap"
+	AirshipDefaultManifestRepoLocation = "https://opendev.org/airship/" + AirshipDefaultManifestRepo
+
+	// Modules
+	AirshipDefaultBootstrapImage = "quay.io/airshipit/isogen:latest"
+	AirshipDefaultIsoURL         = "http://localhost:8099/debian-custom.iso"
+	AirshipDefaultRemoteType     = "redfish"
 )
 
 // Constants defining CLI flags
diff --git a/pkg/config/utils.go b/pkg/config/utils.go
index 52ff7218a..25a3b5f93 100644
--- a/pkg/config/utils.go
+++ b/pkg/config/utils.go
@@ -19,13 +19,48 @@ package config
 // NewConfig returns a newly initialized Config object
 func NewConfig() *Config {
 	return &Config{
-		Kind:          AirshipConfigKind,
-		APIVersion:    AirshipConfigApiVersion,
-		Clusters:      make(map[string]*ClusterPurpose),
-		Contexts:      make(map[string]*Context),
-		AuthInfos:     make(map[string]*AuthInfo),
-		Manifests:     make(map[string]*Manifest),
-		ModulesConfig: NewModules(),
+		Kind:       AirshipConfigKind,
+		APIVersion: AirshipConfigApiVersion,
+		Clusters:   make(map[string]*ClusterPurpose),
+		AuthInfos:  make(map[string]*AuthInfo),
+		Contexts: map[string]*Context{
+			AirshipDefaultContext: {
+				Manifest: AirshipDefaultManifest,
+			},
+		},
+		Manifests: map[string]*Manifest{
+			AirshipDefaultManifest: {
+				Repository: &Repository{
+					URLString: AirshipDefaultManifestRepoLocation,
+					CheckoutOptions: &RepoCheckout{
+						CommitHash: "master",
+						Branch:     "master",
+						RemoteRef:  "master",
+					},
+				},
+				TargetPath: "/tmp/" + AirshipDefaultManifest,
+			},
+		},
+		ModulesConfig: &Modules{
+			BootstrapInfo: map[string]*Bootstrap{
+				AirshipDefaultContext: {
+					Container: &Container{
+						Volume:           "/srv/iso:/config",
+						Image:            AirshipDefaultBootstrapImage,
+						ContainerRuntime: "docker",
+					},
+					Builder: &Builder{
+						UserDataFileName:       "user-data",
+						NetworkConfigFileName:  "network-config",
+						OutputMetadataFileName: "output-metadata.yaml",
+					},
+					RemoteDirect: &RemoteDirect{
+						RemoteType: AirshipDefaultRemoteType,
+						IsoURL:     AirshipDefaultIsoURL,
+					},
+				},
+			},
+		},
 	}
 }