Compare commits
48 Commits
v0.9.10
...
random-fix
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
75ce6caa2b | ||
|
|
d05b119a68 | ||
|
|
ed26e692c9 | ||
|
|
5909c728ab | ||
|
|
813bec2377 | ||
|
|
d77654e763 | ||
|
|
73c3ac1d58 | ||
|
|
083203128c | ||
|
|
97cbfa050c | ||
|
|
ccc2997745 | ||
|
|
1f5ee3d487 | ||
|
|
87ace81dee | ||
|
|
44b936a9aa | ||
|
|
2618e72a46 | ||
|
|
1aac550f66 | ||
|
|
bacaea1b92 | ||
|
|
0e6a1ab18d | ||
|
|
acfa1f16a1 | ||
|
|
8b68a4d305 | ||
|
|
114d0a13c8 | ||
|
|
c733d2821e | ||
|
|
69306605a3 | ||
|
|
67ec3105f0 | ||
|
|
e69149ec64 | ||
|
|
cedb7f8fca | ||
|
|
60a77dab5c | ||
|
|
fee81b25a6 | ||
|
|
b041d8be3c | ||
|
|
a73209864c | ||
|
|
b5eea11050 | ||
|
|
a662e26867 | ||
|
|
198c631bd1 | ||
|
|
6c38708c9f | ||
|
|
8c0ffc667d | ||
|
|
b8fc1474f8 | ||
|
|
bcb0c44300 | ||
|
|
e2294e48c4 | ||
|
|
dbf6f6debc | ||
|
|
002b0faaa1 | ||
|
|
a676d10ed0 | ||
|
|
ad7861cd13 | ||
|
|
f17e27f2ef | ||
|
|
77bf52e0b0 | ||
|
|
3819f29412 | ||
|
|
bdbcc665ae | ||
|
|
b3d0eff376 | ||
|
|
070abea0d8 | ||
|
|
d04defdf13 |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -7,3 +7,5 @@ pkg/qliksense/qliksense-packr.go
|
||||
pkg/qliksense/docker-registry
|
||||
/pkg/qliksense/tests
|
||||
.DS_Store
|
||||
|
||||
.idea/
|
||||
@@ -42,3 +42,20 @@ func configViewCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
func configEditCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
c := &cobra.Command{
|
||||
Use: "edit [context-name]",
|
||||
Short: "Edit the context cr",
|
||||
Long: `edit the context cr. if no context name provided default context will be edited
|
||||
It will open the vim editor unless KUBE_EDITOR is defined`,
|
||||
Example: `qliksense config edit [context-name]`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(args) == 1 {
|
||||
return q.EditCR(args[0])
|
||||
}
|
||||
return q.EditCR("")
|
||||
},
|
||||
}
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -37,6 +37,6 @@ func crdsInstallCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
},
|
||||
}
|
||||
f := c.Flags()
|
||||
f.BoolVarP(&opts.All, "all", "a", false, "Include All CRDs")
|
||||
f.BoolVarP(&opts.All, "all", "", false, "Include All CRDs")
|
||||
return c
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func preflightCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
return preflightCmd
|
||||
}
|
||||
|
||||
func preflightCheckDnsCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
func pfDnsCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightDnsCmd = &cobra.Command{
|
||||
Use: "dns",
|
||||
Short: "perform preflight dns check",
|
||||
@@ -28,39 +28,59 @@ func preflightCheckDnsCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
Example: `qliksense preflight dns`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
err := qp.DownloadPreflight()
|
||||
|
||||
// Preflight DNS check
|
||||
fmt.Printf("Preflight DNS check\n")
|
||||
fmt.Println("---------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("There has been an error downloading preflight: %+v", err)
|
||||
log.Println(err)
|
||||
return err
|
||||
fmt.Printf("Preflight DNS check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return qp.CheckDns()
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
if err = qp.CheckDns(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight DNS check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightDnsCmd
|
||||
}
|
||||
|
||||
func preflightCheckK8sVersionCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
func pfK8sVersionCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightCheckK8sVersionCmd = &cobra.Command{
|
||||
Use: "k8s-version",
|
||||
Short: "check k8s version",
|
||||
Long: `check minimum valid k8s version on the cluster`,
|
||||
Example: `qliksense preflight k8s-version`,
|
||||
Use: "kube-version",
|
||||
Short: "check kubernetes version",
|
||||
Long: `check minimum valid kubernetes version on the cluster`,
|
||||
Example: `qliksense preflight kube-version`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
err := qp.DownloadPreflight()
|
||||
|
||||
// Preflight Kubernetes minimum version check
|
||||
fmt.Printf("Preflight kubernetes minimum version check\n")
|
||||
fmt.Println("------------------------------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("There has been an error downloading preflight: %+v", err)
|
||||
log.Println(err)
|
||||
return err
|
||||
fmt.Printf("Preflight kubernetes minimum version check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
return qp.CheckK8sVersion()
|
||||
if err = qp.CheckK8sVersion(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Printf("Preflight kubernetes minimum version check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightCheckK8sVersionCmd
|
||||
}
|
||||
|
||||
func preflightAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
func pfAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var mongodbUrl string
|
||||
var preflightAllChecksCmd = &cobra.Command{
|
||||
Use: "all",
|
||||
Short: "perform all checks",
|
||||
@@ -68,14 +88,263 @@ func preflightAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
Example: `qliksense preflight all`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
err := qp.DownloadPreflight()
|
||||
|
||||
// Preflight run all checks
|
||||
fmt.Printf("Running all preflight checks\n")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
err = fmt.Errorf("There has been an error downloading preflight: %+v", err)
|
||||
log.Println(err)
|
||||
return err
|
||||
fmt.Println(err)
|
||||
fmt.Printf("Running preflight check suite has FAILED...\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return qp.RunAllPreflightChecks()
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
qp.RunAllPreflightChecks(namespace, kubeConfigContents, mongodbUrl)
|
||||
return nil
|
||||
|
||||
},
|
||||
}
|
||||
f := preflightAllChecksCmd.Flags()
|
||||
f.StringVarP(&mongodbUrl, "mongodb-url", "", "", "mongodbUrl to try connecting to")
|
||||
return preflightAllChecksCmd
|
||||
}
|
||||
|
||||
func pfDeploymentCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var pfDeploymentCheckCmd = &cobra.Command{
|
||||
Use: "deployment",
|
||||
Short: "perform preflight deploymwnt check",
|
||||
Long: `perform preflight deployment check to ensure that we can create deployments in the cluster`,
|
||||
Example: `qliksense preflight deployment`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight deployments check
|
||||
fmt.Printf("Preflight deployment check\n")
|
||||
fmt.Println("--------------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight deployment check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
if err = qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight deploy check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return pfDeploymentCheckCmd
|
||||
}
|
||||
|
||||
func pfServiceCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var pfServiceCheckCmd = &cobra.Command{
|
||||
Use: "service",
|
||||
Short: "perform preflight service check",
|
||||
Long: `perform preflight service check to ensure that we are able to create services in the cluster`,
|
||||
Example: `qliksense preflight service`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight service check
|
||||
fmt.Printf("Preflight service check\n")
|
||||
fmt.Println("-----------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight service check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
if err = qp.CheckService(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight service check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return pfServiceCheckCmd
|
||||
}
|
||||
|
||||
func pfPodCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var pfPodCheckCmd = &cobra.Command{
|
||||
Use: "pod",
|
||||
Short: "perform preflight pod check",
|
||||
Long: `perform preflight pod check to ensure we can create pods in the cluster`,
|
||||
Example: `qliksense preflight pod`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight pod check
|
||||
fmt.Printf("Preflight pod check\n")
|
||||
fmt.Println("--------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight pod check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
if err = qp.CheckPod(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight pod check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return pfPodCheckCmd
|
||||
}
|
||||
|
||||
func pfCreateRoleCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightRoleCmd = &cobra.Command{
|
||||
Use: "role",
|
||||
Short: "preflight create role check",
|
||||
Long: `perform preflight role check to ensure we are able to create a role in the cluster`,
|
||||
Example: `qliksense preflight createRole`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight role check
|
||||
fmt.Printf("Preflight role check\n")
|
||||
fmt.Println("---------------------------")
|
||||
namespace, _, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight role check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = qp.CheckCreateRole(namespace); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight role FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightRoleCmd
|
||||
}
|
||||
|
||||
func pfCreateRoleBindingCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightRoleBindingCmd = &cobra.Command{
|
||||
Use: "rolebinding",
|
||||
Short: "preflight create rolebinding check",
|
||||
Long: `perform preflight rolebinding check to ensure we are able to create a rolebinding in the cluster`,
|
||||
Example: `qliksense preflight rolebinding`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight createRoleBinding check
|
||||
fmt.Printf("Preflight rolebinding check\n")
|
||||
fmt.Println("---------------------------")
|
||||
namespace, _, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight rolebinding check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = qp.CheckCreateRoleBinding(namespace); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight rolebinding check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightRoleBindingCmd
|
||||
}
|
||||
|
||||
func pfCreateServiceAccountCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightServiceAccountCmd = &cobra.Command{
|
||||
Use: "serviceaccount",
|
||||
Short: "preflight create ServiceAccount check",
|
||||
Long: `perform preflight serviceaccount check to ensure we are able to create a service account in the cluster`,
|
||||
Example: `qliksense preflight serviceaccount`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight createServiceAccount check
|
||||
fmt.Printf("Preflight ServiceAccount check\n")
|
||||
fmt.Println("-------------------------------------")
|
||||
namespace, _, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight serviceaccount check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = qp.CheckCreateServiceAccount(namespace); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight serviceaccount check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightServiceAccountCmd
|
||||
}
|
||||
|
||||
func pfCreateAuthCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var preflightCreateAuthCmd = &cobra.Command{
|
||||
Use: "authcheck",
|
||||
Short: "preflight authcheck",
|
||||
Long: `perform preflight authcheck that combines the role, rolebinding and serviceaccount checks`,
|
||||
Example: `qliksense preflight authcheck`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight authcheck
|
||||
fmt.Printf("Preflight authcheck\n")
|
||||
fmt.Println("------------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight authcheck FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if err = qp.CheckCreateRB(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight authcheck FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
return preflightCreateAuthCmd
|
||||
}
|
||||
|
||||
func pfMongoCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
var mongodbUrl string
|
||||
var preflightMongoCmd = &cobra.Command{
|
||||
Use: "mongo",
|
||||
Short: "preflight mongo OR preflight mongo --url=<url>",
|
||||
Long: `perform preflight mongo check to ensure we are able to connect to a mongodb instance in the cluster`,
|
||||
Example: `qliksense preflight mongo OR preflight mongo --url=<url>`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
qp := &preflight.QliksensePreflight{Q: q}
|
||||
|
||||
// Preflight mongo check
|
||||
fmt.Printf("Preflight mongo check\n")
|
||||
fmt.Println("-------------------------------------")
|
||||
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||
if err != nil {
|
||||
fmt.Printf("Preflight mongo check FAILED\n")
|
||||
log.Fatal(err)
|
||||
}
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
if err = qp.CheckMongo(kubeConfigContents, namespace, mongodbUrl); err != nil {
|
||||
fmt.Println(err)
|
||||
fmt.Print("Preflight mongo check FAILED\n")
|
||||
log.Fatal()
|
||||
}
|
||||
return nil
|
||||
},
|
||||
}
|
||||
f := preflightMongoCmd.Flags()
|
||||
f.StringVarP(&mongodbUrl, "url", "", "", "mongodbUrl to try connecting to")
|
||||
return preflightMongoCmd
|
||||
}
|
||||
|
||||
@@ -20,28 +20,7 @@ func pullQliksenseImages(q *qliksense.Qliksense) *cobra.Command {
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||
if version == "" {
|
||||
if qcr, err := qConfig.GetCurrentCR(); err != nil {
|
||||
return err
|
||||
} else {
|
||||
version = qcr.GetLabelFromCr("version")
|
||||
}
|
||||
}
|
||||
|
||||
if version != "" {
|
||||
if !qConfig.IsRepoExistForCurrent(version) {
|
||||
if err := q.FetchQK8s(version); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if err := qConfig.SwitchCurrentCRToVersionAndProfile(version, opts.Profile); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
return q.PullImagesForCurrentCR()
|
||||
return q.PullImages(version, opts.Profile)
|
||||
},
|
||||
}
|
||||
f := cmd.Flags()
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/qlik-oss/sense-installer/pkg"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
"github.com/qlik-oss/sense-installer/pkg/preflight"
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
@@ -100,6 +101,10 @@ func getRootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
if err := p.SetUpQliksenseDefaultContext(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
pf := preflight.NewPreflightConfig(p.QliksenseHome)
|
||||
if err := pf.Initialize(); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
globalEulaPostRun(cmd, p)
|
||||
}
|
||||
},
|
||||
@@ -185,6 +190,8 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
// add clean-config-repo-patches command as a sub-command to the app config sub-command
|
||||
configCmd.AddCommand(cleanConfigRepoPatchesCmd(p))
|
||||
|
||||
// open editor for config
|
||||
configCmd.AddCommand(configEditCmd(p))
|
||||
// add uninstall command
|
||||
cmd.AddCommand(uninstallCmd(p))
|
||||
|
||||
@@ -195,11 +202,17 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
|
||||
// add preflight command
|
||||
preflightCmd := preflightCmd(p)
|
||||
preflightCmd.AddCommand(preflightCheckDnsCmd(p))
|
||||
preflightCmd.AddCommand(preflightCheckK8sVersionCmd(p))
|
||||
preflightCmd.AddCommand(preflightAllChecksCmd(p))
|
||||
//preflightCmd.AddCommand(preflightCheckMongoCmd(p))
|
||||
//preflightCmd.AddCommand(preflightCheckAllCmd(p))
|
||||
preflightCmd.AddCommand(pfDnsCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfK8sVersionCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfAllChecksCmd(p))
|
||||
preflightCmd.AddCommand(pfMongoCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfDeploymentCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfServiceCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfPodCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfCreateRoleCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfCreateRoleBindingCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfCreateServiceAccountCheckCmd(p))
|
||||
preflightCmd.AddCommand(pfCreateAuthCheckCmd(p))
|
||||
|
||||
cmd.AddCommand(preflightCmd)
|
||||
cmd.AddCommand(loadCrFile(p))
|
||||
|
||||
@@ -29,19 +29,20 @@ The expected output should be similar to the one shown below.
|
||||
```console
|
||||
$ qliksense preflight dns
|
||||
|
||||
Creating resources to run preflight checks
|
||||
deployment.apps/qnginx001 created
|
||||
service/qnginx001 created
|
||||
pod/qnginx001-6db5fc95c5-s9sl2 condition met
|
||||
Running Preflight checks ⠇
|
||||
--- PASS DNS check
|
||||
--- DNS check passed
|
||||
--- PASS cluster-preflight-checks
|
||||
PASS
|
||||
|
||||
DNS check completed, cleaning up resources now
|
||||
service "qnginx001" deleted
|
||||
deployment.extensions "qnginx001" deleted
|
||||
Preflight DNS check
|
||||
---------------------
|
||||
Created deployment "dep-dns-preflight-check"
|
||||
Created service "svc-dns-pf-check"
|
||||
Created pod: pf-pod-1
|
||||
Fetching pod: pf-pod-1
|
||||
Fetching pod: pf-pod-1
|
||||
Exec-ing into the container...
|
||||
Preflight DNS check: PASSED
|
||||
Completed preflight DNS check
|
||||
Cleaning up resources...
|
||||
Deleted pod: pf-pod-1
|
||||
Deleted service: svc-dns-pf-check
|
||||
Deleted deployment: dep-dns-preflight-check
|
||||
|
||||
```
|
||||
|
||||
@@ -51,50 +52,202 @@ The command to run this check and the expected similar output are as shown below
|
||||
```console
|
||||
$ qliksense preflight k8s-version
|
||||
|
||||
Minimum Kubernetes version supported: 1.11.0
|
||||
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"06ad960bfd03b39c8310aaf92d1e7c12ce618213", GitTreeState:"clean", BuildDate:"2020-02-13T18:08:14Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"darwin/amd64"}
|
||||
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
|
||||
Running Preflight checks ⠇
|
||||
--- PASS Required Kubernetes Version
|
||||
--- Good to go.
|
||||
--- PASS cluster-preflight-checks
|
||||
PASS
|
||||
Preflight kubernetes minimum version check
|
||||
------------------------------------------
|
||||
Kubernetes API Server version: v1.15.5
|
||||
Current K8s Version: 1.15.5
|
||||
Current 1.15.5 is greater than minimum required version:1.11.0, hence good to go
|
||||
Preflight minimum kubernetes version check: PASSED
|
||||
Completed Preflight kubernetes minimum version check
|
||||
|
||||
Minimum kubernetes version check completed
|
||||
```
|
||||
|
||||
### Service check
|
||||
We use the commmand below to test if we are able to create a service in the cluster.
|
||||
```console
|
||||
$ qliksense preflight service
|
||||
|
||||
Preflight service check
|
||||
-----------------------
|
||||
|
||||
Preflight service check:
|
||||
Created service "svc-pf-check"
|
||||
Preflight service creation check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted service: svc-pf-check
|
||||
Completed preflight service check
|
||||
```
|
||||
|
||||
### Deployment check
|
||||
We use the commmand below to test if we are able to create a deployment in the cluster. After the test exexutes, we wait until the created deployment terminates before we exit the command.
|
||||
```console
|
||||
$ qliksense preflight deployment
|
||||
|
||||
Preflight deployment check
|
||||
-----------------------
|
||||
Preflight deployment check:
|
||||
Created deployment "deployment-preflight-check"
|
||||
Preflight Deployment check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted deployment: deployment-preflight-check
|
||||
Completed preflight deployment check
|
||||
```
|
||||
|
||||
### Pod check
|
||||
We use the commmand below to test if we are able to create a pod in the cluster.
|
||||
```console
|
||||
$ qliksense preflight pod
|
||||
|
||||
Preflight pod check
|
||||
--------------------
|
||||
|
||||
Preflight pod check:
|
||||
Created pod: pod-pf-check
|
||||
Preflight pod creation check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted pod: pod-pf-check
|
||||
Completed preflight pod check
|
||||
```
|
||||
|
||||
### Create-Role check
|
||||
We use the command below to test if we are able to create a role in the cluster
|
||||
```shell
|
||||
$ qliksense preflight create-role
|
||||
Preflight create-role check
|
||||
---------------------------
|
||||
Preflight create-role check:
|
||||
Created role: role-preflight-check
|
||||
Preflight create-role check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted role: role-preflight-check
|
||||
|
||||
Completed preflight create-role check
|
||||
```
|
||||
|
||||
### Create-RoleBinding check
|
||||
We use the command below to test if we are able to create a role binding in the cluster
|
||||
```shell
|
||||
$ qliksense preflight createRoleBinding
|
||||
|
||||
Preflight create roleBinding check
|
||||
---------------------------
|
||||
Preflight createRoleBinding check:
|
||||
Created RoleBinding: role-binding-preflight-check
|
||||
Preflight createRoleBinding check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleting RoleBinding: role-binding-preflight-check
|
||||
Deleted RoleBinding: role-binding-preflight-check
|
||||
|
||||
Completed preflight createRoleBinding check
|
||||
```
|
||||
|
||||
### Create-ServiceAccount check
|
||||
We use the command below to test if we are able to create a service account in the cluster
|
||||
```shell
|
||||
$ qliksense preflight createServiceAccount
|
||||
|
||||
Preflight create ServiceAccount check
|
||||
-------------------------------------
|
||||
Preflight createServiceAccount check:
|
||||
Created Service Account: preflight-check-test-serviceaccount
|
||||
Preflight createServiceAccount check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleting ServiceAccount: preflight-check-test-serviceaccount
|
||||
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
||||
|
||||
Completed preflight createServiceAccount check
|
||||
```
|
||||
|
||||
### CreateRB check
|
||||
We use the command below to combine creation of role, role binding, and service account tests
|
||||
```shell
|
||||
$ qliksense preflight createRB
|
||||
|
||||
Preflight createRB check
|
||||
-------------------------------------
|
||||
Preflight create-role check:
|
||||
Created role: role-preflight-check
|
||||
Preflight create-role check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted role: role-preflight-check
|
||||
|
||||
Completed preflight create-role check
|
||||
|
||||
Preflight create RoleBinding check:
|
||||
Created RoleBinding: role-binding-preflight-check
|
||||
Preflight create RoleBinding check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted RoleBinding: role-binding-preflight-check
|
||||
|
||||
Completed preflight create RoleBinding check
|
||||
|
||||
Preflight createServiceAccount check:
|
||||
Created Service Account: preflight-check-test-serviceaccount
|
||||
Preflight createServiceAccount check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
||||
|
||||
Completed preflight createServiceAccount check
|
||||
Completed preflight CreateRB check
|
||||
```
|
||||
|
||||
### Mongodb check
|
||||
We can check if we are able to connect to an instance of mongodb on the cluster by either supplying the mongodbUri as part of the command or infer it from the current context.
|
||||
|
||||
```shell
|
||||
qliksense preflight mongo --url=<url> OR
|
||||
qliksense preflight mongo
|
||||
|
||||
Preflight mongo check
|
||||
---------------------
|
||||
Preflight mongodb check:
|
||||
Created pod: pf-mongo-pod
|
||||
stdout: MongoDB shell version v4.2.5
|
||||
connecting to: <url>/?compressors=disabled&gssapiServiceName=mongodb
|
||||
Implicit session: session { "id" : UUID("64f639d3-2c93-4894-80f6-ee14acaf56a5") }
|
||||
MongoDB server version: 4.2.5
|
||||
bye
|
||||
stderr:
|
||||
Preflight mongo check: PASSED
|
||||
Deleted pod: pf-mongo-pod
|
||||
Completed preflight mongodb check
|
||||
```
|
||||
|
||||
|
||||
|
||||
### Running all checks
|
||||
Run the command shown below to execute all preflight checks.
|
||||
```console
|
||||
$ qliksense preflight all --mongodb-url=<url> OR
|
||||
$ qliksense preflight all
|
||||
|
||||
Running all preflight checks
|
||||
|
||||
Running DNS check...
|
||||
Creating resources to run preflight checks
|
||||
deployment.apps/qnginx001 created
|
||||
service/qnginx001 created
|
||||
pod/qnginx001-6db5fc95c5-grwv2 condition met
|
||||
Running Preflight checks ⠇
|
||||
--- PASS DNS check
|
||||
--- DNS check passed
|
||||
--- PASS cluster-preflight-checks
|
||||
PASS
|
||||
Preflight DNS check
|
||||
-------------------
|
||||
Created deployment "dep-dns-preflight-check"
|
||||
Created service "svc-dns-pf-check"
|
||||
Created pod: pf-pod-1
|
||||
Fetching pod: pf-pod-1
|
||||
Fetching pod: pf-pod-1
|
||||
Exec-ing into the container...
|
||||
Preflight DNS check: PASSED
|
||||
Completed preflight DNS check
|
||||
Cleaning up resources...
|
||||
Deleted pod: pf-pod-1
|
||||
Deleted service: svc-dns-pf-check
|
||||
Deleted deployment: dep-dns-preflight-check
|
||||
|
||||
DNS check completed, cleaning up resources now
|
||||
service "qnginx001" deleted
|
||||
deployment.extensions "qnginx001" deleted
|
||||
|
||||
Running minimum kubernetes version check...
|
||||
Minimum Kubernetes version supported: 1.11.0
|
||||
Client Version: version.Info{Major:"1", Minor:"17", GitVersion:"v1.17.3", GitCommit:"06ad960bfd03b39c8310aaf92d1e7c12ce618213", GitTreeState:"clean", BuildDate:"2020-02-13T18:08:14Z", GoVersion:"go1.13.8", Compiler:"gc", Platform:"darwin/amd64"}
|
||||
Server Version: version.Info{Major:"1", Minor:"15", GitVersion:"v1.15.5", GitCommit:"20c265fef0741dd71a66480e35bd69f18351daea", GitTreeState:"clean", BuildDate:"2019-10-15T19:07:57Z", GoVersion:"go1.12.10", Compiler:"gc", Platform:"linux/amd64"}
|
||||
Running Preflight checks ⠧
|
||||
--- PASS Required Kubernetes Version
|
||||
--- Good to go.
|
||||
--- PASS cluster-preflight-checks
|
||||
PASS
|
||||
|
||||
Minimum kubernetes version check completed
|
||||
Preflight kubernetes minimum version check
|
||||
------------------------------------------
|
||||
Kubernetes API Server version: v1.15.5
|
||||
Current K8s Version: 1.15.5
|
||||
Current 1.15.5 is greater than minimum required version:1.11.0, hence good to go
|
||||
Preflight minimum kubernetes version check: PASSED
|
||||
Completed Preflight kubernetes minimum version check
|
||||
...
|
||||
...
|
||||
All preflight checks have PASSED
|
||||
Completed running all preflight checks
|
||||
|
||||
```
|
||||
6
go.mod
6
go.mod
@@ -10,12 +10,13 @@ replace (
|
||||
k8s.io/client-go => k8s.io/client-go v0.0.0-20191016111102-bec269661e48
|
||||
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51
|
||||
|
||||
sigs.k8s.io/kustomize/api => github.com/qlik-oss/kustomize/api v0.3.3-0.20200206224201-2e697eccbad9
|
||||
sigs.k8s.io/kustomize/api => github.com/qlik-oss/kustomize/api v0.3.3-0.20200402170547-2e8140160c36
|
||||
)
|
||||
|
||||
require (
|
||||
cloud.google.com/go v0.52.0 // indirect
|
||||
cloud.google.com/go/storage v1.5.0 // indirect
|
||||
github.com/Masterminds/semver/v3 v3.0.3
|
||||
github.com/Shopify/ejson v1.2.1
|
||||
github.com/aws/aws-sdk-go v1.28.9 // indirect
|
||||
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
||||
@@ -41,7 +42,7 @@ require (
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/morikuni/aec v1.0.0 // indirect
|
||||
github.com/pkg/errors v0.8.1
|
||||
github.com/qlik-oss/k-apis v0.0.25
|
||||
github.com/qlik-oss/k-apis v0.0.34
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rogpeppe/go-internal v1.5.2 // indirect
|
||||
github.com/spf13/cobra v0.0.6
|
||||
@@ -59,6 +60,7 @@ require (
|
||||
k8s.io/api v0.17.0
|
||||
k8s.io/apimachinery v0.17.0
|
||||
k8s.io/client-go v11.0.0+incompatible
|
||||
k8s.io/kubectl v0.0.0-20191016120415-2ed914427d51
|
||||
sigs.k8s.io/kustomize/api v0.3.2
|
||||
sigs.k8s.io/yaml v1.1.0
|
||||
)
|
||||
|
||||
24
go.sum
24
go.sum
@@ -131,6 +131,8 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24
|
||||
github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d h1:xDfNPAt8lFiC1UJrqV3uuy861HCTo708pDMbjHHdCas=
|
||||
github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ00z/TKoufEY6K/a0k6AhaJrQKdFe6OfVXsa4=
|
||||
github.com/bgentry/speakeasy v0.1.0/go.mod h1:+zsyZBPWlz7T6j88CTgSN5bM796AkVf0kBD4zp0CCIs=
|
||||
github.com/bitly/go-simplejson v0.5.0 h1:6IH+V8/tVMab511d5bn4M7EwGXZf9Hj6i2xSwkNEM+Y=
|
||||
github.com/bitly/go-simplejson v0.5.0/go.mod h1:cXHtHw4XUPsvGaxgjIAn8PhEWG9NfngEKAMDJEczWVA=
|
||||
@@ -561,6 +563,8 @@ github.com/hashicorp/go-retryablehttp v0.6.3/go.mod h1:vAew36LZh98gCBJNLH42IQ1ER
|
||||
github.com/hashicorp/go-rootcerts v1.0.0/go.mod h1:K6zTfqpRlCUIjkwsN4Z+hiSfzSTQa6eBIzfwKfwNnHU=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1 h1:DMo4fmknnz0E0evoNYnV48RjWndOsmd6OW+09R3cEP8=
|
||||
github.com/hashicorp/go-rootcerts v1.0.1/go.mod h1:pqUvnprVnM5bf7AOirdbb01K4ccR319Vf4pU3K5EGc8=
|
||||
github.com/hashicorp/go-safetemp v1.0.0 h1:2HR189eFNrjHQyENnQMMpCiBAsRxzbTMIgBhEyExpmo=
|
||||
github.com/hashicorp/go-safetemp v1.0.0/go.mod h1:oaerMy3BhqiTbVye6QuFhFtIceqFoDHxNAB65b+Rj1I=
|
||||
github.com/hashicorp/go-sockaddr v1.0.0/go.mod h1:7Xibr9yA9JjQq1JpNB2Vw7kxv8xerXegt+ozgdvDeDU=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2 h1:ztczhD1jLxIRjVejw8gFomI1BQZOe2WoVOu0SyteCQc=
|
||||
github.com/hashicorp/go-sockaddr v1.0.2/go.mod h1:rB4wwRAUzs07qva3c5SdrY/NEtAUjGlgmH/UkBUC97A=
|
||||
@@ -568,6 +572,7 @@ github.com/hashicorp/go-syslog v1.0.0/go.mod h1:qPfqrKkXGihmCqbJM2mZgkZGvKG1dFdv
|
||||
github.com/hashicorp/go-uuid v1.0.0/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.1 h1:fv1ep09latC32wFoVwnqcnKJGnMSdBanPczbHAYm1BE=
|
||||
github.com/hashicorp/go-uuid v1.0.1/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-version v1.1.0 h1:bPIoEKD27tNdebFGGxxYwcL4nepeY4j1QP23PFRGzg0=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go-version v1.1.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA=
|
||||
github.com/hashicorp/go.net v0.0.1/go.mod h1:hjKkEWcCURg++eb33jQU7oqQcI9XDCnUzHA0oac0k90=
|
||||
@@ -847,16 +852,12 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
|
||||
github.com/prometheus/procfs v0.0.5 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/qlik-oss/k-apis v0.0.22 h1:tntQEeRqDYkBi2Ku5+xt7ABGMeFPck7+DOKrHUnpzwI=
|
||||
github.com/qlik-oss/k-apis v0.0.22/go.mod h1:DNiWYqCqPIN216l7+1rccArNIYPb1Le7kYDcPSyNp+Q=
|
||||
github.com/qlik-oss/k-apis v0.0.23 h1:w4lj2PHDTtKkukgoT2a6/jAY3NkkI/V0vNetkRzEXXY=
|
||||
github.com/qlik-oss/k-apis v0.0.23/go.mod h1:DNiWYqCqPIN216l7+1rccArNIYPb1Le7kYDcPSyNp+Q=
|
||||
github.com/qlik-oss/k-apis v0.0.24 h1:cBXggOMeEaUpxO91TfI2jQToh5r/ojBPcjuJM7cBRIM=
|
||||
github.com/qlik-oss/k-apis v0.0.24/go.mod h1:DNiWYqCqPIN216l7+1rccArNIYPb1Le7kYDcPSyNp+Q=
|
||||
github.com/qlik-oss/k-apis v0.0.25 h1:OF4YZDklkNyvPKKLOQ4a8JMQaFaqD/vevl6wOOzlhek=
|
||||
github.com/qlik-oss/k-apis v0.0.25/go.mod h1:DNiWYqCqPIN216l7+1rccArNIYPb1Le7kYDcPSyNp+Q=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200206224201-2e697eccbad9 h1:iqeqTS4zjp6rPEaxmFB7pemA2CMjOEN5dYSXZaQ82uw=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200206224201-2e697eccbad9/go.mod h1:OCt7FTrRVHj4kmR2xLJJUIqu00BTr6GeF09hSmM17Kw=
|
||||
github.com/qlik-oss/k-apis v0.0.34 h1:lOC21wz/nNZNmSfTXZSJCOm1BulaZfdg7tAuYb7knAE=
|
||||
github.com/qlik-oss/k-apis v0.0.34/go.mod h1:DNiWYqCqPIN216l7+1rccArNIYPb1Le7kYDcPSyNp+Q=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200401055330-fa528324112a h1:Vzod5XB+e25ENy5Lse0pXNmSYSDFxSEYhH/6Sj7twPg=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200401055330-fa528324112a/go.mod h1:tSQaDZ4Jt9KwYvD7LlMUPi5nkiGOno3PAKl5/XqEfxs=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200402170547-2e8140160c36 h1:BuT+cnXPQ6mcOWTDS1S8GXy65LAEMdPuNQCC36rMq28=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200402170547-2e8140160c36/go.mod h1:tSQaDZ4Jt9KwYvD7LlMUPi5nkiGOno3PAKl5/XqEfxs=
|
||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||
@@ -967,6 +968,7 @@ github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVM
|
||||
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
|
||||
github.com/ugorji/go/codec v1.1.7 h1:2SvQaVZ1ouYrrKKwoSk2pzd4A9evlKJb9oTL+OaLUSs=
|
||||
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
|
||||
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ulikunitz/xz v0.5.6 h1:jGHAfXawEGZQ3blwU5wnWKQJvAraT7Ftq9EXjnXYgt8=
|
||||
github.com/ulikunitz/xz v0.5.6/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
|
||||
github.com/ultraware/funlen v0.0.2/go.mod h1:Dp4UiAus7Wdb9KUZsYWZEWiRzGuM2kXM1lPbfaF6xhA=
|
||||
@@ -1001,6 +1003,8 @@ github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMx
|
||||
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
|
||||
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
|
||||
github.com/yujunz/go-getter v1.4.1-lite h1:FhvNc94AXMZkfqUwfMKhnQEC9phkphSGdPTL7tIdhOM=
|
||||
github.com/yujunz/go-getter v1.4.1-lite/go.mod h1:sbmqxXjyLunH1PkF3n7zSlnVeMvmYUuIl9ZVs/7NyCc=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940 h1:p7OofyZ509h8DmPLh8Hn+EIIZm/xYhdZHJ9GnXHdr6U=
|
||||
github.com/yvasiyarov/go-metrics v0.0.0-20150112132944-c25f46c4b940/go.mod h1:aX5oPXxHm3bOH+xeAttToC8pqch2ScQN/JoXYupl6xs=
|
||||
github.com/yvasiyarov/gorelic v0.0.6 h1:qMJQYPNdtJ7UNYHjX38KXZtltKTqimMuoQjNnSVIuJg=
|
||||
|
||||
@@ -133,6 +133,17 @@ func (qc *QliksenseConfig) GetCRFilePath(contextName string) string {
|
||||
}
|
||||
return crFilePath
|
||||
}
|
||||
|
||||
func (cr *QliksenseCR) IsRepoExist() bool {
|
||||
if cr.Spec.ManifestsRoot == "" {
|
||||
return false
|
||||
}
|
||||
if _, err := os.Lstat(cr.Spec.ManifestsRoot); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (qc *QliksenseConfig) IsRepoExist(contextName, version string) bool {
|
||||
if _, err := os.Lstat(qc.BuildRepoPathForContext(contextName, version)); err != nil {
|
||||
return false
|
||||
@@ -442,6 +453,18 @@ func (cr *QliksenseCR) SetEULA(value string) {
|
||||
cr.Spec.AddToConfigs("qliksense", "acceptEULA", value)
|
||||
}
|
||||
|
||||
// GetCustomCrdsPath get crds path if exist in the profile dir
|
||||
func (cr *QliksenseCR) GetCustomCrdsPath() string {
|
||||
if cr.Spec.ManifestsRoot == "" || cr.Spec.Profile == "" {
|
||||
return ""
|
||||
}
|
||||
crdsPath := filepath.Join(cr.Spec.GetManifestsRoot(), "manifests", cr.Spec.Profile, "crds")
|
||||
if _, err := os.Lstat(crdsPath); err != nil {
|
||||
return ""
|
||||
}
|
||||
return crdsPath
|
||||
}
|
||||
|
||||
// GetDecryptedCr it decrypts all the encrypted value and return a new CR
|
||||
func (qc *QliksenseConfig) GetDecryptedCr(cr *QliksenseCR) (*QliksenseCR, error) {
|
||||
newCr := &QliksenseCR{}
|
||||
|
||||
@@ -70,7 +70,7 @@ func ProcessConfigArgs(args []string) ([]*ServiceKeyValue, error) {
|
||||
return nil, err
|
||||
}
|
||||
resultSvcKV := make([]*ServiceKeyValue, len(args))
|
||||
re1 := regexp.MustCompile(`(\w{1,}).(\w{1,})=("*[\w\-?=_/:0-9\.]+"*)`)
|
||||
re1 := regexp.MustCompile(`([\w\-]{1,}).([\w\-]{1,})=("*[\w\-?=_/:0-9\.]+"*)`)
|
||||
for i, arg := range args {
|
||||
LogDebugMessage("Arg received: %s", arg)
|
||||
result := re1.FindStringSubmatch(arg)
|
||||
|
||||
46
pkg/api/utils_test.go
Normal file
46
pkg/api/utils_test.go
Normal file
@@ -0,0 +1,46 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestProcessConfigArgs(t *testing.T) {
|
||||
args := []string{
|
||||
"qliksense.mongodb=mongouri://something?ffall",
|
||||
"test_under.test=value_under",
|
||||
"test-dash.dash-key=value-dash",
|
||||
"test-dot.dot-key=127.0.0.1",
|
||||
"test123.key123=value123",
|
||||
}
|
||||
expectedKeys := []string{"mongodb", "test", "dash-key", "dot-key", "key123"}
|
||||
expectedValue := []string{"mongouri://something?ffall", "value_under", "value-dash", "127.0.0.1", "value123"}
|
||||
exppectedSvc := []string{"qliksense", "test_under", "test-dash", "test-dot", "test123"}
|
||||
sv, err := ProcessConfigArgs(args)
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
t.FailNow()
|
||||
}
|
||||
for _, v := range sv {
|
||||
if !contains(expectedKeys, v.Key) {
|
||||
t.Fail()
|
||||
t.Log("expectd key " + v.Key + " not found")
|
||||
}
|
||||
if !contains(expectedValue, v.Value) {
|
||||
t.Fail()
|
||||
t.Log("expectd Value " + v.Value + " not found")
|
||||
}
|
||||
if !contains(exppectedSvc, v.SvcName) {
|
||||
t.Fail()
|
||||
t.Log("expectd service " + v.SvcName + " not found")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func contains(arr []string, str string) bool {
|
||||
for _, a := range arr {
|
||||
if a == str {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
@@ -4,13 +4,94 @@ import (
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) RunAllPreflightChecks() error {
|
||||
//run all preflight checks
|
||||
fmt.Println("Running all preflight checks")
|
||||
fmt.Printf("\nRunning DNS check...\n")
|
||||
qp.CheckDns()
|
||||
fmt.Printf("\nRunning minimum kubernetes version check...\n")
|
||||
qp.CheckK8sVersion()
|
||||
func (qp *QliksensePreflight) RunAllPreflightChecks(namespace string, kubeConfigContents []byte, mongodbUrl string) {
|
||||
|
||||
checkCount := 0
|
||||
// Preflight minimum kuberenetes version check
|
||||
fmt.Printf("\nPreflight kubernetes minimum version check\n")
|
||||
fmt.Println("------------------------------------------")
|
||||
if err := qp.CheckK8sVersion(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Printf("Preflight kubernetes minimum version check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight deployment check
|
||||
fmt.Printf("\nPreflight deployment check\n")
|
||||
fmt.Println("--------------------------")
|
||||
if err := qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Printf("Preflight deployment check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight service check
|
||||
fmt.Printf("\nPreflight service check\n")
|
||||
fmt.Println("-----------------------")
|
||||
if err := qp.CheckService(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Printf("Preflight service check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight pod check
|
||||
fmt.Printf("\nPreflight pod check\n")
|
||||
fmt.Println("-----------------------")
|
||||
if err := qp.CheckPod(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Printf("Preflight pod check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight role check
|
||||
fmt.Printf("\nPreflight role check\n")
|
||||
fmt.Println("--------------------------")
|
||||
if err := qp.CheckCreateRole(namespace); err != nil {
|
||||
fmt.Printf("Preflight role check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight rolebinding check
|
||||
fmt.Printf("\nPreflight rolebinding check\n")
|
||||
fmt.Println("---------------------------------")
|
||||
if err := qp.CheckCreateRoleBinding(namespace); err != nil {
|
||||
fmt.Printf("Preflight rolebinding check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight serviceaccount check
|
||||
fmt.Printf("\nPreflight serviceaccount check\n")
|
||||
fmt.Println("------------------------------------")
|
||||
if err := qp.CheckCreateServiceAccount(namespace); err != nil {
|
||||
fmt.Printf("Preflight serviceaccount check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight mongo check
|
||||
fmt.Printf("\nPreflight mongo check\n")
|
||||
fmt.Println("---------------------")
|
||||
if err := qp.CheckMongo(kubeConfigContents, namespace, mongodbUrl); err != nil {
|
||||
fmt.Printf("Preflight mongo check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
// Preflight DNS check
|
||||
fmt.Printf("\nPreflight DNS check\n")
|
||||
fmt.Println("-------------------")
|
||||
if err := qp.CheckDns(namespace, kubeConfigContents); err != nil {
|
||||
fmt.Printf("Preflight DNS check: FAILED\n")
|
||||
} else {
|
||||
checkCount++
|
||||
}
|
||||
|
||||
if checkCount == 9 {
|
||||
fmt.Printf("\nAll preflight checks have PASSED\n")
|
||||
} else {
|
||||
fmt.Printf("\n1 or more preflight checks have FAILED\n")
|
||||
}
|
||||
fmt.Println("Completed running all preflight checks")
|
||||
return nil
|
||||
}
|
||||
|
||||
118
pkg/preflight/deployability.go
Normal file
118
pkg/preflight/deployability.go
Normal file
@@ -0,0 +1,118 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"k8s.io/client-go/kubernetes"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigContents []byte) error {
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Kube config error: %v\n", err)
|
||||
fmt.Print(err)
|
||||
return err
|
||||
}
|
||||
|
||||
// Deployment check
|
||||
fmt.Printf("Preflight deployment check: \n")
|
||||
err = qp.checkPfDeployment(clientset, namespace, "deployment-preflight-check")
|
||||
if err != nil {
|
||||
fmt.Println("Preflight Deployment check: FAILED")
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight deployment check")
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) CheckService(namespace string, kubeConfigContents []byte) error {
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
// Service check
|
||||
fmt.Printf("\nPreflight service check: \n")
|
||||
err = checkPfService(clientset, namespace)
|
||||
if err != nil {
|
||||
fmt.Println("Preflight Service check: FAILED")
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight service check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) CheckPod(namespace string, kubeConfigContents []byte) error {
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
||||
fmt.Print(err)
|
||||
return err
|
||||
}
|
||||
// Pod check
|
||||
fmt.Printf("\nPreflight pod check: \n")
|
||||
|
||||
err = qp.checkPfPod(clientset, namespace)
|
||||
if err != nil {
|
||||
fmt.Println("Preflight Pod check: FAILED")
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight pod check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) checkPfPod(clientset *kubernetes.Clientset, namespace string) error {
|
||||
// create a pod
|
||||
podName := "pod-pf-check"
|
||||
pod, err := createPreflightTestPod(clientset, namespace, podName, qp.GetPreflightConfigObj().GetImageName(nginx))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create pod %s - %v\n", podName, err)
|
||||
return err
|
||||
}
|
||||
defer deletePod(clientset, namespace, podName)
|
||||
|
||||
if err := waitForPod(clientset, namespace, pod); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Preflight pod creation check: PASSED")
|
||||
fmt.Println("Cleaning up resources...")
|
||||
return nil
|
||||
}
|
||||
|
||||
func checkPfService(clientset *kubernetes.Clientset, namespace string) error {
|
||||
// creating service
|
||||
serviceName := "svc-pf-check"
|
||||
pfService, err := createPreflightTestService(clientset, namespace, serviceName)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create service : %s\n", serviceName)
|
||||
return err
|
||||
}
|
||||
defer deleteService(clientset, namespace, serviceName)
|
||||
_, err = getService(clientset, namespace, pfService.GetName())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to retrieve service: %s\n", serviceName)
|
||||
return err
|
||||
}
|
||||
fmt.Println("Preflight service creation check: PASSED")
|
||||
fmt.Println("Cleaning up resources...")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) checkPfDeployment(clientset *kubernetes.Clientset, namespace, depName string) error {
|
||||
// check if we are able to create a deployment
|
||||
pfDeployment, err := createPreflightTestDeployment(clientset, namespace, depName, qp.GetPreflightConfigObj().GetImageName(nginx))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create deployment: %v\n", err)
|
||||
return err
|
||||
}
|
||||
defer deleteDeployment(clientset, namespace, depName)
|
||||
if err := waitForDeployment(clientset, namespace, pfDeployment); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Preflight Deployment check: PASSED")
|
||||
fmt.Println("Cleaning up resources...")
|
||||
return nil
|
||||
}
|
||||
@@ -1,130 +1,81 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"html/template"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
)
|
||||
|
||||
const dnsCheckYAML = `
|
||||
apiVersion: troubleshoot.replicated.com/v1beta1
|
||||
kind: Preflight
|
||||
metadata:
|
||||
name: cluster-preflight-checks
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
collectors:
|
||||
- run:
|
||||
collectorName: spin-up-pod
|
||||
args: ["-z", "-v", "-w 1", "{{ .serviceName }}", "80"]
|
||||
command: ["nc"]
|
||||
image: subfuzion/netcat:latest
|
||||
imagePullPolicy: IfNotPresent
|
||||
name: spin-up-pod-check-dns
|
||||
namespace: {{ .namespace }}
|
||||
timeout: 30s
|
||||
const (
|
||||
nginx = "nginx"
|
||||
netcat = "netcat"
|
||||
)
|
||||
|
||||
analyzers:
|
||||
- textAnalyze:
|
||||
checkName: DNS check
|
||||
collectorName: spin-up-pod-check-dns
|
||||
fileName: spin-up-pod.log
|
||||
regex: succeeded
|
||||
outcomes:
|
||||
- fail:
|
||||
message: DNS check failed
|
||||
- pass:
|
||||
message: DNS check passed
|
||||
`
|
||||
|
||||
func (qp *QliksensePreflight) CheckDns() error {
|
||||
// retrieve namespace
|
||||
namespace := api.GetKubectlNamespace()
|
||||
|
||||
api.LogDebugMessage("Namespace: %s\n", namespace)
|
||||
|
||||
tmpl, err := template.New("dnsCheckYAML").Parse(dnsCheckYAML)
|
||||
if err != nil {
|
||||
fmt.Printf("cannot parse template: %v", err)
|
||||
return err
|
||||
}
|
||||
tempYaml, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
fmt.Printf("cannot create file: %v", err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("Temp Yaml file: %s\n", tempYaml.Name())
|
||||
|
||||
appName := "qnginx001"
|
||||
const PreflightChecksDirName = "preflight_checks"
|
||||
b := bytes.Buffer{}
|
||||
err = tmpl.Execute(&b, map[string]string{
|
||||
"namespace": namespace,
|
||||
"serviceName": appName,
|
||||
})
|
||||
func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []byte) error {
|
||||
clientset, clientConfig, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
tempYaml.WriteString(b.String())
|
||||
|
||||
// creating Kubectl resources
|
||||
fmt.Println("Creating resources to run preflight checks")
|
||||
|
||||
// kubectl create deployment
|
||||
opr := fmt.Sprintf("create deployment %s --image=nginx", appName)
|
||||
err = initiateK8sOps(opr, namespace)
|
||||
// creating deployment
|
||||
depName := "dep-dns-preflight-check"
|
||||
dnsDeployment, err := createPreflightTestDeployment(clientset, namespace, depName, qp.GetPreflightConfigObj().GetImageName(nginx))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create deployment: %v\n", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
defer deleteDeployment(clientset, namespace, depName)
|
||||
|
||||
if err := waitForDeployment(clientset, namespace, dnsDeployment); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// creating service
|
||||
serviceName := "svc-dns-pf-check"
|
||||
dnsService, err := createPreflightTestService(clientset, namespace, serviceName)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create service : %s\n", serviceName)
|
||||
return err
|
||||
}
|
||||
defer deleteService(clientset, namespace, serviceName)
|
||||
|
||||
// create a pod
|
||||
podName := "pf-pod-1"
|
||||
dnsPod, err := createPreflightTestPod(clientset, namespace, podName, qp.GetPreflightConfigObj().GetImageName(netcat))
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create pod : %s\n", podName)
|
||||
return err
|
||||
}
|
||||
defer deletePod(clientset, namespace, podName)
|
||||
|
||||
if err := waitForPod(clientset, namespace, dnsPod); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(dnsPod.Spec.Containers) == 0 {
|
||||
err := fmt.Errorf("error: there are no containers in the pod")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("Exec-ing into the container...")
|
||||
stdout, stderr, err := executeRemoteCommand(clientset, clientConfig, dnsPod.Name, dnsPod.Spec.Containers[0].Name, namespace, []string{"nc", "-z", "-v", "-w 1", dnsService.Name, "80"})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to execute dns check in the cluster: %v", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// Deleting deployment..
|
||||
opr = fmt.Sprintf("delete deployment %s", appName)
|
||||
// we want to delete the k8s resource here, we dont care a lot about an error here
|
||||
_ = initiateK8sOps(opr, namespace)
|
||||
api.LogDebugMessage("delete deployment executed")
|
||||
}()
|
||||
|
||||
// create service
|
||||
opr = fmt.Sprintf("create service clusterip %s --tcp=80:80", appName)
|
||||
err = initiateK8sOps(opr, namespace)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
if strings.HasSuffix(stdout, "succeeded!") || strings.HasSuffix(stderr, "succeeded!") {
|
||||
fmt.Println("Preflight DNS check: PASSED")
|
||||
} else {
|
||||
fmt.Println("Preflight DNS check: FAILED")
|
||||
}
|
||||
|
||||
defer func() {
|
||||
// delete service
|
||||
opr = fmt.Sprintf("delete service %s", appName)
|
||||
// we want to delete the k8s resource here, we dont care a lot about an error here
|
||||
_ = initiateK8sOps(opr, namespace)
|
||||
api.LogDebugMessage("delete service executed")
|
||||
}()
|
||||
fmt.Println("Completed preflight DNS check")
|
||||
fmt.Println("Cleaning up resources...")
|
||||
|
||||
//kubectl -n $namespace wait --for=condition=ready pod -l app=$appName --timeout=120s
|
||||
opr = fmt.Sprintf("wait --for=condition=ready pod -l app=%s --timeout=120s", appName)
|
||||
err = initiateK8sOps(opr, namespace)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("kubectl wait executed")
|
||||
|
||||
// call preflight
|
||||
preflightCommand := filepath.Join(qp.Q.QliksenseHome, PreflightChecksDirName, preflightFileName)
|
||||
|
||||
err = invokePreflight(preflightCommand, tempYaml)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
fmt.Println("DNS check completed, cleaning up resources now")
|
||||
return nil
|
||||
}
|
||||
|
||||
85
pkg/preflight/mongo_check.go
Normal file
85
pkg/preflight/mongo_check.go
Normal file
@@ -0,0 +1,85 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
)
|
||||
|
||||
const (
|
||||
mongoImage = "mongo"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace, mongodbUrl string) error {
|
||||
fmt.Printf("Preflight mongodb check: \n")
|
||||
|
||||
if mongodbUrl == "" {
|
||||
// infer mongoDbUrl from currentCR
|
||||
fmt.Println("MongoDbUri is empty, infer from CR")
|
||||
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
||||
var currentCR *qapi.QliksenseCR
|
||||
|
||||
var err error
|
||||
qConfig.SetNamespace(namespace)
|
||||
currentCR, err = qConfig.GetCurrentCR()
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to retrieve current CR: %v\n", err)
|
||||
return err
|
||||
}
|
||||
decryptedCR, err := qConfig.GetDecryptedCr(currentCR)
|
||||
mongodbUrl = decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
||||
}
|
||||
|
||||
fmt.Printf("mongodbUrl: %s\n", mongodbUrl)
|
||||
if err := mongoConnCheck(kubeConfigContents, namespace, mongodbUrl); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight mongodb check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func mongoConnCheck(kubeConfigContents []byte, namespace, mongodbUrl string) error {
|
||||
clientset, clientConfig, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
// create a pod
|
||||
podName := "pf-mongo-pod"
|
||||
mongoPod, err := createPreflightTestPod(clientset, namespace, podName, mongoImage)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to create pod : %s\n", podName)
|
||||
fmt.Println("Preflight mongo check: FAILED")
|
||||
return err
|
||||
}
|
||||
defer deletePod(clientset, namespace, podName)
|
||||
|
||||
if err := waitForPod(clientset, namespace, mongoPod); err != nil {
|
||||
return err
|
||||
}
|
||||
if len(mongoPod.Spec.Containers) == 0 {
|
||||
err := fmt.Errorf("error: there are no containers in the pod")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("Exec-ing into the container...")
|
||||
stdout, stderr, err := executeRemoteCommand(clientset, clientConfig, mongoPod.Name, mongoPod.Spec.Containers[0].Name, namespace, []string{"mongo", mongodbUrl})
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to execute mongo check in the cluster: %v", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
api.LogDebugMessage("stdout:", stdout)
|
||||
api.LogDebugMessage("stderr:", stderr)
|
||||
stringToCheck := "Implicit session"
|
||||
if strings.Contains(stdout, stringToCheck) || strings.Contains(stderr, stringToCheck) {
|
||||
fmt.Println("Preflight mongo check: PASSED")
|
||||
} else {
|
||||
fmt.Println("Preflight mongo check: FAILED")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
109
pkg/preflight/preflight_apis.go
Normal file
109
pkg/preflight/preflight_apis.go
Normal file
@@ -0,0 +1,109 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
api "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
type PreflightConfig struct {
|
||||
metav1.TypeMeta `json:",inline" yaml:",inline"`
|
||||
metav1.ObjectMeta `json:"metadata,omitempty" yaml:"metadata,omitempty"`
|
||||
Spec *PreflightSpec `json:"spec" yaml:"spec"`
|
||||
QliksenseHomePath string `json:"-" yaml:"-"`
|
||||
}
|
||||
|
||||
type PreflightSpec struct {
|
||||
MinK8sVersion string `json:"minK8sVersion,omitempty" yaml:"minK8sVersion,omitempty"`
|
||||
Images map[string]string `json:"images,omitempty" yaml:"images,omitempty"`
|
||||
}
|
||||
|
||||
//NewPreflightConfigEmpty create empty PreflightConfig object
|
||||
func NewPreflightConfigEmpty(qHome string) *PreflightConfig {
|
||||
p := &PreflightConfig{
|
||||
QliksenseHomePath: qHome,
|
||||
TypeMeta: metav1.TypeMeta{
|
||||
APIVersion: "config.qlik.com/v1",
|
||||
Kind: "PreflightConfig",
|
||||
},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Name: "PreflightConfigMetadata",
|
||||
},
|
||||
Spec: &PreflightSpec{},
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
//NewPreflightConfig create empty PreflightConfig object if preflit/preflight-config.yaml not exist
|
||||
func NewPreflightConfig(qHome string) *PreflightConfig {
|
||||
p := NewPreflightConfigEmpty(qHome)
|
||||
conFile := p.GetConfigFilePath()
|
||||
if _, err := os.Lstat(conFile); err != nil {
|
||||
return p
|
||||
}
|
||||
p = &PreflightConfig{}
|
||||
if err := api.ReadFromFile(p, conFile); err != nil {
|
||||
return nil
|
||||
}
|
||||
return p
|
||||
}
|
||||
|
||||
//GetConfigFilePath return preflight-config.yaml file path
|
||||
func (p *PreflightConfig) GetConfigFilePath() string {
|
||||
return filepath.Join(p.QliksenseHomePath, "preflight", "preflight-config.yaml")
|
||||
}
|
||||
|
||||
//Write write PreflightConfig object into the ~/.qliksense/preflight/preflight-config.yaml file
|
||||
func (p *PreflightConfig) Write() error {
|
||||
pDir := filepath.Join(p.QliksenseHomePath, "preflight")
|
||||
if err := os.MkdirAll(pDir, os.ModePerm); err != nil {
|
||||
return err
|
||||
}
|
||||
return api.WriteToFile(p, p.GetConfigFilePath())
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) AddMinK8sV(version string) {
|
||||
if p.Spec == nil {
|
||||
p.Spec = &PreflightSpec{}
|
||||
}
|
||||
p.Spec.MinK8sVersion = version
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) AddImage(imageFor, imageName string) {
|
||||
if p.Spec.Images == nil {
|
||||
p.Spec.Images = make(map[string]string)
|
||||
}
|
||||
p.Spec.Images[imageFor] = imageName
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) GetImageName(imageFor string) string {
|
||||
if p.Spec.Images == nil {
|
||||
return ""
|
||||
}
|
||||
return p.Spec.Images[imageFor]
|
||||
}
|
||||
func (p *PreflightConfig) GetMinK8sVersion() string {
|
||||
return p.Spec.MinK8sVersion
|
||||
}
|
||||
func (p *PreflightConfig) IsExistOnDisk() bool {
|
||||
if _, err := os.Lstat(p.GetConfigFilePath()); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) GetImageMap() map[string]string {
|
||||
return p.Spec.Images
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) Initialize() error {
|
||||
if p.IsExistOnDisk() {
|
||||
return nil
|
||||
}
|
||||
p.AddMinK8sV("1.15")
|
||||
p.AddImage("nginx", "nginx")
|
||||
p.AddImage("netcat", "subfuzion/netcat")
|
||||
return p.Write()
|
||||
}
|
||||
41
pkg/preflight/preflight_apis_test.go
Normal file
41
pkg/preflight/preflight_apis_test.go
Normal file
@@ -0,0 +1,41 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"testing"
|
||||
|
||||
api "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
)
|
||||
|
||||
func Test_Initalize(t *testing.T) {
|
||||
tempDir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Log(err)
|
||||
t.FailNow()
|
||||
}
|
||||
pf := NewPreflightConfig(tempDir)
|
||||
if err := pf.Initialize(); err != nil {
|
||||
t.Log()
|
||||
t.FailNow()
|
||||
}
|
||||
p := &PreflightConfig{
|
||||
QliksenseHomePath: tempDir,
|
||||
}
|
||||
if err := api.ReadFromFile(p, pf.GetConfigFilePath()); err != nil {
|
||||
t.Log(err)
|
||||
t.FailNow()
|
||||
}
|
||||
if p.GetMinK8sVersion() != "1.15" {
|
||||
t.Log("expected k8 version: 1.15, but got " + p.GetMinK8sVersion())
|
||||
t.Fail()
|
||||
}
|
||||
p.AddImage("test", "testimage")
|
||||
if err := p.Write(); err != nil {
|
||||
t.Log(err)
|
||||
t.Fail()
|
||||
}
|
||||
p2 := NewPreflightConfig(tempDir)
|
||||
if p2.GetImageName("test") != "testimage" {
|
||||
t.Log("expected image name: testimage, got: " + p2.GetImageName("test"))
|
||||
}
|
||||
}
|
||||
@@ -3,136 +3,72 @@ package preflight
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"os/exec"
|
||||
"net/url"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
|
||||
"k8s.io/apimachinery/pkg/util/wait"
|
||||
|
||||
"k8s.io/client-go/util/retry"
|
||||
|
||||
"k8s.io/client-go/rest"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
"k8s.io/client-go/tools/remotecommand"
|
||||
"k8s.io/kubectl/pkg/scheme"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
"k8s.io/api/rbac/v1beta1"
|
||||
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
restclient "k8s.io/client-go/rest"
|
||||
|
||||
k8serrors "k8s.io/apimachinery/pkg/api/errors"
|
||||
)
|
||||
|
||||
var gracePeriod int64 = 0
|
||||
|
||||
type QliksensePreflight struct {
|
||||
Q *qliksense.Qliksense
|
||||
}
|
||||
|
||||
const (
|
||||
// preflight releases have the same version
|
||||
preflightRelease = "v0.9.28"
|
||||
preflightLinuxFile = "preflight_linux_amd64.tar.gz"
|
||||
preflightMacFile = "preflight_darwin_amd64.tar.gz"
|
||||
preflightWindowsFile = "preflight_windows_amd64.zip"
|
||||
PreflightChecksDirName = "preflight_checks"
|
||||
preflightFileName = "preflight"
|
||||
)
|
||||
|
||||
var preflightBaseURL = fmt.Sprintf("https://github.com/replicatedhq/troubleshoot/releases/download/%s/", preflightRelease)
|
||||
|
||||
func (qp *QliksensePreflight) DownloadPreflight() error {
|
||||
preflightExecutable := "preflight"
|
||||
if runtime.GOOS == "windows" {
|
||||
preflightExecutable += ".exe"
|
||||
}
|
||||
|
||||
preflightInstallDir := filepath.Join(qp.Q.QliksenseHome, PreflightChecksDirName)
|
||||
|
||||
exists, err := checkInstalled(preflightInstallDir, preflightExecutable)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("There has been an error when trying to determine if preflight installer exists")
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
if exists {
|
||||
// preflight exist, no need to download again.
|
||||
api.LogDebugMessage("Preflight already exists, proceeding to perform checks")
|
||||
return nil
|
||||
}
|
||||
|
||||
// Create the Preflight-check directory, download and install preflight
|
||||
if !api.DirExists(preflightInstallDir) {
|
||||
api.LogDebugMessage("%s does not exist, creating now\n", preflightInstallDir)
|
||||
if err := os.Mkdir(preflightInstallDir, os.ModePerm); err != nil {
|
||||
err = fmt.Errorf("Not able to create %s dir: %v", preflightInstallDir, err)
|
||||
log.Println(err)
|
||||
return nil
|
||||
}
|
||||
}
|
||||
api.LogDebugMessage("Preflight-checks install Dir: %s exists", preflightInstallDir)
|
||||
|
||||
preflightUrl, preflightFile, err := determinePlatformSpecificUrls(runtime.GOOS)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("There was an error when trying to determine platform specific paths")
|
||||
return err
|
||||
}
|
||||
|
||||
// Download Preflight
|
||||
err = downloadAndExplode(preflightUrl, preflightInstallDir, preflightFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Downloaded Preflight")
|
||||
|
||||
return nil
|
||||
func (qp *QliksensePreflight) GetPreflightConfigObj() *PreflightConfig {
|
||||
return NewPreflightConfig(qp.Q.QliksenseHome)
|
||||
}
|
||||
|
||||
func checkInstalled(preflightInstallDir, preflightExecutable string) (bool, error) {
|
||||
installerExists := true
|
||||
preflightInstaller := filepath.Join(preflightInstallDir, preflightExecutable)
|
||||
if api.DirExists(preflightInstallDir) {
|
||||
if !api.FileExists(preflightInstaller) {
|
||||
installerExists = false
|
||||
api.LogDebugMessage("Preflight install directory exists, but preflight installer does not exist")
|
||||
}
|
||||
} else {
|
||||
installerExists = false
|
||||
}
|
||||
return installerExists, nil
|
||||
}
|
||||
func InitPreflight() (string, []byte, error) {
|
||||
api.LogDebugMessage("Reading .kube/config file...")
|
||||
|
||||
func downloadAndExplode(url, installDir, file string) error {
|
||||
err := api.DownloadFile(url, installDir, file)
|
||||
homeDir, err := homedir.Dir()
|
||||
if err != nil {
|
||||
return err
|
||||
err = fmt.Errorf("Unable to deduce home dir\n")
|
||||
return "", nil, err
|
||||
}
|
||||
api.LogDebugMessage("Downloaded File: %s", file)
|
||||
api.LogDebugMessage("Kube config location: %s\n\n", filepath.Join(homeDir, ".kube", "config"))
|
||||
|
||||
fileToUntar := filepath.Join(installDir, file)
|
||||
api.LogDebugMessage("File to explode: %s", file)
|
||||
|
||||
err = api.ExplodePackage(installDir, fileToUntar)
|
||||
kubeConfig := filepath.Join(homeDir, ".kube", "config")
|
||||
kubeConfigContents, err := ioutil.ReadFile(kubeConfig)
|
||||
if err != nil {
|
||||
return err
|
||||
err = fmt.Errorf("Unable to deduce home dir\n")
|
||||
return "", nil, err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func determinePlatformSpecificUrls(platform string) (string, string, error) {
|
||||
|
||||
var preflightUrl, preflightFile string
|
||||
|
||||
if runtime.GOARCH != `amd64` {
|
||||
err := fmt.Errorf("%s architecture is not supported", runtime.GOARCH)
|
||||
return "", "", err
|
||||
// retrieve namespace
|
||||
namespace := api.GetKubectlNamespace()
|
||||
// if namespace comes back empty, we will run checks in the default namespace
|
||||
if namespace == "" {
|
||||
namespace = "default"
|
||||
}
|
||||
|
||||
switch platform {
|
||||
case "windows":
|
||||
preflightFile = preflightWindowsFile
|
||||
case "darwin":
|
||||
preflightFile = preflightMacFile
|
||||
case "linux":
|
||||
preflightFile = preflightLinuxFile
|
||||
default:
|
||||
err := fmt.Errorf("Unable to download the preflight executable for the underlying platform\n")
|
||||
return "", "", err
|
||||
}
|
||||
preflightUrl = fmt.Sprintf("%s%s", preflightBaseURL, preflightFile)
|
||||
|
||||
return preflightUrl, preflightFile, nil
|
||||
api.LogDebugMessage("Namespace: %s\n", namespace)
|
||||
return namespace, kubeConfigContents, nil
|
||||
}
|
||||
|
||||
func initiateK8sOps(opr, namespace string) error {
|
||||
@@ -145,46 +81,562 @@ func initiateK8sOps(opr, namespace string) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func invokePreflight(preflightCommand string, yamlFile *os.File) error {
|
||||
var arguments []string
|
||||
func int32Ptr(i int32) *int32 { return &i }
|
||||
|
||||
arguments = append(arguments, yamlFile.Name(), "--interactive=false")
|
||||
cmd := exec.Command(preflightCommand, arguments...)
|
||||
func retryOnError(mf func() error) error {
|
||||
return retry.OnError(wait.Backoff{
|
||||
Duration: 1 * time.Second,
|
||||
Factor: 1,
|
||||
Jitter: 0.1,
|
||||
Steps: 5,
|
||||
}, func(err error) bool {
|
||||
return k8serrors.IsConflict(err) || k8serrors.IsGone(err) || k8serrors.IsServerTimeout(err) ||
|
||||
k8serrors.IsServiceUnavailable(err) || k8serrors.IsTimeout(err) || k8serrors.IsTooManyRequests(err)
|
||||
}, mf)
|
||||
}
|
||||
|
||||
sterrBuffer := &bytes.Buffer{}
|
||||
cmd.Stdout = sterrBuffer
|
||||
cmd.Stderr = sterrBuffer
|
||||
if err := cmd.Run(); err != nil {
|
||||
return fmt.Errorf("Error when running preflight command: %v\n", err)
|
||||
func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clientset, *rest.Config, error) {
|
||||
var clientConfig *rest.Config
|
||||
var err error
|
||||
if len(kubeconfig) == 0 {
|
||||
clientConfig, err = rest.InClusterConfig()
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to load in-cluster kubeconfig")
|
||||
fmt.Println(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
} else {
|
||||
config, err := clientcmd.Load(kubeconfig)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to load kubeconfig")
|
||||
fmt.Println(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if contextName != "" {
|
||||
config.CurrentContext = contextName
|
||||
}
|
||||
clientConfig, err = clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to create client config from config")
|
||||
fmt.Println(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
ind := strings.Index(sterrBuffer.String(), "---")
|
||||
output := sterrBuffer.String()
|
||||
if ind > -1 {
|
||||
output = fmt.Sprintf("%s\n%s", output[:ind], output[ind:])
|
||||
clientset, err := kubernetes.NewForConfig(clientConfig)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to create clientset")
|
||||
fmt.Println(err)
|
||||
return nil, nil, err
|
||||
}
|
||||
fmt.Printf("%v\n", output)
|
||||
return clientset, clientConfig, nil
|
||||
}
|
||||
|
||||
// Maybe good to retain this part in case we need to process the output in future.
|
||||
// We are going to look for the first occurance of PASS or FAIL from the end
|
||||
// there are also some space-like deceiving characters which are being hard to get by
|
||||
func createPreflightTestDeployment(clientset *kubernetes.Clientset, namespace string, depName string, imageName string) (*appsv1.Deployment, error) {
|
||||
deploymentsClient := clientset.AppsV1().Deployments(namespace)
|
||||
deployment := &appsv1.Deployment{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: depName,
|
||||
},
|
||||
Spec: appsv1.DeploymentSpec{
|
||||
Replicas: int32Ptr(1),
|
||||
Selector: &v1.LabelSelector{
|
||||
MatchLabels: map[string]string{
|
||||
"app": "preflight-check",
|
||||
},
|
||||
},
|
||||
Template: apiv1.PodTemplateSpec{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Labels: map[string]string{
|
||||
"app": "preflight-check",
|
||||
"label": "preflight-check-label",
|
||||
},
|
||||
},
|
||||
Spec: apiv1.PodSpec{
|
||||
Containers: []apiv1.Container{
|
||||
{
|
||||
Name: "dep",
|
||||
Image: imageName,
|
||||
Ports: []apiv1.ContainerPort{
|
||||
{
|
||||
Name: "http",
|
||||
Protocol: apiv1.ProtocolTCP,
|
||||
ContainerPort: 80,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
//outputArr := strings.Fields(strings.TrimSpace(output))
|
||||
//trackSuccess := false
|
||||
//trackPrg := false
|
||||
// Create Deployment
|
||||
var result *appsv1.Deployment
|
||||
if err := retryOnError(func() (err error) {
|
||||
result, err = deploymentsClient.Create(deployment)
|
||||
return err
|
||||
}); err != nil {
|
||||
err = errors.Wrapf(err, "error: unable to create deployments in the %s namespace", namespace)
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Created deployment %q\n", result.GetObjectMeta().GetName())
|
||||
|
||||
//for i := len(outputArr) - 1; i >= 0; i-- {
|
||||
// if strings.TrimSpace(outputArr[i]) != "" {
|
||||
// if outputArr[i] == "PASS" {
|
||||
// trackSuccess = true
|
||||
// trackPrg = true
|
||||
// } else if outputArr[i] == "FAIL" {
|
||||
// trackPrg = true
|
||||
// }
|
||||
// }
|
||||
// if trackPrg {
|
||||
// break
|
||||
// }
|
||||
//}
|
||||
return deployment, nil
|
||||
}
|
||||
|
||||
func getDeployment(clientset *kubernetes.Clientset, namespace, depName string) (*appsv1.Deployment, error) {
|
||||
deploymentsClient := clientset.AppsV1().Deployments(namespace)
|
||||
var deployment *appsv1.Deployment
|
||||
if err := retryOnError(func() (err error) {
|
||||
deployment, err = deploymentsClient.Get(depName, v1.GetOptions{})
|
||||
return err
|
||||
}); err != nil {
|
||||
err = errors.Wrapf(err, "error: unable to get deployments in the %s namespace", namespace)
|
||||
api.LogDebugMessage("%v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
return deployment, nil
|
||||
}
|
||||
|
||||
func deleteDeployment(clientset *kubernetes.Clientset, namespace, name string) error {
|
||||
deploymentsClient := clientset.AppsV1().Deployments(namespace)
|
||||
// Create Deployment
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
GracePeriodSeconds: &gracePeriod,
|
||||
}
|
||||
|
||||
if err := retryOnError(func() (err error) {
|
||||
return deploymentsClient.Delete(name, &deleteOptions)
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
if err := waitForDeploymentToDelete(clientset, namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted deployment: %s\n", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPreflightTestService(clientset *kubernetes.Clientset, namespace string, svcName string) (*apiv1.Service, error) {
|
||||
iptr := int32Ptr(80)
|
||||
servicesClient := clientset.CoreV1().Services(namespace)
|
||||
service := &apiv1.Service{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: svcName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app": "preflight-check",
|
||||
},
|
||||
},
|
||||
Spec: apiv1.ServiceSpec{
|
||||
Ports: []apiv1.ServicePort{
|
||||
{Name: "port1",
|
||||
Port: *iptr,
|
||||
},
|
||||
},
|
||||
Selector: map[string]string{
|
||||
"app": "preflight-check",
|
||||
},
|
||||
ClusterIP: "",
|
||||
},
|
||||
}
|
||||
var result *apiv1.Service
|
||||
if err := retryOnError(func() (err error) {
|
||||
result, err = servicesClient.Create(service)
|
||||
return err
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Created service %q\n", result.GetObjectMeta().GetName())
|
||||
|
||||
return service, nil
|
||||
}
|
||||
|
||||
func getService(clientset *kubernetes.Clientset, namespace, svcName string) (*apiv1.Service, error) {
|
||||
servicesClient := clientset.CoreV1().Services(namespace)
|
||||
var svc *apiv1.Service
|
||||
if err := retryOnError(func() (err error) {
|
||||
svc, err = servicesClient.Get(svcName, v1.GetOptions{})
|
||||
return err
|
||||
}); err != nil {
|
||||
err = errors.Wrapf(err, "unable to get services in the %s namespace", namespace)
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return svc, nil
|
||||
}
|
||||
|
||||
func deleteService(clientset *kubernetes.Clientset, namespace, name string) error {
|
||||
servicesClient := clientset.CoreV1().Services(namespace)
|
||||
// Create Deployment
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
}
|
||||
if err := retryOnError(func() (err error) {
|
||||
return servicesClient.Delete(name, &deleteOptions)
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted service: %s\n", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func deletePod(clientset *kubernetes.Clientset, namespace, name string) error {
|
||||
|
||||
podsClient := clientset.CoreV1().Pods(namespace)
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
GracePeriodSeconds: &gracePeriod,
|
||||
}
|
||||
if err := retryOnError(func() (err error) {
|
||||
return podsClient.Delete(name, &deleteOptions)
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
if err := waitForPodToDelete(clientset, namespace, name); err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Printf("Deleted pod: %s\n", name)
|
||||
return nil
|
||||
}
|
||||
|
||||
func createPreflightTestPod(clientset *kubernetes.Clientset, namespace string, podName string, imageName string) (*apiv1.Pod, error) {
|
||||
// build the pod definition we want to deploy
|
||||
pod := &apiv1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: podName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app": "preflight",
|
||||
},
|
||||
},
|
||||
Spec: apiv1.PodSpec{
|
||||
Containers: []apiv1.Container{
|
||||
{
|
||||
Name: "cnt",
|
||||
Image: imageName,
|
||||
ImagePullPolicy: apiv1.PullIfNotPresent,
|
||||
Command: []string{
|
||||
"sleep",
|
||||
"3600",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// now create the pod in kubernetes cluster using the clientset
|
||||
if err := retryOnError(func() (err error) {
|
||||
pod, err = clientset.CoreV1().Pods(namespace).Create(pod)
|
||||
return err
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Created pod: %s\n", pod.Name)
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
func getPod(clientset *kubernetes.Clientset, namespace, podName string) (*apiv1.Pod, error) {
|
||||
api.LogDebugMessage("Fetching pod: %s\n", podName)
|
||||
var pod *apiv1.Pod
|
||||
if err := retryOnError(func() (err error) {
|
||||
pod, err = clientset.CoreV1().Pods(namespace).Get(podName, v1.GetOptions{})
|
||||
return err
|
||||
}); err != nil {
|
||||
api.LogDebugMessage("%v\n", err)
|
||||
return nil, err
|
||||
}
|
||||
return pod, nil
|
||||
}
|
||||
|
||||
func execute(method string, url *url.URL, config *restclient.Config, stdin io.Reader, stdout, stderr io.Writer, tty bool) error {
|
||||
exec, err := remotecommand.NewSPDYExecutor(config, method, url)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return exec.Stream(remotecommand.StreamOptions{
|
||||
Stdin: stdin,
|
||||
Stdout: stdout,
|
||||
Stderr: stderr,
|
||||
Tty: tty,
|
||||
})
|
||||
}
|
||||
|
||||
func executeRemoteCommand(clientset *kubernetes.Clientset, config *rest.Config, podName, containerName, namespace string, command []string) (string, string, error) {
|
||||
tty := false
|
||||
req := clientset.CoreV1().RESTClient().Post().
|
||||
Resource("pods").
|
||||
Name(podName).
|
||||
Namespace(namespace).
|
||||
SubResource("exec").
|
||||
Param("container", containerName)
|
||||
req.VersionedParams(&apiv1.PodExecOptions{
|
||||
Container: containerName,
|
||||
Command: command,
|
||||
Stdin: false,
|
||||
Stdout: true,
|
||||
Stderr: true,
|
||||
TTY: tty,
|
||||
}, scheme.ParameterCodec)
|
||||
|
||||
var stdout, stderr bytes.Buffer
|
||||
err := execute("POST", req.URL(), config, nil, &stdout, &stderr, tty)
|
||||
return strings.TrimSpace(stdout.String()), strings.TrimSpace(stderr.String()), err
|
||||
}
|
||||
|
||||
func waitForDeployment(clientset *kubernetes.Clientset, namespace string, pfDeployment *appsv1.Deployment) error {
|
||||
timeout := time.NewTicker(2 * time.Minute)
|
||||
defer timeout.Stop()
|
||||
var d *appsv1.Deployment
|
||||
var err error
|
||||
WAIT:
|
||||
for {
|
||||
d, err = getDeployment(clientset, namespace, pfDeployment.GetName())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to retrieve deployment: %s\n", pfDeployment.GetName())
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case <-timeout.C:
|
||||
break WAIT
|
||||
default:
|
||||
if int(d.Status.ReadyReplicas) > 0 {
|
||||
break WAIT
|
||||
}
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
if int(d.Status.ReadyReplicas) == 0 {
|
||||
err = fmt.Errorf("error: deployment took longer than expected to spin up pods")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Pod) error {
|
||||
var err error
|
||||
if len(pod.Spec.Containers) > 0 {
|
||||
timeout := time.NewTicker(2 * time.Minute)
|
||||
defer timeout.Stop()
|
||||
podName := pod.Name
|
||||
OUT:
|
||||
for {
|
||||
pod, err = getPod(clientset, namespace, podName)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("error: unable to retrieve %s pod by name", podName)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
select {
|
||||
case <-timeout.C:
|
||||
break OUT
|
||||
default:
|
||||
if len(pod.Status.ContainerStatuses) > 0 && pod.Status.ContainerStatuses[0].Ready {
|
||||
break OUT
|
||||
}
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
if len(pod.Status.ContainerStatuses) == 0 || !pod.Status.ContainerStatuses[0].Ready {
|
||||
err = fmt.Errorf("error: container is taking much longer than expected")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
err = fmt.Errorf("error: there are no containers in the pod")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
func waitForPodToDelete(clientset *kubernetes.Clientset, namespace, podName string) error {
|
||||
var err error
|
||||
timeout := time.NewTicker(2 * time.Minute)
|
||||
defer timeout.Stop()
|
||||
OUT:
|
||||
for {
|
||||
_, err = getPod(clientset, namespace, podName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-timeout.C:
|
||||
break OUT
|
||||
default:
|
||||
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
err = fmt.Errorf("error: delete pod is taking unusually long")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
func waitForDeploymentToDelete(clientset *kubernetes.Clientset, namespace, deploymentName string) error {
|
||||
var err error
|
||||
timeout := time.NewTicker(2 * time.Minute)
|
||||
defer timeout.Stop()
|
||||
OUT:
|
||||
for {
|
||||
_, err = getDeployment(clientset, namespace, deploymentName)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
select {
|
||||
case <-timeout.C:
|
||||
break OUT
|
||||
default:
|
||||
|
||||
}
|
||||
time.Sleep(5 * time.Second)
|
||||
}
|
||||
err = fmt.Errorf("error: delete deployment is taking unusually long")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
func createPfRole(clientset *kubernetes.Clientset, namespace, roleName string) (*v1beta1.Role, error) {
|
||||
// build the role defination we want to create
|
||||
var role *v1beta1.Role
|
||||
roleSpec := &v1beta1.Role{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: roleName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app": "preflight",
|
||||
},
|
||||
},
|
||||
Rules: []v1beta1.PolicyRule{},
|
||||
}
|
||||
|
||||
// now create the role in kubernetes cluster using the clientset
|
||||
if err := retryOnError(func() (err error) {
|
||||
role, err = clientset.RbacV1beta1().Roles(namespace).Create(roleSpec)
|
||||
return err
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Printf("Created role: %s\n", role.Name)
|
||||
|
||||
return role, nil
|
||||
}
|
||||
|
||||
func deleteRole(clientset *kubernetes.Clientset, namespace string, role *v1beta1.Role) {
|
||||
rolesClient := clientset.RbacV1beta1().Roles(namespace)
|
||||
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
}
|
||||
err := rolesClient.Delete(role.GetName(), &deleteOptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Deleted role: %s\n\n", role.Name)
|
||||
}
|
||||
|
||||
func createPfRoleBinding(clientset *kubernetes.Clientset, namespace, roleBindingName string) (*v1beta1.RoleBinding, error) {
|
||||
var roleBinding *v1beta1.RoleBinding
|
||||
// build the rolebinding defination we want to create
|
||||
roleBindingSpec := &v1beta1.RoleBinding{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: roleBindingName,
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app": "demo",
|
||||
},
|
||||
},
|
||||
Subjects: []v1beta1.Subject{
|
||||
{
|
||||
Kind: "ServiceAccount",
|
||||
APIGroup: "",
|
||||
Name: "preflight-check-subject",
|
||||
Namespace: namespace,
|
||||
},
|
||||
},
|
||||
RoleRef: v1beta1.RoleRef{
|
||||
APIGroup: "",
|
||||
Kind: "Role",
|
||||
Name: "preflight-check-roleref",
|
||||
},
|
||||
}
|
||||
|
||||
// now create the roleBinding in kubernetes cluster using the clientset
|
||||
if err := retryOnError(func() (err error) {
|
||||
roleBinding, err = clientset.RbacV1beta1().RoleBindings(namespace).Create(roleBindingSpec)
|
||||
return err
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Created RoleBinding: %s\n", roleBindingSpec.Name)
|
||||
return roleBinding, nil
|
||||
}
|
||||
|
||||
func deleteRoleBinding(clientset *kubernetes.Clientset, namespace string, roleBinding *v1beta1.RoleBinding) {
|
||||
roleBindingClient := clientset.RbacV1beta1().RoleBindings(namespace)
|
||||
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
}
|
||||
err := roleBindingClient.Delete(roleBinding.GetName(), &deleteOptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Deleted RoleBinding: %s\n\n", roleBinding.Name)
|
||||
}
|
||||
|
||||
func createPfServiceAccount(clientset *kubernetes.Clientset, namespace, serviceAccountName string) (*apiv1.ServiceAccount, error) {
|
||||
var serviceAccount *apiv1.ServiceAccount
|
||||
// build the serviceAccount defination we want to create
|
||||
serviceAccountSpec := &apiv1.ServiceAccount{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
Name: "preflight-check-test-serviceaccount",
|
||||
Namespace: namespace,
|
||||
Labels: map[string]string{
|
||||
"app": "demo",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
// now create the serviceAccount in kubernetes cluster using the clientset
|
||||
if err := retryOnError(func() (err error) {
|
||||
serviceAccount, err = clientset.CoreV1().ServiceAccounts(namespace).Create(serviceAccountSpec)
|
||||
return err
|
||||
}); err != nil {
|
||||
fmt.Println(err)
|
||||
return nil, err
|
||||
}
|
||||
fmt.Printf("Created Service Account: %s\n", serviceAccountSpec.Name)
|
||||
return serviceAccount, nil
|
||||
}
|
||||
|
||||
func deleteServiceAccount(clientset *kubernetes.Clientset, namespace string, serviceAccount *apiv1.ServiceAccount) {
|
||||
serviceAccountClient := clientset.CoreV1().ServiceAccounts(namespace)
|
||||
|
||||
deletePolicy := v1.DeletePropagationForeground
|
||||
deleteOptions := v1.DeleteOptions{
|
||||
PropagationPolicy: &deletePolicy,
|
||||
}
|
||||
err := serviceAccountClient.Delete(serviceAccount.GetName(), &deleteOptions)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
fmt.Printf("Deleted ServiceAccount: %s\n\n", serviceAccount.Name)
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ func Test_initiateK8sOps(t *testing.T) {
|
||||
name: "valid case",
|
||||
args: args{
|
||||
opr: fmt.Sprintf("version"),
|
||||
namespace: "ash-ns",
|
||||
namespace: "test-ns",
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -28,7 +28,7 @@ func Test_initiateK8sOps(t *testing.T) {
|
||||
name: "invalid case",
|
||||
args: args{
|
||||
opr: fmt.Sprintf("versions"),
|
||||
namespace: "ash-ns",
|
||||
namespace: "test-ns",
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
@@ -41,50 +41,3 @@ func Test_initiateK8sOps(t *testing.T) {
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func Test_determinePlatformSpecificUrls(t *testing.T) {
|
||||
type args struct {
|
||||
platform string
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want string
|
||||
want1 string
|
||||
wantErr bool
|
||||
}{
|
||||
{
|
||||
name: "valid platform",
|
||||
args: args{
|
||||
platform: "windows",
|
||||
},
|
||||
want: fmt.Sprintf("%s%s", preflightBaseURL, preflightWindowsFile),
|
||||
want1: preflightWindowsFile,
|
||||
wantErr: false,
|
||||
},
|
||||
{
|
||||
name: "invalid platform",
|
||||
args: args{
|
||||
platform: "unix",
|
||||
},
|
||||
want: "",
|
||||
want1: "",
|
||||
wantErr: true,
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
got, got1, err := determinePlatformSpecificUrls(tt.args.platform)
|
||||
if (err != nil) != tt.wantErr {
|
||||
t.Errorf("determinePlatformSpecificUrls() error = %v, wantErr %v", err, tt.wantErr)
|
||||
return
|
||||
}
|
||||
if got != tt.want {
|
||||
t.Errorf("determinePlatformSpecificUrls() got = %v, want %v", got, tt.want)
|
||||
}
|
||||
if got1 != tt.want1 {
|
||||
t.Errorf("determinePlatformSpecificUrls() got1 = %v, want %v", got1, tt.want1)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
148
pkg/preflight/role_check.go
Normal file
148
pkg/preflight/role_check.go
Normal file
@@ -0,0 +1,148 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/qlik-oss/k-apis/pkg/cr"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) CheckCreateRole(namespace string) error {
|
||||
// create a Role
|
||||
fmt.Printf("Preflight role check: \n")
|
||||
err := qp.checkCreateEntity(namespace, "Role")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight role check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) CheckCreateRoleBinding(namespace string) error {
|
||||
// create a RoleBinding
|
||||
fmt.Printf("Preflight rolebinding check: \n")
|
||||
err := qp.checkCreateEntity(namespace, "RoleBinding")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight rolebinding check")
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) CheckCreateServiceAccount(namespace string) error {
|
||||
// create a service account
|
||||
fmt.Printf("Preflight serviceaccount check: \n")
|
||||
err := qp.checkCreateEntity(namespace, "ServiceAccount")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
fmt.Println("Completed preflight serviceaccount check")
|
||||
return nil
|
||||
}
|
||||
func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string) error {
|
||||
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
||||
var currentCR *qapi.QliksenseCR
|
||||
mfroot := ""
|
||||
kusDir := ""
|
||||
var err error
|
||||
currentCR, err = qConfig.GetCurrentCR()
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to retrieve current CR: %v\n", err)
|
||||
return err
|
||||
}
|
||||
if currentCR.IsRepoExist() {
|
||||
mfroot = currentCR.Spec.GetManifestsRoot()
|
||||
} else if tempDownloadedDir, err := qliksense.DownloadFromGitRepoToTmpDir(qliksense.QLIK_GIT_REPO, "master"); err != nil {
|
||||
fmt.Printf("Unable to Download from git repo to tmp dir: %v\n", err)
|
||||
return err
|
||||
} else {
|
||||
mfroot = tempDownloadedDir
|
||||
}
|
||||
|
||||
if currentCR.Spec.Profile == "" {
|
||||
kusDir = filepath.Join(mfroot, "manifests", "docker-desktop")
|
||||
} else {
|
||||
kusDir = filepath.Join(mfroot, "manifests", currentCR.Spec.Profile)
|
||||
}
|
||||
|
||||
currentCR.SetName("random")
|
||||
currentCR.Spec.RotateKeys = "None"
|
||||
currentCR.Spec.ManifestsRoot = mfroot
|
||||
userHomeDir, err := homedir.Dir()
|
||||
if err != nil {
|
||||
fmt.Printf(`error fetching user's home directory: %v\n`, err)
|
||||
return err
|
||||
}
|
||||
|
||||
cr.GeneratePatches(¤tCR.KApiCr, path.Join(userHomeDir, ".kube", "config"))
|
||||
|
||||
resultYamlString, err := qliksense.ExecuteKustomizeBuild(kusDir)
|
||||
if err != nil {
|
||||
fmt.Printf("Unable to retrieve manifests from executing kustomize: %v\n", err)
|
||||
return err
|
||||
}
|
||||
|
||||
sa := qliksense.GetYamlsFromMultiDoc(string(resultYamlString), entityToTest)
|
||||
if sa != "" {
|
||||
// sa = strings.ReplaceAll(sa, "namespace: default\n", fmt.Sprintf("namespace: %s\n", namespace))
|
||||
} else {
|
||||
err := fmt.Errorf("Unable to retrieve yamls to apply on cluster")
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
namespace = "" // namespace is handled when generating the manifests
|
||||
|
||||
defer func() {
|
||||
fmt.Println("Cleaning up resources")
|
||||
api.KubectlDelete(sa, namespace)
|
||||
if err != nil {
|
||||
fmt.Println("Preflight cleanup failed!")
|
||||
}
|
||||
}()
|
||||
|
||||
err = api.KubectlApply(sa, namespace)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("Failed to create entity on the cluster: %v", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("Preflight %s check: PASSED\n", entityToTest)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) CheckCreateRB(namespace string, kubeConfigContents []byte) error {
|
||||
|
||||
// create a role
|
||||
fmt.Printf("Preflight createRole check: \n")
|
||||
err := qp.checkCreateEntity(namespace, "Role")
|
||||
if err != nil {
|
||||
fmt.Println("Preflight role check: FAILED")
|
||||
}
|
||||
fmt.Printf("Completed preflight role check\n\n")
|
||||
|
||||
// create a roleBinding
|
||||
fmt.Printf("Preflight rolebinding check: \n")
|
||||
err = qp.checkCreateEntity(namespace, "RoleBinding")
|
||||
if err != nil {
|
||||
fmt.Println("Preflight rolebinding check: FAILED")
|
||||
}
|
||||
fmt.Printf("Completed preflight rolebinding check\n\n")
|
||||
|
||||
// create a service account
|
||||
fmt.Printf("Preflight serviceaccount check: \n")
|
||||
err = qp.checkCreateEntity(namespace, "ServiceAccount")
|
||||
if err != nil {
|
||||
fmt.Println("Preflight serviceaccount check: FAILED")
|
||||
}
|
||||
fmt.Printf("Completed preflight serviceaccount check\n\n")
|
||||
|
||||
fmt.Println("Preflight RB check: PASSED")
|
||||
fmt.Println("Completed preflight CreateRB check")
|
||||
return nil
|
||||
}
|
||||
@@ -1,84 +1,56 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"path/filepath"
|
||||
"text/template"
|
||||
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"k8s.io/apimachinery/pkg/version"
|
||||
)
|
||||
|
||||
const minK8sVersion = "1.11.0"
|
||||
const checkVersionYAML = `
|
||||
apiVersion: troubleshoot.replicated.com/v1beta1
|
||||
kind: Preflight
|
||||
metadata:
|
||||
name: cluster-preflight-checks
|
||||
namespace: {{ .namespace }}
|
||||
spec:
|
||||
analyzers:
|
||||
- clusterVersion:
|
||||
outcomes:
|
||||
- fail:
|
||||
when: "< {{ .minK8sVersion }}"
|
||||
message: The application requires at least Kubernetes {{ .minK8sVersion }} or later.
|
||||
uri: https://www.kubernetes.io
|
||||
- pass:
|
||||
when: ">= {{ .minK8sVersion }}"
|
||||
message: Good to go.
|
||||
`
|
||||
func (qp *QliksensePreflight) CheckK8sVersion(namespace string, kubeConfigContents []byte) error {
|
||||
|
||||
func (qp *QliksensePreflight) CheckK8sVersion() error {
|
||||
// retrieve namespace
|
||||
namespace := api.GetKubectlNamespace()
|
||||
var currentVersion *semver.Version
|
||||
|
||||
api.LogDebugMessage("Namespace: %s\n", namespace)
|
||||
|
||||
tmpl, err := template.New("checkVersionYAML").Parse(checkVersionYAML)
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
fmt.Printf("cannot parse template: %v", err)
|
||||
err = fmt.Errorf("Unable to create clientset: %v\n", err)
|
||||
return err
|
||||
}
|
||||
tempYaml, err := ioutil.TempFile("", "")
|
||||
if err != nil {
|
||||
fmt.Printf("cannot create file: %v", err)
|
||||
var serverVersion *version.Info
|
||||
if err := retryOnError(func() (err error) {
|
||||
serverVersion, err = clientset.ServerVersion()
|
||||
return err
|
||||
}); err != nil {
|
||||
err = fmt.Errorf("Unable to get server version: %v\n", err)
|
||||
//fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("Temp Yaml file: %s\n", tempYaml.Name())
|
||||
fmt.Printf("Kubernetes API Server version: %s\n", serverVersion.String())
|
||||
|
||||
b := bytes.Buffer{}
|
||||
err = tmpl.Execute(&b, map[string]string{
|
||||
"namespace": namespace,
|
||||
"minK8sVersion": minK8sVersion,
|
||||
})
|
||||
// Compare K8s version on the cluster with minimum supported k8s version
|
||||
currentVersion, err = semver.NewVersion(serverVersion.String())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unable to convert server version into semver version: %v\n", err)
|
||||
//fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
//fmt.Printf("Current K8s Version: %v\n", currentVersion)
|
||||
|
||||
minK8sVersionSemver, err := semver.NewVersion(qp.GetPreflightConfigObj().GetMinK8sVersion())
|
||||
if err != nil {
|
||||
err = fmt.Errorf("Unable to convert minimum Kubernetes version into semver version:%v\n", err)
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
tempYaml.WriteString(b.String())
|
||||
//api.LogDebugMessage("Temp yaml contents: %s", b.String())
|
||||
fmt.Printf("Minimum Kubernetes version supported: %s\n", minK8sVersion)
|
||||
|
||||
// current kubectl version
|
||||
opr := fmt.Sprintf("version")
|
||||
err = initiateK8sOps(opr, namespace)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
if currentVersion.GreaterThan(minK8sVersionSemver) {
|
||||
//fmt.Printf("\n\nCurrent %s Component version: %s is less than minimum required version:%s\n", component, currentComponentVersion, componentVersionFromDependenciesYaml)
|
||||
fmt.Printf("Current %s is greater than minimum required version:%s\n", currentVersion, minK8sVersionSemver)
|
||||
fmt.Println("Preflight minimum kubernetes version check: PASSED")
|
||||
} else {
|
||||
fmt.Printf("Current %s is less than minimum required version:%s\n", currentVersion, minK8sVersionSemver)
|
||||
fmt.Println("Preflight minimum kubernetes version check: FAILED")
|
||||
}
|
||||
|
||||
// call preflight
|
||||
preflightCommand := filepath.Join(qp.Q.QliksenseHome, PreflightChecksDirName, preflightFileName)
|
||||
|
||||
err = invokePreflight(preflightCommand, tempYaml)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Println("Minimum kubernetes version check completed")
|
||||
fmt.Printf("Completed Preflight kubernetes minimum version check\n")
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -94,7 +94,7 @@ func (q *Qliksense) getConfigDirectory(gitUrl, gitRef, profileEntered string) (d
|
||||
}
|
||||
|
||||
if gitRef != "" {
|
||||
if dir, err = downloadFromGitRepoToTmpDir(gitUrl, gitRef); err != nil {
|
||||
if dir, err = DownloadFromGitRepoToTmpDir(gitUrl, gitRef); err != nil {
|
||||
return "", false, "", err
|
||||
} else {
|
||||
return dir, true, profile, nil
|
||||
@@ -120,14 +120,15 @@ func (q *Qliksense) getConfigDirectory(gitUrl, gitRef, profileEntered string) (d
|
||||
return dir, false, profile, nil
|
||||
}
|
||||
|
||||
if dir, err = downloadFromGitRepoToTmpDir(gitUrl, "master"); err != nil {
|
||||
if dir, err = DownloadFromGitRepoToTmpDir(gitUrl, "master"); err != nil {
|
||||
return "", false, "", err
|
||||
} else {
|
||||
return dir, true, profile, nil
|
||||
}
|
||||
}
|
||||
|
||||
func downloadFromGitRepoToTmpDir(gitUrl, gitRef string) (string, error) {
|
||||
//DownloadFromGitRepoToTmpDir download git repo to a temporary directory
|
||||
func DownloadFromGitRepoToTmpDir(gitUrl, gitRef string) (string, error) {
|
||||
if tmpDir, err := ioutil.TempDir("", ""); err != nil {
|
||||
return "", err
|
||||
} else {
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
@@ -88,7 +89,7 @@ func (q *Qliksense) applyConfigToK8s(qcr *qapi.QliksenseCR) error {
|
||||
cr.GeneratePatches(&qcr.KApiCr, path.Join(userHomeDir, ".kube", "config"))
|
||||
// apply generated manifests
|
||||
profilePath := filepath.Join(qcr.Spec.GetManifestsRoot(), qcr.Spec.GetProfileDir())
|
||||
mByte, err := executeKustomizeBuild(profilePath)
|
||||
mByte, err := ExecuteKustomizeBuild(profilePath)
|
||||
if err != nil {
|
||||
fmt.Println("cannot generate manifests for "+profilePath, err)
|
||||
return err
|
||||
@@ -163,3 +164,54 @@ func (q *Qliksense) getCurrentCrDependentResourceAsString() (string, error) {
|
||||
crString.WriteString("\n---\n")
|
||||
return crString.String(), nil
|
||||
}
|
||||
|
||||
func (q *Qliksense) EditCR(contextName string) error {
|
||||
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||
if contextName == "" {
|
||||
cr, err := qConfig.GetCurrentCR()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
contextName = cr.GetName()
|
||||
}
|
||||
crFilePath := qConfig.GetCRFilePath(contextName)
|
||||
tempFile, err := ioutil.TempFile("", "*.yaml")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
crContent, err := ioutil.ReadFile(crFilePath)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := ioutil.WriteFile(tempFile.Name(), crContent, os.ModePerm); err != nil {
|
||||
return nil
|
||||
}
|
||||
cmd := exec.Command(getKubeEditorTool(), tempFile.Name())
|
||||
cmd.Stdin = os.Stdin
|
||||
cmd.Stdout = os.Stdout
|
||||
err = cmd.Run()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
newCr, err := qapi.GetCRObject(tempFile.Name())
|
||||
if err != nil {
|
||||
return errors.New("cannot save the cr. Someting wrong in the file format. It is not saved\n" + err.Error())
|
||||
}
|
||||
oldCr, err := qapi.GetCRObject(crFilePath)
|
||||
|
||||
if oldCr.GetName() != newCr.GetName() {
|
||||
return errors.New("cr name cannot be chagned")
|
||||
}
|
||||
if newCr.Validate() {
|
||||
return qConfig.WriteCR(newCr)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func getKubeEditorTool() string {
|
||||
editor := os.Getenv("KUBE_EDITOR")
|
||||
if editor == "" {
|
||||
editor = "vim"
|
||||
}
|
||||
return editor
|
||||
}
|
||||
|
||||
@@ -19,12 +19,24 @@ func (q *Qliksense) ViewCrds(opts *CrdCommandOptions) error {
|
||||
fmt.Println("cannot get the current-context cr", err)
|
||||
return err
|
||||
}
|
||||
if engineCRD, err := getQliksenseInitCrd(qcr); err != nil {
|
||||
engineCRD, err := getQliksenseInitCrd(qcr)
|
||||
if err != nil {
|
||||
return err
|
||||
} else if opts.All {
|
||||
fmt.Printf("%s\n%s", q.GetOperatorCRDString(), engineCRD)
|
||||
} else {
|
||||
fmt.Printf("%s", engineCRD)
|
||||
}
|
||||
customCrd, err := getCustomCrd(qcr)
|
||||
if err != nil {
|
||||
return nil
|
||||
}
|
||||
|
||||
fmt.Println(engineCRD)
|
||||
if customCrd != "" {
|
||||
fmt.Println("---")
|
||||
fmt.Println(customCrd)
|
||||
}
|
||||
|
||||
if opts.All {
|
||||
fmt.Println("---")
|
||||
fmt.Printf("%s", q.GetOperatorCRDString())
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@@ -43,6 +55,14 @@ func (q *Qliksense) InstallCrds(opts *CrdCommandOptions) error {
|
||||
} else if err = qapi.KubectlApply(engineCRD, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
if customCrd, err := getCustomCrd(qcr); err != nil {
|
||||
return err
|
||||
} else if customCrd != "" {
|
||||
if err = qapi.KubectlApply(customCrd, ""); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if opts.All { // install opeartor crd
|
||||
if err := qapi.KubectlApply(q.GetOperatorCRDString(), ""); err != nil {
|
||||
fmt.Println("cannot do kubectl apply on opeartor CRD", err)
|
||||
@@ -59,16 +79,29 @@ func getQliksenseInitCrd(qcr *qapi.QliksenseCR) (string, error) {
|
||||
if qcr.Spec.GetManifestsRoot() != "" {
|
||||
repoPath = qcr.Spec.GetManifestsRoot()
|
||||
} else {
|
||||
if repoPath, err = downloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master"); err != nil {
|
||||
if repoPath, err = DownloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
qInitMsPath := filepath.Join(repoPath, Q_INIT_CRD_PATH)
|
||||
qInitByte, err := executeKustomizeBuild(qInitMsPath)
|
||||
qInitByte, err := ExecuteKustomizeBuild(qInitMsPath)
|
||||
if err != nil {
|
||||
fmt.Println("cannot generate crds for qliksense-init", err)
|
||||
return "", err
|
||||
}
|
||||
return string(qInitByte), nil
|
||||
}
|
||||
|
||||
func getCustomCrd(qcr *qapi.QliksenseCR) (string, error) {
|
||||
crdPath := qcr.GetCustomCrdsPath()
|
||||
if crdPath == "" {
|
||||
return "", nil
|
||||
}
|
||||
qInitByte, err := ExecuteKustomizeBuild(crdPath)
|
||||
if err != nil {
|
||||
fmt.Println("cannot generate custom crds", err)
|
||||
return "", err
|
||||
}
|
||||
return string(qInitByte), nil
|
||||
}
|
||||
|
||||
@@ -8,7 +8,7 @@ import (
|
||||
)
|
||||
|
||||
func TestGetQliksenseInitCrd(t *testing.T) {
|
||||
someTmpRepoPath, err := downloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master")
|
||||
someTmpRepoPath, err := DownloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v", err)
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package qliksense
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -27,6 +28,29 @@ const (
|
||||
imageSharedBlobsDirName = "blobs"
|
||||
)
|
||||
|
||||
func (q *Qliksense) PullImages(version, profile string) error {
|
||||
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||
if version != "" {
|
||||
if err := q.FetchQK8s(version); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
qcr, err := qConfig.GetCurrentCR()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if !qcr.IsRepoExist() {
|
||||
return errors.New("ManifestsRoot not found")
|
||||
}
|
||||
if profile != "" {
|
||||
qcr.Spec.Profile = profile
|
||||
if e := qConfig.WriteCR(qcr); e != nil {
|
||||
return e
|
||||
}
|
||||
}
|
||||
return q.PullImagesForCurrentCR()
|
||||
}
|
||||
|
||||
// PullImages ...
|
||||
func (q *Qliksense) PullImagesForCurrentCR() error {
|
||||
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||
|
||||
@@ -24,7 +24,7 @@ func (q *Qliksense) GetInstallableVersions(opts *LsRemoteCmdOptions) error {
|
||||
if qcr.Spec.GetManifestsRoot() != "" {
|
||||
repoPath = qcr.Spec.GetManifestsRoot()
|
||||
} else {
|
||||
repoPath, err = downloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master")
|
||||
repoPath, err = DownloadFromGitRepoToTmpDir(defaultConfigRepoGitUrl, "master")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package qliksense
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"log"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
|
||||
@@ -13,7 +15,8 @@ import (
|
||||
"sigs.k8s.io/kustomize/api/types"
|
||||
)
|
||||
|
||||
func executeKustomizeBuild(directory string) ([]byte, error) {
|
||||
//ExecuteKustomizeBuild execute kustomize to the directory and return manifest as byte array
|
||||
func ExecuteKustomizeBuild(directory string) ([]byte, error) {
|
||||
return executeKustomizeBuildForFileSystem(directory, filesys.MakeFsOnDisk())
|
||||
}
|
||||
|
||||
@@ -39,10 +42,26 @@ func executeKustomizeBuildForFileSystem(directory string, fSys filesys.FileSyste
|
||||
|
||||
func executeKustomizeBuildWithStdoutProgress(path string) (kuzManifest []byte, err error) {
|
||||
result, err := api.ExecuteTaskWithBlinkingStdoutFeedback(func() (interface{}, error) {
|
||||
return executeKustomizeBuild(path)
|
||||
return ExecuteKustomizeBuild(path)
|
||||
}, "...")
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return result.([]byte), nil
|
||||
}
|
||||
|
||||
//GetYamlsFromMultiDoc filter yaml docs from multiyaml based on kind
|
||||
func GetYamlsFromMultiDoc(multiYaml string, kind string) string {
|
||||
yamlDocs := strings.Split(string(multiYaml), "---")
|
||||
resultDocs := ""
|
||||
for _, doc := range yamlDocs {
|
||||
scanner := bufio.NewScanner(strings.NewReader(doc))
|
||||
for scanner.Scan() {
|
||||
if scanner.Text() == "kind: "+kind {
|
||||
resultDocs = resultDocs + "\n---\n" + doc
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
return resultDocs
|
||||
}
|
||||
|
||||
@@ -20,7 +20,7 @@ import (
|
||||
kapis_git "github.com/qlik-oss/k-apis/pkg/git"
|
||||
)
|
||||
|
||||
func Test_executeKustomizeBuild(t *testing.T) {
|
||||
func Test_ExecuteKustomizeBuild(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v\n", err)
|
||||
@@ -41,7 +41,7 @@ configMapGenerator:
|
||||
t.Fatalf("error writing kustomization file to path: %v error: %v\n", kustomizationYamlFilePath, err)
|
||||
}
|
||||
|
||||
result, err := executeKustomizeBuild(tmpDir)
|
||||
result, err := ExecuteKustomizeBuild(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected kustomize error: %v\n", err)
|
||||
}
|
||||
@@ -86,7 +86,7 @@ func Test_executeKustomizeBuild_onQlikConfig_regenerateKeys(t *testing.T) {
|
||||
|
||||
generateKeys(cr, "won't-use")
|
||||
|
||||
yamlResources, err := executeKustomizeBuild(path.Join(configPath, "manifests", "base", "resources", "users"))
|
||||
yamlResources, err := ExecuteKustomizeBuild(path.Join(configPath, "manifests", "base", "resources", "users"))
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected kustomize error: %v\n", err)
|
||||
}
|
||||
@@ -139,3 +139,97 @@ func getEjsonKeyDir(defaultKeyDir string) string {
|
||||
}
|
||||
return ejsonKeyDir
|
||||
}
|
||||
|
||||
func Test_GetYamlDocKindFromMultiDoc(t *testing.T) {
|
||||
tmpDir, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected error: %v\n", err)
|
||||
}
|
||||
defer os.RemoveAll(tmpDir)
|
||||
|
||||
kustomizationYamlFilePath := path.Join(tmpDir, "kustomization.yaml")
|
||||
testResFileYamlFilePath := path.Join(tmpDir, "test-file.yaml")
|
||||
kustomizationYaml := `
|
||||
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||
kind: Kustomization
|
||||
resources:
|
||||
- test-file.yaml
|
||||
`
|
||||
testYaml := `
|
||||
apiVersion: v1
|
||||
data:
|
||||
foo: bar
|
||||
kind: ConfigMap
|
||||
metadata:
|
||||
name: foo-config
|
||||
---
|
||||
apiVersion: v1
|
||||
kind: ServiceAccount
|
||||
metadata:
|
||||
labels:
|
||||
app: qix-sessions
|
||||
chart: qix-sessions-4.0.10
|
||||
heritage: Helm
|
||||
release: qliksense
|
||||
name: qliksense-qix-sessions
|
||||
namespace: default
|
||||
---
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
app: chronos
|
||||
chart: chronos-1.5.7
|
||||
heritage: Helm
|
||||
release: qliksense
|
||||
name: qliksense-chronos
|
||||
namespace: default
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
`
|
||||
err = ioutil.WriteFile(kustomizationYamlFilePath, []byte(kustomizationYaml), os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf("error writing kustomization file to path: %v error: %v\n", kustomizationYamlFilePath, err)
|
||||
}
|
||||
err = ioutil.WriteFile(testResFileYamlFilePath, []byte(testYaml), os.ModePerm)
|
||||
if err != nil {
|
||||
t.Fatalf("error writing test-file to path: %v error: %v\n", testResFileYamlFilePath, err)
|
||||
}
|
||||
result, err := ExecuteKustomizeBuild(tmpDir)
|
||||
if err != nil {
|
||||
t.Fatalf("unexpected kustomize error: %v\n", err)
|
||||
}
|
||||
resultYaml := GetYamlsFromMultiDoc(string(result), "Role")
|
||||
|
||||
expectedK8sYaml := `
|
||||
---
|
||||
|
||||
apiVersion: rbac.authorization.k8s.io/v1beta1
|
||||
kind: Role
|
||||
metadata:
|
||||
labels:
|
||||
app: chronos
|
||||
chart: chronos-1.5.7
|
||||
heritage: Helm
|
||||
release: qliksense
|
||||
name: qliksense-chronos
|
||||
namespace: default
|
||||
rules:
|
||||
- apiGroups:
|
||||
- ""
|
||||
resources:
|
||||
- endpoints
|
||||
verbs:
|
||||
- get
|
||||
- update
|
||||
`
|
||||
if resultYaml != expectedK8sYaml {
|
||||
t.Fatalf("expected k8s yaml: [%v] but got: [%v]\n", expectedK8sYaml, resultYaml)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user