Compare commits
1 Commits
export_fun
...
load-file
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
763f59e042 |
38
cmd/qliksense/load.go
Normal file
38
cmd/qliksense/load.go
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
|
||||||
|
"github.com/pkg/errors"
|
||||||
|
"github.com/qlik-oss/sense-installer/pkg/qliksense"
|
||||||
|
"github.com/spf13/cobra"
|
||||||
|
)
|
||||||
|
|
||||||
|
func loadCrFile(q *qliksense.Qliksense) *cobra.Command {
|
||||||
|
filePath := ""
|
||||||
|
c := &cobra.Command{
|
||||||
|
Use: "load",
|
||||||
|
Short: "load a CR a file and create necessary structure for future use",
|
||||||
|
Long: `load a CR a file and create necessary structure for future use`,
|
||||||
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
|
if filePath == "-" {
|
||||||
|
return q.LoadCr(os.Stdin)
|
||||||
|
}
|
||||||
|
file, e := os.Open(filePath)
|
||||||
|
if e != nil {
|
||||||
|
return errors.Wrapf(e,
|
||||||
|
"unable to read the file %s", filePath)
|
||||||
|
}
|
||||||
|
return q.LoadCr(file)
|
||||||
|
},
|
||||||
|
}
|
||||||
|
f := c.Flags()
|
||||||
|
f.StringVarP(&filePath, "file", "f", "", "File to laod CR from")
|
||||||
|
c.MarkFlagRequired("file")
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
|
func isInputFromPipe() bool {
|
||||||
|
fileInfo, _ := os.Stdin.Stat()
|
||||||
|
return fileInfo.Mode()&os.ModeCharDevice == 0
|
||||||
|
}
|
||||||
@@ -172,7 +172,7 @@ func rootCmd(p *qliksense.Qliksense) *cobra.Command {
|
|||||||
//preflightCmd.AddCommand(preflightCheckAllCmd(p))
|
//preflightCmd.AddCommand(preflightCheckAllCmd(p))
|
||||||
|
|
||||||
cmd.AddCommand(preflightCmd)
|
cmd.AddCommand(preflightCmd)
|
||||||
|
cmd.AddCommand(loadCrFile(p))
|
||||||
return cmd
|
return cmd
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ func (qc *QliksenseConfig) GetCR(contextName string) (*QliksenseCR, error) {
|
|||||||
if crFilePath == "" {
|
if crFilePath == "" {
|
||||||
return nil, errors.New("context name " + contextName + " not found")
|
return nil, errors.New("context name " + contextName + " not found")
|
||||||
}
|
}
|
||||||
return getCRObject(crFilePath)
|
return GetCRObject(crFilePath)
|
||||||
}
|
}
|
||||||
|
|
||||||
func getUnencryptedCR() {
|
func getUnencryptedCR() {
|
||||||
@@ -77,7 +77,8 @@ func (qc *QliksenseConfig) SetCrLocation(contextName, filepath string) (*Qliksen
|
|||||||
return nil, errors.New("cannot find the context")
|
return nil, errors.New("cannot find the context")
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCRObject(crfile string) (*QliksenseCR, error) {
|
// GetCRObject create a qliksense CR object from file
|
||||||
|
func GetCRObject(crfile string) (*QliksenseCR, error) {
|
||||||
cr := &QliksenseCR{}
|
cr := &QliksenseCR{}
|
||||||
err := ReadFromFile(cr, crfile)
|
err := ReadFromFile(cr, crfile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -88,6 +89,20 @@ func getCRObject(crfile string) (*QliksenseCR, error) {
|
|||||||
return cr, nil
|
return cr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//CreateCRObjectFromString create a QliksenseCR from string content
|
||||||
|
func CreateCRObjectFromString(crContent string) (*QliksenseCR, error) {
|
||||||
|
if crContent == "" {
|
||||||
|
return nil, errors.New("empty string cannot qliksensecr")
|
||||||
|
}
|
||||||
|
cr := &QliksenseCR{}
|
||||||
|
err := ReadFromStream(cr, strings.NewReader(crContent))
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("cannot unmarshal cr ", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return cr, nil
|
||||||
|
}
|
||||||
|
|
||||||
func (qc *QliksenseConfig) getCRFilePath(contextName string) string {
|
func (qc *QliksenseConfig) getCRFilePath(contextName string) string {
|
||||||
crFilePath := ""
|
crFilePath := ""
|
||||||
for _, ctx := range qc.Spec.Contexts {
|
for _, ctx := range qc.Spec.Contexts {
|
||||||
@@ -374,3 +389,36 @@ func (qc *QliksenseConfig) GetDecryptedCr(cr *QliksenseCR) (*QliksenseCR, error)
|
|||||||
newCr.Spec.Secrets = finalSecrets
|
newCr.Spec.Secrets = finalSecrets
|
||||||
return newCr, nil
|
return newCr, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//Validate validate CR
|
||||||
|
func (cr *QliksenseCR) Validate() bool {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
//CreateContextDirs create context dir structure ~/.qliksense/contexts/contextName
|
||||||
|
func (qc *QliksenseConfig) CreateContextDirs(contextName string) {
|
||||||
|
contexPath := filepath.Join(qc.QliksenseHomePath, qliksenseContextsDirName, contextName)
|
||||||
|
os.MkdirAll(contexPath, os.ModePerm)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (qc *QliksenseConfig) BuildCrFilePath(contextName string) string {
|
||||||
|
return filepath.Join(qc.QliksenseHomePath, qliksenseContextsDirName, contextName, contextName+".yaml")
|
||||||
|
}
|
||||||
|
|
||||||
|
//AddToContexts add the context into qc.Spec.Contexts
|
||||||
|
func (qc *QliksenseConfig) AddToContexts(crName, crFile string) {
|
||||||
|
qc.Spec.Contexts = append(qc.Spec.Contexts, []Context{
|
||||||
|
{CrFile: crFile,
|
||||||
|
Name: crName},
|
||||||
|
}...)
|
||||||
|
}
|
||||||
|
|
||||||
|
//SetCurrentContextName set the qc.Spec.CurrentContext
|
||||||
|
func (qc *QliksenseConfig) SetCurrentContextName(name string) {
|
||||||
|
qc.Spec.CurrentContext = name
|
||||||
|
}
|
||||||
|
|
||||||
|
//Write write QliksenseConfig into config.yaml
|
||||||
|
func (qc *QliksenseConfig) Write() error {
|
||||||
|
return WriteToFile(qc, filepath.Join(qc.QliksenseHomePath, "config.yaml"))
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,8 +3,10 @@ package api
|
|||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
|
"os"
|
||||||
|
|
||||||
"github.com/qlik-oss/k-apis/pkg/config"
|
"github.com/qlik-oss/k-apis/pkg/config"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
"k8s.io/apimachinery/pkg/runtime/schema"
|
||||||
@@ -103,14 +105,22 @@ func ReadFromFile(content interface{}, sourceFile string) error {
|
|||||||
if content == nil || sourceFile == "" {
|
if content == nil || sourceFile == "" {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
contents, err := ioutil.ReadFile(sourceFile)
|
file, e := os.Open(sourceFile)
|
||||||
|
if e != nil {
|
||||||
|
return e
|
||||||
|
}
|
||||||
|
return ReadFromStream(content, file)
|
||||||
|
}
|
||||||
|
|
||||||
|
// ReadFromStream reads from input stream and creat yaml struct of type content
|
||||||
|
func ReadFromStream(content interface{}, reader io.Reader) error {
|
||||||
|
contents, err := ioutil.ReadAll(reader)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("There was an error reading from file: %s, %v", sourceFile, err)
|
err = fmt.Errorf("There was an error reading from reader: %v", err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
// reading k8s style object
|
// reading k8s style object
|
||||||
// https://stackoverflow.com/questions/44306554/how-to-deserialize-kubernetes-yaml-file
|
// https://stackoverflow.com/questions/44306554/how-to-deserialize-kubernetes-yaml-file
|
||||||
dec := machine_yaml.NewYAMLOrJSONDecoder(bytes.NewReader(contents), 10000)
|
dec := machine_yaml.NewYAMLOrJSONDecoder(bytes.NewReader(contents), 10000)
|
||||||
dec.Decode(content)
|
return dec.Decode(content)
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -152,6 +152,7 @@ func removePrivateKey() {
|
|||||||
|
|
||||||
func setup() func() {
|
func setup() func() {
|
||||||
// create tests dir
|
// create tests dir
|
||||||
|
os.RemoveAll(testDir)
|
||||||
if err := os.Mkdir(testDir, 0777); err != nil {
|
if err := os.Mkdir(testDir, 0777); err != nil {
|
||||||
log.Printf("\nError occurred: %v", err)
|
log.Printf("\nError occurred: %v", err)
|
||||||
}
|
}
|
||||||
|
|||||||
60
pkg/qliksense/load_cr.go
Normal file
60
pkg/qliksense/load_cr.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
package qliksense
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
|
||||||
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
//
|
||||||
|
func (q *Qliksense) LoadCr(reader io.Reader) error {
|
||||||
|
for _, doc := range readMultipleYamlFromReader(reader) {
|
||||||
|
if crName, err := q.loadCrStringIntoFileSystem(doc); err != nil {
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
fmt.Println("cr name: [ " + crName + " ] has been loaded")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (q *Qliksense) loadCrStringIntoFileSystem(crstr string) (string, error) {
|
||||||
|
cr, err := qapi.CreateCRObjectFromString(crstr)
|
||||||
|
if err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
qConfig := qapi.NewQConfig(q.QliksenseHome)
|
||||||
|
if qConfig.IsContextExist(cr.GetName()) {
|
||||||
|
return "", errors.New("Context Name: " + cr.GetName() + " already exist. please delete the existing context first using delete-context command")
|
||||||
|
}
|
||||||
|
qConfig.CreateContextDirs(cr.GetName())
|
||||||
|
|
||||||
|
if err = qapi.WriteToFile(cr, qConfig.BuildCrFilePath(cr.GetName())); err != nil {
|
||||||
|
return "", err
|
||||||
|
}
|
||||||
|
qConfig.AddToContexts(cr.GetName(), qConfig.BuildCrFilePath(cr.GetName()))
|
||||||
|
qConfig.SetCurrentContextName(cr.GetName())
|
||||||
|
qConfig.Write()
|
||||||
|
return cr.GetName(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func readMultipleYamlFromReader(reader io.Reader) []string {
|
||||||
|
docs := make([]string, 0)
|
||||||
|
scanner := bufio.NewScanner(bufio.NewReader(reader))
|
||||||
|
adoc := ""
|
||||||
|
for scanner.Scan() {
|
||||||
|
s := scanner.Text()
|
||||||
|
if s == "---" {
|
||||||
|
docs = append(docs, adoc)
|
||||||
|
adoc = ""
|
||||||
|
}
|
||||||
|
adoc = adoc + "\n" + s
|
||||||
|
}
|
||||||
|
if adoc != "" {
|
||||||
|
docs = append(docs, adoc)
|
||||||
|
}
|
||||||
|
return docs
|
||||||
|
}
|
||||||
91
pkg/qliksense/load_cr_test.go
Normal file
91
pkg/qliksense/load_cr_test.go
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
package qliksense
|
||||||
|
|
||||||
|
import (
|
||||||
|
"io/ioutil"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
qapi "github.com/qlik-oss/sense-installer/pkg/api"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestLoadCrFile(t *testing.T) {
|
||||||
|
td := setup()
|
||||||
|
sampleCr := `
|
||||||
|
apiVersion: qlik.com/v1
|
||||||
|
kind: Qliksense
|
||||||
|
metadata:
|
||||||
|
name: qlik-test
|
||||||
|
labels:
|
||||||
|
version: v0.0.2
|
||||||
|
spec:
|
||||||
|
git:
|
||||||
|
repository: https://github.com/ffoysal/qliksense-k8s
|
||||||
|
accessToken: abababababababaab
|
||||||
|
userName: "blblbl"
|
||||||
|
gitOps:
|
||||||
|
enabled: "no"
|
||||||
|
schedule: "*/1 * * * *"
|
||||||
|
watchBranch: pr-branch-db1d26d6
|
||||||
|
image: qlik-docker-oss.bintray.io/qliksense-repo-watcher
|
||||||
|
configs:
|
||||||
|
qliksense:
|
||||||
|
- name: acceptEULA
|
||||||
|
value: "yes"
|
||||||
|
secrets:
|
||||||
|
qliksense:
|
||||||
|
- name: mongoDbUri
|
||||||
|
value: mongodb://qlik-default-mongodb:27017/qliksense?ssl=false
|
||||||
|
profile: docker-desktop
|
||||||
|
rotateKeys: "yes"`
|
||||||
|
|
||||||
|
duplicateCr := `
|
||||||
|
apiVersion: qlik.com/v1
|
||||||
|
kind: Qliksense
|
||||||
|
metadata:
|
||||||
|
name: qlik-default
|
||||||
|
labels:
|
||||||
|
version: v0.0.2
|
||||||
|
spec:
|
||||||
|
git:
|
||||||
|
repository: https://github.com/ffoysal/qliksense-k8s
|
||||||
|
accessToken: abababababababaab
|
||||||
|
userName: "blblbl"`
|
||||||
|
crFile := filepath.Join(testDir, "testcr.yaml")
|
||||||
|
ioutil.WriteFile(crFile, []byte(sampleCr), 0644)
|
||||||
|
|
||||||
|
dupCrFile := filepath.Join(testDir, "dupcr.yaml")
|
||||||
|
ioutil.WriteFile(dupCrFile, []byte(duplicateCr), 0644)
|
||||||
|
|
||||||
|
q := New(testDir)
|
||||||
|
file, e := os.Open(crFile)
|
||||||
|
if e != nil {
|
||||||
|
t.Log(e)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err := q.LoadCr(file); err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
qConfig := qapi.NewQConfig(testDir)
|
||||||
|
cr, err := qConfig.GetCR("qlik-test")
|
||||||
|
if err != nil {
|
||||||
|
t.Log(err)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if cr.GetName() != "qlik-test" {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if qConfig.Spec.CurrentContext != "qlik-test" {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
file, e = os.Open(dupCrFile)
|
||||||
|
if e != nil {
|
||||||
|
t.Log(e)
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
if err := q.LoadCr(file); err == nil {
|
||||||
|
t.FailNow()
|
||||||
|
}
|
||||||
|
td()
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user