function-sdk-go/resource/composed/composed.go

216 lines
6.7 KiB
Go

/*
Copyright 2023 The Crossplane 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 composed contains an unstructured composed resource.
package composed
import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
"github.com/crossplane/crossplane-runtime/pkg/fieldpath"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplane/function-sdk-go/errors"
)
// New returns a new unstructured composed resource.
func New() *Unstructured {
return &Unstructured{unstructured.Unstructured{Object: make(map[string]any)}}
}
// From creates a new unstructured composed resource from the supplied object.
func From(o runtime.Object) (*Unstructured, error) {
obj, err := runtime.DefaultUnstructuredConverter.ToUnstructured(o)
if err != nil {
return nil, err
}
return &Unstructured{unstructured.Unstructured{Object: obj}}, nil
}
// An Unstructured composed resource.
type Unstructured struct {
unstructured.Unstructured
}
var _ runtime.Object = &Unstructured{}
var _ metav1.Object = &Unstructured{}
var _ runtime.Unstructured = &Unstructured{}
var _ resource.Composed = &Unstructured{}
// DeepCopy this composed resource.
func (cd *Unstructured) DeepCopy() *Unstructured {
if cd == nil {
return nil
}
out := new(Unstructured)
*out = *cd
out.Object = runtime.DeepCopyJSON(cd.Object)
return out
}
// DeepCopyObject of this composed resource.
func (cd *Unstructured) DeepCopyObject() runtime.Object {
return cd.DeepCopy()
}
// DeepCopyInto the supplied composed resource.
func (cd *Unstructured) DeepCopyInto(out *Unstructured) {
clone := cd.DeepCopy()
*out = *clone
}
// MarshalJSON for this composed resource.
func (cd *Unstructured) MarshalJSON() ([]byte, error) {
return cd.Unstructured.MarshalJSON()
}
// GetCondition of this Composed resource.
func (cd *Unstructured) GetCondition(ct xpv1.ConditionType) xpv1.Condition {
conditioned := xpv1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
if err := fieldpath.Pave(cd.Object).GetValueInto("status", &conditioned); err != nil {
return xpv1.Condition{}
}
return conditioned.GetCondition(ct)
}
// SetConditions of this Composed resource.
func (cd *Unstructured) SetConditions(c ...xpv1.Condition) {
conditioned := xpv1.ConditionedStatus{}
// The path is directly `status` because conditions are inline.
_ = fieldpath.Pave(cd.Object).GetValueInto("status", &conditioned)
conditioned.SetConditions(c...)
_ = fieldpath.Pave(cd.Object).SetValue("status.conditions", conditioned.Conditions)
}
// GetWriteConnectionSecretToReference of this Composed resource.
func (cd *Unstructured) GetWriteConnectionSecretToReference() *xpv1.SecretReference {
out := &xpv1.SecretReference{}
if err := fieldpath.Pave(cd.Object).GetValueInto("spec.writeConnectionSecretToRef", out); err != nil {
return nil
}
return out
}
// SetWriteConnectionSecretToReference of this Composed resource.
func (cd *Unstructured) SetWriteConnectionSecretToReference(r *xpv1.SecretReference) {
_ = fieldpath.Pave(cd.Object).SetValue("spec.writeConnectionSecretToRef", r)
}
// GetPublishConnectionDetailsTo of this Composed resource.
func (cd *Unstructured) GetPublishConnectionDetailsTo() *xpv1.PublishConnectionDetailsTo {
out := &xpv1.PublishConnectionDetailsTo{}
if err := fieldpath.Pave(cd.Object).GetValueInto("spec.publishConnectionDetailsTo", out); err != nil {
return nil
}
return out
}
// SetPublishConnectionDetailsTo of this Composed resource.
func (cd *Unstructured) SetPublishConnectionDetailsTo(ref *xpv1.PublishConnectionDetailsTo) {
_ = fieldpath.Pave(cd.Object).SetValue("spec.publishConnectionDetailsTo", ref)
}
// GetValue of the supplied field path.
func (cd *Unstructured) GetValue(path string) (any, error) {
return fieldpath.Pave(cd.Object).GetValue(path)
}
// GetValueInto the supplied type.
func (cd *Unstructured) GetValueInto(path string, out any) error {
return fieldpath.Pave(cd.Object).GetValueInto(path, out)
}
// GetString value of the supplied field path.
func (cd *Unstructured) GetString(path string) (string, error) {
return fieldpath.Pave(cd.Object).GetString(path)
}
// GetStringArray value of the supplied field path.
func (cd *Unstructured) GetStringArray(path string) ([]string, error) {
return fieldpath.Pave(cd.Object).GetStringArray(path)
}
// GetStringObject value of the supplied field path.
func (cd *Unstructured) GetStringObject(path string) (map[string]string, error) {
return fieldpath.Pave(cd.Object).GetStringObject(path)
}
// GetBool value of the supplied field path.
func (cd *Unstructured) GetBool(path string) (bool, error) {
return fieldpath.Pave(cd.Object).GetBool(path)
}
// GetInteger value of the supplied field path.
func (cd *Unstructured) GetInteger(path string) (int64, error) {
// This is a bit of a hack. Kubernetes JSON decoders will get us a
// map[string]any where number values are int64, but protojson and structpb
// will get us one where number values are float64.
// https://pkg.go.dev/sigs.k8s.io/json#UnmarshalCaseSensitivePreserveInts
p := fieldpath.Pave(cd.Object)
// If we find an int64, return it.
i64, err := p.GetInteger(path)
if err == nil {
return i64, nil
}
// If not, try return (and truncate) a float64.
if f64, err := getNumber(p, path); err == nil {
return int64(f64), nil
}
// If both fail, return our original error.
return 0, err
}
func getNumber(p *fieldpath.Paved, path string) (float64, error) {
v, err := p.GetValue(path)
if err != nil {
return 0, err
}
f, ok := v.(float64)
if !ok {
return 0, errors.Errorf("%s: not a (float64) number", path)
}
return f, nil
}
// SetValue at the supplied field path.
func (cd *Unstructured) SetValue(path string, value any) error {
return fieldpath.Pave(cd.Object).SetValue(path, value)
}
// SetString value at the supplied field path.
func (cd *Unstructured) SetString(path, value string) error {
return cd.SetValue(path, value)
}
// SetBool value at the supplied field path.
func (cd *Unstructured) SetBool(path string, value bool) error {
return cd.SetValue(path, value)
}
// SetInteger value at the supplied field path.
func (cd *Unstructured) SetInteger(path string, value int64) error {
return cd.SetValue(path, value)
}