@@ -25,19 +25,25 @@ import (
2525 . "github.com/onsi/ginkgo/v2"
2626 . "github.com/onsi/gomega"
2727
28- rbacv1 "k8s.io/api/rbac/v1"
29-
3028 appsv1 "k8s.io/api/apps/v1"
3129 corev1 "k8s.io/api/core/v1"
30+ rbacv1 "k8s.io/api/rbac/v1"
3231 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
32+ "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
3333 "k8s.io/apimachinery/pkg/runtime"
3434 "k8s.io/apimachinery/pkg/runtime/schema"
3535 "k8s.io/apimachinery/pkg/types"
36+ appsv1applyconfigurations "k8s.io/client-go/applyconfigurations/apps/v1"
37+ corev1applyconfigurations "k8s.io/client-go/applyconfigurations/core/v1"
38+ metav1applyconfigurations "k8s.io/client-go/applyconfigurations/meta/v1"
39+ rbacv1applyconfigurations "k8s.io/client-go/applyconfigurations/rbac/v1"
40+
3641 "sigs.k8s.io/controller-runtime/pkg/client"
3742)
3843
3944var _ = Describe ("NamespacedClient" , func () {
4045 var dep * appsv1.Deployment
46+ var acDep * appsv1applyconfigurations.DeploymentApplyConfiguration
4147 var ns = "default"
4248 ctx := context .Background ()
4349 var count uint64 = 0
@@ -75,10 +81,25 @@ var _ = Describe("NamespacedClient", func() {
7581 },
7682 },
7783 }
84+ acDep = appsv1applyconfigurations .Deployment (dep .Name , "" ).
85+ WithLabels (dep .Labels ).
86+ WithSpec (appsv1applyconfigurations .DeploymentSpec ().
87+ WithReplicas (* dep .Spec .Replicas ).
88+ WithSelector (metav1applyconfigurations .LabelSelector ().WithMatchLabels (dep .Spec .Selector .MatchLabels )).
89+ WithTemplate (corev1applyconfigurations .PodTemplateSpec ().
90+ WithLabels (dep .Spec .Template .Labels ).
91+ WithSpec (corev1applyconfigurations .PodSpec ().
92+ WithContainers (corev1applyconfigurations .Container ().
93+ WithName (dep .Spec .Template .Spec .Containers [0 ].Name ).
94+ WithImage (dep .Spec .Template .Spec .Containers [0 ].Image ),
95+ ),
96+ ),
97+ ),
98+ )
99+
78100 })
79101
80102 Describe ("Get" , func () {
81-
82103 BeforeEach (func () {
83104 var err error
84105 dep , err = clientset .AppsV1 ().Deployments (ns ).Create (ctx , dep , metav1.CreateOptions {})
@@ -88,6 +109,7 @@ var _ = Describe("NamespacedClient", func() {
88109 AfterEach (func () {
89110 deleteDeployment (ctx , dep , ns )
90111 })
112+
91113 It ("should successfully Get a namespace-scoped object" , func () {
92114 name := types.NamespacedName {Name : dep .Name }
93115 result := & appsv1.Deployment {}
@@ -135,6 +157,66 @@ var _ = Describe("NamespacedClient", func() {
135157 })
136158 })
137159
160+ Describe ("Apply" , func () {
161+ AfterEach (func () {
162+ deleteDeployment (ctx , dep , ns )
163+ })
164+
165+ It ("should successfully apply an object in the right namespace" , func () {
166+ err := getClient ().Apply (ctx , acDep , client .FieldOwner ("test" ))
167+ Expect (err ).NotTo (HaveOccurred ())
168+
169+ res , err := clientset .AppsV1 ().Deployments (ns ).Get (ctx , dep .Name , metav1.GetOptions {})
170+ Expect (err ).NotTo (HaveOccurred ())
171+ Expect (res .GetNamespace ()).To (BeEquivalentTo (ns ))
172+ })
173+
174+ It ("should successfully apply an object in the right namespace through unstructured" , func () {
175+ serialized , err := json .Marshal (acDep )
176+ Expect (err ).NotTo (HaveOccurred ())
177+ u := & unstructured.Unstructured {}
178+ Expect (json .Unmarshal (serialized , & u .Object )).To (Succeed ())
179+ err = getClient ().Apply (ctx , client .ApplyConfigurationFromUnstructured (u ), client .FieldOwner ("test" ))
180+ Expect (err ).NotTo (HaveOccurred ())
181+
182+ res , err := clientset .AppsV1 ().Deployments (ns ).Get (ctx , dep .Name , metav1.GetOptions {})
183+ Expect (err ).NotTo (HaveOccurred ())
184+ Expect (res .GetNamespace ()).To (BeEquivalentTo (ns ))
185+ })
186+
187+ It ("should not create an object if the namespace of the object is different" , func () {
188+ acDep .WithNamespace ("non-default" )
189+ err := getClient ().Apply (ctx , acDep , client .FieldOwner ("test" ))
190+ Expect (err ).To (HaveOccurred ())
191+ Expect (err .Error ()).To (ContainSubstring ("does not match the namespace" ))
192+ })
193+
194+ It ("should not create an object through unstructured if the namespace of the object is different" , func () {
195+ acDep .WithNamespace ("non-default" )
196+ serialized , err := json .Marshal (acDep )
197+ Expect (err ).NotTo (HaveOccurred ())
198+ u := & unstructured.Unstructured {}
199+ Expect (json .Unmarshal (serialized , & u .Object )).To (Succeed ())
200+ err = getClient ().Apply (ctx , client .ApplyConfigurationFromUnstructured (u ), client .FieldOwner ("test" ))
201+ Expect (err ).To (HaveOccurred ())
202+ Expect (err .Error ()).To (ContainSubstring ("does not match the namespace" ))
203+ })
204+
205+ It ("should create a cluster scoped object" , func () {
206+ cr := rbacv1applyconfigurations .ClusterRole (fmt .Sprintf ("clusterRole-%v" , count ))
207+
208+ err := getClient ().Apply (ctx , cr , client .FieldOwner ("test" ))
209+ Expect (err ).NotTo (HaveOccurred ())
210+
211+ By ("checking if the object was created" )
212+ res , err := clientset .RbacV1 ().ClusterRoles ().Get (ctx , * cr .Name , metav1.GetOptions {})
213+ Expect (err ).NotTo (HaveOccurred ())
214+ Expect (res ).NotTo (BeNil ())
215+
216+ deleteClusterRole (ctx , & rbacv1.ClusterRole {ObjectMeta : metav1.ObjectMeta {Name : * cr .Name }})
217+ })
218+ })
219+
138220 Describe ("Create" , func () {
139221 AfterEach (func () {
140222 deleteDeployment (ctx , dep , ns )
0 commit comments