Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion test/run-tests.sh
Original file line number Diff line number Diff line change
Expand Up @@ -110,4 +110,4 @@ fi


# Running only smoke test cases by default or value passed through TEST_FOCUS env variable. To run different test packages add/remove path from focus argument or TEST_FOCUS variable
ginkgo -v -progress -r -stream -nodes=${NUM_NODES} --focus="${TEST_TO_RUN}" ${topdir}/test -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE}
ginkgo -v -progress -r -stream -keepGoing -nodes=${NUM_NODES} --focus="${TEST_TO_RUN}" ${topdir}/test -- -commit-hash=${COMMIT_HASH} -operator-image=${PRIVATE_SPLUNK_OPERATOR_IMAGE} -splunk-image=${PRIVATE_SPLUNK_ENTERPRISE_IMAGE}
10 changes: 10 additions & 0 deletions test/testenv/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -252,6 +252,16 @@ func (d *Deployment) deployCR(name string, cr runtime.Object) (runtime.Object, e
return cr, nil
}

// UpdateCR method to update existing CR spec
func (d *Deployment) UpdateCR(cr runtime.Object) error {

err := d.testenv.GetKubeClient().Update(context.TODO(), cr)
if err != nil {
return err
}
return nil
}

// DeploySingleSiteCluster deploys a lm and indexer cluster (shc optional)
func (d *Deployment) DeploySingleSiteCluster(name string, indexerReplicas int, shc bool) error {

Expand Down
133 changes: 133 additions & 0 deletions test/testenv/secretutil.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
// Copyright (c) 2018-2021 Splunk Inc. All rights reserved.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package testenv

import (
b64 "encoding/base64"
"encoding/json"
"fmt"
"os/exec"
"strings"

logf "sigs.k8s.io/controller-runtime/pkg/log"
)

//SecretResponse Secret object struct
type SecretResponse struct {
HecToken string `json:"hec_token"`
IdxcSecret string `json:"idxc_secret"`
Pass4SymmKey string `json:"pass4SymmKey"`
Password string `json:"password"`
ShcSecret string `json:"shc_secret"`
}

// DecodeBase64 decodes base64 and returns string
func DecodeBase64(str string) string {
out, err := b64.StdEncoding.DecodeString(str)
if err != nil {
logf.Log.Error(err, "Failed to decode", "string", str)
return ""
}
return string(out)
}

// EncodeBase64 Encodes base64 and returns string
func EncodeBase64(str string) string {
out := b64.StdEncoding.EncodeToString([]byte(str))
return out
}

// GetSecretObject Gets the secret object
func GetSecretObject(deployment *Deployment, ns string) *SecretResponse {
secretObjectName := fmt.Sprintf(SecretObject, ns)
output, err := exec.Command("kubectl", "get", "secret", secretObjectName, "-n", ns, "-o", "jsonpath='{.data}'").Output()
if err != nil {
cmd := fmt.Sprintf("kubectl get secret %s -n %s -o jsonpath='{.data}'", secretObjectName, ns)
logf.Log.Error(err, "Failed to execute command", "command", cmd)
return nil
}
// Parse response into response struct
restResponse := SecretResponse{}
err = json.Unmarshal([]byte(strings.Trim(string(output), "'")), &restResponse)
if err != nil {
logf.Log.Error(err, "Failed to parse response")
return nil
}
return &restResponse
}

// GetSecretKey Gets the value to specific key from secret object
func GetSecretKey(deployment *Deployment, ns string, key string) string {
restResponse := GetSecretObject(deployment, ns)
//return key based on request
switch key {
case "hec_token":
key := DecodeBase64(restResponse.HecToken)
return key
case "idxc_secret":
key := DecodeBase64(restResponse.IdxcSecret)
return key
case "pass4SymmKey":
key := DecodeBase64(restResponse.Pass4SymmKey)
return key
case "password":
key := DecodeBase64(restResponse.Password)
return key
case "shc_secret":
key := DecodeBase64(restResponse.ShcSecret)
return key
default:
return "Invalid Key"
}
}

//ModifySecretObject Modifies the entire secret object
func ModifySecretObject(deployment *Deployment, data map[string][]byte, ns string) bool {
secretName := fmt.Sprintf(SecretObject, ns)
secret := newSecretSpec(ns, secretName, data)
//Update object using spec
err := deployment.updateCR(secret)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does updateCR take care of a case where secret object is not present?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes. If the object is not present. It creates the object with the details specified

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

And if it does exist, does it update? If yes we are good.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup. This fcn is mainly to update it. But does take care of the scenario when object is not present

if err != nil {
logf.Log.Error(err, "Unable to update secret object")
return false
}
return true

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: extra line unnecessary here?

}

//ModifySecretKey Modifies the specific key in secret object
func ModifySecretKey(deployment *Deployment, ns string, key string, value string) bool {
//Get current config for update
restResponse := GetSecretObject(deployment, ns)
out, err := json.Marshal(restResponse)
if err != nil {
logf.Log.Error(err, "Failed to parse response")
return false
}

//Convert object to map for update
var data map[string][]byte
err = json.Unmarshal([]byte(out), &data)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Curious, how does the unmarshal convert the variable out to a map? And what data type is out?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Out is a Json object. Unmarshal will convert it to a map. Tested it out when running the local changes

Copy link
Collaborator

@akondur akondur Mar 2, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does the input to unmarshal need to be of a certain type for it to convert it to a map? i.e []byte? How does it determine the key and value pairs?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the object is initially built into a json out of the exec.command() function using the struct defined at the top. Here we take care of any extra fields that might have come accidentally. Post that its simple to convert from json to map and then to update

if err != nil {
logf.Log.Error(err, "Failed to parse response")
return false
}

//Modify data
data[key] = []byte(EncodeBase64(value))
modify := ModifySecretObject(deployment, data, ns)
return modify

}
3 changes: 3 additions & 0 deletions test/testenv/testenv.go
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ const (

// MonitoringConsolePod Montioring Console Statefulset Template
MonitoringConsolePod = "splunk-%s-monitoring-console-%d"

// SecretObject Secret object Template
SecretObject = "splunk-%s-secret"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Change to SecretObjectName ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I use the secretObjectName in the function itself after i fill in the 'namespace'. Think it would be ok to keep as it is

)

var (
Expand Down