Version-selection for automated baremetal 02/1802/1
authorAndrew Bays <abays@redhat.com>
Fri, 18 Oct 2019 11:29:17 +0000 (07:29 -0400)
committerAndrew Bays <abays@redhat.com>
Fri, 18 Oct 2019 11:29:17 +0000 (07:29 -0400)
Change-Id: I1f46fa879a805800916dec97b5cd147593e03332

pkg/automation/automation.go
pkg/automation/baremetal.go
pkg/site/site.go
pkg/utils/utils.go

index e5c4304..3a4d655 100644 (file)
@@ -16,10 +16,10 @@ type AutomatedDeploymentParams struct {
 }
 
 type AutomatedDeploymentInterface interface {
-       PrepareBastion() error // Prepare host for automation
-       DeployMasters() error  // Deploy cluster masters
-       DeployWorkers() error  // Deploy cluster workers
-       DestroyCluster() error // Destroy the cluster
+       PrepareBastion(map[string]string) error // Prepare host for automation
+       DeployMasters() error                   // Deploy cluster masters
+       DeployWorkers() error                   // Deploy cluster workers
+       DestroyCluster() error                  // Destroy the cluster
 }
 
 var (
index 10d5524..94ff23a 100644 (file)
@@ -8,7 +8,9 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "strings"
 
+       "gerrit.akraino.org/kni/installer/pkg/utils"
        "github.com/otiai10/copy"
 
        getter "github.com/hashicorp/go-getter"
@@ -75,7 +77,7 @@ func newBaremetal(params AutomatedDeploymentParams) (AutomatedDeploymentInterfac
        }, nil
 }
 
-func (bad baremetalAutomatedDeployment) PrepareBastion() error {
+func (bad baremetalAutomatedDeployment) PrepareBastion(requirements map[string]string) error {
        // Download repo
        automationDestination := fmt.Sprintf("%s/%s/baremetal_automation", bad.siteBuildPath, bad.siteName)
 
@@ -118,6 +120,56 @@ func (bad baremetalAutomatedDeployment) PrepareBastion() error {
                return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error writing destination site config file: %s", err)
        }
 
+       // 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
+       binaryVersionsPath := fmt.Sprintf("%s/images_and_binaries.sh", automationDestination)
+
+       for requirementName, requirementSource := range requirements {
+               switch requirementName {
+               case "oc":
+                       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)
+                       }
+               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)
+                       }
+               }
+       }
+
+       // Check site-config.yaml's config block for a releaseImageOverride.  If found, extract
+       // the image's tag to get the requested version for RHCOS images, and inject that into
+       // automation's common.sh script to override the default
+       var siteConfig map[string]interface{}
+       siteConfigFile, err := ioutil.ReadFile(siteConfigDestinationPath)
+
+       err = yaml.Unmarshal(siteConfigFile, &siteConfig)
+
+       if err != nil {
+               return fmt.Errorf("baremetalAutomatedDeployment: PrepareBastion: error unmarshalling site-config.yaml: %s", err)
+       }
+
+       if config, ok := siteConfig["config"].(map[interface{}]interface{}); ok {
+               if releaseImageOverride, ok := config["releaseImageOverride"].(string); ok {
+                       parts := strings.Split(releaseImageOverride, ":")
+
+                       if len(parts) == 2 {
+                               rhcosVersionsPath := fmt.Sprintf("%s/common.sh", automationDestination)
+
+                               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)
+                               }
+                       }
+               }
+       }
+
        // Execute automation's prep_bm_host script
        cmd := exec.Command(fmt.Sprintf("%s/prep_bm_host.sh", automationDestination))
        cmd.Dir = automationDestination
