From 438102702bfb08520095dd04213ed2fbef453eb9 Mon Sep 17 00:00:00 2001 From: Andrew Bays Date: Mon, 21 Oct 2019 14:45:22 -0400 Subject: [PATCH] Move automation prep call to prepare_manifests Change-Id: I8c74cc4c1ef60d23e34cc00dd32f765c29f3187c --- pkg/automation/automation.go | 9 +++--- pkg/automation/baremetal.go | 40 ++++++++++++++++--------- pkg/manifests/manifests.go | 16 ++++++---- pkg/site/site.go | 71 +++++++++++++++++++++++++++++++++++++------- 4 files changed, 103 insertions(+), 33 deletions(-) diff --git a/pkg/automation/automation.go b/pkg/automation/automation.go index 3a4d655..d965c2c 100644 --- a/pkg/automation/automation.go +++ b/pkg/automation/automation.go @@ -16,10 +16,11 @@ type AutomatedDeploymentParams struct { } type AutomatedDeploymentInterface interface { - PrepareBastion(map[string]string) error // Prepare host for automation - DeployMasters() error // Deploy cluster masters - DeployWorkers() error // Deploy cluster workers - DestroyCluster() error // Destroy the cluster + PrepareAutomation(map[string]string) error // Initial host preparation for automation, before finalizing manifests + FinalizeAutomation() error // Final host preparation for automation, after finalizing manifests + DeployMasters() error // Deploy cluster masters + DeployWorkers() error // Deploy cluster workers + DestroyCluster() error // Destroy the cluster } var ( diff --git a/pkg/automation/baremetal.go b/pkg/automation/baremetal.go index 94ff23a..536e2e7 100644 --- a/pkg/automation/baremetal.go +++ b/pkg/automation/baremetal.go @@ -77,27 +77,27 @@ func newBaremetal(params AutomatedDeploymentParams) (AutomatedDeploymentInterfac }, nil } -func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]string) error { +func (bad baremetalAutomatedDeployment) PrepareAutomation(requirements map[string]string) error { // Download repo automationDestination := fmt.Sprintf("%s/%s/baremetal_automation", bad.siteBuildPath, bad.siteName) // Clear baremetal automation repo if it already exists os.RemoveAll(automationDestination) - log.Printf("baremetalAutomatedDeployment: PrepareBastion: downloading baremetal automation repo (%s)\n", automationRemoteSource) + log.Printf("baremetalAutomatedDeployment: PrepareAutomation: downloading baremetal automation repo (%s)...\n", automationRemoteSource) client := &getter.Client{Src: automationRemoteSource, Dst: automationDestination, Mode: getter.ClientModeAny} err := client.Get() if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error cloning baremetal automation repository: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error cloning baremetal automation repository: %s", err) } // Copy the site's site-config.yaml into the automation repo siteConfigSource, err := os.Open(fmt.Sprintf("%s/%s/site/00_install-config/site-config.yaml", bad.siteBuildPath, bad.siteName)) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error opening source site config file: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error opening source site config file: %s", err) } defer siteConfigSource.Close() @@ -109,7 +109,7 @@ func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]s siteConfigDestination, err := os.OpenFile(siteConfigDestinationPath, os.O_RDWR|os.O_CREATE, 0666) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error opening destination site config file: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error opening destination site config file: %s", err) } defer siteConfigDestination.Close() @@ -117,9 +117,13 @@ func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]s _, err = io.Copy(siteConfigDestination, siteConfigSource) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error writing destination site config file: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error writing destination site config file: %s", err) } + log.Printf("baremetalAutomatedDeployment: PrepareAutomation: finished downloading baremetal automation repo (%s)\n", automationRemoteSource) + + log.Printf("baremetalAutomatedDeployment: PrepareAutomation: injecting version selections into automation repo...\n") + // Examine requirements to check for oc or openshift-install version selection. // If they are found, inject them into the automation's images_and_binaries.sh script // to override the default @@ -131,13 +135,13 @@ func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]s err = utils.ReplaceFileText(binaryVersionsPath, "OCP_CLIENT_BINARY_URL=\"\"", fmt.Sprintf("OCP_CLIENT_BINARY_URL=\"%s\"", requirementSource)) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error injecting oc binary version: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error injecting oc binary version: %s", err) } case "openshift-install": err = utils.ReplaceFileText(binaryVersionsPath, "OCP_INSTALL_BINARY_URL=\"\"", fmt.Sprintf("OCP_INSTALL_BINARY_URL=\"%s\"", requirementSource)) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error injecting openshift-install binary version: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error injecting openshift-install binary version: %s", err) } } } @@ -151,7 +155,7 @@ func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]s err = yaml.Unmarshal(siteConfigFile, &siteConfig) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error unmarshalling site-config.yaml: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error unmarshalling site-config.yaml: %s", err) } if config, ok := siteConfig["config"].(map[interface{}]interface{}); ok { @@ -164,27 +168,35 @@ func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]s err = utils.ReplaceFileText(rhcosVersionsPath, "OPENSHIFT_RHCOS_MAJOR_REL=\"\"", fmt.Sprintf("OPENSHIFT_RHCOS_MAJOR_REL=\"%s\"", parts[1])) if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error injecting RHCOS image version: %s", err) + return fmt.Errorf("baremetalAutomatedDeployment: PrepareAutomation: error injecting RHCOS image version: %s", err) } } } } + log.Printf("baremetalAutomatedDeployment: PrepareAutomation: finished injecting version selections into automation repo\n") + + return nil +} + +func (bad baremetalAutomatedDeployment) FinalizeAutomation() error { + automationDestination := fmt.Sprintf("%s/%s/baremetal_automation", bad.siteBuildPath, bad.siteName) + // Execute automation's prep_bm_host script cmd := exec.Command(fmt.Sprintf("%s/prep_bm_host.sh", automationDestination)) cmd.Dir = automationDestination cmd.Stdout = os.Stdout cmd.Stderr = os.Stderr - log.Println("baremetalAutomatedDeployment: PrepareBastion: running baremetal automation host preparation script...") + log.Println("baremetalAutomatedDeployment: FinalizeAutomation: running baremetal automation host preparation script...") - err = cmd.Run() + err := cmd.Run() if err != nil { - return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error running baremetal automation host preparation script") + return fmt.Errorf("baremetalAutomatedDeployment: FinalizeAutomation: error running baremetal automation host preparation script") } - log.Println("baremetalAutomatedDeployment: PrepareBastion: finished running automation host preparation script") + log.Println("baremetalAutomatedDeployment: FinalizeAutomation: finished running automation host preparation script") return nil } diff --git a/pkg/manifests/manifests.go b/pkg/manifests/manifests.go index 90ef926..f5fe0f0 100644 --- a/pkg/manifests/manifests.go +++ b/pkg/manifests/manifests.go @@ -79,7 +79,7 @@ func NameFromGVKN(GVKN string) string { } // utility to merge manifests -func MergeManifests(content string, siteBuildPath string) { +func MergeManifests(content string, siteBuildPath string) string { manifests := strings.Split(content, "\n---\n") kustomizeManifests := make(map[string]map[interface{}]interface{}) @@ -216,10 +216,16 @@ func MergeManifests(content string, siteBuildPath string) { log.Fatal(fmt.Sprintf("Error moving to final manifests folder: %s", err)) os.Exit(1) } else { - log.Println(fmt.Sprintf("*** Manifest generation finished. You can run now: %s/requirements/openshift-install create cluster --dir=%s/final_manifests to create the site cluster ***", siteBuildPath, siteBuildPath)) - log.Println(fmt.Sprintf("If using UPI you can generate ignition files with: %s/requirements/openshift-install create ignition-configs --dir=%s/final_manifests", siteBuildPath, siteBuildPath)) - log.Println(fmt.Sprintf("A profile.env file has been generated inside %s/profile.env, you can source it before starting the openshift-install command", siteBuildPath)) - log.Println(fmt.Sprintf("In order to destroy the cluster you can run: %s/requirements/openshift-install destroy cluster --dir %s/final_manifests", siteBuildPath, siteBuildPath)) + var builder strings.Builder + + fmt.Fprintf(&builder, "*** Manifest generation finished. You can run now: %s/requirements/openshift-install create cluster --dir=%s/final_manifests to create the site cluster ***\n", siteBuildPath, siteBuildPath) + fmt.Fprintf(&builder, "If using UPI you can generate ignition files with: %s/requirements/openshift-install create ignition-configs --dir=%s/final_manifests", siteBuildPath, siteBuildPath) + fmt.Fprintf(&builder, "A profile.env file has been generated inside %s/profile.env, you can source it before starting the openshift-install command", siteBuildPath) + fmt.Fprintf(&builder, "In order to destroy the cluster you can run: %s/requirements/openshift-install destroy cluster --dir %s/final_manifests", siteBuildPath, siteBuildPath) + + return builder.String() } + // Should never get here + return "" } diff --git a/pkg/site/site.go b/pkg/site/site.go index 7aeb8f8..3c090fd 100644 --- a/pkg/site/site.go +++ b/pkg/site/site.go @@ -128,7 +128,7 @@ func (s Site) GetProfileFromSite() (string, string, string) { } // using the downloaded site content, fetches (and builds) the specified requirements, -// and also runs any required host preparation scripts for the site's profile type +// and also prepares the host for running scripts for the site's profile type func (s Site) FetchRequirements(individualRequirements []string) { log.Println(fmt.Sprintf("Downloading requirements for %s", s.siteName)) sitePath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName) @@ -197,7 +197,7 @@ func (s Site) FetchRequirements(individualRequirements []string) { r.FetchRequirement() } - // Checks for and executes any required host preparation for this site + // Prepares host automation for post-'prepare_manifests' execution (if any) err = s.prepareHostForAutomation(profileName, parsedRequirements) if err != nil { @@ -332,7 +332,8 @@ func (s Site) DownloadRepo(sitePath string, profileLayerPath string, profileRef }) } -// using the downloaded site content, prepares the manifests for it +// using the downloaded site content, prepares the manifests for it, and also runs +// host preparation finalization scripts for site automation (if any) func (s Site) PrepareManifests() { sitePath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName) log.Println(fmt.Sprintf("Preparing manifests for %s", s.siteName)) @@ -341,13 +342,14 @@ func (s Site) PrepareManifests() { utils.ValidateRequirements(s.buildPath, s.siteName) binariesPath := fmt.Sprintf("%s/requirements", sitePath) - // retrieve profile path and clone the repo - _, profileLayerPath, profileRef := s.GetProfileFromSite() + // retrieve profile name/path and clone the repo + profileName, profileLayerPath, profileRef := s.GetProfileFromSite() s.DownloadRepo(sitePath, profileLayerPath, profileRef) // create automation sub-directory to store a copy of anything that might be - // needed if automation is later requested + // needed in the case of potential automation automationPath := fmt.Sprintf("%s/automation", sitePath) + automationRepoPath := fmt.Sprintf("%s/baremetal_automation", sitePath) os.Mkdir(automationPath, 0755) // copy 00_install-config directory contents (minus kustomization.yaml) @@ -378,13 +380,22 @@ func (s Site) PrepareManifests() { os.Exit(1) } - // create a copy of final install-config.yaml in site automation sub-directory - // in case automation is later requested + // create a copy of final install-config.yaml in any site automation sub-directories + // in case automation is later needed err = ioutil.WriteFile(fmt.Sprintf("%s/install-config.yaml", automationPath), out, 0644) if err != nil { log.Fatal(fmt.Sprintf("Error writing final install-config file to automation assets directory: %s", err)) os.Exit(1) } + + automationRepoClusterPath := fmt.Sprintf("%s/cluster", automationRepoPath) + if _, err = os.Stat(automationRepoClusterPath); err == nil { + err = ioutil.WriteFile(fmt.Sprintf("%s/install-config.yaml", automationRepoClusterPath), out, 0644) + if err != nil { + log.Fatal(fmt.Sprintf("Error writing final install-config file to automation repo directory: %s", err)) + os.Exit(1) + } + } } else { log.Fatal("Error, kustomize did not return any content") os.Exit(1) @@ -433,8 +444,18 @@ func (s Site) PrepareManifests() { out = utils.ApplyKustomize(fmt.Sprintf("%s/kustomize", binariesPath), fmt.Sprintf("%s/blueprint/sites/site/01_cluster-mods", sitePath)) if len(out) > 0 { // now apply modifications on the manifests - manifests.MergeManifests(string(out), sitePath) + resultStr := manifests.MergeManifests(string(out), sitePath) + + // Now that we have finalized our manifests, call automation finalization (if any) + err = s.finalizeHostForAutomation(profileName) + if err != nil { + log.Fatal(err) + os.Exit(1) + } + + // Finally, print manifest merge output + fmt.Println(resultStr) } else { log.Fatal("Error, kustomize did not return any content") os.Exit(1) @@ -706,5 +727,35 @@ func (s Site) prepareHostForAutomation(profileName string, requirements map[stri } // Tell the automated deployment instance to prepare the host for automation - return automatedDeployment.PrepareBastion(requirements) + return automatedDeployment.PrepareAutomation(requirements) +} + +func (s Site) finalizeHostForAutomation(profileName string) error { + if s.buildPath == "" || s.siteName == "" { + return errors.New("Site: finalizeHostForAutomation: build path and/or site name missing") + } + + // Get an automated deployment object + automatedDeployment, err := s.getAutomatedDeployment() + + if err != nil { + // If automation isn't supported for this profile type, it's not a fatal error in + // this context, since this function is just trying to finalize the host for potential + // automation (and is not called in the context of an explicit automation request) + if strings.Contains(err.Error(), "automation not supported") || strings.Contains(err.Error(), "automated deployment not supported") { + return nil + } + + // Anything else should be treated as an error + return err + } + + // If automatedDeployment is nil, then automation isn't required/supported + // for this particular site, which isn't an error in this context + if automatedDeployment == nil { + return nil + } + + // Tell the automated deployment instance to prepare the host for automation + return automatedDeployment.FinalizeAutomation() } -- 2.16.6