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

mockkubeapiserver: set generation on objects #384

Merged
merged 1 commit into from
Jun 10, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 0 additions & 6 deletions mockkubeapiserver/hooks/crd.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,6 @@ func (s *CRDHook) updateCRDConditions(ev *storage.WatchEvent) error {
return fmt.Errorf("status was of unexpected type %T", statusObj)
}

generation := u.GetGeneration()
if generation == 0 {
generation = 1
u.SetGeneration(generation)
}

var conditions []interface{}
conditions = append(conditions, map[string]interface{}{
"type": "NamesAccepted",
Expand Down
8 changes: 1 addition & 7 deletions mockkubeapiserver/hooks/deployment.go
Original file line number Diff line number Diff line change
Expand Up @@ -53,12 +53,6 @@ func (s *DeploymentHook) deploymentChanged(ev *storage.WatchEvent) error {
return fmt.Errorf("status was of unexpected type %T", statusObj)
}

generation := u.GetGeneration()
if generation == 0 {
generation = 1
u.SetGeneration(generation)
}

replicasVal, _, err := unstructured.NestedFieldNoCopy(u.Object, "spec", "replicas")
if err != nil {
return fmt.Errorf("error getting spec.replicas: %w", err)
Expand Down Expand Up @@ -91,7 +85,7 @@ func (s *DeploymentHook) deploymentChanged(ev *storage.WatchEvent) error {
status["replicas"] = replicas
status["updatedReplicas"] = replicas

observedGeneration := generation
observedGeneration := u.GetGeneration()
status["observedGeneration"] = observedGeneration

return nil
Expand Down
15 changes: 15 additions & 0 deletions mockkubeapiserver/patchresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import (
"fmt"
"io"
"net/http"
"reflect"
"strconv"

metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand Down Expand Up @@ -79,6 +80,11 @@ func (req *patchResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
// TODO: Should we treat this like an apply to an empty object?

patched := body

if resource.SetsGeneration() {
patched.SetGeneration(1)
}

if err := resource.CreateObject(ctx, id, patched); err != nil {
return err
}
Expand Down Expand Up @@ -124,6 +130,15 @@ func (req *patchResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
klog.Infof("skipping write, object not changed")
return req.writeResponse(existingObj)
} else {
if resource.SetsGeneration() {
specIsSame := reflect.DeepEqual(existingObj.Object["spec"], updated.Object["spec"])
if !specIsSame {
generation := updated.GetGeneration()
generation++
updated.SetGeneration(generation)
}
}

if err := resource.UpdateObject(ctx, id, updated); err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions mockkubeapiserver/postresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,10 @@ func (req *postResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
return fmt.Errorf("name must be provided in payload")
}

if resource.SetsGeneration() {
obj.SetGeneration(1)
}

if err := resource.CreateObject(ctx, id, obj); err != nil {
return err
}
Expand Down
9 changes: 9 additions & 0 deletions mockkubeapiserver/putresource.go
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,15 @@ func (req *putResource) Run(ctx context.Context, s *MockKubeAPIServer) error {
return req.writeResponse(original)
}

if resource.SetsGeneration() {
specIsSame := reflect.DeepEqual(original.Object["spec"], updated.Object["spec"])
if !specIsSame {
generation := updated.GetGeneration()
generation++
updated.SetGeneration(generation)
}
}

if err := resource.UpdateObject(ctx, id, updated); err != nil {
return err
}
Expand Down
4 changes: 4 additions & 0 deletions mockkubeapiserver/storage/memorystorage/memorystorage.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,10 @@ func (s *MemoryStorage) AddObject(obj *unstructured.Unstructured) error {
return fmt.Errorf("object group/version/kind %v not known", gvk)
}

if resource.SetsGeneration() {
obj.SetGeneration(1)
}

return resource.CreateObject(ctx, id, obj)
}

Expand Down
16 changes: 16 additions & 0 deletions mockkubeapiserver/storage/memorystorage/resourceinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,3 +33,19 @@ func (r *memoryResourceInfo) ListGVK() schema.GroupVersionKind {
func (r *memoryResourceInfo) ParseableType() *typed.ParseableType {
return r.parseableType
}

func (r *memoryResourceInfo) SetsGeneration() bool {
// Not all resources support metadata.generation; it looks like only those with status do (?)
// For now, exclude some well-known types that do not set metadata.generation.
switch r.gvk.GroupKind() {
case schema.GroupKind{Group: "", Kind: "ConfigMap"}:
return false
case schema.GroupKind{Group: "", Kind: "Secret"}:
return false
case schema.GroupKind{Group: "", Kind: "Namespace"}:
return false

default:
return true
}
}
3 changes: 3 additions & 0 deletions mockkubeapiserver/storage/resourceinfo.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@ type ResourceInfo interface {
ListGVK() schema.GroupVersionKind
ParseableType() *typed.ParseableType

// SetsGeneration is true if we should automatically set metadata.generation for this resource kind.
SetsGeneration() bool

GetObject(ctx context.Context, id types.NamespacedName) (*unstructured.Unstructured, bool, error)

ListObjects(ctx context.Context, filter ListFilter) (*unstructured.UnstructuredList, error)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ Accept: application/json, */*

200 OK
Cache-Control: no-cache, private
Content-Length: 364
Content-Length: 379
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}

---

Expand Down Expand Up @@ -219,16 +219,16 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
Accept: application/json, */*
Content-Type: application/json

{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}


200 OK
Cache-Control: no-cache, private
Content-Length: 276
Content-Length: 291
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}

---

Expand Down Expand Up @@ -301,13 +301,13 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
Accept: application/json, */*
Content-Type: application/json

{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"5","creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"5","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z"},"spec":{"channel":"stable"},"status":{"healthy":true}}


200 OK
Cache-Control: no-cache, private
Content-Length: 276
Content-Length: 291
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"5","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":true}}
Original file line number Diff line number Diff line change
Expand Up @@ -16,11 +16,11 @@ Accept: application/json, */*

200 OK
Cache-Control: no-cache, private
Content-Length: 364
Content-Length: 379
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}
{"apiVersion":"addons.example.org/v1alpha1","items":[{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"name":"simple1","namespace":"ns1","resourceVersion":"2","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"}}],"kind":"SimpleTestList","metadata":{"resourceVersion":"2"}}

---

Expand Down Expand Up @@ -118,16 +118,16 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
Accept: application/json, */*
Content-Type: application/json

{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"}},"spec":{"channel":"stable"},"status":{"healthy":false}}
{"kind":"SimpleTest","apiVersion":"addons.example.org/v1alpha1","metadata":{"name":"simple1","namespace":"ns1","uid":"00000000-0000-0000-0000-000000000002","resourceVersion":"2","generation":1,"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"}},"spec":{"channel":"stable"},"status":{"healthy":false}}


200 OK
Cache-Control: no-cache, private
Content-Length: 561
Content-Length: 576
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":false}}
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"healthy":false}}

---

Expand Down Expand Up @@ -193,15 +193,15 @@ PUT http://kube-apiserver/apis/addons.example.org/v1alpha1/namespaces/ns1/simple
Accept: application/json, */*
Content-Type: application/json

{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"3","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}

200 OK
Cache-Control: no-cache, private
Content-Length: 730
Content-Length: 745
Content-Type: application/json
Date: (removed)

{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"6","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}
{"apiVersion":"addons.example.org/v1alpha1","kind":"SimpleTest","metadata":{"annotations":{"applyset.kubernetes.io/additional-namespaces":"","applyset.kubernetes.io/contains-group-kinds":"ConfigMap,Deployment.apps","applyset.kubernetes.io/tooling":"SimpleTest/"},"creationTimestamp":"2022-01-01T00:00:01Z","generation":1,"labels":{"applyset.kubernetes.io/id":"applyset-xbxAWnAItX3p1Gxrs86F-ZQAGwGoys9xxQGK3IED7bY-v1"},"name":"simple1","namespace":"ns1","resourceVersion":"6","uid":"00000000-0000-0000-0000-000000000002"},"spec":{"channel":"stable"},"status":{"conditions":[{"lastTransitionTime":"2022-01-01T00:00:00Z","message":"all manifests are reconciled.","reason":"Normal","status":"True","type":"Ready"}],"healthy":true,"phase":"Current"}}

---

Expand Down
Loading