Skip to content

Commit

Permalink
Handle empty namespace on trigger resources (#224)
Browse files Browse the repository at this point in the history
* Set sensor namespace on trigger resources by default

* Update OpenAPI gen

* Update Gopkg.lock

* Fix tests

* Make condition easier to read
  • Loading branch information
dtaniwaki authored and VaibhavPage committed Mar 13, 2019
1 parent 2921f78 commit ec51559
Show file tree
Hide file tree
Showing 6 changed files with 94 additions and 26 deletions.
5 changes: 4 additions & 1 deletion Gopkg.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 5 additions & 4 deletions pkg/apis/sensor/v1alpha1/openapi_generated.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/apis/sensor/v1alpha1/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ type ResourceObject struct {
GroupVersionKind `json:",inline" protobuf:"bytes,5,opt,name=groupVersionKind"`

// Namespace in which to create this object
// defaults to the service account namespace
// defaults to the sensor namespace
Namespace string `json:"namespace" protobuf:"bytes,1,opt,name=namespace"`

// Source of the K8 resource file(s)
Expand Down
17 changes: 15 additions & 2 deletions sensors/event-handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
var sensorStr = `apiVersion: argoproj.io/v1alpha1
kind: Sensor
metadata:
namespace: argo-events
name: test-sensor
labels:
sensors.argoproj.io/sensor-controller-instanceid: argo-events
Expand Down Expand Up @@ -78,6 +79,13 @@ spec:
image: "docker/whalesay:latest"
name: whalesay`

var podResourceList = metav1.APIResourceList{
GroupVersion: metav1.GroupVersion{Group: "", Version: "v1"}.String(),
APIResources: []metav1.APIResource{
{Kind: "Pod", Namespaced: true, Name: "pods", SingularName: "pod", Group: "", Version: "v1", Verbs: []string{"create", "get"}},
},
}

func getSensor() (*v1alpha1.Sensor, error) {
var sensor v1alpha1.Sensor
err := yaml.Unmarshal([]byte(sensorStr), &sensor)
Expand All @@ -100,10 +108,15 @@ func (m *mockHttpWriter) WriteHeader(statusCode int) {

func getsensorExecutionCtx(sensor *v1alpha1.Sensor) *sensorExecutionCtx {
kubeClientset := fake.NewSimpleClientset()
fakeDiscoveryClient := kubeClientset.Discovery().(*discoveryFake.FakeDiscovery)
clientPool := &FakeClientPool{
Fake: kubeClientset.Fake,
}
fakeDiscoveryClient.Resources = append(fakeDiscoveryClient.Resources, &podResourceList)
return &sensorExecutionCtx{
kubeClient: kubeClientset,
discoveryClient: kubeClientset.Discovery().(*discoveryFake.FakeDiscovery),
clientPool: NewFakeClientPool(),
discoveryClient: fakeDiscoveryClient,
clientPool: clientPool,
log: common.GetLoggerContext(common.LoggerConf()).Logger(),
sensorClient: sensorFake.NewSimpleClientset(),
sensor: sensor,
Expand Down
12 changes: 8 additions & 4 deletions sensors/trigger.go
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,13 @@ func (sec *sensorExecutionCtx) executeTrigger(trigger v1alpha1.Trigger) error {

// createResourceObject creates K8s object for trigger
func (sec *sensorExecutionCtx) createResourceObject(resource *v1alpha1.ResourceObject, obj *unstructured.Unstructured) error {
if resource.Namespace != "" {
obj.SetNamespace(resource.Namespace)
namespace := resource.Namespace
// Defaults to sensor's namespace
if namespace == "" {
namespace = sec.sensor.Namespace
}
obj.SetNamespace(namespace)

if resource.Labels != nil {
labels := obj.GetLabels()
if labels != nil {
Expand Down Expand Up @@ -225,13 +229,13 @@ func (sec *sensorExecutionCtx) createResourceObject(resource *v1alpha1.ResourceO
}
sec.log.Info().Str("api", apiResource.Name).Str("group-version", gvk.Version).Msg("created api resource")

reIf := client.Resource(apiResource, resource.Namespace)
reIf := client.Resource(apiResource, namespace)
liveObj, err := reIf.Create(obj)
if err != nil {
return fmt.Errorf("failed to create resource object. err: %+v", err)
}
sec.log.Info().Str("kind", liveObj.GetKind()).Str("name", liveObj.GetName()).Msg("created object")
if !errors.IsAlreadyExists(err) {
if err == nil || !errors.IsAlreadyExists(err) {
return err
}
liveObj, err = reIf.Get(obj.GetName(), metav1.GetOptions{})
Expand Down
75 changes: 61 additions & 14 deletions sensors/trigger_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ import (
"k8s.io/apimachinery/pkg/types"
"k8s.io/apimachinery/pkg/watch"
"k8s.io/client-go/dynamic"
dynamicfake "k8s.io/client-go/dynamic/fake"
"k8s.io/client-go/kubernetes/fake"
kTesting "k8s.io/client-go/testing"
"k8s.io/client-go/util/flowcontrol"
Expand Down Expand Up @@ -197,30 +198,23 @@ func (p *FakeClientPool) ClientForGroupVersionKind(kind schema.GroupVersionKind)
}

var testWf = `
apiVersion: argoproj.io/v1alpha1
kind: Workflow
apiVersion: v1
kind: Pod
metadata:
generateName: hello-world-
spec:
entrypoint: whalesay
templates:
- name: whalesay
container:
args:
- "hello world"
command:
- cowsay
image: "docker/whalesay:latest"
containers:
- name: whalesay
image: "docker/whalesay:latest"
`

var testTrigger = v1alpha1.Trigger{
Name: "sample",
Resource: &v1alpha1.ResourceObject{
Namespace: corev1.NamespaceDefault,
GroupVersionKind: v1alpha1.GroupVersionKind{
Group: "argoproj.io",
Version: "v1alpha1",
Kind: "workflow",
Version: "v1",
Kind: "Pod",
},
Source: v1alpha1.ArtifactLocation{
Inline: &testWf,
Expand All @@ -241,3 +235,56 @@ func TestProcessTrigger(t *testing.T) {
convey.So(err, convey.ShouldNotBeNil)
})
}

func TestCreateResourceObject(t *testing.T) {
convey.Convey("Given a resource object", t, func() {
testSensor, err := getSensor()
convey.So(err, convey.ShouldBeNil)
soc := getsensorExecutionCtx(testSensor)
fakeclient := soc.clientPool.(*FakeClientPool).Fake
dynamicClient := dynamicfake.FakeResourceClient{Resource: schema.GroupVersionResource{Version: "v1", Resource: "pods"}, Fake: &fakeclient}

convey.Convey("Given a pod", func() {
rObj := testTrigger.Resource.DeepCopy()
rObj.Namespace = "foo"
pod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{Namespace: rObj.Namespace, Name: "my-pod"},
}
uObj, err := getUnstructuredPod(pod)
convey.So(err, convey.ShouldBeNil)

err = soc.createResourceObject(rObj, uObj)
convey.So(err, convey.ShouldBeNil)

unstructuredPod, err := dynamicClient.Get(pod.Name, metav1.GetOptions{})
convey.So(err, convey.ShouldBeNil)
convey.So(unstructuredPod.GetNamespace(), convey.ShouldEqual, rObj.Namespace)
})
convey.Convey("Given a pod without namespace, use sensor namespace", func() {
rObj := testTrigger.Resource.DeepCopy()
rObj.Namespace = ""
pod := &corev1.Pod{
TypeMeta: metav1.TypeMeta{Kind: "Pod", APIVersion: "v1"},
ObjectMeta: metav1.ObjectMeta{Name: "my-pod-without-namespace"},
}
uObj, err := getUnstructuredPod(pod)
convey.So(err, convey.ShouldBeNil)

err = soc.createResourceObject(rObj, uObj)
convey.So(err, convey.ShouldBeNil)

unstructuredPod, err := dynamicClient.Get(pod.Name, metav1.GetOptions{})
convey.So(err, convey.ShouldBeNil)
convey.So(unstructuredPod.GetNamespace(), convey.ShouldEqual, testSensor.Namespace)
})
})
}

func getUnstructuredPod(pod *corev1.Pod) (*unstructured.Unstructured, error) {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(pod)
if err != nil {
return nil, err
}
return &unstructured.Unstructured{Object: obj}, nil
}

0 comments on commit ec51559

Please sign in to comment.