Skip to content

Commit 0b6831c

Browse files
committed
add function to check if the inventory-id match
1 parent bff0ab8 commit 0b6831c

File tree

2 files changed

+311
-0
lines changed

2 files changed

+311
-0
lines changed

pkg/inventory/policy.go

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,10 @@
33

44
package inventory
55

6+
import (
7+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
8+
)
9+
610
// InventoryPolicy defines if an inventory object can take over
711
// objects that belong to another inventory object or don't
812
// belong to any inventory object.
@@ -56,3 +60,59 @@ const (
5660
// in the package.
5761
AdoptAll
5862
)
63+
64+
const owningInventoryKey = "config.kubernetes.io/owning-inventory"
65+
66+
// inventoryIDMatchStatus represents the result of comparing the
67+
// id from current inventory info and the inventory-id from a live object.
68+
type inventoryIDMatchStatus int
69+
70+
const (
71+
Empty inventoryIDMatchStatus = iota
72+
Match
73+
Unmatch
74+
)
75+
76+
func inventoryIDMatch(inv InventoryInfo, obj *unstructured.Unstructured) inventoryIDMatchStatus {
77+
annotations := obj.GetAnnotations()
78+
value, found := annotations[owningInventoryKey]
79+
if !found {
80+
return Empty
81+
}
82+
if value == inv.ID() {
83+
return Match
84+
}
85+
return Unmatch
86+
}
87+
88+
func CanApply(inv InventoryInfo, obj *unstructured.Unstructured, policy InventoryPolicy) bool {
89+
if obj == nil {
90+
return true
91+
}
92+
matchStatus := inventoryIDMatch(inv, obj)
93+
switch matchStatus {
94+
case Empty:
95+
return policy != InventoryPolicyMustMatch
96+
case Match:
97+
return true
98+
case Unmatch:
99+
return policy == AdoptAll
100+
}
101+
return false
102+
}
103+
104+
func CanPrune(inv InventoryInfo, obj *unstructured.Unstructured, policy InventoryPolicy) bool {
105+
if obj == nil {
106+
return false
107+
}
108+
matchStatus := inventoryIDMatch(inv, obj)
109+
switch matchStatus {
110+
case Empty:
111+
return false
112+
case Match:
113+
return true
114+
case Unmatch:
115+
return false
116+
}
117+
return false
118+
}

