mirror of
https://github.com/fluxcd/flagger.git
synced 2026-04-15 06:57:34 +00:00
Merge pull request #433 from weaveworks/projected-configs
Track projected configmaps and secrets
This commit is contained in:
@@ -124,6 +124,32 @@ func (ct *ConfigTracker) GetTargetConfigs(cd *flaggerv1.Canary) (map[string]Conf
|
||||
res[secret.GetName()] = *secret
|
||||
}
|
||||
}
|
||||
|
||||
if projected := volume.Projected; projected != nil {
|
||||
for _, source := range projected.Sources {
|
||||
if cmv := source.ConfigMap; cmv != nil {
|
||||
config, err := ct.getRefFromConfigMap(cmv.Name, cd.Namespace)
|
||||
if err != nil {
|
||||
ct.Logger.Errorf("configMap %s.%s query error %v", cmv.Name, cd.Namespace, err)
|
||||
continue
|
||||
}
|
||||
if config != nil {
|
||||
res[config.GetName()] = *config
|
||||
}
|
||||
}
|
||||
|
||||
if sv := source.Secret; sv != nil {
|
||||
secret, err := ct.getRefFromSecret(sv.Name, cd.Namespace)
|
||||
if err != nil {
|
||||
ct.Logger.Errorf("secret %s.%s query error %v", sv.Name, cd.Namespace, err)
|
||||
continue
|
||||
}
|
||||
if secret != nil {
|
||||
res[secret.GetName()] = *secret
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// scan containers
|
||||
for _, container := range targetDep.Spec.Template.Spec.Containers {
|
||||
@@ -335,7 +361,26 @@ func (ct *ConfigTracker) ApplyPrimaryConfigs(spec corev1.PodSpec, refs map[strin
|
||||
spec.Volumes[i].Secret.SecretName += "-primary"
|
||||
}
|
||||
}
|
||||
|
||||
if projected := volume.Projected; projected != nil {
|
||||
for s, source := range projected.Sources {
|
||||
if cmv := source.ConfigMap; cmv != nil {
|
||||
name := fmt.Sprintf("%s/%s", ConfigRefMap, cmv.Name)
|
||||
if _, exists := refs[name]; exists {
|
||||
spec.Volumes[i].Projected.Sources[s].ConfigMap.Name += "-primary"
|
||||
}
|
||||
}
|
||||
|
||||
if sv := source.Secret; sv != nil {
|
||||
name := fmt.Sprintf("%s/%s", ConfigRefSecret, sv.Name)
|
||||
if _, exists := refs[name]; exists {
|
||||
spec.Volumes[i].Projected.Sources[s].Secret.Name += "-primary"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update containers
|
||||
for _, container := range spec.Containers {
|
||||
// update env
|
||||
|
||||
@@ -0,0 +1,131 @@
|
||||
package canary
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
)
|
||||
|
||||
func TestConfigTracker_ConfigMaps(t *testing.T) {
|
||||
mocks := newFixture()
|
||||
configMap := newTestConfigMap()
|
||||
configMapProjected := newTestConfigProjected()
|
||||
|
||||
err := mocks.deployer.Initialize(mocks.canary, true)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
depPrimary, err := mocks.kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
configPrimaryVolName := depPrimary.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap.LocalObjectReference.Name
|
||||
if configPrimaryVolName != "podinfo-config-vol-primary" {
|
||||
t.Errorf("Got config name %v wanted %v", configPrimaryVolName, "podinfo-config-vol-primary")
|
||||
}
|
||||
|
||||
configPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimary.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap color %s wanted %s", configPrimary.Data["color"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
configPrimaryEnv, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-all-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimaryEnv.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap %s wanted %s", configPrimaryEnv.Data["a"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
configPrimaryVol, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-vol-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimaryVol.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap color %s wanted %s", configPrimary.Data["color"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
configProjectedName := depPrimary.Spec.Template.Spec.Volumes[2].VolumeSource.Projected.Sources[0].ConfigMap.Name
|
||||
if configProjectedName != "podinfo-config-projected-primary" {
|
||||
t.Errorf("Got config name %v wanted %v", configProjectedName, "podinfo-config-projected-primary")
|
||||
}
|
||||
|
||||
configPrimaryProjected, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-vol-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimaryProjected.Data["color"] != configMapProjected.Data["color"] {
|
||||
t.Errorf("Got ConfigMap color %s wanted %s", configPrimaryProjected.Data["color"], configMapProjected.Data["color"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestConfigTracker_Secrets(t *testing.T) {
|
||||
mocks := newFixture()
|
||||
secret := newTestSecret()
|
||||
secretProjected := newTestSecretProjected()
|
||||
|
||||
err := mocks.deployer.Initialize(mocks.canary, true)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
depPrimary, err := mocks.kubeClient.AppsV1().Deployments("default").Get("podinfo-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
secretPrimaryVolName := depPrimary.Spec.Template.Spec.Volumes[1].VolumeSource.Secret.SecretName
|
||||
if secretPrimaryVolName != "podinfo-secret-vol-primary" {
|
||||
t.Errorf("Got config name %v wanted %v", secretPrimaryVolName, "podinfo-secret-vol-primary")
|
||||
}
|
||||
|
||||
secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimary.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
|
||||
secretPrimaryEnv, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-all-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimaryEnv.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
|
||||
secretPrimaryVol, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-vol-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimaryVol.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
|
||||
secretProjectedName := depPrimary.Spec.Template.Spec.Volumes[2].VolumeSource.Projected.Sources[1].Secret.Name
|
||||
if secretProjectedName != "podinfo-secret-projected-primary" {
|
||||
t.Errorf("Got config name %v wanted %v", secretProjectedName, "podinfo-secret-projected-primary")
|
||||
}
|
||||
|
||||
secretPrimaryProjected, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-projected-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimaryProjected.Data["apiKey"]) != string(secretProjected.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimaryProjected.Data["apiKey"], secretProjected.Data["apiKey"])
|
||||
}
|
||||
}
|
||||
@@ -21,14 +21,7 @@ func TestCanaryDeployer_Sync(t *testing.T) {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
configName := depPrimary.Spec.Template.Spec.Volumes[0].VolumeSource.ConfigMap.LocalObjectReference.Name
|
||||
if configName != "podinfo-config-vol-primary" {
|
||||
t.Errorf("Got config name %v wanted %v", configName, "podinfo-config-vol-primary")
|
||||
}
|
||||
|
||||
dep := newTestDeployment()
|
||||
configMap := NewTestConfigMap()
|
||||
secret := NewTestSecret()
|
||||
|
||||
primaryImage := depPrimary.Spec.Template.Spec.Containers[0].Image
|
||||
sourceImage := dep.Spec.Template.Spec.Containers[0].Image
|
||||
@@ -44,60 +37,6 @@ func TestCanaryDeployer_Sync(t *testing.T) {
|
||||
if hpaPrimary.Spec.ScaleTargetRef.Name != depPrimary.Name {
|
||||
t.Errorf("Got HPA target %s wanted %s", hpaPrimary.Spec.ScaleTargetRef.Name, depPrimary.Name)
|
||||
}
|
||||
|
||||
configPrimary, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimary.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap color %s wanted %s", configPrimary.Data["color"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
configPrimaryEnv, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-all-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimaryEnv.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap %s wanted %s", configPrimaryEnv.Data["a"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
configPrimaryVol, err := mocks.kubeClient.CoreV1().ConfigMaps("default").Get("podinfo-config-vol-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if configPrimaryVol.Data["color"] != configMap.Data["color"] {
|
||||
t.Errorf("Got ConfigMap color %s wanted %s", configPrimary.Data["color"], configMap.Data["color"])
|
||||
}
|
||||
|
||||
secretPrimary, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimary.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
|
||||
secretPrimaryEnv, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-all-env-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimaryEnv.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
|
||||
secretPrimaryVol, err := mocks.kubeClient.CoreV1().Secrets("default").Get("podinfo-secret-vol-primary", metav1.GetOptions{})
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
}
|
||||
|
||||
if string(secretPrimaryVol.Data["apiKey"]) != string(secret.Data["apiKey"]) {
|
||||
t.Errorf("Got primary secret %s wanted %s", secretPrimary.Data["apiKey"], secret.Data["apiKey"])
|
||||
}
|
||||
}
|
||||
|
||||
func TestCanaryDeployer_IsNewSpec(t *testing.T) {
|
||||
@@ -284,7 +223,7 @@ func TestCanaryDeployer_SyncStatus(t *testing.T) {
|
||||
t.Fatalf("Status tracking configs are empty")
|
||||
}
|
||||
configs := *res.Status.TrackedConfigs
|
||||
secret := NewTestSecret()
|
||||
secret := newTestSecret()
|
||||
if _, exists := configs["secret/"+secret.GetName()]; !exists {
|
||||
t.Errorf("Secret %s not found in status", secret.GetName())
|
||||
}
|
||||
|
||||
+100
-15
@@ -32,12 +32,14 @@ func newFixture() fixture {
|
||||
kubeClient := fake.NewSimpleClientset(
|
||||
newTestDeployment(),
|
||||
newTestHPA(),
|
||||
NewTestConfigMap(),
|
||||
NewTestConfigMapEnv(),
|
||||
NewTestConfigMapVol(),
|
||||
NewTestSecret(),
|
||||
NewTestSecretEnv(),
|
||||
NewTestSecretVol(),
|
||||
newTestConfigMap(),
|
||||
newTestConfigMapEnv(),
|
||||
newTestConfigMapVol(),
|
||||
newTestConfigProjected(),
|
||||
newTestSecret(),
|
||||
newTestSecretEnv(),
|
||||
newTestSecretVol(),
|
||||
newTestSecretProjected(),
|
||||
)
|
||||
|
||||
logger, _ := logger.NewLogger("debug")
|
||||
@@ -63,7 +65,7 @@ func newFixture() fixture {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestConfigMap() *corev1.ConfigMap {
|
||||
func newTestConfigMap() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -90,7 +92,20 @@ func NewTestConfigMapV2() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestConfigMapEnv() *corev1.ConfigMap {
|
||||
func newTestConfigProjected() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-config-projected",
|
||||
},
|
||||
Data: map[string]string{
|
||||
"color": "red",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func newTestConfigMapEnv() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -103,7 +118,7 @@ func NewTestConfigMapEnv() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestConfigMapVol() *corev1.ConfigMap {
|
||||
func newTestConfigMapVol() *corev1.ConfigMap {
|
||||
return &corev1.ConfigMap{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -116,7 +131,7 @@ func NewTestConfigMapVol() *corev1.ConfigMap {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestSecret() *corev1.Secret {
|
||||
func newTestSecret() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -130,21 +145,21 @@ func NewTestSecret() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestSecretV2() *corev1.Secret {
|
||||
func newTestSecretProjected() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
Namespace: "default",
|
||||
Name: "podinfo-secret-env",
|
||||
Name: "podinfo-secret-projected",
|
||||
},
|
||||
Type: corev1.SecretTypeOpaque,
|
||||
Data: map[string][]byte{
|
||||
"apiKey": []byte("test2"),
|
||||
"apiKey": []byte("test"),
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestSecretEnv() *corev1.Secret {
|
||||
func newTestSecretEnv() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -158,7 +173,7 @@ func NewTestSecretEnv() *corev1.Secret {
|
||||
}
|
||||
}
|
||||
|
||||
func NewTestSecretVol() *corev1.Secret {
|
||||
func newTestSecretVol() *corev1.Secret {
|
||||
return &corev1.Secret{
|
||||
TypeMeta: metav1.TypeMeta{APIVersion: corev1.SchemeGroupVersion.String()},
|
||||
ObjectMeta: metav1.ObjectMeta{
|
||||
@@ -311,6 +326,41 @@ func newTestDeployment() *appsv1.Deployment {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "projected",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
ConfigMap: &corev1.ConfigMapProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-projected",
|
||||
},
|
||||
Items: []corev1.KeyToPath{
|
||||
{
|
||||
Key: "color",
|
||||
Path: "my-group/my-color",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Secret: &corev1.SecretProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-projected",
|
||||
},
|
||||
Items: []corev1.KeyToPath{
|
||||
{
|
||||
Key: "apiKey",
|
||||
Path: "my-group/my-api-key",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
@@ -421,6 +471,41 @@ func newTestDeploymentV2() *appsv1.Deployment {
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Name: "projected",
|
||||
VolumeSource: corev1.VolumeSource{
|
||||
Projected: &corev1.ProjectedVolumeSource{
|
||||
Sources: []corev1.VolumeProjection{
|
||||
{
|
||||
ConfigMap: &corev1.ConfigMapProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-config-projected",
|
||||
},
|
||||
Items: []corev1.KeyToPath{
|
||||
{
|
||||
Key: "color",
|
||||
Path: "my-group/my-color",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
Secret: &corev1.SecretProjection{
|
||||
LocalObjectReference: corev1.LocalObjectReference{
|
||||
Name: "podinfo-secret-projected",
|
||||
},
|
||||
Items: []corev1.KeyToPath{
|
||||
{
|
||||
Key: "apiKey",
|
||||
Path: "my-group/my-api-key",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user