--- /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"
+ "log"
+ "os"
+
+ "gerrit.akraino.org/kni/installer/pkg/site"
+ "github.com/spf13/cobra"
+)
+
+// prepareManifestsCmd represents the prepare_manifests command
+var prepareManifestsCmd = &cobra.Command{
+ Use: "prepare_manifests siteName [--build_path=<local_build_path>]",
+ Short: "Command to prepare the manifests needed for a site",
+ Long: ``,
+ TraverseChildren: true,
+ Run: func(cmd *cobra.Command, args []string) {
+ // retrieve config values and start fetching
+ var siteName string
+ if len(args) == 0 {
+ log.Fatal("Please specify site name as first argument")
+ os.Exit(1)
+ } else {
+ siteName = args[0]
+ }
+
+ buildPath, _ := cmd.Flags().GetString("build_path")
+ if len(buildPath) == 0 {
+ // will generate a temporary directory
+ buildPath = fmt.Sprintf("%s/.kni", os.Getenv("HOME"))
+ }
+
+ // define a site object and proceed with requirements fetch
+ s := site.NewWithName(siteName, buildPath)
+ s.PrepareManifests()
+ },
+}
+
+func init() {
+ rootCmd.AddCommand(prepareManifestsCmd)
+
+ prepareManifestsCmd.Flags().StringP("build_path", "", "", "Directory to use as build path. If that doesn't exist, the installer will generate a default directory")
+
+}
--- /dev/null
+package manifests
+
+import (
+ "fmt"
+ "io/ioutil"
+ "log"
+ "os"
+ "path/filepath"
+ "reflect"
+ "strings"
+
+ "gopkg.in/yaml.v2"
+)
+
+// Generates an unique identifier based on the GKV (from K8s) + Name
+func GetGKVN(manifestObj map[interface{}]interface{}) string {
+
+ // retrieves version, and defaults to ~G/~V if not
+ version, ok := manifestObj["apiVersion"]
+ if !ok {
+ version = "~G/~V"
+ }
+
+ kind, ok := manifestObj["kind"]
+ if !ok {
+ kind = "~K"
+ }
+
+ var metadata map[interface{}]interface{}
+ var name string
+
+ metadata, ok = manifestObj["metadata"].(map[interface{}]interface{})
+ if ok {
+ name, ok = metadata["name"].(string)
+ if !ok {
+ name = "~N"
+ }
+ } else {
+ name = "~N"
+ }
+
+ if !strings.Contains(version.(string), "/") {
+ version = fmt.Sprintf("~G/%s", version)
+ }
+
+ // prepare the final key
+ GVKN := fmt.Sprintf("%s/%s|%s", version, kind, name)
+ return GVKN
+}
+
+// we have a list of items, we need to split and get their individual gvkn
+func GetNestedManifestsWithGVKN(manifestObj map[interface{}]interface{}) map[string]map[interface{}]interface{} {
+ var items []interface{}
+ var parsedItem map[interface{}]interface{}
+ var GVKN string
+ GVKNS := make(map[string]map[interface{}]interface{})
+
+ items = manifestObj["items"].([]interface{})
+ for _, item := range items {
+ parsedItem = item.(map[interface{}]interface{})
+ GVKN = GetGKVN(parsedItem)
+ if len(GVKN) > 0 {
+ GVKNS[GVKN] = parsedItem
+ }
+ }
+
+ return GVKNS
+}
+
+// given a gvkn, gets a name from it
+func NameFromGVKN(GVKN string) string {
+ items := strings.Split(GVKN, "|")
+ subItems := strings.Split(items[0], "/")
+ name := fmt.Sprintf("%s-%s", subItems[2], items[1])
+ if subItems[0] != "~G" {
+ name = fmt.Sprintf("%s-%s", subItems[0], name)
+ }
+ return strings.ToLower(name)
+}
+
+// utility to merge manifests
+func MergeManifests(content string, siteBuildPath string) {
+ manifests := strings.Split(content, "\n---\n")
+ kustomizeManifests := make(map[string]map[interface{}]interface{})
+
+ // first split all manifests and unmarshall into objects
+ for _, manifest := range manifests {
+ var manifestObj map[interface{}]interface{}
+
+ err := yaml.Unmarshal([]byte(manifest), &manifestObj)
+ if err != nil {
+ log.Println(fmt.Sprintf("Error parsing manifest: %s", err))
+ os.Exit(1)
+ }
+ // add to the list of manifests with the generated key
+ GVKN := GetGKVN(manifestObj)
+ if GVKN == "~G/v1/List|~N" {
+ nestedManifests := GetNestedManifestsWithGVKN(manifestObj)
+ for k, v := range nestedManifests {
+ kustomizeManifests[k] = v
+ }
+ } else {
+ kustomizeManifests[GVKN] = manifestObj
+ }
+ }
+
+ // now read all the manifests that have been generated by installer
+ processedManifests := make(map[string]string)
+ filepath.Walk(fmt.Sprintf("%s/blueprint/base/00_cluster", siteBuildPath), func(path string, info os.FileInfo, err error) error {
+ if err == nil {
+ // check if it is a file ending with yml/yaml and it is inside openshift or manifests directory
+ if !info.IsDir() && (strings.Contains(path, "/openshift/") || strings.Contains(path, "/manifests/")) && (strings.HasSuffix(path, ".yaml") || strings.HasSuffix(path, ".yml")) {
+ // read file content and unmarshal it
+ manifestContent, err := ioutil.ReadFile(path)
+ if err != nil {
+ log.Println(fmt.Sprintf("Error reading manifest content: %s", err))
+ os.Exit(1)
+ }
+ var manifestContentObj map[interface{}]interface{}
+ err = yaml.Unmarshal(manifestContent, &manifestContentObj)
+ if err != nil {
+ log.Println(fmt.Sprintf("Error parsing manifest: %s", err))
+ os.Exit(1)
+ }
+
+ GVKN := GetGKVN(manifestContentObj)
+ var walkedManifests map[string]map[interface{}]interface{}
+ if GVKN == "~G/v1/List|~N" {
+ walkedManifests = GetNestedManifestsWithGVKN(manifestContentObj)
+ for k, _ := range walkedManifests {
+ processedManifests[k] = ""
+ }
+ } else {
+ walkedManifests = make(map[string]map[interface{}]interface{})
+ walkedManifests[GVKN] = manifestContentObj
+ processedManifests[GVKN] = ""
+ }
+
+ // now compare each content with the ones from kustomize
+ counter := 0
+ for k, v := range walkedManifests {
+ kustomizedContentObj, ok := kustomizeManifests[k]
+ if ok {
+ if !reflect.DeepEqual(kustomizedContentObj, v) {
+ // do a backup of the original file
+ if _, err := os.Stat(path); err == nil {
+ err = os.Rename(path, fmt.Sprintf("%s.orig", path))
+ }
+
+ kustomizedString, err := yaml.Marshal(kustomizedContentObj)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error marshaling kustomized content: %s", err))
+ os.Exit(1)
+ }
+
+ if len(walkedManifests) == 1 {
+ // just rewrite with the original name
+ err = ioutil.WriteFile(path, kustomizedString, 0644)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing new manifest content: %s", err))
+ os.Exit(1)
+ }
+ } else {
+ // rewrite with a prefix
+ newPath := fmt.Sprintf("%02d_%s", counter, path)
+ err = ioutil.WriteFile(newPath, kustomizedString, 0644)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing new manifest content: %s", err))
+ os.Exit(1)
+ }
+ counter = counter + 1
+ }
+ }
+ }
+ }
+
+ }
+ } else {
+ log.Println(fmt.Sprintf("Error walking on manifests directory: %s", err))
+ os.Exit(1)
+ }
+ return nil
+ })
+
+ // now find manifests not yet in assets dir and write them out
+ counter := 0
+ for k, v := range kustomizeManifests {
+ _, ok := processedManifests[k]
+ if !ok {
+ // the manifest is not there, add it
+ manifestName := fmt.Sprintf("99_%04d_%s.yaml", counter, NameFromGVKN(k))
+ log.Println(fmt.Sprintf("Blueprint added manifests %s, writing to %s", k, manifestName))
+
+ newPath := fmt.Sprintf("%s/blueprint/base/00_cluster/manifests/%s", siteBuildPath, manifestName)
+
+ // marshal the file to write
+ kustomizedString, err := yaml.Marshal(v)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error marshing manifest: %s", err))
+ os.Exit(1)
+ }
+ err = ioutil.WriteFile(newPath, kustomizedString, 0644)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing manifest: %s", err))
+ os.Exit(1)
+ }
+ counter = counter + 1
+
+ }
+ }
+
+ // finally, move content to final manifests
+ os.RemoveAll(fmt.Sprintf("%s/final_manifests", siteBuildPath))
+ err := os.Rename(fmt.Sprintf("%s/blueprint/base/00_cluster", siteBuildPath), fmt.Sprintf("%s/final_manifests", siteBuildPath))
+ if err != nil {
+ 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("In order to destroy the cluster you can run: %s/requirements/openshift-install destroy cluster --dir %s/final_manifests", siteBuildPath, siteBuildPath))
+ }
+
+}
err = filepath.Walk(extractDir, func(path string, info os.FileInfo, err error) error {
if (info.Name() == r.binaryName || info.Name() == alternativeBinaryName) && !info.IsDir() {
// we found the binary, move it. Give exec perms as well
- finalName := fmt.Sprintf("%s/%s", r.buildPath, r.binaryName)
- os.Rename(path, finalName)
- os.Chmod(finalName, 0755)
+ finalBinary := fmt.Sprintf("%s/%s", r.buildPath, r.binaryName)
+ os.Rename(path, finalBinary)
+ os.Chmod(finalBinary, 0755)
os.RemoveAll(extractDir)
return nil
}
"io/ioutil"
"log"
"os"
+ "os/exec"
"path"
+ "path/filepath"
"strings"
+ "gerrit.akraino.org/kni/installer/pkg/manifests"
"gerrit.akraino.org/kni/installer/pkg/requirements"
+ "gerrit.akraino.org/kni/installer/pkg/utils"
getter "github.com/hashicorp/go-getter"
"gopkg.in/yaml.v2"
)
return s
}
+// new constructor but just passing the name and path
+func NewWithName(siteName string, buildPath string) Site {
+ s := Site{"", siteName, buildPath}
+ return s
+}
+
// given a site repo, downloads the content and places into buildPath
func (s Site) DownloadSite() {
- // Clone the site repository
- log.Println(fmt.Sprintf("Cloning the site repository from %s", s.siteRepo))
- siteBuildPath := fmt.Sprintf("%s/%s/site", s.buildPath, s.siteName)
- client := &getter.Client{Src: s.siteRepo, Dst: siteBuildPath, Mode: getter.ClientModeAny}
- err := client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cloning site repository: %s", err))
+ if s.siteRepo != "" {
+ // Clone the site repository
+ log.Println(fmt.Sprintf("Cloning the site repository from %s", s.siteRepo))
+ siteLayerPath := fmt.Sprintf("%s/%s/site", s.buildPath, s.siteName)
+ os.RemoveAll(siteLayerPath)
+ client := &getter.Client{Src: s.siteRepo, Dst: siteLayerPath, Mode: getter.ClientModeAny}
+ err := client.Get()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error cloning site repository: %s", err))
+ }
+ } else {
+ log.Fatal(fmt.Sprintf("Site repository does not exist for the site %s", s.siteName))
+ os.Exit(1)
}
}
-// using the downloaded site content, fetches (and builds) the specified requirements
-func (s Site) FetchRequirements() {
- log.Println(fmt.Sprintf("Downloading requirements for %s", s.siteName))
- siteBuildPath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName)
+// retrieves the given profile used in a site
+func (s Site) GetProfileFromSite() (string, string) {
+ sitePath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName)
- // searches for file containing the profile of the blueprint
- profileFile := fmt.Sprintf("%s/site/00_install-config/kustomization.yaml", siteBuildPath)
+ profileFile := fmt.Sprintf("%s/site/00_install-config/kustomization.yaml", sitePath)
if _, err := os.Stat(profileFile); err == nil {
// parse yaml and extract base
// given the profile repo, we need to get the full path without file, and clone it
profileBits := strings.Split(profileRepo, "/")
profileName := profileBits[len(profileBits)-2]
- profilePath := strings.TrimSuffix(profileRepo, profileBits[len(profileBits)-1])
+ profileLayerPath := strings.TrimSuffix(profileRepo, profileBits[len(profileBits)-1])
- profileBuildPath := fmt.Sprintf("%s/%s", siteBuildPath, profileName)
- log.Println(fmt.Sprintf("Downloading profile repo from %s into %s", profilePath, profileBuildPath))
- client := &getter.Client{Src: profilePath, Dst: profileBuildPath, Mode: getter.ClientModeAny}
- err = client.Get()
- if err != nil {
- log.Fatal(fmt.Sprintf("Error cloning profile repository: %s", err))
+ return profileName, profileLayerPath
+ } else if os.IsNotExist(err) {
+ log.Fatal(fmt.Sprintf("File %s does not exist, exiting", profileFile))
+ os.Exit(1)
+ }
+
+ return "", ""
+}
+
+// using the downloaded site content, fetches (and builds) the specified requirements
+func (s Site) FetchRequirements() {
+ log.Println(fmt.Sprintf("Downloading requirements for %s", s.siteName))
+ sitePath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName)
+
+ // searches for file containing the profile of the blueprint
+ profileName, profileLayerPath := s.GetProfileFromSite()
+
+ profileBuildPath := fmt.Sprintf("%s/%s", sitePath, profileName)
+ log.Println(fmt.Sprintf("Downloading profile repo from %s into %s", profileLayerPath, profileBuildPath))
+ client := &getter.Client{Src: profileLayerPath, Dst: profileBuildPath, Mode: getter.ClientModeAny}
+ err := client.Get()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error cloning profile repository: %s", err))
+ }
+
+ // read yaml from requirements and start fetching the bits
+ requirementsFile := fmt.Sprintf("%s/requirements.yaml", profileBuildPath)
+ file, err := os.Open(requirementsFile)
+ if err != nil {
+ log.Fatal("Error reading requirements file")
+ os.Exit(1)
+ }
+ defer file.Close()
+
+ scanner := bufio.NewScanner(file)
+ for scanner.Scan() {
+ requirementsLine := scanner.Text()
+
+ // requirements is composed of binary and source
+ requirementsBits := strings.SplitN(strings.TrimSpace(requirementsLine), ":", 2)
+ r := requirements.New(strings.TrimSpace(requirementsBits[0]), strings.TrimSpace(requirementsBits[1]), fmt.Sprintf("%s/requirements", sitePath))
+ r.FetchRequirement()
+ }
+
+ // remove profile folder
+ os.RemoveAll(profileBuildPath)
+
+}
+
+// using the downloaded site content, prepares the manifests for it
+func (s Site) PrepareManifests() {
+ sitePath := fmt.Sprintf("%s/%s", s.buildPath, s.siteName)
+ log.Println(fmt.Sprintf("Preparing manifests for %s", s.siteName))
+
+ // do the initial validation of pre-requisites
+ utils.ValidateRequirements(s.buildPath, s.siteName)
+ binariesPath := fmt.Sprintf("%s/requirements", sitePath)
+
+ // retrieve profile path and clone the repo
+ _, profileLayerPath := s.GetProfileFromSite()
+ indexGit := strings.LastIndex(profileLayerPath, "//")
+ var blueprintRepo string
+ var absoluteBlueprintRepo string
+ if indexGit == -1 {
+ blueprintRepo = profileLayerPath
+ absoluteBlueprintRepo = profileLayerPath
+ } else {
+ blueprintRepo = profileLayerPath[0:indexGit]
+ absoluteBlueprintRepo = profileLayerPath[0:(indexGit + 2)]
+ }
+
+ log.Println(fmt.Sprintf("Downloading blueprint repo from %s", blueprintRepo))
+ blueprintDir := fmt.Sprintf("%s/blueprint", sitePath)
+ os.RemoveAll(blueprintDir)
+ client := &getter.Client{Src: blueprintRepo, Dst: blueprintDir, Mode: getter.ClientModeAny}
+ err := client.Get()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error cloning profile repository: %s", err))
+ }
+
+ // and now copy site inside the sites folder, replacing the absolute references to relative
+ cmd := exec.Command("cp", "-R", fmt.Sprintf("%s/site", sitePath), fmt.Sprintf("%s/blueprint/sites/site", sitePath))
+ err = cmd.Run()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error copying site into blueprint: %s", err))
+ os.Exit(1)
+ }
+
+ err = filepath.Walk(fmt.Sprintf("%s/blueprint/sites/site", sitePath), func(path string, info os.FileInfo, err error) error {
+ if err == nil {
+ if info.Name() == "kustomization.yaml" {
+ readKustomization, err := ioutil.ReadFile(path)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error opening kustomization file: %s", err))
+ os.Exit(1)
+ }
+ newKustomization := strings.Replace(string(readKustomization), absoluteBlueprintRepo, "../../../", -1)
+
+ err = ioutil.WriteFile(path, []byte(newKustomization), 0)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing modified kustomization file: %s", err))
+ os.Exit(1)
+ }
+ return nil
+ }
+ } else {
+ log.Println(fmt.Sprintf("Error walking on site directory: %s", err))
+ os.Exit(1)
}
- // read yaml from requirements and start fetching the bits
- requirementsFile := fmt.Sprintf("%s/requirements.yaml", profileBuildPath)
- file, err := os.Open(requirementsFile)
+ return nil
+ })
+
+ // generate openshift-install manifests based on phase 00_install-config
+ assetsPath := fmt.Sprintf("%s/generated_assets", sitePath)
+ os.RemoveAll(assetsPath)
+ os.Mkdir(assetsPath, 0755)
+
+ out := utils.ApplyKustomize(fmt.Sprintf("%s/kustomize", binariesPath), fmt.Sprintf("%s/blueprint/sites/site/00_install-config", sitePath))
+ // check if we have any content and write to the target file
+ if len(out) > 0 {
+ err := ioutil.WriteFile(fmt.Sprintf("%s/install-config.yaml", assetsPath), out, 0644)
if err != nil {
- log.Fatal("Error reading requirements file")
+ log.Fatal(fmt.Sprintf("Error writing final install-config file: %s", err))
os.Exit(1)
}
- defer file.Close()
- scanner := bufio.NewScanner(file)
- for scanner.Scan() {
- requirementsLine := scanner.Text()
+ } else {
+ log.Fatal("Error, kustomize did not return any content")
+ os.Exit(1)
+ }
- // requirements is composed of binary and source
- requirementsBits := strings.SplitN(strings.TrimSpace(requirementsLine), ":", 2)
- r := requirements.New(strings.TrimSpace(requirementsBits[0]), strings.TrimSpace(requirementsBits[1]), fmt.Sprintf("%s/requirements", siteBuildPath))
- r.FetchRequirement()
+ // now generate the manifests
+ cmd = exec.Command(fmt.Sprintf("%s/openshift-install", binariesPath), "create", "manifests", fmt.Sprintf("--dir=%s", assetsPath), "--log-level", "debug")
+ err = cmd.Run()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error creating manifests: %s", err))
+ os.Exit(1)
+ }
+
+ // iterate over all the generated files and create a kustomization file
+ f, err := os.Create(fmt.Sprintf("%s/kustomization.yaml", assetsPath))
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error creating kustomization file: %s", err))
+ os.Exit(1)
+ }
+ defer f.Close()
+
+ _, err = f.WriteString("resources:\n")
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing kustomization file: %s", err))
+ os.Exit(1)
+ }
+
+ filePatterns := []string{fmt.Sprintf("%s/manifests/*.yaml", assetsPath), fmt.Sprintf("%s/manifests/*.yml", assetsPath), fmt.Sprintf("%s/openshift/*.yaml", assetsPath)}
+ for _, filePattern := range filePatterns {
+ files, err := filepath.Glob(filePattern)
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error reading manifest files: %s", err))
+ os.Exit(1)
}
- // remove profile folder
- os.RemoveAll(profileBuildPath)
+ // iterate over each file, remove the absolute path and write it
+ for _, fileName := range files {
+ strippedName := strings.TrimPrefix(fileName, fmt.Sprintf("%s/", assetsPath))
+ _, err := f.WriteString(fmt.Sprintf("- %s\n", strippedName))
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error writing kustomization file: %s", err))
+ os.Exit(1)
+ }
+ }
+ }
- } else if os.IsNotExist(err) {
- log.Fatal(fmt.Sprintf("File %s does not exist, exiting", profileFile))
+ // move the content of the generated site to blueprint base
+ os.Rename(fmt.Sprintf("%s/generated_assets/", sitePath), fmt.Sprintf("%s/blueprint/base/00_cluster/", sitePath))
+
+ // apply kustomize on cluster-mods
+ 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)
+
+ } else {
+ log.Fatal("Error, kustomize did not return any content")
os.Exit(1)
}
+
}
--- /dev/null
+package utils
+
+import (
+ "fmt"
+ "log"
+ "os"
+ "os/exec"
+ "path/filepath"
+)
+
+// utility to validate pre-requisites for deploying
+func ValidateRequirements(buildPath string, siteName string) {
+ // check for pull-secret.json
+ if _, err := os.Stat(fmt.Sprintf("%s/pull-secret.json", buildPath)); os.IsNotExist(err) {
+ log.Fatal(fmt.Sprintf("Error, no valid pull-secret.json found in %s", buildPath))
+ os.Exit(1)
+ }
+
+ // check for ssh key , and generate if it does not exist
+ if _, err := os.Stat(fmt.Sprintf("%s/id_rsa.pub", buildPath)); os.IsNotExist(err) {
+ log.Println(fmt.Sprintf("No SSH public key (id_rsa.pub) found in %s. Generating keypair.", buildPath))
+
+ cmd := exec.Command("ssh-keygen", "-b", "2048", "-f", fmt.Sprintf("%s/id_rsa", buildPath), "-C", "user@example.com", "-q", "-N", "\"\"")
+ err = cmd.Run()
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error generating ssh keypair: %s", err))
+ os.Exit(1)
+ }
+ }
+
+ // check if requirements folder exist
+ requirementsFolder := fmt.Sprintf("%s/%s/requirements", buildPath, siteName)
+ if _, err := os.Stat(requirementsFolder); os.IsNotExist(err) {
+ log.Fatal(fmt.Sprintf("Error, requirements folder not found in %s", requirementsFolder))
+ os.Exit(1)
+ }
+
+}
+
+// utility to apply kustomize on a given directory
+func ApplyKustomize(kustomizeBinary string, kustomizePath string) []byte {
+ // retrieve executable path to inject env var
+ ex, err := os.Executable()
+ if err != nil {
+ log.Fatal("Error retrieving the current running path")
+ os.Exit(1)
+ }
+ exPath := filepath.Dir(ex)
+
+ cmd := exec.Command(kustomizeBinary, "build", "--enable_alpha_plugins", "--reorder", "none", kustomizePath)
+ cmd.Env = os.Environ()
+ cmd.Env = append(cmd.Env, fmt.Sprintf("XDG_CONFIG_HOME=%s/plugins", exPath))
+ out, err := cmd.Output()
+
+ if err != nil {
+ log.Fatal(fmt.Sprintf("Error kustomizing manifests for %s: %s", kustomizePath, err))
+ os.Exit(1)
+ }
+
+ return out
+}