mirror of https://github.com/fluxcd/cli-utils.git
110 lines
3.2 KiB
Go
110 lines
3.2 KiB
Go
// Copyright 2020 The Kubernetes Authors.
|
|
// SPDX-License-Identifier: Apache-2.0
|
|
//
|
|
// Introduces the InventoryConfigMap struct which implements
|
|
// the Inventory interface. The InventoryConfigMap wraps a
|
|
// ConfigMap resource which stores the set of inventory
|
|
// (object metadata).
|
|
|
|
package inventory
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
|
|
"k8s.io/cli-runtime/pkg/resource"
|
|
"sigs.k8s.io/cli-utils/pkg/object"
|
|
)
|
|
|
|
// WrapInventoryObj takes a passed ConfigMap (as a resource.Info),
|
|
// wraps it with the InventoryConfigMap and upcasts the wrapper as
|
|
// an the Inventory interface.
|
|
func WrapInventoryObj(info *resource.Info) Inventory {
|
|
return &InventoryConfigMap{inv: info}
|
|
}
|
|
|
|
// InventoryConfigMap wraps a ConfigMap resource and implements
|
|
// the Inventory interface. This wrapper loads and stores the
|
|
// object metadata (inventory) to and from the wrapped ConfigMap.
|
|
type InventoryConfigMap struct {
|
|
inv *resource.Info
|
|
objMetas []object.ObjMetadata
|
|
}
|
|
|
|
// Load is an Inventory interface function returning the set of
|
|
// object metadata from the wrapped ConfigMap, or an error.
|
|
func (icm *InventoryConfigMap) Load() ([]object.ObjMetadata, error) {
|
|
objs := []object.ObjMetadata{}
|
|
inventoryObj, ok := icm.inv.Object.(*unstructured.Unstructured)
|
|
if !ok {
|
|
err := fmt.Errorf("inventory object is not an Unstructured: %#v", inventoryObj)
|
|
return objs, err
|
|
}
|
|
objMap, exists, err := unstructured.NestedStringMap(inventoryObj.Object, "data")
|
|
if err != nil {
|
|
err := fmt.Errorf("error retrieving object metadata from inventory object")
|
|
return objs, err
|
|
}
|
|
if exists {
|
|
for objStr := range objMap {
|
|
obj, err := object.ParseObjMetadata(objStr)
|
|
if err != nil {
|
|
return objs, err
|
|
}
|
|
objs = append(objs, obj)
|
|
}
|
|
}
|
|
return objs, nil
|
|
}
|
|
|
|
// Store is an Inventory interface function implemented to store
|
|
// the object metadata in the wrapped ConfigMap. Actual storing
|
|
// happens in "GetObject".
|
|
func (icm *InventoryConfigMap) Store(objMetas []object.ObjMetadata) error {
|
|
icm.objMetas = objMetas
|
|
return nil
|
|
}
|
|
|
|
// GetObject returns the wrapped object (ConfigMap) as a resource.Info
|
|
// or an error if one occurs.
|
|
func (icm *InventoryConfigMap) GetObject() (*resource.Info, error) {
|
|
// Verify the ConfigMap is in Unstructured format.
|
|
obj := icm.inv.Object
|
|
if obj == nil {
|
|
return nil, fmt.Errorf("inventory info has nil Object")
|
|
}
|
|
iot, ok := obj.(*unstructured.Unstructured)
|
|
if !ok {
|
|
return nil, fmt.Errorf(
|
|
"inventory ConfigMap is not in Unstructured format: %s",
|
|
icm.inv.Source)
|
|
}
|
|
|
|
// Create the objMap of all the resources, and compute the hash.
|
|
objMap := buildObjMap(icm.objMetas)
|
|
// Create the inventory object by copying the template.
|
|
invCopy := iot.DeepCopy()
|
|
// Adds the inventory map to the ConfigMap "data" section.
|
|
err := unstructured.SetNestedStringMap(invCopy.UnstructuredContent(),
|
|
objMap, "data")
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &resource.Info{
|
|
Client: icm.inv.Client,
|
|
Mapping: icm.inv.Mapping,
|
|
Source: "generated",
|
|
Name: invCopy.GetName(),
|
|
Namespace: invCopy.GetNamespace(),
|
|
Object: invCopy,
|
|
}, nil
|
|
}
|
|
|
|
func buildObjMap(objMetas []object.ObjMetadata) map[string]string {
|
|
objMap := map[string]string{}
|
|
for _, objMetadata := range objMetas {
|
|
objMap[objMetadata.String()] = ""
|
|
}
|
|
return objMap
|
|
}
|