Skip to content
This repository has been archived by the owner on Jan 13, 2021. It is now read-only.

Enqueue Bundle on ConfigMap/Secret event #397

Merged
merged 3 commits into from
Jan 30, 2019
Merged
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
10 changes: 7 additions & 3 deletions cmd/smith/app/bundle_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -116,8 +116,9 @@ func (c *BundleControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Contex
if err != nil {
return nil, err
}
crdGVK := apiext_v1b1.SchemeGroupVersion.WithKind("CustomResourceDefinition")
crdInf, err := apiExtensionsInformer(config, cctx, apiExtClient,
apiext_v1b1.SchemeGroupVersion.WithKind("CustomResourceDefinition"),
crdGVK,
apiext_v1b1inf.NewCustomResourceDefinitionInformer)
if err != nil {
return nil, err
Expand Down Expand Up @@ -148,7 +149,7 @@ func (c *BundleControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Contex
if err != nil {
return nil, err
}
resourceInfs[apiext_v1b1.SchemeGroupVersion.WithKind("CustomResourceDefinition")] = crdInf
resourceInfs[crdGVK] = crdInf
resourceInfs[smith_v1.BundleGVK] = bundleInf
for gvk, inf := range resourceInfs {
if err = multiStore.AddInformer(gvk, inf); err != nil {
Expand Down Expand Up @@ -226,7 +227,10 @@ func (c *BundleControllerConstructor) New(config *ctrl.Config, cctx *ctrl.Contex
Broadcaster: broadcaster,
Recorder: recorder,
}
cntrlr.Prepare(crdInf, resourceInfs)
err = cntrlr.Prepare(crdInf, resourceInfs)

Choose a reason for hiding this comment

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

🤔 this should have been a warning before...

Copy link
Contributor Author

Choose a reason for hiding this comment

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

It wasn't returning an error before this PR.

if err != nil {
return nil, err
}

return &ctrl.Constructed{
Interface: cntrlr,
Expand Down
7 changes: 7 additions & 0 deletions it/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ go_library(
"//vendor/github.com/stretchr/testify/require:go_default_library",
"//vendor/go.uber.org/zap:go_default_library",
"//vendor/go.uber.org/zap/zaptest:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1:go_default_library",
Expand All @@ -34,6 +35,7 @@ go_library(
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/watch:go_default_library",
"//vendor/k8s.io/client-go/dynamic:go_default_library",
"//vendor/k8s.io/client-go/kubernetes:go_default_library",
Expand All @@ -51,6 +53,7 @@ go_test(
srcs = [
"adoption_test.go",
"crd_attribute_test.go",
"deployment_dependencies_test.go",
"deployment_ready_test.go",
"main_test.go",
"resource_deletion_test.go",
Expand All @@ -67,6 +70,7 @@ go_test(
"//examples/sleeper:go_default_library",
"//examples/sleeper/pkg/apis/sleeper/v1:go_default_library",
"//pkg/apis/smith/v1:go_default_library",
"//pkg/specchecker/builtin:go_default_library",
"//pkg/util/testing:go_default_library",
"//vendor/github.com/ash2k/stager:go_default_library",
"//vendor/github.com/atlassian/ctrl/apis/condition/v1:go_default_library",
Expand All @@ -76,7 +80,10 @@ go_test(
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/apis/meta/v1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/fields:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/runtime:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/util/intstr:go_default_library",
"//vendor/k8s.io/client-go/tools/cache:go_default_library",
"//vendor/k8s.io/client-go/tools/watch:go_default_library",
],
)
196 changes: 196 additions & 0 deletions it/deployment_dependencies_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,196 @@
package it

import (
"context"
"testing"

smith_v1 "github.com/atlassian/smith/pkg/apis/smith/v1"
"github.com/atlassian/smith/pkg/specchecker/builtin"
"github.com/stretchr/testify/require"
apps_v1 "k8s.io/api/apps/v1"
core_v1 "k8s.io/api/core/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/util/intstr"
"k8s.io/client-go/tools/cache"
toolswatch "k8s.io/client-go/tools/watch"
)

const (
deploymentDependenciesConfigMapName = "map1"
deploymentDependenciesSecretName = "secret1"
)

func TestConfigMapAndSecretToDeploymentToBundleIndex(t *testing.T) {
t.Parallel()

bundle := constructDeploymentDependenciesBundle()
SetupApp(t, bundle, false, true, assertConfigMapAndSecretToDeploymentToBundleIndex)
}

func assertConfigMapAndSecretToDeploymentToBundleIndex(ctx context.Context, t *testing.T, cfg *Config, args ...interface{}) {
// initial create of ConfigMap and Secret
cm, err := cfg.MainClient.CoreV1().ConfigMaps(cfg.Namespace).Create(deploymentDependenciesConfigMap())
require.NoError(cfg.T, err)
secret, err := cfg.MainClient.CoreV1().Secrets(cfg.Namespace).Create(deploymentDependenciesSecret())
require.NoError(cfg.T, err)

// Wait for stable state
deploymentName := cfg.Bundle.Spec.Resources[0].Spec.Object.(meta_v1.Object).GetName()
lw := cache.NewListWatchFromClient(cfg.MainClient.AppsV1().RESTClient(), "deployments", cfg.Namespace, fields.Everything())
cond := IsPodSpecAnnotationCond(t, cfg.Namespace, deploymentName, builtin.EnvRefHashAnnotation, "97b5461821487e047e760880764dd9b31a5b7f39e8961b98b809c6d3f5b3cf3a")
_, err = toolswatch.UntilWithSync(ctx, lw, &apps_v1.Deployment{}, nil, cond)
require.NoError(cfg.T, err)

// Update ConfigMap
cm.Data["b"] = "a"
_, err = cfg.MainClient.CoreV1().ConfigMaps(cfg.Namespace).Update(cm)
require.NoError(cfg.T, err)

// Wait for updated annotation
cond = IsPodSpecAnnotationCond(t, cfg.Namespace, deploymentName, builtin.EnvRefHashAnnotation, "5fb60505d125dd42160a9ef237873345020a90e8d607861ced50a641c3a800a9")
_, err = toolswatch.UntilWithSync(ctx, lw, &apps_v1.Deployment{}, nil, cond)
require.NoError(cfg.T, err)

// Update Secret
secret.StringData = map[string]string{
"z": "c",
}
_, err = cfg.MainClient.CoreV1().Secrets(cfg.Namespace).Update(secret)
require.NoError(cfg.T, err)

// Wait for updated annotation
cond = IsPodSpecAnnotationCond(t, cfg.Namespace, deploymentName, builtin.EnvRefHashAnnotation, "20ed86a5106aab7e892f498f38dc1b713405d864878e6a074377fbdcba129599")
_, err = toolswatch.UntilWithSync(ctx, lw, &apps_v1.Deployment{}, nil, cond)
require.NoError(cfg.T, err)
}

func constructDeploymentDependenciesBundle() *smith_v1.Bundle {
var (
replicas int32 = 1
minReadySeconds int32 = 1
revisionHistoryLimit int32 = 10
progressDeadlineSeconds int32 = 5
terminationGracePeriodSeconds int64 = 30
labelMap = map[string]string{
"name": string(deploymentResourceName),
}
)
return &smith_v1.Bundle{
TypeMeta: meta_v1.TypeMeta{
Kind: smith_v1.BundleResourceKind,
APIVersion: smith_v1.BundleResourceGroupVersion,
},
ObjectMeta: meta_v1.ObjectMeta{
Name: "bundle-dt",
},
Spec: smith_v1.BundleSpec{
Resources: []smith_v1.Resource{
{
Name: deploymentResourceName,
Spec: smith_v1.ResourceSpec{

Choose a reason for hiding this comment

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

We're going to have to make builders for this stuff or put it in files. I'm realizing there's.... a lot of boilerplate.

Object: &apps_v1.Deployment{
TypeMeta: meta_v1.TypeMeta{
Kind: "Deployment",
APIVersion: apps_v1.SchemeGroupVersion.String(),
},
ObjectMeta: meta_v1.ObjectMeta{
Name: string(deploymentResourceName),
},
Spec: apps_v1.DeploymentSpec{
Selector: &meta_v1.LabelSelector{
MatchLabels: labelMap,
},
Replicas: &replicas,
Template: core_v1.PodTemplateSpec{
ObjectMeta: meta_v1.ObjectMeta{
Labels: labelMap,
},
Spec: core_v1.PodSpec{
Containers: []core_v1.Container{
{
Name: "container1",
Image: "roaanv/k8sti",
EnvFrom: []core_v1.EnvFromSource{
{
ConfigMapRef: &core_v1.ConfigMapEnvSource{
LocalObjectReference: core_v1.LocalObjectReference{
Name: deploymentDependenciesConfigMapName,
},
},
},
{
SecretRef: &core_v1.SecretEnvSource{
LocalObjectReference: core_v1.LocalObjectReference{
Name: deploymentDependenciesSecretName,
},
},
},
},
ImagePullPolicy: core_v1.PullAlways,
TerminationMessagePath: "/dev/termination-log",
TerminationMessagePolicy: core_v1.TerminationMessageReadFile,
},
},
DNSPolicy: core_v1.DNSClusterFirst,
RestartPolicy: core_v1.RestartPolicyAlways,
SchedulerName: "default-scheduler",
SecurityContext: &core_v1.PodSecurityContext{},
TerminationGracePeriodSeconds: &terminationGracePeriodSeconds,
},
},
MinReadySeconds: minReadySeconds,
ProgressDeadlineSeconds: &progressDeadlineSeconds,
RevisionHistoryLimit: &revisionHistoryLimit,

Strategy: apps_v1.DeploymentStrategy{
Type: apps_v1.RollingUpdateDeploymentStrategyType,
RollingUpdate: &apps_v1.RollingUpdateDeployment{
MaxUnavailable: &intstr.IntOrString{
Type: intstr.String,
StrVal: "25%",
},
MaxSurge: &intstr.IntOrString{
Type: intstr.String,
StrVal: "25%",
},
},
},
},
},
},
},
},
},
}
}

func deploymentDependenciesConfigMap() *core_v1.ConfigMap {
return &core_v1.ConfigMap{
TypeMeta: meta_v1.TypeMeta{
Kind: "ConfigMap",
APIVersion: core_v1.SchemeGroupVersion.String(),
},
ObjectMeta: meta_v1.ObjectMeta{
Name: deploymentDependenciesConfigMapName,
},
Data: map[string]string{
"a": "b",
},
}
}

func deploymentDependenciesSecret() *core_v1.Secret {
return &core_v1.Secret{
TypeMeta: meta_v1.TypeMeta{
Kind: "Secret",
APIVersion: core_v1.SchemeGroupVersion.String(),
},
ObjectMeta: meta_v1.ObjectMeta{
Name: deploymentDependenciesSecretName,
},
StringData: map[string]string{
"x": "b",
},
}
}
35 changes: 35 additions & 0 deletions it/utils_for_tests.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ import (
"github.com/stretchr/testify/require"
"go.uber.org/zap"
"go.uber.org/zap/zaptest"
apps_v1 "k8s.io/api/apps/v1"
core_v1 "k8s.io/api/core/v1"
apiExtClientset "k8s.io/apiextensions-apiserver/pkg/client/clientset/clientset"
apiext_v1b1inf "k8s.io/apiextensions-apiserver/pkg/client/informers/externalversions/apiextensions/v1beta1"
Expand All @@ -36,6 +37,7 @@ import (
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/fields"
"k8s.io/apimachinery/pkg/runtime"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
"k8s.io/client-go/kubernetes"
Expand All @@ -45,6 +47,14 @@ import (
toolswatch "k8s.io/client-go/tools/watch"
)

var (
appsV1Scheme = runtime.NewScheme()
)

func init() {
utilruntime.Must(apps_v1.SchemeBuilder.AddToScheme(appsV1Scheme))
}

type TestFunc func(context.Context, *testing.T, *Config, ...interface{})

type Config struct {
Expand Down Expand Up @@ -161,6 +171,31 @@ func IsBundleObservedGenerationCond(namespace, name string) toolswatch.Condition
}
}

func IsPodSpecAnnotationCond(t *testing.T, namespace, name, annotation, value string) toolswatch.ConditionFunc {
return func(event watch.Event) (bool, error) {
metaObj := event.Object.(meta_v1.Object)
if metaObj.GetNamespace() != namespace || metaObj.GetName() != name {
return false, nil
}
deployment := &apps_v1.Deployment{}
err := util.ConvertType(appsV1Scheme, event.Object, deployment)
if err != nil {
return false, err
}
annotations := deployment.Spec.Template.Annotations
actual, ok := annotations[annotation]
if !ok {
t.Logf("Pod Spec annotation %s is not set", annotation)
return false, nil
}
if actual != value {
t.Logf("Ignoring Pod Spec annotation %s value %s. Expecting %s", annotation, actual, value)
return false, nil
}
return true, nil
}
}

func TestSetup(t *testing.T) (*rest.Config, *kubernetes.Clientset, *smithClientset.Clientset) {
config, err := options.LoadRestClientConfig("voyager-test", options.RestClientOptions{
APIQPS: 10,
Expand Down
1 change: 1 addition & 0 deletions pkg/controller/bundlec/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ go_library(
"//vendor/github.com/pkg/errors:go_default_library",
"//vendor/github.com/prometheus/client_golang/prometheus:go_default_library",
"//vendor/go.uber.org/zap:go_default_library",
"//vendor/k8s.io/api/apps/v1:go_default_library",
"//vendor/k8s.io/api/core/v1:go_default_library",
"//vendor/k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1beta1:go_default_library",
"//vendor/k8s.io/apimachinery/pkg/api/errors:go_default_library",
Expand Down
Loading