Merge pull request #10 from 1Password/restart-cr

Configure Auto Restarts for a OnePasswordItem Custom Resource
This commit is contained in:
Jillian W
2021-04-07 14:39:39 -03:00
committed by GitHub
15 changed files with 323 additions and 69 deletions

View File

@@ -176,6 +176,18 @@ metadata:
```
If the value is not set, the auto reset settings on the namespace will be used.
**Per OnePasswordItem Custom Resource**
This method allows for managing auto restarts on a given OnePasswordItem custom resource. Auto restarts can by managed by setting the annotation `onepasswordoperator/auto_restart` to either `true` or `false` on the desired OnePasswordItem. An example of this is shown below:
```yaml
# enabled auto restarts for the OnePasswordItem
apiVersion: onepassword.com/v1
kind: OnePasswordItem
metadata:
name: example
onepasswordoperator/auto_restart: "true"
```
If the value is not set, the auto reset settings on the deployment will be used.
## Development
### Creating a Docker image

View File

@@ -142,7 +142,7 @@ func (r *ReconcileDeployment) cleanupKubernetesSecretForDeployment(secretName st
if len(secretName) == 0 {
return nil
}
updatedSecrets := map[string]bool{secretName: true}
updatedSecrets := map[string]*corev1.Secret{secretName: kubernetesSecret}
multipleDeploymentsUsingSecret, err := r.areMultipleDeploymentsUsingSecret(updatedSecrets, *deletedDeployment)
if err != nil {
@@ -160,7 +160,7 @@ func (r *ReconcileDeployment) cleanupKubernetesSecretForDeployment(secretName st
return nil
}
func (r *ReconcileDeployment) areMultipleDeploymentsUsingSecret(updatedSecrets map[string]bool, deletedDeployment appsv1.Deployment) (bool, error) {
func (r *ReconcileDeployment) areMultipleDeploymentsUsingSecret(updatedSecrets map[string]*corev1.Secret, deletedDeployment appsv1.Deployment) (bool, error) {
deployments := &appsv1.DeploymentList{}
opts := []client.ListOption{
client.InNamespace(deletedDeployment.Namespace),
@@ -201,5 +201,5 @@ func (r *ReconcileDeployment) HandleApplyingDeployment(namespace string, annotat
return fmt.Errorf("Failed to retrieve item: %v", err)
}
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item)
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, namespace, item, annotations[op.RestartDeploymentsAnnotation])
}

View File

@@ -7,6 +7,7 @@ import (
onepasswordv1 "github.com/1Password/onepassword-operator/pkg/apis/onepassword/v1"
kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets"
"github.com/1Password/onepassword-operator/pkg/onepassword"
op "github.com/1Password/onepassword-operator/pkg/onepassword"
"github.com/1Password/onepassword-operator/pkg/utils"
"github.com/1Password/connect-sdk-go/connect"
@@ -143,11 +144,12 @@ func (r *ReconcileOnePasswordItem) removeOnePasswordFinalizerFromOnePasswordItem
func (r *ReconcileOnePasswordItem) HandleOnePasswordItem(resource *onepasswordv1.OnePasswordItem, request reconcile.Request) error {
secretName := resource.GetName()
autoRestart := resource.Annotations[op.RestartDeploymentsAnnotation]
item, err := onepassword.GetOnePasswordItemByPath(r.opConnectClient, resource.Spec.ItemPath)
if err != nil {
return fmt.Errorf("Failed to retrieve item: %v", err)
}
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item)
return kubeSecrets.CreateKubernetesSecretFromItem(r.kubeClient, secretName, resource.Namespace, item, autoRestart)
}

View File

@@ -5,6 +5,7 @@ import (
"fmt"
"github.com/1Password/connect-sdk-go/onepassword"
"github.com/1Password/onepassword-operator/pkg/utils"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/errors"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@@ -13,21 +14,30 @@ import (
logf "sigs.k8s.io/controller-runtime/pkg/log"
)
const onepasswordPrefix = "onepasswordoperator"
const NameAnnotation = onepasswordPrefix + "/item-name"
const VersionAnnotation = onepasswordPrefix + "/item-version"
const restartAnnotation = onepasswordPrefix + "/lastRestarted"
const ItemPathAnnotation = onepasswordPrefix + "/item-path"
const OnepasswordPrefix = "onepasswordoperator"
const NameAnnotation = OnepasswordPrefix + "/item-name"
const VersionAnnotation = OnepasswordPrefix + "/item-version"
const restartAnnotation = OnepasswordPrefix + "/lastRestarted"
const ItemPathAnnotation = OnepasswordPrefix + "/item-path"
const RestartDeploymentsAnnotation = OnepasswordPrefix + "/auto_restart"
var log = logf.Log
func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretName, namespace string, item *onepassword.Item) error {
func CreateKubernetesSecretFromItem(kubeClient kubernetesClient.Client, secretName, namespace string, item *onepassword.Item, autoRestart string) error {
itemVersion := fmt.Sprint(item.Version)
annotations := map[string]string{
VersionAnnotation: itemVersion,
ItemPathAnnotation: fmt.Sprintf("vaults/%v/items/%v", item.Vault.ID, item.ID),
}
if autoRestart != "" {
_, err := utils.StringToBool(autoRestart)
if err != nil {
log.Error(err, "Error parsing %v annotation on Secret %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, secretName)
return err
}
annotations[RestartDeploymentsAnnotation] = autoRestart
}
secret := BuildKubernetesSecretFromOnePasswordItem(secretName, namespace, annotations, *item)
currentSecret := &corev1.Secret{}

View File

@@ -13,6 +13,8 @@ import (
"sigs.k8s.io/controller-runtime/pkg/client/fake"
)
const restartDeploymentAnnotation = "false"
type k8s struct {
clientset kubernetes.Interface
}
@@ -28,7 +30,7 @@ func TestCreateKubernetesSecretFromOnePasswordItem(t *testing.T) {
item.ID = "h46bb3jddvay7nxopfhvlwg35q"
kubeClient := fake.NewFakeClient()
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item)
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@@ -53,7 +55,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) {
item.ID = "h46bb3jddvay7nxopfhvlwg35q"
kubeClient := fake.NewFakeClient()
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item)
err := CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &item, restartDeploymentAnnotation)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@@ -64,7 +66,7 @@ func TestUpdateKubernetesSecretFromOnePasswordItem(t *testing.T) {
newItem.Version = 456
newItem.Vault.ID = "hfnjvi6aymbsnfc2xeeoheizda"
newItem.ID = "h46bb3jddvay7nxopfhvlwg35q"
err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem)
err = CreateKubernetesSecretFromItem(kubeClient, secretName, namespace, &newItem, restartDeploymentAnnotation)
if err != nil {
t.Errorf("Unexpected error: %v", err)
}
@@ -125,6 +127,10 @@ func compareAnnotationsToItem(annotations map[string]string, item onepassword.It
if annotations[VersionAnnotation] != fmt.Sprint(item.Version) {
t.Errorf("Expected annotation version to be %v but was %v", item.Version, annotations[VersionAnnotation])
}
if annotations[RestartDeploymentsAnnotation] != "false" {
t.Errorf("Expected restart deployments annotation to be %v but was %v", restartDeploymentAnnotation, RestartDeploymentsAnnotation)
}
}
func compareFields(actualFields []*onepassword.ItemField, secretData map[string][]byte, t *testing.T) {

View File

@@ -4,6 +4,7 @@ import (
"regexp"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
)
const (
@@ -42,10 +43,18 @@ func FilterAnnotations(annotations map[string]string, regex *regexp.Regexp) map[
return filteredAnnotations
}
func AreAnnotationsUsingSecrets(annotations map[string]string, secrets map[string]bool) bool {
func AreAnnotationsUsingSecrets(annotations map[string]string, secrets map[string]*corev1.Secret) bool {
_, ok := secrets[annotations[NameAnnotation]]
if ok {
return true
}
return false
}
func AppendAnnotationUpdatedSecret(annotations map[string]string, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret {
secret, ok := secrets[annotations[NameAnnotation]]
if ok {
updatedDeploymentSecrets[secret.Name] = secret
}
return updatedDeploymentSecrets
}

View File

@@ -2,7 +2,7 @@ package onepassword
import corev1 "k8s.io/api/core/v1"
func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string]bool) bool {
func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret) bool {
for i := 0; i < len(containers); i++ {
envVariables := containers[i].Env
for j := 0; j < len(envVariables); j++ {
@@ -16,3 +16,18 @@ func AreContainersUsingSecrets(containers []corev1.Container, secrets map[string
}
return false
}
func AppendUpdatedContainerSecrets(containers []corev1.Container, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret {
for i := 0; i < len(containers); i++ {
envVariables := containers[i].Env
for j := 0; j < len(envVariables); j++ {
if envVariables[j].ValueFrom != nil && envVariables[j].ValueFrom.SecretKeyRef != nil {
secret, ok := secrets[envVariables[j].ValueFrom.SecretKeyRef.Name]
if ok {
updatedDeploymentSecrets[secret.Name] = secret
}
}
}
}
return updatedDeploymentSecrets
}

View File

@@ -2,12 +2,14 @@ package onepassword
import (
"testing"
corev1 "k8s.io/api/core/v1"
)
func TestAreContainersUsingSecrets(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
containerSecretNames := []string{
@@ -24,9 +26,9 @@ func TestAreContainersUsingSecrets(t *testing.T) {
}
func TestAreContainersNotUsingSecrets(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
containerSecretNames := []string{

View File

@@ -1,10 +1,26 @@
package onepassword
import appsv1 "k8s.io/api/apps/v1"
import (
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
)
func IsDeploymentUsingSecrets(deployment *appsv1.Deployment, secrets map[string]bool) bool {
func IsDeploymentUsingSecrets(deployment *appsv1.Deployment, secrets map[string]*corev1.Secret) bool {
volumes := deployment.Spec.Template.Spec.Volumes
containers := deployment.Spec.Template.Spec.Containers
containers = append(containers, deployment.Spec.Template.Spec.InitContainers...)
return AreAnnotationsUsingSecrets(deployment.Annotations, secrets) || AreContainersUsingSecrets(containers, secrets) || AreVolumesUsingSecrets(volumes, secrets)
}
func GetUpdatedSecretsForDeployment(deployment *appsv1.Deployment, secrets map[string]*corev1.Secret) map[string]*corev1.Secret {
volumes := deployment.Spec.Template.Spec.Volumes
containers := deployment.Spec.Template.Spec.Containers
containers = append(containers, deployment.Spec.Template.Spec.InitContainers...)
updatedSecretsForDeployment := map[string]*corev1.Secret{}
AppendAnnotationUpdatedSecret(deployment.Annotations, secrets, updatedSecretsForDeployment)
AppendUpdatedContainerSecrets(containers, secrets, updatedSecretsForDeployment)
AppendUpdatedVolumeSecrets(volumes, secrets, updatedSecretsForDeployment)
return updatedSecretsForDeployment
}

View File

@@ -4,12 +4,13 @@ import (
"testing"
appsv1 "k8s.io/api/apps/v1"
corev1 "k8s.io/api/core/v1"
)
func TestIsDeploymentUsingSecretsUsingVolumes(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
volumeSecretNames := []string{
@@ -26,9 +27,9 @@ func TestIsDeploymentUsingSecretsUsingVolumes(t *testing.T) {
}
func TestIsDeploymentUsingSecretsUsingContainers(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
containerSecretNames := []string{
@@ -45,9 +46,9 @@ func TestIsDeploymentUsingSecretsUsingContainers(t *testing.T) {
}
func TestIsDeploymentNotUSingSecrets(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
deployment := &appsv1.Deployment{}

View File

@@ -3,11 +3,10 @@ package onepassword
import (
"context"
"fmt"
"strconv"
"strings"
"time"
kubeSecrets "github.com/1Password/onepassword-operator/pkg/kubernetessecrets"
"github.com/1Password/onepassword-operator/pkg/utils"
"github.com/1Password/connect-sdk-go/connect"
"github.com/1Password/connect-sdk-go/onepassword"
@@ -45,7 +44,7 @@ func (h *SecretUpdateHandler) UpdateKubernetesSecretsTask() error {
return h.restartDeploymentsWithUpdatedSecrets(updatedKubernetesSecrets)
}
func (h *SecretUpdateHandler) restartDeploymentsWithUpdatedSecrets(updatedSecretsByNamespace map[string]map[string]bool) error {
func (h *SecretUpdateHandler) restartDeploymentsWithUpdatedSecrets(updatedSecretsByNamespace map[string]map[string]*corev1.Secret) error {
// No secrets to update. Exit
if len(updatedSecretsByNamespace) == 0 || updatedSecretsByNamespace == nil {
return nil
@@ -69,16 +68,21 @@ func (h *SecretUpdateHandler) restartDeploymentsWithUpdatedSecrets(updatedSecret
for i := 0; i < len(deployments.Items); i++ {
deployment := &deployments.Items[i]
if !isDeploymentSetForAutoRestart(deployment, setForAutoRestartByNamespaceMap) {
updatedSecrets := updatedSecretsByNamespace[deployment.Namespace]
updatedDeploymentSecrets := GetUpdatedSecretsForDeployment(deployment, updatedSecrets)
if len(updatedDeploymentSecrets) == 0 {
continue
}
updatedSecrets := updatedSecretsByNamespace[deployment.Namespace]
secretName := deployment.Annotations[NameAnnotation]
if isUpdatedSecret(secretName, updatedSecrets) || IsDeploymentUsingSecrets(deployment, updatedSecrets) {
h.restartDeployment(deployment)
} else {
log.Info(fmt.Sprintf("Deployment %q at namespace %q is up to date", deployment.GetName(), deployment.Namespace))
for _, secret := range updatedDeploymentSecrets {
if isSecretSetForAutoRestart(secret, deployment, setForAutoRestartByNamespaceMap) {
h.restartDeployment(deployment)
continue
}
}
log.Info(fmt.Sprintf("Deployment %q at namespace %q is up to date", deployment.GetName(), deployment.Namespace))
}
return nil
}
@@ -94,7 +98,7 @@ func (h *SecretUpdateHandler) restartDeployment(deployment *appsv1.Deployment) {
}
}
func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]bool, error) {
func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]*corev1.Secret, error) {
secrets := &corev1.SecretList{}
err := h.client.List(context.Background(), secrets)
if err != nil {
@@ -102,7 +106,7 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]b
return nil, err
}
updatedSecrets := map[string]map[string]bool{}
updatedSecrets := map[string]map[string]*corev1.Secret{}
for i := 0; i < len(secrets.Items); i++ {
secret := secrets.Items[i]
@@ -130,9 +134,9 @@ func (h *SecretUpdateHandler) updateKubernetesSecrets() (map[string]map[string]b
updatedSecret := kubeSecrets.BuildKubernetesSecretFromOnePasswordItem(secret.Name, secret.Namespace, secret.Annotations, *item)
h.client.Update(context.Background(), updatedSecret)
if updatedSecrets[secret.Namespace] == nil {
updatedSecrets[secret.Namespace] = make(map[string]bool)
updatedSecrets[secret.Namespace] = make(map[string]*corev1.Secret)
}
updatedSecrets[secret.Namespace][secret.Name] = true
updatedSecrets[secret.Namespace][secret.Name] = &secret
}
}
return updatedSecrets, nil
@@ -148,7 +152,7 @@ func isItemLockedForForcedRestarts(item *onepassword.Item) bool {
return false
}
func isUpdatedSecret(secretName string, updatedSecrets map[string]bool) bool {
func isUpdatedSecret(secretName string, updatedSecrets map[string]*corev1.Secret) bool {
_, ok := updatedSecrets[secretName]
if ok {
return true
@@ -172,6 +176,21 @@ func (h *SecretUpdateHandler) getIsSetForAutoRestartByNamespaceMap() (map[string
return namespacesMap, nil
}
func isSecretSetForAutoRestart(secret *corev1.Secret, deployment *appsv1.Deployment, setForAutoRestartByNamespace map[string]bool) bool {
restartDeployment := secret.Annotations[RestartDeploymentsAnnotation]
//If annotation for auto restarts for deployment is not set. Check for the annotation on its namepsace
if restartDeployment == "" {
return isDeploymentSetForAutoRestart(deployment, setForAutoRestartByNamespace)
}
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Secret %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, secret.Name)
return false
}
return restartDeploymentBool
}
func isDeploymentSetForAutoRestart(deployment *appsv1.Deployment, setForAutoRestartByNamespace map[string]bool) bool {
restartDeployment := deployment.Annotations[RestartDeploymentsAnnotation]
//If annotation for auto restarts for deployment is not set. Check for the annotation on its namepsace
@@ -179,7 +198,7 @@ func isDeploymentSetForAutoRestart(deployment *appsv1.Deployment, setForAutoRest
return setForAutoRestartByNamespace[deployment.Namespace]
}
restartDeploymentBool, err := stringToBool(restartDeployment)
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Deployment %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, deployment.Name)
return false
@@ -194,18 +213,10 @@ func (h *SecretUpdateHandler) isNamespaceSetToAutoRestart(namespace *corev1.Name
return h.shouldAutoRestartDeploymentsGlobal
}
restartDeploymentBool, err := stringToBool(restartDeployment)
restartDeploymentBool, err := utils.StringToBool(restartDeployment)
if err != nil {
log.Error(err, "Error parsing %v annotation on Namespace %v. Must be true or false. Defaulting to false.", RestartDeploymentsAnnotation, namespace.Name)
return false
}
return restartDeploymentBool
}
func stringToBool(str string) (bool, error) {
restartDeploymentBool, err := strconv.ParseBool(strings.ToLower(str))
if err != nil {
return false, err
}
return restartDeploymentBool, nil
}

View File

@@ -394,6 +394,148 @@ var tests = []testUpdateSecretTask{
expectedRestart: false,
globalAutoRestartEnabled: false,
},
{
testName: `Secret autostart true value takes precedence over false deployment value`,
existingNamespace: defaultNamespace,
existingDeployment: &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: deploymentKind,
APIVersion: deploymentAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
RestartDeploymentsAnnotation: "false",
},
},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Env: []corev1.EnvVar{
{
Name: name,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
Key: passKey,
},
},
},
},
},
},
},
},
},
},
existingSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
VersionAnnotation: "old version",
ItemPathAnnotation: itemPath,
RestartDeploymentsAnnotation: "true",
},
},
Data: expectedSecretData,
},
expectedError: nil,
expectedResultSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
VersionAnnotation: fmt.Sprint(itemVersion),
ItemPathAnnotation: itemPath,
RestartDeploymentsAnnotation: "true",
},
},
Data: expectedSecretData,
},
opItem: map[string]string{
userKey: username,
passKey: password,
},
expectedRestart: true,
globalAutoRestartEnabled: false,
},
{
testName: `Secret autostart true value takes precedence over false deployment value`,
existingNamespace: defaultNamespace,
existingDeployment: &appsv1.Deployment{
TypeMeta: metav1.TypeMeta{
Kind: deploymentKind,
APIVersion: deploymentAPIVersion,
},
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
RestartDeploymentsAnnotation: "true",
},
},
Spec: appsv1.DeploymentSpec{
Template: corev1.PodTemplateSpec{
Spec: corev1.PodSpec{
Containers: []corev1.Container{
{
Env: []corev1.EnvVar{
{
Name: name,
ValueFrom: &corev1.EnvVarSource{
SecretKeyRef: &corev1.SecretKeySelector{
LocalObjectReference: corev1.LocalObjectReference{
Name: name,
},
Key: passKey,
},
},
},
},
},
},
},
},
},
},
existingSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
VersionAnnotation: "old version",
ItemPathAnnotation: itemPath,
RestartDeploymentsAnnotation: "false",
},
},
Data: expectedSecretData,
},
expectedError: nil,
expectedResultSecret: &corev1.Secret{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Namespace: namespace,
Annotations: map[string]string{
VersionAnnotation: fmt.Sprint(itemVersion),
ItemPathAnnotation: itemPath,
RestartDeploymentsAnnotation: "false",
},
},
Data: expectedSecretData,
},
opItem: map[string]string{
userKey: username,
passKey: password,
},
expectedRestart: false,
globalAutoRestartEnabled: true,
},
{
testName: `Deployment autostart true value takes precedence over false global auto restart value`,
existingNamespace: defaultNamespace,
@@ -461,7 +603,7 @@ var tests = []testUpdateSecretTask{
passKey: password,
},
expectedRestart: true,
globalAutoRestartEnabled: true,
globalAutoRestartEnabled: false,
},
{
testName: `Deployment autostart false value takes precedence over false global auto restart value,
@@ -685,7 +827,7 @@ func TestUpdateSecretHandler(t *testing.T) {
if ok {
assert.True(t, testData.expectedRestart, "Expected deployment to restart but it did not")
} else {
assert.False(t, testData.expectedRestart)
assert.False(t, testData.expectedRestart, "Deployment was restarted but should not have been.")
}
})
}
@@ -694,12 +836,12 @@ func TestUpdateSecretHandler(t *testing.T) {
func TestIsUpdatedSecret(t *testing.T) {
secretName := "test-secret"
updatedSecrets := map[string]bool{
"some_secret": true,
updatedSecrets := map[string]*corev1.Secret{
"some_secret": &corev1.Secret{},
}
assert.False(t, isUpdatedSecret(secretName, updatedSecrets))
updatedSecrets[secretName] = true
updatedSecrets[secretName] = &corev1.Secret{}
assert.True(t, isUpdatedSecret(secretName, updatedSecrets))
}

View File

@@ -2,7 +2,7 @@ package onepassword
import corev1 "k8s.io/api/core/v1"
func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]bool) bool {
func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]*corev1.Secret) bool {
for i := 0; i < len(volumes); i++ {
if secret := volumes[i].Secret; secret != nil {
secretName := secret.SecretName
@@ -14,3 +14,16 @@ func AreVolumesUsingSecrets(volumes []corev1.Volume, secrets map[string]bool) bo
}
return false
}
func AppendUpdatedVolumeSecrets(volumes []corev1.Volume, secrets map[string]*corev1.Secret, updatedDeploymentSecrets map[string]*corev1.Secret) map[string]*corev1.Secret {
for i := 0; i < len(volumes); i++ {
if secret := volumes[i].Secret; secret != nil {
secretName := secret.SecretName
secret, ok := secrets[secretName]
if ok {
updatedDeploymentSecrets[secret.Name] = secret
}
}
}
return updatedDeploymentSecrets
}

View File

@@ -2,12 +2,14 @@ package onepassword
import (
"testing"
corev1 "k8s.io/api/core/v1"
)
func TestAreVolmesUsingSecrets(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
volumeSecretNames := []string{
@@ -24,9 +26,9 @@ func TestAreVolmesUsingSecrets(t *testing.T) {
}
func TestAreVolumesNotUsingSecrets(t *testing.T) {
secretNamesToSearch := map[string]bool{
"onepassword-database-secret": true,
"onepassword-api-key": true,
secretNamesToSearch := map[string]*corev1.Secret{
"onepassword-database-secret": &corev1.Secret{},
"onepassword-api-key": &corev1.Secret{},
}
volumeSecretNames := []string{

View File

@@ -1,5 +1,10 @@
package utils
import (
"strconv"
"strings"
)
func ContainsString(slice []string, s string) bool {
for _, item := range slice {
if item == s {
@@ -18,3 +23,11 @@ func RemoveString(slice []string, s string) (result []string) {
}
return
}
func StringToBool(str string) (bool, error) {
restartDeploymentBool, err := strconv.ParseBool(strings.ToLower(str))
if err != nil {
return false, err
}
return restartDeploymentBool, nil
}