Compare commits

..

4 Commits

Author SHA1 Message Date
Ilir Bekteshi
7d0a7ee791 [action] Remove MacOS from matrix 2020-04-16 16:40:33 +02:00
Ilir Bekteshi
8eebdefb7d [action] go@beta to clean WFs from workarounds 2020-04-16 16:21:30 +02:00
Ilir Bekteshi
52c17699ea [action] install make on windows 2020-04-16 16:01:52 +02:00
Ilir Bekteshi
aff35f3f86 [action] test on supported platforms (#319) 2020-04-16 16:01:52 +02:00
20 changed files with 395 additions and 620 deletions

View File

@@ -1,84 +1,51 @@
package main
import (
"bytes"
"fmt"
qapi "github.com/qlik-oss/sense-installer/pkg/api"
"github.com/qlik-oss/sense-installer/pkg/qliksense"
"github.com/spf13/cobra"
)
func installCmd(q *qliksense.Qliksense) *cobra.Command {
opts := &qliksense.InstallCommandOptions{}
filePath := ""
keepPatchFiles, pull, push := false, false, false
c := &cobra.Command{
Use: "install",
Short: "install a qliksense release",
Long: `install a qliksense release`,
Example: `qliksense install <version> #if no version provides, expect manifestsRoot is set somewhere in the file system
# qliksense install -f file_name or cat cr_file | qliksense install -f -
`,
Use: "install",
Short: "install a qliksense release",
Long: `install a qliksense release`,
Example: `qliksense install <version> #if no version provides, expect manifestsRoot is set somewhere in the file system`,
RunE: func(cmd *cobra.Command, args []string) error {
if filePath != "" {
return runLoadOrApplyCommandE(cmd, func(crBytes []byte) error {
if cr, crBytesWithEula, err := getCrWithEulaInserted(crBytes); err != nil {
return err
} else if err := validatePullPushFlagsOnApply(cr, pull, push); err != nil {
return err
} else {
return q.ApplyCRFromReader(bytes.NewReader(crBytesWithEula), opts, keepPatchFiles, true, pull, push)
}
})
} else {
version := ""
if len(args) != 0 {
version = args[0]
}
if err := validatePullPushFlagsOnInstall(q, pull, push); err != nil {
version := ""
if len(args) != 0 {
version = args[0]
}
if err := validatePullPushFlagsOnInstall(q, pull, push); err != nil {
return err
}
if pull {
fmt.Println("Pulling images...")
if err := q.PullImages(version, ""); err != nil {
return err
}
if pull {
fmt.Println("Pulling images...")
if err := q.PullImages(version, ""); err != nil {
return err
}
}
if push {
fmt.Println("Pushing images...")
if err := q.PushImagesForCurrentCR(); err != nil {
return err
}
}
return q.InstallQK8s(version, opts, keepPatchFiles)
}
if push {
fmt.Println("Pushing images...")
if err := q.PushImagesForCurrentCR(); err != nil {
return err
}
}
return q.InstallQK8s(version, opts, keepPatchFiles)
},
}
eulaPreRunHooks.addValidator(fmt.Sprintf("%v %v", rootCommandName, c.Name()), func(cmd *cobra.Command, q *qliksense.Qliksense) (b bool, err error) {
if filePath != "" {
return loadOrApplyCommandEulaPreRunHook(cmd, q)
} else if qConfig, err := qapi.NewQConfigE(q.QliksenseHome); err != nil {
return false, err
} else if qcr, err := qConfig.GetCurrentCR(); err != nil {
return false, err
} else {
return qcr.IsEULA(), nil
}
})
f := c.Flags()
f.StringVarP(&opts.StorageClass, "storageClass", "s", "", "Storage class for qliksense")
f.StringVarP(&opts.MongoDbUri, "mongoDbUri", "m", "", "mongoDbUri for qliksense (i.e. mongodb://qlik-default-mongodb:27017/qliksense?ssl=false)")
f.StringVarP(&opts.RotateKeys, "rotateKeys", "r", "", "Rotate JWT keys for qliksense (yes:rotate keys/ no:use exising keys from cluster/ None: use default EJSON_KEY from env")
f.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
f.BoolVarP(&push, pushFlagName, pushFlagShorthand, push, pushFlagUsage)
return c
}

View File

@@ -2,11 +2,9 @@ package main
import (
"fmt"
"log"
"github.com/kyokomi/emoji"
ansi "github.com/mattn/go-colorable"
"github.com/qlik-oss/sense-installer/pkg/preflight"
"github.com/ttacon/chalk"
"github.com/qlik-oss/sense-installer/pkg/qliksense"
"github.com/spf13/cobra"
@@ -23,83 +21,67 @@ func preflightCmd(q *qliksense.Qliksense) *cobra.Command {
}
func pfDnsCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
var preflightDnsCmd = &cobra.Command{
Use: "dns",
Short: "perform preflight dns check",
Long: `perform preflight dns check to check DNS connectivity status in the cluster`,
Example: `qliksense preflight dns`,
RunE: func(cmd *cobra.Command, args []string) error {
qp := &preflight.QliksensePreflight{Q: q, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight DNS check
fmt.Printf("Preflight DNS check\n")
fmt.Println("---------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight DNS check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight DNS check FAILED\n")
log.Fatal(err)
}
if namespace == "" {
namespace = "default"
}
if err = qp.CheckDns(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight DNS check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight DNS check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight DNS check"))
return nil
},
}
f := preflightDnsCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightDnsCmd
}
func pfK8sVersionCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
var preflightCheckK8sVersionCmd = &cobra.Command{
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight Kubernetes minimum version check
fmt.Printf("Preflight kubernetes minimum version check\n")
fmt.Println("------------------------------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight kubernetes minimum version check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight kubernetes minimum version check FAILED\n")
log.Fatal(err)
}
if err = qp.CheckK8sVersion(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight kubernetes minimum version check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Printf("Preflight kubernetes minimum version check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight kubernetes minimum version check"))
return nil
},
}
f := preflightCheckK8sVersionCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightCheckK8sVersionCmd
}
func pfAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
preflightOpts := &preflight.PreflightMongoOptions{}
var preflightAllChecksCmd = &cobra.Command{
Use: "all",
@@ -107,333 +89,276 @@ func pfAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
Long: `perform all preflight checks on the target cluster`,
Example: `qliksense preflight all`,
RunE: func(cmd *cobra.Command, args []string) error {
qp := &preflight.QliksensePreflight{Q: q, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight run all checks
fmt.Printf("Running all preflight checks...\n\n")
fmt.Printf("Running all preflight checks\n")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Unable to run the preflight checks suite"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Printf("Running preflight check suite has FAILED...\n")
log.Fatal()
}
if namespace == "" {
namespace = "default"
}
if err = qp.RunAllPreflightChecks(kubeConfigContents, namespace, preflightOpts); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: 1 or more preflight checks have FAILED"))
fmt.Println("Completed running all preflight checks")
return nil
}
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: All preflight checks have PASSED"))
qp.RunAllPreflightChecks(kubeConfigContents, namespace, preflightOpts)
return nil
},
}
f := preflightAllChecksCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
f.StringVarP(&preflightOpts.MongoOptions.MongodbUrl, "mongodb-url", "", "", "mongodbUrl to try connecting to")
f.StringVarP(&preflightOpts.MongoOptions.Username, "mongodb-username", "", "", "username to connect to mongodb")
f.StringVarP(&preflightOpts.MongoOptions.Password, "mongodb-password", "", "", "password to connect to mongodb")
f.StringVarP(&preflightOpts.MongoOptions.CaCertFile, "mongodb-ca-cert", "", "", "certificate to use for mongodb check")
f.StringVarP(&preflightOpts.MongoOptions.ClientCertFile, "mongodb-client-cert", "", "", "client-certificate to use for mongodb check")
f.BoolVar(&preflightOpts.MongoOptions.Tls, "mongodb-tls", false, "enable tls?")
f.StringVarP(&preflightOpts.MongodbUrl, "mongodb-url", "", "", "mongodbUrl to try connecting to")
f.StringVarP(&preflightOpts.Username, "mongodb-username", "", "", "username to connect to mongodb")
f.StringVarP(&preflightOpts.Password, "mongodb-password", "", "", "password to connect to mongodb")
f.StringVarP(&preflightOpts.CaCertFile, "mongodb-ca-cert", "", "", "certificate to use for mongodb check")
f.StringVarP(&preflightOpts.ClientCertFile, "mongodb-client-cert", "", "", "client-certificate to use for mongodb check")
f.BoolVar(&preflightOpts.Tls, "mongodb-tls", false, "enable tls?")
return preflightAllChecksCmd
}
func pfDeploymentCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight deployments check
fmt.Printf("Preflight deployment check\n")
fmt.Println("--------------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight deployment check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight deployment check FAILED\n")
log.Fatal(err)
}
if namespace == "" {
namespace = "default"
}
if err = qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight deployment check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight deploy check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight deployment check"))
return nil
},
}
f := pfDeploymentCheckCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return pfDeploymentCheckCmd
}
func pfServiceCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight service check
fmt.Printf("Preflight service check\n")
fmt.Println("-----------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight service check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight service check FAILED\n")
log.Fatal(err)
}
if namespace == "" {
namespace = "default"
}
if err = qp.CheckService(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight service check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight service check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight service check"))
return nil
},
}
f := pfServiceCheckCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return pfServiceCheckCmd
}
func pfPodCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight pod check
fmt.Printf("Preflight pod check\n")
fmt.Println("--------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight pod check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight pod check FAILED\n")
log.Fatal(err)
}
if namespace == "" {
namespace = "default"
}
if err = qp.CheckPod(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight pod check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight pod check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight pod check"))
return nil
},
}
f := pfPodCheckCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return pfPodCheckCmd
}
func pfCreateRoleCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight role check
fmt.Printf("Preflight role check\n")
fmt.Println("---------------------------")
namespace, _, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight role check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight role check FAILED\n")
log.Fatal(err)
}
if err = qp.CheckCreateRole(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight role check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight role FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight role check"))
return nil
},
}
f := preflightRoleCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightRoleCmd
}
func pfCreateRoleBindingCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight createRoleBinding check
fmt.Printf("Preflight rolebinding check\n")
fmt.Println("---------------------------")
namespace, _, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight rolebinding check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight rolebinding check FAILED\n")
log.Fatal(err)
}
if err = qp.CheckCreateRoleBinding(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight rolebinding check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight rolebinding check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight rolebinding check"))
return nil
},
}
f := preflightRoleBindingCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightRoleBindingCmd
}
func pfCreateServiceAccountCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight createServiceAccount check
fmt.Printf("Preflight ServiceAccount check\n")
fmt.Println("-------------------------------------")
namespace, _, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight ServiceAccount check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight serviceaccount check FAILED\n")
log.Fatal(err)
}
if err = qp.CheckCreateServiceAccount(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight ServiceAccount check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight serviceaccount check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight rolebinding check"))
return nil
},
}
f := preflightServiceAccountCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightServiceAccountCmd
}
func pfCreateAuthCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight authcheck
fmt.Printf("Preflight authcheck\n")
fmt.Println("------------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight authcheck"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight authcheck FAILED\n")
log.Fatal(err)
}
if err = qp.CheckCreateRB(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight authcheck"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight authcheck FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight authcheck"))
return nil
},
}
f := preflightCreateAuthCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
return preflightCreateAuthCmd
}
func pfMongoCheckCmd(q *qliksense.Qliksense) *cobra.Command {
out := ansi.NewColorableStdout()
preflightOpts := &preflight.PreflightOptions{
MongoOptions: &preflight.MongoOptions{},
}
preflightOpts := &preflight.PreflightMongoOptions{}
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, P: preflightOpts}
qp := &preflight.QliksensePreflight{Q: q}
// Preflight mongo check
fmt.Printf("Preflight mongo check\n")
fmt.Println("-------------------------------------")
namespace, kubeConfigContents, err := preflight.InitPreflight()
if err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight mongo check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Printf("Preflight mongo check FAILED\n")
log.Fatal(err)
}
if namespace == "" {
namespace = "default"
}
if err = qp.CheckMongo(kubeConfigContents, namespace, preflightOpts); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight mongo check"))
fmt.Printf("Error: %v\n", err)
return nil
fmt.Println(err)
fmt.Print("Preflight mongo check FAILED\n")
log.Fatal()
}
emoji.Fprintf(out, "%s\n", chalk.Green.Color(":heavy_check_mark: Preflight mongo check"))
return nil
},
}
f := preflightMongoCmd.Flags()
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
f.StringVarP(&preflightOpts.MongoOptions.MongodbUrl, "url", "", "", "mongodbUrl to try connecting to")
f.StringVarP(&preflightOpts.MongoOptions.Username, "username", "", "", "username to connect to mongodb")
f.StringVarP(&preflightOpts.MongoOptions.Password, "password", "", "", "password to connect to mongodb")
f.StringVarP(&preflightOpts.MongoOptions.CaCertFile, "ca-cert", "", "", "ca certificate to use for mongodb check")
f.StringVarP(&preflightOpts.MongoOptions.ClientCertFile, "client-cert", "", "", "client-certificate to use for mongodb check")
f.BoolVar(&preflightOpts.MongoOptions.Tls, "tls", false, "enable tls?")
f.StringVarP(&preflightOpts.MongodbUrl, "url", "", "", "mongodbUrl to try connecting to")
f.StringVarP(&preflightOpts.Username, "username", "", "", "username to connect to mongodb")
f.StringVarP(&preflightOpts.Password, "password", "", "", "password to connect to mongodb")
f.StringVarP(&preflightOpts.CaCertFile, "ca-cert", "", "", "ca certificate to use for mongodb check")
f.StringVarP(&preflightOpts.ClientCertFile, "client-cert", "", "", "client-certificate to use for mongodb check")
f.BoolVar(&preflightOpts.Tls, "tls", false, "enable tls?")
return preflightMongoCmd
}

