v2/pkg/genruntime/convertible_spec.go (28 lines of code) (raw):
/*
* Copyright (c) Microsoft Corporation.
* Licensed under the MIT license.
*/
package genruntime
import (
"github.com/rotisserie/eris"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
)
// ConvertibleSpec is implemented by Spec types to allow conversion among the different versions of a given spec
//
// Why do we need both directions of conversion?
//
// Each version of a resource is in a different package, so the implementations of this interface will necessarily be
// referencing types from other packages. If we tried to use an interface with a single method, we'd inevitably end up
// with circular package references:
//
// +----------------+ +----------------+
// | v1 | | v2 |
// | PersonSpec | --- import v2 ---> | PersonSpec |
// | | | |
// | ConvertTo() | <--- import v1 --- | ConvertTo() |
// +----------------+ +----------------+
//
// Instead, we have to have support for both directions, so that we can always operate from one side of the package
// reference chain:
//
// +----------------+ +----------------+
// | v1 | | v2 |
// | PersonSpec | | PersonSpec |
// | | | |
// | ConvertTo() | --- import v2 ---> | |
// | ConvertFrom() | | |
// +----------------+ +----------------+
type ConvertibleSpec interface {
// ConvertSpecTo will populate the passed Spec by copying over all available information from this one
ConvertSpecTo(destination ConvertibleSpec) error
// ConvertSpecFrom will populate this spec by copying over all available information from the passed one
ConvertSpecFrom(source ConvertibleSpec) error
}
// GetVersionedSpec returns a versioned spec for the provided resource; the original API version used when the
// resource was first created is used to identify the version to return
// TODO: This is currently unused
func GetVersionedSpec(metaObject ARMMetaObject, scheme *runtime.Scheme) (ConvertibleSpec, error) {
return GetVersionedSpecFromGVK(metaObject, scheme, GetOriginalGVK(metaObject))
}
// GetVersionedSpecFromGVK returns a versioned spec for the provided resource; the original API version used when the
// resource was first created is used to identify the version to return
func GetVersionedSpecFromGVK(metaObject ARMMetaObject, scheme *runtime.Scheme, gvk schema.GroupVersionKind) (ConvertibleSpec, error) {
rsrc, err := NewEmptyVersionedResourceFromGVK(scheme, gvk)
if err != nil {
return nil, eris.Wrap(err, "getting versioned spec")
}
if rsrc.GetObjectKind().GroupVersionKind() == metaObject.GetObjectKind().GroupVersionKind() {
// No conversion needed, empty resource is the same GVK that we already have
return metaObject.GetSpec(), nil
}
// Get a blank spec and populate it
spec := rsrc.GetSpec()
err = spec.ConvertSpecFrom(metaObject.GetSpec())
if err != nil {
return nil, eris.Wrap(err, "failed conversion of spec")
}
return spec, nil
}