pkg/inventory/policy_test.go

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,251 @@
1+
// Copyright 2020 The Kubernetes Authors.
2+
// SPDX-License-Identifier: Apache-2.0
3+
4+
package inventory
5+
6+
import (
7+
"testing"
8+
9+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
10+
)
11+
12+
type fakeInventoryInfo struct {
13+
id string
14+
}
15+
16+
func (i *fakeInventoryInfo) Name() string {
17+
return ""
18+
}
19+
20+
func (i *fakeInventoryInfo) Namespace() string {
21+
return ""
22+
}
23+
24+
func (i *fakeInventoryInfo) ID() string {
25+
return i.id
26+
}
27+
28+
func testObjectWithAnnotation(key, val string) *unstructured.Unstructured {
29+
obj := &unstructured.Unstructured{
30+
Object: map[string]interface{}{
31+
"apiVersion": "v1",
32+
"kind": "Deployment",
33+
"metadata": map[string]interface{}{
34+
"name": "foo",
35+
"namespace": "ns",
36+
},
37+
},
38+
}
39+
if key != "" {
40+
obj.SetAnnotations(map[string]string{
41+
key: val,
42+
})
43+
}
44+
return obj
45+
}
46+
47+
func TestInventoryIDMatch(t *testing.T) {
48+
testcases := []struct {
49+
name string
50+
obj *unstructured.Unstructured
51+
inv InventoryInfo
52+
expected inventoryIDMatchStatus
53+
}{
54+
{
55+
name: "empty",
56+
obj: testObjectWithAnnotation("", ""),
57+
inv: &fakeInventoryInfo{id: "random-id"},
58+
expected: Empty,
59+
},
60+
{
61+
name: "matched",
62+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
63+
inv: &fakeInventoryInfo{id: "matched"},
64+
expected: Match,
65+
},
66+
{
67+
name: "unmatched",
68+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
69+
inv: &fakeInventoryInfo{id: "random-id"},
70+
expected: Unmatch,
71+
},
72+
}
73+
for _, tc := range testcases {
74+
actual := inventoryIDMatch(tc.inv, tc.obj)
75+
if actual != tc.expected {
76+
t.Errorf("expected %v, but got %v", tc.expected, actual)
77+
}
78+
}
79+
}
80+
81+
func TestCanApply(t *testing.T) {
82+
testcases := []struct {
83+
name string
84+
obj *unstructured.Unstructured
85+
inv InventoryInfo
86+
policy InventoryPolicy
87+
canApply bool
88+
}{
89+
{
90+
name: "nil object",
91+
obj: nil,
92+
inv: &fakeInventoryInfo{id: "random-id"},
93+
canApply: true,
94+
},
95+
{
96+
name: "empty with AdoptIfNoInventory",
97+
obj: testObjectWithAnnotation("", ""),
98+
inv: &fakeInventoryInfo{id: "random-id"},
99+
policy: AdoptIfNoInventory,
100+
canApply: true,
101+
},
102+
{
103+
name: "empty with AdoptAll",
104+
obj: testObjectWithAnnotation("", ""),
105+
inv: &fakeInventoryInfo{id: "random-id"},
106+
policy: AdoptAll,
107+
canApply: true,
108+
},
109+
{
110+
name: "empty with InventoryPolicyMustMatch",
111+
obj: testObjectWithAnnotation("", ""),
112+
inv: &fakeInventoryInfo{id: "random-id"},
113+
policy: InventoryPolicyMustMatch,
114+
canApply: false,
115+
},
116+
{
117+
name: "matched with InventoryPolicyMustMatch",
118+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
119+
inv: &fakeInventoryInfo{id: "matched"},
120+
policy: InventoryPolicyMustMatch,
121+
canApply: true,
122+
},
123+
{
124+
name: "matched with AdoptIfNoInventory",
125+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
126+
inv: &fakeInventoryInfo{id: "matched"},
127+
policy: AdoptIfNoInventory,
128+
canApply: true,
129+
},
130+
{
131+
name: "matched with AloptAll",
132+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
133+
inv: &fakeInventoryInfo{id: "matched"},
134+
policy: AdoptAll,
135+
canApply: true,
136+
},
137+
{
138+
name: "unmatched with InventoryPolicyMustMatch",
139+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
140+
inv: &fakeInventoryInfo{id: "random-id"},
141+
policy: InventoryPolicyMustMatch,
142+
canApply: false,
143+
},
144+
{
145+
name: "unmatched with AdoptIfNoInventory",
146+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
147+
inv: &fakeInventoryInfo{id: "random-id"},
148+
policy: AdoptIfNoInventory,
149+
canApply: false,
150+
},
151+
{
152+
name: "unmatched with AdoptAll",
153+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
154+
inv: &fakeInventoryInfo{id: "random-id"},
155+
policy: AdoptAll,
156+
canApply: true,
157+
},
158+
}
159+
for _, tc := range testcases {
160+
actual := CanApply(tc.inv, tc.obj, tc.policy)
161+
if actual != tc.canApply {
162+
t.Errorf("expected %v, but got %v", tc.canApply, actual)
163+
}
164+
}
165+
}
166+
167+
func TestCanPrune(t *testing.T) {
168+
testcases := []struct {
169+
name string
170+
obj *unstructured.Unstructured
171+
inv InventoryInfo
172+
policy InventoryPolicy
173+
canPrune bool
174+
}{
175+
{
176+
name: "nil object",
177+
obj: nil,
178+
inv: &fakeInventoryInfo{id: "random-id"},
179+
canPrune: false,
180+
},
181+
{
182+
name: "empty with AdoptIfNoInventory",
183+
obj: testObjectWithAnnotation("", ""),
184+
inv: &fakeInventoryInfo{id: "random-id"},
185+
policy: AdoptIfNoInventory,
186+
canPrune: false,
187+
},
188+
{
189+
name: "empty with AdoptAll",
190+
obj: testObjectWithAnnotation("", ""),
191+
inv: &fakeInventoryInfo{id: "random-id"},
192+
policy: AdoptAll,
193+
canPrune: false,
194+
},
195+
{
196+
name: "empty with InventoryPolicyMustMatch",
197+
obj: testObjectWithAnnotation("", ""),
198+
inv: &fakeInventoryInfo{id: "random-id"},
199+
policy: InventoryPolicyMustMatch,
200+
canPrune: false,
201+
},
202+
{
203+
name: "matched with InventoryPolicyMustMatch",
204+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
205+
inv: &fakeInventoryInfo{id: "matched"},
206+
policy: InventoryPolicyMustMatch,
207+
canPrune: true,
208+
},
209+
{
210+
name: "matched with AdoptIfNoInventory",
211+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
212+
inv: &fakeInventoryInfo{id: "matched"},
213+
policy: AdoptIfNoInventory,
214+
canPrune: true,
215+
},
216+
{
217+
name: "matched with AloptAll",
218+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "matched"),
219+
inv: &fakeInventoryInfo{id: "matched"},
220+
policy: AdoptAll,
221+
canPrune: true,
222+
},
223+
{
224+
name: "unmatched with InventoryPolicyMustMatch",
225+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
226+
inv: &fakeInventoryInfo{id: "random-id"},
227+
policy: InventoryPolicyMustMatch,
228+
canPrune: false,
229+
},
230+
{
231+
name: "unmatched with AdoptIfNoInventory",
232+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
233+
inv: &fakeInventoryInfo{id: "random-id"},
234+
policy: AdoptIfNoInventory,
235+
canPrune: false,
236+
},
237+
{
238+
name: "unmatched with AdoptAll",
239+
obj: testObjectWithAnnotation("config.kubernetes.io/owning-inventory", "unmatched"),
240+
inv: &fakeInventoryInfo{id: "random-id"},
241+
policy: AdoptAll,
242+
canPrune: false,
243+
},
244+
}
245+
for _, tc := range testcases {
246+
actual := CanPrune(tc.inv, tc.obj, tc.policy)
247+
if actual != tc.canPrune {
248+
t.Errorf("expected %v, but got %v", tc.canPrune, actual)
249+
}
250+
}
251+
}

0 commit comments

Comments
 (0)