View File

@@ -172,6 +172,9 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
viper.SetEnvKeyReplacer(strings.NewReplacer("-", "_"))
//add upgrade command
cmd.AddCommand(upgradeCmd(p))
// add the set-context config command as a sub-command to the app config command
configCmd.AddCommand(setContextConfigCmd(p))

23
cmd/qliksense/upgrade.go Normal file
View File

@@ -0,0 +1,23 @@
package main
import (
"github.com/qlik-oss/sense-installer/pkg/qliksense"
"github.com/spf13/cobra"
)
func upgradeCmd(q *qliksense.Qliksense) *cobra.Command {
keepPatchFiles := false
c := &cobra.Command{
Use: "upgrade",
Short: "upgrade qliksense release",
Long: `upgrade qliksense release`,
Example: `qliksense upgrade <version>`,
RunE: func(cmd *cobra.Command, args []string) error {
return q.UpgradeQK8s(keepPatchFiles)
},
}
f := c.Flags()
f.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
return c
}

1
go.mod
View File

@@ -37,7 +37,6 @@ require (
github.com/hashicorp/golang-lru v0.5.4 // indirect
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
github.com/kyokomi/emoji v2.2.2+incompatible
github.com/mattn/go-colorable v0.1.4
github.com/mattn/go-tty v0.0.3
github.com/mitchellh/go-homedir v1.1.0

3
go.sum
View File

@@ -675,9 +675,6 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/kyokomi/emoji v1.5.1 h1:qp9dub1mW7C4MlvoRENH6EAENb9skEFOvIEbp1Waj38=
github.com/kyokomi/emoji v2.2.2+incompatible h1:gaQFbK2+uSxOR4iGZprJAbpmtqTrHhSdgOyIMD6Oidc=
github.com/kyokomi/emoji v2.2.2+incompatible/go.mod h1:mZ6aGCD7yk8j6QY6KICwnZ2pxoszVseX1DNoGtU2tBA=
github.com/lib/pq v1.1.1/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
github.com/lib/pq v1.2.0 h1:LXpIM/LZ5xGFhOpXAQUIMM1HdyqzVYM13zNdjCEEcA0=
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=

View File

@@ -15,20 +15,12 @@ func KubectlApply(manifests, namespace string) error {
return kubectlOperation(manifests, "apply", namespace)
}
func KubectlApplyVerbose(manifests, namespace string, verbose bool) error {
return kubectlOperationVerbose(manifests, "apply", namespace, verbose)
}
// KubectlDelete delete resoruces in the provided namespace,
// if namespace="" then use whatever the kubectl default is
func KubectlDelete(manifests, namespace string) error {
return kubectlOperation(manifests, "delete", namespace)
}
func KubectlDeleteVerbose(manifests, namespace string, verbose bool) error {
return kubectlOperationVerbose(manifests, "delete", namespace, verbose)
}
func GetKubectlNamespace() string {
namespace := ""
cmd := exec.Command("kubectl", "config", "current-context")
@@ -69,10 +61,6 @@ func SetKubectlNamespace(ns string) {
}
func kubectlOperation(manifests string, oprName string, namespace string) error {
return kubectlOperationVerbose(manifests, oprName, namespace, true)
}
func kubectlOperationVerbose(manifests string, oprName string, namespace string, verbose bool) error {
tempYaml, err := ioutil.TempFile("", "")
if err != nil {
fmt.Println("cannot create file ", err)
@@ -100,16 +88,12 @@ func kubectlOperationVerbose(manifests string, oprName string, namespace string,
}
sterrBuffer := &bytes.Buffer{}
stoutBuffer := &bytes.Buffer{}
cmd.Stdout = stoutBuffer
cmd.Stdout = os.Stdout
cmd.Stderr = sterrBuffer
err = cmd.Run()
if err != nil {
return fmt.Errorf("kubectl %v failed with: %v, %v, temp k8s yaml file:%v\n", oprName, err, sterrBuffer.String(), tempYaml.Name())
}
if verbose {
fmt.Println(stoutBuffer.String())
}
os.Remove(tempYaml.Name())
return nil
}

View File

@@ -46,7 +46,7 @@ func DirExists(dirname string) bool {
// LogDebugMessage logs a debug message
func LogDebugMessage(strMessage string, args ...interface{}) {
if os.Getenv("QLIKSENSE_DEBUG") == "true" {
fmt.Printf(strMessage, args...)
log.Printf(strMessage, args...)
}
}

View File

@@ -2,111 +2,106 @@ package preflight
import (
"fmt"
"github.com/kyokomi/emoji"
ansi "github.com/mattn/go-colorable"
"github.com/pkg/errors"
"github.com/ttacon/chalk"
)
func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
out := ansi.NewColorableStdout()
func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, namespace string, preflightOpts *PreflightMongoOptions) {
checkCount := 0
totalCount := 0
// Preflight minimum kuberenetes version check
fmt.Printf("\nPreflight kubernetes minimum version check\n")
fmt.Println("------------------------------------------")
if err := qp.CheckK8sVersion(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight kubernetes minimum version check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight kubernetes minimum version check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight kubernetes minimum version check"))
checkCount++
}
totalCount++
// Preflight deployment check
fmt.Printf("\nPreflight deployment check\n")
fmt.Println("--------------------------")
if err := qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight deployment check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight deployment check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight deployment check"))
checkCount++
}
totalCount++
// Preflight service check
fmt.Printf("\nPreflight service check\n")
fmt.Println("-----------------------")
if err := qp.CheckService(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight service check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight service check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight service check"))
checkCount++
}
totalCount++
// Preflight pod check
fmt.Printf("\nPreflight pod check\n")
fmt.Println("-----------------------")
if err := qp.CheckPod(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight pod check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight pod check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight pod check"))
checkCount++
}
totalCount++
// Preflight role check
fmt.Printf("\nPreflight role check\n")
fmt.Println("--------------------------")
if err := qp.CheckCreateRole(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight role check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight role check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight role check"))
checkCount++
}
totalCount++
// Preflight rolebinding check
fmt.Printf("\nPreflight rolebinding check\n")
fmt.Println("---------------------------------")
if err := qp.CheckCreateRoleBinding(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight rolebinding check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight rolebinding check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight rolebinding check"))
checkCount++
}
totalCount++
// Preflight serviceaccount check
fmt.Printf("\nPreflight serviceaccount check\n")
fmt.Println("------------------------------------")
if err := qp.CheckCreateServiceAccount(namespace); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight serviceaccount check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight serviceaccount check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight serviceaccount check"))
checkCount++
}
totalCount++
// Preflight mongo check
fmt.Printf("\nPreflight mongo check\n")
fmt.Println("---------------------")
if err := qp.CheckMongo(kubeConfigContents, namespace, preflightOpts); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight mongo check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight mongo check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight mongo check"))
checkCount++
}
totalCount++
// Preflight DNS check
fmt.Printf("\nPreflight DNS check\n")
fmt.Println("-------------------")
if err := qp.CheckDns(namespace, kubeConfigContents); err != nil {
emoji.Fprintf(out, "%s\n", chalk.Red.Color(":heavy_multiplication_x: Preflight DNS check"))
fmt.Printf("Error: %v\n\n", err)
fmt.Printf("Preflight DNS check: FAILED\n")
} else {
emoji.Fprintf(out, "%s\n\n", chalk.Green.Color(":heavy_check_mark: Preflight DNS check"))
checkCount++
}
totalCount++
if checkCount == totalCount {
// All preflight checks were successful
return nil
fmt.Printf("\nAll preflight checks have PASSED\n")
} else {
fmt.Printf("\n1 or more preflight checks have FAILED\n")
}
return errors.New("1 or more preflight checks have FAILED")
fmt.Println("Completed running all preflight checks")
}

