+++ /dev/null
-// Copyright © 2019 Red Hat <yroblamo@redhat.com>
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cmd
-
-import (
- "bytes"
- "fmt"
- "io"
- "log"
- "os"
- "os/exec"
-
- "github.com/spf13/cobra"
-)
-
-// cleanCmd represents the binary command
-var cleanCmd = &cobra.Command{
- Use: "clean",
- Short: "Command to clean a previous cluster. It relies on metadata.json file",
- Long: ``,
- TraverseChildren: true,
- Run: func(cmd *cobra.Command, args []string) {
- // Check if build path exists, if not fail
- buildPath, _ := cmd.Flags().GetString("build_path")
-
- // check if metadata exists
- metadataFile := fmt.Sprintf("%s/metadata.json", buildPath)
- if _, err := os.Stat(metadataFile); os.IsNotExist(err) {
- log.Fatal(fmt.Sprintf("Metadata file %s does not exist. Stopping cleanup", metadataFile))
- os.Exit(1)
- } else {
- // launch cleanup command
- cmd := exec.Command("./openshift-install", "destroy", "cluster")
- cmd.Dir = buildPath
- cmd.Env = os.Environ()
- cmd.Env = append(cmd.Env, fmt.Sprintf("GOPATH=%s/go", os.Getenv("HOME")))
-
- var stdBuffer bytes.Buffer
- mw := io.MultiWriter(os.Stdout, &stdBuffer)
- cmd.Stdout = mw
- cmd.Stderr = mw
-
- err := cmd.Run()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cleaning cluster: %s - %s", err, stdBuffer.String()))
- os.Exit(1)
- }
- log.Println(stdBuffer.String())
- log.Println("Cluster cleaned successfully")
- }
-
- },
-}
-
-func init() {
- rootCmd.AddCommand(cleanCmd)
-
- cleanCmd.Flags().StringP("build_path", "", "", "Directory to use as build path. If that not exists, the installer will generate a default directory")
-
-}
+++ /dev/null
-// Copyright © 2019 NAME HERE <EMAIL ADDRESS>
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cmd
-
-import (
- "io/ioutil"
- "os"
-
- "gerrit.akraino.org/kni/installer/pkg/generator"
- "github.com/spf13/cobra"
-)
-
-// generateCmd represents the generate command
-var generateCmd = &cobra.Command{
- Use: "generate",
- Short: "Command to generate manifests for a cluster",
- Long: ``,
- TraverseChildren: true,
- Run: func(cmd *cobra.Command, args []string) {
- // retrieve config values and start generation
- baseRepo, _ := cmd.Flags().GetString("base_repository")
- basePath, _ := cmd.Flags().GetString("base_path")
- installerPath, _ := cmd.Flags().GetString("installer_path")
- secretsRepository, _ := cmd.Flags().GetString("secrets_repository")
- siteRepository, _ := cmd.Flags().GetString("site_repository")
- settingsPath, _ := cmd.Flags().GetString("settings_path")
- masterMemoryMB, _ := cmd.Flags().GetString("master_memory_mb")
- sshKeyPath, _ := cmd.Flags().GetString("ssh_key_path")
-
- // Check if build path exists, create if not
- buildPath, _ := cmd.Flags().GetString("build_path")
- if len(buildPath) == 0 {
- // will generate a temporary directory
- buildPath, _ = ioutil.TempDir("/tmp", "kni")
- } else {
- // remove if exists, recreate
- os.RemoveAll(buildPath)
- os.MkdirAll(buildPath, 0775)
- }
-
- // start generation process
- g := generator.New(baseRepo, basePath, installerPath, secretsRepository, siteRepository, settingsPath, buildPath, masterMemoryMB, sshKeyPath)
- g.GenerateManifests()
- },
-}
-
-func init() {
- rootCmd.AddCommand(generateCmd)
-
- generateCmd.Flags().StringP("base_repository", "", "", "Url for the base github repository for the blueprint")
- generateCmd.MarkFlagRequired("base_repository")
- generateCmd.Flags().StringP("base_path", "", "", "Path to the base config and manifests for the blueprint")
- generateCmd.MarkFlagRequired("base_path")
- generateCmd.Flags().StringP("installer_path", "", "https://github.com/openshift/installer/releases/download/v0.16.1/openshift-install-linux-amd64", "Path where openshift-install binary is stored")
- generateCmd.Flags().StringP("build_path", "", "", "Directory to use as build path. If that not exists, the installer will generate a default directory")
-
- generateCmd.Flags().StringP("secrets_repository", "", "", "Path to repository that contains secrets")
- generateCmd.MarkFlagRequired("secrets_repository")
-
- generateCmd.Flags().StringP("site_repository", "", "", "Url for the specific site github repository")
- generateCmd.MarkFlagRequired("site_repository")
- generateCmd.Flags().StringP("settings_path", "", "", "Path to settings.yaml with specific config for the site")
- generateCmd.MarkFlagRequired("settings_path")
-
- generateCmd.Flags().StringP("master_memory_mb", "", "", "MB of memory to use for master node (libvirt)")
- generateCmd.Flags().StringP("ssh_key_path", "", "", "Path for the SSH private key to retrieve private repos")
- generateCmd.MarkFlagRequired("ssh_key_path")
-
-}
+++ /dev/null
-// Copyright © 2019 Red Hat <yroblamo@redhat.com>
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-// http://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
-package cmd
-
-import (
- "fmt"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
-
- getter "github.com/hashicorp/go-getter"
- "github.com/spf13/cobra"
-)
-
-// generateWorkloads will run kustomize and apply the generated workloads on the cluster
-func generateWorkloads(siteRepository string, buildPath string, clusterCredentials string, workloadType string) {
- // Clone the site repository
- log.Println("Cloning the site repository")
- siteBuildPath := fmt.Sprintf("%s/site", buildPath)
- client := &getter.Client{Src: siteRepository, Dst: siteBuildPath, Mode: getter.ClientModeAny}
- err := client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cloning site repository: %s", err))
- }
-
- // apply kustomize on the given path
- log.Println(fmt.Sprintf("Generating %s", workloadType))
- workloadsPath := fmt.Sprintf("%s/%s", siteBuildPath, workloadType)
- cmd := exec.Command("kustomize", "build", workloadsPath)
- out, err := cmd.CombinedOutput()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error calling kustomize: %s - %s", err, string(out)))
- os.Exit(1)
- }
- outfile, err := os.Create(fmt.Sprintf("%s/content.yaml", workloadsPath))
- if err != nil {
- log.Fatal(fmt.Sprintf("Error storing output from kustomize: %s", err))
- os.Exit(1)
- }
- _, err = outfile.WriteString(fmt.Sprintf("%s", out))
- if err != nil {
- log.Fatal(fmt.Sprintf("Error writing kustomize file: %s", err))
- }
- defer outfile.Close()
-
- // and now apply the content of the file
- log.Println("Applying the generated workloads")
- cmd = exec.Command("oc", "apply", "-f", fmt.Sprintf("%s/content.yaml", workloadsPath))
- cmd.Env = os.Environ()
- cmd.Env = append(cmd.Env, fmt.Sprintf("KUBECONFIG=%s", clusterCredentials))
- out, err = cmd.CombinedOutput()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error applying kustomize workloads: %s - %s", err, out))
- os.Exit(1)
- }
- log.Println(fmt.Sprintf("%s", out))
-}
-
-// workloadsCmd represents the workloads command
-var workloadsCmd = &cobra.Command{
- Use: "workloads",
- Short: "Command to apply workloads on a working cluster",
- Long: ``,
- TraverseChildren: true,
- Run: func(cmd *cobra.Command, args []string) {
- // retrieve config values and start generation
- siteRepository, _ := cmd.Flags().GetString("site_repository")
-
- // Check if build path exists, create if not
- buildPath, _ := cmd.Flags().GetString("build_path")
- if len(buildPath) == 0 {
- // will generate a temporary directory
- buildPath, _ = ioutil.TempDir("/tmp", "kni")
- } else {
- // remove if exists, recreate
- os.RemoveAll(buildPath)
- os.MkdirAll(buildPath, 0775)
- }
-
- clusterCredentials, _ := cmd.Flags().GetString("cluster_credentials")
- workloadType, _ := cmd.Flags().GetString("workload_type")
-
- // start generation process
- generateWorkloads(siteRepository, buildPath, clusterCredentials, workloadType)
- },
-}
-
-func init() {
- rootCmd.AddCommand(workloadsCmd)
-
- workloadsCmd.Flags().StringP("site_repository", "", "", "Url for the specific site workloads folder")
- workloadsCmd.MarkFlagRequired("site_repository")
- workloadsCmd.Flags().StringP("cluster_credentials", "", "", "The credentials to use to access the cluster")
- workloadsCmd.MarkFlagRequired("cluster_credentials")
- workloadsCmd.Flags().StringP("workload_type", "", "", "The type of workloads to execute")
- workloadsCmd.MarkFlagRequired("workload_type")
-
-}
+++ /dev/null
-package generator
-
-import (
- "bytes"
- "encoding/base64"
- "fmt"
- "io"
- "io/ioutil"
- "log"
- "os"
- "os/exec"
- "path/filepath"
- "strings"
- "text/template"
-
- getter "github.com/hashicorp/go-getter"
- "gopkg.in/yaml.v2"
-)
-
-// Generator : Structure that contains the settings needed for generation
-type Generator struct {
- baseRepo string
- basePath string
- installerPath string
- secretsRepo string
- siteRepo string
- settingsPath string
- buildPath string
- masterMemoryMB string
- sshKeyPath string
- secrets map[string]string
- clusterName string
- baseDomain string
- providerType string
-}
-
-// New constructor for the generator
-func New(baseRepo string, basePath string, installerPath string, secretsRepo string, siteRepo string, settingsPath string, buildPath string, masterMemoryMB string, sshKeyPath string) Generator {
- g := Generator{baseRepo, basePath, installerPath, secretsRepo, siteRepo, settingsPath, buildPath, masterMemoryMB, sshKeyPath, make(map[string]string), "", "", ""}
- return g
-}
-
-// DownloadArtifacts is a method for downloading all the initial artifacts
-func (g Generator) DownloadArtifacts() {
- // Download installer for openshift
- log.Println("Downloading openshift-install binary")
- binaryPath := fmt.Sprintf("%s/openshift-install", g.buildPath)
- client := &getter.Client{Src: g.installerPath, Dst: binaryPath}
- err := client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error downloading openshift-install binary: %s", err))
- os.Exit(1)
- }
- os.Chmod(binaryPath, 0777)
-
- // Download the credentials repo
- log.Println("Download secrets repo")
- secretsPath := fmt.Sprintf("%s/secrets", g.buildPath)
-
- // Retrieve private key and b64encode it, if secrets is not local
- finalURL := ""
- if !strings.HasPrefix(g.secretsRepo, "file://") {
- priv, err := ioutil.ReadFile(g.sshKeyPath)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error reading secret key: %s", err))
- os.Exit(1)
- }
- sEnc := base64.StdEncoding.EncodeToString(priv)
- finalURL = fmt.Sprintf("%s?sshkey=%s", g.secretsRepo, sEnc)
- } else {
- finalURL = g.secretsRepo
- }
- client = &getter.Client{Src: finalURL, Dst: secretsPath, Mode: getter.ClientModeAny}
- err = client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error downloading secrets repo: %s", err))
- os.Exit(1)
- }
- os.Chmod(secretsPath, 0700)
-
- // Clone the base repository with base manifests
- log.Println("Cloning the base repository with base manifests")
- baseBuildPath := fmt.Sprintf("%s/base_manifests", g.buildPath)
- client = &getter.Client{Src: g.baseRepo, Dst: baseBuildPath, Mode: getter.ClientModeAny}
- err = client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cloning base repository with base manifests: %s", err))
- os.Exit(1)
- }
-
- // Clone the site repository with settings.yaml
- log.Println("Cloning the site repository with settings")
- siteBuildPath := fmt.Sprintf("%s/site", g.buildPath)
- client = &getter.Client{Src: g.siteRepo, Dst: siteBuildPath, Mode: getter.ClientModeAny}
- err = client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cloning site repository: %s", err))
- }
-}
-
-// ReadSecretFiles will traverse secrets directory and read content
-func (g Generator) ReadSecretFiles(path string, info os.FileInfo, err error) error {
- var matches = map[string]string{"coreos-pull-secret": "pullSecret",
- "ssh-pub-key": "SSHKey", "aws-access-key-id": "aws-access-key-id",
- "aws-secret-access-key": "aws-secret-access-key"}
-
- if info.IsDir() && info.Name() == ".git" {
- return filepath.SkipDir
- }
-
- if err != nil {
- log.Fatal(fmt.Sprintf("Error traversing file: %s", err))
- os.Exit(1)
- }
-
- if !info.IsDir() {
- data, err := ioutil.ReadFile(path)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error reading file content: %s", err))
- os.Exit(1)
- }
- g.secrets[matches[info.Name()]] = strings.Trim(string(data), "\n")
- }
- return nil
-}
-
-// GenerateInstallConfig generates the initial config.yaml
-func (g *Generator) GenerateInstallConfig() {
- // Read install-config.yaml on the given path and parse it
- manifestsPath := fmt.Sprintf("%s/base_manifests/%s", g.buildPath, g.basePath)
- installPath := fmt.Sprintf("%s/install-config.yaml.go", manifestsPath)
-
- t, err := template.New("install-config.yaml.go").ParseFiles(installPath)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error reading install file: %s", err))
- os.Exit(1)
- }
-
- // parse settings file
- settingsPath := fmt.Sprintf("%s/site/%s", g.buildPath, g.settingsPath)
- yamlContent, err := ioutil.ReadFile(settingsPath)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error reading settings file: %s", err))
- os.Exit(1)
- }
-
- siteSettings := &map[string]map[string]interface{}{}
- err = yaml.Unmarshal(yamlContent, &siteSettings)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error parsing settings yaml file: %s", err))
- os.Exit(1)
- }
- parsedSettings := (*siteSettings)["settings"]
- g.clusterName = parsedSettings["clusterName"].(string)
- g.baseDomain = parsedSettings["baseDomain"].(string)
-
- // Read secrets
- secretsPath := fmt.Sprintf("%s/secrets", g.buildPath)
- ln, err := filepath.EvalSymlinks(secretsPath)
- if err != nil {
- log.Fatal(fmt.Sprintf("Error evaluating symlinks: %s", err))
- os.Exit(1)
- }
- if len(ln) > 0 {
- // we need to traverse that instead of the given path
- secretsPath = ln
- }
- err = filepath.Walk(secretsPath, g.ReadSecretFiles)
-
- // Prepare the final file to write the template
- f, err := os.Create(fmt.Sprintf("%s/install-config.yaml", g.buildPath))
- if err != nil {
- log.Fatal(fmt.Sprintf("Error opening the install file: %s", err))
- os.Exit(1)
- }
-
- // Prepare the vars to be executed in the template
- var settings = make(map[string]string)
- var mandatorySettings = map[string]string{
- "baseDomain": "string",
- "clusterName": "string",
- "clusterCIDR": "string",
- "clusterSubnetLength": "int",
- "machineCIDR": "string",
- "serviceCIDR": "string",
- "SDNType": "string",
- }
- for key, value := range mandatorySettings {
- if _, ok := parsedSettings[key]; ok {
- if value == "int" {
- settings[key] = fmt.Sprintf("%d", parsedSettings[key].(int))
- } else {
- settings[key] = parsedSettings[key].(string)
- }
- }
- }
- // Settings depending on provider
- providerSettings := [2]string{"libvirtURI", "AWSRegion"}
- for _, element := range providerSettings {
- if _, ok := parsedSettings[element]; ok {
- settings[element] = parsedSettings[element].(string)
- }
- }
-
- if _, ok := settings["libvirtURI"]; ok {
- g.providerType = "libvirt"
- } else if _, ok := settings["AWSRegion"]; ok {
- g.providerType = "aws"
- }
-
- // Merge with secrets dictionary
- for k, v := range g.secrets {
- settings[k] = v
- }
- err = t.Execute(f, settings)
-
- if err != nil {
- log.Fatal(fmt.Sprintf("Error parsing template: %s", err))
- }
-
-}
-
-// GenerateCredentials create the AWS credentials file if needed
-func (g Generator) GenerateCredentials() {
- AWSKey, ok1 := g.secrets["aws-access-key-id"]
- AWSSecret, ok2 := g.secrets["aws-secret-access-key"]
-
- if ok1 && ok2 {
- log.Println("Generating AWS credentials")
- // generate aws creds file
- settings := make(map[string]string)
- settings["AWSKey"] = AWSKey
- settings["AWSSecret"] = AWSSecret
-
- // Create AWS credentials directory, or overwrite it
- AWSPath := fmt.Sprintf("%s/.aws", os.Getenv("HOME"))
- os.RemoveAll(AWSPath)
- os.MkdirAll(AWSPath, 0700)
-
- f, err := os.Create(fmt.Sprintf("%s/credentials", AWSPath))
- if err != nil {
- log.Fatal(fmt.Sprintf("Error opening the install file: %s", err))
- os.Exit(1)
- }
- os.Chmod(fmt.Sprintf("%s/credentials", AWSPath), 0600)
-
- t, err := template.New("aws").Parse("[default]\naws_access_key_id={{.AWSKey}}\naws_secret_access_key={{.AWSSecret}}")
- err = t.Execute(f, settings)
- } else {
- log.Println("No secrets provided, skipping credentials creation")
- }
-}
-
-// CreateManifests creates the initial manifests for the cluster
-func (g Generator) CreateManifests() {
- log.Println("Creating manifests")
- cmd := exec.Command("./openshift-install", "create", "manifests")
- cmd.Dir = g.buildPath
- out, err := cmd.CombinedOutput()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error creating manifests: %s - %s", err, string(out)))
- os.Exit(1)
- }
-}
-
-
-//ModifyIngressManifest modifies the cluster ingress manifest for Libvirt deployments
-func (g Generator) ModifyIngressManifest() {
- log.Println("Modify Ingress Manifest")
- file := g.buildPath+"/manifests/cluster-ingress-02-config.yml"
- input, err := ioutil.ReadFile(file)
- if err != nil {
- log.Fatalln(err)
- }
-
- lines := strings.Split(string(input), "\n")
-
- for i, line := range lines {
- if strings.Contains(line, "domain") {
- lines[i] = " domain: apps."+g.baseDomain
- }
- }
- output := strings.Join(lines, "\n")
- err = ioutil.WriteFile(file, []byte(output), 0644)
- if err != nil {
- log.Fatalln(err)
- }
-}
-
-
-// DeployCluster starts deployment of the cluster
-func (g Generator) DeployCluster() {
- log.Println("Deploying cluster")
- cmd := exec.Command("./openshift-install", "create", "cluster")
- cmd.Dir = g.buildPath
-
- if len(g.masterMemoryMB) > 0 {
- cmd.Env = os.Environ()
- cmd.Env = append(cmd.Env, fmt.Sprintf("TF_VAR_libvirt_master_memory=%s", g.masterMemoryMB))
- }
-
- var stdBuffer bytes.Buffer
- mw := io.MultiWriter(os.Stdout, &stdBuffer)
- cmd.Stdout = mw
- cmd.Stderr = mw
-
- err := cmd.Run()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error creating cluster: %s - %s", err, stdBuffer.String()))
- os.Exit(1)
- }
- log.Println(stdBuffer.String())
-}
-
-// GenerateManifests generates the manifests with the parsed values
-func (g Generator) GenerateManifests() {
- // First download the needed artifacts
- g.DownloadArtifacts()
-
- // Generate install-config.yaml
- g.GenerateInstallConfig()
-
- // Generate credentials for AWS if needed
- g.GenerateCredentials()
-
- // Create manifests
- g.CreateManifests()
-
- // Modify Ingress manifest if libvirt
- if g.providerType == "libvirt" {
- g.ModifyIngressManifest()
- }
-
- // Deploy cluster
- g.DeployCluster()
-}