Skip to content

Commit 4eb3ca3

Browse files
author
Alexander Matyushentsev
authored
feat: Namespace/CRD creation should happen before PreSync phase (argoproj#159)
1 parent 872c470 commit 4eb3ca3

File tree

4 files changed

+100
-12
lines changed

4 files changed

+100
-12
lines changed

pkg/sync/sync_context.go

+19-12
Original file line numberDiff line numberDiff line change
@@ -736,20 +736,27 @@ func (sc *syncContext) targetObjs() []*unstructured.Unstructured {
736736
return objs
737737
}
738738

739+
func isCRDOfGroupKind(group string, kind string, obj *unstructured.Unstructured) bool {
740+
if kube.IsCRD(obj) {
741+
crdGroup, ok, err := unstructured.NestedString(obj.Object, "spec", "group")
742+
if err != nil || !ok {
743+
return false
744+
}
745+
crdKind, ok, err := unstructured.NestedString(obj.Object, "spec", "names", "kind")
746+
if err != nil || !ok {
747+
return false
748+
}
749+
if group == crdGroup && crdKind == kind {
750+
return true
751+
}
752+
}
753+
return false
754+
}
755+
739756
func (sc *syncContext) hasCRDOfGroupKind(group string, kind string) bool {
740757
for _, obj := range sc.targetObjs() {
741-
if kube.IsCRD(obj) {
742-
crdGroup, ok, err := unstructured.NestedString(obj.Object, "spec", "group")
743-
if err != nil || !ok {
744-
continue
745-
}
746-
crdKind, ok, err := unstructured.NestedString(obj.Object, "spec", "names", "kind")
747-
if err != nil || !ok {
748-
continue
749-
}
750-
if group == crdGroup && crdKind == kind {
751-
return true
752-
}
758+
if isCRDOfGroupKind(group, kind, obj) {
759+
return true
753760
}
754761
}
755762
return false

pkg/sync/sync_task.go

+16
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,22 @@ type syncTask struct {
2525
message string
2626
}
2727

28+
// isDependsOn returns true if given task depends on current task and should be executed after
29+
func (t *syncTask) isDependsOn(other *syncTask) bool {
30+
otherObj := other.obj()
31+
thisGVK := t.obj().GroupVersionKind()
32+
otherGVK := otherObj.GroupVersionKind()
33+
34+
if isCRDOfGroupKind(thisGVK.Group, thisGVK.Kind, otherObj) {
35+
return true
36+
}
37+
38+
if otherGVK.Group == "" && otherGVK.Kind == kube.NamespaceKind && otherObj.GetName() == t.obj().GetNamespace() {
39+
return true
40+
}
41+
return false
42+
}
43+
2844
func ternary(val bool, a, b string) string {
2945
if val {
3046
return a

pkg/sync/sync_tasks.go

+6
Original file line numberDiff line numberDiff line change
@@ -74,6 +74,12 @@ func (s syncTasks) Less(i, j int) bool {
7474
tA := s[i]
7575
tB := s[j]
7676

77+
if tA.isDependsOn(tB) {
78+
return false
79+
} else if tB.isDependsOn(tA) {
80+
return true
81+
}
82+
7783
d := syncPhaseOrder[tA.phase] - syncPhaseOrder[tB.phase]
7884
if d != 0 {
7985
return d < 0

pkg/sync/sync_tasks_test.go

+59
Original file line numberDiff line numberDiff line change
@@ -368,6 +368,65 @@ func TestSyncNamespaceAgainstCRD(t *testing.T) {
368368
assert.Equal(t, syncTasks{namespace, crd}, unsorted)
369369
}
370370

371+
func TestSyncTasksSort_NamespaceAndObjectInNamespace(t *testing.T) {
372+
deployment := &syncTask{
373+
phase: common.SyncPhasePreSync,
374+
targetObj: &unstructured.Unstructured{
375+
Object: map[string]interface{}{
376+
"kind": "Job",
377+
"metadata": map[string]interface{}{
378+
"namespace": "myNamespace",
379+
"name": "mySyncHookJob",
380+
},
381+
},
382+
}}
383+
namespace := &syncTask{
384+
targetObj: &unstructured.Unstructured{
385+
Object: map[string]interface{}{
386+
"kind": "Namespace",
387+
"metadata": map[string]interface{}{
388+
"name": "myNamespace",
389+
},
390+
},
391+
},
392+
}
393+
394+
unsorted := syncTasks{deployment, namespace}
395+
sort.Sort(unsorted)
396+
397+
assert.Equal(t, syncTasks{namespace, deployment}, unsorted)
398+
}
399+
400+
func TestSyncTasksSort_CRDAndCR(t *testing.T) {
401+
crd := &syncTask{
402+
phase: common.SyncPhasePreSync,
403+
targetObj: &unstructured.Unstructured{
404+
Object: map[string]interface{}{
405+
"apiVersion": "apiextensions.k8s.io/v1",
406+
"kind": "CustomResourceDefinition",
407+
"spec": map[string]interface{}{
408+
"group": "argoproj.io",
409+
"names": map[string]interface{}{
410+
"kind": "Workflow",
411+
},
412+
},
413+
},
414+
}}
415+
cr := &syncTask{
416+
targetObj: &unstructured.Unstructured{
417+
Object: map[string]interface{}{
418+
"kind": "Workflow",
419+
"apiVersion": "argoproj.io/v1",
420+
},
421+
},
422+
}
423+
424+
unsorted := syncTasks{cr, crd}
425+
sort.Sort(unsorted)
426+
427+
assert.Equal(t, syncTasks{crd, cr}, unsorted)
428+
}
429+
371430
func Test_syncTasks_multiStep(t *testing.T) {
372431
t.Run("Single", func(t *testing.T) {
373432
tasks := syncTasks{{liveObj: Annotate(NewPod(), common.AnnotationSyncWave, "-1"), phase: common.SyncPhaseSync}}

0 commit comments

Comments
 (0)