Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add test to guard unset fields in deployer pod #17471

Merged
merged 1 commit into from
Nov 28, 2017
Merged
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
80 changes: 80 additions & 0 deletions pkg/apps/controller/deployer/deployer_controller_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,29 @@ package deployment

import (
"fmt"
"math/rand"
"reflect"
"sort"
"testing"

fuzz "github.com/google/gofuzz"

"k8s.io/api/core/v1"
kapiv1 "k8s.io/api/core/v1"
kerrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/api/resource"
"k8s.io/apimachinery/pkg/api/testing/fuzzer"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/diff"
kinformers "k8s.io/client-go/informers"
kclientset "k8s.io/client-go/kubernetes"
"k8s.io/client-go/kubernetes/fake"
clientgotesting "k8s.io/client-go/testing"
"k8s.io/client-go/tools/cache"
kapi "k8s.io/kubernetes/pkg/api"
kapihelper "k8s.io/kubernetes/pkg/api/helper"
kapitesting "k8s.io/kubernetes/pkg/api/testing"

deployapi "github.com/openshift/origin/pkg/apps/apis/apps"
_ "github.com/openshift/origin/pkg/apps/apis/apps/install"
Expand Down Expand Up @@ -1075,3 +1082,76 @@ func TestDeployerCustomLabelsAndAnnotations(t *testing.T) {
expectMapContains(t, podTemplate.Annotations, test.annotations, "annotations")
}
}

func TestMakeDeployerPod(t *testing.T) {
client := &fake.Clientset{}
controller := okDeploymentController(client, nil, nil, true, v1.PodUnknown)
config := deploytest.OkDeploymentConfig(1)
deployment, _ := deployutil.MakeDeploymentV1(config, codec)
container := controller.makeDeployerContainer(&config.Spec.Strategy)
container.Resources = deployutil.CopyApiResourcesToV1Resources(&config.Spec.Strategy.Resources)
defaultGracePeriod := int64(10)
maxDeploymentDurationSeconds := deployapi.MaxDeploymentDurationSeconds

for i := 1; i <= 25; i++ {
seed := rand.Int63()
f := fuzzer.FuzzerFor(kapitesting.FuzzerFuncs, rand.NewSource(seed), kapi.Codecs)
f.Funcs(
func(p *kapiv1.PodTemplateSpec, c fuzz.Continue) {
c.FuzzNoCustom(p)
p.Spec.InitContainers = nil

// These are specific for deployer pod container:
p.Spec.Containers = []kapiv1.Container{*container}
p.Spec.Containers[0].Name = "deployment"
p.Spec.Containers[0].Command = container.Command
p.Spec.Containers[0].Args = container.Args
p.Spec.Containers[0].Image = container.Image
p.Spec.Containers[0].Env = append(p.Spec.Containers[0].Env, kapiv1.EnvVar{Name: "OPENSHIFT_DEPLOYMENT_NAME", Value: "config-1"})
p.Spec.Containers[0].Env = append(p.Spec.Containers[0].Env, kapiv1.EnvVar{Name: "OPENSHIFT_DEPLOYMENT_NAMESPACE", Value: "default"})
p.Spec.Containers[0].Resources = container.Resources
p.Spec.Containers[0].ImagePullPolicy = kapiv1.PullIfNotPresent

// These are hardcoded for deployer pod spec
p.Spec.RestartPolicy = kapiv1.RestartPolicyNever
p.Spec.TerminationGracePeriodSeconds = &defaultGracePeriod
p.Spec.ActiveDeadlineSeconds = &maxDeploymentDurationSeconds
p.Spec.ServiceAccountName = "sa:test"

// FIXME: These are weird or missing. If you get an error below, consider
// adding this field into deployer controller or to this list:
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Kargakis @tnozicka @smarterclayton we probably need to decide which fields we want to copy from the deployment config template to deployer pod (some of these are not copied for reason (like Volume...), some of them we should copy? (like NodeName?)..))

Copy link
Contributor

Choose a reason for hiding this comment

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

I don't think any of these should be copied except for volumes only in case of customStrategy otherwise that would be a security hole

Copy link
Contributor

Choose a reason for hiding this comment

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

feels like it should be the cluster admin who gets to choose deployers scheduling, not the user

Copy link
Contributor

Choose a reason for hiding this comment

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

Running pods on the users behalf is always fraught - we have to be careful what we allow. We have gradually given users more control over deployer pods including location of scheduling, but our current API won’t scale by one off adding fields.

Toleration improve scheduling (give the pod more options) in most cases, so it’s probably correct to copy them. However, we might have to filter some of the conditions to be safe. For now, I’m a bit concerned about adding them without some design time.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@smarterclayton i'm fine keeping this test as it is (it will alert us if new fields are added to PodSpec) with a follow up issue where we can discuss what fields we want to copy.

p.Spec.DeprecatedServiceAccount = ""
p.Spec.AutomountServiceAccountToken = nil
p.Spec.Tolerations = nil
p.Spec.Volumes = nil
p.Spec.NodeName = ""
p.Spec.HostNetwork = false
p.Spec.HostPID = false
p.Spec.HostIPC = false
p.Spec.Hostname = ""
p.Spec.Subdomain = ""
p.Spec.Affinity = nil
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Probably need to be copied as well?

p.Spec.SchedulerName = ""
p.Spec.HostAliases = nil
p.Spec.Priority = nil
p.Spec.PriorityClassName = ""
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@smarterclayton reminds me that we should maybe populate this to SYSTEM for deployer pods?

p.Spec.SecurityContext = nil
Copy link
Contributor Author

Choose a reason for hiding this comment

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

@php-coder @pweil- is this something we want to copy into deployer pod?

Copy link
Contributor

Choose a reason for hiding this comment

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

user shouldn't be able to set this on deployer pods I think; we control the image hence this as well

},
)
inputPodTemplate := &kapiv1.PodTemplateSpec{}
f.Fuzz(&inputPodTemplate)
deployment.Spec.Template = inputPodTemplate

outputPodTemplate, err := controller.makeDeployerPod(deployment)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

if !reflect.DeepEqual(inputPodTemplate.Spec, outputPodTemplate.Spec) {
t.Fatalf("Deployer pod is missing fields:\n%s\n\n%s",
diff.ObjectReflectDiff(inputPodTemplate.Spec, outputPodTemplate.Spec),
diff.ObjectDiff(inputPodTemplate.Spec, outputPodTemplate.Spec),
)
}
}
}