mirror of https://github.com/fluxcd/cli-utils.git
commit
73a24dc859
|
|
@ -114,7 +114,8 @@ func (r ResourceReference) GroupVersionKind() schema.GroupVersionKind {
|
||||||
return schema.FromAPIVersionAndKind(r.APIVersion, r.Kind)
|
return schema.FromAPIVersionAndKind(r.APIVersion, r.Kind)
|
||||||
}
|
}
|
||||||
|
|
||||||
// ObjMetadata returns the name, namespace, group, and kind of the ResourceReference
|
// ObjMetadata returns the name, namespace, group, and kind of the
|
||||||
|
// ResourceReference, wrapped in a new ObjMetadata object.
|
||||||
func (r ResourceReference) ObjMetadata() object.ObjMetadata {
|
func (r ResourceReference) ObjMetadata() object.ObjMetadata {
|
||||||
return object.ObjMetadata{
|
return object.ObjMetadata{
|
||||||
Name: r.Name,
|
Name: r.Name,
|
||||||
|
|
@ -123,6 +124,18 @@ func (r ResourceReference) ObjMetadata() object.ObjMetadata {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Unstructured returns the name, namespace, group, version, and kind of the
|
||||||
|
// ResourceReference, wrapped in a new Unstructured object.
|
||||||
|
// This is useful for performing operations with
|
||||||
|
// sigs.k8s.io/controller-runtime/pkg/client's unstructured Client.
|
||||||
|
func (r ResourceReference) Unstructured() *unstructured.Unstructured {
|
||||||
|
obj := &unstructured.Unstructured{}
|
||||||
|
obj.SetName(r.Name)
|
||||||
|
obj.SetNamespace(r.Namespace)
|
||||||
|
obj.SetGroupVersionKind(r.GroupVersionKind())
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
// String returns the format GROUP[/VERSION][/namespaces/NAMESPACE]/KIND/NAME
|
// String returns the format GROUP[/VERSION][/namespaces/NAMESPACE]/KIND/NAME
|
||||||
func (r ResourceReference) String() string {
|
func (r ResourceReference) String() string {
|
||||||
group := r.Group
|
group := r.Group
|
||||||
|
|
|
||||||
|
|
@ -28,7 +28,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
inventoryInfo := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
inventoryInfo := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
||||||
|
|
||||||
resources := []*unstructured.Unstructured{
|
resources := []*unstructured.Unstructured{
|
||||||
deploymentManifest(namespaceName),
|
withNamespace(manifestToUnstructured(deployment1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
applyCh := applier.Run(context.TODO(), inventoryInfo, resources, apply.Options{
|
applyCh := applier.Run(context.TODO(), inventoryInfo, resources, apply.Options{
|
||||||
|
|
@ -38,7 +38,6 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range applyCh {
|
for e := range applyCh {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -80,7 +79,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -136,7 +135,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
expected := testutil.ExpEvent{
|
expected := testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.NotFoundStatus,
|
Status: status.NotFoundStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -148,7 +147,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
expected = testutil.ExpEvent{
|
expected = testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.InProgressStatus,
|
Status: status.InProgressStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -159,7 +158,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
expected = testutil.ExpEvent{
|
expected = testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.CurrentStatus,
|
Status: status.CurrentStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -169,6 +168,9 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
|
|
||||||
Expect(received).To(testutil.Equal(expEvents))
|
Expect(received).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("Verify deployment created")
|
||||||
|
assertUnstructuredExists(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
|
|
||||||
By("Verify inventory")
|
By("Verify inventory")
|
||||||
invConfig.InvSizeVerifyFunc(c, inventoryName, namespaceName, inventoryID, 1)
|
invConfig.InvSizeVerifyFunc(c, inventoryName, namespaceName, inventoryID, 1)
|
||||||
|
|
||||||
|
|
@ -176,7 +178,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
destroyer := invConfig.DestroyerFactoryFunc()
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
|
|
||||||
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
||||||
destroyerEvents := runCollectNoErr(destroyer.Run(inventoryInfo, options))
|
destroyerEvents := runCollect(destroyer.Run(inventoryInfo, options))
|
||||||
|
|
||||||
expEvents = []testutil.ExpEvent{
|
expEvents = []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
|
|
@ -198,7 +200,7 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
EventType: event.DeleteType,
|
EventType: event.DeleteType,
|
||||||
DeleteEvent: &testutil.ExpDeleteEvent{
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
Operation: event.Deleted,
|
Operation: event.Deleted,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -251,6 +253,9 @@ func applyAndDestroyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("Verify deployment deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
}
|
}
|
||||||
|
|
||||||
func createInventoryInfo(invConfig InventoryConfig, inventoryName, namespaceName, inventoryID string) inventory.InventoryInfo {
|
func createInventoryInfo(invConfig InventoryConfig, inventoryName, namespaceName, inventoryID string) inventory.InventoryInfo {
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,143 @@
|
||||||
|
// Copyright 2020 The Kubernetes Authors.
|
||||||
|
// SPDX-License-Identifier: Apache-2.0
|
||||||
|
|
||||||
|
package e2e
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var deployment1 = []byte(strings.TrimSpace(`
|
||||||
|
apiVersion: apps/v1
|
||||||
|
kind: Deployment
|
||||||
|
metadata:
|
||||||
|
name: nginx-deployment
|
||||||
|
spec:
|
||||||
|
replicas: 4
|
||||||
|
selector:
|
||||||
|
matchLabels:
|
||||||
|
app: nginx
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: nginx
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.19.6
|
||||||
|
ports:
|
||||||
|
- containerPort: 80
|
||||||
|
`))
|
||||||
|
|
||||||
|
var apiservice1 = []byte(strings.TrimSpace(`
|
||||||
|
apiVersion: apiregistration.k8s.io/v1
|
||||||
|
kind: APIService
|
||||||
|
metadata:
|
||||||
|
name: v1beta1.custom.metrics.k8s.io
|
||||||
|
spec:
|
||||||
|
insecureSkipTLSVerify: true
|
||||||
|
group: custom.metrics.k8s.io
|
||||||
|
groupPriorityMinimum: 100
|
||||||
|
versionPriority: 100
|
||||||
|
service:
|
||||||
|
name: custom-metrics-stackdriver-adapter
|
||||||
|
namespace: custom-metrics
|
||||||
|
version: v1beta1
|
||||||
|
`))
|
||||||
|
|
||||||
|
var invalidCrd = []byte(strings.TrimSpace(`
|
||||||
|
apiVersion: apiextensions.k8s.io/v1
|
||||||
|
kind: CustomResourceDefinition
|
||||||
|
metadata:
|
||||||
|
name: invalidexamples.cli-utils.example.io
|
||||||
|
spec:
|
||||||
|
conversion:
|
||||||
|
strategy: None
|
||||||
|
group: cli-utils.example.io
|
||||||
|
names:
|
||||||
|
kind: InvalidExample
|
||||||
|
listKind: InvalidExampleList
|
||||||
|
plural: invalidexamples
|
||||||
|
singular: invalidexample
|
||||||
|
scope: Cluster
|
||||||
|
`))
|
||||||
|
|
||||||
|
var pod1 = []byte(strings.TrimSpace(`
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: pod1
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kubernetes-pause
|
||||||
|
image: k8s.gcr.io/pause:2.0
|
||||||
|
`))
|
||||||
|
|
||||||
|
var pod2 = []byte(strings.TrimSpace(`
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: pod2
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kubernetes-pause
|
||||||
|
image: k8s.gcr.io/pause:2.0
|
||||||
|
`))
|
||||||
|
|
||||||
|
var pod3 = []byte(strings.TrimSpace(`
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: pod3
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: kubernetes-pause
|
||||||
|
image: k8s.gcr.io/pause:2.0
|
||||||
|
`))
|
||||||
|
|
||||||
|
var podA = []byte(strings.TrimSpace(`
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: pod-a
|
||||||
|
namespace: test
|
||||||
|
annotations:
|
||||||
|
config.kubernetes.io/apply-time-mutation: |
|
||||||
|
- sourceRef:
|
||||||
|
kind: Pod
|
||||||
|
name: pod-b
|
||||||
|
sourcePath: $.status.podIP
|
||||||
|
targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
|
||||||
|
token: ${pob-b-ip}
|
||||||
|
- sourceRef:
|
||||||
|
kind: Pod
|
||||||
|
name: pod-b
|
||||||
|
sourcePath: $.spec.containers[?(@.name=="nginx")].ports[?(@.name=="tcp")].containerPort
|
||||||
|
targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
|
||||||
|
token: ${pob-b-port}
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.21
|
||||||
|
ports:
|
||||||
|
- name: tcp
|
||||||
|
containerPort: 80
|
||||||
|
env:
|
||||||
|
- name: SERVICE_HOST
|
||||||
|
value: "${pob-b-ip}:${pob-b-port}"
|
||||||
|
`))
|
||||||
|
|
||||||
|
var podB = []byte(strings.TrimSpace(`
|
||||||
|
kind: Pod
|
||||||
|
apiVersion: v1
|
||||||
|
metadata:
|
||||||
|
name: pod-b
|
||||||
|
namespace: test
|
||||||
|
spec:
|
||||||
|
containers:
|
||||||
|
- name: nginx
|
||||||
|
image: nginx:1.21
|
||||||
|
ports:
|
||||||
|
- name: tcp
|
||||||
|
containerPort: 80
|
||||||
|
`))
|
||||||
|
|
@ -4,20 +4,149 @@
|
||||||
package e2e
|
package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
|
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime"
|
"k8s.io/apimachinery/pkg/runtime"
|
||||||
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/apimachinery/pkg/util/yaml"
|
"k8s.io/apimachinery/pkg/util/yaml"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
||||||
"sigs.k8s.io/cli-utils/pkg/common"
|
"sigs.k8s.io/cli-utils/pkg/common"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/object/dependson"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/object/mutation"
|
||||||
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
func withReplicas(obj *unstructured.Unstructured, replicas int) *unstructured.Unstructured {
|
||||||
|
err := unstructured.SetNestedField(obj.Object, int64(replicas), "spec", "replicas")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
func withNamespace(obj *unstructured.Unstructured, namespace string) *unstructured.Unstructured {
|
||||||
|
obj.SetNamespace(namespace)
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
func withDependsOn(obj *unstructured.Unstructured, dep string) *unstructured.Unstructured {
|
||||||
|
a := obj.GetAnnotations()
|
||||||
|
if a == nil {
|
||||||
|
a = make(map[string]string, 1)
|
||||||
|
}
|
||||||
|
a[dependson.Annotation] = dep
|
||||||
|
obj.SetAnnotations(a)
|
||||||
|
return obj
|
||||||
|
}
|
||||||
|
|
||||||
|
func deleteUnstructuredAndWait(c client.Client, obj *unstructured.Unstructured) {
|
||||||
|
ref := mutation.NewResourceReference(obj)
|
||||||
|
|
||||||
|
err := c.Delete(context.TODO(), obj,
|
||||||
|
client.PropagationPolicy(metav1.DeletePropagationForeground))
|
||||||
|
Expect(err).NotTo(HaveOccurred(),
|
||||||
|
"expected DELETE to not error (%s): %s", ref, err)
|
||||||
|
|
||||||
|
waitForDeletion(c, obj)
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForDeletion(c client.Client, obj *unstructured.Unstructured) {
|
||||||
|
ref := mutation.NewResourceReference(obj)
|
||||||
|
resultObj := ref.Unstructured()
|
||||||
|
|
||||||
|
timeout := 30 * time.Second
|
||||||
|
retry := 2 * time.Second
|
||||||
|
|
||||||
|
t := time.NewTimer(timeout)
|
||||||
|
s := time.NewTimer(0)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
Fail("timed out waiting for resource to be fully deleted")
|
||||||
|
return
|
||||||
|
case <-s.C:
|
||||||
|
err := c.Get(context.TODO(), types.NamespacedName{
|
||||||
|
Namespace: obj.GetNamespace(),
|
||||||
|
Name: obj.GetName(),
|
||||||
|
}, resultObj)
|
||||||
|
if err != nil {
|
||||||
|
Expect(apierrors.ReasonForError(err)).To(Equal(metav1.StatusReasonNotFound),
|
||||||
|
"expected GET to error with NotFound (%s): %s", ref, err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
s = time.NewTimer(retry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func waitForCreation(c client.Client, obj *unstructured.Unstructured) {
|
||||||
|
ref := mutation.NewResourceReference(obj)
|
||||||
|
resultObj := ref.Unstructured()
|
||||||
|
|
||||||
|
timeout := 30 * time.Second
|
||||||
|
retry := 2 * time.Second
|
||||||
|
|
||||||
|
t := time.NewTimer(timeout)
|
||||||
|
s := time.NewTimer(0)
|
||||||
|
defer t.Stop()
|
||||||
|
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-t.C:
|
||||||
|
Fail("timed out waiting for resource to be fully created")
|
||||||
|
return
|
||||||
|
case <-s.C:
|
||||||
|
err := c.Get(context.TODO(), types.NamespacedName{
|
||||||
|
Namespace: obj.GetNamespace(),
|
||||||
|
Name: obj.GetName(),
|
||||||
|
}, resultObj)
|
||||||
|
if err == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
Expect(apierrors.ReasonForError(err)).To(Equal(metav1.StatusReasonNotFound),
|
||||||
|
"expected GET to error with NotFound (%s): %s", ref, err)
|
||||||
|
// if NotFound, sleep and retry
|
||||||
|
s = time.NewTimer(retry)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertUnstructuredExists(c client.Client, obj *unstructured.Unstructured) *unstructured.Unstructured {
|
||||||
|
ref := mutation.NewResourceReference(obj)
|
||||||
|
resultObj := ref.Unstructured()
|
||||||
|
|
||||||
|
err := c.Get(context.TODO(), types.NamespacedName{
|
||||||
|
Namespace: obj.GetNamespace(),
|
||||||
|
Name: obj.GetName(),
|
||||||
|
}, resultObj)
|
||||||
|
Expect(err).NotTo(HaveOccurred(),
|
||||||
|
"expected GET not to error (%s): %s", ref, err)
|
||||||
|
return resultObj
|
||||||
|
}
|
||||||
|
|
||||||
|
func assertUnstructuredDoesNotExist(c client.Client, obj *unstructured.Unstructured) {
|
||||||
|
ref := mutation.NewResourceReference(obj)
|
||||||
|
resultObj := ref.Unstructured()
|
||||||
|
|
||||||
|
err := c.Get(context.TODO(), types.NamespacedName{
|
||||||
|
Namespace: obj.GetNamespace(),
|
||||||
|
Name: obj.GetName(),
|
||||||
|
}, resultObj)
|
||||||
|
Expect(err).To(HaveOccurred(),
|
||||||
|
"expected GET to error (%s)", ref)
|
||||||
|
Expect(apierrors.ReasonForError(err)).To(Equal(metav1.StatusReasonNotFound),
|
||||||
|
"expected GET to error with NotFound (%s): %s", ref, err)
|
||||||
|
}
|
||||||
|
|
||||||
func randomString(prefix string) string {
|
func randomString(prefix string) string {
|
||||||
randomSuffix := common.RandomStr()
|
randomSuffix := common.RandomStr()
|
||||||
return fmt.Sprintf("%s%s", prefix, randomSuffix)
|
return fmt.Sprintf("%s%s", prefix, randomSuffix)
|
||||||
|
|
@ -91,73 +220,6 @@ metadata:
|
||||||
return u
|
return u
|
||||||
}
|
}
|
||||||
|
|
||||||
func deploymentManifest(namespace string) *unstructured.Unstructured {
|
|
||||||
dep := &appsv1.Deployment{
|
|
||||||
TypeMeta: metav1.TypeMeta{
|
|
||||||
APIVersion: appsv1.SchemeGroupVersion.String(),
|
|
||||||
Kind: "Deployment",
|
|
||||||
},
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Name: "nginx-deployment",
|
|
||||||
Namespace: namespace,
|
|
||||||
},
|
|
||||||
Spec: appsv1.DeploymentSpec{
|
|
||||||
Replicas: func() *int32 { r := int32(4); return &r }(),
|
|
||||||
Selector: &metav1.LabelSelector{
|
|
||||||
MatchLabels: map[string]string{
|
|
||||||
"app": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Template: v1.PodTemplateSpec{
|
|
||||||
ObjectMeta: metav1.ObjectMeta{
|
|
||||||
Labels: map[string]string{
|
|
||||||
"app": "nginx",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
Spec: v1.PodSpec{
|
|
||||||
Containers: []v1.Container{
|
|
||||||
{
|
|
||||||
Name: "nginx",
|
|
||||||
Image: "nginx:1.19.6",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
u, err := runtime.DefaultUnstructuredConverter.ToUnstructured(dep)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return &unstructured.Unstructured{
|
|
||||||
Object: u,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func apiserviceManifest() *unstructured.Unstructured {
|
|
||||||
apiservice := &unstructured.Unstructured{
|
|
||||||
Object: map[string]interface{}{
|
|
||||||
"apiVersion": "apiregistration.k8s.io/v1",
|
|
||||||
"kind": "APIService",
|
|
||||||
"metadata": map[string]interface{}{
|
|
||||||
"name": "v1beta1.custom.metrics.k8s.io",
|
|
||||||
},
|
|
||||||
"spec": map[string]interface{}{
|
|
||||||
"insecureSkipTLSVerify": true,
|
|
||||||
"group": "custom.metrics.k8s.io",
|
|
||||||
"groupPriorityMinimum": 100,
|
|
||||||
"versionPriority": 100,
|
|
||||||
"service": map[string]interface{}{
|
|
||||||
"name": "custom-metrics-stackdriver-adapter",
|
|
||||||
"namespace": "custome-metrics",
|
|
||||||
},
|
|
||||||
"version": "v1beta1",
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}
|
|
||||||
return apiservice
|
|
||||||
}
|
|
||||||
|
|
||||||
func manifestToUnstructured(manifest []byte) *unstructured.Unstructured {
|
func manifestToUnstructured(manifest []byte) *unstructured.Unstructured {
|
||||||
u := make(map[string]interface{})
|
u := make(map[string]interface{})
|
||||||
err := yaml.Unmarshal(manifest, &u)
|
err := yaml.Unmarshal(manifest, &u)
|
||||||
|
|
@ -168,11 +230,3 @@ func manifestToUnstructured(manifest []byte) *unstructured.Unstructured {
|
||||||
Object: u,
|
Object: u,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func updateReplicas(u *unstructured.Unstructured, replicas int) *unstructured.Unstructured {
|
|
||||||
err := unstructured.SetNestedField(u.Object, int64(replicas), "spec", "replicas")
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -6,7 +6,6 @@ package e2e
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"strings"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
@ -19,7 +18,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryName, namespaceName string) {
|
func continueOnErrorTest(c client.Client, invConfig InventoryConfig, inventoryName, namespaceName string) {
|
||||||
By("apply an invalid CRD")
|
By("apply an invalid CRD")
|
||||||
applier := invConfig.ApplierFactoryFunc()
|
applier := invConfig.ApplierFactoryFunc()
|
||||||
|
|
||||||
|
|
@ -27,13 +26,13 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
|
|
||||||
resources := []*unstructured.Unstructured{
|
resources := []*unstructured.Unstructured{
|
||||||
manifestToUnstructured(invalidCrd),
|
manifestToUnstructured(invalidCrd),
|
||||||
|
withNamespace(manifestToUnstructured(pod1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), inv, resources, apply.Options{})
|
ch := applier.Run(context.TODO(), inv, resources, apply.Options{})
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -71,7 +70,7 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// Apply object which fails
|
// Apply invalidCrd fails
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(invalidCrd)),
|
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(invalidCrd)),
|
||||||
|
|
@ -80,6 +79,15 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
),
|
),
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
// Create pod1
|
||||||
|
EventType: event.ApplyType,
|
||||||
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
|
Operation: event.Created,
|
||||||
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod1), namespaceName)),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
{
|
{
|
||||||
// ApplyTask finished
|
// ApplyTask finished
|
||||||
EventType: event.ActionGroupType,
|
EventType: event.ActionGroupType,
|
||||||
|
|
@ -90,6 +98,25 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
// Note: No WaitTask when apply fails
|
// Note: No WaitTask when apply fails
|
||||||
|
// TODO: why no wait after create tho?
|
||||||
|
// {
|
||||||
|
// // WaitTask start
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Started,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// // WaitTask finished
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Finished,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
{
|
{
|
||||||
// InvSetTask start
|
// InvSetTask start
|
||||||
EventType: event.ActionGroupType,
|
EventType: event.ActionGroupType,
|
||||||
|
|
@ -110,21 +137,10 @@ func continueOnErrorTest(_ client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
||||||
}
|
|
||||||
|
|
||||||
var invalidCrd = []byte(strings.TrimSpace(`
|
By("Verify pod1 created")
|
||||||
apiVersion: apiextensions.k8s.io/v1
|
assertUnstructuredExists(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
kind: CustomResourceDefinition
|
|
||||||
metadata:
|
By("Verify CRD not created")
|
||||||
name: invalidexamples.cli-utils.example.io
|
assertUnstructuredDoesNotExist(c, manifestToUnstructured(invalidCrd))
|
||||||
spec:
|
}
|
||||||
conversion:
|
|
||||||
strategy: None
|
|
||||||
group: cli-utils.example.io
|
|
||||||
names:
|
|
||||||
kind: InvalidExample
|
|
||||||
listKind: InvalidExampleList
|
|
||||||
plural: invalidexamples
|
|
||||||
singular: invalidexample
|
|
||||||
scope: Cluster
|
|
||||||
`))
|
|
||||||
|
|
|
||||||
|
|
@ -37,7 +37,6 @@ func crdTest(_ client.Client, invConfig InventoryConfig, inventoryName, namespac
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -179,7 +178,7 @@ func crdTest(_ client.Client, invConfig InventoryConfig, inventoryName, namespac
|
||||||
By("destroy the resources, including the crd")
|
By("destroy the resources, including the crd")
|
||||||
destroyer := invConfig.DestroyerFactoryFunc()
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
||||||
destroyerEvents := runCollectNoErr(destroyer.Run(inv, options))
|
destroyerEvents := runCollect(destroyer.Run(inv, options))
|
||||||
|
|
||||||
expEvents = []testutil.ExpEvent{
|
expEvents = []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ package e2e
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"strings"
|
"fmt"
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
|
|
@ -18,7 +18,7 @@ import (
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, namespaceName string) {
|
func dependsOnTest(c client.Client, invConfig InventoryConfig, inventoryName, namespaceName string) {
|
||||||
By("apply resources in order based on depends-on annotation")
|
By("apply resources in order based on depends-on annotation")
|
||||||
applier := invConfig.ApplierFactoryFunc()
|
applier := invConfig.ApplierFactoryFunc()
|
||||||
|
|
||||||
|
|
@ -27,9 +27,9 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
// Dependency order: pod1 -> pod3 -> pod2
|
// Dependency order: pod1 -> pod3 -> pod2
|
||||||
// Apply order: pod2, pod3, pod1
|
// Apply order: pod2, pod3, pod1
|
||||||
resources := []*unstructured.Unstructured{
|
resources := []*unstructured.Unstructured{
|
||||||
manifestToUnstructured(pod1),
|
withDependsOn(withNamespace(manifestToUnstructured(pod1), namespaceName), fmt.Sprintf("/namespaces/%s/Pod/pod3", namespaceName)),
|
||||||
manifestToUnstructured(pod2),
|
withNamespace(manifestToUnstructured(pod2), namespaceName),
|
||||||
manifestToUnstructured(pod3),
|
withDependsOn(withNamespace(manifestToUnstructured(pod3), namespaceName), fmt.Sprintf("/namespaces/%s/Pod/pod2", namespaceName)),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
||||||
|
|
@ -38,7 +38,6 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
expEvents := []testutil.ExpEvent{
|
expEvents := []testutil.ExpEvent{
|
||||||
|
|
@ -79,7 +78,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod2)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod2), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -124,7 +123,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod3)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod3), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -169,7 +168,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod1)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -221,10 +220,31 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
}
|
}
|
||||||
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("verify pod1 created and ready")
|
||||||
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
podIP, found, err := testutil.NestedField(result.Object, "status", "podIP")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
|
||||||
|
|
||||||
|
By("verify pod2 created and ready")
|
||||||
|
result = assertUnstructuredExists(c, withNamespace(manifestToUnstructured(pod2), namespaceName))
|
||||||
|
podIP, found, err = testutil.NestedField(result.Object, "status", "podIP")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
|
||||||
|
|
||||||
|
By("verify pod3 created and ready")
|
||||||
|
result = assertUnstructuredExists(c, withNamespace(manifestToUnstructured(pod3), namespaceName))
|
||||||
|
podIP, found, err = testutil.NestedField(result.Object, "status", "podIP")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
|
||||||
|
|
||||||
By("destroy resources in opposite order")
|
By("destroy resources in opposite order")
|
||||||
destroyer := invConfig.DestroyerFactoryFunc()
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
||||||
destroyerEvents := runCollectNoErr(destroyer.Run(inv, options))
|
destroyerEvents := runCollect(destroyer.Run(inv, options))
|
||||||
|
|
||||||
expEvents = []testutil.ExpEvent{
|
expEvents = []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
|
|
@ -246,7 +266,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.DeleteType,
|
EventType: event.DeleteType,
|
||||||
DeleteEvent: &testutil.ExpDeleteEvent{
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
Operation: event.Deleted,
|
Operation: event.Deleted,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod1)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -291,7 +311,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.DeleteType,
|
EventType: event.DeleteType,
|
||||||
DeleteEvent: &testutil.ExpDeleteEvent{
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
Operation: event.Deleted,
|
Operation: event.Deleted,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod3)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod3), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -336,7 +356,7 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
EventType: event.DeleteType,
|
EventType: event.DeleteType,
|
||||||
DeleteEvent: &testutil.ExpDeleteEvent{
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
Operation: event.Deleted,
|
Operation: event.Deleted,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod2)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod2), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -386,46 +406,14 @@ func dependsOnTest(_ client.Client, invConfig InventoryConfig, inventoryName, na
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("verify pod1 deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
|
||||||
|
By("verify pod2 deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(pod2), namespaceName))
|
||||||
|
|
||||||
|
By("verify pod3 deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(pod3), namespaceName))
|
||||||
}
|
}
|
||||||
|
|
||||||
var pod1 = []byte(strings.TrimSpace(`
|
|
||||||
kind: Pod
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: pod1
|
|
||||||
namespace: default
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/depends-on: /namespaces/default/Pod/pod3
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: kubernetes-pause
|
|
||||||
image: k8s.gcr.io/pause:2.0
|
|
||||||
`))
|
|
||||||
|
|
||||||
var pod2 = []byte(strings.TrimSpace(`
|
|
||||||
kind: Pod
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: pod2
|
|
||||||
namespace: default
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: kubernetes-pause
|
|
||||||
image: k8s.gcr.io/pause:2.0
|
|
||||||
`))
|
|
||||||
|
|
||||||
var pod3 = []byte(strings.TrimSpace(`
|
|
||||||
kind: Pod
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: pod3
|
|
||||||
namespace: default
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/depends-on: /namespaces/default/Pod/pod2
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: kubernetes-pause
|
|
||||||
image: k8s.gcr.io/pause:2.0
|
|
||||||
`))
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@ import (
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
"k8s.io/apimachinery/pkg/types"
|
||||||
"k8s.io/cli-runtime/pkg/genericclioptions"
|
"k8s.io/cli-runtime/pkg/genericclioptions"
|
||||||
|
"k8s.io/klog/v2"
|
||||||
"k8s.io/kubectl/pkg/cmd/util"
|
"k8s.io/kubectl/pkg/cmd/util"
|
||||||
"k8s.io/kubectl/pkg/scheme"
|
"k8s.io/kubectl/pkg/scheme"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply"
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
||||||
|
|
@ -72,6 +73,15 @@ var inventoryConfigs = map[string]InventoryConfig{
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Parse optional logging flags
|
||||||
|
// Ex: ginkgo ./test/e2e/... -- -v=5
|
||||||
|
// Allow init for e2e test (not imported by external code)
|
||||||
|
// nolint:gochecknoinits
|
||||||
|
func init() {
|
||||||
|
klog.InitFlags(nil)
|
||||||
|
klog.SetOutput(GinkgoWriter)
|
||||||
|
}
|
||||||
|
|
||||||
var _ = Describe("Applier", func() {
|
var _ = Describe("Applier", func() {
|
||||||
|
|
||||||
var c client.Client
|
var c client.Client
|
||||||
|
|
@ -116,10 +126,13 @@ var _ = Describe("Applier", func() {
|
||||||
objs := []*unstructured.Unstructured{
|
objs := []*unstructured.Unstructured{
|
||||||
manifestToUnstructured(cr),
|
manifestToUnstructured(cr),
|
||||||
manifestToUnstructured(crd),
|
manifestToUnstructured(crd),
|
||||||
manifestToUnstructured(pod1),
|
withNamespace(manifestToUnstructured(pod1), namespace.GetName()),
|
||||||
manifestToUnstructured(pod2),
|
withNamespace(manifestToUnstructured(pod2), namespace.GetName()),
|
||||||
manifestToUnstructured(pod3),
|
withNamespace(manifestToUnstructured(pod3), namespace.GetName()),
|
||||||
deploymentManifest(namespace.GetName()),
|
withNamespace(manifestToUnstructured(podA), namespace.GetName()),
|
||||||
|
withNamespace(manifestToUnstructured(podB), namespace.GetName()),
|
||||||
|
withNamespace(manifestToUnstructured(deployment1), namespace.GetName()),
|
||||||
|
manifestToUnstructured(apiservice1),
|
||||||
}
|
}
|
||||||
for _, obj := range objs {
|
for _, obj := range objs {
|
||||||
deleteUnstructuredIfExists(c, obj)
|
deleteUnstructuredIfExists(c, obj)
|
||||||
|
|
@ -354,9 +367,3 @@ func newDestroyerFromInvFactory(invFactory inventory.InventoryClientFactory) *ap
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
return d
|
return d
|
||||||
}
|
}
|
||||||
|
|
||||||
// Delete the passed object from the cluster using the passed client.
|
|
||||||
func deleteObj(c client.Client, obj *unstructured.Unstructured) {
|
|
||||||
err := c.Delete(context.TODO(), obj)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -10,9 +10,7 @@ import (
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply"
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
||||||
"sigs.k8s.io/cli-utils/pkg/inventory"
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
||||||
|
|
@ -29,7 +27,7 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
firstInvName := randomString("first-inv-")
|
firstInvName := randomString("first-inv-")
|
||||||
firstInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(firstInvName, namespaceName, firstInvName))
|
firstInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(firstInvName, namespaceName, firstInvName))
|
||||||
firstResources := []*unstructured.Unstructured{
|
firstResources := []*unstructured.Unstructured{
|
||||||
deploymentManifest(namespaceName),
|
withNamespace(manifestToUnstructured(deployment1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithNoErr(applier.Run(context.TODO(), firstInv, firstResources, apply.Options{
|
runWithNoErr(applier.Run(context.TODO(), firstInv, firstResources, apply.Options{
|
||||||
|
|
@ -41,7 +39,7 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
secondInvName := randomString("second-inv-")
|
secondInvName := randomString("second-inv-")
|
||||||
secondInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(secondInvName, namespaceName, secondInvName))
|
secondInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(secondInvName, namespaceName, secondInvName))
|
||||||
secondResources := []*unstructured.Unstructured{
|
secondResources := []*unstructured.Unstructured{
|
||||||
updateReplicas(deploymentManifest(namespaceName), 6),
|
withReplicas(withNamespace(manifestToUnstructured(deployment1), namespaceName), 6),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), secondInv, secondResources, apply.Options{
|
ch := applier.Run(context.TODO(), secondInv, secondResources, apply.Options{
|
||||||
|
|
@ -93,7 +91,7 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
// ApplyTask error: resource managed by another inventory
|
// ApplyTask error: resource managed by another inventory
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Error: testutil.EqualErrorType(
|
Error: testutil.EqualErrorType(
|
||||||
inventory.NewInventoryOverlapError(errors.New("test")),
|
inventory.NewInventoryOverlapError(errors.New("test")),
|
||||||
),
|
),
|
||||||
|
|
@ -151,7 +149,7 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
expected := testutil.ExpEvent{
|
expected := testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.InProgressStatus,
|
Status: status.InProgressStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -162,7 +160,7 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
expected = testutil.ExpEvent{
|
expected = testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.CurrentStatus,
|
Status: status.CurrentStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -173,20 +171,18 @@ func inventoryPolicyMustMatchTest(c client.Client, invConfig InventoryConfig, na
|
||||||
Expect(received).To(testutil.Equal(expEvents))
|
Expect(received).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
By("Verify resource wasn't updated")
|
By("Verify resource wasn't updated")
|
||||||
var d appsv1.Deployment
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
err := c.Get(context.TODO(), types.NamespacedName{
|
replicas, found, err := testutil.NestedField(result.Object, "spec", "replicas")
|
||||||
Namespace: namespaceName,
|
|
||||||
Name: deploymentManifest(namespaceName).GetName(),
|
|
||||||
}, &d)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(d.Spec.Replicas).To(Equal(func(i int32) *int32 { return &i }(4)))
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(replicas).To(Equal(int64(4)))
|
||||||
|
|
||||||
invConfig.InvCountVerifyFunc(c, namespaceName, 2)
|
invConfig.InvCountVerifyFunc(c, namespaceName, 2)
|
||||||
}
|
}
|
||||||
|
|
||||||
func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryConfig, namespaceName string) {
|
func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryConfig, namespaceName string) {
|
||||||
By("Create unmanaged resource")
|
By("Create unmanaged resource")
|
||||||
err := c.Create(context.TODO(), deploymentManifest(namespaceName))
|
err := c.Create(context.TODO(), withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
|
||||||
By("Apply resources")
|
By("Apply resources")
|
||||||
|
|
@ -195,7 +191,7 @@ func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryC
|
||||||
invName := randomString("test-inv-")
|
invName := randomString("test-inv-")
|
||||||
inv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(invName, namespaceName, invName))
|
inv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(invName, namespaceName, invName))
|
||||||
resources := []*unstructured.Unstructured{
|
resources := []*unstructured.Unstructured{
|
||||||
updateReplicas(deploymentManifest(namespaceName), 6),
|
withReplicas(withNamespace(manifestToUnstructured(deployment1), namespaceName), 6),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
||||||
|
|
@ -248,7 +244,7 @@ func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryC
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Configured,
|
Operation: event.Configured,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -304,7 +300,7 @@ func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryC
|
||||||
expected := testutil.ExpEvent{
|
expected := testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.InProgressStatus,
|
Status: status.InProgressStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -315,7 +311,7 @@ func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryC
|
||||||
expected = testutil.ExpEvent{
|
expected = testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.CurrentStatus,
|
Status: status.CurrentStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -326,14 +322,17 @@ func inventoryPolicyAdoptIfNoInventoryTest(c client.Client, invConfig InventoryC
|
||||||
Expect(received).To(testutil.Equal(expEvents))
|
Expect(received).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
By("Verify resource was updated and added to inventory")
|
By("Verify resource was updated and added to inventory")
|
||||||
var d appsv1.Deployment
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
err = c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Namespace: namespaceName,
|
replicas, found, err := testutil.NestedField(result.Object, "spec", "replicas")
|
||||||
Name: deploymentManifest(namespaceName).GetName(),
|
|
||||||
}, &d)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(d.Spec.Replicas).To(Equal(func(i int32) *int32 { return &i }(6)))
|
Expect(found).To(BeTrue())
|
||||||
Expect(d.ObjectMeta.Annotations["config.k8s.io/owning-inventory"]).To(Equal(invName))
|
Expect(replicas).To(Equal(int64(6)))
|
||||||
|
|
||||||
|
value, found, err := testutil.NestedField(result.Object, "metadata", "annotations", "config.k8s.io/owning-inventory")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(value).To(Equal(invName))
|
||||||
|
|
||||||
invConfig.InvCountVerifyFunc(c, namespaceName, 1)
|
invConfig.InvCountVerifyFunc(c, namespaceName, 1)
|
||||||
invConfig.InvSizeVerifyFunc(c, invName, namespaceName, invName, 1)
|
invConfig.InvSizeVerifyFunc(c, invName, namespaceName, invName, 1)
|
||||||
|
|
@ -346,7 +345,7 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
firstInvName := randomString("first-inv-")
|
firstInvName := randomString("first-inv-")
|
||||||
firstInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(firstInvName, namespaceName, firstInvName))
|
firstInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(firstInvName, namespaceName, firstInvName))
|
||||||
firstResources := []*unstructured.Unstructured{
|
firstResources := []*unstructured.Unstructured{
|
||||||
deploymentManifest(namespaceName),
|
withNamespace(manifestToUnstructured(deployment1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithNoErr(applier.Run(context.TODO(), firstInv, firstResources, apply.Options{
|
runWithNoErr(applier.Run(context.TODO(), firstInv, firstResources, apply.Options{
|
||||||
|
|
@ -358,7 +357,7 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
secondInvName := randomString("test-inv-")
|
secondInvName := randomString("test-inv-")
|
||||||
secondInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(secondInvName, namespaceName, secondInvName))
|
secondInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(secondInvName, namespaceName, secondInvName))
|
||||||
secondResources := []*unstructured.Unstructured{
|
secondResources := []*unstructured.Unstructured{
|
||||||
updateReplicas(deploymentManifest(namespaceName), 6),
|
withReplicas(withNamespace(manifestToUnstructured(deployment1), namespaceName), 6),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), secondInv, secondResources, apply.Options{
|
ch := applier.Run(context.TODO(), secondInv, secondResources, apply.Options{
|
||||||
|
|
@ -411,7 +410,7 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Operation: event.Configured,
|
Operation: event.Configured,
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
@ -467,7 +466,7 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
expected := testutil.ExpEvent{
|
expected := testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.InProgressStatus,
|
Status: status.InProgressStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -478,7 +477,7 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
expected = testutil.ExpEvent{
|
expected = testutil.ExpEvent{
|
||||||
EventType: event.StatusType,
|
EventType: event.StatusType,
|
||||||
StatusEvent: &testutil.ExpStatusEvent{
|
StatusEvent: &testutil.ExpStatusEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(deploymentManifest(namespaceName)),
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(deployment1), namespaceName)),
|
||||||
Status: status.CurrentStatus,
|
Status: status.CurrentStatus,
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
|
|
@ -489,14 +488,17 @@ func inventoryPolicyAdoptAllTest(c client.Client, invConfig InventoryConfig, nam
|
||||||
Expect(received).To(testutil.Equal(expEvents))
|
Expect(received).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
By("Verify resource was updated and added to inventory")
|
By("Verify resource was updated and added to inventory")
|
||||||
var d appsv1.Deployment
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
err := c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Namespace: namespaceName,
|
replicas, found, err := testutil.NestedField(result.Object, "spec", "replicas")
|
||||||
Name: deploymentManifest(namespaceName).GetName(),
|
|
||||||
}, &d)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(d.Spec.Replicas).To(Equal(func(i int32) *int32 { return &i }(6)))
|
Expect(found).To(BeTrue())
|
||||||
Expect(d.ObjectMeta.Annotations["config.k8s.io/owning-inventory"]).To(Equal(secondInvName))
|
Expect(replicas).To(Equal(int64(6)))
|
||||||
|
|
||||||
|
value, found, err := testutil.NestedField(result.Object, "metadata", "annotations", "config.k8s.io/owning-inventory")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(value).To(Equal(secondInvName))
|
||||||
|
|
||||||
invConfig.InvCountVerifyFunc(c, namespaceName, 2)
|
invConfig.InvCountVerifyFunc(c, namespaceName, 2)
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,15 +6,10 @@ package e2e
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
v1 "k8s.io/api/core/v1"
|
|
||||||
apierrors "k8s.io/apimachinery/pkg/api/errors"
|
|
||||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply"
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
"sigs.k8s.io/cli-utils/pkg/apply/event"
|
||||||
"sigs.k8s.io/cli-utils/pkg/inventory"
|
"sigs.k8s.io/cli-utils/pkg/inventory"
|
||||||
|
|
@ -49,17 +44,12 @@ func mutationTest(c client.Client, invConfig InventoryConfig, inventoryName, nam
|
||||||
withNamespace(manifestToUnstructured(podB), namespaceName),
|
withNamespace(manifestToUnstructured(podB), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, obj := range resources {
|
|
||||||
obj.SetNamespace(namespaceName)
|
|
||||||
}
|
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
ch := applier.Run(context.TODO(), inv, resources, apply.Options{
|
||||||
EmitStatusEvents: false,
|
EmitStatusEvents: false,
|
||||||
})
|
})
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
expEvents := []testutil.ExpEvent{
|
expEvents := []testutil.ExpEvent{
|
||||||
|
|
@ -197,29 +187,38 @@ func mutationTest(c client.Client, invConfig InventoryConfig, inventoryName, nam
|
||||||
}
|
}
|
||||||
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
By("verify resource was mutated")
|
By("verify podB is created and ready")
|
||||||
var podBObj v1.Pod
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(podB), namespaceName))
|
||||||
err := c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Namespace: namespaceName,
|
|
||||||
Name: manifestToUnstructured(podB).GetName(),
|
|
||||||
}, &podBObj)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
Expect(podBObj.Status.PodIP).NotTo(BeEmpty())
|
|
||||||
Expect(podBObj.Spec.Containers[0].Ports[0].ContainerPort).To(Equal(int32(80)))
|
|
||||||
host := fmt.Sprintf("%s:%d", podBObj.Status.PodIP, podBObj.Spec.Containers[0].Ports[0].ContainerPort)
|
|
||||||
|
|
||||||
var podAObj v1.Pod
|
podIP, found, err := testutil.NestedField(result.Object, "status", "podIP")
|
||||||
err = c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Namespace: namespaceName,
|
|
||||||
Name: manifestToUnstructured(podA).GetName(),
|
|
||||||
}, &podAObj)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(podAObj.Spec.Containers[0].Env[0].Value).To(Equal(host))
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
|
||||||
|
|
||||||
|
containerPort, found, err := testutil.NestedField(result.Object, "spec", "containers", 0, "ports", 0, "containerPort")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(containerPort).To(Equal(int64(80)))
|
||||||
|
|
||||||
|
host := fmt.Sprintf("%s:%d", podIP, containerPort)
|
||||||
|
|
||||||
|
By("verify podA is mutated, created, and ready")
|
||||||
|
result = assertUnstructuredExists(c, withNamespace(manifestToUnstructured(podA), namespaceName))
|
||||||
|
|
||||||
|
podIP, found, err = testutil.NestedField(result.Object, "status", "podIP")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(podIP).NotTo(BeEmpty()) // use podIP as proxy for readiness
|
||||||
|
|
||||||
|
envValue, found, err := testutil.NestedField(result.Object, "spec", "containers", 0, "env", 0, "value")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(envValue).To(Equal(host))
|
||||||
|
|
||||||
By("destroy resources in opposite order")
|
By("destroy resources in opposite order")
|
||||||
destroyer := invConfig.DestroyerFactoryFunc()
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
||||||
destroyerEvents := runCollectNoErr(destroyer.Run(inv, options))
|
destroyerEvents := runCollect(destroyer.Run(inv, options))
|
||||||
|
|
||||||
expEvents = []testutil.ExpEvent{
|
expEvents = []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
|
|
@ -339,70 +338,9 @@ func mutationTest(c client.Client, invConfig InventoryConfig, inventoryName, nam
|
||||||
|
|
||||||
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
By("verify resources deleted")
|
By("verify podB deleted")
|
||||||
err = c.Get(context.TODO(), types.NamespacedName{
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(podB), namespaceName))
|
||||||
Namespace: namespaceName,
|
|
||||||
Name: manifestToUnstructured(podB).GetName(),
|
|
||||||
}, &podBObj)
|
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(apierrors.ReasonForError(err)).To(Equal(metav1.StatusReasonNotFound))
|
|
||||||
|
|
||||||
err = c.Get(context.TODO(), types.NamespacedName{
|
By("verify podA deleted")
|
||||||
Namespace: namespaceName,
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(podA), namespaceName))
|
||||||
Name: manifestToUnstructured(podA).GetName(),
|
|
||||||
}, &podAObj)
|
|
||||||
Expect(err).To(HaveOccurred())
|
|
||||||
Expect(apierrors.ReasonForError(err)).To(Equal(metav1.StatusReasonNotFound))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func withNamespace(obj *unstructured.Unstructured, namespace string) *unstructured.Unstructured {
|
|
||||||
obj.SetNamespace(namespace)
|
|
||||||
return obj
|
|
||||||
}
|
|
||||||
|
|
||||||
var podA = []byte(strings.TrimSpace(`
|
|
||||||
kind: Pod
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: pod-a
|
|
||||||
namespace: test
|
|
||||||
annotations:
|
|
||||||
config.kubernetes.io/apply-time-mutation: |
|
|
||||||
- sourceRef:
|
|
||||||
kind: Pod
|
|
||||||
name: pod-b
|
|
||||||
sourcePath: $.status.podIP
|
|
||||||
targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
|
|
||||||
token: ${pob-b-ip}
|
|
||||||
- sourceRef:
|
|
||||||
kind: Pod
|
|
||||||
name: pod-b
|
|
||||||
sourcePath: $.spec.containers[?(@.name=="nginx")].ports[?(@.name=="tcp")].containerPort
|
|
||||||
targetPath: $.spec.containers[?(@.name=="nginx")].env[?(@.name=="SERVICE_HOST")].value
|
|
||||||
token: ${pob-b-port}
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:1.21
|
|
||||||
ports:
|
|
||||||
- name: tcp
|
|
||||||
containerPort: 80
|
|
||||||
env:
|
|
||||||
- name: SERVICE_HOST
|
|
||||||
value: "${pob-b-ip}:${pob-b-port}"
|
|
||||||
`))
|
|
||||||
|
|
||||||
var podB = []byte(strings.TrimSpace(`
|
|
||||||
kind: Pod
|
|
||||||
apiVersion: v1
|
|
||||||
metadata:
|
|
||||||
name: pod-b
|
|
||||||
namespace: test
|
|
||||||
spec:
|
|
||||||
containers:
|
|
||||||
- name: nginx
|
|
||||||
image: nginx:1.21
|
|
||||||
ports:
|
|
||||||
- name: tcp
|
|
||||||
containerPort: 80
|
|
||||||
`))
|
|
||||||
|
|
|
||||||
|
|
@ -23,7 +23,7 @@ func applyWithExistingInvTest(c client.Client, invConfig InventoryConfig, invent
|
||||||
orgApplyInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(inventoryName, namespaceName, orgInventoryID))
|
orgApplyInv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(inventoryName, namespaceName, orgInventoryID))
|
||||||
|
|
||||||
resources := []*unstructured.Unstructured{
|
resources := []*unstructured.Unstructured{
|
||||||
deploymentManifest(namespaceName),
|
withNamespace(manifestToUnstructured(deployment1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithNoErr(applier.Run(context.TODO(), orgApplyInv, resources, apply.Options{
|
runWithNoErr(applier.Run(context.TODO(), orgApplyInv, resources, apply.Options{
|
||||||
|
|
|
||||||
|
|
@ -27,7 +27,7 @@ func pruneRetrieveErrorTest(c client.Client, invConfig InventoryConfig, inventor
|
||||||
inv := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
inv := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
||||||
|
|
||||||
resource1 := []*unstructured.Unstructured{
|
resource1 := []*unstructured.Unstructured{
|
||||||
manifestToUnstructured(pod1),
|
withNamespace(manifestToUnstructured(pod1), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch := applier.Run(context.TODO(), inv, resource1, apply.Options{
|
ch := applier.Run(context.TODO(), inv, resource1, apply.Options{
|
||||||
|
|
@ -36,29 +36,105 @@ func pruneRetrieveErrorTest(c client.Client, invConfig InventoryConfig, inventor
|
||||||
|
|
||||||
var applierEvents []event.Event
|
var applierEvents []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents = append(applierEvents, e)
|
applierEvents = append(applierEvents, e)
|
||||||
}
|
}
|
||||||
err := testutil.VerifyEvents([]testutil.ExpEvent{
|
expEvents := []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
// Pod1 is applied
|
// InitTask
|
||||||
|
EventType: event.InitType,
|
||||||
|
InitEvent: &testutil.ExpInitEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-add-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-add-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
Name: "apply-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Create deployment
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod1)),
|
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod1), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ApplyTask finished
|
// ApplyTask finished
|
||||||
EventType: event.ActionGroupType,
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
Name: "apply-0",
|
||||||
|
Type: event.Finished,
|
||||||
},
|
},
|
||||||
}, applierEvents)
|
},
|
||||||
Expect(err).ToNot(HaveOccurred())
|
// TODO: Why no waiting???
|
||||||
|
// {
|
||||||
|
// // WaitTask start
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Started,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// // WaitTask finished
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Finished,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
// InvSetTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-set-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvSetTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-set-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Expect(testutil.EventsToExpEvents(applierEvents)).To(testutil.Equal(expEvents))
|
||||||
|
|
||||||
|
By("Verify pod1 created")
|
||||||
|
assertUnstructuredExists(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
|
||||||
// Delete the previously applied resource, which is referenced in the inventory.
|
// Delete the previously applied resource, which is referenced in the inventory.
|
||||||
By("delete resource, which is referenced in the inventory")
|
By("delete resource, which is referenced in the inventory")
|
||||||
deleteObj(c, resource1[0])
|
deleteUnstructuredAndWait(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
|
||||||
By("Verify inventory")
|
By("Verify inventory")
|
||||||
// The inventory should still have the previously deleted item.
|
// The inventory should still have the previously deleted item.
|
||||||
|
|
@ -66,7 +142,7 @@ func pruneRetrieveErrorTest(c client.Client, invConfig InventoryConfig, inventor
|
||||||
|
|
||||||
By("apply a different resource, and validate the inventory accurately reflects only this object")
|
By("apply a different resource, and validate the inventory accurately reflects only this object")
|
||||||
resource2 := []*unstructured.Unstructured{
|
resource2 := []*unstructured.Unstructured{
|
||||||
manifestToUnstructured(pod2),
|
withNamespace(manifestToUnstructured(pod2), namespaceName),
|
||||||
}
|
}
|
||||||
|
|
||||||
ch = applier.Run(context.TODO(), inv, resource2, apply.Options{
|
ch = applier.Run(context.TODO(), inv, resource2, apply.Options{
|
||||||
|
|
@ -75,25 +151,106 @@ func pruneRetrieveErrorTest(c client.Client, invConfig InventoryConfig, inventor
|
||||||
|
|
||||||
var applierEvents2 []event.Event
|
var applierEvents2 []event.Event
|
||||||
for e := range ch {
|
for e := range ch {
|
||||||
Expect(e.Type).NotTo(Equal(event.ErrorType))
|
|
||||||
applierEvents2 = append(applierEvents2, e)
|
applierEvents2 = append(applierEvents2, e)
|
||||||
}
|
}
|
||||||
err = testutil.VerifyEvents([]testutil.ExpEvent{
|
expEvents2 := []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
// Pod2 is applied
|
// InitTask
|
||||||
|
EventType: event.InitType,
|
||||||
|
InitEvent: &testutil.ExpInitEvent{},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-add-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvAddTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-add-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// ApplyTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
Name: "apply-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Create pod2
|
||||||
EventType: event.ApplyType,
|
EventType: event.ApplyType,
|
||||||
ApplyEvent: &testutil.ExpApplyEvent{
|
ApplyEvent: &testutil.ExpApplyEvent{
|
||||||
Identifier: object.UnstructuredToObjMetaOrDie(manifestToUnstructured(pod2)),
|
|
||||||
Operation: event.Created,
|
Operation: event.Created,
|
||||||
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod2), namespaceName)),
|
||||||
Error: nil,
|
Error: nil,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
// ApplyTask finished
|
// ApplyTask finished
|
||||||
EventType: event.ActionGroupType,
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.ApplyAction,
|
||||||
|
Name: "apply-0",
|
||||||
|
Type: event.Finished,
|
||||||
},
|
},
|
||||||
}, applierEvents2)
|
},
|
||||||
Expect(err).ToNot(HaveOccurred())
|
// Don't prune pod1, it should already be deleted.
|
||||||
|
// TODO: Why is waiting skipped on create?
|
||||||
|
// {
|
||||||
|
// // WaitTask start
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Started,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// // WaitTask finished
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Finished,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
// InvSetTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-set-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// InvSetTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "inventory-set-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Expect(testutil.EventsToExpEvents(applierEvents2)).To(testutil.Equal(expEvents2))
|
||||||
|
|
||||||
|
By("Wait for pod2 to be created")
|
||||||
|
// TODO: change behavior so the user doesn't need to code their own wait
|
||||||
|
waitForCreation(c, withNamespace(manifestToUnstructured(pod2), namespaceName))
|
||||||
|
|
||||||
|
By("Verify pod1 still deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
|
||||||
By("Verify inventory")
|
By("Verify inventory")
|
||||||
// The inventory should only have the currently applied item.
|
// The inventory should only have the currently applied item.
|
||||||
|
|
@ -102,13 +259,87 @@ func pruneRetrieveErrorTest(c client.Client, invConfig InventoryConfig, inventor
|
||||||
By("Destroy resources")
|
By("Destroy resources")
|
||||||
destroyer := invConfig.DestroyerFactoryFunc()
|
destroyer := invConfig.DestroyerFactoryFunc()
|
||||||
|
|
||||||
destroyInv := createInventoryInfo(invConfig, inventoryName, namespaceName, inventoryID)
|
|
||||||
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
options := apply.DestroyerOptions{InventoryPolicy: inventory.AdoptIfNoInventory}
|
||||||
destroyerEvents := runCollectNoErr(destroyer.Run(destroyInv, options))
|
destroyerEvents := runCollect(destroyer.Run(inv, options))
|
||||||
err = testutil.VerifyEvents([]testutil.ExpEvent{
|
|
||||||
|
expEvents3 := []testutil.ExpEvent{
|
||||||
{
|
{
|
||||||
EventType: event.DeleteType,
|
// InitTask
|
||||||
|
EventType: event.InitType,
|
||||||
|
InitEvent: &testutil.ExpInitEvent{},
|
||||||
},
|
},
|
||||||
}, destroyerEvents)
|
{
|
||||||
Expect(err).ToNot(HaveOccurred())
|
// PruneTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
Name: "prune-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// Delete pod2
|
||||||
|
EventType: event.DeleteType,
|
||||||
|
DeleteEvent: &testutil.ExpDeleteEvent{
|
||||||
|
// TODO: this delete is flakey (sometimes skipped), because there's no WaitTask after creation
|
||||||
|
Operation: event.Deleted,
|
||||||
|
Identifier: object.UnstructuredToObjMetaOrDie(withNamespace(manifestToUnstructured(pod2), namespaceName)),
|
||||||
|
Error: nil,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// PruneTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.DeleteAction,
|
||||||
|
Name: "prune-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
// TODO: Why is waiting skipped on destroy?
|
||||||
|
// {
|
||||||
|
// // WaitTask start
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Started,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
// {
|
||||||
|
// // WaitTask finished
|
||||||
|
// EventType: event.ActionGroupType,
|
||||||
|
// ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
// Action: event.WaitAction,
|
||||||
|
// Name: "wait-0",
|
||||||
|
// Type: event.Finished,
|
||||||
|
// },
|
||||||
|
// },
|
||||||
|
{
|
||||||
|
// DeleteInvTask start
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "delete-inventory-0",
|
||||||
|
Type: event.Started,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
// DeleteInvTask finished
|
||||||
|
EventType: event.ActionGroupType,
|
||||||
|
ActionGroupEvent: &testutil.ExpActionGroupEvent{
|
||||||
|
Action: event.InventoryAction,
|
||||||
|
Name: "delete-inventory-0",
|
||||||
|
Type: event.Finished,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
Expect(testutil.EventsToExpEvents(destroyerEvents)).To(testutil.Equal(expEvents3))
|
||||||
|
|
||||||
|
By("Verify pod1 is deleted")
|
||||||
|
assertUnstructuredDoesNotExist(c, withNamespace(manifestToUnstructured(pod1), namespaceName))
|
||||||
|
|
||||||
|
By("Wait for pod2 to be deleted")
|
||||||
|
// TODO: change behavior so the user doesn't need to code their own wait
|
||||||
|
waitForDeletion(c, withNamespace(manifestToUnstructured(pod2), namespaceName))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -9,13 +9,11 @@ import (
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo"
|
. "github.com/onsi/ginkgo"
|
||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
appsv1 "k8s.io/api/apps/v1"
|
|
||||||
v1 "k8s.io/api/core/v1"
|
v1 "k8s.io/api/core/v1"
|
||||||
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
||||||
"k8s.io/apimachinery/pkg/runtime/schema"
|
|
||||||
"k8s.io/apimachinery/pkg/types"
|
|
||||||
"sigs.k8s.io/cli-utils/pkg/apply"
|
"sigs.k8s.io/cli-utils/pkg/apply"
|
||||||
"sigs.k8s.io/cli-utils/pkg/common"
|
"sigs.k8s.io/cli-utils/pkg/common"
|
||||||
|
"sigs.k8s.io/cli-utils/pkg/testutil"
|
||||||
"sigs.k8s.io/controller-runtime/pkg/client"
|
"sigs.k8s.io/controller-runtime/pkg/client"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -25,8 +23,8 @@ func serversideApplyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
|
|
||||||
inv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(inventoryName, namespaceName, "test"))
|
inv := invConfig.InvWrapperFunc(invConfig.InventoryFactoryFunc(inventoryName, namespaceName, "test"))
|
||||||
firstResources := []*unstructured.Unstructured{
|
firstResources := []*unstructured.Unstructured{
|
||||||
deploymentManifest(namespaceName),
|
withNamespace(manifestToUnstructured(deployment1), namespaceName),
|
||||||
apiserviceManifest(),
|
manifestToUnstructured(apiservice1),
|
||||||
}
|
}
|
||||||
|
|
||||||
runWithNoErr(applier.Run(context.TODO(), inv, firstResources, apply.Options{
|
runWithNoErr(applier.Run(context.TODO(), inv, firstResources, apply.Options{
|
||||||
|
|
@ -40,34 +38,28 @@ func serversideApplyTest(c client.Client, invConfig InventoryConfig, inventoryNa
|
||||||
}))
|
}))
|
||||||
|
|
||||||
By("Verify deployment is server-side applied")
|
By("Verify deployment is server-side applied")
|
||||||
var d appsv1.Deployment
|
result := assertUnstructuredExists(c, withNamespace(manifestToUnstructured(deployment1), namespaceName))
|
||||||
err := c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Namespace: namespaceName,
|
|
||||||
Name: deploymentManifest(namespaceName).GetName(),
|
|
||||||
}, &d)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, found := d.ObjectMeta.Annotations[v1.LastAppliedConfigAnnotation]
|
|
||||||
// LastAppliedConfigAnnotation annotation is only set for client-side apply and we've server-side applied here.
|
// LastAppliedConfigAnnotation annotation is only set for client-side apply and we've server-side applied here.
|
||||||
|
_, found, err := testutil.NestedField(result.Object, "metadata", "annotations", v1.LastAppliedConfigAnnotation)
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(found).To(BeFalse())
|
Expect(found).To(BeFalse())
|
||||||
fields := d.GetManagedFields()
|
|
||||||
Expect(fields[0].Manager).To(Equal("test"))
|
manager, found, err := testutil.NestedField(result.Object, "metadata", "managedFields", 0, "manager")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(manager).To(Equal("test"))
|
||||||
|
|
||||||
By("Verify APIService is server-side applied")
|
By("Verify APIService is server-side applied")
|
||||||
var apiService = &unstructured.Unstructured{}
|
result = assertUnstructuredExists(c, manifestToUnstructured(apiservice1))
|
||||||
apiService.SetGroupVersionKind(
|
|
||||||
schema.GroupVersionKind{
|
|
||||||
Group: "apiregistration.k8s.io",
|
|
||||||
Version: "v1",
|
|
||||||
Kind: "APIService",
|
|
||||||
},
|
|
||||||
)
|
|
||||||
err = c.Get(context.TODO(), types.NamespacedName{
|
|
||||||
Name: "v1beta1.custom.metrics.k8s.io",
|
|
||||||
}, apiService)
|
|
||||||
Expect(err).NotTo(HaveOccurred())
|
|
||||||
_, found2 := apiService.GetAnnotations()[v1.LastAppliedConfigAnnotation]
|
|
||||||
// LastAppliedConfigAnnotation annotation is only set for client-side apply and we've server-side applied here.
|
// LastAppliedConfigAnnotation annotation is only set for client-side apply and we've server-side applied here.
|
||||||
Expect(found2).To(BeFalse())
|
_, found, err = testutil.NestedField(result.Object, "metadata", "annotations", v1.LastAppliedConfigAnnotation)
|
||||||
fields2 := apiService.GetManagedFields()
|
Expect(err).NotTo(HaveOccurred())
|
||||||
Expect(fields2[0].Manager).To(Equal("test"))
|
Expect(found).To(BeFalse())
|
||||||
|
|
||||||
|
manager, found, err = testutil.NestedField(result.Object, "metadata", "managedFields", 0, "manager")
|
||||||
|
Expect(err).NotTo(HaveOccurred())
|
||||||
|
Expect(found).To(BeTrue())
|
||||||
|
Expect(manager).To(Equal("test"))
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue