Compare commits
11 Commits
upgrade_li
...
pf_mongo_t
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
26955d749e | ||
|
|
3e678d9056 | ||
|
|
ec9423330d | ||
|
|
c5b6443179 | ||
|
|
a228757e0b | ||
|
|
8f2e464d0e | ||
|
|
9d547bfe0c | ||
|
|
7525c2e698 | ||
|
|
60763e034a | ||
|
|
ce4081a422 | ||
|
|
dd503a40c1 |
@@ -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
|
||||
}
|
||||
|
||||
@@ -147,7 +152,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 +337,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 {
|
||||
|
||||
@@ -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)
|
||||
@@ -195,7 +195,6 @@ 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))
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
```
|
||||
|
||||
1
go.mod
1
go.mod
@@ -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
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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,6 +130,7 @@ 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")
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
package preflight
|
||||
|
||||
import (
|
||||
"encoding/pem"
|
||||
"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"
|
||||
@@ -38,13 +43,67 @@ func (qp *QliksensePreflight) CheckMongo(kubeConfigContents []byte, namespace st
|
||||
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")
|
||||
preflightOpts.MongoOptions.MongodbUrl = strings.TrimSpace(decryptedCR.Spec.GetFromSecrets("qliksense", "mongoDbUri"))
|
||||
tmpDir := os.TempDir()
|
||||
caCrtFile := filepath.Join(tmpDir, "rootCA.crt")
|
||||
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)
|
||||
|
||||
// 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
|
||||
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")
|
||||
@@ -99,7 +158,7 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
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 != "" {
|
||||
if preflightOpts.MongoOptions.Tls || preflightOpts.MongoOptions.ClientCertFile != "" {
|
||||
mongoCommand.WriteString(" --tls")
|
||||
api.LogDebugMessage("Adding --tls: Mongo command: %s\n", mongoCommand.String())
|
||||
}
|
||||
@@ -143,6 +202,13 @@ func (qp *QliksensePreflight) mongoConnCheck(kubeConfigContents []byte, namespac
|
||||
return err
|
||||
}
|
||||
|
||||
// check mongo server version
|
||||
ok, err := qp.checkMongoVersion(logStr)
|
||||
if !ok || err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// check if connection succeeded
|
||||
stringToCheck := "Implicit session:"
|
||||
if strings.Contains(logStr, stringToCheck) {
|
||||
qp.P.LogVerboseMessage("Preflight mongo check: PASSED\n")
|
||||
@@ -153,6 +219,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 := "MongoDB 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.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,7 +264,7 @@ 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
|
||||
@@ -172,3 +275,41 @@ func (qp *QliksensePreflight) runMongoCleanup(clientset *kubernetes.Clientset, n
|
||||
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
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
@@ -115,13 +114,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 +128,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 +185,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 +200,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 +270,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
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
}
|
||||
@@ -411,7 +411,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 +452,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
|
||||
}
|
||||
|
||||
@@ -53,9 +53,7 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
|
||||
}
|
||||
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 +130,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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user