View File

@@ -10,18 +10,18 @@ func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigConten
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
if err != nil {
err = fmt.Errorf("Kube config error: %v\n", err)
fmt.Print(err)
return err
}
// Deployment check
qp.P.LogVerboseMessage("Preflight deployment check: \n")
qp.P.LogVerboseMessage("--------------------------- \n")
fmt.Printf("Preflight deployment check: \n")
err = qp.checkPfDeployment(clientset, namespace, "deployment-preflight-check")
if err != nil {
qp.P.LogVerboseMessage("Preflight Deployment check: FAILED\n")
fmt.Println("Preflight Deployment check: FAILED")
return err
}
qp.P.LogVerboseMessage("Completed preflight deployment check\n")
fmt.Println("Completed preflight deployment check")
return nil
}
@@ -29,18 +29,18 @@ func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigConten
func (qp *QliksensePreflight) CheckService(namespace string, kubeConfigContents []byte) error {
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
if err != nil {
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
fmt.Println(err)
return err
}
// Service check
qp.P.LogVerboseMessage("Preflight service check: \n")
qp.P.LogVerboseMessage("------------------------ \n")
err = qp.checkPfService(clientset, namespace)
fmt.Printf("\nPreflight service check: \n")
err = checkPfService(clientset, namespace)
if err != nil {
qp.P.LogVerboseMessage("Preflight Service check: FAILED\n")
fmt.Println("Preflight Service check: FAILED")
return err
}
qp.P.LogVerboseMessage("Completed preflight service check\n")
fmt.Println("Completed preflight service check")
return nil
}
@@ -48,17 +48,18 @@ func (qp *QliksensePreflight) CheckPod(namespace string, kubeConfigContents []by
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
qp.P.LogVerboseMessage("Preflight pod check: \n")
qp.P.LogVerboseMessage("-------------------- \n")
fmt.Printf("\nPreflight pod check: \n")
err = qp.checkPfPod(clientset, namespace)
if err != nil {
qp.P.LogVerboseMessage("Preflight Pod check: FAILED\n")
fmt.Println("Preflight Pod check: FAILED")
return err
}
qp.P.LogVerboseMessage("Completed preflight pod check\n")
fmt.Println("Completed preflight pod check")
return nil
}
@@ -71,38 +72,38 @@ func (qp *QliksensePreflight) checkPfPod(clientset *kubernetes.Clientset, namesp
if err != nil {
return err
}
pod, err := qp.createPreflightTestPod(clientset, namespace, podName, imageName, nil, commandToRun)
pod, err := createPreflightTestPod(clientset, namespace, podName, imageName, nil, commandToRun)
if err != nil {
err = fmt.Errorf("unable to create pod - %v\n", err)
err = fmt.Errorf("error: unable to create pod %s - %v\n", podName, err)
return err
}
defer qp.deletePod(clientset, namespace, podName)
defer deletePod(clientset, namespace, podName)
if err := waitForPod(clientset, namespace, pod); err != nil {
return err
}
qp.P.LogVerboseMessage("Preflight pod creation check: PASSED\n")
qp.P.LogVerboseMessage("Cleaning up resources...\n")
fmt.Println("Preflight pod creation check: PASSED")
fmt.Println("Cleaning up resources...")
return nil
}
func (qp *QliksensePreflight) checkPfService(clientset *kubernetes.Clientset, namespace string) error {
func checkPfService(clientset *kubernetes.Clientset, namespace string) error {
// creating service
serviceName := "svc-pf-check"
pfService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
pfService, err := createPreflightTestService(clientset, namespace, serviceName)
if err != nil {
err = fmt.Errorf("unable to create service - %v\n", err)
err = fmt.Errorf("error: unable to create service : %s\n", serviceName)
return err
}
defer qp.deleteService(clientset, namespace, serviceName)
defer deleteService(clientset, namespace, serviceName)
_, err = getService(clientset, namespace, pfService.GetName())
if err != nil {
err = fmt.Errorf("unable to retrieve service - %v\n", err)
err = fmt.Errorf("error: unable to retrieve service: %s\n", serviceName)
return err
}
qp.P.LogVerboseMessage("Preflight service creation check: PASSED\n")
qp.P.LogVerboseMessage("Cleaning up resources...\n")
fmt.Println("Preflight service creation check: PASSED")
fmt.Println("Cleaning up resources...")
return nil
}
@@ -112,16 +113,16 @@ func (qp *QliksensePreflight) checkPfDeployment(clientset *kubernetes.Clientset,
if err != nil {
return err
}
pfDeployment, err := qp.createPreflightTestDeployment(clientset, namespace, depName, imageName)
pfDeployment, err := createPreflightTestDeployment(clientset, namespace, depName, imageName)
if err != nil {
err = fmt.Errorf("unable to create deployment - %v\n", err)
err = fmt.Errorf("error: unable to create deployment: %v\n", err)
return err
}
defer qp.deleteDeployment(clientset, namespace, depName)
defer deleteDeployment(clientset, namespace, depName)
if err := waitForDeployment(clientset, namespace, pfDeployment); err != nil {
return err
}
qp.P.LogVerboseMessage("Preflight Deployment check: PASSED\n")
qp.P.LogVerboseMessage("Cleaning up resources...\n")
fmt.Println("Preflight Deployment check: PASSED")
fmt.Println("Cleaning up resources...")
return nil
}

View File

@@ -11,11 +11,10 @@ const (
)
func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []byte) error {
qp.P.LogVerboseMessage("Preflight DNS check: \n")
qp.P.LogVerboseMessage("------------------- \n")
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
if err != nil {
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
fmt.Println(err)
return err
}
@@ -25,12 +24,13 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
if err != nil {
return err
}
dnsDeployment, err := qp.createPreflightTestDeployment(clientset, namespace, depName, nginxImageName)
dnsDeployment, err := createPreflightTestDeployment(clientset, namespace, depName, nginxImageName)
if err != nil {
err = fmt.Errorf("unable to create deployment: %v\n", err)
err = fmt.Errorf("error: unable to create deployment: %v\n", err)
fmt.Println(err)
return err
}
defer qp.deleteDeployment(clientset, namespace, depName)
defer deleteDeployment(clientset, namespace, depName)
if err := waitForDeployment(clientset, namespace, dnsDeployment); err != nil {
return err
@@ -38,34 +38,34 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
// creating service
serviceName := "svc-dns-pf-check"
dnsService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
dnsService, err := createPreflightTestService(clientset, namespace, serviceName)
if err != nil {
err = fmt.Errorf("unable to create service : %s, %s\n", serviceName, err)
err = fmt.Errorf("error: unable to create service : %s\n", serviceName)
return err
}
defer qp.deleteService(clientset, namespace, serviceName)
defer deleteService(clientset, namespace, serviceName)
// create a pod
podName := "pf-pod-1"
commandToRun := []string{"sh", "-c", "sleep 10; nc -z -v -w 1 " + dnsService.Name + " 80"}
netcatImageName, err := qp.GetPreflightConfigObj().GetImageName(netcat, true)
if err != nil {
err = fmt.Errorf("unable to retrieve image : %v\n", err)
return err
}
dnsPod, err := qp.createPreflightTestPod(clientset, namespace, podName, netcatImageName, nil, commandToRun)
dnsPod, err := createPreflightTestPod(clientset, namespace, podName, netcatImageName, nil, commandToRun)
if err != nil {
err = fmt.Errorf("unable to create pod : %s, %s\n", podName, err)
err = fmt.Errorf("error: unable to create pod : %s\n", podName)
return err
}
defer qp.deletePod(clientset, namespace, podName)
defer deletePod(clientset, namespace, podName)
if err := waitForPod(clientset, namespace, dnsPod); err != nil {
return err
}
if len(dnsPod.Spec.Containers) == 0 {
err := fmt.Errorf("there are no containers in the pod")
err := fmt.Errorf("error: there are no containers in the pod")
fmt.Println(err)
return err
}
@@ -73,19 +73,20 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
logStr, err := getPodLogs(clientset, dnsPod)
if err != nil {
err = fmt.Errorf("unable to execute dns check in the cluster: %v", err)
err = fmt.Errorf("error: unable to execute dns check in the cluster: %v", err)
fmt.Println(err)
return err
}
if strings.HasSuffix(strings.TrimSpace(logStr), "succeeded!") {
qp.P.LogVerboseMessage("Preflight DNS check: PASSED\n")
fmt.Println("Preflight DNS check: PASSED")
} else {
err = fmt.Errorf("Expected response not found\n")
return err
}
qp.P.LogVerboseMessage("Completed preflight DNS check\n")
qp.P.LogVerboseMessage("Cleaning up resources...\n")
fmt.Println("Completed preflight DNS check")
fmt.Println("Cleaning up resources...")
return nil
}

View File

@@ -15,13 +15,12 @@ const (
mongo = "mongo"
)
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
qp.P.LogVerboseMessage("Preflight mongodb check: \n")
qp.P.LogVerboseMessage("------------------------ \n")
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightMongoOptions) error {
fmt.Printf("Preflight mongodb check: \n")
if preflightOpts.MongoOptions.MongodbUrl == "" {
if preflightOpts.MongodbUrl == "" {
// infer mongoDbUrl from currentCR
qp.P.LogVerboseMessage("MongoDbUri is empty, infer from CR\n")
fmt.Println("MongoDbUri is empty, infer from CR")
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
var currentCR *qapi.QliksenseCR
@@ -29,130 +28,135 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
qConfig.SetNamespace(namespace)
currentCR, err = qConfig.GetCurrentCR()
if err != nil {
qp.P.LogVerboseMessage("Unable to retrieve current CR: %v\n", err)
fmt.Printf("Unable to retrieve current CR: %v\n", err)
return err
}
decryptedCR, err := qConfig.GetDecryptedCr(currentCR)
if err != nil {
qp.P.LogVerboseMessage("An error occurred while retrieving mongodbUrl from current CR: %v\n", err)
fmt.Printf("An error occurred while retrieving mongodbUrl from current CR: %v\n", err)
return err
}
preflightOpts.MongoOptions.MongodbUrl = decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri")
preflightOpts.MongodbUrl = decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri")
}
qp.P.LogVerboseMessage("MongodbUrl: %s\n", preflightOpts.MongoOptions.MongodbUrl)
fmt.Printf("mongodbUrl: %s\n", preflightOpts.MongodbUrl)
if err := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts); err != nil {
return err
}
qp.P.LogVerboseMessage("Completed preflight mongodb check\n")
fmt.Println("Completed preflight mongodb check")
return nil
}
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightMongoOptions) error {
var caCertSecretName, clientCertSecretName string
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
if err != nil {
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
fmt.Println(err)
return err
}
var secrets []string
if preflightOpts.MongoOptions.CaCertFile != "" {
if preflightOpts.CaCertFile != "" {
caCertSecretName = "preflight-mongo-test-cacert"
caCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.CaCertFile, caCertSecretName)
caCertSecret, err := createSecret(clientset, namespace, preflightOpts.CaCertFile, caCertSecretName)
if err != nil {
err = fmt.Errorf("unable to create a create ca cert kubernetes secret: %v\n", err)
err = fmt.Errorf("error: unable to create a create ca cert kubernetes secret: %v\n", err)
fmt.Println(err)
return err
}
defer qp.deleteK8sSecret(clientset, namespace, caCertSecret)
defer deleteK8sSecret(clientset, namespace, caCertSecret)
secrets = append(secrets, caCertSecretName)
}
if preflightOpts.MongoOptions.ClientCertFile != "" {
if preflightOpts.ClientCertFile != "" {
clientCertSecretName = "preflight-mongo-test-clientcert"
clientCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.ClientCertFile, clientCertSecretName)
clientCertSecret, err := createSecret(clientset, namespace, preflightOpts.ClientCertFile, clientCertSecretName)
if err != nil {
err = fmt.Errorf("unable to create a create client cert kubernetes secret: %v\n", err)
err = fmt.Errorf("error: unable to create a create client cert kubernetes secret: %v\n", err)
fmt.Println(err)
return err
}
defer qp.deleteK8sSecret(clientset, namespace, clientCertSecret)
defer deleteK8sSecret(clientset, namespace, clientCertSecret)
secrets = append(secrets, clientCertSecretName)
}
mongoCommand := strings.Builder{}
mongoCommand.WriteString(fmt.Sprintf("sleep 10;mongo %s", preflightOpts.MongoOptions.MongodbUrl))
if preflightOpts.MongoOptions.Username != "" {
mongoCommand.WriteString(fmt.Sprintf(" --username %s", preflightOpts.MongoOptions.Username))
mongoCommand.WriteString(fmt.Sprintf("sleep 10;mongo %s", preflightOpts.MongodbUrl))
if preflightOpts.Username != "" {
mongoCommand.WriteString(fmt.Sprintf(" --username %s", preflightOpts.Username))
api.LogDebugMessage("Adding username: Mongo command: %s\n", mongoCommand.String())
}
if preflightOpts.MongoOptions.Password != "" {
mongoCommand.WriteString(fmt.Sprintf(" --password %s", preflightOpts.MongoOptions.Password))
if preflightOpts.Password != "" {
mongoCommand.WriteString(fmt.Sprintf(" --password %s", preflightOpts.Password))
api.LogDebugMessage("Adding username and password\n")
}
if preflightOpts.MongoOptions.Tls || preflightOpts.MongoOptions.CaCertFile != "" || preflightOpts.MongoOptions.ClientCertFile != "" {
if preflightOpts.Tls || preflightOpts.CaCertFile != "" || preflightOpts.ClientCertFile != "" {
mongoCommand.WriteString(" --tls")
api.LogDebugMessage("Adding --tls: Mongo command: %s\n", mongoCommand.String())
}
if preflightOpts.MongoOptions.CaCertFile != "" {
mongoCommand.WriteString(fmt.Sprintf(" --tlsCAFile=/etc/ssl/%s/%[1]s", caCertSecretName))
if preflightOpts.CaCertFile != "" {
api.LogDebugMessage("Adding caCertFile: Mongo command: %s\n", mongoCommand.String())
}
if preflightOpts.MongoOptions.ClientCertFile != "" {
if preflightOpts.ClientCertFile != "" {
mongoCommand.WriteString(fmt.Sprintf(" --tlsCertificateKeyFile=/etc/ssl/%s/%[1]s", clientCertSecretName))
api.LogDebugMessage("Adding clientCertFile: Mongo command: %s\n", mongoCommand.String())
}
mongoCommand.WriteString(` --eval "print(\"connected to mongo\")"`)
commandToRun := []string{"sh", "-c", mongoCommand.String()}
api.LogDebugMessage("Mongo command: %s\n", strings.Join(commandToRun, " "))
api.LogDebugMessage("Mongo commandToRun: %s\n", strings.Join(commandToRun, " "))
// create a pod
podName := "pf-mongo-pod"
imageName, err := qp.GetPreflightConfigObj().GetImageName(mongo, true)
if err != nil {
err = fmt.Errorf("unable to retrieve image : %v\n", err)
return err
}
mongoPod, err := qp.createPreflightTestPod(clientset, namespace, podName, imageName, secrets, commandToRun)
mongoPod, err := createPreflightTestPod(clientset, namespace, podName, imageName, secrets, commandToRun)
if err != nil {
err = fmt.Errorf("unable to create pod : %v\n", err)
err = fmt.Errorf("error: unable to create pod : %v\n", err)
return err
}
defer qp.deletePod(clientset, namespace, podName)
defer deletePod(clientset, namespace, podName)
if err := waitForPod(clientset, namespace, mongoPod); err != nil {
return err
}
if len(mongoPod.Spec.Containers) == 0 {
err := fmt.Errorf("there are no containers in the pod- %v\n", err)
err := fmt.Errorf("error: there are no containers in the pod- %v\n", err)
fmt.Println(err)
return err
}
waitForPodToDie(clientset, namespace, mongoPod)
logStr, err := getPodLogs(clientset, mongoPod)
if err != nil {
err = fmt.Errorf("unable to execute mongo check in the cluster: %v\n", err)
err = fmt.Errorf("error: unable to execute mongo check in the cluster: %v\n", err)
fmt.Println(err)
return err
}
stringToCheck := "Implicit session:"
if strings.Contains(logStr, stringToCheck) {
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
fmt.Println("Preflight mongo check: PASSED")
} else {
err = fmt.Errorf("Connection failed: %s\n", logStr)
err = fmt.Errorf("Expected response not found\n")
return err
}
return nil
}
func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, namespace, certFile, certSecretName string) (*apiv1.Secret, error) {
func createSecret(clientset *kubernetes.Clientset, namespace, certFile, certSecretName string) (*apiv1.Secret, error) {
certBytes, err := ioutil.ReadFile(certFile)
if err != nil {
return nil, err
}
certSecret, err := qp.createPreflightTestSecret(clientset, namespace, certSecretName, certBytes)
certSecret, err := createPreflightTestSecret(clientset, namespace, certSecretName, certBytes)
if err != nil {
err = fmt.Errorf("unable to create secret with ca cert : %v\n", err)
err = fmt.Errorf("error: unable to create secret with ca cert : %v\n", err)
return nil, err
}
return certSecret, nil

View File

@@ -6,7 +6,6 @@ import (
"io"
"io/ioutil"
"log"
"os"
"path/filepath"
"strings"
"time"
@@ -27,19 +26,7 @@ import (
"k8s.io/client-go/util/retry"
)
type PreflightOptions struct {
Verbose bool
MongoOptions *MongoOptions
}
// LogVerboseMessage logs a verbose message
func (p *PreflightOptions) LogVerboseMessage(strMessage string, args ...interface{}) {
if p.Verbose || os.Getenv("QLIKSENSE_DEBUG") == "true" {
fmt.Printf(strMessage, args...)
}
}
type MongoOptions struct {
type PreflightMongoOptions struct {
MongodbUrl string
Username string
Password string
@@ -52,7 +39,6 @@ var gracePeriod int64 = 0
type QliksensePreflight struct {
Q *qliksense.Qliksense
P *PreflightOptions
}
func (qp *QliksensePreflight) GetPreflightConfigObj() *api.PreflightConfig {
@@ -116,12 +102,14 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
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 != "" {
@@ -130,18 +118,20 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
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
}
}
clientset, err := kubernetes.NewForConfig(clientConfig)
if err != nil {
err = errors.Wrap(err, "Unable to create clientset")
fmt.Println(err)
return nil, nil, err
}
return clientset, clientConfig, nil
}
func (qp *QliksensePreflight) createPreflightTestDeployment(clientset *kubernetes.Clientset, namespace string, depName string, imageName string) (*appsv1.Deployment, error) {
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{
@@ -186,10 +176,11 @@ func (qp *QliksensePreflight) createPreflightTestDeployment(clientset *kubernete
result, err = deploymentsClient.Create(deployment)
return err
}); err != nil {
err = errors.Wrapf(err, "unable to create deployments in the %s namespace", namespace)
err = errors.Wrapf(err, "error: unable to create deployments in the %s namespace", namespace)
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created deployment %q\n", result.GetObjectMeta().GetName())
fmt.Printf("Created deployment %q\n", result.GetObjectMeta().GetName())
return deployment, nil
}
@@ -201,14 +192,14 @@ func getDeployment(clientset *kubernetes.Clientset, namespace, depName string) (
deployment, err = deploymentsClient.Get(depName, v1.GetOptions{})
return err
}); err != nil {
err = errors.Wrapf(err, "unable to get deployments in the %s namespace", namespace)
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 (qp *QliksensePreflight) deleteDeployment(clientset *kubernetes.Clientset, namespace, name string) error {
func deleteDeployment(clientset *kubernetes.Clientset, namespace, name string) error {
deploymentsClient := clientset.AppsV1().Deployments(namespace)
// Create Deployment
deletePolicy := v1.DeletePropagationForeground
@@ -220,16 +211,17 @@ func (qp *QliksensePreflight) deleteDeployment(clientset *kubernetes.Clientset,
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
}
qp.P.LogVerboseMessage("Deleted deployment: %s\n", name)
fmt.Printf("Deleted deployment: %s\n", name)
return nil
}
func (qp *QliksensePreflight) createPreflightTestService(clientset *kubernetes.Clientset, namespace string, svcName string) (*apiv1.Service, error) {
func createPreflightTestService(clientset *kubernetes.Clientset, namespace string, svcName string) (*apiv1.Service, error) {
iptr := int32Ptr(80)
servicesClient := clientset.CoreV1().Services(namespace)
service := &apiv1.Service{
@@ -257,9 +249,10 @@ func (qp *QliksensePreflight) createPreflightTestService(clientset *kubernetes.C
result, err = servicesClient.Create(service)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created service %q\n", result.GetObjectMeta().GetName())
fmt.Printf("Created service %q\n", result.GetObjectMeta().GetName())
return service, nil
}
@@ -272,13 +265,14 @@ func getService(clientset *kubernetes.Clientset, namespace, svcName string) (*ap
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 (qp *QliksensePreflight) deleteService(clientset *kubernetes.Clientset, namespace, name string) error {
func deleteService(clientset *kubernetes.Clientset, namespace, name string) error {
servicesClient := clientset.CoreV1().Services(namespace)
// Create Deployment
deletePolicy := v1.DeletePropagationForeground
@@ -291,11 +285,11 @@ func (qp *QliksensePreflight) deleteService(clientset *kubernetes.Clientset, nam
fmt.Println(err)
return err
}
qp.P.LogVerboseMessage("Deleted service: %s\n", name)
fmt.Printf("Deleted service: %s\n", name)
return nil
}
func (qp *QliksensePreflight) deletePod(clientset *kubernetes.Clientset, namespace, name string) error {
func deletePod(clientset *kubernetes.Clientset, namespace, name string) error {
podsClient := clientset.CoreV1().Pods(namespace)
deletePolicy := v1.DeletePropagationForeground
@@ -306,16 +300,17 @@ func (qp *QliksensePreflight) deletePod(clientset *kubernetes.Clientset, namespa
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
}
qp.P.LogVerboseMessage("Deleted pod: %s\n", name)
fmt.Printf("Deleted pod: %s\n", name)
return nil
}
func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames []string, commandToRun []string) (*apiv1.Pod, error) {
func createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames []string, commandToRun []string) (*apiv1.Pod, error) {
// build the pod definition we want to deploy
pod := &apiv1.Pod{
ObjectMeta: v1.ObjectMeta{
@@ -368,9 +363,10 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
pod, err = clientset.CoreV1().Pods(namespace).Create(pod)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created pod: %s\n", pod.Name)
fmt.Printf("Created pod: %s\n", pod.Name)
return pod, nil
}
@@ -435,7 +431,8 @@ func waitForDeployment(clientset *kubernetes.Clientset, namespace string, pfDepl
checkFunc := func() (interface{}, error) {
pfDeployment, err = getDeployment(clientset, namespace, depName)
if err != nil {
err = fmt.Errorf("unable to retrieve deployment: %s\n", depName)
err = fmt.Errorf("error: unable to retrieve deployment: %s\n", depName)
fmt.Println(err)
return nil, err
}
return pfDeployment, nil
@@ -448,7 +445,8 @@ func waitForDeployment(clientset *kubernetes.Clientset, namespace string, pfDepl
return err
}
if int(pfDeployment.Status.ReadyReplicas) == 0 {
err = fmt.Errorf("deployment took longer than expected to spin up pods")
err = fmt.Errorf("error: deployment took longer than expected to spin up pods")
fmt.Println(err)
return err
}
return nil
@@ -457,14 +455,16 @@ func waitForDeployment(clientset *kubernetes.Clientset, namespace string, pfDepl
func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Pod) error {
var err error
if len(pod.Spec.Containers) == 0 {
err = fmt.Errorf("there are no containers in the pod")
err = fmt.Errorf("error: there are no containers in the pod")
fmt.Println(err)
return err
}
podName := pod.Name
checkFunc := func() (interface{}, error) {
pod, err = getPod(clientset, namespace, podName)
if err != nil {
err = fmt.Errorf("unable to retrieve %s pod by name", podName)
err = fmt.Errorf("error: unable to retrieve %s pod by name", podName)
fmt.Println(err)
return nil, err
}
return pod, nil
@@ -478,7 +478,8 @@ func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Po
return err
}
if len(pod.Status.ContainerStatuses) == 0 || !pod.Status.ContainerStatuses[0].Ready {
err = fmt.Errorf("container is taking much longer than expected")
err = fmt.Errorf("error: container is taking much longer than expected")
fmt.Println(err)
return err
}
return nil
@@ -489,7 +490,8 @@ func waitForPodToDie(clientset *kubernetes.Clientset, namespace string, pod *api
checkFunc := func() (interface{}, error) {
po, err := getPod(clientset, namespace, podName)
if err != nil {
err = fmt.Errorf("unable to retrieve %s pod by name", podName)
err = fmt.Errorf("error: unable to retrieve %s pod by name", podName)
fmt.Println(err)
return nil, err
}
api.LogDebugMessage("pod status: %v\n", po.Status.Phase)
@@ -519,7 +521,8 @@ func waitForPodToDelete(clientset *kubernetes.Clientset, namespace, podName stri
if err := waitForResource(checkFunc, validateFunc); err != nil {
return nil
}
err := fmt.Errorf("delete pod is taking unusually long")
err := fmt.Errorf("error: delete pod is taking unusually long")
fmt.Println(err)
return err
}
@@ -537,11 +540,12 @@ func waitForDeploymentToDelete(clientset *kubernetes.Clientset, namespace, deplo
if err := waitForResource(checkFunc, validateFunc); err != nil {
return nil
}
err := fmt.Errorf("delete deployment is taking unusually long")
err := fmt.Errorf("error: delete deployment is taking unusually long")
fmt.Println(err)
return err
}
func (qp *QliksensePreflight) createPfRole(clientset *kubernetes.Clientset, namespace, roleName string) (*v1beta1.Role, error) {
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{
@@ -560,15 +564,16 @@ func (qp *QliksensePreflight) createPfRole(clientset *kubernetes.Clientset, name
role, err = clientset.RbacV1beta1().Roles(namespace).Create(roleSpec)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created role: %s\n", role.Name)
fmt.Printf("Created role: %s\n", role.Name)
return role, nil
}
func (qp *QliksensePreflight) deleteRole(clientset *kubernetes.Clientset, namespace string, role *v1beta1.Role) {
func deleteRole(clientset *kubernetes.Clientset, namespace string, role *v1beta1.Role) {
rolesClient := clientset.RbacV1beta1().Roles(namespace)
deletePolicy := v1.DeletePropagationForeground
@@ -579,10 +584,10 @@ func (qp *QliksensePreflight) deleteRole(clientset *kubernetes.Clientset, namesp
if err != nil {
log.Fatal(err)
}
qp.P.LogVerboseMessage("Deleted role: %s\n\n", role.Name)
fmt.Printf("Deleted role: %s\n\n", role.Name)
}
func (qp *QliksensePreflight) createPfRoleBinding(clientset *kubernetes.Clientset, namespace, roleBindingName string) (*v1beta1.RoleBinding, error) {
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{
@@ -613,13 +618,14 @@ func (qp *QliksensePreflight) createPfRoleBinding(clientset *kubernetes.Clientse
roleBinding, err = clientset.RbacV1beta1().RoleBindings(namespace).Create(roleBindingSpec)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created RoleBinding: %s\n", roleBindingSpec.Name)
fmt.Printf("Created RoleBinding: %s\n", roleBindingSpec.Name)
return roleBinding, nil
}
func (qp *QliksensePreflight) deleteRoleBinding(clientset *kubernetes.Clientset, namespace string, roleBinding *v1beta1.RoleBinding) {
func deleteRoleBinding(clientset *kubernetes.Clientset, namespace string, roleBinding *v1beta1.RoleBinding) {
roleBindingClient := clientset.RbacV1beta1().RoleBindings(namespace)
deletePolicy := v1.DeletePropagationForeground
@@ -630,10 +636,10 @@ func (qp *QliksensePreflight) deleteRoleBinding(clientset *kubernetes.Clientset,
if err != nil {
log.Fatal(err)
}
qp.P.LogVerboseMessage("Deleted RoleBinding: %s\n\n", roleBinding.Name)
fmt.Printf("Deleted RoleBinding: %s\n\n", roleBinding.Name)
}
func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clientset, namespace, serviceAccountName string) (*apiv1.ServiceAccount, error) {
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{
@@ -641,7 +647,7 @@ func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clien
Name: "preflight-check-test-serviceaccount",
Namespace: namespace,
Labels: map[string]string{
"app": "preflight",
"app": "demo",
},
},
}
@@ -651,13 +657,14 @@ func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clien
serviceAccount, err = clientset.CoreV1().ServiceAccounts(namespace).Create(serviceAccountSpec)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created Service Account: %s\n", serviceAccountSpec.Name)
fmt.Printf("Created Service Account: %s\n", serviceAccountSpec.Name)
return serviceAccount, nil
}
func (qp *QliksensePreflight) deleteServiceAccount(clientset *kubernetes.Clientset, namespace string, serviceAccount *apiv1.ServiceAccount) {
func deleteServiceAccount(clientset *kubernetes.Clientset, namespace string, serviceAccount *apiv1.ServiceAccount) {
serviceAccountClient := clientset.CoreV1().ServiceAccounts(namespace)
deletePolicy := v1.DeletePropagationForeground
@@ -668,10 +675,10 @@ func (qp *QliksensePreflight) deleteServiceAccount(clientset *kubernetes.Clients
if err != nil {
log.Fatal(err)
}
qp.P.LogVerboseMessage("Deleted ServiceAccount: %s\n\n", serviceAccount.Name)
fmt.Printf("Deleted ServiceAccount: %s\n\n", serviceAccount.Name)
}
func (qp *QliksensePreflight) createPreflightTestSecret(clientset *kubernetes.Clientset, namespace, secretName string, secretData []byte) (*apiv1.Secret, error) {
func createPreflightTestSecret(clientset *kubernetes.Clientset, namespace, secretName string, secretData []byte) (*apiv1.Secret, error) {
var secret *apiv1.Secret
var err error
// build the secret defination we want to create
@@ -693,13 +700,14 @@ func (qp *QliksensePreflight) createPreflightTestSecret(clientset *kubernetes.Cl
secret, err = clientset.CoreV1().Secrets(namespace).Create(secretSpec)
return err
}); err != nil {
fmt.Println(err)
return nil, err
}
qp.P.LogVerboseMessage("Created Secret: %s\n", secret.Name)
fmt.Printf("Created Secret: %s\n", secret.Name)
return secret, nil
}
func (qp *QliksensePreflight) deleteK8sSecret(clientset *kubernetes.Clientset, namespace string, k8sSecret *apiv1.Secret) {
func deleteK8sSecret(clientset *kubernetes.Clientset, namespace string, k8sSecret *apiv1.Secret) {
secretClient := clientset.CoreV1().Secrets(namespace)
deletePolicy := v1.DeletePropagationForeground
@@ -710,5 +718,5 @@ func (qp *QliksensePreflight) deleteK8sSecret(clientset *kubernetes.Clientset, n
if err != nil {
log.Fatal(err)
}
qp.P.LogVerboseMessage("Deleted Secret: %s\n", k8sSecret.Name)
fmt.Printf("Deleted Secret: %s\n\n", k8sSecret.Name)
}

View File

@@ -5,7 +5,6 @@ import (
"path/filepath"
"strings"
"github.com/pkg/errors"
"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"
@@ -15,37 +14,34 @@ var resultYamlBytes = []byte("")
func (qp *QliksensePreflight) CheckCreateRole(namespace string) error {
// create a Role
qp.P.LogVerboseMessage("Preflight role check: \n")
qp.P.LogVerboseMessage("--------------------- \n")
fmt.Printf("Preflight role check: \n")
err := qp.checkCreateEntity(namespace, "Role")
if err != nil {
return err
}
qp.P.LogVerboseMessage("Completed preflight role check\n")
fmt.Println("Completed preflight role check")
return nil
}
func (qp *QliksensePreflight) CheckCreateRoleBinding(namespace string) error {
// create a RoleBinding
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
qp.P.LogVerboseMessage("---------------------------- \n")
fmt.Printf("Preflight rolebinding check: \n")
err := qp.checkCreateEntity(namespace, "RoleBinding")
if err != nil {
return err
}
qp.P.LogVerboseMessage("Completed preflight rolebinding check\n")
fmt.Println("Completed preflight rolebinding check")
return nil
}
func (qp *QliksensePreflight) CheckCreateServiceAccount(namespace string) error {
// create a service account
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
qp.P.LogVerboseMessage("------------------------------- \n")
fmt.Printf("Preflight serviceaccount check: \n")
err := qp.checkCreateEntity(namespace, "ServiceAccount")
if err != nil {
return err
}
qp.P.LogVerboseMessage("Completed preflight serviceaccount check\n")
fmt.Println("Completed preflight serviceaccount check")
return nil
}
func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string) error {
@@ -56,13 +52,13 @@ func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string)
var err error
currentCR, err = qConfig.GetCurrentCR()
if err != nil {
qp.P.LogVerboseMessage("Unable to retrieve current CR: %v\n", err)
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 {
qp.P.LogVerboseMessage("Unable to Download from git repo to tmp dir: %v\n", err)
fmt.Printf("Unable to Download from git repo to tmp dir: %v\n", err)
return err
} else {
mfroot = tempDownloadedDir
@@ -76,7 +72,8 @@ func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string)
if len(resultYamlBytes) == 0 {
resultYamlBytes, err = qliksense.ExecuteKustomizeBuild(kusDir)
if err != nil {
err := fmt.Errorf("Unable to retrieve manifests from executing kustomize: %s, error: %v", kusDir, err)
err := fmt.Errorf("Unable to retrieve manifests from executing kustomize from dir: %s", kusDir)
fmt.Println(err)
return err
}
}
@@ -84,74 +81,58 @@ func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string)
if sa != "" {
sa = strings.Replace(sa, "name: qliksense", "name: preflight", -1)
} else {
err := fmt.Errorf("Unable to retrieve yamls to apply on cluster from dir: %s, error: %v", kusDir, err)
err := fmt.Errorf("Unable to retrieve yamls to apply on cluster from dir: %s", kusDir)
fmt.Println(err)
return err
}
namespace = "" // namespace is handled when generating the manifests
defer func() {
qp.P.LogVerboseMessage("Cleaning up resources...\n")
err := api.KubectlDeleteVerbose(sa, namespace, qp.P.Verbose)
fmt.Println("Cleaning up resources")
api.KubectlDelete(sa, namespace)
if err != nil {
qp.P.LogVerboseMessage("Preflight cleanup failed!\n")
fmt.Println("Preflight cleanup failed!")
}
}()
err = api.KubectlApplyVerbose(sa, namespace, qp.P.Verbose)
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
}
qp.P.LogVerboseMessage("Preflight %s check: PASSED\n", entityToTest)
fmt.Printf("Preflight %s check: PASSED\n", entityToTest)
return nil
}
func (qp *QliksensePreflight) CheckCreateRB(namespace string, kubeConfigContents []byte) error {
// create a role
qp.P.LogVerboseMessage("Preflight createRole check: \n")
qp.P.LogVerboseMessage("--------------------------- \n")
errStr := strings.Builder{}
err1 := qp.checkCreateEntity(namespace, "Role")
if err1 != nil {
errStr.WriteString(err1.Error())
errStr.WriteString("\n")
qp.P.LogVerboseMessage("%v\n", err1)
qp.P.LogVerboseMessage("Preflight role check: FAILED\n")
fmt.Printf("Preflight createRole check: \n")
err := qp.checkCreateEntity(namespace, "Role")
if err != nil {
fmt.Println("Preflight role check: FAILED")
}
qp.P.LogVerboseMessage("Completed preflight role check\n\n")
fmt.Printf("Completed preflight role check\n\n")
// create a roleBinding
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
qp.P.LogVerboseMessage("---------------------------- \n")
err2 := qp.checkCreateEntity(namespace, "RoleBinding")
if err2 != nil {
errStr.WriteString(err2.Error())
errStr.WriteString("\n")
qp.P.LogVerboseMessage("%v\n", err2)
qp.P.LogVerboseMessage("Preflight rolebinding check: FAILED\n")
fmt.Printf("Preflight rolebinding check: \n")
err = qp.checkCreateEntity(namespace, "RoleBinding")
if err != nil {
fmt.Println("Preflight rolebinding check: FAILED")
}
qp.P.LogVerboseMessage("Completed preflight rolebinding check\n\n")
fmt.Printf("Completed preflight rolebinding check\n\n")
// create a service account
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
qp.P.LogVerboseMessage("------------------------------- \n")
err3 := qp.checkCreateEntity(namespace, "ServiceAccount")
if err3 != nil {
errStr.WriteString(err3.Error())
errStr.WriteString("\n")
qp.P.LogVerboseMessage("%v\n", err3)
qp.P.LogVerboseMessage("Preflight serviceaccount check: FAILED\n")
fmt.Printf("Preflight serviceaccount check: \n")
err = qp.checkCreateEntity(namespace, "ServiceAccount")
if err != nil {
fmt.Println("Preflight serviceaccount check: FAILED")
}
qp.P.LogVerboseMessage("Completed preflight serviceaccount check\n\n")
fmt.Printf("Completed preflight serviceaccount check\n\n")
if err1 != nil || err2 != nil || err3 != nil {
qp.P.LogVerboseMessage("Preflight authcheck: FAILED\n")
qp.P.LogVerboseMessage("Completed preflight authcheck\n")
return errors.New(errStr.String())
}
qp.P.LogVerboseMessage("Preflight authcheck: PASSED\n")
qp.P.LogVerboseMessage("Completed preflight authcheck\n")
fmt.Println("Preflight RB check: PASSED")
fmt.Println("Completed preflight CreateRB check")
return nil
}

View File

@@ -4,13 +4,11 @@ import (
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/qlik-oss/sense-installer/pkg/api"
"k8s.io/apimachinery/pkg/version"
)
func (qp *QliksensePreflight) CheckK8sVersion(namespace string, kubeConfigContents []byte) error {
qp.P.LogVerboseMessage("Preflight kubernetes version check: \n")
qp.P.LogVerboseMessage("----------------------------------- \n")
var currentVersion *semver.Version
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
@@ -24,29 +22,35 @@ func (qp *QliksensePreflight) CheckK8sVersion(namespace string, kubeConfigConten
return err
}); err != nil {
err = fmt.Errorf("Unable to get server version: %v\n", err)
//fmt.Println(err)
return err
}
qp.P.LogVerboseMessage("Kubernetes API Server version: %s\n", serverVersion.String())
fmt.Printf("Kubernetes API Server version: %s\n", serverVersion.String())
// 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
}
api.LogDebugMessage("Current Kubernetes Version: %v\n", currentVersion)
//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
}
if currentVersion.GreaterThan(minK8sVersionSemver) {
qp.P.LogVerboseMessage("Current Kubernetes API Server version %s is greater than or equal to minimum required version: %s\n", currentVersion, 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 {
err = fmt.Errorf("Current Kubernetes API Server version %s is less than minimum required version: %s", currentVersion, minK8sVersionSemver)
return err
fmt.Printf("Current %s is less than minimum required version:%s\n", currentVersion, minK8sVersionSemver)
fmt.Println("Preflight minimum kubernetes version check: FAILED")
}
fmt.Printf("Completed Preflight kubernetes minimum version check\n")
return nil
}

View File

@@ -80,14 +80,9 @@ func fetchAndUpdateCR(qConfig *qapi.QliksenseConfig, version string) error {
}
if version == "" {
if qcr.GetLabelFromCr("version") == "" {
if encKey, err := qConfig.GetEncryptionKeyFor(qcr.GetName()); err != nil {
return err
} else if version, err = getLatestTag(qcr.GetFetchUrl(), qcr.GetFetchAccessToken(encKey)); err != nil {
return err
}
} else {
version = qcr.GetLabelFromCr("version")
return errors.New("Cannot find gitref/tag/branch/version to fetch")
}
version = qcr.GetLabelFromCr("version")
}
encKey, err := qConfig.GetEncryptionKeyFor(qcr.GetName())
if err != nil {

View File

@@ -32,19 +32,4 @@ func TestFetchAndUpdateCR(t *testing.T) {
t.Log("actual path: " + cr.Spec.ManifestsRoot + ", expected path: contexts/test1/qlik-k8s/v0.0.2")
t.FailNow()
}
//testing latest tag is fetched
cr.AddLabelToCr("version", "")
qConfig.WriteCR(cr)
err := fetchAndUpdateCR(qConfig, "")
if err != nil {
t.Log(err)
t.Fail()
}
cr = &qapi.QliksenseCR{}
qapi.ReadFromFile(cr, actualCrFile)
v := cr.GetLabelFromCr("version")
if v == "" || v == "v0.0.2" {
t.Log("should get latest but got version: " + v)
t.Fail()
}
}

View File

@@ -4,7 +4,6 @@ import (
"errors"
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/qlik-oss/k-apis/pkg/git"
qapi "github.com/qlik-oss/sense-installer/pkg/api"
)
@@ -87,69 +86,3 @@ func (q *Qliksense) GetInstallableVersions(opts *LsRemoteCmdOptions) error {
return nil
}
func getLatestTag(repoUrl, accessToken string) (string, error) {
if repoUrl == "" {
return "", errors.New("repo url is empty")
}
repoPath, err := fetchToTempDir(repoUrl, "master", accessToken)
if err != nil {
return "", err
}
r, err := git.OpenRepository(repoPath)
if err != nil {
return "", err
}
remoteRefsList, err := git.GetRemoteRefs(r, nil,
&git.RemoteRefConstraints{
Include: true,
Sort: true,
SortOrder: git.RefSortOrderDescending,
},
&git.RemoteRefConstraints{
Include: false,
Sort: true,
SortOrder: git.RefSortOrderAscending,
})
if err != nil {
return "", err
}
if len(remoteRefsList) < 1 {
return "", errors.New("cannot find git remote information in the config repository")
}
var originRemoteRefs *git.RemoteRefs
for _, remoteRefs := range remoteRefsList {
if remoteRefs.Name == "origin" {
originRemoteRefs = remoteRefs
break
}
}
if originRemoteRefs == nil {
return "", errors.New(`cannot find git remote called "origin" in the config repository`)
}
tags := originRemoteRefs.Tags
if len(tags) == 0 {
return "", errors.New(("no tags exists in the repo: " + repoPath))
}
maxSem, _ := semver.NewVersion(tags[0])
for _, sv := range tags[1:] {
if sv == "" {
continue
}
v, err := semver.NewVersion(sv)
if err != nil {
// it may happen, in the repo some tags may not conform to semver
fmt.Print("Unconform tags: " + sv)
continue
}
if maxSem == nil || maxSem.LessThan(v) {
maxSem = v
}
}
return maxSem.Original(), nil
}

View File

@@ -1,25 +0,0 @@
package qliksense
import (
"testing"
"github.com/Masterminds/semver/v3"
)
func TestGetLatestTag(t *testing.T) {
s, err := getLatestTag(defaultConfigRepoGitUrl, "")
if s == "" || err != nil {
t.Log(err)
t.Fail()
}
sv, err := semver.NewVersion(s)
if err != nil {
t.Log(err)
t.Log(sv)
}
baseV, _ := semver.NewVersion("v0.0.7")
if !sv.GreaterThan(baseV) {
t.Log("Expected greater than v0.0.7, but got: " + s)
t.Fail()
}
}

View File

@@ -109,16 +109,11 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
if dcr, err := qConfig.GetDecryptedCr(qcr); err != nil {
return err
} else if err := q.applyConfigToK8s(dcr); err != nil {
fmt.Println("cannot do kubectl apply on manifests")
return err
} else {
if IsQliksenseInstalled(dcr.GetName()) {
return q.UpgradeQK8s(keepPatchFiles)
}
if err := q.applyConfigToK8s(dcr); err != nil {
fmt.Println("cannot do kubectl apply on manifests")
return err
} else {
return q.applyCR(dcr)
}
return q.applyCR(dcr)
}
}