Compare commits
17 Commits
export_fun
...
v0.22.0
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ec8a9376e7 | ||
|
|
bcc321e180 | ||
|
|
0aabf63715 | ||
|
|
c9ca5c8be0 | ||
|
|
9d0ac0290f | ||
|
|
dd8a48b2b8 | ||
|
|
9fb6800993 | ||
|
|
bbb811a879 | ||
|
|
8156b884ce | ||
|
|
7525c2e698 | ||
|
|
60763e034a | ||
|
|
ce4081a422 | ||
|
|
dd503a40c1 | ||
|
|
b790419fc2 | ||
|
|
55f9c07c21 | ||
|
|
ef77ea3a5f | ||
|
|
7f70bfc7de |
@@ -37,7 +37,7 @@ func applyCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
||||||
c.MarkFlagRequired("file")
|
c.MarkFlagRequired("file")
|
||||||
f.StringVarP(&opts.StorageClass, "storageClass", "s", "", "Storage class for qliksense")
|
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.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.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.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
|
||||||
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
|
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
|
||||||
|
|||||||
@@ -220,3 +220,27 @@ func cleanConfigRepoPatchesCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func unsetCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||||
|
cmd := &cobra.Command{
|
||||||
|
Use: "unset",
|
||||||
|
Short: "remove a key from a context or a secrets or a configs from the context",
|
||||||
|
Example: `
|
||||||
|
# remove the key from CR
|
||||||
|
qliksense config unset <key>
|
||||||
|
|
||||||
|
# remove the key from service inside configs/secrets of CR
|
||||||
|
qliksense config unset <service>.<key>
|
||||||
|
|
||||||
|
# remove the service from inside configs/secrets of CR
|
||||||
|
qliksense config usnet <servcie>
|
||||||
|
|
||||||
|
all of the above supports space separated multiple arguments
|
||||||
|
`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
return q.UnsetCmd(args)
|
||||||
|
},
|
||||||
|
Args: cobra.MinimumNArgs(1),
|
||||||
|
}
|
||||||
|
return cmd
|
||||||
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ func (e *eulaPreRunHooksT) getPostValidationArtifact(artifactName string) interf
|
|||||||
var eulaEnforced = os.Getenv("QLIKSENSE_EULA_ENFORCE") == "true"
|
var eulaEnforced = os.Getenv("QLIKSENSE_EULA_ENFORCE") == "true"
|
||||||
var eulaText = "Please read the end user license agreement at: https://www.qlik.com/us/legal/license-terms"
|
var eulaText = "Please read the end user license agreement at: https://www.qlik.com/us/legal/license-terms"
|
||||||
var eulaPrompt = "Do you accept our EULA? (y/n): "
|
var eulaPrompt = "Do you accept our EULA? (y/n): "
|
||||||
var eulaErrorInstruction = `You must enter "y" to continue`
|
var eulaErrorInstruction = `You must enter "y" to continue or execute the command with the acceptEULA flag set to "yes"`
|
||||||
var eulaPreRunHooks = eulaPreRunHooksT{
|
var eulaPreRunHooks = eulaPreRunHooksT{
|
||||||
validators: make(map[string]func(cmd *cobra.Command, q *qliksense.Qliksense) (bool, error)),
|
validators: make(map[string]func(cmd *cobra.Command, q *qliksense.Qliksense) (bool, error)),
|
||||||
postValidationArtifacts: make(map[string]interface{}),
|
postValidationArtifacts: make(map[string]interface{}),
|
||||||
@@ -54,7 +54,10 @@ func commandAlwaysRequiresEulaAcceptance(commandName string) bool {
|
|||||||
|
|
||||||
func globalEulaPreRun(cmd *cobra.Command, q *qliksense.Qliksense) {
|
func globalEulaPreRun(cmd *cobra.Command, q *qliksense.Qliksense) {
|
||||||
if isEulaEnforced(cmd.CommandPath()) {
|
if isEulaEnforced(cmd.CommandPath()) {
|
||||||
if strings.TrimSpace(strings.ToLower(cmd.Flag("acceptEULA").Value.String())) != "yes" {
|
eulaFlagValue := strings.TrimSpace(strings.ToLower(cmd.Flag("acceptEULA").Value.String()))
|
||||||
|
if eulaFlagValue != "" && eulaFlagValue != "yes" {
|
||||||
|
doEnforceEula()
|
||||||
|
} else if eulaFlagValue == "" {
|
||||||
if eulaPreRunHook := eulaPreRunHooks.getValidator(cmd.CommandPath()); eulaPreRunHook != nil {
|
if eulaPreRunHook := eulaPreRunHooks.getValidator(cmd.CommandPath()); eulaPreRunHook != nil {
|
||||||
if eulaAccepted, err := eulaPreRunHook(cmd, q); err != nil {
|
if eulaAccepted, err := eulaPreRunHook(cmd, q); err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -61,9 +61,9 @@ func installCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if filePath != "" {
|
if filePath != "" {
|
||||||
return loadOrApplyCommandEulaPreRunHook(cmd, q)
|
return loadOrApplyCommandEulaPreRunHook(cmd, q)
|
||||||
} else if qConfig, err := qapi.NewQConfigE(q.QliksenseHome); err != nil {
|
} else if qConfig, err := qapi.NewQConfigE(q.QliksenseHome); err != nil {
|
||||||
return false, err
|
return false, nil
|
||||||
} else if qcr, err := qConfig.GetCurrentCR(); err != nil {
|
} else if qcr, err := qConfig.GetCurrentCR(); err != nil {
|
||||||
return false, err
|
return false, nil
|
||||||
} else {
|
} else {
|
||||||
return qcr.IsEULA(), nil
|
return qcr.IsEULA(), nil
|
||||||
}
|
}
|
||||||
@@ -71,11 +71,13 @@ func installCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
|
|
||||||
f := c.Flags()
|
f := c.Flags()
|
||||||
f.StringVarP(&opts.StorageClass, "storageClass", "s", "", "Storage class for qliksense")
|
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.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.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.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
|
||||||
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
||||||
|
|
||||||
|
f.BoolVarP(&opts.DryRun, "dry-run", "", false, "Dry run will generate the patches without rotating keys")
|
||||||
|
|
||||||
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
|
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
|
||||||
f.BoolVarP(&push, pushFlagName, pushFlagShorthand, push, pushFlagUsage)
|
f.BoolVarP(&push, pushFlagName, pushFlagShorthand, push, pushFlagUsage)
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,26 @@ package main
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
. "github.com/logrusorgru/aurora"
|
||||||
ansi "github.com/mattn/go-colorable"
|
ansi "github.com/mattn/go-colorable"
|
||||||
"github.com/qlik-oss/sense-installer/pkg/preflight"
|
"github.com/qlik-oss/sense-installer/pkg/preflight"
|
||||||
. "github.com/logrusorgru/aurora"
|
|
||||||
|
|
||||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
)
|
)
|
||||||
|
|
||||||
func preflightCmd(q *qliksense.Qliksense) *cobra.Command {
|
func preflightCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||||
|
preflightOpts := &preflight.PreflightOptions{
|
||||||
|
MongoOptions: &preflight.MongoOptions{},
|
||||||
|
}
|
||||||
var preflightCmd = &cobra.Command{
|
var preflightCmd = &cobra.Command{
|
||||||
Use: "preflight",
|
Use: "preflight",
|
||||||
Short: "perform preflight checks on the cluster",
|
Short: "perform preflight checks on the cluster",
|
||||||
Long: `perform preflight checks on the cluster`,
|
Long: `perform preflight checks on the cluster`,
|
||||||
Example: `qliksense preflight <preflight_check_to_run>`,
|
Example: `qliksense preflight <preflight_check_to_run>`,
|
||||||
}
|
}
|
||||||
|
f := preflightCmd.Flags()
|
||||||
|
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||||
return preflightCmd
|
return preflightCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +49,7 @@ func pfDnsCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
if err = qp.CheckDns(namespace, kubeConfigContents); err != nil {
|
if err = qp.CheckDns(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight DNS check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight DNS check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -131,12 +136,7 @@ func pfAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
f := preflightAllChecksCmd.Flags()
|
f := preflightAllChecksCmd.Flags()
|
||||||
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
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.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.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?")
|
|
||||||
|
|
||||||
return preflightAllChecksCmd
|
return preflightAllChecksCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -147,7 +147,7 @@ func pfDeploymentCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
}
|
}
|
||||||
var pfDeploymentCheckCmd = &cobra.Command{
|
var pfDeploymentCheckCmd = &cobra.Command{
|
||||||
Use: "deployment",
|
Use: "deployment",
|
||||||
Short: "perform preflight deploymwnt check",
|
Short: "perform preflight deployment check",
|
||||||
Long: `perform preflight deployment check to ensure that we can create deployments in the cluster`,
|
Long: `perform preflight deployment check to ensure that we can create deployments in the cluster`,
|
||||||
Example: `qliksense preflight deployment`,
|
Example: `qliksense preflight deployment`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@@ -163,7 +163,7 @@ func pfDeploymentCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
if err = qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
|
if err = qp.CheckDeployment(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight deployment check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight deployment check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -202,7 +202,7 @@ func pfServiceCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
if err = qp.CheckService(namespace, kubeConfigContents); err != nil {
|
if err = qp.CheckService(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight service check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight service check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -240,7 +240,7 @@ func pfPodCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
if err = qp.CheckPod(namespace, kubeConfigContents); err != nil {
|
if err = qp.CheckPod(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight pod check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight pod check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -275,7 +275,7 @@ func pfCreateRoleCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err = qp.CheckCreateRole(namespace); err != nil {
|
if err = qp.CheckCreateRole(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight role check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight role check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -310,7 +310,7 @@ func pfCreateRoleBindingCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err = qp.CheckCreateRoleBinding(namespace); err != nil {
|
if err = qp.CheckCreateRoleBinding(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight rolebinding check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight rolebinding check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -332,7 +332,7 @@ func pfCreateServiceAccountCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
|
|
||||||
var preflightServiceAccountCmd = &cobra.Command{
|
var preflightServiceAccountCmd = &cobra.Command{
|
||||||
Use: "serviceaccount",
|
Use: "serviceaccount",
|
||||||
Short: "preflight create ServiceAccount check",
|
Short: "preflight create serviceaccount check",
|
||||||
Long: `perform preflight serviceaccount check to ensure we are able to create a service account in the cluster`,
|
Long: `perform preflight serviceaccount check to ensure we are able to create a service account in the cluster`,
|
||||||
Example: `qliksense preflight serviceaccount`,
|
Example: `qliksense preflight serviceaccount`,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
@@ -345,7 +345,7 @@ func pfCreateServiceAccountCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
if err = qp.CheckCreateServiceAccount(namespace); err != nil {
|
if err = qp.CheckCreateServiceAccount(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight ServiceAccount check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight ServiceAccount check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -417,7 +417,7 @@ func pfMongoCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
if namespace == "" {
|
if namespace == "" {
|
||||||
namespace = "default"
|
namespace = "default"
|
||||||
}
|
}
|
||||||
if err = qp.CheckMongo(kubeConfigContents, namespace, preflightOpts); err != nil {
|
if err = qp.CheckMongo(kubeConfigContents, namespace, preflightOpts, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight mongo check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight mongo check FAILED"))
|
||||||
fmt.Printf("Error: %v\n", err)
|
fmt.Printf("Error: %v\n", err)
|
||||||
return nil
|
return nil
|
||||||
@@ -429,10 +429,45 @@ func pfMongoCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
|||||||
f := preflightMongoCmd.Flags()
|
f := preflightMongoCmd.Flags()
|
||||||
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||||
f.StringVarP(&preflightOpts.MongoOptions.MongodbUrl, "url", "", "", "mongodbUrl to try connecting to")
|
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.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?")
|
|
||||||
return preflightMongoCmd
|
return preflightMongoCmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func pfCleanupCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||||
|
out := ansi.NewColorableStdout()
|
||||||
|
preflightOpts := &preflight.PreflightOptions{
|
||||||
|
MongoOptions: &preflight.MongoOptions{},
|
||||||
|
}
|
||||||
|
|
||||||
|
var pfCleanCmd = &cobra.Command{
|
||||||
|
Use: "clean",
|
||||||
|
Short: "perform preflight clean",
|
||||||
|
Long: `perform preflight clean to ensure that all resources are cleared up in the cluster`,
|
||||||
|
Example: `qliksense preflight clean`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
qp := &preflight.QliksensePreflight{Q: q, P: preflightOpts}
|
||||||
|
|
||||||
|
// Preflight clean
|
||||||
|
namespace, kubeConfigContents, err := preflight.InitPreflight()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Fprintf(out, "%s\n", Red("Preflight cleanup FAILED"))
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if namespace == "" {
|
||||||
|
namespace = "default"
|
||||||
|
}
|
||||||
|
if err = qp.Cleanup(namespace, kubeConfigContents); err != nil {
|
||||||
|
fmt.Fprintf(out, "%s\n", Red("Preflight cleanup FAILED"))
|
||||||
|
fmt.Printf("Error: %v\n", err)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
fmt.Fprintf(out, "%s\n", Green("Preflight cleanup complete"))
|
||||||
|
return nil
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f := pfCleanCmd.Flags()
|
||||||
|
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||||
|
return pfCleanCmd
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
. "github.com/logrusorgru/aurora"
|
||||||
ansi "github.com/mattn/go-colorable"
|
ansi "github.com/mattn/go-colorable"
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/qlik-oss/sense-installer/pkg"
|
"github.com/qlik-oss/sense-installer/pkg"
|
||||||
@@ -15,7 +16,6 @@ import (
|
|||||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||||
"github.com/spf13/cobra"
|
"github.com/spf13/cobra"
|
||||||
"github.com/spf13/viper"
|
"github.com/spf13/viper"
|
||||||
. "github.com/logrusorgru/aurora"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// To run this project in debug mode, run:
|
// To run this project in debug mode, run:
|
||||||
@@ -46,7 +46,7 @@ func initAndExecute() error {
|
|||||||
log.Fatal(err)
|
log.Fatal(err)
|
||||||
}
|
}
|
||||||
// create dirs and appropriate files for setting up contexts
|
// create dirs and appropriate files for setting up contexts
|
||||||
api.LogDebugMessage("QliksenseHomeDir: %s", qlikSenseHome)
|
api.LogDebugMessage("QliksenseHomeDir: %s\n", qlikSenseHome)
|
||||||
|
|
||||||
qliksenseClient := qliksense.New(qlikSenseHome)
|
qliksenseClient := qliksense.New(qlikSenseHome)
|
||||||
cmd := rootCmd(qliksenseClient)
|
cmd := rootCmd(qliksenseClient)
|
||||||
@@ -122,6 +122,7 @@ func getRootCmd(p *qliksense.Qliksense) *cobra.Command {
|
|||||||
globalEulaPostRun(cmd, p)
|
globalEulaPostRun(cmd, p)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
SilenceUsage: true,
|
||||||
}
|
}
|
||||||
origHelpFunc := cmd.HelpFunc()
|
origHelpFunc := cmd.HelpFunc()
|
||||||
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
|
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
|
||||||
@@ -195,10 +196,13 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
|||||||
|
|
||||||
// add clean-config-repo-patches command as a sub-command to the app config sub-command
|
// add clean-config-repo-patches command as a sub-command to the app config sub-command
|
||||||
configCmd.AddCommand(cleanConfigRepoPatchesCmd(p))
|
configCmd.AddCommand(cleanConfigRepoPatchesCmd(p))
|
||||||
|
|
||||||
|
|
||||||
// open editor for config
|
// open editor for config
|
||||||
configCmd.AddCommand(configEditCmd(p))
|
configCmd.AddCommand(configEditCmd(p))
|
||||||
|
|
||||||
|
// add unset for config
|
||||||
|
configCmd.AddCommand((unsetCmd(p)))
|
||||||
|
|
||||||
// add uninstall command
|
// add uninstall command
|
||||||
cmd.AddCommand(uninstallCmd(p))
|
cmd.AddCommand(uninstallCmd(p))
|
||||||
|
|
||||||
@@ -220,6 +224,7 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
|||||||
preflightCmd.AddCommand(pfCreateRoleBindingCheckCmd(p))
|
preflightCmd.AddCommand(pfCreateRoleBindingCheckCmd(p))
|
||||||
preflightCmd.AddCommand(pfCreateServiceAccountCheckCmd(p))
|
preflightCmd.AddCommand(pfCreateServiceAccountCheckCmd(p))
|
||||||
preflightCmd.AddCommand(pfCreateAuthCheckCmd(p))
|
preflightCmd.AddCommand(pfCreateAuthCheckCmd(p))
|
||||||
|
preflightCmd.AddCommand(pfCleanupCmd(p))
|
||||||
|
|
||||||
cmd.AddCommand(preflightCmd)
|
cmd.AddCommand(preflightCmd)
|
||||||
cmd.AddCommand(loadCrFile(p))
|
cmd.AddCommand(loadCrFile(p))
|
||||||
|
|||||||
@@ -23,6 +23,12 @@ Run the following command to execute a specific check
|
|||||||
qliksense preflight dns
|
qliksense preflight dns
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Running cleanup
|
||||||
|
Run the following command to cleanup entities created for preflight checks that were left behind on the cluster.
|
||||||
|
```
|
||||||
|
qliksense preflight clean
|
||||||
|
```
|
||||||
|
|
||||||
### qliksense load
|
### qliksense load
|
||||||
|
|
||||||
`qliksense load` command takes input from a file or from pipe
|
`qliksense load` command takes input from a file or from pipe
|
||||||
@@ -57,7 +63,7 @@ spec:
|
|||||||
value: "yes"
|
value: "yes"
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: mongodb://qlik-test-mongodb:27017/qliksense?ssl=false
|
value: mongodb://qlik-test-mongodb:27017/qliksense?ssl=false
|
||||||
profile: docker-desktop
|
profile: docker-desktop
|
||||||
rotateKeys: "yes"
|
rotateKeys: "yes"
|
||||||
@@ -98,7 +104,7 @@ spec:
|
|||||||
value: "yes"
|
value: "yes"
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: "mongo://mongo:3307"
|
value: "mongo://mongo:3307"
|
||||||
- name: messagingPassword
|
- name: messagingPassword
|
||||||
valueFromKey: messagingPassword
|
valueFromKey: messagingPassword
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ spec:
|
|||||||
profile: docker-desktop
|
profile: docker-desktop
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||||
rotateKeys: "yes"
|
rotateKeys: "yes"
|
||||||
releaseName: qlik-default
|
releaseName: qlik-default
|
||||||
|
|||||||
@@ -16,19 +16,29 @@ Examples:
|
|||||||
qliksense preflight <preflight_check_to_run>
|
qliksense preflight <preflight_check_to_run>
|
||||||
|
|
||||||
Available Commands:
|
Available Commands:
|
||||||
all perform all checks
|
all perform all checks
|
||||||
dns perform preflight dns check
|
authcheck preflight authcheck
|
||||||
k8s-version check k8s version
|
clean perform preflight clean
|
||||||
|
deployment perform preflight deployment check
|
||||||
|
dns perform preflight dns check
|
||||||
|
kube-version check kubernetes version
|
||||||
|
mongo preflight mongo OR preflight mongo --url=<url>
|
||||||
|
pod perform preflight pod check
|
||||||
|
role preflight create role check
|
||||||
|
rolebinding preflight create rolebinding check
|
||||||
|
service perform preflight service check
|
||||||
|
serviceaccount preflight create ServiceAccount check
|
||||||
|
|
||||||
Flags:
|
Flags:
|
||||||
-h, --help help for preflight
|
-h, --help help for preflight
|
||||||
|
-v, --verbose verbose mode
|
||||||
```
|
```
|
||||||
|
|
||||||
### DNS check
|
### DNS check
|
||||||
Run the following command to perform preflight DNS check. We setup a kubernetes deployment and try to reach it as part of establishing DNS connectivity in this check.
|
Run the following command to perform preflight DNS check. We setup a kubernetes deployment and try to reach it as part of establishing DNS connectivity in this check.
|
||||||
The expected output should be similar to the one shown below.
|
The expected output should be similar to the one shown below.
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight dns
|
$ qliksense preflight dns -v
|
||||||
|
|
||||||
Preflight DNS check
|
Preflight DNS check
|
||||||
---------------------
|
---------------------
|
||||||
@@ -51,7 +61,7 @@ Deleted deployment: dep-dns-preflight-check
|
|||||||
We check the version of the target kubernetes cluster and ensure that it falls in the valid range of kubernetes versions that are supported by qliksense.
|
We check the version of the target kubernetes cluster and ensure that it falls in the valid range of kubernetes versions that are supported by qliksense.
|
||||||
The command to run this check and the expected similar output are as shown below:
|
The command to run this check and the expected similar output are as shown below:
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight k8s-version
|
$ qliksense preflight k8s-version -v
|
||||||
|
|
||||||
Preflight kubernetes minimum version check
|
Preflight kubernetes minimum version check
|
||||||
------------------------------------------
|
------------------------------------------
|
||||||
@@ -66,7 +76,7 @@ Completed Preflight kubernetes minimum version check
|
|||||||
### Service check
|
### Service check
|
||||||
We use the commmand below to test if we are able to create a service in the cluster.
|
We use the commmand below to test if we are able to create a service in the cluster.
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight service
|
$ qliksense preflight service -v
|
||||||
|
|
||||||
Preflight service check
|
Preflight service check
|
||||||
-----------------------
|
-----------------------
|
||||||
@@ -82,7 +92,7 @@ Completed preflight service check
|
|||||||
### Deployment 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.
|
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.
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight deployment
|
$ qliksense preflight deployment -v
|
||||||
|
|
||||||
Preflight deployment check
|
Preflight deployment check
|
||||||
-----------------------
|
-----------------------
|
||||||
@@ -97,7 +107,7 @@ Completed preflight deployment check
|
|||||||
### Pod check
|
### Pod check
|
||||||
We use the commmand below to test if we are able to create a pod in the cluster.
|
We use the commmand below to test if we are able to create a pod in the cluster.
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight pod
|
$ qliksense preflight pod -v
|
||||||
|
|
||||||
Preflight pod check
|
Preflight pod check
|
||||||
--------------------
|
--------------------
|
||||||
@@ -110,61 +120,61 @@ Deleted pod: pod-pf-check
|
|||||||
Completed preflight pod check
|
Completed preflight pod check
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create-Role check
|
### Role check
|
||||||
We use the command below to test if we are able to create a role in the cluster
|
We use the command below to test if we are able to create a role in the cluster
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight create-role
|
$ qliksense preflight role -v
|
||||||
Preflight create-role check
|
Preflight role check
|
||||||
---------------------------
|
---------------------------
|
||||||
Preflight create-role check:
|
Preflight role check:
|
||||||
Created role: role-preflight-check
|
Created role: role-preflight-check
|
||||||
Preflight create-role check: PASSED
|
Preflight role check: PASSED
|
||||||
Cleaning up resources...
|
Cleaning up resources...
|
||||||
Deleted role: role-preflight-check
|
Deleted role: role-preflight-check
|
||||||
|
|
||||||
Completed preflight create-role check
|
Completed preflight role check
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create-RoleBinding check
|
### RoleBinding check
|
||||||
We use the command below to test if we are able to create a role binding in the cluster
|
We use the command below to test if we are able to create a role binding in the cluster
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight createRoleBinding
|
$ qliksense preflight rolebinding -v
|
||||||
|
|
||||||
Preflight create roleBinding check
|
Preflight rolebinding check
|
||||||
---------------------------
|
---------------------------
|
||||||
Preflight createRoleBinding check:
|
Preflight rolebinding check:
|
||||||
Created RoleBinding: role-binding-preflight-check
|
Created RoleBinding: role-binding-preflight-check
|
||||||
Preflight createRoleBinding check: PASSED
|
Preflight rolebinding check: PASSED
|
||||||
Cleaning up resources...
|
Cleaning up resources...
|
||||||
Deleting RoleBinding: role-binding-preflight-check
|
Deleting RoleBinding: role-binding-preflight-check
|
||||||
Deleted RoleBinding: role-binding-preflight-check
|
Deleted RoleBinding: role-binding-preflight-check
|
||||||
|
|
||||||
Completed preflight createRoleBinding check
|
Completed preflight rolebinding check
|
||||||
```
|
```
|
||||||
|
|
||||||
### Create-ServiceAccount check
|
### Create-ServiceAccount check
|
||||||
We use the command below to test if we are able to create a service account in the cluster
|
We use the command below to test if we are able to create a service account in the cluster
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight createServiceAccount
|
$ qliksense preflight serviceaccount -v
|
||||||
|
|
||||||
Preflight create ServiceAccount check
|
Preflight ServiceAccount check
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
Preflight createServiceAccount check:
|
Preflight serviceaccount check:
|
||||||
Created Service Account: preflight-check-test-serviceaccount
|
Created Service Account: preflight-check-test-serviceaccount
|
||||||
Preflight createServiceAccount check: PASSED
|
Preflight serviceaccount check: PASSED
|
||||||
Cleaning up resources...
|
Cleaning up resources...
|
||||||
Deleting ServiceAccount: preflight-check-test-serviceaccount
|
Deleting ServiceAccount: preflight-check-test-serviceaccount
|
||||||
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
||||||
|
|
||||||
Completed preflight createServiceAccount check
|
Completed preflight serviceaccount check
|
||||||
```
|
```
|
||||||
|
|
||||||
### CreateRB check
|
### Auth check
|
||||||
We use the command below to combine creation of role, role binding, and service account tests
|
We use the command below to combine creation of role, role binding, and service account tests
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight createRB
|
$ qliksense preflight authcheck -v
|
||||||
|
|
||||||
Preflight createRB check
|
Preflight auth check
|
||||||
-------------------------------------
|
-------------------------------------
|
||||||
Preflight create-role check:
|
Preflight create-role check:
|
||||||
Created role: role-preflight-check
|
Created role: role-preflight-check
|
||||||
@@ -189,18 +199,18 @@ Cleaning up resources...
|
|||||||
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
||||||
|
|
||||||
Completed preflight createServiceAccount check
|
Completed preflight createServiceAccount check
|
||||||
Completed preflight CreateRB check
|
Completed preflight auth check
|
||||||
```
|
```
|
||||||
|
|
||||||
### Mongodb 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.
|
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
|
```shell
|
||||||
qliksense preflight mongo --url=<url> OR
|
qliksense preflight mongo --url=<url> -v OR
|
||||||
qliksense preflight mongo
|
qliksense preflight mongo -v
|
||||||
qliksense preflight mongo --url=<mongo-server url> --ca-cert=<path to ca-cert file>
|
qliksense preflight mongo --url=<mongo-server url> --ca-cert=<path to ca-cert file> -v
|
||||||
|
```
|
||||||
|
```shell
|
||||||
Preflight mongo check
|
Preflight mongo check
|
||||||
---------------------
|
---------------------
|
||||||
Preflight mongodb check:
|
Preflight mongodb check:
|
||||||
@@ -216,13 +226,35 @@ Deleted pod: pf-mongo-pod
|
|||||||
Completed preflight mongodb check
|
Completed preflight mongodb check
|
||||||
```
|
```
|
||||||
|
|
||||||
|
#### Mongodb check with mutual tls
|
||||||
|
In order to perform mutual tls with mongo we need to:
|
||||||
|
- append client certificate to the beginning/end of CA certificate. Make sure to include the beginning and end tags on each certificate.
|
||||||
|
The CA certificate file should look like this in the end:
|
||||||
|
```shell
|
||||||
|
<existing contents of CA cert>
|
||||||
|
...
|
||||||
|
-----BEGIN RSA PRIVATE KEY-----
|
||||||
|
<private key>
|
||||||
|
-----END RSA PRIVATE KEY-----
|
||||||
|
-----BEGIN CERTIFICATE-----
|
||||||
|
<public key>
|
||||||
|
-----END CERTIFICATE-----
|
||||||
|
```
|
||||||
|
- Run the command below to set the ca certificate into the CR
|
||||||
|
```shell
|
||||||
|
cat <path_to_ca.crt> | base64 | qliksense config set-secrets qliksense.caCertificates --base64
|
||||||
|
```
|
||||||
|
|
||||||
|
Next, run:
|
||||||
|
```shell
|
||||||
|
qliksense preflight mongo -v
|
||||||
|
```
|
||||||
|
|
||||||
### Running all checks
|
### Running all checks
|
||||||
Run the command shown below to execute all preflight checks.
|
Run the command shown below to execute all preflight checks.
|
||||||
```shell
|
```shell
|
||||||
$ qliksense preflight all --mongodb-url=<url> OR
|
$ qliksense preflight all --mongodb-url=<url> -v OR
|
||||||
$ qliksense preflight all --mongodb-url=<mongo-server url> --mongodb-ca-cert=<path to ca-cert file>
|
$ qliksense preflight all --mongodb-url=<mongo-server url> --mongodb-ca-cert=<path to ca-cert file> -v
|
||||||
|
|
||||||
Running all preflight checks
|
Running all preflight checks
|
||||||
|
|
||||||
@@ -253,4 +285,23 @@ Completed Preflight kubernetes minimum version check
|
|||||||
All preflight checks have PASSED
|
All preflight checks have PASSED
|
||||||
Completed running all preflight checks
|
Completed running all preflight checks
|
||||||
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Clean
|
||||||
|
Run the command below to cleanup entities that were created for the purpose of running preflight checks and left behind in the cluster.
|
||||||
|
```shell
|
||||||
|
$ qliksense preflight clean -v
|
||||||
|
|
||||||
|
Preflight clean
|
||||||
|
----------------
|
||||||
|
Removing deployment...
|
||||||
|
Removing service...
|
||||||
|
Removing pod...
|
||||||
|
Removing role...
|
||||||
|
Removing rolebinding...
|
||||||
|
Removing serviceaccount...
|
||||||
|
Removing DNS check components...
|
||||||
|
Removing mongo check components...
|
||||||
|
Preflight cleanup complete
|
||||||
|
|
||||||
|
```
|
||||||
|
|||||||
10
go.mod
10
go.mod
@@ -10,13 +10,13 @@ replace (
|
|||||||
k8s.io/client-go => k8s.io/client-go v0.17.0
|
k8s.io/client-go => k8s.io/client-go v0.17.0
|
||||||
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd
|
k8s.io/kubectl => k8s.io/kubectl v0.0.0-20191219154910-1528d4eea6dd
|
||||||
|
|
||||||
sigs.k8s.io/kustomize/api => github.com/qlik-oss/kustomize/api v0.3.3-0.20200424070349-b0312eb71568
|
sigs.k8s.io/kustomize/api => github.com/qlik-oss/kustomize/api v0.3.3-0.20200514233516-4ac83864b7bd
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
cloud.google.com/go v0.52.0 // indirect
|
cloud.google.com/go v0.52.0 // indirect
|
||||||
cloud.google.com/go/storage v1.5.0 // indirect
|
cloud.google.com/go/storage v1.5.0 // indirect
|
||||||
github.com/Masterminds/semver/v3 v3.0.3
|
github.com/Masterminds/semver/v3 v3.1.0
|
||||||
github.com/Shopify/ejson v1.2.1
|
github.com/Shopify/ejson v1.2.1
|
||||||
github.com/aws/aws-sdk-go v1.28.9 // indirect
|
github.com/aws/aws-sdk-go v1.28.9 // indirect
|
||||||
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
github.com/bugsnag/bugsnag-go v1.5.3 // indirect
|
||||||
@@ -34,15 +34,13 @@ require (
|
|||||||
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
github.com/hashicorp/golang-lru v0.5.4 // indirect
|
||||||
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
|
github.com/jinzhu/copier v0.0.0-20190924061706-b57f9002281a
|
||||||
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
github.com/kardianos/osext v0.0.0-20190222173326-2bc1f35cddc0 // indirect
|
||||||
|
|
||||||
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381
|
github.com/logrusorgru/aurora v0.0.0-20200102142835-e9ef32dff381
|
||||||
|
|
||||||
github.com/mattn/go-colorable v0.1.4
|
github.com/mattn/go-colorable v0.1.4
|
||||||
github.com/mattn/go-tty v0.0.3
|
github.com/mattn/go-tty v0.0.3
|
||||||
github.com/mitchellh/go-homedir v1.1.0
|
github.com/mitchellh/go-homedir v1.1.0
|
||||||
github.com/otiai10/copy v1.1.1
|
github.com/otiai10/copy v1.1.1
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/qlik-oss/k-apis v0.1.1
|
github.com/qlik-oss/k-apis v0.1.4
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/rogpeppe/go-internal v1.5.2 // indirect
|
github.com/rogpeppe/go-internal v1.5.2 // indirect
|
||||||
github.com/spf13/cobra v0.0.6
|
github.com/spf13/cobra v0.0.6
|
||||||
@@ -53,8 +51,8 @@ require (
|
|||||||
golang.org/x/tools v0.0.0-20200312194400-c312e98713c2 // indirect
|
golang.org/x/tools v0.0.0-20200312194400-c312e98713c2 // indirect
|
||||||
google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b // indirect
|
google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b // indirect
|
||||||
gopkg.in/yaml.v2 v2.2.8
|
gopkg.in/yaml.v2 v2.2.8
|
||||||
gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555
|
|
||||||
k8s.io/api v0.17.2
|
k8s.io/api v0.17.2
|
||||||
|
k8s.io/apiextensions-apiserver v0.17.2
|
||||||
k8s.io/apimachinery v0.17.2
|
k8s.io/apimachinery v0.17.2
|
||||||
k8s.io/client-go v11.0.0+incompatible
|
k8s.io/client-go v11.0.0+incompatible
|
||||||
sigs.k8s.io/kustomize/api v0.3.2
|
sigs.k8s.io/kustomize/api v0.3.2
|
||||||
|
|||||||
12
go.sum
12
go.sum
@@ -72,6 +72,8 @@ github.com/Masterminds/goutils v1.1.0 h1:zukEsf/1JZwCMgHiK3GZftabmxiCw4apj3a28RP
|
|||||||
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
github.com/Masterminds/goutils v1.1.0/go.mod h1:8cTjp+g8YejhMuvIA5y2vz3BpJxksy863GQaJW2MFNU=
|
||||||
github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14=
|
github.com/Masterminds/semver/v3 v3.0.3 h1:znjIyLfpXEDQjOIEWh+ehwpTU14UzUPub3c3sm36u14=
|
||||||
github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
github.com/Masterminds/semver/v3 v3.0.3/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
|
github.com/Masterminds/semver/v3 v3.1.0 h1:Y2lUDsFKVRSYGojLJ1yLxSXdMmMYTYls0rCvoqmMUQk=
|
||||||
|
github.com/Masterminds/semver/v3 v3.1.0/go.mod h1:VPu/7SZ7ePZ3QOrcuXROw5FAcLl4a0cBrbBpGY/8hQs=
|
||||||
github.com/Masterminds/sprig/v3 v3.0.2 h1:wz22D0CiSctrliXiI9ZO3HoNApweeRGftyDN+BQa3B8=
|
github.com/Masterminds/sprig/v3 v3.0.2 h1:wz22D0CiSctrliXiI9ZO3HoNApweeRGftyDN+BQa3B8=
|
||||||
github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU=
|
github.com/Masterminds/sprig/v3 v3.0.2/go.mod h1:oesJ8kPONMONaZgtiHNzUShJbksypC5kWczhZAf6+aU=
|
||||||
github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
|
github.com/Masterminds/vcs v1.13.1/go.mod h1:N09YCmOQr6RLxC6UNHzuVwAdodYbbnycGHSmwVJjcKA=
|
||||||
@@ -881,10 +883,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 h1:3+auTFlqw+ZaQYJARz6ArODtkaIwtvBTx3N2NehQlL8=
|
||||||
github.com/prometheus/procfs v0.0.5/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
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/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||||
github.com/qlik-oss/k-apis v0.1.1 h1:aZ4eTMB3mSn03Kuj7+RI0eFLkjK9+0qxADBioRb3qVA=
|
github.com/qlik-oss/k-apis v0.1.2 h1:BBcrXl+NxdsvuRsZuJbvIFxMv5QIXqWBzhXOcr5KUX8=
|
||||||
github.com/qlik-oss/k-apis v0.1.1/go.mod h1:yoYGgPJ/H0t9H3NSq64dWfyQY6QWi2L9c+hCJoVO03U=
|
github.com/qlik-oss/k-apis v0.1.2/go.mod h1:yoYGgPJ/H0t9H3NSq64dWfyQY6QWi2L9c+hCJoVO03U=
|
||||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200424070349-b0312eb71568 h1:wHOUCGfnmgYqW3aCjuP3fXmB2T/uZXMvltO+F3us83E=
|
github.com/qlik-oss/k-apis v0.1.4 h1:YXnjKXm/yhPblzYYyVCtD0dNbIkLPLlDdBKnjeYW0IY=
|
||||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200424070349-b0312eb71568/go.mod h1:Yg8bqX8Mq/eSgXfcenxCxhZuSXg+NCsKq6NBdch/oUc=
|
github.com/qlik-oss/k-apis v0.1.4/go.mod h1:yoYGgPJ/H0t9H3NSq64dWfyQY6QWi2L9c+hCJoVO03U=
|
||||||
|
github.com/qlik-oss/kustomize/api v0.3.3-0.20200514233516-4ac83864b7bd h1:dYd6duTr54L7OqykGkd3Z+336frAvzsibWNYruYkYVc=
|
||||||
|
github.com/qlik-oss/kustomize/api v0.3.3-0.20200514233516-4ac83864b7bd/go.mod h1:zh3yFgE5zFk1kreqzVyyj1eXyIxQJT53l4zSg8Wt4SA=
|
||||||
github.com/quasilyte/go-consistent v0.0.0-20190521200055-c6f3937de18c/go.mod h1:5STLWrekHfjyYwxBRVRXNOSewLJ3PWfDJd1VyTS21fI=
|
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 h1:ta7tUOvsPHVHGom5hKW5VXNc2xZIkfCKP8iaqOyYtUQ=
|
||||||
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
github.com/rainycape/unidecode v0.0.0-20150907023854-cb7f23ec59be/go.mod h1:MIDFMn7db1kT65GmV94GzpX9Qdi7N/pQlwb+AN8wh+Q=
|
||||||
|
|||||||
@@ -157,6 +157,8 @@ func (cr *QliksenseCR) GetFetchAccessToken(encryptionKey string) string {
|
|||||||
if tok, err := cr.Spec.FetchSource.GetAccessToken(); err != nil {
|
if tok, err := cr.Spec.FetchSource.GetAccessToken(); err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return ""
|
return ""
|
||||||
|
} else if tok == "" {
|
||||||
|
return tok
|
||||||
} else {
|
} else {
|
||||||
by, _ := b64.StdEncoding.DecodeString(tok)
|
by, _ := b64.StdEncoding.DecodeString(tok)
|
||||||
res, err := DecryptData(by, encryptionKey)
|
res, err := DecryptData(by, encryptionKey)
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ func TestGetDecryptedCr(t *testing.T) {
|
|||||||
key, _ := setupGenerateKey(dir)
|
key, _ := setupGenerateKey(dir)
|
||||||
ecn, _ := EncryptData([]byte("mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"), key)
|
ecn, _ := EncryptData([]byte("mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"), key)
|
||||||
b := b64.StdEncoding.EncodeToString(ecn)
|
b := b64.StdEncoding.EncodeToString(ecn)
|
||||||
qcr.Spec.AddToSecrets("qliksense", "mongoDbUri", b, "")
|
qcr.Spec.AddToSecrets("qliksense", "mongodbUri", b, "")
|
||||||
|
|
||||||
qcr.SetFetchAccessToken("mytoken", key)
|
qcr.SetFetchAccessToken("mytoken", key)
|
||||||
|
|
||||||
@@ -117,8 +117,8 @@ func TestGetDecryptedCr(t *testing.T) {
|
|||||||
t.Log(err)
|
t.Log(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
decryptedValue := newCr.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
decryptedValue := newCr.Spec.GetFromSecrets("qliksense", "mongodbUri")
|
||||||
orignalValue := qcr.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
orignalValue := qcr.Spec.GetFromSecrets("qliksense", "mongodbUri")
|
||||||
if decryptedValue != "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false" {
|
if decryptedValue != "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false" {
|
||||||
t.Fail()
|
t.Fail()
|
||||||
b, _ := K8sToYaml(newCr)
|
b, _ := K8sToYaml(newCr)
|
||||||
|
|||||||
@@ -24,8 +24,8 @@ const (
|
|||||||
QliksenseDefaultProfile = "docker-desktop"
|
QliksenseDefaultProfile = "docker-desktop"
|
||||||
DefaultRotateKeys = "yes"
|
DefaultRotateKeys = "yes"
|
||||||
QliksenseMetadataName = "QliksenseConfigMetadata"
|
QliksenseMetadataName = "QliksenseConfigMetadata"
|
||||||
DefaultMongoDbUri = "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"
|
DefaultMongodbUri = "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"
|
||||||
DefaultMongoDbUriKey = "mongoDbUri"
|
DefaultMongodbUriKey = "mongodbUri"
|
||||||
)
|
)
|
||||||
|
|
||||||
// AddCommonConfig adds common configs into CRs
|
// AddCommonConfig adds common configs into CRs
|
||||||
@@ -40,7 +40,7 @@ func (qliksenseCR *QliksenseCR) AddCommonConfig(contextName string) {
|
|||||||
Profile: QliksenseDefaultProfile,
|
Profile: QliksenseDefaultProfile,
|
||||||
RotateKeys: DefaultRotateKeys,
|
RotateKeys: DefaultRotateKeys,
|
||||||
}
|
}
|
||||||
qliksenseCR.Spec.AddToSecrets("qliksense", DefaultMongoDbUriKey, DefaultMongoDbUri, "")
|
qliksenseCR.Spec.AddToSecrets("qliksense", DefaultMongodbUriKey, DefaultMongodbUri, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
// AddBaseQliksenseConfigs adds configs into config.yaml
|
// AddBaseQliksenseConfigs adds configs into config.yaml
|
||||||
@@ -96,7 +96,7 @@ func WriteToFile(content interface{}, targetFile string) error {
|
|||||||
log.Println(err)
|
log.Println(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
LogDebugMessage("Wrote content into %s", targetFile)
|
LogDebugMessage("Wrote content into %s\n", targetFile)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,8 @@ func TestAddCommonConfig(t *testing.T) {
|
|||||||
RotateKeys: DefaultRotateKeys,
|
RotateKeys: DefaultRotateKeys,
|
||||||
Secrets: map[string]config.NameValues{
|
Secrets: map[string]config.NameValues{
|
||||||
"qliksense": []config.NameValue{{
|
"qliksense": []config.NameValue{{
|
||||||
Name: DefaultMongoDbUriKey,
|
Name: DefaultMongodbUriKey,
|
||||||
Value: DefaultMongoDbUri,
|
Value: DefaultMongodbUri,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ import (
|
|||||||
"reflect"
|
"reflect"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v2"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestDockerConfigJsonSecret(t *testing.T) {
|
func TestDockerConfigJsonSecret(t *testing.T) {
|
||||||
@@ -34,10 +34,10 @@ func TestDockerConfigJsonSecret(t *testing.T) {
|
|||||||
t.Fatalf("error unmarshalling yaml string: %v, error: %v", string(dockerConfigJsonSecretYamlBytes), err)
|
t.Fatalf("error unmarshalling yaml string: %v, error: %v", string(dockerConfigJsonSecretYamlBytes), err)
|
||||||
} else if validYamlMap["apiVersion"] != "v1" ||
|
} else if validYamlMap["apiVersion"] != "v1" ||
|
||||||
validYamlMap["kind"] != "Secret" ||
|
validYamlMap["kind"] != "Secret" ||
|
||||||
validYamlMap["metadata"].(map[string]interface{})["name"] != dockerConfigJsonSecret.Name ||
|
validYamlMap["metadata"].(map[interface {}]interface {})["name"] != dockerConfigJsonSecret.Name ||
|
||||||
validYamlMap["type"] != "kubernetes.io/dockerconfigjson" {
|
validYamlMap["type"] != "kubernetes.io/dockerconfigjson" {
|
||||||
t.Fatalf("error verifying validity of secret yaml: %v", string(dockerConfigJsonSecretYamlBytes))
|
t.Fatalf("error verifying validity of secret yaml: %v", string(dockerConfigJsonSecretYamlBytes))
|
||||||
} else if dockerConfigJsonBytesBase64, ok := validYamlMap["data"].(map[string]interface{})[".dockerconfigjson"]; !ok {
|
} else if dockerConfigJsonBytesBase64, ok := validYamlMap["data"].(map[interface {}]interface {})[".dockerconfigjson"]; !ok {
|
||||||
t.Fatalf("no .dockerconfigjson data key in the secret yaml: %v", string(dockerConfigJsonSecretYamlBytes))
|
t.Fatalf("no .dockerconfigjson data key in the secret yaml: %v", string(dockerConfigJsonSecretYamlBytes))
|
||||||
} else if dockerConfigJsonEncryptedBytes, err := base64.StdEncoding.DecodeString(dockerConfigJsonBytesBase64.(string)); err != nil {
|
} else if dockerConfigJsonEncryptedBytes, err := base64.StdEncoding.DecodeString(dockerConfigJsonBytesBase64.(string)); err != nil {
|
||||||
t.Fatalf("error decoding dockerConfigJsonBytes from base64: %v", err)
|
t.Fatalf("error decoding dockerConfigJsonBytes from base64: %v", err)
|
||||||
@@ -45,14 +45,14 @@ func TestDockerConfigJsonSecret(t *testing.T) {
|
|||||||
t.Fatalf("error decrypting dockerConfigJsonBytes: %v", err)
|
t.Fatalf("error decrypting dockerConfigJsonBytes: %v", err)
|
||||||
} else if err := json.Unmarshal(dockerConfigJsonBytes, &dockerConfigJsonMap); err != nil {
|
} else if err := json.Unmarshal(dockerConfigJsonBytes, &dockerConfigJsonMap); err != nil {
|
||||||
t.Fatalf("error unmarshalling dockerConfigJson from json: %v", err)
|
t.Fatalf("error unmarshalling dockerConfigJson from json: %v", err)
|
||||||
} else if dockerConfigJson, ok := dockerConfigJsonMap["auths"].(map[string]interface{})[dockerConfigJsonSecret.Uri]; !ok {
|
} else if dockerConfigJson, ok := dockerConfigJsonMap["auths"].(map[string]interface {})[dockerConfigJsonSecret.Uri]; !ok {
|
||||||
t.Fatalf("dockerConfigJson map does not contain data for the registry: %v", dockerConfigJsonSecret.Uri)
|
t.Fatalf("dockerConfigJson map does not contain data for the registry: %v", dockerConfigJsonSecret.Uri)
|
||||||
} else if dockerConfigJson.(map[string]interface{})["username"] != dockerConfigJsonSecret.Username ||
|
} else if dockerConfigJson.(map[string]interface {})["username"] != dockerConfigJsonSecret.Username ||
|
||||||
dockerConfigJson.(map[string]interface{})["password"] != dockerConfigJsonSecret.Password ||
|
dockerConfigJson.(map[string]interface {})["password"] != dockerConfigJsonSecret.Password ||
|
||||||
dockerConfigJson.(map[string]interface{})["email"] != dockerConfigJsonSecret.Email {
|
dockerConfigJson.(map[string]interface {})["email"] != dockerConfigJsonSecret.Email {
|
||||||
t.Fatal("dockerConfigJson map does not contain expected values")
|
t.Fatal("dockerConfigJson map does not contain expected values")
|
||||||
} else {
|
} else {
|
||||||
authBase64 := dockerConfigJson.(map[string]interface{})["auth"]
|
authBase64 := dockerConfigJson.(map[string]interface {})["auth"]
|
||||||
if auth, err := base64.StdEncoding.DecodeString(authBase64.(string)); err != nil {
|
if auth, err := base64.StdEncoding.DecodeString(authBase64.(string)); err != nil {
|
||||||
t.Fatal("error base64 decoding auth value")
|
t.Fatal("error base64 decoding auth value")
|
||||||
} else if string(auth) != fmt.Sprintf("%s:%s", dockerConfigJsonSecret.Username, dockerConfigJsonSecret.Password) {
|
} else if string(auth) != fmt.Sprintf("%s:%s", dockerConfigJsonSecret.Username, dockerConfigJsonSecret.Password) {
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ type PreflightConfig struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type PreflightSpec struct {
|
type PreflightSpec struct {
|
||||||
MinK8sVersion string `json:"minK8sVersion,omitempty" yaml:"minK8sVersion,omitempty"`
|
MinK8sVersion string `json:"minK8sVersion,omitempty" yaml:"minK8sVersion,omitempty"`
|
||||||
Images map[string]string `json:"images,omitempty" yaml:"images,omitempty"`
|
MinMongoVersion string `json:"minMongoVersion,omitempty" yaml:"minMongoVersion,omitempty"`
|
||||||
|
Images map[string]string `json:"images,omitempty" yaml:"images,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//NewPreflightConfigEmpty create empty PreflightConfig object
|
//NewPreflightConfigEmpty create empty PreflightConfig object
|
||||||
@@ -74,6 +75,13 @@ func (p *PreflightConfig) AddMinK8sV(version string) {
|
|||||||
p.Spec.MinK8sVersion = version
|
p.Spec.MinK8sVersion = version
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PreflightConfig) AddMinMongoV(version string) {
|
||||||
|
if p.Spec == nil {
|
||||||
|
p.Spec = &PreflightSpec{}
|
||||||
|
}
|
||||||
|
p.Spec.MinMongoVersion = version
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PreflightConfig) AddImage(imageFor, imageName string) {
|
func (p *PreflightConfig) AddImage(imageFor, imageName string) {
|
||||||
if p.Spec.Images == nil {
|
if p.Spec.Images == nil {
|
||||||
p.Spec.Images = make(map[string]string)
|
p.Spec.Images = make(map[string]string)
|
||||||
@@ -101,6 +109,11 @@ func (p *PreflightConfig) GetImageName(imageFor string, accountForImageRegistry
|
|||||||
func (p *PreflightConfig) GetMinK8sVersion() string {
|
func (p *PreflightConfig) GetMinK8sVersion() string {
|
||||||
return p.Spec.MinK8sVersion
|
return p.Spec.MinK8sVersion
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PreflightConfig) GetMinMongoVersion() string {
|
||||||
|
return p.Spec.MinMongoVersion
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PreflightConfig) IsExistOnDisk() bool {
|
func (p *PreflightConfig) IsExistOnDisk() bool {
|
||||||
if _, err := os.Lstat(p.GetConfigFilePath()); err != nil {
|
if _, err := os.Lstat(p.GetConfigFilePath()); err != nil {
|
||||||
return false
|
return false
|
||||||
@@ -117,8 +130,9 @@ func (p *PreflightConfig) Initialize() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
p.AddMinK8sV("1.15")
|
p.AddMinK8sV("1.15")
|
||||||
|
p.AddMinMongoV("3.6")
|
||||||
p.AddImage("nginx", "nginx")
|
p.AddImage("nginx", "nginx")
|
||||||
p.AddImage("netcat", "subfuzion/netcat")
|
p.AddImage("netcat", "subfuzion/netcat")
|
||||||
p.AddImage("mongo", "mongo")
|
p.AddImage("preflight-mongo", "qlik-docker-oss.bintray.io/preflight-mongo")
|
||||||
return p.Write()
|
return p.Write()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ func checkExists(filename string) os.FileInfo {
|
|||||||
if os.IsNotExist(err) {
|
if os.IsNotExist(err) {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
LogDebugMessage("File exists")
|
LogDebugMessage("File exists\n")
|
||||||
return info
|
return info
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -73,7 +73,7 @@ func ProcessConfigArgs(args []string, base64Encoded bool) ([]*ServiceKeyValue, e
|
|||||||
resultSvcKV := make([]*ServiceKeyValue, len(args))
|
resultSvcKV := make([]*ServiceKeyValue, len(args))
|
||||||
// qliksense.mongodb=somethig
|
// qliksense.mongodb=somethig
|
||||||
for i, arg := range args {
|
for i, arg := range args {
|
||||||
LogDebugMessage("Arg received: %s", arg)
|
LogDebugMessage("Arg received: %s\n", arg)
|
||||||
first := strings.SplitN(arg, "=", 2)
|
first := strings.SplitN(arg, "=", 2)
|
||||||
if len(first) != 2 {
|
if len(first) != 2 {
|
||||||
return nil, notValidErr
|
return nil, notValidErr
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ package preflight
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
|
. "github.com/logrusorgru/aurora"
|
||||||
ansi "github.com/mattn/go-colorable"
|
ansi "github.com/mattn/go-colorable"
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
. "github.com/logrusorgru/aurora"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
|
func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
|
||||||
@@ -24,7 +24,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight deployment check
|
// Preflight deployment check
|
||||||
if err := qp.CheckDeployment(namespace, kubeConfigContents); err != nil {
|
if err := qp.CheckDeployment(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight deployment check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight deployment check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -34,7 +34,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight service check
|
// Preflight service check
|
||||||
if err := qp.CheckService(namespace, kubeConfigContents); err != nil {
|
if err := qp.CheckService(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight service check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight service check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -44,7 +44,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight pod check
|
// Preflight pod check
|
||||||
if err := qp.CheckPod(namespace, kubeConfigContents); err != nil {
|
if err := qp.CheckPod(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight pod check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight pod check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -54,7 +54,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight role check
|
// Preflight role check
|
||||||
if err := qp.CheckCreateRole(namespace); err != nil {
|
if err := qp.CheckCreateRole(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red("Preflight role check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red("Preflight role check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -64,7 +64,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight rolebinding check
|
// Preflight rolebinding check
|
||||||
if err := qp.CheckCreateRoleBinding(namespace); err != nil {
|
if err := qp.CheckCreateRoleBinding(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red(" Preflight rolebinding check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red(" Preflight rolebinding check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -74,7 +74,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight serviceaccount check
|
// Preflight serviceaccount check
|
||||||
if err := qp.CheckCreateServiceAccount(namespace); err != nil {
|
if err := qp.CheckCreateServiceAccount(namespace, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red(" Preflight serviceaccount check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red(" Preflight serviceaccount check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -84,7 +84,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight mongo check
|
// Preflight mongo check
|
||||||
if err := qp.CheckMongo(kubeConfigContents, namespace, preflightOpts); err != nil {
|
if err := qp.CheckMongo(kubeConfigContents, namespace, preflightOpts, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red(" Preflight mongo check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red(" Preflight mongo check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
@@ -94,7 +94,7 @@ func (qp *QliksensePreflight) RunAllPreflightChecks(kubeConfigContents []byte, n
|
|||||||
totalCount++
|
totalCount++
|
||||||
|
|
||||||
// Preflight DNS check
|
// Preflight DNS check
|
||||||
if err := qp.CheckDns(namespace, kubeConfigContents); err != nil {
|
if err := qp.CheckDns(namespace, kubeConfigContents, false); err != nil {
|
||||||
fmt.Fprintf(out, "%s\n", Red(" Preflight DNS check FAILED"))
|
fmt.Fprintf(out, "%s\n", Red(" Preflight DNS check FAILED"))
|
||||||
fmt.Printf("Error: %v\n\n", err)
|
fmt.Printf("Error: %v\n\n", err)
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
"k8s.io/client-go/kubernetes"
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigContents []byte) error {
|
func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigContents []byte, cleanup bool) error {
|
||||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("Kube config error: %v\n", err)
|
err = fmt.Errorf("Kube config error: %v\n", err)
|
||||||
@@ -14,63 +14,80 @@ func (qp *QliksensePreflight) CheckDeployment(namespace string, kubeConfigConten
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Deployment check
|
// Deployment check
|
||||||
qp.P.LogVerboseMessage("Preflight deployment check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("--------------------------- \n")
|
qp.P.LogVerboseMessage("Preflight deployment check: \n")
|
||||||
err = qp.checkPfDeployment(clientset, namespace, "deployment-preflight-check")
|
qp.P.LogVerboseMessage("--------------------------- \n")
|
||||||
|
}
|
||||||
|
err = qp.checkPfDeployment(clientset, namespace, cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qp.P.LogVerboseMessage("Preflight Deployment check: FAILED\n")
|
qp.P.LogVerboseMessage("Preflight Deployment check: FAILED\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight deployment check\n")
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight deployment check\n")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckService(namespace string, kubeConfigContents []byte) error {
|
func (qp *QliksensePreflight) CheckService(namespace string, kubeConfigContents []byte, cleanup bool) error {
|
||||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Service check
|
// Service check
|
||||||
qp.P.LogVerboseMessage("Preflight service check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("------------------------ \n")
|
qp.P.LogVerboseMessage("Preflight service check: \n")
|
||||||
err = qp.checkPfService(clientset, namespace)
|
qp.P.LogVerboseMessage("------------------------ \n")
|
||||||
|
}
|
||||||
|
err = qp.checkPfService(clientset, namespace, cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qp.P.LogVerboseMessage("Preflight Service check: FAILED\n")
|
qp.P.LogVerboseMessage("Preflight Service check: FAILED\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight service check\n")
|
|
||||||
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight service check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckPod(namespace string, kubeConfigContents []byte) error {
|
func (qp *QliksensePreflight) CheckPod(namespace string, kubeConfigContents []byte, cleanup bool) error {
|
||||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
err = fmt.Errorf("error: unable to create a kubernetes client: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// Pod check
|
// Pod check
|
||||||
qp.P.LogVerboseMessage("Preflight pod check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("-------------------- \n")
|
qp.P.LogVerboseMessage("Preflight pod check: \n")
|
||||||
err = qp.checkPfPod(clientset, namespace)
|
qp.P.LogVerboseMessage("-------------------- \n")
|
||||||
|
}
|
||||||
|
err = qp.checkPfPod(clientset, namespace, cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
qp.P.LogVerboseMessage("Preflight Pod check: FAILED\n")
|
qp.P.LogVerboseMessage("Preflight Pod check: FAILED\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight pod check\n")
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight pod check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) checkPfPod(clientset *kubernetes.Clientset, namespace string) error {
|
func (qp *QliksensePreflight) checkPfPod(clientset *kubernetes.Clientset, namespace string, cleanup bool) error {
|
||||||
// create a pod
|
// delete the pod we are going to create, if it already exists in the cluster
|
||||||
podName := "pod-pf-check"
|
podName := "pod-pf-check"
|
||||||
|
qp.deletePod(clientset, namespace, podName)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
commandToRun := []string{}
|
commandToRun := []string{}
|
||||||
|
|
||||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
imageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
// create a pod
|
||||||
pod, err := qp.createPreflightTestPod(clientset, namespace, podName, imageName, nil, commandToRun)
|
pod, err := qp.createPreflightTestPod(clientset, namespace, podName, imageName, nil, commandToRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create pod - %v\n", err)
|
err = fmt.Errorf("unable to create pod - %v\n", err)
|
||||||
@@ -87,9 +104,14 @@ func (qp *QliksensePreflight) checkPfPod(clientset *kubernetes.Clientset, namesp
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) checkPfService(clientset *kubernetes.Clientset, namespace string) error {
|
func (qp *QliksensePreflight) checkPfService(clientset *kubernetes.Clientset, namespace string, cleanup bool) error {
|
||||||
// creating service
|
// delete the service we are going to create, if it already exists in the cluster
|
||||||
serviceName := "svc-pf-check"
|
serviceName := "svc-pf-check"
|
||||||
|
qp.deleteService(clientset, namespace, serviceName)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
// creating service
|
||||||
pfService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
|
pfService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create service - %v\n", err)
|
err = fmt.Errorf("unable to create service - %v\n", err)
|
||||||
@@ -106,7 +128,14 @@ func (qp *QliksensePreflight) checkPfService(clientset *kubernetes.Clientset, na
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) checkPfDeployment(clientset *kubernetes.Clientset, namespace, depName string) error {
|
func (qp *QliksensePreflight) checkPfDeployment(clientset *kubernetes.Clientset, namespace string, cleanup bool) error {
|
||||||
|
// delete the deployment we are going to create, if it already exists in the cluster
|
||||||
|
depName := "deployment-preflight-check"
|
||||||
|
qp.deleteDeployment(clientset, namespace, depName)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
// check if we are able to create a deployment
|
// check if we are able to create a deployment
|
||||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
imageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -3,6 +3,8 @@ package preflight
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"k8s.io/client-go/kubernetes"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -10,21 +12,32 @@ const (
|
|||||||
netcat = "netcat"
|
netcat = "netcat"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []byte) error {
|
func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []byte, cleanup bool) error {
|
||||||
qp.P.LogVerboseMessage("Preflight DNS check: \n")
|
depName := "dep-dns-preflight-check"
|
||||||
qp.P.LogVerboseMessage("------------------- \n")
|
serviceName := "svc-dns-pf-check"
|
||||||
|
podName := "pf-pod-1"
|
||||||
|
|
||||||
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Preflight DNS check: \n")
|
||||||
|
qp.P.LogVerboseMessage("------------------- \n")
|
||||||
|
}
|
||||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// delete the deployment we are going to create, if it already exists in the cluster
|
||||||
|
qp.runDNSCleanup(clientset, namespace, podName, serviceName, depName)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
// creating deployment
|
// creating deployment
|
||||||
depName := "dep-dns-preflight-check"
|
|
||||||
nginxImageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
nginxImageName, err := qp.GetPreflightConfigObj().GetImageName(nginx, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsDeployment, err := qp.createPreflightTestDeployment(clientset, namespace, depName, nginxImageName)
|
dnsDeployment, err := qp.createPreflightTestDeployment(clientset, namespace, depName, nginxImageName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create deployment: %v\n", err)
|
err = fmt.Errorf("unable to create deployment: %v\n", err)
|
||||||
@@ -37,7 +50,6 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
|
|||||||
}
|
}
|
||||||
|
|
||||||
// creating service
|
// creating service
|
||||||
serviceName := "svc-dns-pf-check"
|
|
||||||
dnsService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
|
dnsService, err := qp.createPreflightTestService(clientset, namespace, serviceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create service : %s, %s\n", serviceName, err)
|
err = fmt.Errorf("unable to create service : %s, %s\n", serviceName, err)
|
||||||
@@ -46,13 +58,13 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
|
|||||||
defer qp.deleteService(clientset, namespace, serviceName)
|
defer qp.deleteService(clientset, namespace, serviceName)
|
||||||
|
|
||||||
// create a pod
|
// create a pod
|
||||||
podName := "pf-pod-1"
|
|
||||||
commandToRun := []string{"sh", "-c", "sleep 10; nc -z -v -w 1 " + dnsService.Name + " 80"}
|
commandToRun := []string{"sh", "-c", "sleep 10; nc -z -v -w 1 " + dnsService.Name + " 80"}
|
||||||
netcatImageName, err := qp.GetPreflightConfigObj().GetImageName(netcat, true)
|
netcatImageName, err := qp.GetPreflightConfigObj().GetImageName(netcat, true)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to retrieve image : %v\n", err)
|
err = fmt.Errorf("unable to retrieve image : %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
dnsPod, err := qp.createPreflightTestPod(clientset, namespace, podName, netcatImageName, nil, commandToRun)
|
dnsPod, err := qp.createPreflightTestPod(clientset, namespace, podName, netcatImageName, nil, commandToRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create pod : %s, %s\n", podName, err)
|
err = fmt.Errorf("unable to create pod : %s, %s\n", podName, err)
|
||||||
@@ -83,9 +95,16 @@ func (qp *QliksensePreflight) CheckDns(namespace string, kubeConfigContents []by
|
|||||||
err = fmt.Errorf("Expected response not found\n")
|
err = fmt.Errorf("Expected response not found\n")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("Completed preflight DNS check\n")
|
qp.P.LogVerboseMessage("Completed preflight DNS check\n")
|
||||||
qp.P.LogVerboseMessage("Cleaning up resources...\n")
|
qp.P.LogVerboseMessage("Cleaning up resources...\n")
|
||||||
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qp *QliksensePreflight) runDNSCleanup(clientset *kubernetes.Clientset, namespace, podName, serviceName, depName string) {
|
||||||
|
qp.deleteDeployment(clientset, namespace, depName)
|
||||||
|
qp.deletePod(clientset, namespace, podName)
|
||||||
|
qp.deleteService(clientset, namespace, serviceName)
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,12 @@ package preflight
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/Masterminds/semver/v3"
|
||||||
|
"github.com/pkg/errors"
|
||||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
apiv1 "k8s.io/api/core/v1"
|
apiv1 "k8s.io/api/core/v1"
|
||||||
@@ -12,113 +16,108 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
mongo = "mongo"
|
preflight_mongo = "preflight-mongo"
|
||||||
|
caCertMountPath = "/etc/ssl/certs/ca-certificates.crt"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
|
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||||
qp.P.LogVerboseMessage("Preflight mongodb check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("------------------------ \n")
|
qp.P.LogVerboseMessage("Preflight mongodb check: \n")
|
||||||
|
qp.P.LogVerboseMessage("------------------------ \n")
|
||||||
if preflightOpts.MongoOptions.MongodbUrl == "" {
|
|
||||||
// infer mongoDbUrl from currentCR
|
|
||||||
qp.P.LogVerboseMessage("MongoDbUri is empty, infer from CR\n")
|
|
||||||
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
|
||||||
var currentCR *qapi.QliksenseCR
|
|
||||||
|
|
||||||
var err error
|
|
||||||
qConfig.SetNamespace(namespace)
|
|
||||||
currentCR, err = qConfig.GetCurrentCR()
|
|
||||||
if err != nil {
|
|
||||||
qp.P.LogVerboseMessage("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)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
preflightOpts.MongoOptions.MongodbUrl = decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
|
||||||
}
|
}
|
||||||
|
var currentCR *qapi.QliksenseCR
|
||||||
qp.P.LogVerboseMessage("MongodbUrl: %s\n", preflightOpts.MongoOptions.MongodbUrl)
|
var err error
|
||||||
if err := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts); err != nil {
|
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
||||||
|
qConfig.SetNamespace(namespace)
|
||||||
|
currentCR, err = qConfig.GetCurrentCR()
|
||||||
|
if err != nil {
|
||||||
|
qp.P.LogVerboseMessage("Unable to retrieve current CR: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight mongodb check\n")
|
decryptedCR, err := qConfig.GetDecryptedCr(currentCR)
|
||||||
|
if err != nil {
|
||||||
|
qp.P.LogVerboseMessage("An error occurred while retrieving mongodbUrl from current CR: %v\n", err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if preflightOpts.MongoOptions.MongodbUrl == "" && !cleanup {
|
||||||
|
// infer mongoDbUrl from currentCR
|
||||||
|
qp.P.LogVerboseMessage("mongodbUri is empty, infer from CR\n")
|
||||||
|
preflightOpts.MongoOptions.MongodbUrl = strings.TrimSpace(decryptedCR.Spec.GetFromSecrets("qliksense", "mongodbUri"))
|
||||||
|
}
|
||||||
|
|
||||||
|
if preflightOpts.MongoOptions.CaCertFile == "" && !cleanup {
|
||||||
|
caCertStr := decryptedCR.Spec.GetFromSecrets("qliksense", "caCertificates")
|
||||||
|
tmpDir := os.TempDir()
|
||||||
|
caCrtFile := filepath.Join(tmpDir, "rootCA.crt")
|
||||||
|
api.LogDebugMessage("received ca crt: %s\n", caCertStr)
|
||||||
|
if err := ioutil.WriteFile(caCrtFile, []byte(caCertStr), 0644); err != nil {
|
||||||
|
return fmt.Errorf("unable to write CA crt to file: %v", err)
|
||||||
|
}
|
||||||
|
preflightOpts.MongoOptions.CaCertFile = caCrtFile
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("MongodbUrl: %s\n", preflightOpts.MongoOptions.MongodbUrl)
|
||||||
|
|
||||||
|
// if mongoDbUrl is empty, abort check
|
||||||
|
if preflightOpts.MongoOptions.MongodbUrl == "" {
|
||||||
|
qp.P.LogVerboseMessage("Mongodb Url is empty, hence aborting preflight check\n")
|
||||||
|
return errors.New("MongoDbUrl is empty")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts, cleanup); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight mongodb check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions) error {
|
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||||
var caCertSecretName, clientCertSecretName string
|
caCertSecretName := "ca-certificates-crt"
|
||||||
|
mongoPodName := "pf-mongo-pod"
|
||||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
err = fmt.Errorf("unable to create a kubernetes client: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
var secrets []string
|
|
||||||
|
// cleanup before starting check
|
||||||
|
qp.runMongoCleanup(clientset, namespace, mongoPodName, caCertSecretName)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
secrets := map[string]string{}
|
||||||
if preflightOpts.MongoOptions.CaCertFile != "" {
|
if preflightOpts.MongoOptions.CaCertFile != "" {
|
||||||
caCertSecretName = "preflight-mongo-test-cacert"
|
|
||||||
caCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.CaCertFile, caCertSecretName)
|
caCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.CaCertFile, caCertSecretName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create a ca cert kubernetes secret: %v\n", err)
|
err = fmt.Errorf("unable to create a ca cert kubernetes secret: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer qp.deleteK8sSecret(clientset, namespace, caCertSecret)
|
defer qp.deleteK8sSecret(clientset, namespace, caCertSecret.Name)
|
||||||
secrets = append(secrets, caCertSecretName)
|
secrets[caCertSecretName] = caCertMountPath
|
||||||
}
|
|
||||||
if preflightOpts.MongoOptions.ClientCertFile != "" {
|
|
||||||
clientCertSecretName = "preflight-mongo-test-clientcert"
|
|
||||||
clientCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.ClientCertFile, clientCertSecretName)
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("unable to create a client cert kubernetes secret: %v\n", err)
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer qp.deleteK8sSecret(clientset, namespace, clientCertSecret)
|
|
||||||
secrets = append(secrets, clientCertSecretName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mongoCommand := strings.Builder{}
|
commandToRun := []string{"./preflight-mongo", fmt.Sprintf(`-url="%s"`, preflightOpts.MongoOptions.MongodbUrl)}
|
||||||
mongoCommand.WriteString(fmt.Sprintf("sleep 10;mongo %s", preflightOpts.MongoOptions.MongodbUrl))
|
|
||||||
if preflightOpts.MongoOptions.Username != "" {
|
|
||||||
mongoCommand.WriteString(fmt.Sprintf(" --username %s", preflightOpts.MongoOptions.Username))
|
|
||||||
api.LogDebugMessage("Adding username: Mongo command: %s\n", mongoCommand.String())
|
|
||||||
}
|
|
||||||
if preflightOpts.MongoOptions.Password != "" {
|
|
||||||
mongoCommand.WriteString(fmt.Sprintf(" --password %s", preflightOpts.MongoOptions.Password))
|
|
||||||
api.LogDebugMessage("Adding username and password\n")
|
|
||||||
}
|
|
||||||
if preflightOpts.MongoOptions.Tls || preflightOpts.MongoOptions.CaCertFile != "" || preflightOpts.MongoOptions.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))
|
|
||||||
api.LogDebugMessage("Adding caCertFile: Mongo command: %s\n", mongoCommand.String())
|
|
||||||
}
|
|
||||||
if preflightOpts.MongoOptions.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 command: %s\n", strings.Join(commandToRun, " "))
|
||||||
|
|
||||||
// create a pod
|
// create a pod
|
||||||
podName := "pf-mongo-pod"
|
imageName, err := qp.GetPreflightConfigObj().GetImageName(preflight_mongo, true)
|
||||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(mongo, true)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to retrieve image : %v\n", err)
|
err = fmt.Errorf("unable to retrieve image : %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
mongoPod, err := qp.createPreflightTestPod(clientset, namespace, podName, imageName, secrets, commandToRun)
|
api.LogDebugMessage("image name to be used: %s\n", imageName)
|
||||||
|
mongoPod, err := qp.createPreflightTestPod(clientset, namespace, mongoPodName, imageName, secrets, commandToRun)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create pod : %v\n", err)
|
err = fmt.Errorf("unable to create pod : %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
defer qp.deletePod(clientset, namespace, podName)
|
defer qp.deletePod(clientset, namespace, mongoPodName)
|
||||||
|
|
||||||
if err := waitForPod(clientset, namespace, mongoPod); err != nil {
|
if err := waitForPod(clientset, namespace, mongoPod); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -134,7 +133,14 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
stringToCheck := "Implicit session:"
|
// check mongo server version
|
||||||
|
ok, err := qp.checkMongoVersion(logStr)
|
||||||
|
if !ok || err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// check if connection succeeded
|
||||||
|
stringToCheck := "qlik - connection succeeded!!"
|
||||||
if strings.Contains(logStr, stringToCheck) {
|
if strings.Contains(logStr, stringToCheck) {
|
||||||
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
|
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
|
||||||
} else {
|
} else {
|
||||||
@@ -144,6 +150,43 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qp *QliksensePreflight) checkMongoVersion(logStr string) (bool, error) {
|
||||||
|
// check mongo server version
|
||||||
|
api.LogDebugMessage("Minimum required mongo version: %s\n", qp.GetPreflightConfigObj().GetMinMongoVersion())
|
||||||
|
mongoVersionStrToCheck := "qlik mongo server version:"
|
||||||
|
if strings.Contains(logStr, mongoVersionStrToCheck) {
|
||||||
|
logLines := strings.Split(logStr, "\n")
|
||||||
|
for _, eachline := range logLines {
|
||||||
|
if strings.Contains(eachline, mongoVersionStrToCheck) {
|
||||||
|
mongoVersionLog := strings.Split(eachline, ":")
|
||||||
|
if len(mongoVersionLog) < 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
mongoVersionStr := strings.ReplaceAll(strings.TrimSpace(mongoVersionLog[1]), `"`, "")
|
||||||
|
api.LogDebugMessage("Extracted mongo version from pod log: %s\n", mongoVersionStr)
|
||||||
|
currentMongoVersionSemver, err := semver.NewVersion(mongoVersionStr)
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Unable to convert minimum mongo version into semver version:%v\n", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
minMongoVersionSemver, err := semver.NewVersion(qp.GetPreflightConfigObj().GetMinMongoVersion())
|
||||||
|
if err != nil {
|
||||||
|
err = fmt.Errorf("Unable to convert required minimum mongo version into semver version:%v\n", err)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
if currentMongoVersionSemver.GreaterThan(minMongoVersionSemver) || currentMongoVersionSemver.Equal(minMongoVersionSemver) {
|
||||||
|
qp.P.LogVerboseMessage("Current mongodb server version %s is greater than or equal to minimum required mongodb version: %s\n", currentMongoVersionSemver, minMongoVersionSemver)
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
err = fmt.Errorf("Current mongodb server version %s is less than minimum required mongodb version: %s", currentMongoVersionSemver, minMongoVersionSemver)
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
err := errors.New("Unable to infer mongodb server version")
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, namespace, certFile, certSecretName string) (*apiv1.Secret, error) {
|
func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, namespace, certFile, certSecretName string) (*apiv1.Secret, error) {
|
||||||
certBytes, err := ioutil.ReadFile(certFile)
|
certBytes, err := ioutil.ReadFile(certFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -152,8 +195,13 @@ func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, name
|
|||||||
|
|
||||||
certSecret, err := qp.createPreflightTestSecret(clientset, namespace, certSecretName, certBytes)
|
certSecret, err := qp.createPreflightTestSecret(clientset, namespace, certSecretName, certBytes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("unable to create secret with ca cert : %v\n", err)
|
err = fmt.Errorf("unable to create secret with cert : %v\n", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return certSecret, nil
|
return certSecret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, namespace, mongoPodName, caCertSecretName string) {
|
||||||
|
qp.deletePod(clientset, namespace, mongoPodName)
|
||||||
|
qp.deleteK8sSecret(clientset, namespace, caCertSecretName)
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,7 +12,6 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/mitchellh/go-homedir"
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/pkg/errors"
|
|
||||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
appsv1 "k8s.io/api/apps/v1"
|
||||||
@@ -40,12 +39,8 @@ func (p *PreflightOptions) LogVerboseMessage(strMessage string, args ...interfac
|
|||||||
}
|
}
|
||||||
|
|
||||||
type MongoOptions struct {
|
type MongoOptions struct {
|
||||||
MongodbUrl string
|
MongodbUrl string
|
||||||
Username string
|
CaCertFile string
|
||||||
Password string
|
|
||||||
CaCertFile string
|
|
||||||
ClientCertFile string
|
|
||||||
Tls bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var gracePeriod int64 = 0
|
var gracePeriod int64 = 0
|
||||||
@@ -115,13 +110,13 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
|
|||||||
if len(kubeconfig) == 0 {
|
if len(kubeconfig) == 0 {
|
||||||
clientConfig, err = rest.InClusterConfig()
|
clientConfig, err = rest.InClusterConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "Unable to load in-cluster kubeconfig")
|
err = fmt.Errorf("Unable to load in-cluster kubeconfig: %w", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
config, err := clientcmd.Load(kubeconfig)
|
config, err := clientcmd.Load(kubeconfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "Unable to load kubeconfig")
|
err = fmt.Errorf("Unable to load kubeconfig: %w", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
if contextName != "" {
|
if contextName != "" {
|
||||||
@@ -129,13 +124,13 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
|
|||||||
}
|
}
|
||||||
clientConfig, err = clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
|
clientConfig, err = clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "Unable to create client config from config")
|
err = fmt.Errorf("Unable to create client config from config: %w", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
clientset, err := kubernetes.NewForConfig(clientConfig)
|
clientset, err := kubernetes.NewForConfig(clientConfig)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errors.Wrap(err, "Unable to create clientset")
|
err = fmt.Errorf("Unable to create clientset: %w", err)
|
||||||
return nil, nil, err
|
return nil, nil, err
|
||||||
}
|
}
|
||||||
return clientset, clientConfig, nil
|
return clientset, clientConfig, nil
|
||||||
@@ -186,7 +181,7 @@ func (qp *QliksensePreflight) createPreflightTestDeployment(clientset *kubernete
|
|||||||
result, err = deploymentsClient.Create(deployment)
|
result, err = deploymentsClient.Create(deployment)
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
err = errors.Wrapf(err, "unable to create deployments in the %s namespace", namespace)
|
err = fmt.Errorf("unable to create deployments in the %s namespace: %w", namespace, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Created deployment %q\n", result.GetObjectMeta().GetName())
|
qp.P.LogVerboseMessage("Created deployment %q\n", result.GetObjectMeta().GetName())
|
||||||
@@ -201,7 +196,7 @@ func getDeployment(clientset *kubernetes.Clientset, namespace, depName string) (
|
|||||||
deployment, err = deploymentsClient.Get(depName, v1.GetOptions{})
|
deployment, err = deploymentsClient.Get(depName, v1.GetOptions{})
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
err = errors.Wrapf(err, "unable to get deployments in the %s namespace", namespace)
|
err = fmt.Errorf("unable to get deployments in the %s namespace: %w", namespace, err)
|
||||||
api.LogDebugMessage("%v\n", err)
|
api.LogDebugMessage("%v\n", err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@@ -271,7 +266,7 @@ func getService(clientset *kubernetes.Clientset, namespace, svcName string) (*ap
|
|||||||
svc, err = servicesClient.Get(svcName, v1.GetOptions{})
|
svc, err = servicesClient.Get(svcName, v1.GetOptions{})
|
||||||
return err
|
return err
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
err = errors.Wrapf(err, "unable to get services in the %s namespace", namespace)
|
err = fmt.Errorf("unable to get services in the %s namespace: %w", namespace, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -288,7 +283,6 @@ func (qp *QliksensePreflight) deleteService(clientset *kubernetes.Clientset, nam
|
|||||||
if err := retryOnError(func() (err error) {
|
if err := retryOnError(func() (err error) {
|
||||||
return servicesClient.Delete(name, &deleteOptions)
|
return servicesClient.Delete(name, &deleteOptions)
|
||||||
}); err != nil {
|
}); err != nil {
|
||||||
fmt.Println(err)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Deleted service: %s\n", name)
|
qp.P.LogVerboseMessage("Deleted service: %s\n", name)
|
||||||
@@ -315,7 +309,7 @@ func (qp *QliksensePreflight) deletePod(clientset *kubernetes.Clientset, namespa
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames []string, commandToRun []string) (*apiv1.Pod, error) {
|
func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames map[string]string, commandToRun []string) (*apiv1.Pod, error) {
|
||||||
// build the pod definition we want to deploy
|
// build the pod definition we want to deploy
|
||||||
pod := &apiv1.Pod{
|
pod := &apiv1.Pod{
|
||||||
ObjectMeta: v1.ObjectMeta{
|
ObjectMeta: v1.ObjectMeta{
|
||||||
@@ -338,7 +332,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
if len(secretNames) > 0 {
|
if len(secretNames) > 0 {
|
||||||
for _, secretName := range secretNames {
|
for secretName, mountPath := range secretNames {
|
||||||
pod.Spec.Volumes = append(pod.Spec.Volumes, apiv1.Volume{
|
pod.Spec.Volumes = append(pod.Spec.Volumes, apiv1.Volume{
|
||||||
Name: secretName,
|
Name: secretName,
|
||||||
VolumeSource: apiv1.VolumeSource{
|
VolumeSource: apiv1.VolumeSource{
|
||||||
@@ -347,7 +341,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
|||||||
Items: []apiv1.KeyToPath{
|
Items: []apiv1.KeyToPath{
|
||||||
{
|
{
|
||||||
Key: secretName,
|
Key: secretName,
|
||||||
Path: secretName,
|
Path: filepath.Base(mountPath),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
@@ -356,7 +350,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
|||||||
if len(pod.Spec.Containers) > 0 {
|
if len(pod.Spec.Containers) > 0 {
|
||||||
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, apiv1.VolumeMount{
|
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, apiv1.VolumeMount{
|
||||||
Name: secretName,
|
Name: secretName,
|
||||||
MountPath: "/etc/ssl/" + secretName,
|
MountPath: filepath.Dir(mountPath),
|
||||||
ReadOnly: true,
|
ReadOnly: true,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@@ -471,13 +465,13 @@ func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Po
|
|||||||
}
|
}
|
||||||
validateFunc := func(data interface{}) bool {
|
validateFunc := func(data interface{}) bool {
|
||||||
po := data.(*apiv1.Pod)
|
po := data.(*apiv1.Pod)
|
||||||
return len(po.Status.ContainerStatuses) > 0 && po.Status.ContainerStatuses[0].Ready
|
return po.Status.Phase == apiv1.PodRunning || po.Status.Phase == apiv1.PodSucceeded || po.Status.Phase == apiv1.PodFailed
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := waitForResource(checkFunc, validateFunc); err != nil {
|
if err := waitForResource(checkFunc, validateFunc); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if len(pod.Status.ContainerStatuses) == 0 || !pod.Status.ContainerStatuses[0].Ready {
|
if pod.Status.Phase != apiv1.PodRunning && pod.Status.Phase != apiv1.PodSucceeded && pod.Status.Phase != apiv1.PodFailed {
|
||||||
err = fmt.Errorf("container is taking much longer than expected")
|
err = fmt.Errorf("container is taking much longer than expected")
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -492,7 +486,6 @@ func waitForPodToDie(clientset *kubernetes.Clientset, namespace string, pod *api
|
|||||||
err = fmt.Errorf("unable to retrieve %s pod by name", podName)
|
err = fmt.Errorf("unable to retrieve %s pod by name", podName)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
api.LogDebugMessage("pod status: %v\n", po.Status.Phase)
|
|
||||||
return po, nil
|
return po, nil
|
||||||
}
|
}
|
||||||
validateFunc := func(r interface{}) bool {
|
validateFunc := func(r interface{}) bool {
|
||||||
@@ -568,18 +561,20 @@ func (qp *QliksensePreflight) createPfRole(clientset *kubernetes.Clientset, name
|
|||||||
return role, nil
|
return role, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) deleteRole(clientset *kubernetes.Clientset, namespace string, role *v1beta1.Role) {
|
func (qp *QliksensePreflight) deleteRole(clientset *kubernetes.Clientset, namespace string, roleName string) error {
|
||||||
rolesClient := clientset.RbacV1beta1().Roles(namespace)
|
rolesClient := clientset.RbacV1beta1().Roles(namespace)
|
||||||
|
|
||||||
deletePolicy := v1.DeletePropagationForeground
|
deletePolicy := v1.DeletePropagationForeground
|
||||||
deleteOptions := v1.DeleteOptions{
|
deleteOptions := v1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePolicy,
|
PropagationPolicy: &deletePolicy,
|
||||||
}
|
}
|
||||||
err := rolesClient.Delete(role.GetName(), &deleteOptions)
|
err := rolesClient.Delete(roleName, &deleteOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Error: %v\n", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Deleted role: %s\n\n", role.Name)
|
qp.P.LogVerboseMessage("Deleted role: %s\n\n", roleName)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) createPfRoleBinding(clientset *kubernetes.Clientset, namespace, roleBindingName string) (*v1beta1.RoleBinding, error) {
|
func (qp *QliksensePreflight) createPfRoleBinding(clientset *kubernetes.Clientset, namespace, roleBindingName string) (*v1beta1.RoleBinding, error) {
|
||||||
@@ -619,18 +614,20 @@ func (qp *QliksensePreflight) createPfRoleBinding(clientset *kubernetes.Clientse
|
|||||||
return roleBinding, nil
|
return roleBinding, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) deleteRoleBinding(clientset *kubernetes.Clientset, namespace string, roleBinding *v1beta1.RoleBinding) {
|
func (qp *QliksensePreflight) deleteRoleBinding(clientset *kubernetes.Clientset, namespace string, roleBindingName string) error {
|
||||||
roleBindingClient := clientset.RbacV1beta1().RoleBindings(namespace)
|
roleBindingClient := clientset.RbacV1beta1().RoleBindings(namespace)
|
||||||
|
|
||||||
deletePolicy := v1.DeletePropagationForeground
|
deletePolicy := v1.DeletePropagationForeground
|
||||||
deleteOptions := v1.DeleteOptions{
|
deleteOptions := v1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePolicy,
|
PropagationPolicy: &deletePolicy,
|
||||||
}
|
}
|
||||||
err := roleBindingClient.Delete(roleBinding.GetName(), &deleteOptions)
|
err := roleBindingClient.Delete(roleBindingName, &deleteOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Error: %v\n", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Deleted RoleBinding: %s\n\n", roleBinding.Name)
|
qp.P.LogVerboseMessage("Deleted RoleBinding: %s\n\n", roleBindingName)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clientset, namespace, serviceAccountName string) (*apiv1.ServiceAccount, error) {
|
func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clientset, namespace, serviceAccountName string) (*apiv1.ServiceAccount, error) {
|
||||||
@@ -657,18 +654,20 @@ func (qp *QliksensePreflight) createPfServiceAccount(clientset *kubernetes.Clien
|
|||||||
return serviceAccount, nil
|
return serviceAccount, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) deleteServiceAccount(clientset *kubernetes.Clientset, namespace string, serviceAccount *apiv1.ServiceAccount) {
|
func (qp *QliksensePreflight) deleteServiceAccount(clientset *kubernetes.Clientset, namespace string, serviceAccountName string) error {
|
||||||
serviceAccountClient := clientset.CoreV1().ServiceAccounts(namespace)
|
serviceAccountClient := clientset.CoreV1().ServiceAccounts(namespace)
|
||||||
|
|
||||||
deletePolicy := v1.DeletePropagationForeground
|
deletePolicy := v1.DeletePropagationForeground
|
||||||
deleteOptions := v1.DeleteOptions{
|
deleteOptions := v1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePolicy,
|
PropagationPolicy: &deletePolicy,
|
||||||
}
|
}
|
||||||
err := serviceAccountClient.Delete(serviceAccount.GetName(), &deleteOptions)
|
err := serviceAccountClient.Delete(serviceAccountName, &deleteOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
log.Printf("Error: %v\n", err)
|
||||||
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Deleted ServiceAccount: %s\n\n", serviceAccount.Name)
|
qp.P.LogVerboseMessage("Deleted ServiceAccount: %s\n\n", serviceAccountName)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) createPreflightTestSecret(clientset *kubernetes.Clientset, namespace, secretName string, secretData []byte) (*apiv1.Secret, error) {
|
func (qp *QliksensePreflight) createPreflightTestSecret(clientset *kubernetes.Clientset, namespace, secretName string, secretData []byte) (*apiv1.Secret, error) {
|
||||||
@@ -699,16 +698,42 @@ func (qp *QliksensePreflight) createPreflightTestSecret(clientset *kubernetes.Cl
|
|||||||
return secret, nil
|
return secret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) deleteK8sSecret(clientset *kubernetes.Clientset, namespace string, k8sSecret *apiv1.Secret) {
|
func (qp *QliksensePreflight) deleteK8sSecret(clientset *kubernetes.Clientset, namespace string, secretName string) error {
|
||||||
secretClient := clientset.CoreV1().Secrets(namespace)
|
secretClient := clientset.CoreV1().Secrets(namespace)
|
||||||
|
|
||||||
deletePolicy := v1.DeletePropagationForeground
|
deletePolicy := v1.DeletePropagationForeground
|
||||||
deleteOptions := v1.DeleteOptions{
|
deleteOptions := v1.DeleteOptions{
|
||||||
PropagationPolicy: &deletePolicy,
|
PropagationPolicy: &deletePolicy,
|
||||||
}
|
}
|
||||||
err := secretClient.Delete(k8sSecret.GetName(), &deleteOptions)
|
err := secretClient.Delete(secretName, &deleteOptions)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal(err)
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Deleted Secret: %s\n", k8sSecret.Name)
|
qp.P.LogVerboseMessage("Deleted Secret: %s\n", secretName)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qp *QliksensePreflight) Cleanup(namespace string, kubeConfigContents []byte) error {
|
||||||
|
qp.P.LogVerboseMessage("Preflight clean\n")
|
||||||
|
qp.P.LogVerboseMessage("----------------\n")
|
||||||
|
|
||||||
|
qp.P.LogVerboseMessage("Removing deployment...\n")
|
||||||
|
qp.CheckDeployment(namespace, kubeConfigContents, true)
|
||||||
|
qp.P.LogVerboseMessage("Removing service...\n")
|
||||||
|
qp.CheckService(namespace, kubeConfigContents, true)
|
||||||
|
qp.P.LogVerboseMessage("Removing pod...\n")
|
||||||
|
qp.CheckPod(namespace, kubeConfigContents, true)
|
||||||
|
|
||||||
|
qp.P.LogVerboseMessage("Removing role...\n")
|
||||||
|
qp.CheckCreateRole(namespace, true)
|
||||||
|
qp.P.LogVerboseMessage("Removing rolebinding...\n")
|
||||||
|
qp.CheckCreateRoleBinding(namespace, true)
|
||||||
|
qp.P.LogVerboseMessage("Removing serviceaccount...\n")
|
||||||
|
qp.CheckCreateServiceAccount(namespace, true)
|
||||||
|
|
||||||
|
qp.P.LogVerboseMessage("Removing DNS check components...\n")
|
||||||
|
qp.CheckDns(namespace, kubeConfigContents, true)
|
||||||
|
qp.P.LogVerboseMessage("Removing mongo check components...\n")
|
||||||
|
qp.CheckMongo(kubeConfigContents, namespace, &PreflightOptions{MongoOptions: &MongoOptions{}}, true)
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,48 +11,59 @@ import (
|
|||||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||||
)
|
)
|
||||||
|
|
||||||
var resultYamlBytes = []byte("")
|
func (qp *QliksensePreflight) CheckCreateRole(namespace string, cleanup bool) error {
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckCreateRole(namespace string) error {
|
|
||||||
// create a Role
|
// create a Role
|
||||||
qp.P.LogVerboseMessage("Preflight role check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("--------------------- \n")
|
qp.P.LogVerboseMessage("Preflight role check: \n")
|
||||||
err := qp.checkCreateEntity(namespace, "Role")
|
qp.P.LogVerboseMessage("--------------------- \n")
|
||||||
|
}
|
||||||
|
err := qp.checkCreateEntity(namespace, "Role", cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight role check\n")
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight role check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckCreateRoleBinding(namespace string) error {
|
func (qp *QliksensePreflight) CheckCreateRoleBinding(namespace string, cleanup bool) error {
|
||||||
// create a RoleBinding
|
// create a RoleBinding
|
||||||
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("---------------------------- \n")
|
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
|
||||||
err := qp.checkCreateEntity(namespace, "RoleBinding")
|
qp.P.LogVerboseMessage("---------------------------- \n")
|
||||||
|
}
|
||||||
|
err := qp.checkCreateEntity(namespace, "RoleBinding", cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight rolebinding check\n")
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight rolebinding check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (qp *QliksensePreflight) CheckCreateServiceAccount(namespace string) error {
|
func (qp *QliksensePreflight) CheckCreateServiceAccount(namespace string, cleanup bool) error {
|
||||||
// create a service account
|
// create a service account
|
||||||
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
|
if !cleanup {
|
||||||
qp.P.LogVerboseMessage("------------------------------- \n")
|
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
|
||||||
err := qp.checkCreateEntity(namespace, "ServiceAccount")
|
qp.P.LogVerboseMessage("------------------------------- \n")
|
||||||
|
}
|
||||||
|
err := qp.checkCreateEntity(namespace, "ServiceAccount", cleanup)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
qp.P.LogVerboseMessage("Completed preflight serviceaccount check\n")
|
if !cleanup {
|
||||||
|
qp.P.LogVerboseMessage("Completed preflight serviceaccount check\n")
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string) error {
|
func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string, cleanup bool) error {
|
||||||
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
||||||
var currentCR *qapi.QliksenseCR
|
var currentCR *qapi.QliksenseCR
|
||||||
mfroot := ""
|
mfroot := ""
|
||||||
kusDir := ""
|
kusDir := ""
|
||||||
|
resultYamlBytes := []byte("")
|
||||||
var err error
|
var err error
|
||||||
currentCR, err = qConfig.GetCurrentCR()
|
currentCR, err = qConfig.GetCurrentCR()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -89,6 +100,12 @@ func (qp *QliksensePreflight) checkCreateEntity(namespace, entityToTest string)
|
|||||||
}
|
}
|
||||||
namespace = "" // namespace is handled when generating the manifests
|
namespace = "" // namespace is handled when generating the manifests
|
||||||
|
|
||||||
|
// check if entity already exists in the cluster, if so - delete it
|
||||||
|
api.KubectlDeleteVerbose(sa, namespace, qp.P.Verbose)
|
||||||
|
if cleanup {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
qp.P.LogVerboseMessage("Cleaning up resources...\n")
|
qp.P.LogVerboseMessage("Cleaning up resources...\n")
|
||||||
err := api.KubectlDeleteVerbose(sa, namespace, qp.P.Verbose)
|
err := api.KubectlDeleteVerbose(sa, namespace, qp.P.Verbose)
|
||||||
@@ -113,7 +130,7 @@ func (qp *QliksensePreflight) CheckCreateRB(namespace string, kubeConfigContents
|
|||||||
qp.P.LogVerboseMessage("Preflight createRole check: \n")
|
qp.P.LogVerboseMessage("Preflight createRole check: \n")
|
||||||
qp.P.LogVerboseMessage("--------------------------- \n")
|
qp.P.LogVerboseMessage("--------------------------- \n")
|
||||||
errStr := strings.Builder{}
|
errStr := strings.Builder{}
|
||||||
err1 := qp.checkCreateEntity(namespace, "Role")
|
err1 := qp.checkCreateEntity(namespace, "Role", false)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
errStr.WriteString(err1.Error())
|
errStr.WriteString(err1.Error())
|
||||||
errStr.WriteString("\n")
|
errStr.WriteString("\n")
|
||||||
@@ -125,7 +142,7 @@ func (qp *QliksensePreflight) CheckCreateRB(namespace string, kubeConfigContents
|
|||||||
// create a roleBinding
|
// create a roleBinding
|
||||||
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
|
qp.P.LogVerboseMessage("Preflight rolebinding check: \n")
|
||||||
qp.P.LogVerboseMessage("---------------------------- \n")
|
qp.P.LogVerboseMessage("---------------------------- \n")
|
||||||
err2 := qp.checkCreateEntity(namespace, "RoleBinding")
|
err2 := qp.checkCreateEntity(namespace, "RoleBinding", false)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
errStr.WriteString(err2.Error())
|
errStr.WriteString(err2.Error())
|
||||||
errStr.WriteString("\n")
|
errStr.WriteString("\n")
|
||||||
@@ -137,7 +154,7 @@ func (qp *QliksensePreflight) CheckCreateRB(namespace string, kubeConfigContents
|
|||||||
// create a service account
|
// create a service account
|
||||||
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
|
qp.P.LogVerboseMessage("Preflight serviceaccount check: \n")
|
||||||
qp.P.LogVerboseMessage("------------------------------- \n")
|
qp.P.LogVerboseMessage("------------------------------- \n")
|
||||||
err3 := qp.checkCreateEntity(namespace, "ServiceAccount")
|
err3 := qp.checkCreateEntity(namespace, "ServiceAccount", false)
|
||||||
if err3 != nil {
|
if err3 != nil {
|
||||||
errStr.WriteString(err3.Error())
|
errStr.WriteString(err3.Error())
|
||||||
errStr.WriteString("\n")
|
errStr.WriteString("\n")
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ func (q *Qliksense) ConfigApplyQK8s() error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create patch dependent resoruces
|
// create patch dependent resoruces
|
||||||
fmt.Println("Installing resoruces used kuztomize patch")
|
fmt.Println("Installing resources used by the kuztomize patch")
|
||||||
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
|
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -89,11 +89,13 @@ func (q *Qliksense) applyConfigToK8s(qcr *qapi.QliksenseCR) error {
|
|||||||
cr.GeneratePatches(&qcr.KApiCr, path.Join(userHomeDir, ".kube", "config"))
|
cr.GeneratePatches(&qcr.KApiCr, path.Join(userHomeDir, ".kube", "config"))
|
||||||
// apply generated manifests
|
// apply generated manifests
|
||||||
profilePath := filepath.Join(qcr.Spec.GetManifestsRoot(), qcr.Spec.GetProfileDir())
|
profilePath := filepath.Join(qcr.Spec.GetManifestsRoot(), qcr.Spec.GetProfileDir())
|
||||||
|
fmt.Printf("Generating manifests for profile: %v\n", profilePath)
|
||||||
mByte, err := ExecuteKustomizeBuild(profilePath)
|
mByte, err := ExecuteKustomizeBuild(profilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println("cannot generate manifests for "+profilePath, err)
|
fmt.Printf("error generating manifests: %v\n", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
fmt.Println("Applying manifests to the cluster")
|
||||||
if err = qapi.KubectlApply(string(mByte), qcr.GetNamespace()); err != nil {
|
if err = qapi.KubectlApply(string(mByte), qcr.GetNamespace()); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,12 +18,12 @@ import (
|
|||||||
|
|
||||||
b64 "encoding/base64"
|
b64 "encoding/base64"
|
||||||
|
|
||||||
|
. "github.com/logrusorgru/aurora"
|
||||||
ansi "github.com/mattn/go-colorable"
|
ansi "github.com/mattn/go-colorable"
|
||||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
_ "gopkg.in/yaml.v2"
|
_ "gopkg.in/yaml.v2"
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
. "github.com/logrusorgru/aurora"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -62,7 +62,7 @@ func (q *Qliksense) SetSecrets(args []string, isSecretSet bool, base64Encoded bo
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Metadata name in qliksense CR is the name of the current context
|
// Metadata name in qliksense CR is the name of the current context
|
||||||
api.LogDebugMessage("Current context: %s", qliksenseCR.GetName())
|
api.LogDebugMessage("Current context: %s\n", qliksenseCR.GetName())
|
||||||
encryptionKey, err := qConfig.GetEncryptionKeyForCurrent()
|
encryptionKey, err := qConfig.GetEncryptionKeyForCurrent()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -72,7 +72,7 @@ func (q *Qliksense) SetSecrets(args []string, isSecretSet bool, base64Encoded bo
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, ra := range resultArgs {
|
for _, ra := range resultArgs {
|
||||||
api.LogDebugMessage("value args to be encrypted: %s", ra.Value)
|
api.LogDebugMessage("value args to be encrypted: %s\n", ra.Value)
|
||||||
if err := q.processSecret(ra, encryptionKey, qliksenseCR, isSecretSet); err != nil {
|
if err := q.processSecret(ra, encryptionKey, qliksenseCR, isSecretSet); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -213,8 +213,8 @@ func validateCR(key string, keySub string, value string, crSpec *api.QliksenseCR
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
switch key {
|
switch key {
|
||||||
case "gitops":
|
case "opsrunner":
|
||||||
crSpec.Spec.GitOps = &config.GitOps{}
|
crSpec.Spec.OpsRunner = &config.OpsRunner{}
|
||||||
case "git":
|
case "git":
|
||||||
crSpec.Spec.Git = &config.Repo{}
|
crSpec.Spec.Git = &config.Repo{}
|
||||||
}
|
}
|
||||||
@@ -248,8 +248,8 @@ func (q *Qliksense) SetOtherConfigs(args []string) error {
|
|||||||
if err := q.processSetGit(arg, qliksenseCR); err != nil {
|
if err := q.processSetGit(arg, qliksenseCR); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else if strings.HasPrefix(arg, "gitOps.") {
|
} else if strings.HasPrefix(arg, "opsRunner.") {
|
||||||
if err := q.processSetGitOps(arg, qliksenseCR); err != nil {
|
if err := q.processSetOpsRunner(arg, qliksenseCR); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@@ -337,27 +337,29 @@ func (q *Qliksense) processSetGit(arg string, cr *api.QliksenseCR) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Qliksense) processSetGitOps(arg string, cr *api.QliksenseCR) error {
|
func (q *Qliksense) processSetOpsRunner(arg string, cr *api.QliksenseCR) error {
|
||||||
args := strings.Split(arg, "=")
|
args := strings.Split(arg, "=")
|
||||||
subs := strings.Split(args[0], ".")
|
subs := strings.Split(args[0], ".")
|
||||||
if cr.Spec.Git == nil {
|
if cr.Spec.OpsRunner == nil {
|
||||||
cr.Spec.GitOps = &config.GitOps{}
|
cr.Spec.OpsRunner = &config.OpsRunner{}
|
||||||
}
|
}
|
||||||
switch subs[1] {
|
switch subs[1] {
|
||||||
case "enabled":
|
case "enabled":
|
||||||
if args[1] != "yes" && args[1] != "no" {
|
if args[1] != "yes" && args[1] != "no" {
|
||||||
return errors.New("Please use yes or no for key enabled")
|
return errors.New("Please use yes or no for key enabled")
|
||||||
}
|
}
|
||||||
cr.Spec.GitOps.Enabled = args[1]
|
cr.Spec.OpsRunner.Enabled = args[1]
|
||||||
case "schedule":
|
case "schedule":
|
||||||
if _, err := cron.ParseStandard(args[1]); err != nil {
|
if _, err := cron.ParseStandard(args[1]); err != nil {
|
||||||
return errors.New("Please enter string with standard cron scheduling syntax ")
|
return errors.New("Please enter string with standard cron scheduling syntax ")
|
||||||
}
|
}
|
||||||
cr.Spec.GitOps.Schedule = args[1]
|
cr.Spec.OpsRunner.Schedule = args[1]
|
||||||
case "watchBranch":
|
case "watchBranch":
|
||||||
cr.Spec.GitOps.WatchBranch = args[1]
|
cr.Spec.OpsRunner.WatchBranch = args[1]
|
||||||
case "image":
|
case "image":
|
||||||
cr.Spec.GitOps.Image = args[1]
|
cr.Spec.OpsRunner.Image = args[1]
|
||||||
|
case "crPvc":
|
||||||
|
cr.Spec.OpsRunner.CrPvc = args[1]
|
||||||
default:
|
default:
|
||||||
return errors.New(arg + " does not match any cr spec")
|
return errors.New(arg + " does not match any cr spec")
|
||||||
}
|
}
|
||||||
@@ -411,7 +413,7 @@ func (q *Qliksense) DeleteContextConfig(args []string, flag bool) error {
|
|||||||
out := ansi.NewColorableStdout()
|
out := ansi.NewColorableStdout()
|
||||||
switch args[0] {
|
switch args[0] {
|
||||||
case qliksenseConfig.Spec.CurrentContext:
|
case qliksenseConfig.Spec.CurrentContext:
|
||||||
fmt.Fprintln(out,Yellow("Please switch contexts to be able to delete this context."))
|
fmt.Fprintln(out, Yellow("Please switch contexts to be able to delete this context."))
|
||||||
err := fmt.Errorf(Red("Cannot delete current context - %s").String(), White(Bold(qliksenseConfig.Spec.CurrentContext)))
|
err := fmt.Errorf(Red("Cannot delete current context - %s").String(), White(Bold(qliksenseConfig.Spec.CurrentContext)))
|
||||||
return err
|
return err
|
||||||
case DefaultQliksenseContext:
|
case DefaultQliksenseContext:
|
||||||
@@ -452,7 +454,7 @@ func (q *Qliksense) DeleteContextConfig(args []string, flag bool) error {
|
|||||||
if ans == true {
|
if ans == true {
|
||||||
api.WriteToFile(&qliksenseConfig, qliksenseConfigFile)
|
api.WriteToFile(&qliksenseConfig, qliksenseConfigFile)
|
||||||
fmt.Fprintln(out, Yellow(Underline("Warning: Active resources may still be running in-cluster")))
|
fmt.Fprintln(out, Yellow(Underline("Warning: Active resources may still be running in-cluster")))
|
||||||
fmt.Fprintln(out, Green("Successfully deleted context: "),Bold(args[0]))
|
fmt.Fprintln(out, Green("Successfully deleted context: "), Bold(args[0]))
|
||||||
} else {
|
} else {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -520,7 +522,7 @@ func (q *Qliksense) SetUpQliksenseContext(contextName string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// set the encrypted default mongo
|
// set the encrypted default mongo
|
||||||
return q.SetSecrets([]string{`qliksense.mongoDbUri="mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"`}, false, false)
|
return q.SetSecrets([]string{`qliksense.mongodbUri="mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"`}, false, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func validateInput(input string) (string, error) {
|
func validateInput(input string) (string, error) {
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ const (
|
|||||||
var targetFileStringTemplate = `
|
var targetFileStringTemplate = `
|
||||||
apiVersion: v1
|
apiVersion: v1
|
||||||
data:
|
data:
|
||||||
mongoDbUri: %s
|
mongodbUri: %s
|
||||||
kind: Secret
|
kind: Secret
|
||||||
metadata:
|
metadata:
|
||||||
name: testctx-qliksense-senseinstaller
|
name: testctx-qliksense-senseinstaller
|
||||||
@@ -244,7 +244,7 @@ func TestSetOtherConfigs(t *testing.T) {
|
|||||||
q: &Qliksense{
|
q: &Qliksense{
|
||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: []string{"profile=minikube", "rotateKeys=yes", "storageClassName=efs", "gitOps.enabled=yes", "gitOps.schedule=30 * * * *", "git.repository=master", "git.userName=foo", "git.accessToken=1234"},
|
args: []string{"profile=minikube", "rotateKeys=yes", "storageClassName=efs", "opsRunner.enabled=yes", "opsRunner.schedule=30 * * * *", "git.repository=master", "git.userName=foo", "git.accessToken=1234"},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@@ -254,7 +254,7 @@ func TestSetOtherConfigs(t *testing.T) {
|
|||||||
q: &Qliksense{
|
q: &Qliksense{
|
||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: []string{"someconfig=somevalue, gitOps.schedule=bar", "gitOps.enabled=bar", "git.foo=bar", "rotateKeys=bar"},
|
args: []string{"someconfig=somevalue, opsRunner.schedule=bar", "opsRunner.enabled=bar", "git.foo=bar", "rotateKeys=bar"},
|
||||||
},
|
},
|
||||||
wantErr: true,
|
wantErr: true,
|
||||||
},
|
},
|
||||||
@@ -296,7 +296,7 @@ func TestSetConfigs(t *testing.T) {
|
|||||||
q: &Qliksense{
|
q: &Qliksense{
|
||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: []string{"qliksense.acceptEULA=\"yes\"", "qliksense.mongoDbUri=\"mongo://mongo:3307\""},
|
args: []string{"qliksense.acceptEULA=\"yes\"", "qliksense.mongodbUri=\"mongo://mongo:3307\""},
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
},
|
},
|
||||||
@@ -572,7 +572,7 @@ func Test_SetSecrets(t *testing.T) {
|
|||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
args: []string{"qliksense.mongoDbUri=\"mongodb://qlik-default-mongodb:27017/qliksense?ssl=false\""},
|
args: []string{"qliksense.mongodbUri=\"mongodb://qlik-default-mongodb:27017/qliksense?ssl=false\""},
|
||||||
isSecretSet: false,
|
isSecretSet: false,
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@@ -583,7 +583,7 @@ func Test_SetSecrets(t *testing.T) {
|
|||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
args: []string{"qliksense.mongoDbUri=bW9uZ29kYjovL3FsaWstZGVmYXVsdC1tb25nb2RiOjI3MDE3L3FsaWtzZW5zZT9zc2w9ZmFsc2U="},
|
args: []string{"qliksense.mongodbUri=bW9uZ29kYjovL3FsaWstZGVmYXVsdC1tb25nb2RiOjI3MDE3L3FsaWtzZW5zZT9zc2w9ZmFsc2U="},
|
||||||
isSecretSet: false,
|
isSecretSet: false,
|
||||||
base64: true,
|
base64: true,
|
||||||
},
|
},
|
||||||
@@ -595,7 +595,7 @@ func Test_SetSecrets(t *testing.T) {
|
|||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
args: []string{"qliksense.mongoDbUri=\"mongo://mongo:3307\""},
|
args: []string{"qliksense.mongodbUri=\"mongo://mongo:3307\""},
|
||||||
isSecretSet: true,
|
isSecretSet: true,
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
@@ -606,7 +606,7 @@ func Test_SetSecrets(t *testing.T) {
|
|||||||
QliksenseHome: testDir,
|
QliksenseHome: testDir,
|
||||||
},
|
},
|
||||||
args: args{
|
args: args{
|
||||||
args: []string{"qliksense.mongoDbUri=\"mongodb://qlik-default-mongodb:27017/qliksense?ssl=false\""},
|
args: []string{"qliksense.mongodbUri=\"mongodb://qlik-default-mongodb:27017/qliksense?ssl=false\""},
|
||||||
isSecretSet: true,
|
isSecretSet: true,
|
||||||
},
|
},
|
||||||
wantErr: false,
|
wantErr: false,
|
||||||
|
|||||||
109
pkg/qliksense/context_configs_unset.go
Normal file
109
pkg/qliksense/context_configs_unset.go
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
package qliksense
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"reflect"
|
||||||
|
|
||||||
|
kconfig "github.com/qlik-oss/k-apis/pkg/config"
|
||||||
|
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (q *Qliksense) UnsetCmd(args []string) error {
|
||||||
|
return unsetAll(q.QliksenseHome, args)
|
||||||
|
}
|
||||||
|
func unsetAll(qHome string, args []string) error {
|
||||||
|
qConfig := api.NewQConfig(qHome)
|
||||||
|
|
||||||
|
qcr, err := qConfig.GetCurrentCR()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// either delete all args or none
|
||||||
|
for _, arg := range args {
|
||||||
|
isRemoved := false
|
||||||
|
// delete if key present
|
||||||
|
if !strings.Contains(arg, ".") {
|
||||||
|
if isRemoved = unsetOnlyKey(arg, qcr); isRemoved {
|
||||||
|
//continue to the next arg
|
||||||
|
continue
|
||||||
|
} else if isRemoved = unsetServiceName(arg, qcr); isRemoved {
|
||||||
|
//continue to the next arg
|
||||||
|
continue
|
||||||
|
} else {
|
||||||
|
return fmt.Errorf("%s not found in the context", arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// delete key inside configs if present
|
||||||
|
// delete key inside secrets if present
|
||||||
|
if isRemoved = unsetServiceKey(arg, qcr); !isRemoved {
|
||||||
|
return fmt.Errorf("%s not found in the context", arg)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return qConfig.WriteCR(qcr)
|
||||||
|
}
|
||||||
|
func unsetOnlyKey(key string, qcr *api.QliksenseCR) bool {
|
||||||
|
|
||||||
|
v := reflect.ValueOf(qcr.Spec).Elem().FieldByName(strings.Title(key))
|
||||||
|
if v.IsValid() && v.CanSet() {
|
||||||
|
v.SetString("")
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetServiceName(svc string, qcr *api.QliksenseCR) bool {
|
||||||
|
if qcr.Spec.Configs != nil && qcr.Spec.Configs[svc] != nil {
|
||||||
|
delete(qcr.Spec.Configs, svc)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if qcr.Spec.Secrets != nil && qcr.Spec.Secrets[svc] != nil {
|
||||||
|
delete(qcr.Spec.Secrets, svc)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func unsetServiceKey(svcKey string, qcr *api.QliksenseCR) bool {
|
||||||
|
sk := strings.Split(svcKey, ".")
|
||||||
|
svc := sk[0]
|
||||||
|
key := sk[1]
|
||||||
|
|
||||||
|
if qcr.Spec.Configs != nil && qcr.Spec.Configs[svc] != nil {
|
||||||
|
index := findIndex(key, qcr.Spec.Configs[svc])
|
||||||
|
if index > -1 {
|
||||||
|
qcr.Spec.Configs[svc][index] = qcr.Spec.Configs[svc][len(qcr.Spec.Configs[svc])-1]
|
||||||
|
qcr.Spec.Configs[svc] = qcr.Spec.Configs[svc][:len(qcr.Spec.Configs[svc])-1]
|
||||||
|
if len(qcr.Spec.Configs[svc]) == 0 {
|
||||||
|
delete(qcr.Spec.Configs, svc)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if qcr.Spec.Secrets != nil && qcr.Spec.Secrets[svc] != nil {
|
||||||
|
index := findIndex(key, qcr.Spec.Secrets[svc])
|
||||||
|
if index > -1 {
|
||||||
|
qcr.Spec.Secrets[svc][index] = qcr.Spec.Secrets[svc][len(qcr.Spec.Secrets[svc])-1]
|
||||||
|
qcr.Spec.Secrets[svc] = qcr.Spec.Secrets[svc][:len(qcr.Spec.Secrets[svc])-1]
|
||||||
|
if len(qcr.Spec.Secrets[svc]) == 0 {
|
||||||
|
delete(qcr.Spec.Secrets, svc)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func findIndex(elem string, nvs kconfig.NameValues) int {
|
||||||
|
for i, nv := range nvs {
|
||||||
|
if nv.Name == elem {
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1
|
||||||
|
}
|
||||||
99
pkg/qliksense/context_configs_unset_test.go
Normal file
99
pkg/qliksense/context_configs_unset_test.go
Normal file
@@ -0,0 +1,99 @@
|
|||||||
|
package qliksense
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
|
_ "gopkg.in/yaml.v2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestUnsetAll(t *testing.T) {
|
||||||
|
qHome, _ := ioutil.TempDir("", "")
|
||||||
|
testPepareDir(qHome)
|
||||||
|
defer os.RemoveAll(qHome)
|
||||||
|
//fmt.Print(qHome)
|
||||||
|
args := []string{"rotateKeys", "qliksense", "qliksense2.acceptEula3", "serviceA.acceptEula"}
|
||||||
|
if err := unsetAll(qHome, args); err != nil {
|
||||||
|
t.Log("error during unset", err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
qc := api.NewQConfig(qHome)
|
||||||
|
qcr, err := qc.GetCurrentCR()
|
||||||
|
if err != nil {
|
||||||
|
t.Log("error while getting current cr", err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if qcr.Spec.RotateKeys != "" {
|
||||||
|
t.Log("Expected empty rotateKeys but got: " + qcr.Spec.RotateKeys)
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
|
||||||
|
if qcr.Spec.Configs["qliksense"] != nil {
|
||||||
|
t.Log("qliksense in configs not deleted")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if len(qcr.Spec.Configs["qliksense2"]) != 1 {
|
||||||
|
t.Log("qliksense2.acceptEula3 not deleted")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
if qcr.Spec.Configs["serviceA"] != nil {
|
||||||
|
t.Log("serviceA not deleted")
|
||||||
|
t.Fail()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func testPepareDir(qHome string) {
|
||||||
|
|
||||||
|
config :=
|
||||||
|
`
|
||||||
|
apiVersion: config.qlik.com/v1
|
||||||
|
kind: QliksenseConfig
|
||||||
|
metadata:
|
||||||
|
name: qliksenseConfig
|
||||||
|
spec:
|
||||||
|
contexts:
|
||||||
|
- name: qlik-default
|
||||||
|
crFile: contexts/qlik-default/qlik-default.yaml
|
||||||
|
currentContext: qlik-default
|
||||||
|
`
|
||||||
|
configFile := filepath.Join(qHome, "config.yaml")
|
||||||
|
// tests/config.yaml exists
|
||||||
|
ioutil.WriteFile(configFile, []byte(config), 0777)
|
||||||
|
|
||||||
|
contextYaml :=
|
||||||
|
`
|
||||||
|
apiVersion: qlik.com/v1
|
||||||
|
kind: Qliksense
|
||||||
|
metadata:
|
||||||
|
name: qlik-default
|
||||||
|
spec:
|
||||||
|
profile: docker-desktop
|
||||||
|
rotateKeys: "yes"
|
||||||
|
configs:
|
||||||
|
qliksense:
|
||||||
|
- name: acceptEula
|
||||||
|
value: some
|
||||||
|
qliksense2:
|
||||||
|
- name: acceptEula2
|
||||||
|
value: some
|
||||||
|
- name: acceptEula3
|
||||||
|
value: some
|
||||||
|
serviceA:
|
||||||
|
- name: acceptEula
|
||||||
|
value: some
|
||||||
|
`
|
||||||
|
qlikDefaultContext := "qlik-default"
|
||||||
|
// create contexts/qlik-default/ under tests/
|
||||||
|
contexts := "contexts"
|
||||||
|
contextsDir := filepath.Join(qHome, contexts, qlikDefaultContext)
|
||||||
|
if err := os.MkdirAll(contextsDir, 0777); err != nil {
|
||||||
|
err = fmt.Errorf("Not able to create directories")
|
||||||
|
}
|
||||||
|
|
||||||
|
contextFile := filepath.Join(contextsDir, qlikDefaultContext+".yaml")
|
||||||
|
ioutil.WriteFile(contextFile, []byte(contextYaml), 0777)
|
||||||
|
}
|
||||||
@@ -5,7 +5,15 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
|
apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"k8s.io/client-go/tools/clientcmd"
|
||||||
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
)
|
)
|
||||||
|
|
||||||
type CrdCommandOptions struct {
|
type CrdCommandOptions struct {
|
||||||
@@ -20,11 +28,11 @@ func (q *Qliksense) ViewCrds(opts *CrdCommandOptions) error {
|
|||||||
fmt.Println("cannot get the current-context cr", err)
|
fmt.Println("cannot get the current-context cr", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
engineCRD, err := getQliksenseInitCrd(qcr)
|
engineCRD, err := getQliksenseInitCrds(qcr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
customCrd, err := getCustomCrd(qcr)
|
customCrd, err := getCustomCrds(qcr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -51,12 +59,12 @@ func (q *Qliksense) InstallCrds(opts *CrdCommandOptions) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
if engineCRD, err := getQliksenseInitCrd(qcr); err != nil {
|
if engineCRD, err := getQliksenseInitCrds(qcr); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err = qapi.KubectlApply(engineCRD, ""); err != nil {
|
} else if err = qapi.KubectlApply(engineCRD, ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if customCrd, err := getCustomCrd(qcr); err != nil {
|
if customCrd, err := getCustomCrds(qcr); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if customCrd != "" {
|
} else if customCrd != "" {
|
||||||
if err = qapi.KubectlApply(customCrd, ""); err != nil {
|
if err = qapi.KubectlApply(customCrd, ""); err != nil {
|
||||||
@@ -73,7 +81,7 @@ func (q *Qliksense) InstallCrds(opts *CrdCommandOptions) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getQliksenseInitCrd(qcr *qapi.QliksenseCR) (string, error) {
|
func getQliksenseInitCrds(qcr *qapi.QliksenseCR) (string, error) {
|
||||||
var repoPath string
|
var repoPath string
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
@@ -98,7 +106,7 @@ func getQliksenseInitCrd(qcr *qapi.QliksenseCR) (string, error) {
|
|||||||
return string(qInitByte), nil
|
return string(qInitByte), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCustomCrd(qcr *qapi.QliksenseCR) (string, error) {
|
func getCustomCrds(qcr *qapi.QliksenseCR) (string, error) {
|
||||||
crdPath := qcr.GetCustomCrdsPath()
|
crdPath := qcr.GetCustomCrdsPath()
|
||||||
if crdPath == "" {
|
if crdPath == "" {
|
||||||
return "", nil
|
return "", nil
|
||||||
@@ -110,3 +118,77 @@ func getCustomCrd(qcr *qapi.QliksenseCR) (string, error) {
|
|||||||
}
|
}
|
||||||
return string(qInitByte), nil
|
return string(qInitByte), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (q *Qliksense) CheckAllCrdsInstalled() (bool, error) {
|
||||||
|
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||||
|
qcr, err := qConfig.GetCurrentCR()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
customResourceDefinitionInterface, err := getCustomResourceDefinitionInterface()
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if engineCRDs, err := getQliksenseInitCrds(qcr); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if allInstalled, err := checkCrdsInstalled(engineCRDs, customResourceDefinitionInterface); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !allInstalled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if customCrds, err := getCustomCrds(qcr); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if allInstalled, err := checkCrdsInstalled(customCrds, customResourceDefinitionInterface); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !allInstalled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if allInstalled, err := checkCrdsInstalled(q.GetOperatorCRDString(), customResourceDefinitionInterface); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if !allInstalled {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func checkCrdsInstalled(crds string, customResourceDefinitionInterface apixv1beta1client.CustomResourceDefinitionInterface) (bool, error) {
|
||||||
|
kuzResourceFactory := resmap.NewFactory(resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
if kuzResMap, err := kuzResourceFactory.NewResMapFromBytes([]byte(crds)); err != nil {
|
||||||
|
return false, err
|
||||||
|
} else {
|
||||||
|
for _, kuzRes := range kuzResMap.Resources() {
|
||||||
|
if customResourceDefinition, err := customResourceDefinitionInterface.Get(kuzRes.GetName(), v1.GetOptions{}); err != nil && apierrors.IsNotFound(err) {
|
||||||
|
return false, nil
|
||||||
|
} else if err != nil {
|
||||||
|
return false, err
|
||||||
|
} else if customResourceDefinition == nil {
|
||||||
|
return false, fmt.Errorf("failed looking up crd: %v", kuzRes.GetName())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func getCustomResourceDefinitionInterface() (apixv1beta1client.CustomResourceDefinitionInterface, error) {
|
||||||
|
homeDir, err := homedir.Dir()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
kubeconfigPath := filepath.Join(homeDir, ".kube", "config")
|
||||||
|
k8sRestConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
apixClient, err := apixv1beta1client.NewForConfig(k8sRestConfig)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return apixClient.CustomResourceDefinitions(), nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,8 +1,18 @@
|
|||||||
package qliksense
|
package qliksense
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
|
||||||
|
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
|
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
|
||||||
|
"sigs.k8s.io/kustomize/api/resmap"
|
||||||
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
|
|
||||||
|
"github.com/gobuffalo/packr/v2"
|
||||||
|
|
||||||
kapi_config "github.com/qlik-oss/k-apis/pkg/config"
|
kapi_config "github.com/qlik-oss/k-apis/pkg/config"
|
||||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
)
|
)
|
||||||
@@ -13,7 +23,7 @@ func TestGetQliksenseInitCrd(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crdFromContextConfig, err := getQliksenseInitCrd(&qapi.QliksenseCR{
|
crdFromContextConfig, err := getQliksenseInitCrds(&qapi.QliksenseCR{
|
||||||
KApiCr: kapi_config.KApiCr{
|
KApiCr: kapi_config.KApiCr{
|
||||||
Spec: &kapi_config.CRSpec{
|
Spec: &kapi_config.CRSpec{
|
||||||
ManifestsRoot: someTmpRepoPath,
|
ManifestsRoot: someTmpRepoPath,
|
||||||
@@ -24,7 +34,7 @@ func TestGetQliksenseInitCrd(t *testing.T) {
|
|||||||
t.Fatalf("unexpected error: %v", err)
|
t.Fatalf("unexpected error: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
crdFromDownloadedConfig, err := getQliksenseInitCrd(&qapi.QliksenseCR{
|
crdFromDownloadedConfig, err := getQliksenseInitCrds(&qapi.QliksenseCR{
|
||||||
KApiCr: kapi_config.KApiCr{
|
KApiCr: kapi_config.KApiCr{
|
||||||
Spec: &kapi_config.CRSpec{
|
Spec: &kapi_config.CRSpec{
|
||||||
ManifestsRoot: "",
|
ManifestsRoot: "",
|
||||||
@@ -39,3 +49,87 @@ func TestGetQliksenseInitCrd(t *testing.T) {
|
|||||||
t.Fatalf("expected %v to equal %v, but they didn't", crdFromContextConfig, crdFromDownloadedConfig)
|
t.Fatalf("expected %v to equal %v, but they didn't", crdFromContextConfig, crdFromDownloadedConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestCheckAllCrdsInstalled(t *testing.T) {
|
||||||
|
t.Skip("Skipping this test because it makes kubernetes calls")
|
||||||
|
|
||||||
|
tmpQlikSenseHome, err := ioutil.TempDir("", "tmp-qlik-sense-home-")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error creating tmp dir: %v", err)
|
||||||
|
}
|
||||||
|
defer os.RemoveAll(tmpQlikSenseHome)
|
||||||
|
|
||||||
|
setupQliksenseTestDefaultContext(t, tmpQlikSenseHome, `
|
||||||
|
apiVersion: qlik.com/v1
|
||||||
|
kind: Qliksense
|
||||||
|
metadata:
|
||||||
|
name: qlik-default
|
||||||
|
spec:
|
||||||
|
profile: docker-desktop
|
||||||
|
`)
|
||||||
|
|
||||||
|
q := &Qliksense{
|
||||||
|
QliksenseHome: tmpQlikSenseHome,
|
||||||
|
CrdBox: packr.New("crds", "./crds"),
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.FetchQK8s("v1.50.3"); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if allInstalled, err := q.CheckAllCrdsInstalled(); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
} else if allInstalled {
|
||||||
|
t.Fatal("expected crds to NOT be installed at this point")
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := q.InstallCrds(&CrdCommandOptions{All: true}); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
} else if allInstalled, err := q.CheckAllCrdsInstalled(); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
} else if !allInstalled {
|
||||||
|
t.Fatal("expected crds to BE installed at this point")
|
||||||
|
}
|
||||||
|
|
||||||
|
//cleanup:
|
||||||
|
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||||
|
qcr, err := qConfig.GetCurrentCR()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
customResourceDefinitionInterface, err := getCustomResourceDefinitionInterface()
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if engineCRDs, err := getQliksenseInitCrds(qcr); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
} else if err := deleteCrds(engineCRDs, customResourceDefinitionInterface); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if customCrd, err := getCustomCrds(qcr); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
} else if err := deleteCrds(customCrd, customResourceDefinitionInterface); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := deleteCrds(q.GetOperatorCRDString(), customResourceDefinitionInterface); err != nil {
|
||||||
|
t.Fatalf("unexpected error: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteCrds(crds string, customResourceDefinitionInterface apixv1beta1client.CustomResourceDefinitionInterface) error {
|
||||||
|
kuzResourceFactory := resmap.NewFactory(resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()), nil)
|
||||||
|
if kuzResMap, err := kuzResourceFactory.NewResMapFromBytes([]byte(crds)); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
for _, kuzRes := range kuzResMap.Resources() {
|
||||||
|
if err := customResourceDefinitionInterface.Delete(kuzRes.GetName(), &v1.DeleteOptions{}); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -95,9 +95,9 @@ func (q *Qliksense) PullImagesForCurrentCR() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Qliksense) appendGitOpsImage(images *[]string, qcr *qapi.QliksenseCR) {
|
func (q *Qliksense) appendOpsRunnerImage(images *[]string, qcr *qapi.QliksenseCR) {
|
||||||
if qcr.Spec.GitOps != nil && qcr.Spec.GitOps.Image != "" {
|
if qcr.Spec.OpsRunner != nil && qcr.Spec.OpsRunner.Image != "" {
|
||||||
*images = append(*images, qcr.Spec.GitOps.Image)
|
*images = append(*images, qcr.Spec.OpsRunner.Image)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -212,7 +212,7 @@ func (q *Qliksense) appendAdditionalImages(images *[]string, qcr *qapi.Qliksense
|
|||||||
if err := q.appendOperatorImages(images); err != nil {
|
if err := q.appendOperatorImages(images); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
q.appendGitOpsImage(images, qcr)
|
q.appendOpsRunnerImage(images, qcr)
|
||||||
q.appendPreflightImages(images)
|
q.appendPreflightImages(images)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -186,7 +186,7 @@ kind: Qliksense
|
|||||||
metadata:
|
metadata:
|
||||||
name: qlik-default
|
name: qlik-default
|
||||||
spec:
|
spec:
|
||||||
gitOps:
|
opsRunner:
|
||||||
image: some-gitops-image
|
image: some-gitops-image
|
||||||
`)
|
`)
|
||||||
|
|
||||||
@@ -225,7 +225,7 @@ spec:
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
if !haveMatchingImage(func(image string) bool {
|
if !haveMatchingImage(func(image string) bool {
|
||||||
return strings.Contains(image, "qlik-docker-oss.bintray.io/qliksense-operator:v")
|
return strings.Contains(image, "qlik-docker-oss.bintray.io/qliksense-operator:")
|
||||||
}) {
|
}) {
|
||||||
t.Fatal("expected to find the operator image in the list, but it wasn't there")
|
t.Fatal("expected to find the operator image in the list, but it wasn't there")
|
||||||
}
|
}
|
||||||
@@ -245,7 +245,7 @@ spec:
|
|||||||
t.Fatal("expected to find the netcat Preflight image in the list, but it wasn't there")
|
t.Fatal("expected to find the netcat Preflight image in the list, but it wasn't there")
|
||||||
}
|
}
|
||||||
if !haveMatchingImage(func(image string) bool {
|
if !haveMatchingImage(func(image string) bool {
|
||||||
return image == "mongo"
|
return image == "qlik-docker-oss.bintray.io/preflight-mongo"
|
||||||
}) {
|
}) {
|
||||||
t.Fatal("expected to find the mongo Preflight image in the list, but it wasn't there")
|
t.Fatal("expected to find the mongo Preflight image in the list, but it wasn't there")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ package qliksense
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
"errors"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"os"
|
"os"
|
||||||
@@ -54,10 +53,7 @@ func (q *Qliksense) FetchK8sWithOpts(opts *FetchCommandOptions) error {
|
|||||||
cr.SetFetchUrl(opts.GitUrl)
|
cr.SetFetchUrl(opts.GitUrl)
|
||||||
}
|
}
|
||||||
v := getVersion(opts, cr)
|
v := getVersion(opts, cr)
|
||||||
if v == "" {
|
if v != "" && qConfig.IsRepoExistForCurrent(v) {
|
||||||
return errors.New("Cannot find gitref/tag/branch/version to fetch")
|
|
||||||
}
|
|
||||||
if qConfig.IsRepoExistForCurrent(v) {
|
|
||||||
if opts.Overwrite || getVerionsOverwriteConfirmation(v) == "y" {
|
if opts.Overwrite || getVerionsOverwriteConfirmation(v) == "y" {
|
||||||
if err := qConfig.DeleteRepoForCurrent(v); err != nil {
|
if err := qConfig.DeleteRepoForCurrent(v); err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -144,7 +144,7 @@ func getLatestTag(repoUrl, accessToken string) (string, error) {
|
|||||||
v, err := semver.NewVersion(sv)
|
v, err := semver.NewVersion(sv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// it may happen, in the repo some tags may not conform to semver
|
// it may happen, in the repo some tags may not conform to semver
|
||||||
fmt.Print("Unconform tags: " + sv)
|
//fmt.Println("the tag is not conform to semver: " + sv)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if maxSem == nil || maxSem.LessThan(v) {
|
if maxSem == nil || maxSem.LessThan(v) {
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ func TestGetLatestTag(t *testing.T) {
|
|||||||
t.Log(err)
|
t.Log(err)
|
||||||
t.Log(sv)
|
t.Log(sv)
|
||||||
}
|
}
|
||||||
baseV, _ := semver.NewVersion("v0.0.7")
|
baseV, _ := semver.NewVersion("v0.0.8")
|
||||||
if !sv.GreaterThan(baseV) {
|
if !sv.GreaterThan(baseV) {
|
||||||
t.Log("Expected greater than v0.0.7, but got: " + s)
|
t.Log("Expected greater than v0.0.8, but got: " + s)
|
||||||
t.Fail()
|
t.Fail()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,7 +8,9 @@ import (
|
|||||||
"path"
|
"path"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/mitchellh/go-homedir"
|
||||||
"github.com/qlik-oss/k-apis/pkg/config"
|
"github.com/qlik-oss/k-apis/pkg/config"
|
||||||
|
"github.com/qlik-oss/k-apis/pkg/cr"
|
||||||
"sigs.k8s.io/kustomize/api/filesys"
|
"sigs.k8s.io/kustomize/api/filesys"
|
||||||
|
|
||||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
@@ -16,8 +18,9 @@ import (
|
|||||||
|
|
||||||
type InstallCommandOptions struct {
|
type InstallCommandOptions struct {
|
||||||
StorageClass string
|
StorageClass string
|
||||||
MongoDbUri string
|
MongodbUri string
|
||||||
RotateKeys string
|
RotateKeys string
|
||||||
|
DryRun bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, keepPatchFiles bool) error {
|
func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, keepPatchFiles bool) error {
|
||||||
@@ -42,8 +45,8 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
|||||||
}
|
}
|
||||||
|
|
||||||
qcr.SetEULA("yes")
|
qcr.SetEULA("yes")
|
||||||
if opts.MongoDbUri != "" {
|
if opts.MongodbUri != "" {
|
||||||
qcr.Spec.AddToSecrets("qliksense", "mongoDbUri", opts.MongoDbUri, "")
|
qcr.Spec.AddToSecrets("qliksense", "mongodbUri", opts.MongodbUri, "")
|
||||||
}
|
}
|
||||||
if opts.StorageClass != "" {
|
if opts.StorageClass != "" {
|
||||||
qcr.Spec.StorageClassName = opts.StorageClass
|
qcr.Spec.StorageClassName = opts.StorageClass
|
||||||
@@ -51,17 +54,26 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
|||||||
if opts.RotateKeys != "" {
|
if opts.RotateKeys != "" {
|
||||||
qcr.Spec.RotateKeys = opts.RotateKeys
|
qcr.Spec.RotateKeys = opts.RotateKeys
|
||||||
}
|
}
|
||||||
|
// for debugging purpose
|
||||||
|
if opts.DryRun {
|
||||||
|
// generate patches
|
||||||
|
qcr.Spec.RotateKeys = "None"
|
||||||
|
userHomeDir, _ := homedir.Dir()
|
||||||
|
fmt.Println("Generating patches only")
|
||||||
|
cr.GeneratePatches(&qcr.KApiCr, path.Join(userHomeDir, ".kube", "config"))
|
||||||
|
return nil
|
||||||
|
}
|
||||||
qConfig.WriteCurrentContextCR(qcr)
|
qConfig.WriteCurrentContextCR(qcr)
|
||||||
|
|
||||||
//if the docker pull secret exists on disk, install it in the cluster
|
if installed, err := q.CheckAllCrdsInstalled(); err != nil {
|
||||||
//if it doesn't exist on disk, remove it in the cluster
|
fmt.Println("error verifying whether CRDs are installed", err)
|
||||||
if err := installOrRemoveImagePullSecret(qConfig); err != nil {
|
|
||||||
return err
|
return err
|
||||||
|
} else if !installed {
|
||||||
|
return errors.New(`please install CRDs by executing: $ qliksense crds install --all`)
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if acceptEULA is yes or not
|
if err := applyImagePullSecret(qConfig); err != nil {
|
||||||
if !qcr.IsEULA() {
|
return err
|
||||||
return errors.New(agreementTempalte + "\n Please do $ qliksense install --acceptEULA=yes\n")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//CRD will be installed outside of operator
|
//CRD will be installed outside of operator
|
||||||
@@ -76,7 +88,7 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
|||||||
}
|
}
|
||||||
|
|
||||||
// create patch dependent resoruces
|
// create patch dependent resoruces
|
||||||
fmt.Println("Installing resoruces used kuztomize patch")
|
fmt.Println("Installing resources used by the kuztomize patch")
|
||||||
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
|
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -105,7 +117,7 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
|||||||
}
|
}
|
||||||
|
|
||||||
// install generated manifests into cluster
|
// install generated manifests into cluster
|
||||||
fmt.Println("Installing generated manifests into cluster")
|
fmt.Println("Installing generated manifests into the cluster")
|
||||||
|
|
||||||
if dcr, err := qConfig.GetDecryptedCr(qcr); err != nil {
|
if dcr, err := qConfig.GetDecryptedCr(qcr); err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -132,22 +144,13 @@ func (q *Qliksense) getProcessedOperatorControllerString(qcr *qapi.QliksenseCR)
|
|||||||
return operatorControllerString, nil
|
return operatorControllerString, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func installOrRemoveImagePullSecret(qConfig *qapi.QliksenseConfig) error {
|
func applyImagePullSecret(qConfig *qapi.QliksenseConfig) error {
|
||||||
if pullDockerConfigJsonSecret, err := qConfig.GetPullDockerConfigJsonSecret(); err == nil {
|
if pullDockerConfigJsonSecret, err := qConfig.GetPullDockerConfigJsonSecret(); err == nil {
|
||||||
if dockerConfigJsonSecretYaml, err := pullDockerConfigJsonSecret.ToYaml(""); err != nil {
|
if dockerConfigJsonSecretYaml, err := pullDockerConfigJsonSecret.ToYaml(""); err != nil {
|
||||||
return err
|
return err
|
||||||
} else if err := qapi.KubectlApply(string(dockerConfigJsonSecretYaml), ""); err != nil {
|
} else if err := qapi.KubectlApply(string(dockerConfigJsonSecretYaml), ""); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
deleteDockerConfigJsonSecret := qapi.DockerConfigJsonSecret{
|
|
||||||
Name: pullSecretName,
|
|
||||||
}
|
|
||||||
if deleteDockerConfigJsonSecretYaml, err := deleteDockerConfigJsonSecret.ToYaml(""); err != nil {
|
|
||||||
return err
|
|
||||||
} else if err := qapi.KubectlDelete(string(deleteDockerConfigJsonSecretYaml), ""); err != nil {
|
|
||||||
qapi.LogDebugMessage("failed deleting %v, error: %v\n", pullSecretName, err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -192,7 +195,7 @@ images:
|
|||||||
func (q *Qliksense) applyCR(cr *qapi.QliksenseCR) error {
|
func (q *Qliksense) applyCR(cr *qapi.QliksenseCR) error {
|
||||||
// install operator cr into cluster
|
// install operator cr into cluster
|
||||||
//get the current context cr
|
//get the current context cr
|
||||||
fmt.Println("Install operator CR into cluster")
|
fmt.Println("Installing operator CR into the cluster")
|
||||||
r, err := cr.GetString()
|
r, err := cr.GetString()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
|
|||||||
@@ -43,7 +43,7 @@ spec:
|
|||||||
value: "yes"
|
value: "yes"
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||||
profile: docker-desktop
|
profile: docker-desktop
|
||||||
rotateKeys: "yes"`
|
rotateKeys: "yes"`
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ import (
|
|||||||
"sigs.k8s.io/kustomize/api/resource"
|
"sigs.k8s.io/kustomize/api/resource"
|
||||||
"sigs.k8s.io/kustomize/api/types"
|
"sigs.k8s.io/kustomize/api/types"
|
||||||
|
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v2"
|
||||||
|
|
||||||
"github.com/Shopify/ejson"
|
"github.com/Shopify/ejson"
|
||||||
"github.com/qlik-oss/k-apis/pkg/config"
|
"github.com/qlik-oss/k-apis/pkg/config"
|
||||||
@@ -310,8 +310,8 @@ func Test_executeKustomizeBuild_onQlikConfig_regenerateKeys(t *testing.T) {
|
|||||||
}
|
}
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if resource["kind"].(string) == "Secret" && strings.Contains(resource["metadata"].(map[string]interface{})["name"].(string), "users-secrets-") {
|
if resource["kind"].(string) == "Secret" && strings.Contains(resource["metadata"].(map[interface {}]interface {})["name"].(string), "users-secrets-") {
|
||||||
keyIdBase64 = resource["data"].(map[string]interface{})["tokenAuthPrivateKeyId"].(string)
|
keyIdBase64 = resource["data"].(map[interface {}]interface {})["tokenAuthPrivateKeyId"].(string)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ spec:
|
|||||||
value: "yes"
|
value: "yes"
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||||
profile: docker-desktop
|
profile: docker-desktop
|
||||||
rotateKeys: "yes"`
|
rotateKeys: "yes"`
|
||||||
@@ -62,7 +62,7 @@ spec:
|
|||||||
value: "yes"
|
value: "yes"
|
||||||
secrets:
|
secrets:
|
||||||
qliksense:
|
qliksense:
|
||||||
- name: mongoDbUri
|
- name: mongodbUri
|
||||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||||
profile: docker-desktop
|
profile: docker-desktop
|
||||||
rotateKeys: "yes"`
|
rotateKeys: "yes"`
|
||||||
|
|||||||
Reference in New Issue
Block a user