Compare commits
7 Commits
unset
...
pf_mongo_t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26955d749e | ||
|
|
3e678d9056 | ||
|
|
ec9423330d | ||
|
|
c5b6443179 | ||
|
|
a228757e0b | ||
|
|
8f2e464d0e | ||
|
|
9d547bfe0c |
@@ -220,27 +220,3 @@ 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
|
||||
}
|
||||
|
||||
@@ -136,7 +136,12 @@ 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
|
||||
}
|
||||
|
||||
@@ -429,7 +434,11 @@ 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
|
||||
}
|
||||
|
||||
|
||||
@@ -122,7 +122,6 @@ func getRootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
globalEulaPostRun(cmd, p)
|
||||
}
|
||||
},
|
||||
SilenceUsage: true,
|
||||
}
|
||||
origHelpFunc := cmd.HelpFunc()
|
||||
cmd.SetHelpFunc(func(cmd *cobra.Command, args []string) {
|
||||
@@ -199,10 +198,6 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
||||
|
||||
// open editor for config
|
||||
configCmd.AddCommand(configEditCmd(p))
|
||||
|
||||
// add unset for config
|
||||
configCmd.AddCommand((unsetCmd(p)))
|
||||
|
||||
// add uninstall command
|
||||
cmd.AddCommand(uninstallCmd(p))
|
||||
|
||||
|
||||
4
go.mod
4
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.20200514233516-4ac83864b7bd
|
||||
sigs.k8s.io/kustomize/api => github.com/qlik-oss/kustomize/api v0.3.3-0.20200424070349-b0312eb71568
|
||||
)
|
||||
|
||||
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.2
|
||||
github.com/qlik-oss/k-apis v0.1.1
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rogpeppe/go-internal v1.5.2 // indirect
|
||||
github.com/spf13/cobra v0.0.6
|
||||
|
||||
8
go.sum
8
go.sum
@@ -883,10 +883,10 @@ 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.2 h1:BBcrXl+NxdsvuRsZuJbvIFxMv5QIXqWBzhXOcr5KUX8=
|
||||
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.20200514233516-4ac83864b7bd h1:dYd6duTr54L7OqykGkd3Z+336frAvzsibWNYruYkYVc=
|
||||
github.com/qlik-oss/kustomize/api v0.3.3-0.20200514233516-4ac83864b7bd/go.mod h1:zh3yFgE5zFk1kreqzVyyj1eXyIxQJT53l4zSg8Wt4SA=
|
||||
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/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,8 +157,6 @@ 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)
|
||||
|
||||
@@ -133,6 +133,6 @@ func (p *PreflightConfig) Initialize() error {
|
||||
p.AddMinMongoV("3.6")
|
||||
p.AddImage("nginx", "nginx")
|
||||
p.AddImage("netcat", "subfuzion/netcat")
|
||||
p.AddImage("preflight-mongo", "qlik-docker-oss.bintray.io/preflight-mongo")
|
||||
p.AddImage("mongo", "mongo")
|
||||
return p.Write()
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
@@ -16,8 +17,7 @@ import (
|
||||
)
|
||||
|
||||
const (
|
||||
preflight_mongo = "preflight-mongo"
|
||||
caCertMountPath = "/etc/ssl/certs/ca-certificates.crt"
|
||||
mongo = "mongo"
|
||||
)
|
||||
|
||||
func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||
@@ -25,37 +25,47 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
qp.P.LogVerboseMessage("Preflight mongodb check: \n")
|
||||
qp.P.LogVerboseMessage("------------------------ \n")
|
||||
}
|
||||
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 {
|
||||
if preflightOpts != nil && 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"))
|
||||
}
|
||||
qConfig := qapi.NewQConfig(qp.Q.QliksenseHome)
|
||||
var currentCR *qapi.QliksenseCR
|
||||
|
||||
if preflightOpts.MongoOptions.CaCertFile == "" && !cleanup {
|
||||
caCertStr := decryptedCR.Spec.GetFromSecrets("qliksense", "caCertificates")
|
||||
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 = strings.TrimSpace(decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri"))
|
||||
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
|
||||
}
|
||||
clientCrtFile := filepath.Join(tmpDir, "mongoClient.crt")
|
||||
caCertStr := decryptedCR.Spec.GetFromSecrets("qliksense", "caCertificates")
|
||||
clientCertStr := decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbClientCrt")
|
||||
|
||||
if preflightOpts.MongoOptions.CaCertFile == "" && caCertStr != "" {
|
||||
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 preflightOpts.MongoOptions.ClientCertFile == "" && clientCertStr != "" {
|
||||
api.LogDebugMessage("received client crt: %s\n", clientCertStr)
|
||||
if err := ioutil.WriteFile(clientCrtFile, []byte(clientCertStr), 0644); err != nil {
|
||||
return fmt.Errorf("unable to write client crt to file: %v", err)
|
||||
}
|
||||
preflightOpts.MongoOptions.ClientCertFile = clientCrtFile
|
||||
}
|
||||
}
|
||||
if !cleanup {
|
||||
qp.P.LogVerboseMessage("MongodbUrl: %s\n", preflightOpts.MongoOptions.MongodbUrl)
|
||||
|
||||
@@ -65,11 +75,36 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
return errors.New("MongoDbUrl is empty")
|
||||
}
|
||||
}
|
||||
|
||||
if err := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts, cleanup); err != nil {
|
||||
return err
|
||||
var privKeys []string
|
||||
var err error
|
||||
if preflightOpts.MongoOptions.CaCertFile != "" && preflightOpts.MongoOptions.ClientCertFile == "" {
|
||||
privKeys, err = qp.extractPrivateKeysFromCA(preflightOpts.MongoOptions.CaCertFile)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to parse CA cert: %v", err)
|
||||
}
|
||||
}
|
||||
privKeyCount := len(privKeys)
|
||||
if privKeyCount == 0 {
|
||||
api.LogDebugMessage("no private keys extrated from CA, hence proceeding with usual flow\n")
|
||||
if err := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts, cleanup); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
api.LogDebugMessage("found %d private keys\n", privKeyCount)
|
||||
successCount := 0
|
||||
for _, privKey := range privKeys {
|
||||
preflightOpts.MongoOptions.ClientCertFile = privKey
|
||||
if err1 := qp.mongoConnCheck(kubeConfigContents, namespace, preflightOpts, cleanup); err1 != nil {
|
||||
err = err1
|
||||
continue
|
||||
}
|
||||
successCount++
|
||||
break
|
||||
}
|
||||
if successCount == 0 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if !cleanup {
|
||||
qp.P.LogVerboseMessage("Completed preflight mongodb check\n")
|
||||
}
|
||||
@@ -77,7 +112,8 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespace string, preflightOpts *PreflightOptions, cleanup bool) error {
|
||||
caCertSecretName := "ca-certificates-crt"
|
||||
caCertSecretName := "preflight-mongo-test-cacert"
|
||||
clientCertSecretName := "preflight-mongo-test-clientcert"
|
||||
mongoPodName := "pf-mongo-pod"
|
||||
clientset, _, err := getK8SClientSet(kubeConfigContents, "")
|
||||
if err != nil {
|
||||
@@ -86,11 +122,11 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
}
|
||||
|
||||
// cleanup before starting check
|
||||
qp.runMongoCleanup(clientset, namespace, mongoPodName, caCertSecretName)
|
||||
qp.runMongoCleanup(clientset, namespace, mongoPodName, caCertSecretName, clientCertSecretName)
|
||||
if cleanup {
|
||||
return nil
|
||||
}
|
||||
secrets := map[string]string{}
|
||||
var secrets []string
|
||||
if preflightOpts.MongoOptions.CaCertFile != "" {
|
||||
caCertSecret, err := qp.createSecret(clientset, namespace, preflightOpts.MongoOptions.CaCertFile, caCertSecretName)
|
||||
if err != nil {
|
||||
@@ -99,19 +135,52 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
}
|
||||
|
||||
defer qp.deleteK8sSecret(clientset, namespace, caCertSecret.Name)
|
||||
secrets[caCertSecretName] = caCertMountPath
|
||||
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)
|
||||
}
|
||||
|
||||
commandToRun := []string{"./preflight-mongo", fmt.Sprintf(`-url="%s"`, preflightOpts.MongoOptions.MongodbUrl)}
|
||||
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.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, " "))
|
||||
|
||||
// create a pod
|
||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(preflight_mongo, true)
|
||||
imageName, err := qp.GetPreflightConfigObj().GetImageName(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)
|
||||
@@ -140,7 +209,7 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
}
|
||||
|
||||
// check if connection succeeded
|
||||
stringToCheck := "qlik - connection succeeded!!"
|
||||
stringToCheck := "Implicit session:"
|
||||
if strings.Contains(logStr, stringToCheck) {
|
||||
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
|
||||
} else {
|
||||
@@ -153,7 +222,7 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
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:"
|
||||
mongoVersionStrToCheck := "MongoDB server version:"
|
||||
if strings.Contains(logStr, mongoVersionStrToCheck) {
|
||||
logLines := strings.Split(logStr, "\n")
|
||||
for _, eachline := range logLines {
|
||||
@@ -162,7 +231,7 @@ func (qp *QliksensePreflight) checkMongoVersion(logStr string) (bool, error) {
|
||||
if len(mongoVersionLog) < 2 {
|
||||
continue
|
||||
}
|
||||
mongoVersionStr := strings.ReplaceAll(strings.TrimSpace(mongoVersionLog[1]), `"`, "")
|
||||
mongoVersionStr := strings.TrimSpace(mongoVersionLog[1])
|
||||
api.LogDebugMessage("Extracted mongo version from pod log: %s\n", mongoVersionStr)
|
||||
currentMongoVersionSemver, err := semver.NewVersion(mongoVersionStr)
|
||||
if err != nil {
|
||||
@@ -201,7 +270,46 @@ func (qp *QliksensePreflight) createSecret(clientset *kubernetes.Clientset, name
|
||||
return certSecret, nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, namespace, mongoPodName, caCertSecretName string) {
|
||||
func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, namespace, mongoPodName, caCertSecretName, clientCertSecretName string) {
|
||||
qp.deletePod(clientset, namespace, mongoPodName)
|
||||
qp.deleteK8sSecret(clientset, namespace, caCertSecretName)
|
||||
qp.deleteK8sSecret(clientset, namespace, clientCertSecretName)
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) extractPrivateKeysFromCA(cafile string) ([]string, error) {
|
||||
api.LogDebugMessage("extracting private keys from CA file: %s\n", cafile)
|
||||
raw, err := ioutil.ReadFile(cafile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
dirPath := os.TempDir()
|
||||
count := 0
|
||||
var files []string
|
||||
for {
|
||||
block, rest := pem.Decode(raw)
|
||||
if block == nil {
|
||||
break
|
||||
}
|
||||
if block.Type != "CERTIFICATE" {
|
||||
api.LogDebugMessage("found a private key\n")
|
||||
privFile := filepath.Join(dirPath, fmt.Sprintf("mongo_priv_%d.key", count+1))
|
||||
api.LogDebugMessage("creating a private key file: %s\n", privFile)
|
||||
keyData := pem.EncodeToMemory(block)
|
||||
block, rest = pem.Decode(rest)
|
||||
if block != nil && block.Type == "CERTIFICATE" {
|
||||
api.LogDebugMessage("block type: %s\n", block.Type)
|
||||
keyData = append(keyData, pem.EncodeToMemory(block)...)
|
||||
}
|
||||
api.LogDebugMessage("key data: %s\n", keyData)
|
||||
if err := ioutil.WriteFile(privFile, keyData, 0600); err != nil {
|
||||
return nil, fmt.Errorf("error writing private key to file: \"%s\"", privFile)
|
||||
}
|
||||
api.LogDebugMessage("successfully wrote contents to the private key file\n")
|
||||
files = append(files, privFile)
|
||||
count++
|
||||
}
|
||||
raw = rest
|
||||
}
|
||||
api.LogDebugMessage("extracted private key files: %v\n", files)
|
||||
return files, nil
|
||||
}
|
||||
|
||||
@@ -39,8 +39,12 @@ func (p *PreflightOptions) LogVerboseMessage(strMessage string, args ...interfac
|
||||
}
|
||||
|
||||
type MongoOptions struct {
|
||||
MongodbUrl string
|
||||
CaCertFile string
|
||||
MongodbUrl string
|
||||
Username string
|
||||
Password string
|
||||
CaCertFile string
|
||||
ClientCertFile string
|
||||
Tls bool
|
||||
}
|
||||
|
||||
var gracePeriod int64 = 0
|
||||
@@ -309,7 +313,7 @@ func (qp *QliksensePreflight) deletePod(clientset *kubernetes.Clientset, namespa
|
||||
return nil
|
||||
}
|
||||
|
||||
func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames map[string]string, commandToRun []string) (*apiv1.Pod, error) {
|
||||
func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clientset, namespace, podName, imageName string, secretNames []string, commandToRun []string) (*apiv1.Pod, error) {
|
||||
// build the pod definition we want to deploy
|
||||
pod := &apiv1.Pod{
|
||||
ObjectMeta: v1.ObjectMeta{
|
||||
@@ -332,7 +336,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
||||
},
|
||||
}
|
||||
if len(secretNames) > 0 {
|
||||
for secretName, mountPath := range secretNames {
|
||||
for _, secretName := range secretNames {
|
||||
pod.Spec.Volumes = append(pod.Spec.Volumes, apiv1.Volume{
|
||||
Name: secretName,
|
||||
VolumeSource: apiv1.VolumeSource{
|
||||
@@ -341,7 +345,7 @@ func (qp *QliksensePreflight) createPreflightTestPod(clientset *kubernetes.Clien
|
||||
Items: []apiv1.KeyToPath{
|
||||
{
|
||||
Key: secretName,
|
||||
Path: filepath.Base(mountPath),
|
||||
Path: secretName,
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -350,7 +354,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: filepath.Dir(mountPath),
|
||||
MountPath: "/etc/ssl/" + secretName,
|
||||
ReadOnly: true,
|
||||
})
|
||||
}
|
||||
@@ -465,13 +469,13 @@ func waitForPod(clientset *kubernetes.Clientset, namespace string, pod *apiv1.Po
|
||||
}
|
||||
validateFunc := func(data interface{}) bool {
|
||||
po := data.(*apiv1.Pod)
|
||||
return po.Status.Phase == apiv1.PodRunning || po.Status.Phase == apiv1.PodSucceeded || po.Status.Phase == apiv1.PodFailed
|
||||
return len(po.Status.ContainerStatuses) > 0 && po.Status.ContainerStatuses[0].Ready
|
||||
}
|
||||
|
||||
if err := waitForResource(checkFunc, validateFunc); err != nil {
|
||||
return err
|
||||
}
|
||||
if pod.Status.Phase != apiv1.PodRunning && pod.Status.Phase != apiv1.PodSucceeded && pod.Status.Phase != apiv1.PodFailed {
|
||||
if len(pod.Status.ContainerStatuses) == 0 || !pod.Status.ContainerStatuses[0].Ready {
|
||||
err = fmt.Errorf("container is taking much longer than expected")
|
||||
return err
|
||||
}
|
||||
@@ -486,6 +490,7 @@ 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 {
|
||||
|
||||
@@ -213,8 +213,8 @@ func validateCR(key string, keySub string, value string, crSpec *api.QliksenseCR
|
||||
}
|
||||
} else {
|
||||
switch key {
|
||||
case "opsrunner":
|
||||
crSpec.Spec.OpsRunner = &config.OpsRunner{}
|
||||
case "gitops":
|
||||
crSpec.Spec.GitOps = &config.GitOps{}
|
||||
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, "opsRunner.") {
|
||||
if err := q.processSetOpsRunner(arg, qliksenseCR); err != nil {
|
||||
} else if strings.HasPrefix(arg, "gitOps.") {
|
||||
if err := q.processSetGitOps(arg, qliksenseCR); err != nil {
|
||||
return err
|
||||
}
|
||||
} else {
|
||||
@@ -337,29 +337,27 @@ func (q *Qliksense) processSetGit(arg string, cr *api.QliksenseCR) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (q *Qliksense) processSetOpsRunner(arg string, cr *api.QliksenseCR) error {
|
||||
func (q *Qliksense) processSetGitOps(arg string, cr *api.QliksenseCR) error {
|
||||
args := strings.Split(arg, "=")
|
||||
subs := strings.Split(args[0], ".")
|
||||
if cr.Spec.OpsRunner == nil {
|
||||
cr.Spec.OpsRunner = &config.OpsRunner{}
|
||||
if cr.Spec.Git == nil {
|
||||
cr.Spec.GitOps = &config.GitOps{}
|
||||
}
|
||||
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.OpsRunner.Enabled = args[1]
|
||||
cr.Spec.GitOps.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.OpsRunner.Schedule = args[1]
|
||||
cr.Spec.GitOps.Schedule = args[1]
|
||||
case "watchBranch":
|
||||
cr.Spec.OpsRunner.WatchBranch = args[1]
|
||||
cr.Spec.GitOps.WatchBranch = args[1]
|
||||
case "image":
|
||||
cr.Spec.OpsRunner.Image = args[1]
|
||||
case "crPvc":
|
||||
cr.Spec.OpsRunner.CrPvc = args[1]
|
||||
cr.Spec.GitOps.Image = args[1]
|
||||
default:
|
||||
return errors.New(arg + " does not match any cr spec")
|
||||
}
|
||||
|
||||
@@ -244,7 +244,7 @@ func TestSetOtherConfigs(t *testing.T) {
|
||||
q: &Qliksense{
|
||||
QliksenseHome: testDir,
|
||||
},
|
||||
args: []string{"profile=minikube", "rotateKeys=yes", "storageClassName=efs", "opsRunner.enabled=yes", "opsRunner.schedule=30 * * * *", "git.repository=master", "git.userName=foo", "git.accessToken=1234"},
|
||||
args: []string{"profile=minikube", "rotateKeys=yes", "storageClassName=efs", "gitOps.enabled=yes", "gitOps.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, opsRunner.schedule=bar", "opsRunner.enabled=bar", "git.foo=bar", "rotateKeys=bar"},
|
||||
args: []string{"someconfig=somevalue, gitOps.schedule=bar", "gitOps.enabled=bar", "git.foo=bar", "rotateKeys=bar"},
|
||||
},
|
||||
wantErr: true,
|
||||
},
|
||||
|
||||
@@ -1,109 +0,0 @@
|
||||
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
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
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) appendOpsRunnerImage(images *[]string, qcr *qapi.QliksenseCR) {
|
||||
if qcr.Spec.OpsRunner != nil && qcr.Spec.OpsRunner.Image != "" {
|
||||
*images = append(*images, qcr.Spec.OpsRunner.Image)
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -212,7 +212,7 @@ func (q *Qliksense) appendAdditionalImages(images *[]string, qcr *qapi.Qliksense
|
||||
if err := q.appendOperatorImages(images); err != nil {
|
||||
return err
|
||||
}
|
||||
q.appendOpsRunnerImage(images, qcr)
|
||||
q.appendGitOpsImage(images, qcr)
|
||||
q.appendPreflightImages(images)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -186,7 +186,7 @@ kind: Qliksense
|
||||
metadata:
|
||||
name: qlik-default
|
||||
spec:
|
||||
opsRunner:
|
||||
gitOps:
|
||||
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:")
|
||||
return strings.Contains(image, "qlik-docker-oss.bintray.io/qliksense-operator:v")
|
||||
}) {
|
||||
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 == "qlik-docker-oss.bintray.io/preflight-mongo"
|
||||
return image == "mongo"
|
||||
}) {
|
||||
t.Fatal("expected to find the mongo Preflight image in the list, but it wasn't there")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user