From 7b339d00aa63229ca1a0c522b9e6fa0fdb4ed66b Mon Sep 17 00:00:00 2001 From: Jared Watts Date: Tue, 7 May 2019 14:55:23 -0700 Subject: [PATCH] API (CRDs) for Crossplane extensions Signed-off-by: Jared Watts --- Gopkg.lock | 1 + pkg/apis/apis.go | 2 + pkg/apis/core/core.go | 2 +- pkg/apis/core/v1alpha1/register.go | 9 +- pkg/apis/extensions/extensions.go | 37 ++ pkg/apis/extensions/extensions_test.go | 42 ++ pkg/apis/extensions/v1alpha1/doc.go | 23 + pkg/apis/extensions/v1alpha1/register.go | 54 +++ pkg/apis/extensions/v1alpha1/types.go | 190 ++++++++ pkg/apis/extensions/v1alpha1/types_test.go | 136 ++++++ .../v1alpha1/zz_generated.deepcopy.go | 405 ++++++++++++++++++ 11 files changed, 896 insertions(+), 5 deletions(-) create mode 100644 pkg/apis/extensions/extensions.go create mode 100644 pkg/apis/extensions/extensions_test.go create mode 100644 pkg/apis/extensions/v1alpha1/doc.go create mode 100644 pkg/apis/extensions/v1alpha1/register.go create mode 100644 pkg/apis/extensions/v1alpha1/types.go create mode 100644 pkg/apis/extensions/v1alpha1/types_test.go create mode 100644 pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.go diff --git a/Gopkg.lock b/Gopkg.lock index 83456bd..2873014 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1356,6 +1356,7 @@ "gopkg.in/alecthomas/kingpin.v2", "k8s.io/api/apps/v1", "k8s.io/api/core/v1", + "k8s.io/api/rbac/v1", "k8s.io/apimachinery/pkg/api/errors", "k8s.io/apimachinery/pkg/api/meta", "k8s.io/apimachinery/pkg/api/resource", diff --git a/pkg/apis/apis.go b/pkg/apis/apis.go index 51e5fcf..2277dc9 100644 --- a/pkg/apis/apis.go +++ b/pkg/apis/apis.go @@ -28,6 +28,7 @@ import ( "github.com/crossplaneio/crossplane/pkg/apis/cache" "github.com/crossplaneio/crossplane/pkg/apis/compute" "github.com/crossplaneio/crossplane/pkg/apis/core" + "github.com/crossplaneio/crossplane/pkg/apis/extensions" "github.com/crossplaneio/crossplane/pkg/apis/gcp" "github.com/crossplaneio/crossplane/pkg/apis/storage" "github.com/crossplaneio/crossplane/pkg/apis/workload" @@ -41,6 +42,7 @@ func init() { cache.AddToScheme, compute.AddToScheme, core.AddToScheme, + extensions.AddToScheme, gcp.AddToScheme, storage.AddToScheme, workload.AddToScheme, diff --git a/pkg/apis/core/core.go b/pkg/apis/core/core.go index b4eb595..11a716a 100644 --- a/pkg/apis/core/core.go +++ b/pkg/apis/core/core.go @@ -14,7 +14,7 @@ See the License for the specific language governing permissions and limitations under the License. */ -// Package core contains Kubernetes API groups for AWS cloud provider. +// Package core contains Kubernetes API groups for the Crossplane core API. package core import ( diff --git a/pkg/apis/core/v1alpha1/register.go b/pkg/apis/core/v1alpha1/register.go index 95e5285..c621a45 100644 --- a/pkg/apis/core/v1alpha1/register.go +++ b/pkg/apis/core/v1alpha1/register.go @@ -31,10 +31,11 @@ import ( // Kubernetes Group, Version, and Kind metadata. const ( - Group = "core.crossplane.io" - Version = "v1alpha1" - ResourceClassKind = "resourceclass" - APIVersion = Group + "/" + Version + Group = "core.crossplane.io" + Version = "v1alpha1" + APIVersion = Group + "/" + Version + ResourceClassKind = "resourceclass" + ResourceClassKindAPIVersion = ResourceClassKind + "." + APIVersion ) var ( diff --git a/pkg/apis/extensions/extensions.go b/pkg/apis/extensions/extensions.go new file mode 100644 index 0000000..276a315 --- /dev/null +++ b/pkg/apis/extensions/extensions.go @@ -0,0 +1,37 @@ +/* +Copyright 2019 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 extensions contains Kubernetes API groups for Crossplane extensions. +package extensions + +import ( + "k8s.io/apimachinery/pkg/runtime" + + "github.com/crossplaneio/crossplane/pkg/apis/extensions/v1alpha1" +) + +func init() { + // Register the types with the Scheme so the components can map objects to GroupVersionKinds and back + AddToSchemes = append(AddToSchemes, v1alpha1.SchemeBuilder.AddToScheme) +} + +// AddToSchemes may be used to add all resources defined in the project to a Scheme +var AddToSchemes runtime.SchemeBuilder + +// AddToScheme adds all Resources to the Scheme +func AddToScheme(s *runtime.Scheme) error { + return AddToSchemes.AddToScheme(s) +} diff --git a/pkg/apis/extensions/extensions_test.go b/pkg/apis/extensions/extensions_test.go new file mode 100644 index 0000000..e3d01af --- /dev/null +++ b/pkg/apis/extensions/extensions_test.go @@ -0,0 +1,42 @@ +/* +Copyright 2018 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 extensions contains Kubernetes API groups for Crossplane extensions. +package extensions + +import ( + "testing" + + "k8s.io/apimachinery/pkg/runtime" + "k8s.io/apimachinery/pkg/runtime/schema" + + "github.com/crossplaneio/crossplane/pkg/apis/extensions/v1alpha1" +) + +func TestAddToScheme(t *testing.T) { + s := runtime.NewScheme() + if err := AddToScheme(s); err != nil { + t.Errorf("AddToScheme() error = %v", err) + } + gvs := []schema.GroupVersion{ + v1alpha1.SchemeGroupVersion, + } + for _, gv := range gvs { + if !s.IsVersionRegistered(gv) { + t.Errorf("AddToScheme() %v should be registered", gv) + } + } +} diff --git a/pkg/apis/extensions/v1alpha1/doc.go b/pkg/apis/extensions/v1alpha1/doc.go new file mode 100644 index 0000000..935d1dd --- /dev/null +++ b/pkg/apis/extensions/v1alpha1/doc.go @@ -0,0 +1,23 @@ +/* +Copyright 2019 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 v1alpha1 contains API Schema definitions for the crossplane extensions v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/crossplaneio/crossplane/pkg/apis/extensions +// +k8s:defaulter-gen=TypeMeta +// +groupName=extensions.crossplane.io +package v1alpha1 diff --git a/pkg/apis/extensions/v1alpha1/register.go b/pkg/apis/extensions/v1alpha1/register.go new file mode 100644 index 0000000..15af6da --- /dev/null +++ b/pkg/apis/extensions/v1alpha1/register.go @@ -0,0 +1,54 @@ +/* +Copyright 2019 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. +*/ + +// NOTE: Boilerplate only. Ignore this file. + +// Package v1alpha1 contains API Schema definitions for the crossplane extensions v1alpha1 API group +// +k8s:openapi-gen=true +// +k8s:deepcopy-gen=package,register +// +k8s:conversion-gen=github.com/crossplaneio/crossplane/pkg/apis/extensions +// +k8s:defaulter-gen=TypeMeta +// +groupName=extensions.crossplane.io +package v1alpha1 + +import ( + "k8s.io/apimachinery/pkg/runtime/schema" + "sigs.k8s.io/controller-runtime/pkg/runtime/scheme" +) + +// Kubernetes Group, Version, and Kind metadata. +const ( + Group = "extensions.crossplane.io" + Version = "v1alpha1" + APIVersion = Group + "/" + Version + ExtensionRequestKind = "extensionrequest" + ExtensionRequestKindAPIVersion = ExtensionRequestKind + "." + APIVersion + ExtensionKind = "extension" + ExtensionKindAPIVersion = ExtensionKind + "." + APIVersion +) + +var ( + // SchemeGroupVersion is group version used to register these objects + SchemeGroupVersion = schema.GroupVersion{Group: Group, Version: Version} + + // SchemeBuilder is used to add go types to the GroupVersionKind scheme + SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion} +) + +func init() { + SchemeBuilder.Register(&ExtensionRequest{}, &ExtensionRequestList{}) + SchemeBuilder.Register(&Extension{}, &ExtensionList{}) +} diff --git a/pkg/apis/extensions/v1alpha1/types.go b/pkg/apis/extensions/v1alpha1/types.go new file mode 100644 index 0000000..eed948e --- /dev/null +++ b/pkg/apis/extensions/v1alpha1/types.go @@ -0,0 +1,190 @@ +/* +Copyright 2019 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 v1alpha1 + +import ( + apps "k8s.io/api/apps/v1" + corev1 "k8s.io/api/core/v1" + rbac "k8s.io/api/rbac/v1" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + + corev1alpha1 "github.com/crossplaneio/crossplane/pkg/apis/core/v1alpha1" +) + +// TODO: how do we pretty print conditioned status items? There may be multiple of them, and they +// can have varying status (e.g., True, False, Unknown) + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExtensionRequest is the CRD type for a request to add an extension to Crossplane. +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.conditions[0].type" +// +kubebuilder:printcolumn:name="SOURCE",type="string",JSONPath=".spec.source" +// +kubebuilder:printcolumn:name="PACKAGE",type="string",JSONPath=".spec.package" +// +kubebuilder:printcolumn:name="CRD",type="string",JSONPath=".spec.crd" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +type ExtensionRequest struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ExtensionRequestSpec `json:"spec,omitempty"` + Status ExtensionRequestStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExtensionRequestList contains a list of ExtensionRequest +type ExtensionRequestList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []ExtensionRequest `json:"items"` +} + +// ExtensionRequestSpec specifies details about a request to add an extension to Crossplane. +type ExtensionRequestSpec struct { + // Source is the domain name for the extension registry hosting the extension being requested, + // e.g., registry.crossplane.io + Source string `json:"source,omitempty"` + + // Package is the name of the extension package that is being requested, e.g., myapp. + // Either Package or CustomResourceDefinition can be specified. + Package string `json:"package,omitempty"` + + // CustomResourceDefinition is the full name of a CRD that is owned by the extension being + // requested. This can be a convenient way of installing an extension when the desired + // CRD is known, but the package name that contains it is not known. + // Either Package or CustomResourceDefinition can be specified. + CustomResourceDefinition string `json:"crd,omitempty"` +} + +// ExtensionRequestStatus defines the observed state of ExtensionRequest +type ExtensionRequestStatus struct { + corev1alpha1.ConditionedStatus + InstallJob *corev1.ObjectReference `json:"installJob,omitempty"` + ExtensionRecord *corev1.ObjectReference `json:"extensionRecord,omitempty"` +} + +// +genclient +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// Extension is the CRD type for a request to add an extension to Crossplane. +// +k8s:openapi-gen=true +// +kubebuilder:subresource:status +// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.conditions[0].type" +// +kubebuilder:printcolumn:name="DESCRIPTION",type="string",JSONPath=".spec.description" +// +kubebuilder:printcolumn:name="VERSION",type="string",JSONPath=".spec.version" +// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp" +type Extension struct { + metav1.TypeMeta `json:",inline"` + metav1.ObjectMeta `json:"metadata,omitempty"` + + Spec ExtensionSpec `json:"spec,omitempty"` + Status ExtensionStatus `json:"status,omitempty"` +} + +// +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object + +// ExtensionList contains a list of Extension +type ExtensionList struct { + metav1.TypeMeta `json:",inline"` + metav1.ListMeta `json:"metadata,omitempty"` + Items []Extension `json:"items"` +} + +// ExtensionSpec specifies details about an extension that has been added to Crossplane +type ExtensionSpec struct { + AppMetadataSpec `json:",inline"` + CRDs CRDList `json:"customresourcedefinitions,omitempty"` + Controller ControllerSpec `json:"controller,omitempty"` + Permissions PermissionsSpec `json:"permissions,omitempty"` +} + +// ExtensionStatus defines the observed state of Extension +type ExtensionStatus struct { + corev1alpha1.ConditionedStatus +} + +// AppMetadataSpec defines metadata about the extension application +type AppMetadataSpec struct { + Title string `json:"title,omitempty"` + Description string `json:"description,omitempty"` + Version string `json:"version,omitempty"` + Icons []IconSpec `json:"icons,omitempty"` + Maintainers []ContributorSpec `json:"maintainers,omitempty"` + Owners []ContributorSpec `json:"owners,omitempty"` + Company string `json:"company,omitempty"` + Keywords []string `json:"keywords,omitempty"` + Links []LinkSpec `json:"links,omitempty"` + License string `json:"license,omitempty"` +} + +// CRDList is the full list of CRDs that this extension owns and depends on +type CRDList struct { + // Owned is the list of CRDs that this extension defines and owns + Owned []metav1.TypeMeta `json:"owns,omitempty"` + + // DependsOn is the list of CRDs that this extension depends on. This data drives the + // dependency resolution process. + DependsOn []metav1.TypeMeta `json:"dependsOn,omitempty"` +} + +// NewCRDList creates a new CRDList with its members initialized. +func NewCRDList() *CRDList { + return &CRDList{ + Owned: []metav1.TypeMeta{}, + DependsOn: []metav1.TypeMeta{}, + } +} + +// IconSpec defines the icon for an extension +type IconSpec struct { + Base64IconData string `json:"base64Data"` + MediaType string `json:"mediatype"` +} + +// ContributorSpec defines a contributor for an extension (e.g., maintainer, owner, etc.) +type ContributorSpec struct { + Name string `json:"name,omitempty"` + Email string `json:"email,omitempty"` +} + +// LinkSpec defines a useful link about an extension (e.g., homepage, about page, etc.) +type LinkSpec struct { + Description string `json:"description,omitempty"` + URL string `json:"url"` +} + +// ControllerSpec defines the controller that implements the logic for an extension, which can come +// in different flavors. A golang code (controller-runtime) controller with a managing Deployment +// is all that is supported currently, but more types will come in the future (e.g., templates, +// functions/hooks, templates, a new DSL, etc. +type ControllerSpec struct { + Deployment *ControllerDeployment `json:"deployment,omitempty"` +} + +// ControllerDeployment defines a controller for an extension that is managed by a Deployment. +type ControllerDeployment struct { + Name string `json:"name"` + Spec apps.DeploymentSpec `json:"spec"` +} + +// PermissionsSpec defines the permissions that an extension will require to operate. +type PermissionsSpec struct { + Rules []rbac.PolicyRule `json:"rules,omitempty"` +} diff --git a/pkg/apis/extensions/v1alpha1/types_test.go b/pkg/apis/extensions/v1alpha1/types_test.go new file mode 100644 index 0000000..ad1255c --- /dev/null +++ b/pkg/apis/extensions/v1alpha1/types_test.go @@ -0,0 +1,136 @@ +/* +Copyright 2018 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 v1alpha1 + +import ( + "testing" + + . "github.com/onsi/gomega" + "golang.org/x/net/context" + metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "k8s.io/apimachinery/pkg/types" + "sigs.k8s.io/controller-runtime/pkg/client" + + "github.com/crossplaneio/crossplane/pkg/test" +) + +const ( + namespace = "default" + name = "test-instance" +) + +var ( + ctx = context.TODO() + c client.Client + + key = types.NamespacedName{Name: name, Namespace: namespace} +) + +func TestMain(m *testing.M) { + t := test.NewEnv(namespace, SchemeBuilder.SchemeBuilder, test.CRDs()) + c = t.StartClient() + t.StopAndExit(m.Run()) +} + +func TestExtensionRequest(t *testing.T) { + g := NewGomegaWithT(t) + + created := &ExtensionRequest{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: ExtensionRequestSpec{ + Source: "registry.crossplane.io", + Package: "testpackage:v0.1", + }, + } + + // Test Create + fetched := &ExtensionRequest{} + g.Expect(c.Create(ctx, created)).NotTo(HaveOccurred()) + + g.Expect(c.Get(ctx, key, fetched)).NotTo(HaveOccurred()) + g.Expect(fetched).To(Equal(created)) + + // Test Updating the annotations + updated := fetched.DeepCopy() + updated.Annotations = map[string]string{"hello": "world"} + g.Expect(c.Update(ctx, updated)).NotTo(HaveOccurred()) + + g.Expect(c.Get(ctx, key, fetched)).NotTo(HaveOccurred()) + g.Expect(fetched).To(Equal(updated)) + + // Test Delete + g.Expect(c.Delete(ctx, fetched)).NotTo(HaveOccurred()) + g.Expect(c.Get(ctx, key, fetched)).To(HaveOccurred()) +} + +func TestExtension(t *testing.T) { + g := NewGomegaWithT(t) + + created := &Extension{ + ObjectMeta: metav1.ObjectMeta{ + Namespace: namespace, + Name: name, + }, + Spec: ExtensionSpec{ + AppMetadataSpec: AppMetadataSpec{ + Title: "myapp", + Version: "v0.1.0", + Owners: []ContributorSpec{ + {Name: "dev1", Email: "dev1@foo.com"}, + }, + Company: "foo-inc.", + Keywords: []string{"app", "useless", "example"}, + Links: []LinkSpec{ + { + Description: "about page", + URL: "https://app.foo.io", + }, + }, + }, + }, + } + + // Test Create + fetched := &Extension{} + g.Expect(c.Create(ctx, created)).NotTo(HaveOccurred()) + + g.Expect(c.Get(ctx, key, fetched)).NotTo(HaveOccurred()) + g.Expect(fetched).To(Equal(created)) + + // Test Updating the annotations + updated := fetched.DeepCopy() + updated.Annotations = map[string]string{"hello": "world"} + g.Expect(c.Update(ctx, updated)).NotTo(HaveOccurred()) + + g.Expect(c.Get(ctx, key, fetched)).NotTo(HaveOccurred()) + g.Expect(fetched).To(Equal(updated)) + + // Test Delete + g.Expect(c.Delete(ctx, fetched)).NotTo(HaveOccurred()) + g.Expect(c.Get(ctx, key, fetched)).To(HaveOccurred()) +} + +func TestNewCRDList(t *testing.T) { + g := NewGomegaWithT(t) + crdList := NewCRDList() + g.Expect(crdList).NotTo(BeNil()) + g.Expect(crdList.Owned).NotTo(BeNil()) + g.Expect(crdList.DependsOn).NotTo(BeNil()) +} diff --git a/pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.go b/pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.go new file mode 100644 index 0000000..783761a --- /dev/null +++ b/pkg/apis/extensions/v1alpha1/zz_generated.deepcopy.go @@ -0,0 +1,405 @@ +// +build !ignore_autogenerated + +/* +Copyright 2018 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. +*/ +// Code generated by main. DO NOT EDIT. + +package v1alpha1 + +import ( + corev1 "k8s.io/api/core/v1" + rbacv1 "k8s.io/api/rbac/v1" + v1 "k8s.io/apimachinery/pkg/apis/meta/v1" + runtime "k8s.io/apimachinery/pkg/runtime" +) + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *AppMetadataSpec) DeepCopyInto(out *AppMetadataSpec) { + *out = *in + if in.Icons != nil { + in, out := &in.Icons, &out.Icons + *out = make([]IconSpec, len(*in)) + copy(*out, *in) + } + if in.Maintainers != nil { + in, out := &in.Maintainers, &out.Maintainers + *out = make([]ContributorSpec, len(*in)) + copy(*out, *in) + } + if in.Owners != nil { + in, out := &in.Owners, &out.Owners + *out = make([]ContributorSpec, len(*in)) + copy(*out, *in) + } + if in.Keywords != nil { + in, out := &in.Keywords, &out.Keywords + *out = make([]string, len(*in)) + copy(*out, *in) + } + if in.Links != nil { + in, out := &in.Links, &out.Links + *out = make([]LinkSpec, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new AppMetadataSpec. +func (in *AppMetadataSpec) DeepCopy() *AppMetadataSpec { + if in == nil { + return nil + } + out := new(AppMetadataSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *CRDList) DeepCopyInto(out *CRDList) { + *out = *in + if in.Owned != nil { + in, out := &in.Owned, &out.Owned + *out = make([]v1.TypeMeta, len(*in)) + copy(*out, *in) + } + if in.DependsOn != nil { + in, out := &in.DependsOn, &out.DependsOn + *out = make([]v1.TypeMeta, len(*in)) + copy(*out, *in) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new CRDList. +func (in *CRDList) DeepCopy() *CRDList { + if in == nil { + return nil + } + out := new(CRDList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ContributorSpec) DeepCopyInto(out *ContributorSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ContributorSpec. +func (in *ContributorSpec) DeepCopy() *ContributorSpec { + if in == nil { + return nil + } + out := new(ContributorSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControllerDeployment) DeepCopyInto(out *ControllerDeployment) { + *out = *in + in.Spec.DeepCopyInto(&out.Spec) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerDeployment. +func (in *ControllerDeployment) DeepCopy() *ControllerDeployment { + if in == nil { + return nil + } + out := new(ControllerDeployment) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ControllerSpec) DeepCopyInto(out *ControllerSpec) { + *out = *in + if in.Deployment != nil { + in, out := &in.Deployment, &out.Deployment + *out = new(ControllerDeployment) + (*in).DeepCopyInto(*out) + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ControllerSpec. +func (in *ControllerSpec) DeepCopy() *ControllerSpec { + if in == nil { + return nil + } + out := new(ControllerSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *Extension) DeepCopyInto(out *Extension) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + in.Spec.DeepCopyInto(&out.Spec) + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new Extension. +func (in *Extension) DeepCopy() *Extension { + if in == nil { + return nil + } + out := new(Extension) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *Extension) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionList) DeepCopyInto(out *ExtensionList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]Extension, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionList. +func (in *ExtensionList) DeepCopy() *ExtensionList { + if in == nil { + return nil + } + out := new(ExtensionList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExtensionList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionRequest) DeepCopyInto(out *ExtensionRequest) { + *out = *in + out.TypeMeta = in.TypeMeta + in.ObjectMeta.DeepCopyInto(&out.ObjectMeta) + out.Spec = in.Spec + in.Status.DeepCopyInto(&out.Status) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionRequest. +func (in *ExtensionRequest) DeepCopy() *ExtensionRequest { + if in == nil { + return nil + } + out := new(ExtensionRequest) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExtensionRequest) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionRequestList) DeepCopyInto(out *ExtensionRequestList) { + *out = *in + out.TypeMeta = in.TypeMeta + out.ListMeta = in.ListMeta + if in.Items != nil { + in, out := &in.Items, &out.Items + *out = make([]ExtensionRequest, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionRequestList. +func (in *ExtensionRequestList) DeepCopy() *ExtensionRequestList { + if in == nil { + return nil + } + out := new(ExtensionRequestList) + in.DeepCopyInto(out) + return out +} + +// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object. +func (in *ExtensionRequestList) DeepCopyObject() runtime.Object { + if c := in.DeepCopy(); c != nil { + return c + } + return nil +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionRequestSpec) DeepCopyInto(out *ExtensionRequestSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionRequestSpec. +func (in *ExtensionRequestSpec) DeepCopy() *ExtensionRequestSpec { + if in == nil { + return nil + } + out := new(ExtensionRequestSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionRequestStatus) DeepCopyInto(out *ExtensionRequestStatus) { + *out = *in + in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus) + if in.InstallJob != nil { + in, out := &in.InstallJob, &out.InstallJob + *out = new(corev1.ObjectReference) + **out = **in + } + if in.ExtensionRecord != nil { + in, out := &in.ExtensionRecord, &out.ExtensionRecord + *out = new(corev1.ObjectReference) + **out = **in + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionRequestStatus. +func (in *ExtensionRequestStatus) DeepCopy() *ExtensionRequestStatus { + if in == nil { + return nil + } + out := new(ExtensionRequestStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionSpec) DeepCopyInto(out *ExtensionSpec) { + *out = *in + in.AppMetadataSpec.DeepCopyInto(&out.AppMetadataSpec) + in.CRDs.DeepCopyInto(&out.CRDs) + in.Controller.DeepCopyInto(&out.Controller) + in.Permissions.DeepCopyInto(&out.Permissions) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionSpec. +func (in *ExtensionSpec) DeepCopy() *ExtensionSpec { + if in == nil { + return nil + } + out := new(ExtensionSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *ExtensionStatus) DeepCopyInto(out *ExtensionStatus) { + *out = *in + in.ConditionedStatus.DeepCopyInto(&out.ConditionedStatus) + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new ExtensionStatus. +func (in *ExtensionStatus) DeepCopy() *ExtensionStatus { + if in == nil { + return nil + } + out := new(ExtensionStatus) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *IconSpec) DeepCopyInto(out *IconSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new IconSpec. +func (in *IconSpec) DeepCopy() *IconSpec { + if in == nil { + return nil + } + out := new(IconSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *LinkSpec) DeepCopyInto(out *LinkSpec) { + *out = *in + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new LinkSpec. +func (in *LinkSpec) DeepCopy() *LinkSpec { + if in == nil { + return nil + } + out := new(LinkSpec) + in.DeepCopyInto(out) + return out +} + +// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil. +func (in *PermissionsSpec) DeepCopyInto(out *PermissionsSpec) { + *out = *in + if in.Rules != nil { + in, out := &in.Rules, &out.Rules + *out = make([]rbacv1.PolicyRule, len(*in)) + for i := range *in { + (*in)[i].DeepCopyInto(&(*out)[i]) + } + } + return +} + +// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new PermissionsSpec. +func (in *PermissionsSpec) DeepCopy() *PermissionsSpec { + if in == nil { + return nil + } + out := new(PermissionsSpec) + in.DeepCopyInto(out) + return out +}