Move automation prep call to prepare_manifests 11/1811/1
authorAndrew Bays <andrew.bays@gmail.com>
Mon, 21 Oct 2019 18:45:22 +0000 (14:45 -0400)
committerAndrew Bays <andrew.bays@gmail.com>
Mon, 21 Oct 2019 18:45:33 +0000 (14:45 -0400)
Change-Id: I8c74cc4c1ef60d23e34cc00dd32f765c29f3187c

pkg/automation/automation.go
pkg/automation/baremetal.go
pkg/manifests/manifests.go
pkg/site/site.go

index 3a4d655..d965c2c 100644 (file)
@@ -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 (
index 94ff23a..536e2e7 100644 (file)
@@ -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
 }
index 90ef926..f5fe0f0 100644 (file)
@@ -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 ""
 }
index 7aeb8f8..3c090fd 100644 (file)
@@ -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()
 }