Compare commits

..

4 Commits

Author SHA1 Message Date
Foysal Iqbal
99b442020f add dry-run for debugging purpose
Signed-off-by: Foysal Iqbal <mqb@qlik.com>
2020-06-02 11:05:41 -04:00
Foysal Iqbal
9c6e83152d add dry-run for debugging purpose
Signed-off-by: Foysal Iqbal <mqb@qlik.com>
2020-06-02 10:27:44 -04:00
Foysal Iqbal
a9a9d464c0 Merge branch 'master' into dry-run 2020-06-02 09:42:33 -04:00
Foysal Iqbal
ef3224fb2c add dry-run for debugging purpose
Signed-off-by: Foysal Iqbal <mqb@qlik.com>
2020-05-28 22:41:57 -04:00
10 changed files with 30 additions and 210 deletions

View File

@@ -41,7 +41,7 @@ func (e *eulaPreRunHooksT) getPostValidationArtifact(artifactName string) interf
var eulaEnforced = os.Getenv("QLIKSENSE_EULA_ENFORCE") == "true"
var eulaText = "Please read the end user license agreement at: https://www.qlik.com/us/legal/license-terms"
var eulaPrompt = "Do you accept our EULA? (y/n): "
var eulaErrorInstruction = `You must enter "y" to continue or execute the command with the acceptEULA flag set to "yes"`
var eulaErrorInstruction = `You must enter "y" to continue`
var eulaPreRunHooks = eulaPreRunHooksT{
validators: make(map[string]func(cmd *cobra.Command, q *qliksense.Qliksense) (bool, error)),
postValidationArtifacts: make(map[string]interface{}),
@@ -54,10 +54,7 @@ func commandAlwaysRequiresEulaAcceptance(commandName string) bool {
func globalEulaPreRun(cmd *cobra.Command, q *qliksense.Qliksense) {
if isEulaEnforced(cmd.CommandPath()) {
eulaFlagValue := strings.TrimSpace(strings.ToLower(cmd.Flag("acceptEULA").Value.String()))
if eulaFlagValue != "" && eulaFlagValue != "yes" {
doEnforceEula()
} else if eulaFlagValue == "" {
if strings.TrimSpace(strings.ToLower(cmd.Flag("acceptEULA").Value.String())) != "yes" {
if eulaPreRunHook := eulaPreRunHooks.getValidator(cmd.CommandPath()); eulaPreRunHook != nil {
if eulaAccepted, err := eulaPreRunHook(cmd, q); err != nil {
panic(err)

View File

@@ -61,9 +61,9 @@ func installCmd(q *qliksense.Qliksense) *cobra.Command {
if filePath != "" {
return loadOrApplyCommandEulaPreRunHook(cmd, q)
} else if qConfig, err := qapi.NewQConfigE(q.QliksenseHome); err != nil {
return false, nil
return false, err
} else if qcr, err := qConfig.GetCurrentCR(); err != nil {
return false, nil
return false, err
} else {
return qcr.IsEULA(), nil
}

1
go.mod
View File

@@ -52,7 +52,6 @@ require (
google.golang.org/genproto v0.0.0-20200128133413-58ce757ed39b // indirect
gopkg.in/yaml.v2 v2.2.8
k8s.io/api v0.17.2
k8s.io/apiextensions-apiserver v0.17.2
k8s.io/apimachinery v0.17.2
k8s.io/client-go v11.0.0+incompatible
sigs.k8s.io/kustomize/api v0.3.2

View File

@@ -40,7 +40,7 @@ func (q *Qliksense) ConfigApplyQK8s() error {
}
// create patch dependent resoruces
fmt.Println("Installing resources used by the kuztomize patch")
fmt.Println("Installing resoruces used kuztomize patch")
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
return err
}
@@ -89,13 +89,11 @@ func (q *Qliksense) applyConfigToK8s(qcr *qapi.QliksenseCR) error {
cr.GeneratePatches(&qcr.KApiCr, path.Join(userHomeDir, ".kube", "config"))
// apply generated manifests
profilePath := filepath.Join(qcr.Spec.GetManifestsRoot(), qcr.Spec.GetProfileDir())
fmt.Printf("Generating manifests for profile: %v\n", profilePath)
mByte, err := ExecuteKustomizeBuild(profilePath)
if err != nil {
fmt.Printf("error generating manifests: %v\n", err)
fmt.Println("cannot generate manifests for "+profilePath, err)
return err
}
fmt.Println("Applying manifests to the cluster")
if err = qapi.KubectlApply(string(mByte), qcr.GetNamespace()); err != nil {
return err
}

View File

@@ -5,15 +5,7 @@ import (
"os"
"path/filepath"
"github.com/mitchellh/go-homedir"
qapi "github.com/qlik-oss/sense-installer/pkg/api"
apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
apierrors "k8s.io/apimachinery/pkg/api/errors"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/client-go/tools/clientcmd"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
)
type CrdCommandOptions struct {
@@ -28,11 +20,11 @@ func (q *Qliksense) ViewCrds(opts *CrdCommandOptions) error {
fmt.Println("cannot get the current-context cr", err)
return err
}
engineCRD, err := getQliksenseInitCrds(qcr)
engineCRD, err := getQliksenseInitCrd(qcr)
if err != nil {
return err
}
customCrd, err := getCustomCrds(qcr)
customCrd, err := getCustomCrd(qcr)
if err != nil {
return nil
}
@@ -59,12 +51,12 @@ func (q *Qliksense) InstallCrds(opts *CrdCommandOptions) error {
return err
}
if engineCRD, err := getQliksenseInitCrds(qcr); err != nil {
if engineCRD, err := getQliksenseInitCrd(qcr); err != nil {
return err
} else if err = qapi.KubectlApply(engineCRD, ""); err != nil {
return err
}
if customCrd, err := getCustomCrds(qcr); err != nil {
if customCrd, err := getCustomCrd(qcr); err != nil {
return err
} else if customCrd != "" {
if err = qapi.KubectlApply(customCrd, ""); err != nil {
@@ -81,7 +73,7 @@ func (q *Qliksense) InstallCrds(opts *CrdCommandOptions) error {
return nil
}
func getQliksenseInitCrds(qcr *qapi.QliksenseCR) (string, error) {
func getQliksenseInitCrd(qcr *qapi.QliksenseCR) (string, error) {
var repoPath string
var err error
@@ -106,7 +98,7 @@ func getQliksenseInitCrds(qcr *qapi.QliksenseCR) (string, error) {
return string(qInitByte), nil
}
func getCustomCrds(qcr *qapi.QliksenseCR) (string, error) {
func getCustomCrd(qcr *qapi.QliksenseCR) (string, error) {
crdPath := qcr.GetCustomCrdsPath()
if crdPath == "" {
return "", nil
@@ -118,77 +110,3 @@ func getCustomCrds(qcr *qapi.QliksenseCR) (string, error) {
}
return string(qInitByte), nil
}
func (q *Qliksense) CheckAllCrdsInstalled() (bool, error) {
qConfig := qapi.NewQConfig(q.QliksenseHome)
qcr, err := qConfig.GetCurrentCR()
if err != nil {
return false, err
}
customResourceDefinitionInterface, err := getCustomResourceDefinitionInterface()
if err != nil {
return false, err
}
if engineCRDs, err := getQliksenseInitCrds(qcr); err != nil {
return false, err
} else if allInstalled, err := checkCrdsInstalled(engineCRDs, customResourceDefinitionInterface); err != nil {
return false, err
} else if !allInstalled {
return false, nil
}
if customCrds, err := getCustomCrds(qcr); err != nil {
return false, err
} else if allInstalled, err := checkCrdsInstalled(customCrds, customResourceDefinitionInterface); err != nil {
return false, err
} else if !allInstalled {
return false, nil
}
if allInstalled, err := checkCrdsInstalled(q.GetOperatorCRDString(), customResourceDefinitionInterface); err != nil {
return false, err
} else if !allInstalled {
return false, nil
}
return true, nil
}
func checkCrdsInstalled(crds string, customResourceDefinitionInterface apixv1beta1client.CustomResourceDefinitionInterface) (bool, error) {
kuzResourceFactory := resmap.NewFactory(resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()), nil)
if kuzResMap, err := kuzResourceFactory.NewResMapFromBytes([]byte(crds)); err != nil {
return false, err
} else {
for _, kuzRes := range kuzResMap.Resources() {
if customResourceDefinition, err := customResourceDefinitionInterface.Get(kuzRes.GetName(), v1.GetOptions{}); err != nil && apierrors.IsNotFound(err) {
return false, nil
} else if err != nil {
return false, err
} else if customResourceDefinition == nil {
return false, fmt.Errorf("failed looking up crd: %v", kuzRes.GetName())
}
}
return true, nil
}
}
func getCustomResourceDefinitionInterface() (apixv1beta1client.CustomResourceDefinitionInterface, error) {
homeDir, err := homedir.Dir()
if err != nil {
return nil, err
}
kubeconfigPath := filepath.Join(homeDir, ".kube", "config")
k8sRestConfig, err := clientcmd.BuildConfigFromFlags("", kubeconfigPath)
if err != nil {
return nil, err
}
apixClient, err := apixv1beta1client.NewForConfig(k8sRestConfig)
if err != nil {
return nil, err
}
return apixClient.CustomResourceDefinitions(), nil
}

View File

@@ -1,18 +1,8 @@
package qliksense
import (
"io/ioutil"
"os"
"testing"
apixv1beta1client "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset/typed/apiextensions/v1beta1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"sigs.k8s.io/kustomize/api/k8sdeps/kunstruct"
"sigs.k8s.io/kustomize/api/resmap"
"sigs.k8s.io/kustomize/api/resource"
"github.com/gobuffalo/packr/v2"
kapi_config "github.com/qlik-oss/k-apis/pkg/config"
qapi "github.com/qlik-oss/sense-installer/pkg/api"
)
@@ -23,7 +13,7 @@ func TestGetQliksenseInitCrd(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
crdFromContextConfig, err := getQliksenseInitCrds(&qapi.QliksenseCR{
crdFromContextConfig, err := getQliksenseInitCrd(&qapi.QliksenseCR{
KApiCr: kapi_config.KApiCr{
Spec: &kapi_config.CRSpec{
ManifestsRoot: someTmpRepoPath,
@@ -34,7 +24,7 @@ func TestGetQliksenseInitCrd(t *testing.T) {
t.Fatalf("unexpected error: %v", err)
}
crdFromDownloadedConfig, err := getQliksenseInitCrds(&qapi.QliksenseCR{
crdFromDownloadedConfig, err := getQliksenseInitCrd(&qapi.QliksenseCR{
KApiCr: kapi_config.KApiCr{
Spec: &kapi_config.CRSpec{
ManifestsRoot: "",
@@ -49,87 +39,3 @@ func TestGetQliksenseInitCrd(t *testing.T) {
t.Fatalf("expected %v to equal %v, but they didn't", crdFromContextConfig, crdFromDownloadedConfig)
}
}
func TestCheckAllCrdsInstalled(t *testing.T) {
t.Skip("Skipping this test because it makes kubernetes calls")
tmpQlikSenseHome, err := ioutil.TempDir("", "tmp-qlik-sense-home-")
if err != nil {
t.Fatalf("unexpected error creating tmp dir: %v", err)
}
defer os.RemoveAll(tmpQlikSenseHome)
setupQliksenseTestDefaultContext(t, tmpQlikSenseHome, `
apiVersion: qlik.com/v1
kind: Qliksense
metadata:
name: qlik-default
spec:
profile: docker-desktop
`)
q := &Qliksense{
QliksenseHome: tmpQlikSenseHome,
CrdBox: packr.New("crds", "./crds"),
}
if err := q.FetchQK8s("v1.50.3"); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if allInstalled, err := q.CheckAllCrdsInstalled(); err != nil {
t.Fatalf("unexpected error: %v", err)
} else if allInstalled {
t.Fatal("expected crds to NOT be installed at this point")
}
if err := q.InstallCrds(&CrdCommandOptions{All: true}); err != nil {
t.Fatalf("unexpected error: %v", err)
} else if allInstalled, err := q.CheckAllCrdsInstalled(); err != nil {
t.Fatalf("unexpected error: %v", err)
} else if !allInstalled {
t.Fatal("expected crds to BE installed at this point")
}
//cleanup:
qConfig := qapi.NewQConfig(q.QliksenseHome)
qcr, err := qConfig.GetCurrentCR()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
customResourceDefinitionInterface, err := getCustomResourceDefinitionInterface()
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if engineCRDs, err := getQliksenseInitCrds(qcr); err != nil {
t.Fatalf("unexpected error: %v", err)
} else if err := deleteCrds(engineCRDs, customResourceDefinitionInterface); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if customCrd, err := getCustomCrds(qcr); err != nil {
t.Fatalf("unexpected error: %v", err)
} else if err := deleteCrds(customCrd, customResourceDefinitionInterface); err != nil {
t.Fatalf("unexpected error: %v", err)
}
if err := deleteCrds(q.GetOperatorCRDString(), customResourceDefinitionInterface); err != nil {
t.Fatalf("unexpected error: %v", err)
}
}
func deleteCrds(crds string, customResourceDefinitionInterface apixv1beta1client.CustomResourceDefinitionInterface) error {
kuzResourceFactory := resmap.NewFactory(resource.NewFactory(kunstruct.NewKunstructuredFactoryImpl()), nil)
if kuzResMap, err := kuzResourceFactory.NewResMapFromBytes([]byte(crds)); err != nil {
return err
} else {
for _, kuzRes := range kuzResMap.Resources() {
if err := customResourceDefinitionInterface.Delete(kuzRes.GetName(), &v1.DeleteOptions{}); err != nil {
return err
}
}
return nil
}
}

View File

@@ -2,6 +2,7 @@ package qliksense
import (
"bufio"
"errors"
"fmt"
"io/ioutil"
"os"
@@ -53,7 +54,10 @@ func (q *Qliksense) FetchK8sWithOpts(opts *FetchCommandOptions) error {
cr.SetFetchUrl(opts.GitUrl)
}
v := getVersion(opts, cr)
if v != "" && qConfig.IsRepoExistForCurrent(v) {
if v == "" {
return errors.New("Cannot find gitref/tag/branch/version to fetch")
}
if qConfig.IsRepoExistForCurrent(v) {
if opts.Overwrite || getVerionsOverwriteConfirmation(v) == "y" {
if err := qConfig.DeleteRepoForCurrent(v); err != nil {
return err

View File

@@ -144,7 +144,7 @@ func getLatestTag(repoUrl, accessToken string) (string, error) {
v, err := semver.NewVersion(sv)
if err != nil {
// it may happen, in the repo some tags may not conform to semver
//fmt.Println("the tag is not conform to semver: " + sv)
fmt.Print("Unconform tags: " + sv)
continue
}
if maxSem == nil || maxSem.LessThan(v) {

View File

@@ -17,9 +17,9 @@ func TestGetLatestTag(t *testing.T) {
t.Log(err)
t.Log(sv)
}
baseV, _ := semver.NewVersion("v0.0.8")
baseV, _ := semver.NewVersion("v0.0.7")
if !sv.GreaterThan(baseV) {
t.Log("Expected greater than v0.0.8, but got: " + s)
t.Log("Expected greater than v0.0.7, but got: " + s)
t.Fail()
}
}

View File

@@ -65,17 +65,15 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
}
qConfig.WriteCurrentContextCR(qcr)
if installed, err := q.CheckAllCrdsInstalled(); err != nil {
fmt.Println("error verifying whether CRDs are installed", err)
return err
} else if !installed {
return errors.New(`please install CRDs by executing: $ qliksense crds install --all`)
}
if err := applyImagePullSecret(qConfig); err != nil {
return err
}
// check if acceptEULA is yes or not
if !qcr.IsEULA() {
return errors.New(agreementTempalte + "\n Please do $ qliksense install --acceptEULA=yes\n")
}
//CRD will be installed outside of operator
//install operator controller into the namespace
fmt.Println("Installing operator controller")
@@ -88,7 +86,7 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
}
// create patch dependent resoruces
fmt.Println("Installing resources used by the kuztomize patch")
fmt.Println("Installing resoruces used kuztomize patch")
if err := q.createK8sResoruceBeforePatch(qcr); err != nil {
return err
}
@@ -117,7 +115,7 @@ func (q *Qliksense) InstallQK8s(version string, opts *InstallCommandOptions, kee
}
// install generated manifests into cluster
fmt.Println("Installing generated manifests into the cluster")
fmt.Println("Installing generated manifests into cluster")
if dcr, err := qConfig.GetDecryptedCr(qcr); err != nil {
return err
@@ -195,7 +193,7 @@ images:
func (q *Qliksense) applyCR(cr *qapi.QliksenseCR) error {
// install operator cr into cluster
//get the current context cr
fmt.Println("Installing operator CR into the cluster")
fmt.Println("Install operator CR into cluster")
r, err := cr.GetString()
if err != nil {
return err