Compare commits
13 Commits
upgrade_li
...
dry-run
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
99b442020f | ||
|
|
9c6e83152d | ||
|
|
a9a9d464c0 | ||
|
|
9d0ac0290f | ||
|
|
ef3224fb2c | ||
|
|
dd8a48b2b8 | ||
|
|
9fb6800993 | ||
|
|
bbb811a879 | ||
|
|
8156b884ce | ||
|
|
7525c2e698 | ||
|
|
60763e034a | ||
|
|
ce4081a422 | ||
|
|
dd503a40c1 |
@@ -37,7 +37,7 @@ func applyCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
||||
c.MarkFlagRequired("file")
|
||||
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.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
|
||||
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
|
||||
}
|
||||
|
||||
@@ -71,11 +71,13 @@ func installCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
|
||||
f := c.Flags()
|
||||
f.StringVarP(&opts.StorageClass, "storageClass", "s", "", "Storage class for qliksense")
|
||||
f.StringVarP(&opts.MongoDbUri, "mongoDbUri", "m", "", "mongoDbUri for qliksense (i.e. mongodb://qlik-default-mongodb:27017/qliksense?ssl=false)")
|
||||
f.StringVarP(&opts.MongodbUri, "mongodbUri", "m", "", "mongodbUri for qliksense (i.e. mongodb://qlik-default-mongodb:27017/qliksense?ssl=false)")
|
||||
f.StringVarP(&opts.RotateKeys, "rotateKeys", "r", "", "Rotate JWT keys for qliksense (yes:rotate keys/ no:use exising keys from cluster/ None: use default EJSON_KEY from env")
|
||||
f.BoolVar(&keepPatchFiles, keepPatchFilesFlagName, keepPatchFiles, keepPatchFilesFlagUsage)
|
||||
f.StringVarP(&filePath, "file", "f", "", "Install from a CR file")
|
||||
|
||||
f.BoolVarP(&opts.DryRun, "dry-run", "", false, "Dry run will generate the patches without rotating keys")
|
||||
|
||||
f.BoolVarP(&pull, pullFlagName, pullFlagShorthand, pull, pullFlagUsage)
|
||||
f.BoolVarP(&push, pushFlagName, pushFlagShorthand, push, pushFlagUsage)
|
||||
|
||||
|
||||
@@ -12,12 +12,17 @@ import (
|
||||
)
|
||||
|
||||
func preflightCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
preflightOpts := &preflight.PreflightOptions{
|
||||
MongoOptions: &preflight.MongoOptions{},
|
||||
}
|
||||
var preflightCmd = &cobra.Command{
|
||||
Use: "preflight",
|
||||
Short: "perform preflight checks on the cluster",
|
||||
Long: `perform preflight checks on the cluster`,
|
||||
Example: `qliksense preflight <preflight_check_to_run>`,
|
||||
}
|
||||
f := preflightCmd.Flags()
|
||||
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||
return preflightCmd
|
||||
}
|
||||
|
||||
@@ -131,12 +136,7 @@ func pfAllChecksCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
f := preflightAllChecksCmd.Flags()
|
||||
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.MongodbUrl, "mongodb-url", "", "", "mongodbUrl to try connecting to")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.Username, "mongodb-username", "", "", "username to connect to mongodb")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.Password, "mongodb-password", "", "", "password to connect to mongodb")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.CaCertFile, "mongodb-ca-cert", "", "", "certificate to use for mongodb check")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.ClientCertFile, "mongodb-client-cert", "", "", "client-certificate to use for mongodb check")
|
||||
f.BoolVar(&preflightOpts.MongoOptions.Tls, "mongodb-tls", false, "enable tls?")
|
||||
|
||||
return preflightAllChecksCmd
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ func pfDeploymentCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
}
|
||||
var pfDeploymentCheckCmd = &cobra.Command{
|
||||
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`,
|
||||
Example: `qliksense preflight deployment`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
@@ -332,7 +332,7 @@ func pfCreateServiceAccountCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
|
||||
var preflightServiceAccountCmd = &cobra.Command{
|
||||
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`,
|
||||
Example: `qliksense preflight serviceaccount`,
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
@@ -429,11 +429,7 @@ func pfMongoCheckCmd(q *qliksense.Qliksense) *cobra.Command {
|
||||
f := preflightMongoCmd.Flags()
|
||||
f.BoolVarP(&preflightOpts.Verbose, "verbose", "v", false, "verbose mode")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.MongodbUrl, "url", "", "", "mongodbUrl to try connecting to")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.Username, "username", "", "", "username to connect to mongodb")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.Password, "password", "", "", "password to connect to mongodb")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.CaCertFile, "ca-cert", "", "", "ca certificate to use for mongodb check")
|
||||
f.StringVarP(&preflightOpts.MongoOptions.ClientCertFile, "client-cert", "", "", "client-certificate to use for mongodb check")
|
||||
f.BoolVar(&preflightOpts.MongoOptions.Tls, "tls", false, "enable tls?")
|
||||
return preflightMongoCmd
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ import (
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
. "github.com/logrusorgru/aurora"
|
||||
ansi "github.com/mattn/go-colorable"
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/qlik-oss/sense-installer/pkg"
|
||||
@@ -15,7 +16,6 @@ import (
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
. "github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
// To run this project in debug mode, run:
|
||||
@@ -46,7 +46,7 @@ func initAndExecute() error {
|
||||
log.Fatal(err)
|
||||
}
|
||||
// create dirs and appropriate files for setting up contexts
|
||||
api.LogDebugMessage("QliksenseHomeDir: %s", qlikSenseHome)
|
||||
api.LogDebugMessage("QliksenseHomeDir: %s\n", qlikSenseHome)
|
||||
|
||||
qliksenseClient := qliksense.New(qlikSenseHome)
|
||||
cmd := rootCmd(qliksenseClient)
|
||||
@@ -122,6 +122,7 @@ func getRootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
globalEulaPostRun(cmd, p)
|
||||
}
|
||||
},
|
||||
SilenceUsage: true,
|
||||
}
|
||||
origHelpFunc := cmd.HelpFunc()
|
||||
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
|
||||
configCmd.AddCommand(cleanConfigRepoPatchesCmd(p))
|
||||
|
||||
|
||||
// open editor for config
|
||||
configCmd.AddCommand(configEditCmd(p))
|
||||
|
||||
// add unset for config
|
||||
configCmd.AddCommand((unsetCmd(p)))
|
||||
|
||||
// add uninstall command
|
||||
cmd.AddCommand(uninstallCmd(p))
|
||||
|
||||
|
||||
@@ -23,6 +23,12 @@ Run the following command to execute a specific check
|
||||
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` command takes input from a file or from pipe
|
||||
@@ -57,7 +63,7 @@ spec:
|
||||
value: "yes"
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: mongodb://qlik-test-mongodb:27017/qliksense?ssl=false
|
||||
profile: docker-desktop
|
||||
rotateKeys: "yes"
|
||||
@@ -98,7 +104,7 @@ spec:
|
||||
value: "yes"
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: "mongo://mongo:3307"
|
||||
- name: messagingPassword
|
||||
valueFromKey: messagingPassword
|
||||
|
||||
@@ -23,7 +23,7 @@ spec:
|
||||
profile: docker-desktop
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||
rotateKeys: "yes"
|
||||
releaseName: qlik-default
|
||||
|
||||
@@ -16,19 +16,29 @@ Examples:
|
||||
qliksense preflight <preflight_check_to_run>
|
||||
|
||||
Available Commands:
|
||||
all perform all checks
|
||||
dns perform preflight dns check
|
||||
k8s-version check k8s version
|
||||
all perform all checks
|
||||
authcheck preflight authcheck
|
||||
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:
|
||||
-h, --help help for preflight
|
||||
-v, --verbose verbose mode
|
||||
```
|
||||
|
||||
### 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.
|
||||
The expected output should be similar to the one shown below.
|
||||
```shell
|
||||
$ qliksense preflight dns
|
||||
$ qliksense preflight dns -v
|
||||
|
||||
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.
|
||||
The command to run this check and the expected similar output are as shown below:
|
||||
```shell
|
||||
$ qliksense preflight k8s-version
|
||||
$ qliksense preflight k8s-version -v
|
||||
|
||||
Preflight kubernetes minimum version check
|
||||
------------------------------------------
|
||||
@@ -66,7 +76,7 @@ Completed Preflight kubernetes minimum version check
|
||||
### Service check
|
||||
We use the commmand below to test if we are able to create a service in the cluster.
|
||||
```shell
|
||||
$ qliksense preflight service
|
||||
$ qliksense preflight service -v
|
||||
|
||||
Preflight service check
|
||||
-----------------------
|
||||
@@ -82,7 +92,7 @@ Completed preflight service check
|
||||
### Deployment check
|
||||
We use the commmand below to test if we are able to create a deployment in the cluster. After the test exexutes, we wait until the created deployment terminates before we exit the command.
|
||||
```shell
|
||||
$ qliksense preflight deployment
|
||||
$ qliksense preflight deployment -v
|
||||
|
||||
Preflight deployment check
|
||||
-----------------------
|
||||
@@ -97,7 +107,7 @@ Completed preflight deployment check
|
||||
### Pod check
|
||||
We use the commmand below to test if we are able to create a pod in the cluster.
|
||||
```shell
|
||||
$ qliksense preflight pod
|
||||
$ qliksense preflight pod -v
|
||||
|
||||
Preflight pod check
|
||||
--------------------
|
||||
@@ -110,61 +120,61 @@ Deleted pod: pod-pf-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
|
||||
```shell
|
||||
$ qliksense preflight create-role
|
||||
Preflight create-role check
|
||||
$ qliksense preflight role -v
|
||||
Preflight role check
|
||||
---------------------------
|
||||
Preflight create-role check:
|
||||
Preflight role check:
|
||||
Created role: role-preflight-check
|
||||
Preflight create-role check: PASSED
|
||||
Preflight role check: PASSED
|
||||
Cleaning up resources...
|
||||
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
|
||||
```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
|
||||
Preflight createRoleBinding check: PASSED
|
||||
Preflight rolebinding check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleting RoleBinding: role-binding-preflight-check
|
||||
Deleted RoleBinding: role-binding-preflight-check
|
||||
|
||||
Completed preflight createRoleBinding check
|
||||
Completed preflight rolebinding check
|
||||
```
|
||||
|
||||
### Create-ServiceAccount check
|
||||
We use the command below to test if we are able to create a service account in the cluster
|
||||
```shell
|
||||
$ qliksense preflight createServiceAccount
|
||||
$ qliksense preflight serviceaccount -v
|
||||
|
||||
Preflight create ServiceAccount check
|
||||
Preflight ServiceAccount check
|
||||
-------------------------------------
|
||||
Preflight createServiceAccount check:
|
||||
Preflight serviceaccount check:
|
||||
Created Service Account: preflight-check-test-serviceaccount
|
||||
Preflight createServiceAccount check: PASSED
|
||||
Preflight serviceaccount check: PASSED
|
||||
Cleaning up resources...
|
||||
Deleting 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
|
||||
```shell
|
||||
$ qliksense preflight createRB
|
||||
$ qliksense preflight authcheck -v
|
||||
|
||||
Preflight createRB check
|
||||
Preflight auth check
|
||||
-------------------------------------
|
||||
Preflight create-role check:
|
||||
Created role: role-preflight-check
|
||||
@@ -189,18 +199,18 @@ Cleaning up resources...
|
||||
Deleted ServiceAccount: preflight-check-test-serviceaccount
|
||||
|
||||
Completed preflight createServiceAccount check
|
||||
Completed preflight CreateRB check
|
||||
Completed preflight auth check
|
||||
```
|
||||
|
||||
### Mongodb check
|
||||
We can check if we are able to connect to an instance of mongodb on the cluster by either supplying the mongodbUri as part of the command or infer it from the current context.
|
||||
|
||||
```shell
|
||||
qliksense preflight mongo --url=<url> OR
|
||||
qliksense preflight mongo
|
||||
qliksense preflight mongo --url=<mongo-server url> --ca-cert=<path to ca-cert file>
|
||||
|
||||
|
||||
qliksense preflight mongo --url=<url> -v OR
|
||||
qliksense preflight mongo -v
|
||||
qliksense preflight mongo --url=<mongo-server url> --ca-cert=<path to ca-cert file> -v
|
||||
```
|
||||
```shell
|
||||
Preflight mongo check
|
||||
---------------------
|
||||
Preflight mongodb check:
|
||||
@@ -216,13 +226,35 @@ Deleted pod: pf-mongo-pod
|
||||
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
|
||||
Run the command shown below to execute all preflight checks.
|
||||
```shell
|
||||
$ qliksense preflight all --mongodb-url=<url> OR
|
||||
$ qliksense preflight all --mongodb-url=<mongo-server url> --mongodb-ca-cert=<path to ca-cert file>
|
||||
$ qliksense preflight all --mongodb-url=<url> -v OR
|
||||
$ qliksense preflight all --mongodb-url=<mongo-server url> --mongodb-ca-cert=<path to ca-cert file> -v
|
||||
|
||||
Running all preflight checks
|
||||
|
||||
@@ -253,4 +285,23 @@ Completed Preflight kubernetes minimum version check
|
||||
All preflight checks have PASSED
|
||||
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
|
||||
|
||||
```
|
||||
|
||||
5
go.mod
5
go.mod
@@ -10,7 +10,7 @@ replace (
|
||||
k8s.io/client-go => k8s.io/client-go v0.17.0
|
||||
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 (
|
||||
@@ -40,7 +40,7 @@ require (
|
||||
github.com/mitchellh/go-homedir v1.1.0
|
||||
github.com/otiai10/copy v1.1.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/rogpeppe/go-internal v1.5.2 // indirect
|
||||
github.com/spf13/cobra v0.0.6
|
||||
@@ -51,7 +51,6 @@ require (
|
||||
golang.org/x/tools v0.0.0-20200312194400-c312e98713c2 // indirect
|
||||
google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b // indirect
|
||||
gopkg.in/yaml.v2 v2.2.8
|
||||
gopkg.in/yaml.v3 v3.0.0-20190924164351-c8b7dadae555
|
||||
k8s.io/api v0.17.2
|
||||
k8s.io/apimachinery v0.17.2
|
||||
k8s.io/client-go v11.0.0+incompatible
|
||||
|
||||
10
go.sum
10
go.sum
@@ -883,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/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDaekg4FpcdQ=
|
||||
github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU=
|
||||
github.com/qlik-oss/k-apis v0.1.1 h1:aZ4eTMB3mSn03Kuj7+RI0eFLkjK9+0qxADBioRb3qVA=
|
||||
github.com/qlik-oss/k-apis v0.1.1/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/kustomize/api v0.3.3-0.20200424070349-b0312eb71568/go.mod h1:Yg8bqX8Mq/eSgXfcenxCxhZuSXg+NCsKq6NBdch/oUc=
|
||||
github.com/qlik-oss/k-apis v0.1.2 h1:BBcrXl+NxdsvuRsZuJbvIFxMv5QIXqWBzhXOcr5KUX8=
|
||||
github.com/qlik-oss/k-apis v0.1.2/go.mod h1:yoYGgPJ/H0t9H3NSq64dWfyQY6QWi2L9c+hCJoVO03U=
|
||||
github.com/qlik-oss/k-apis v0.1.4 h1:YXnjKXm/yhPblzYYyVCtD0dNbIkLPLlDdBKnjeYW0IY=
|
||||
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/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=
|
||||
|
||||
@@ -157,6 +157,8 @@ func (cr *QliksenseCR) GetFetchAccessToken(encryptionKey string) string {
|
||||
if tok, err := cr.Spec.FetchSource.GetAccessToken(); err != nil {
|
||||
fmt.Println(err)
|
||||
return ""
|
||||
} else if tok == "" {
|
||||
return tok
|
||||
} else {
|
||||
by, _ := b64.StdEncoding.DecodeString(tok)
|
||||
res, err := DecryptData(by, encryptionKey)
|
||||
|
||||
@@ -107,7 +107,7 @@ func TestGetDecryptedCr(t *testing.T) {
|
||||
key, _ := setupGenerateKey(dir)
|
||||
ecn, _ := EncryptData([]byte("mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"), key)
|
||||
b := b64.StdEncoding.EncodeToString(ecn)
|
||||
qcr.Spec.AddToSecrets("qliksense", "mongoDbUri", b, "")
|
||||
qcr.Spec.AddToSecrets("qliksense", "mongodbUri", b, "")
|
||||
|
||||
qcr.SetFetchAccessToken("mytoken", key)
|
||||
|
||||
@@ -117,8 +117,8 @@ func TestGetDecryptedCr(t *testing.T) {
|
||||
t.Log(err)
|
||||
}
|
||||
|
||||
decryptedValue := newCr.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
||||
orignalValue := qcr.Spec.GetFromSecrets("qliksense", "mongoDbUri")
|
||||
decryptedValue := newCr.Spec.GetFromSecrets("qliksense", "mongodbUri")
|
||||
orignalValue := qcr.Spec.GetFromSecrets("qliksense", "mongodbUri")
|
||||
if decryptedValue != "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false" {
|
||||
t.Fail()
|
||||
b, _ := K8sToYaml(newCr)
|
||||
|
||||
@@ -24,8 +24,8 @@ const (
|
||||
QliksenseDefaultProfile = "docker-desktop"
|
||||
DefaultRotateKeys = "yes"
|
||||
QliksenseMetadataName = "QliksenseConfigMetadata"
|
||||
DefaultMongoDbUri = "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"
|
||||
DefaultMongoDbUriKey = "mongoDbUri"
|
||||
DefaultMongodbUri = "mongodb://qlik-default-mongodb:27017/qliksense?ssl=false"
|
||||
DefaultMongodbUriKey = "mongodbUri"
|
||||
)
|
||||
|
||||
// AddCommonConfig adds common configs into CRs
|
||||
@@ -40,7 +40,7 @@ func (qliksenseCR *QliksenseCR) AddCommonConfig(contextName string) {
|
||||
Profile: QliksenseDefaultProfile,
|
||||
RotateKeys: DefaultRotateKeys,
|
||||
}
|
||||
qliksenseCR.Spec.AddToSecrets("qliksense", DefaultMongoDbUriKey, DefaultMongoDbUri, "")
|
||||
qliksenseCR.Spec.AddToSecrets("qliksense", DefaultMongodbUriKey, DefaultMongodbUri, "")
|
||||
}
|
||||
|
||||
// AddBaseQliksenseConfigs adds configs into config.yaml
|
||||
@@ -96,7 +96,7 @@ func WriteToFile(content interface{}, targetFile string) error {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
LogDebugMessage("Wrote content into %s", targetFile)
|
||||
LogDebugMessage("Wrote content into %s\n", targetFile)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ func TestAddCommonConfig(t *testing.T) {
|
||||
RotateKeys: DefaultRotateKeys,
|
||||
Secrets: map[string]config.NameValues{
|
||||
"qliksense": []config.NameValue{{
|
||||
Name: DefaultMongoDbUriKey,
|
||||
Value: DefaultMongoDbUri,
|
||||
Name: DefaultMongodbUriKey,
|
||||
Value: DefaultMongodbUri,
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
@@ -17,8 +17,9 @@ type PreflightConfig struct {
|
||||
}
|
||||
|
||||
type PreflightSpec struct {
|
||||
MinK8sVersion string `json:"minK8sVersion,omitempty" yaml:"minK8sVersion,omitempty"`
|
||||
Images map[string]string `json:"images,omitempty" yaml:"images,omitempty"`
|
||||
MinK8sVersion string `json:"minK8sVersion,omitempty" yaml:"minK8sVersion,omitempty"`
|
||||
MinMongoVersion string `json:"minMongoVersion,omitempty" yaml:"minMongoVersion,omitempty"`
|
||||
Images map[string]string `json:"images,omitempty" yaml:"images,omitempty"`
|
||||
}
|
||||
|
||||
//NewPreflightConfigEmpty create empty PreflightConfig object
|
||||
@@ -74,6 +75,13 @@ func (p *PreflightConfig) AddMinK8sV(version string) {
|
||||
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) {
|
||||
if p.Spec.Images == nil {
|
||||
p.Spec.Images = make(map[string]string)
|
||||
@@ -101,6 +109,11 @@ func (p *PreflightConfig) GetImageName(imageFor string, accountForImageRegistry
|
||||
func (p *PreflightConfig) GetMinK8sVersion() string {
|
||||
return p.Spec.MinK8sVersion
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) GetMinMongoVersion() string {
|
||||
return p.Spec.MinMongoVersion
|
||||
}
|
||||
|
||||
func (p *PreflightConfig) IsExistOnDisk() bool {
|
||||
if _, err := os.Lstat(p.GetConfigFilePath()); err != nil {
|
||||
return false
|
||||
@@ -117,8 +130,9 @@ func (p *PreflightConfig) Initialize() error {
|
||||
return nil
|
||||
}
|
||||
p.AddMinK8sV("1.15")
|
||||
p.AddMinMongoV("3.6")
|
||||
p.AddImage("nginx", "nginx")
|
||||
p.AddImage("netcat", "subfuzion/netcat")
|
||||
p.AddImage("mongo", "mongo")
|
||||
p.AddImage("preflight-mongo", "qlik-docker-oss.bintray.io/preflight-mongo")
|
||||
return p.Write()
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@ func checkExists(filename string) os.FileInfo {
|
||||
if os.IsNotExist(err) {
|
||||
return nil
|
||||
}
|
||||
LogDebugMessage("File exists")
|
||||
LogDebugMessage("File exists\n")
|
||||
return info
|
||||
}
|
||||
|
||||
@@ -73,7 +73,7 @@ func ProcessConfigArgs(args []string, base64Encoded bool) ([]*ServiceKeyValue, e
|
||||
resultSvcKV := make([]*ServiceKeyValue, len(args))
|
||||
// qliksense.mongodb=somethig
|
||||
for i, arg := range args {
|
||||
LogDebugMessage("Arg received: %s", arg)
|
||||
LogDebugMessage("Arg received: %s\n", arg)
|
||||
first := strings.SplitN(arg, "=", 2)
|
||||
if len(first) != 2 {
|
||||
return nil, notValidErr
|
||||
|
||||
@@ -3,8 +3,12 @@ package preflight
|
||||
import (
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/Masterminds/semver/v3"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
@@ -12,7 +16,8 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
mongo = "mongo"
|
||||
preflight_mongo = "preflight-mongo"
|
||||
caCertMountPath = "/etc/ssl/certs/ca-certificates.crt"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||
@@ -20,32 +25,51 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
qp.P.LogVerboseMessage("Preflight mongodb check: \n")
|
||||
qp.P.LogVerboseMessage("------------------------ \n")
|
||||
}
|
||||
if preflightOpts != nil && preflightOpts.MongoOptions.MongodbUrl == "" && !cleanup {
|
||||
// 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
|
||||
var err error
|
||||
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
|
||||
}
|
||||
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")
|
||||
}
|
||||
@@ -53,8 +77,7 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||
caCertSecretName := "preflight-mongo-test-cacert"
|
||||
clientCertSecretName := "preflight-mongo-test-clientcert"
|
||||
caCertSecretName := "ca-certificates-crt"
|
||||
mongoPodName := "pf-mongo-pod"
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
@@ -63,11 +86,11 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
}
|
||||
|
||||
// cleanup before starting check
|
||||
qp.runMongoCleanup(clientset, namespace, mongoPodName, caCertSecretName, clientCertSecretName)
|
||||
qp.runMongoCleanup(clientset, namespace, mongoPodName, caCertSecretName)
|
||||
if cleanup {
|
||||
return nil
|
||||
}
|
||||
var secrets []string
|
||||
secrets := map[string]string{}
|
||||
if preflightOpts.MongoOptions.CaCertFile != "" {
|
||||
caCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.CaCertFile, caCertSecretName)
|
||||
if err != nil {
|
||||
@@ -76,52 +99,19 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
}
|
||||
|
||||
defer qp.deleteK8sSecret(clientset, namespace, caCertSecret.Name)
|
||||
secrets = append(secrets, caCertSecretName)
|
||||
}
|
||||
if preflightOpts.MongoOptions.ClientCertFile != "" {
|
||||
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.Name)
|
||||
secrets = append(secrets, clientCertSecretName)
|
||||
secrets[caCertSecretName] = caCertMountPath
|
||||
}
|
||||
|
||||
mongoCommand := strings.Builder{}
|
||||
mongoCommand.WriteString(fmt.Sprintf("sleep 10;mongo %s", preflightOpts.MongoOptions.MongodbUrl))
|
||||
if preflightOpts.MongoOptions.Username != "" {
|
||||
mongoCommand.WriteString(fmt.Sprintf(" --username %s", preflightOpts.MongoOptions.Username))
|
||||
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()}
|
||||
commandToRun := []string{"./preflight-mongo", fmt.Sprintf(`-url="%s"`, preflightOpts.MongoOptions.MongodbUrl)}
|
||||
api.LogDebugMessage("Mongo command: %s\n", strings.Join(commandToRun, " "))
|
||||
|
||||
// create a pod
|
||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(mongo, true)
|
||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(preflight_mongo, true)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to retrieve image : %v\n", err)
|
||||
return err
|
||||
}
|
||||
api.LogDebugMessage("image name to be used: %s\n", imageName)
|
||||
mongoPod, err := qp.createPreflightTestPod(clientset, namespace, mongoPodName, imageName, secrets, commandToRun)
|
||||
if err != nil {
|
||||
err = fmt.Errorf("unable to create pod : %v\n", err)
|
||||
@@ -143,7 +133,14 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
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) {
|
||||
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
|
||||
} else {
|
||||
@@ -153,6 +150,43 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
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) {
|
||||
certBytes, err := ioutil.ReadFile(certFile)
|
||||
if err != nil {
|
||||
@@ -161,14 +195,13 @@ func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, name
|
||||
|
||||
certSecret, err := qp.createPreflightTestSecret(clientset, namespace, certSecretName, certBytes)
|
||||
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 certSecret, nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, namespace, mongoPodName, caCertSecretName, clientCertSecretName string) {
|
||||
func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, namespace, mongoPodName, caCertSecretName string) {
|
||||
qp.deletePod(clientset, namespace, mongoPodName)
|
||||
qp.deleteK8sSecret(clientset, namespace, caCertSecretName)
|
||||
qp.deleteK8sSecret(clientset, namespace, clientCertSecretName)
|
||||
}
|
||||
|
||||
@@ -12,7 +12,6 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/pkg/errors"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||
appsv1 "k8s.io/api/apps/v1"
|
||||
@@ -40,12 +39,8 @@ func (p *PreflightOptions) LogVerboseMessage(strMessage string, args ...interfac
|
||||
}
|
||||
|
||||
type MongoOptions struct {
|
||||
MongodbUrl string
|
||||
Username string
|
||||
Password string
|
||||
CaCertFile string
|
||||
ClientCertFile string
|
||||
Tls bool
|
||||
MongodbUrl string
|
||||
CaCertFile string
|
||||
}
|
||||
|
||||
var gracePeriod int64 = 0
|
||||
@@ -115,13 +110,13 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
|
||||
if len(kubeconfig) == 0 {
|
||||
clientConfig, err = rest.InClusterConfig()
|
||||
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
|
||||
}
|
||||
} else {
|
||||
config, err := clientcmd.Load(kubeconfig)
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to load kubeconfig")
|
||||
err = fmt.Errorf("Unable to load kubeconfig: %w", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
if contextName != "" {
|
||||
@@ -129,13 +124,13 @@ func getK8SClientSet(kubeconfig []byte, contextName string) (*kubernetes.Clients
|
||||
}
|
||||
clientConfig, err = clientcmd.NewDefaultClientConfig(*config, &clientcmd.ConfigOverrides{}).ClientConfig()
|
||||
if err != nil {
|
||||
err = errors.Wrap(err, "Unable to create client config from config")
|
||||
err = fmt.Errorf("Unable to create client config from config: %w", err)
|
||||
return nil, nil, err
|
||||
}
|
||||
}
|
||||
clientset, err := kubernetes.NewForConfig(clientConfig)
|
||||
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 clientset, clientConfig, nil
|
||||
@@ -186,7 +181,7 @@ func (qp *QliksensePreflight) createPreflightTestDeployment(clientset *kubernete
|
||||
result, err = deploymentsClient.Create(deployment)
|
||||
return err
|
||||
}); err != nil {
|
||||
err = errors.Wrapf(err, "unable to create deployments in the %s namespace", namespace)
|
||||
err = fmt.Errorf("unable to create deployments in the %s namespace: %w", namespace, err)
|
||||
return nil, err
|
||||
}
|
||||
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{})
|
||||
return err
|
||||
}); 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)
|
||||
return nil, err
|
||||
}
|
||||
@@ -271,7 +266,7 @@ func getService(clientset *kubernetes.Clientset, namespace, svcName string) (*ap
|
||||
svc, err = servicesClient.Get(svcName, v1.GetOptions{})
|
||||
return err
|
||||
}); 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
|
||||
}
|
||||
|
||||
@@ -314,7 +309,7 @@ func (qp *QliksensePreflight) deletePod(clientset *kubernetes.Clientset, namespa
|
||||
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
|
||||
pod := &apiv1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
@@ -337,7 +332,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
||||
},
|
||||
}
|
||||
if len(secretNames) > 0 {
|
||||
for _, secretName := range secretNames {
|
||||
for secretName, mountPath := range secretNames {
|
||||
pod.Spec.Volumes = append(pod.Spec.Volumes, apiv1.Volume{
|
||||
Name: secretName,
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
@@ -346,7 +341,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: secretName,
|
||||
Path: secretName,
|
||||
Path: filepath.Base(mountPath),
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -355,7 +350,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
||||
if len(pod.Spec.Containers) > 0 {
|
||||
pod.Spec.Containers[0].VolumeMounts = append(pod.Spec.Containers[0].VolumeMounts, apiv1.VolumeMount{
|
||||
Name: secretName,
|
||||
MountPath: "/etc/ssl/" + secretName,
|
||||
MountPath: filepath.Dir(mountPath),
|
||||
ReadOnly: true,
|
||||
})
|
||||
}
|
||||
@@ -470,13 +465,13 @@ func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Po
|
||||
}
|
||||
validateFunc := func(data interface{}) bool {
|
||||
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 {
|
||||
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")
|
||||
return err
|
||||
}
|
||||
@@ -491,7 +486,6 @@ func waitForPodToDie(clientset *kubernetes.Clientset, namespace string, pod *api
|
||||
err = fmt.Errorf("unable to retrieve %s pod by name", podName)
|
||||
return nil, err
|
||||
}
|
||||
api.LogDebugMessage("pod status: %v\n", po.Status.Phase)
|
||||
return po, nil
|
||||
}
|
||||
validateFunc := func(r interface{}) bool {
|
||||
|
||||
@@ -18,12 +18,12 @@ import (
|
||||
|
||||
b64 "encoding/base64"
|
||||
|
||||
. "github.com/logrusorgru/aurora"
|
||||
ansi "github.com/mattn/go-colorable"
|
||||
"github.com/qlik-oss/sense-installer/pkg/api"
|
||||
_ "gopkg.in/yaml.v2"
|
||||
v1 "k8s.io/api/core/v1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
. "github.com/logrusorgru/aurora"
|
||||
)
|
||||
|
||||
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
|
||||
api.LogDebugMessage("Current context: %s", qliksenseCR.GetName())
|
||||
api.LogDebugMessage("Current context: %s\n", qliksenseCR.GetName())
|
||||
encryptionKey, err := qConfig.GetEncryptionKeyForCurrent()
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -72,7 +72,7 @@ func (q *Qliksense) SetSecrets(args []string, isSecretSet bool, base64Encoded bo
|
||||
return err
|
||||
}
|
||||
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 {
|
||||
return err
|
||||
}
|
||||
@@ -213,8 +213,8 @@ func validateCR(key string, keySub string, value string, crSpec *api.QliksenseCR
|
||||
}
|
||||
} else {
|
||||
switch key {
|
||||
case "gitops":
|
||||
crSpec.Spec.GitOps = &config.GitOps{}
|
||||
case "opsrunner":
|
||||
crSpec.Spec.OpsRunner = &config.OpsRunner{}
|
||||
case "git":
|
||||
crSpec.Spec.Git = &config.Repo{}
|
||||
}
|
||||
@@ -248,8 +248,8 @@ func (q *Qliksense) SetOtherConfigs(args []string) error {
|
||||
if err := q.processSetGit(arg, qliksenseCR); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if strings.HasPrefix(arg, "gitOps.") {
|
||||
if err := q.processSetGitOps(arg, qliksenseCR); err != nil {
|
||||
} else if strings.HasPrefix(arg, "opsRunner.") {
|
||||
if err := q.processSetOpsRunner(arg, qliksenseCR); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -337,27 +337,29 @@ func (q *Qliksense) processSetGit(arg string, cr *api.QliksenseCR) error {
|
||||
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, "=")
|
||||
subs := strings.Split(args[0], ".")
|
||||
if cr.Spec.Git == nil {
|
||||
cr.Spec.GitOps = &config.GitOps{}
|
||||
if cr.Spec.OpsRunner == nil {
|
||||
cr.Spec.OpsRunner = &config.OpsRunner{}
|
||||
}
|
||||
switch subs[1] {
|
||||
case "enabled":
|
||||
if args[1] != "yes" && args[1] != "no" {
|
||||
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":
|
||||
if _, err := cron.ParseStandard(args[1]); err != nil {
|
||||
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":
|
||||
cr.Spec.GitOps.WatchBranch = args[1]
|
||||
cr.Spec.OpsRunner.WatchBranch = args[1]
|
||||
case "image":
|
||||
cr.Spec.GitOps.Image = args[1]
|
||||
cr.Spec.OpsRunner.Image = args[1]
|
||||
case "crPvc":
|
||||
cr.Spec.OpsRunner.CrPvc = args[1]
|
||||
default:
|
||||
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()
|
||||
switch args[0] {
|
||||
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)))
|
||||
return err
|
||||
case DefaultQliksenseContext:
|
||||
@@ -452,7 +454,7 @@ func (q *Qliksense) DeleteContextConfig(args []string, flag bool) error {
|
||||
if ans == true {
|
||||
api.WriteToFile(&qliksenseConfig, qliksenseConfigFile)
|
||||
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 {
|
||||
return nil
|
||||
}
|
||||
@@ -520,7 +522,7 @@ func (q *Qliksense) SetUpQliksenseContext(contextName string) error {
|
||||
}
|
||||
|
||||
// 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) {
|
||||
|
||||
@@ -29,7 +29,7 @@ const (
|
||||
var targetFileStringTemplate = `
|
||||
apiVersion: v1
|
||||
data:
|
||||
mongoDbUri: %s
|
||||
mongodbUri: %s
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: testctx-qliksense-senseinstaller
|
||||
@@ -244,7 +244,7 @@ func TestSetOtherConfigs(t *testing.T) {
|
||||
q: &Qliksense{
|
||||
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,
|
||||
},
|
||||
@@ -254,7 +254,7 @@ func TestSetOtherConfigs(t *testing.T) {
|
||||
q: &Qliksense{
|
||||
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,
|
||||
},
|
||||
@@ -296,7 +296,7 @@ func TestSetConfigs(t *testing.T) {
|
||||
q: &Qliksense{
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
args: []string{"qliksense.acceptEULA=\"yes\"", "qliksense.mongoDbUri=\"mongo://mongo:3307\""},
|
||||
args: []string{"qliksense.acceptEULA=\"yes\"", "qliksense.mongodbUri=\"mongo://mongo:3307\""},
|
||||
},
|
||||
wantErr: false,
|
||||
},
|
||||
@@ -572,7 +572,7 @@ func Test_SetSecrets(t *testing.T) {
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
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,
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -583,7 +583,7 @@ func Test_SetSecrets(t *testing.T) {
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
args: args{
|
||||
args: []string{"qliksense.mongoDbUri=bW9uZ29kYjovL3FsaWstZGVmYXVsdC1tb25nb2RiOjI3MDE3L3FsaWtzZW5zZT9zc2w9ZmFsc2U="},
|
||||
args: []string{"qliksense.mongodbUri=bW9uZ29kYjovL3FsaWstZGVmYXVsdC1tb25nb2RiOjI3MDE3L3FsaWtzZW5zZT9zc2w9ZmFsc2U="},
|
||||
isSecretSet: false,
|
||||
base64: true,
|
||||
},
|
||||
@@ -595,7 +595,7 @@ func Test_SetSecrets(t *testing.T) {
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
args: args{
|
||||
args: []string{"qliksense.mongoDbUri=\"mongo://mongo:3307\""},
|
||||
args: []string{"qliksense.mongodbUri=\"mongo://mongo:3307\""},
|
||||
isSecretSet: true,
|
||||
},
|
||||
wantErr: false,
|
||||
@@ -606,7 +606,7 @@ func Test_SetSecrets(t *testing.T) {
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
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,
|
||||
},
|
||||
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)
|
||||
}
|
||||
@@ -95,9 +95,9 @@ func (q *Qliksense) PullImagesForCurrentCR() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Qliksense) appendGitOpsImage(images *[]string, qcr *qapi.QliksenseCR) {
|
||||
if qcr.Spec.GitOps != nil && qcr.Spec.GitOps.Image != "" {
|
||||
*images = append(*images, qcr.Spec.GitOps.Image)
|
||||
func (q *Qliksense) appendOpsRunnerImage(images *[]string, qcr *qapi.QliksenseCR) {
|
||||
if qcr.Spec.OpsRunner != nil && qcr.Spec.OpsRunner.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 {
|
||||
return err
|
||||
}
|
||||
q.appendGitOpsImage(images, qcr)
|
||||
q.appendOpsRunnerImage(images, qcr)
|
||||
q.appendPreflightImages(images)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ kind: Qliksense
|
||||
metadata:
|
||||
name: qlik-default
|
||||
spec:
|
||||
gitOps:
|
||||
opsRunner:
|
||||
image: some-gitops-image
|
||||
`)
|
||||
|
||||
@@ -225,7 +225,7 @@ spec:
|
||||
return false
|
||||
}
|
||||
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")
|
||||
}
|
||||
@@ -245,7 +245,7 @@ spec:
|
||||
t.Fatal("expected to find the netcat Preflight image in the list, but it wasn't there")
|
||||
}
|
||||
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")
|
||||
}
|
||||
|
||||
@@ -8,7 +8,9 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/mitchellh/go-homedir"
|
||||
"github.com/qlik-oss/k-apis/pkg/config"
|
||||
"github.com/qlik-oss/k-apis/pkg/cr"
|
||||
"sigs.k8s.io/kustomize/api/filesys"
|
||||
|
||||
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||
@@ -16,8 +18,9 @@ import (
|
||||
|
||||
type InstallCommandOptions struct {
|
||||
StorageClass string
|
||||
MongoDbUri string
|
||||
MongodbUri string
|
||||
RotateKeys string
|
||||
DryRun bool
|
||||
}
|
||||
|
||||
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")
|
||||
if opts.MongoDbUri != "" {
|
||||
qcr.Spec.AddToSecrets("qliksense", "mongoDbUri", opts.MongoDbUri, "")
|
||||
if opts.MongodbUri != "" {
|
||||
qcr.Spec.AddToSecrets("qliksense", "mongodbUri", opts.MongodbUri, "")
|
||||
}
|
||||
if opts.StorageClass != "" {
|
||||
qcr.Spec.StorageClassName = opts.StorageClass
|
||||
@@ -51,11 +54,18 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
||||
if 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)
|
||||
|
||||
//if the docker pull secret exists on disk, install it in the cluster
|
||||
//if it doesn't exist on disk, remove it in the cluster
|
||||
if err := installOrRemoveImagePullSecret(qConfig); err != nil {
|
||||
if err := applyImagePullSecret(qConfig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -132,22 +142,13 @@ func (q *Qliksense) getProcessedOperatorControllerString(qcr *qapi.QliksenseCR)
|
||||
return operatorControllerString, nil
|
||||
}
|
||||
|
||||
func installOrRemoveImagePullSecret(qConfig *qapi.QliksenseConfig) error {
|
||||
func applyImagePullSecret(qConfig *qapi.QliksenseConfig) error {
|
||||
if pullDockerConfigJsonSecret, err := qConfig.GetPullDockerConfigJsonSecret(); err == nil {
|
||||
if dockerConfigJsonSecretYaml, err := pullDockerConfigJsonSecret.ToYaml(""); err != nil {
|
||||
return err
|
||||
} else if err := qapi.KubectlApply(string(dockerConfigJsonSecretYaml), ""); err != nil {
|
||||
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
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ spec:
|
||||
value: "yes"
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||
profile: docker-desktop
|
||||
rotateKeys: "yes"`
|
||||
|
||||
@@ -35,7 +35,7 @@ spec:
|
||||
value: "yes"
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||
profile: docker-desktop
|
||||
rotateKeys: "yes"`
|
||||
@@ -62,7 +62,7 @@ spec:
|
||||
value: "yes"
|
||||
secrets:
|
||||
qliksense:
|
||||
- name: mongoDbUri
|
||||
- name: mongodbUri
|
||||
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||
profile: docker-desktop
|
||||
rotateKeys: "yes"`
|
||||
|
||||
Reference in New Issue
Block a user