@@ -165,20 +217,7 @@ func (bad baremetalAutomatedDeployment) DeployMasters() error {
        _, err = os.Stat(automationRepoPath)
 
        if err != nil {
-               if !os.IsNotExist(err) {
-                       return fmt.Errorf("baremetalAutomatedDeployment: DeployMasters: unable to access local automation repo at %s: %s", automationRepoPath, err)
-               }
-
-               // Doesn't exist, so clone it?
-               // NOTE: It should already exist, having been created during the "fetch_requirements" step
-               log.Printf("baremetalAutomatedDeployment: DeployMasters: downloading missing baremetal automation repo (%s)\n", automationRemoteSource)
-
-               client := &getter.Client{Src: automationRemoteSource, Dst: automationRepoPath, Mode: getter.ClientModeAny}
-               err := client.Get()
-
-               if err != nil {
-                       return fmt.Errorf("baremetalAutomatedDeployment: DeployMasters: error cloning baremetal automation repository: %s", err)
-               }
+               return fmt.Errorf("baremetalAutomatedDeployment: DeployMasters: unable to access local automation repo at %s: %s", automationRepoPath, err)
        }
 
        // Copy final_manifests into the automation repo's ocp directory (the ocp
index 4a44ad9..7aeb8f8 100644 (file)
@@ -161,6 +161,8 @@ func (s Site) FetchRequirements(individualRequirements []string) {
        }
        defer file.Close()
 
+       parsedRequirements := map[string]string{}
+
        scanner := bufio.NewScanner(file)
        for scanner.Scan() {
                requirementsLine := scanner.Text()
@@ -168,6 +170,13 @@ func (s Site) FetchRequirements(individualRequirements []string) {
                // requirements is composed of binary and source
                requirementsBits := strings.SplitN(strings.TrimSpace(requirementsLine), ":", 2)
                binaryName := strings.TrimSpace(requirementsBits[0])
+               binarySource := strings.TrimSpace(requirementsBits[1])
+
+               // Store requirement for use in call to prepareHostForAutomation, regardless of
+               // what happens with the "individualRequirements" check below.  If automation is
+               // in fact used later on, we want to honor the potential "oc" and "openshift-install"
+               // binary versions set in the blueprint profile's "requirements.yaml"
+               parsedRequirements[binaryName] = binarySource
 
                // if we have individual requirements list, check if we have the requirement on it. Otherwise, skip
                if len(individualRequirements) > 0 {
@@ -184,12 +193,12 @@ func (s Site) FetchRequirements(individualRequirements []string) {
                                continue
                        }
                }
-               r := requirements.New(binaryName, strings.TrimSpace(requirementsBits[1]), fmt.Sprintf("%s/requirements", sitePath))
+               r := requirements.New(binaryName, binarySource, fmt.Sprintf("%s/requirements", sitePath))
                r.FetchRequirement()
        }
 
        // Checks for and executes any required host preparation for this site
-       err = s.prepareHostForAutomation(profileName)
+       err = s.prepareHostForAutomation(profileName, parsedRequirements)
 
        if err != nil {
                log.Fatal(err)
@@ -663,7 +672,7 @@ func (s Site) getProfileType(profileName string) (string, error) {
        return "", nil
 }
 
-func (s Site) prepareHostForAutomation(profileName string) error {
+func (s Site) prepareHostForAutomation(profileName string, requirements map[string]string) error {
        if s.buildPath == "" || s.siteName == "" {
                return errors.New("Site: prepareHostForAutomation: build path and/or site name missing")
        }
@@ -697,5 +706,5 @@ func (s Site) prepareHostForAutomation(profileName string) error {
        }
 
        // Tell the automated deployment instance to prepare the host for automation
-       return automatedDeployment.PrepareBastion()
+       return automatedDeployment.PrepareBastion(requirements)
 }
index c12122f..b0b71d0 100644 (file)
@@ -8,6 +8,7 @@ import (
        "os"
        "os/exec"
        "path/filepath"
+       "strings"
        "time"
 )
 
@@ -135,3 +136,21 @@ func CopyFile(sourcePath string, destinationPath string) error {
 
        return nil
 }
+
+func ReplaceFileText(sourcePath string, oldText string, newText string) error {
+       read, err := ioutil.ReadFile(sourcePath)
+
+       if err != nil {
+               return err
+       }
+
+       newContents := strings.Replace(string(read), oldText, newText, -1)
+
+       err = ioutil.WriteFile(sourcePath, []byte(newContents), 0)
+
+       if err != nil {
+               return err
+       }
+
+       return nil
+}