kubernetes-entrypoint/dependencies/customresource/customresource.go

95 lines
2.4 KiB
Go

package customresource
import (
"encoding/json"
"fmt"
"os"
"strings"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"opendev.org/airship/kubernetes-entrypoint/entrypoint"
"opendev.org/airship/kubernetes-entrypoint/logger"
"opendev.org/airship/kubernetes-entrypoint/util/env"
)
// A Resolver represents the state of a CustomResource
type Resolver struct {
APIVersion string `json:"apiVersion"`
Kind string `json:"kind"`
Name string `json:"name"`
Namespace string `json:"namespace"`
Fields []Field `json:"fields"`
}
var _ entrypoint.Resolver = Resolver{}
// A Field represents a key-value pair
type Field struct {
Key string `json:"key"`
Value string `json:"value"`
}
func init() {
crEnv := fmt.Sprintf("%sCUSTOM_RESOURCE", entrypoint.DependencyPrefix)
resolvers, err := fromEnv(crEnv)
if err != nil {
logger.Error.Printf(err.Error())
}
for _, resolver := range resolvers {
entrypoint.Register(resolver)
}
}
// IsResolved will return true when the values for each key in r.Fields is the same as the resource in the cluster
func (r Resolver) IsResolved(ep entrypoint.EntrypointInterface) (bool, error) {
customResource, err := ep.Client().CustomResource(r.APIVersion, r.Kind, r.Namespace, r.Name)
if err != nil {
return false, err
}
for _, field := range r.Fields {
key := field.Key
expected := field.Value
// Extract the specified value from the resource
actual, found, err := unstructured.NestedFieldNoCopy(customResource.Object, strings.Split(key, ".")...)
if err != nil {
return false, err
}
if !found {
return false, fmt.Errorf("Could not find key [%s]", key)
}
if actual != expected {
return false, fmt.Errorf("Expected value of [%s] to be [%s], but got [%s]", key, expected, actual)
}
}
return true, nil
}
// fromEnv reads the value of the jsonEnv variable and returns the array of
// Resolvers it contains, if any
func fromEnv(jsonEnv string) ([]Resolver, error) {
resolvers := []Resolver{}
jsonEnvVal, isSet := os.LookupEnv(jsonEnv)
if !isSet {
return resolvers, nil
}
err := json.Unmarshal([]byte(jsonEnvVal), &resolvers)
if err != nil {
return resolvers, fmt.Errorf("Unable to unmarshal variable %s with value %s: %s",
jsonEnv, jsonEnvVal, err.Error())
}
namespace := env.GetBaseNamespace()
for i := range resolvers {
if resolvers[i].Namespace == "" {
resolvers[i].Namespace = namespace
}
}
return resolvers, nil
}