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

Refactor: Move inventory helpers to internal package #744

Merged
merged 1 commit into from
Oct 11, 2022
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
13 changes: 7 additions & 6 deletions controllers/kustomization_controller.go
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ import (
kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
"github.com/fluxcd/kustomize-controller/internal/decryptor"
"github.com/fluxcd/kustomize-controller/internal/generator"
"github.com/fluxcd/kustomize-controller/internal/inventory"
)

// +kubebuilder:rbac:groups=kustomize.toolkit.fluxcd.io,resources=kustomizations,verbs=get;list;watch;create;update;patch;delete
Expand Down Expand Up @@ -440,8 +441,8 @@ func (r *KustomizationReconciler) reconcile(
}

// create an inventory of objects to be reconciled
newInventory := NewInventory()
err = AddObjectsToInventory(newInventory, changeSet)
newInventory := inventory.New()
err = inventory.AddChangeSet(newInventory, changeSet)
if err != nil {
return kustomizev1.KustomizationNotReady(
kustomization,
Expand All @@ -454,7 +455,7 @@ func (r *KustomizationReconciler) reconcile(
// detect stale objects which are subject to garbage collection
var staleObjects []*unstructured.Unstructured
if oldStatus.Inventory != nil {
diffObjects, err := DiffInventory(oldStatus.Inventory, newInventory)
diffObjects, err := inventory.Diff(oldStatus.Inventory, newInventory)
if err != nil {
return kustomizev1.KustomizationNotReady(
kustomization,
Expand All @@ -467,7 +468,7 @@ func (r *KustomizationReconciler) reconcile(
// TODO: remove this workaround after kustomize-controller 0.18 release
// skip objects that were wrongly marked as namespaced
// https://github.com/fluxcd/kustomize-controller/issues/466
newObjects, _ := ListObjectsInInventory(newInventory)
newObjects, _ := inventory.List(newInventory)
for _, obj := range diffObjects {
preserve := false
if obj.GetNamespace() != "" {
Expand Down Expand Up @@ -846,7 +847,7 @@ func (r *KustomizationReconciler) checkHealth(ctx context.Context, manager *ssa.
checkStart := time.Now()
var err error
if !kustomization.Spec.Wait {
objects, err = referenceToObjMetadataSet(kustomization.Spec.HealthChecks)
objects, err = inventory.ReferenceToObjMetadataSet(kustomization.Spec.HealthChecks)
if err != nil {
return err
}
Expand Down Expand Up @@ -932,7 +933,7 @@ func (r *KustomizationReconciler) finalize(ctx context.Context, kustomization ku
!kustomization.Spec.Suspend &&
kustomization.Status.Inventory != nil &&
kustomization.Status.Inventory.Entries != nil {
objects, _ := ListObjectsInInventory(kustomization.Status.Inventory)
objects, _ := inventory.List(kustomization.Status.Inventory)

impersonation := runtimeClient.NewImpersonator(
r.Client,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,28 +14,29 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package controllers
package inventory

import (
"sort"

"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/ssa"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/cli-utils/pkg/object"

"github.com/fluxcd/pkg/apis/meta"
"github.com/fluxcd/pkg/ssa"

kustomizev1 "github.com/fluxcd/kustomize-controller/api/v1beta2"
)

func NewInventory() *kustomizev1.ResourceInventory {
func New() *kustomizev1.ResourceInventory {
return &kustomizev1.ResourceInventory{
Entries: []kustomizev1.ResourceRef{},
}
}

// AddObjectsToInventory extracts the metadata from the given objects and adds it to the inventory.
func AddObjectsToInventory(inv *kustomizev1.ResourceInventory, set *ssa.ChangeSet) error {
// AddChangeSet extracts the metadata from the given objects and adds it to the inventory.
func AddChangeSet(inv *kustomizev1.ResourceInventory, set *ssa.ChangeSet) error {
if set == nil {
return nil
}
Expand All @@ -50,8 +51,8 @@ func AddObjectsToInventory(inv *kustomizev1.ResourceInventory, set *ssa.ChangeSe
return nil
}

// ListObjectsInInventory returns the inventory entries as unstructured.Unstructured objects.
func ListObjectsInInventory(inv *kustomizev1.ResourceInventory) ([]*unstructured.Unstructured, error) {
// List returns the inventory entries as unstructured.Unstructured objects.
func List(inv *kustomizev1.ResourceInventory) ([]*unstructured.Unstructured, error) {
objects := make([]*unstructured.Unstructured, 0)

if inv.Entries == nil {
Expand Down Expand Up @@ -79,8 +80,8 @@ func ListObjectsInInventory(inv *kustomizev1.ResourceInventory) ([]*unstructured
return objects, nil
}

// ListMetaInInventory returns the inventory entries as object.ObjMetadata objects.
func ListMetaInInventory(inv *kustomizev1.ResourceInventory) (object.ObjMetadataSet, error) {
// ListMetadata returns the inventory entries as object.ObjMetadata objects.
func ListMetadata(inv *kustomizev1.ResourceInventory) (object.ObjMetadataSet, error) {
var metas []object.ObjMetadata
for _, e := range inv.Entries {
m, err := object.ParseObjMetadata(e.ID)
Expand All @@ -93,8 +94,8 @@ func ListMetaInInventory(inv *kustomizev1.ResourceInventory) (object.ObjMetadata
return metas, nil
}

// DiffInventory returns the slice of objects that do not exist in the target inventory.
func DiffInventory(inv *kustomizev1.ResourceInventory, target *kustomizev1.ResourceInventory) ([]*unstructured.Unstructured, error) {
// Diff returns the slice of objects that do not exist in the target inventory.
func Diff(inv *kustomizev1.ResourceInventory, target *kustomizev1.ResourceInventory) ([]*unstructured.Unstructured, error) {
versionOf := func(i *kustomizev1.ResourceInventory, objMetadata object.ObjMetadata) string {
for _, entry := range i.Entries {
if entry.ID == objMetadata.String() {
Expand All @@ -105,12 +106,12 @@ func DiffInventory(inv *kustomizev1.ResourceInventory, target *kustomizev1.Resou
}

objects := make([]*unstructured.Unstructured, 0)
aList, err := ListMetaInInventory(inv)
aList, err := ListMetadata(inv)
if err != nil {
return nil, err
}

bList, err := ListMetaInInventory(target)
bList, err := ListMetadata(target)
if err != nil {
return nil, err
}
Expand All @@ -136,7 +137,8 @@ func DiffInventory(inv *kustomizev1.ResourceInventory, target *kustomizev1.Resou
return objects, nil
}

func referenceToObjMetadataSet(cr []meta.NamespacedObjectKindReference) (object.ObjMetadataSet, error) {
// ReferenceToObjMetadataSet transforms a NamespacedObjectKindReference to an ObjMetadataSet.
func ReferenceToObjMetadataSet(cr []meta.NamespacedObjectKindReference) (object.ObjMetadataSet, error) {
var objects []object.ObjMetadata

for _, c := range cr {
Expand Down
93 changes: 93 additions & 0 deletions internal/inventory/inventory_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
/*
Copyright 2022 The Flux authors

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

package inventory

import (
"os"
"strings"
"testing"

. "github.com/onsi/gomega"
"sigs.k8s.io/cli-utils/pkg/object"

"github.com/fluxcd/pkg/ssa"
)

func Test_Inventory(t *testing.T) {
g := NewWithT(t)

set1, err := readManifest("testdata/inventory1.yaml")
if err != nil {
t.Fatal(err)
}

inv1 := New()
err = AddChangeSet(inv1, set1)
g.Expect(err).ToNot(HaveOccurred())

set2, err := readManifest("testdata/inventory2.yaml")
if err != nil {
t.Fatal(err)
}

inv2 := New()
err = AddChangeSet(inv2, set2)
g.Expect(err).ToNot(HaveOccurred())

t.Run("lists objects in inventory", func(t *testing.T) {
unList, err := List(inv1)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(unList)).To(BeIdenticalTo(len(inv1.Entries)))

mList, err := ListMetadata(inv1)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(mList)).To(BeIdenticalTo(len(inv1.Entries)))
})

t.Run("diff objects in inventory", func(t *testing.T) {
unList, err := Diff(inv2, inv1)
g.Expect(err).ToNot(HaveOccurred())
g.Expect(len(unList)).To(BeIdenticalTo(1))
g.Expect(unList[0].GetName()).To(BeIdenticalTo("test2"))
})
}

func readManifest(manifest string) (*ssa.ChangeSet, error) {
data, err := os.ReadFile(manifest)
if err != nil {
return nil, err
}

objects, err := ssa.ReadObjects(strings.NewReader(string(data)))
if err != nil {
return nil, err
}

cs := ssa.NewChangeSet()

for _, o := range objects {
cse := ssa.ChangeSetEntry{
ObjMetadata: object.UnstructuredToObjMetadata(o),
GroupVersion: o.GroupVersionKind().Version,
Subject: ssa.FmtUnstructured(o),
Action: string(ssa.CreatedAction),
}
cs.Add(cse)
}

return cs, nil
}
12 changes: 12 additions & 0 deletions internal/inventory/testdata/inventory1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
apiVersion: v1
kind: Namespace
metadata:
name: test
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test1
namespace: test
data:
key: value1
20 changes: 20 additions & 0 deletions internal/inventory/testdata/inventory2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: v1
kind: Namespace
metadata:
name: test
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test1
namespace: test
data:
key: value1
---
apiVersion: v1
kind: ConfigMap
metadata:
name: test2
namespace: test
data:
key: value2