diff --git a/cmd/bootstrap/bootstrap.go b/cmd/bootstrap/bootstrap.go index be892677a..8d740a90e 100644 --- a/cmd/bootstrap/bootstrap.go +++ b/cmd/bootstrap/bootstrap.go @@ -1,8 +1,6 @@ package bootstrap import ( - "fmt" - "github.com/spf13/cobra" "opendev.org/airship/airshipctl/pkg/environment" @@ -12,12 +10,11 @@ import ( func NewBootstrapCommand(rootSettings *environment.AirshipCTLSettings) *cobra.Command { bootstrapRootCmd := &cobra.Command{ Use: "bootstrap", - Short: "bootstraps airshipctl", - Run: func(cmd *cobra.Command, args []string) { - out := cmd.OutOrStdout() - fmt.Fprintf(out, "Under construction\n") - }, + Short: "Bootstrap ephemeral Kubernetes cluster", } + ISOGenCmd := NewISOGenCommand(bootstrapRootCmd, rootSettings) + bootstrapRootCmd.AddCommand(ISOGenCmd) + return bootstrapRootCmd } diff --git a/cmd/bootstrap/bootstrap_isogen.go b/cmd/bootstrap/bootstrap_isogen.go new file mode 100644 index 000000000..90375d9c2 --- /dev/null +++ b/cmd/bootstrap/bootstrap_isogen.go @@ -0,0 +1,24 @@ +package bootstrap + +import ( + "github.com/spf13/cobra" + + "opendev.org/airship/airshipctl/pkg/bootstrap/isogen" + "opendev.org/airship/airshipctl/pkg/environment" +) + +// NewISOGenCommand creates a new command for ISO image creation +func NewISOGenCommand(parent *cobra.Command, rootSettings *environment.AirshipCTLSettings) *cobra.Command { + settings := &isogen.Settings{AirshipCTLSettings: rootSettings} + imageGen := &cobra.Command{ + Use: "isogen", + Short: "Generate bootstrap ISO image", + RunE: func(cmd *cobra.Command, args []string) error { + return isogen.GenerateBootstrapIso(settings, args, cmd.OutOrStdout()) + }, + } + + settings.InitFlags(imageGen) + + return imageGen +} diff --git a/cmd/bootstrap/bootstrap_test.go b/cmd/bootstrap/bootstrap_test.go new file mode 100644 index 000000000..9e76a0ba6 --- /dev/null +++ b/cmd/bootstrap/bootstrap_test.go @@ -0,0 +1,26 @@ +package bootstrap_test + +import ( + "testing" + + "opendev.org/airship/airshipctl/cmd/bootstrap" + "opendev.org/airship/airshipctl/testutil" +) + +func TestBootstrap(t *testing.T) { + tests := []*testutil.CmdTest{ + { + Name: "bootstrap-cmd-with-defaults", + CmdLine: "", + Cmd: bootstrap.NewBootstrapCommand(nil), + }, + { + Name: "bootstrap-isogen-cmd-with-help", + CmdLine: "isogen --help", + Cmd: bootstrap.NewBootstrapCommand(nil), + }, + } + for _, tt := range tests { + testutil.RunTest(t, tt) + } +} diff --git a/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-cmd-with-defaults.golden b/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-cmd-with-defaults.golden new file mode 100644 index 000000000..69b9f2045 --- /dev/null +++ b/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-cmd-with-defaults.golden @@ -0,0 +1,13 @@ +Bootstrap ephemeral Kubernetes cluster + +Usage: + bootstrap [command] + +Available Commands: + help Help about any command + isogen Generate bootstrap ISO image + +Flags: + -h, --help help for bootstrap + +Use "bootstrap [command] --help" for more information about a command. diff --git a/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-isogen-cmd-with-help.golden b/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-isogen-cmd-with-help.golden new file mode 100644 index 000000000..4bc76b9df --- /dev/null +++ b/cmd/bootstrap/testdata/TestBootstrapGoldenOutput/bootstrap-isogen-cmd-with-help.golden @@ -0,0 +1,8 @@ +Generate bootstrap ISO image + +Usage: + bootstrap isogen [flags] + +Flags: + -c, --config string Configuration file path for ISO builder container. + -h, --help help for isogen diff --git a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden index 02acb4859..91771afdc 100644 --- a/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden +++ b/cmd/testdata/TestRootGoldenOutput/rootCmd-with-defaults.golden @@ -5,7 +5,7 @@ Usage: Available Commands: argo argo is the command line interface to Argo - bootstrap bootstraps airshipctl + bootstrap Bootstrap ephemeral Kubernetes cluster completion Generate autocompletions script for the specified shell (bash or zsh) document manages deployment documents help Help about any command diff --git a/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden b/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden index 5b9967915..314a7025a 100644 --- a/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden +++ b/cmd/testdata/TestRootGoldenOutput/specialized-rootCmd-with-bootstrap.golden @@ -4,7 +4,7 @@ Usage: airshipctl [command] Available Commands: - bootstrap bootstraps airshipctl + bootstrap Bootstrap ephemeral Kubernetes cluster help Help about any command version Show the version number of airshipctl diff --git a/go.mod b/go.mod index fcb5ac422..7b3b114bb 100644 --- a/go.mod +++ b/go.mod @@ -110,6 +110,6 @@ require ( k8s.io/metrics v0.0.0-20190516231729-8b83d5daaa8f // indirect k8s.io/utils v0.0.0-20190529001817-6999998975a7 // indirect sigs.k8s.io/kustomize v2.0.3+incompatible // indirect - sigs.k8s.io/yaml v1.1.0 // indirect + sigs.k8s.io/yaml v1.1.0 vbom.ml/util v0.0.0-20180919145318-efcd4e0f9787 // indirect ) diff --git a/pkg/bootstrap/isogen/command.go b/pkg/bootstrap/isogen/command.go new file mode 100644 index 000000000..7cf1c4547 --- /dev/null +++ b/pkg/bootstrap/isogen/command.go @@ -0,0 +1,28 @@ +package isogen + +import ( + "errors" + "fmt" + "io" + + "opendev.org/airship/airshipctl/pkg/util" +) + +// ErrNotImplemented returned for not implemented features +var ErrNotImplemented = errors.New("Error. Not implemented") + +// GenerateBootstrapIso will generate data for cloud init and start ISO builder container +func GenerateBootstrapIso(settings *Settings, args []string, out io.Writer) error { + if settings.IsogenConfigFile == "" { + fmt.Fprintln(out, "Reading config file location from global settings is not supported") + return ErrNotImplemented + } + + cfg := Config{} + + if err := util.ReadYAMLFile(settings.IsogenConfigFile, &cfg); err != nil { + return err + } + fmt.Println("Under construction") + return nil +} diff --git a/pkg/bootstrap/isogen/config.go b/pkg/bootstrap/isogen/config.go new file mode 100644 index 000000000..50bb7fe48 --- /dev/null +++ b/pkg/bootstrap/isogen/config.go @@ -0,0 +1,56 @@ +package isogen + +import ( + "github.com/spf13/cobra" + + "sigs.k8s.io/yaml" + + "opendev.org/airship/airshipctl/pkg/environment" +) + +// Settings settings for isogen command +type Settings struct { + *environment.AirshipCTLSettings + + // Configuration file (YAML-formatted) path for ISO builder container. + IsogenConfigFile string +} + +// InitFlags adds falgs and their default settings for isogen command +func (i *Settings) InitFlags(cmd *cobra.Command) { + flags := cmd.Flags() + flags.StringVarP(&i.IsogenConfigFile, "config", "c", "", "Configuration file path for ISO builder container.") +} + +// Config ISO builder container configuration +type Config struct { + // Configuration parameters for container + Container Container `json:"container,omitempty"` + // Configuration parameters for ISO builder + Builder Builder `json:"builder,omitempty"` +} + +// Container parameters +type Container struct { + // Container volume directory binding. + Volume string `json:"volume,omitempty"` + // ISO generator container image URL + Image string `json:"image,omitempty"` + // Container Runtime Interface driver + ContainerRuntime string `json:"containerRuntime,omitempty"` +} + +// Builder parameters +type Builder struct { + // Cloud Init user-data file name placed to the container volume root + UserDataFileName string `json:"userDataFileName,omitempty"` + // Cloud Init network-config file name placed to the container volume root + NetworkConfigFileName string `json:"networkConfigFileName,omitempty"` + // File name for output metadata + OutputMetadataFileName string `json:"outputMetadataFileName,omitempty"` +} + +// ToYAML serializes confid to YAML +func (c *Config) ToYAML() ([]byte, error) { + return yaml.Marshal(c) +} diff --git a/pkg/util/configreader.go b/pkg/util/configreader.go new file mode 100644 index 000000000..015e42f20 --- /dev/null +++ b/pkg/util/configreader.go @@ -0,0 +1,17 @@ +package util + +import ( + "io/ioutil" + + "sigs.k8s.io/yaml" +) + +// ReadYAMLFile reads YAML-formatted configuration file and +// de-serializes it to a given object +func ReadYAMLFile(filePath string, cfg interface{}) error { + data, err := ioutil.ReadFile(filePath) + if err != nil { + return err + } + return yaml.Unmarshal(data, cfg) +}