Add simple controller

Signed-off-by: hasheddan <georgedanielmangum@gmail.com>
This commit is contained in:
hasheddan 2020-03-31 10:50:04 -05:00
parent 195ac8f8fe
commit 0f4061e718
No known key found for this signature in database
GPG Key ID: BD68BC686A14C271
25 changed files with 1238 additions and 17 deletions

View File

@ -17,6 +17,11 @@ build: generate build-stack-package test
image: generate build-stack-package test
docker build . -t $(ORG_NAME)/$(PROVIDER_NAME):latest -f cluster/Dockerfile
image-push:
docker push $(ORG_NAME)/$(PROVIDER_NAME):latest
all: image image-push
generate:
go generate ./...
@ -35,7 +40,7 @@ $(STACK_PACKAGE_REGISTRY):
@touch $(STACK_PACKAGE_REGISTRY)/app.yaml $(STACK_PACKAGE_REGISTRY)/install.yaml
CRD_DIR=config/crd
build-stack-package: $(STACK_PACKAGE_REGISTRY)
build-stack-package: clean $(STACK_PACKAGE_REGISTRY)
# Copy CRDs over
@find $(CRD_DIR) -type f -name '*.yaml' | \
while read filename ; do mkdir -p $(STACK_PACKAGE_REGISTRY)/resources/$$(basename $${filename%_*});\
@ -50,4 +55,4 @@ clean: clean-stack-package
clean-stack-package:
@rm -rf $(STACK_PACKAGE)
.PHONY: generate tidy build-stack-package clean clean-stack-package
.PHONY: generate tidy build-stack-package clean clean-stack-package build image all

18
apis/sample/sample.go Normal file
View File

@ -0,0 +1,18 @@
/*
Copyright 2020 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 sample contains group Sample API versions
package sample

View File

@ -0,0 +1,21 @@
/*
Copyright 2020 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 the v1alpha1 group Sample resources of the Template provider.
// +kubebuilder:object:generate=true
// +groupName=sample.template.crossplanebook.io
// +versionName=v1alpha1
package v1alpha1

View File

@ -0,0 +1,50 @@
/*
Copyright 2020 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 (
"reflect"
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)
// Package type metadata.
const (
Group = "sample.template.crossplanebook.io"
Version = "v1alpha1"
)
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}
)
// MyType type metadata.
var (
MyTypeKind = reflect.TypeOf(MyType{}).Name()
MyTypeGroupKind = schema.GroupKind{Group: Group, Kind: MyTypeKind}.String()
MyTypeKindAPIVersion = MyTypeKind + "." + SchemeGroupVersion.String()
MyTypeGroupVersionKind = SchemeGroupVersion.WithKind(MyTypeKind)
)
func init() {
SchemeBuilder.Register(&MyType{}, &MyTypeList{})
}

View File

@ -0,0 +1,104 @@
/*
Copyright 2020 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 (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
)
// MyTypeParameters are the configurable fields of a MyType.
type MyTypeParameters struct {
ConfigurableField string `json:"configurableField"`
}
// MyTypeObservation are the observable fields of a MyType.
type MyTypeObservation struct {
ObservableField string `json:"observableField,omitempty"`
}
// A MyTypeSpec defines the desired state of a MyType.
type MyTypeSpec struct {
runtimev1alpha1.ResourceSpec `json:",inline"`
ForProvider MyTypeParameters `json:"forProvider"`
}
// A MyTypeStatus represents the observed state of a MyType.
type MyTypeStatus struct {
runtimev1alpha1.ResourceStatus `json:",inline"`
AtProvider MyTypeObservation `json:"atProvider,omitempty"`
}
// +kubebuilder:object:root=true
// A MyType is an example API type
// +kubebuilder:subresource:status
// +kubebuilder:printcolumn:name="STATUS",type="string",JSONPath=".status.bindingPhase"
// +kubebuilder:printcolumn:name="STATE",type="string",JSONPath=".status.atProvider.state"
// +kubebuilder:printcolumn:name="CLASS",type="string",JSONPath=".spec.classRef.name"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:resource:scope=Cluster
type MyType struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec MyTypeSpec `json:"spec"`
Status MyTypeStatus `json:"status,omitempty"`
}
// +kubebuilder:object:root=true
// MyTypeList contains a list of MyType
type MyTypeList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MyType `json:"items"`
}
// A MyTypeClassSpecTemplate is a template for the spec of a
// dynamically provisioned MyType.
type MyTypeClassSpecTemplate struct {
runtimev1alpha1.ClassSpecTemplate `json:",inline"`
ForProvider MyTypeParameters `json:"forProvider"`
}
// +kubebuilder:object:root=true
// A MyTypeClass is a resource class. It defines the desired spec of
// resource claims that use it to dynamically provision a managed resource.
// +kubebuilder:printcolumn:name="PROVIDER-REF",type="string",JSONPath=".specTemplate.providerRef.name"
// +kubebuilder:printcolumn:name="RECLAIM-POLICY",type="string",JSONPath=".specTemplate.reclaimPolicy"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:resource:scope=Cluster
type MyTypeClass struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
// SpecTemplate is a template for the spec of a dynamically provisioned
// MyType.
SpecTemplate MyTypeClassSpecTemplate `json:"specTemplate"`
}
// +kubebuilder:object:root=true
// MyTypeClassList contains a list of MyType resource classes.
type MyTypeClassList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []MyTypeClass `json:"items"`
}

View File

@ -0,0 +1,30 @@
/*
Copyright 2020 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 angryjet. DO NOT EDIT.
package v1alpha1
import runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
// GetReclaimPolicy of this MyTypeClass.
func (cs *MyTypeClass) GetReclaimPolicy() runtimev1alpha1.ReclaimPolicy {
return cs.SpecTemplate.ReclaimPolicy
}
// SetReclaimPolicy of this MyTypeClass.
func (cs *MyTypeClass) SetReclaimPolicy(r runtimev1alpha1.ReclaimPolicy) {
cs.SpecTemplate.ReclaimPolicy = r
}

View File

@ -0,0 +1,223 @@
// +build !ignore_autogenerated
/*
Copyright 2020 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 controller-gen. DO NOT EDIT.
package v1alpha1
import (
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 *MyType) DeepCopyInto(out *MyType) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.Spec.DeepCopyInto(&out.Spec)
in.Status.DeepCopyInto(&out.Status)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyType.
func (in *MyType) DeepCopy() *MyType {
if in == nil {
return nil
}
out := new(MyType)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MyType) 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 *MyTypeClass) DeepCopyInto(out *MyTypeClass) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ObjectMeta.DeepCopyInto(&out.ObjectMeta)
in.SpecTemplate.DeepCopyInto(&out.SpecTemplate)
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeClass.
func (in *MyTypeClass) DeepCopy() *MyTypeClass {
if in == nil {
return nil
}
out := new(MyTypeClass)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MyTypeClass) 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 *MyTypeClassList) DeepCopyInto(out *MyTypeClassList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]MyTypeClass, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeClassList.
func (in *MyTypeClassList) DeepCopy() *MyTypeClassList {
if in == nil {
return nil
}
out := new(MyTypeClassList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MyTypeClassList) 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 *MyTypeClassSpecTemplate) DeepCopyInto(out *MyTypeClassSpecTemplate) {
*out = *in
in.ClassSpecTemplate.DeepCopyInto(&out.ClassSpecTemplate)
out.ForProvider = in.ForProvider
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeClassSpecTemplate.
func (in *MyTypeClassSpecTemplate) DeepCopy() *MyTypeClassSpecTemplate {
if in == nil {
return nil
}
out := new(MyTypeClassSpecTemplate)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MyTypeList) DeepCopyInto(out *MyTypeList) {
*out = *in
out.TypeMeta = in.TypeMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]MyType, len(*in))
for i := range *in {
(*in)[i].DeepCopyInto(&(*out)[i])
}
}
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeList.
func (in *MyTypeList) DeepCopy() *MyTypeList {
if in == nil {
return nil
}
out := new(MyTypeList)
in.DeepCopyInto(out)
return out
}
// DeepCopyObject is an autogenerated deepcopy function, copying the receiver, creating a new runtime.Object.
func (in *MyTypeList) 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 *MyTypeObservation) DeepCopyInto(out *MyTypeObservation) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeObservation.
func (in *MyTypeObservation) DeepCopy() *MyTypeObservation {
if in == nil {
return nil
}
out := new(MyTypeObservation)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MyTypeParameters) DeepCopyInto(out *MyTypeParameters) {
*out = *in
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeParameters.
func (in *MyTypeParameters) DeepCopy() *MyTypeParameters {
if in == nil {
return nil
}
out := new(MyTypeParameters)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MyTypeSpec) DeepCopyInto(out *MyTypeSpec) {
*out = *in
in.ResourceSpec.DeepCopyInto(&out.ResourceSpec)
out.ForProvider = in.ForProvider
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeSpec.
func (in *MyTypeSpec) DeepCopy() *MyTypeSpec {
if in == nil {
return nil
}
out := new(MyTypeSpec)
in.DeepCopyInto(out)
return out
}
// DeepCopyInto is an autogenerated deepcopy function, copying the receiver, writing into out. in must be non-nil.
func (in *MyTypeStatus) DeepCopyInto(out *MyTypeStatus) {
*out = *in
in.ResourceStatus.DeepCopyInto(&out.ResourceStatus)
out.AtProvider = in.AtProvider
}
// DeepCopy is an autogenerated deepcopy function, copying the receiver, creating a new MyTypeStatus.
func (in *MyTypeStatus) DeepCopy() *MyTypeStatus {
if in == nil {
return nil
}
out := new(MyTypeStatus)
in.DeepCopyInto(out)
return out
}

View File

@ -0,0 +1,93 @@
/*
Copyright 2020 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 angryjet. DO NOT EDIT.
package v1alpha1
import (
runtimev1alpha1 "github.com/crossplane/crossplane-runtime/apis/core/v1alpha1"
corev1 "k8s.io/api/core/v1"
)
// GetBindingPhase of this MyType.
func (mg *MyType) GetBindingPhase() runtimev1alpha1.BindingPhase {
return mg.Status.GetBindingPhase()
}
// GetClaimReference of this MyType.
func (mg *MyType) GetClaimReference() *corev1.ObjectReference {
return mg.Spec.ClaimReference
}
// GetClassReference of this MyType.
func (mg *MyType) GetClassReference() *corev1.ObjectReference {
return mg.Spec.ClassReference
}
// GetCondition of this MyType.
func (mg *MyType) GetCondition(ct runtimev1alpha1.ConditionType) runtimev1alpha1.Condition {
return mg.Status.GetCondition(ct)
}
// GetProviderReference of this MyType.
func (mg *MyType) GetProviderReference() *corev1.ObjectReference {
return mg.Spec.ProviderReference
}
// GetReclaimPolicy of this MyType.
func (mg *MyType) GetReclaimPolicy() runtimev1alpha1.ReclaimPolicy {
return mg.Spec.ReclaimPolicy
}
// GetWriteConnectionSecretToReference of this MyType.
func (mg *MyType) GetWriteConnectionSecretToReference() *runtimev1alpha1.SecretReference {
return mg.Spec.WriteConnectionSecretToReference
}
// SetBindingPhase of this MyType.
func (mg *MyType) SetBindingPhase(p runtimev1alpha1.BindingPhase) {
mg.Status.SetBindingPhase(p)
}
// SetClaimReference of this MyType.
func (mg *MyType) SetClaimReference(r *corev1.ObjectReference) {
mg.Spec.ClaimReference = r
}
// SetClassReference of this MyType.
func (mg *MyType) SetClassReference(r *corev1.ObjectReference) {
mg.Spec.ClassReference = r
}
// SetConditions of this MyType.
func (mg *MyType) SetConditions(c ...runtimev1alpha1.Condition) {
mg.Status.SetConditions(c...)
}
// SetProviderReference of this MyType.
func (mg *MyType) SetProviderReference(r *corev1.ObjectReference) {
mg.Spec.ProviderReference = r
}
// SetReclaimPolicy of this MyType.
func (mg *MyType) SetReclaimPolicy(r runtimev1alpha1.ReclaimPolicy) {
mg.Spec.ReclaimPolicy = r
}
// SetWriteConnectionSecretToReference of this MyType.
func (mg *MyType) SetWriteConnectionSecretToReference(r *runtimev1alpha1.SecretReference) {
mg.Spec.WriteConnectionSecretToReference = r
}

View File

@ -20,13 +20,15 @@ package apis
import (
"k8s.io/apimachinery/pkg/runtime"
templatev1alpha1 "github.com/crossplane-book/provider-template/apis/v1alpha1"
samplev1alpha1 "github.com/crossplanebook/provider-template/apis/sample/v1alpha1"
templatev1alpha1 "github.com/crossplanebook/provider-template/apis/v1alpha1"
)
func init() {
// Register the types with the Scheme so the components can map objects to GroupVersionKinds and back
AddToSchemes = append(AddToSchemes,
templatev1alpha1.SchemeBuilder.AddToScheme,
samplev1alpha1.SchemeBuilder.AddToScheme,
)
}

View File

@ -16,6 +16,6 @@ limitations under the License.
// Package v1alpha1 contains the core resources of the Template provider.
// +kubebuilder:object:generate=true
// +groupName=template.crossplane-book.io
// +groupName=template.crossplanebook.io
// +versionName=v1alpha1
package v1alpha1

View File

@ -25,7 +25,7 @@ import (
// Package type metadata.
const (
Group = "template.crossplane-book.io"
Group = "template.crossplanebook.io"
Version = "v1alpha1"
)

View File

@ -32,7 +32,6 @@ type ProviderSpec struct {
// +kubebuilder:object:root=true
// A Provider configures a Template 'provider'
// +kubebuilder:printcolumn:name="PROJECT-ID",type="string",JSONPath=".spec.projectID"
// +kubebuilder:printcolumn:name="AGE",type="date",JSONPath=".metadata.creationTimestamp"
// +kubebuilder:printcolumn:name="SECRET-NAME",type="string",JSONPath=".spec.credentialsSecretRef.name",priority=1
// +kubebuilder:resource:scope=Cluster

View File

@ -27,7 +27,8 @@ import (
"github.com/crossplane/crossplane-runtime/pkg/logging"
crossplaneapis "github.com/crossplane/crossplane/apis"
"github.com/crossplane-book/provider-template/apis"
"github.com/crossplanebook/provider-template/apis"
"github.com/crossplanebook/provider-template/pkg/controller"
)
func main() {
@ -57,6 +58,6 @@ func main() {
kingpin.FatalIfError(crossplaneapis.AddToScheme(mgr.GetScheme()), "Cannot add core Crossplane APIs to scheme")
kingpin.FatalIfError(apis.AddToScheme(mgr.GetScheme()), "Cannot add Template APIs to scheme")
// kingpin.FatalIfError(controller.Setup(mgr, log), "Cannot setup Template controllers")
kingpin.FatalIfError(controller.Setup(mgr, log), "Cannot setup Template controllers")
kingpin.FatalIfError(mgr.Start(ctrl.SetupSignalHandler()), "Cannot start controller manager")
}

View File

@ -0,0 +1,136 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: mytypeclasses.sample.template.crossplanebook.io
spec:
additionalPrinterColumns:
- JSONPath: .specTemplate.providerRef.name
name: PROVIDER-REF
type: string
- JSONPath: .specTemplate.reclaimPolicy
name: RECLAIM-POLICY
type: string
- JSONPath: .metadata.creationTimestamp
name: AGE
type: date
group: sample.template.crossplanebook.io
names:
kind: MyTypeClass
listKind: MyTypeClassList
plural: mytypeclasses
singular: mytypeclass
scope: Cluster
subresources: {}
validation:
openAPIV3Schema:
description: A MyTypeClass is a resource class. It defines the desired spec
of resource claims that use it to dynamically provision a managed resource.
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
specTemplate:
description: SpecTemplate is a template for the spec of a dynamically provisioned
MyType.
properties:
forProvider:
description: MyTypeParameters are the configurable fields of a MyType.
properties:
configurableField:
type: string
required:
- configurableField
type: object
providerRef:
description: ProviderReference specifies the provider that will be used
to create, observe, update, and delete managed resources that are
dynamically provisioned using this resource class.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an
entire object, this string should contain a valid JSON/Go field
access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen only
to have some well-defined way of referencing a part of an object.
TODO: this design is not final and this field is subject to change
in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is
made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
reclaimPolicy:
description: ReclaimPolicy specifies what will happen to managed resources
dynamically provisioned using this class when their resource claims
are deleted, and what will happen to their underlying external resource
when they are deleted. The "Delete" policy causes the managed resource
to be deleted when its bound resource claim is deleted, and in turn
causes the external resource to be deleted when its managed resource
is deleted. The "Retain" policy causes the managed resource to be
retained, in binding phase "Released", when its resource claim is
deleted, and in turn causes the external resource to be retained when
its managed resource is deleted. The "Retain" policy is used when
no policy is specified, however the "Delete" policy is set at dynamic
provisioning time if no policy is set.
enum:
- Retain
- Delete
type: string
writeConnectionSecretsToNamespace:
description: WriteConnectionSecretsToNamespace specifies the namespace
in which the connection secrets of managed resources dynamically provisioned
using this claim will be created.
type: string
required:
- forProvider
- providerRef
- writeConnectionSecretsToNamespace
type: object
required:
- specTemplate
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -0,0 +1,278 @@
---
apiVersion: apiextensions.k8s.io/v1beta1
kind: CustomResourceDefinition
metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: mytypes.sample.template.crossplanebook.io
spec:
additionalPrinterColumns:
- JSONPath: .status.bindingPhase
name: STATUS
type: string
- JSONPath: .status.atProvider.state
name: STATE
type: string
- JSONPath: .spec.classRef.name
name: CLASS
type: string
- JSONPath: .metadata.creationTimestamp
name: AGE
type: date
group: sample.template.crossplanebook.io
names:
kind: MyType
listKind: MyTypeList
plural: mytypes
singular: mytype
scope: Cluster
subresources:
status: {}
validation:
openAPIV3Schema:
description: A MyType is an example API type
properties:
apiVersion:
description: 'APIVersion defines the versioned schema of this representation
of an object. Servers should convert recognized schemas to the latest
internal value, and may reject unrecognized values. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#resources'
type: string
kind:
description: 'Kind is a string value representing the REST resource this
object represents. Servers may infer this from the endpoint the client
submits requests to. Cannot be updated. In CamelCase. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
metadata:
type: object
spec:
description: A MyTypeSpec defines the desired state of a MyType.
properties:
claimRef:
description: ClaimReference specifies the resource claim to which this
managed resource will be bound. ClaimReference is set automatically
during dynamic provisioning. Crossplane does not currently support
setting this field manually, per https://github.com/crossplane/crossplane-runtime/issues/19
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an
entire object, this string should contain a valid JSON/Go field
access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen only
to have some well-defined way of referencing a part of an object.
TODO: this design is not final and this field is subject to change
in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is
made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
classRef:
description: ClassReference specifies the resource class that was used
to dynamically provision this managed resource, if any. Crossplane
does not currently support setting this field manually, per https://github.com/crossplane/crossplane-runtime/issues/20
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an
entire object, this string should contain a valid JSON/Go field
access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen only
to have some well-defined way of referencing a part of an object.
TODO: this design is not final and this field is subject to change
in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is
made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
forProvider:
description: MyTypeParameters are the configurable fields of a MyType.
properties:
configurableField:
type: string
required:
- configurableField
type: object
providerRef:
description: ProviderReference specifies the provider that will be used
to create, observe, update, and delete this managed resource.
properties:
apiVersion:
description: API version of the referent.
type: string
fieldPath:
description: 'If referring to a piece of an object instead of an
entire object, this string should contain a valid JSON/Go field
access statement, such as desiredState.manifest.containers[2].
For example, if the object reference is to a container within
a pod, this would take on a value like: "spec.containers{name}"
(where "name" refers to the name of the container that triggered
the event) or if no container name is specified "spec.containers[2]"
(container with index 2 in this pod). This syntax is chosen only
to have some well-defined way of referencing a part of an object.
TODO: this design is not final and this field is subject to change
in the future.'
type: string
kind:
description: 'Kind of the referent. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#types-kinds'
type: string
name:
description: 'Name of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#names'
type: string
namespace:
description: 'Namespace of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/namespaces/'
type: string
resourceVersion:
description: 'Specific resourceVersion to which this reference is
made, if any. More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#concurrency-control-and-consistency'
type: string
uid:
description: 'UID of the referent. More info: https://kubernetes.io/docs/concepts/overview/working-with-objects/names/#uids'
type: string
type: object
reclaimPolicy:
description: ReclaimPolicy specifies what will happen to this managed
resource when its resource claim is deleted, and what will happen
to the underlying external resource when the managed resource is deleted.
The "Delete" policy causes the managed resource to be deleted when
its bound resource claim is deleted, and in turn causes the external
resource to be deleted when its managed resource is deleted. The "Retain"
policy causes the managed resource to be retained, in binding phase
"Released", when its resource claim is deleted, and in turn causes
the external resource to be retained when its managed resource is
deleted. The "Retain" policy is used when no policy is specified.
enum:
- Retain
- Delete
type: string
writeConnectionSecretToRef:
description: WriteConnectionSecretToReference specifies the namespace
and name of a Secret to which any connection details for this managed
resource should be written. Connection details frequently include
the endpoint, username, and password required to connect to the managed
resource.
properties:
name:
description: Name of the secret.
type: string
namespace:
description: Namespace of the secret.
type: string
required:
- name
- namespace
type: object
required:
- forProvider
- providerRef
type: object
status:
description: A MyTypeStatus represents the observed state of a MyType.
properties:
atProvider:
description: MyTypeObservation are the observable fields of a MyType.
properties:
observableField:
type: string
type: object
bindingPhase:
description: Phase represents the binding phase of a managed resource
or claim. Unbindable resources cannot be bound, typically because
they are currently unavailable, or still being created. Unbound resource
are available for binding, and Bound resources have successfully bound
to another resource.
enum:
- Unbindable
- Unbound
- Bound
- Released
type: string
conditions:
description: Conditions of the resource.
items:
description: A Condition that may apply to a resource.
properties:
lastTransitionTime:
description: LastTransitionTime is the last time this condition
transitioned from one status to another.
format: date-time
type: string
message:
description: A Message containing details about this condition's
last transition from one status to another, if any.
type: string
reason:
description: A Reason for this condition's last transition from
one status to another.
type: string
status:
description: Status of this condition; is it currently True, False,
or Unknown?
type: string
type:
description: Type of this condition. At most one of each condition
type may apply to a resource at any point in time.
type: string
required:
- lastTransitionTime
- reason
- status
- type
type: object
type: array
type: object
required:
- spec
type: object
version: v1alpha1
versions:
- name: v1alpha1
served: true
storage: true
status:
acceptedNames:
kind: ""
plural: ""
conditions: []
storedVersions: []

View File

@ -6,12 +6,9 @@ metadata:
annotations:
controller-gen.kubebuilder.io/version: v0.2.4
creationTimestamp: null
name: providers.template.crossplane-book.io
name: providers.template.crossplanebook.io
spec:
additionalPrinterColumns:
- JSONPath: .spec.projectID
name: PROJECT-ID
type: string
- JSONPath: .metadata.creationTimestamp
name: AGE
type: date
@ -19,7 +16,7 @@ spec:
name: SECRET-NAME
priority: 1
type: string
group: template.crossplane-book.io
group: template.crossplanebook.io
names:
kind: Provider
listKind: ProviderList

View File

@ -33,8 +33,8 @@ keywords:
- "infrastructure"
# Links to more information about the application (about page, source code, etc.)
website: "https://crossplane-book.github.io"
source: "https://github.com/crossplane-book/provider-template"
website: "https://crossplanebook.github.io"
source: "https://github.com/crossplanebook/provider-template"
# RBAC ClusterRoles will be generated permitting this stack to use all verbs on all
# resources in the groups listed below.

View File

@ -9,4 +9,4 @@ metadata:
name: provider-template
namespace: template
spec:
package: "hasheddan/provider-template:latest"
package: "crossplanebook/provider-template:latest"

View File

@ -0,0 +1,18 @@
apiVersion: v1
kind: Secret
metadata:
namespace: crossplane-system
name: example-provider-secret
type: Opaque
data:
# credentials: BASE64ENCODED_PROVIDER_CREDS
---
apiVersion: template.crossplanebook.io/v1alpha1
kind: Provider
metadata:
name: example
spec:
credentialsSecretRef:
namespace: crossplane-system
name: example-provider-secret
key: credentials

View File

@ -0,0 +1,9 @@
apiVersion: sample.template.crossplanebook.io/v1alpha1
kind: MyType
metadata:
name: example
spec:
forProvider:
configurableField: test
providerRef:
name: example

4
go.mod
View File

@ -1,4 +1,4 @@
module github.com/crossplane-book/provider-template
module github.com/crossplanebook/provider-template
go 1.13
@ -6,7 +6,9 @@ require (
github.com/crossplane/crossplane v0.9.0
github.com/crossplane/crossplane-runtime v0.6.0
github.com/crossplane/crossplane-tools v0.0.0-20200303232609-b3831cbb446d
github.com/pkg/errors v0.8.1
gopkg.in/alecthomas/kingpin.v2 v2.2.6
k8s.io/api v0.17.3
k8s.io/apimachinery v0.17.3
sigs.k8s.io/controller-runtime v0.4.0
sigs.k8s.io/controller-tools v0.2.4

23
go.sum
View File

@ -3,6 +3,7 @@ cloud.google.com/go v0.34.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMT
cloud.google.com/go v0.38.0/go.mod h1:990N+gfupTy94rShfmMCWGDn0LpTmnzTp2qbd1dvSRU=
cloud.google.com/go v0.44.1/go.mod h1:iSa0KzasP4Uvy3f1mN/7PiObzGgflwredwwASm/v6AU=
cloud.google.com/go v0.44.2/go.mod h1:60680Gw3Yr4ikxnPRS/oxxkBccT6SA1yMk63TGekxKY=
cloud.google.com/go v0.45.1 h1:lRi0CHyU+ytlvylOlFKKq0af6JncuyoRh1J+QJBqQx0=
cloud.google.com/go v0.45.1/go.mod h1:RpBamKRgapWJb87xiFSdk4g1CME7QZg3uwTez+TSTjc=
cloud.google.com/go/bigquery v1.0.1/go.mod h1:i/xbL2UlR5RvWAURpBYZTtm/cXjCha9lbfbpx4poX+o=
cloud.google.com/go/datastore v1.0.0/go.mod h1:LXYbyblFSglQ5pkeyhO+Qmw7ukd3C+pD7TKLgZqpHYE=
@ -44,14 +45,19 @@ github.com/bgentry/go-netrc v0.0.0-20140422174119-9fd32a8b3d3d/go.mod h1:6QX/PXZ
github.com/blang/semver v3.5.0+incompatible/go.mod h1:kRBLl5iJ+tD4TcOOxsy/0fnwebNt5EWlYSAyrTnjyyk=
github.com/cheggaaa/pb v1.0.27/go.mod h1:pQciLPpbU0oxA0h+VJYYLxO+XeDQb5pZijXscXHm81s=
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
github.com/coreos/bbolt v1.3.1-coreos.6 h1:uTXKg9gY70s9jMAKdfljFQcuh4e/BXOM+V+d00KFj3A=
github.com/coreos/bbolt v1.3.1-coreos.6/go.mod h1:iRUV2dpdMOn7Bo10OQBFzIJO9kkE559Wcmn+qkEiiKk=
github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/etcd v3.3.15+incompatible h1:+9RjdC18gMxNQVvSiXvObLu29mOFmkgdsB4cRTlV+EE=
github.com/coreos/etcd v3.3.15+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE=
github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk=
github.com/coreos/go-oidc v2.1.0+incompatible/go.mod h1:CgnwVTmzoESiwO9qyAFEMiHoZ1nMCKZlZ9V6mm3/LKc=
github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-semver v0.3.0 h1:wkHLiw0WNATZnSG7epLsujiMCgPAc9xhjJ4tgnAxmfM=
github.com/coreos/go-semver v0.3.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7 h1:u9SHYsPQNyt5tgDm3YN7+9dYrpK96E5wFilTFWIDZOM=
github.com/coreos/go-systemd v0.0.0-20180511133405-39ca1b05acc7/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea h1:n2Ltr3SrfQlf/9nOna1DoGKxLx3qTSI8Ttl6Xrqp6mw=
github.com/coreos/pkg v0.0.0-20180108230652-97fdf19511ea/go.mod h1:E3G3o1h8I7cfcXa63jLwjI0eiQQMgzzUDFVpN/nH/eA=
github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE=
github.com/crossplane/crossplane v0.9.0 h1:EfN4bsZBPvgQKAF/efdBZS0s8OdhIco7RQ4W9dovlKg=
@ -67,6 +73,7 @@ github.com/davecgh/go-spew v0.0.0-20151105211317-5215b55f46b2/go.mod h1:J7Y8YcW2
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/dgrijalva/jwt-go v3.2.0+incompatible h1:7qlOGliEKZXTDg6OTjfoBKDXWrumCAMpl/TFQ4/5kLM=
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
github.com/docker/distribution v2.7.1+incompatible h1:a5mlkVzth6W5A4fOsS3D2EO5BUmsJpcB+cRlLU7cSug=
github.com/docker/distribution v2.7.1+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w=
@ -151,6 +158,7 @@ github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5y
github.com/golang/protobuf v1.3.2 h1:6nsPYzhq5kReh6QImI3k5qWzO4PEbvbIW2cwSfR/6xs=
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/btree v1.0.0 h1:0udJVsspx3VBr5FwtLhQQtuAsVc79tTq0ocGIPAU6qo=
github.com/google/btree v1.0.0/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
github.com/google/go-cmp v0.2.0/go.mod h1:oXzfMopK8JAjlY9xF4vHSVASa0yLyX7SntLO5aqRK0M=
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
@ -166,17 +174,22 @@ github.com/google/uuid v1.0.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+
github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/googleapis/gnostic v0.3.1 h1:WeAefnSUHlBb0iJKwxFDZdbfGwkd7xRNuV+IpXMJhYk=
github.com/googleapis/gnostic v0.3.1/go.mod h1:on+2t9HRStVgn95RSsFWFz+6Q0Snyqv1awfrALZdbtU=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gophercloud/gophercloud v0.6.0/go.mod h1:GICNByuaEBibcjmjvI7QvYJSZEbGkcYwAR7EZK2WMqM=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79 h1:lR9ssWAqp9qL0bALxqEEkuudiP1eweOdv9jsRK3e7lE=
github.com/grpc-ecosystem/go-grpc-middleware v0.0.0-20190222133341-cfaf5686ec79/go.mod h1:FiyG127CGDf3tlThmgyCl78X/SZQqEOJBCDaAfeWzPs=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0 h1:Ovs26xHkKqVztRpIrF/92BcuyuQ/YW4NSIpoGtfXNho=
github.com/grpc-ecosystem/go-grpc-prometheus v1.2.0/go.mod h1:8NvIoxWQoOIhqOTXgfV/d3M/q6VIi02HzZEHgUlZvzk=
github.com/grpc-ecosystem/grpc-gateway v1.3.0 h1:HJtP6RRwj2EpPCD/mhAWzSvLL/dFTdPm1UrWwanoFos=
github.com/grpc-ecosystem/grpc-gateway v1.3.0/go.mod h1:RSKVYQBd5MCa4OVpNdGskqpgL2+G+NZTnrVHpWWfpdw=
github.com/hashicorp/go-cleanhttp v0.5.0/go.mod h1:JpRdi6/HCYpAwUzNwuwqhbovhLtngrth3wmdIIUrZ80=
github.com/hashicorp/go-getter v1.4.0/go.mod h1:7qxyCd8rBfcShwsvxgIguu4KbS3l8bUCwg2Umn7RjeY=
@ -196,6 +209,7 @@ github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJ
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0 h1:VKV+ZcuP6l3yW9doeqz6ziZGgcynBVQO+obU0+0hcPo=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/json-iterator/go v0.0.0-20180612202835-f2b4162afba3/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
@ -285,7 +299,9 @@ github.com/prometheus/procfs v0.0.3/go.mod h1:4A/X28fw3Fc593LaREMrKMqOKvUAntwMDa
github.com/remyoudompheng/bigfft v0.0.0-20170806203942-52369c62f446/go.mod h1:uYEyJGbgTkfkS4+E/PavXkNJcbFIpEtjt2B0KDQ5+9M=
github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/soheilhy/cmux v0.1.3 h1:09wy7WZk4AqO03yH85Ex1X+Uo3vDsil3Fa9AgF8Emss=
github.com/soheilhy/cmux v0.1.3/go.mod h1:IM3LyeVVIOuxMH7sFAkER9+bJ4dT7Ms6E4xg4kGIyLM=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
@ -306,12 +322,15 @@ github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXf
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.4.0 h1:2E4SXV/wtOkTonXsotYi4li6zVWxYlZuYNCXe9XRJyk=
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8 h1:ndzgwNDnKIqyCvHTXaCqh9KlOWKvBry6nuXMJmonVsE=
github.com/tmc/grpc-websocket-proxy v0.0.0-20170815181823-89b8d40f7ca8/go.mod h1:ncp9v5uamzpCO7NfCPTXjqaC+bZgJeR0sMTm6dMHP7U=
github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ulikunitz/xz v0.5.5/go.mod h1:2bypXElzHzzJZwzH67Y6wb67pO62Rzfn7BSiF4ABRW8=
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18 h1:MPPkRncZLN9Kh4MEFmbnK4h3BD7AUmskWv2+EeZJCCs=
github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
go.opencensus.io v0.21.0/go.mod h1:mSImk1erAIZhrmZN+AvHh14ztQfjbGwt4TtuofqLduU=
go.opencensus.io v0.22.0 h1:C9hSCOW830chIVkdja34wa6Ky+IzWllkUinR+BtRZd4=
go.opencensus.io v0.22.0/go.mod h1:+kGneAE2xo2IficOXnaByMWTGM9T73dGwxeWcUqIpI8=
go.uber.org/atomic v0.0.0-20181018215023-8dc6146f7569/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
@ -374,6 +393,7 @@ golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJ
golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190227155943-e225da77a7e6/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e h1:vcxGaoTs7kV8m5Np9uUNQin4BrLOthgV7252N8V+FwY=
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20170830134202-bb24a47a89ea/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20180117170059-2c42eef0765b/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
@ -434,6 +454,7 @@ gonum.org/v1/netlib v0.0.0-20190331212654-76723241ea4e/go.mod h1:kS+toOQn6AQKjmK
google.golang.org/api v0.4.0/go.mod h1:8k5glujaEP+g9n7WNsDg8QP6cUVNI86fCNMcbazEtwE=
google.golang.org/api v0.7.0/go.mod h1:WtwebWUNSVBH/HAw79HIFXZNqEvBhG+Ra+ax0hx3E3M=
google.golang.org/api v0.8.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/api v0.9.0 h1:jbyannxz0XFD3zdjgrSUsaJbgpH4eTrkdhRChkHPfO8=
google.golang.org/api v0.9.0/go.mod h1:o4eAsZoiT+ibD93RtjEohWalFOjRDx6CVaqeizhEnKg=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
@ -446,10 +467,12 @@ google.golang.org/genproto v0.0.0-20190418145605-e7d98fc518a7/go.mod h1:VzzqZJRn
google.golang.org/genproto v0.0.0-20190425155659-357c62f0e4bb/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190502173448-54afdca5d873/go.mod h1:VzzqZJRnGkLBvHegQrXjBqPurQTc5/KpmUdxsrq26oE=
google.golang.org/genproto v0.0.0-20190801165951-fa694d86fc64/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55 h1:gSJIx1SDwno+2ElGhA4+qG2zF97qiUzTM+rQ0klBOcE=
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
google.golang.org/grpc v1.20.1/go.mod h1:10oTOabMzJvdu6/UiuZezV6QK5dSlG84ov/aaiqXj38=
google.golang.org/grpc v1.21.1/go.mod h1:oYelfM1adQP15Ek0mdvEgi9Df8B9CZIaU1084ijfRaM=
google.golang.org/grpc v1.23.0 h1:AzbTB6ux+okLTzP8Ru1Xs41C303zdcfEht7MQnYJt5A=
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=

17
pkg/controller/doc.go Normal file
View File

@ -0,0 +1,17 @@
/*
Copyright 2020 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 controller

View File

@ -0,0 +1,157 @@
/*
Copyright 2020 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 sample
import (
"context"
"fmt"
"github.com/pkg/errors"
v1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/types"
ctrl "sigs.k8s.io/controller-runtime"
"sigs.k8s.io/controller-runtime/pkg/client"
"github.com/crossplane/crossplane-runtime/pkg/event"
"github.com/crossplane/crossplane-runtime/pkg/logging"
"github.com/crossplane/crossplane-runtime/pkg/meta"
"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
"github.com/crossplane/crossplane-runtime/pkg/resource"
"github.com/crossplanebook/provider-template/apis/sample/v1alpha1"
apisv1alpha1 "github.com/crossplanebook/provider-template/apis/v1alpha1"
)
const (
errNotMyType = "managed resource is not a MyType custom resource"
errProviderNotRetrieved = "provider could not be retrieved"
errProviderSecretNil = "cannot find Secret reference on Provider"
errProviderSecretNotRetrieved = "secret referred in provider could not be retrieved"
errNewClient = "cannot create new Service"
)
// A NoOpService does nothing.
type NoOpService struct{}
var (
newNoOpService = func() (interface{}, error) { return &NoOpService{}, nil }
)
// SetupMyType adds a controller that reconciles MyType managed resources.
func SetupMyType(mgr ctrl.Manager, l logging.Logger) error {
name := managed.ControllerName(v1alpha1.MyTypeGroupKind)
r := managed.NewReconciler(mgr,
resource.ManagedKind(v1alpha1.MyTypeGroupVersionKind),
managed.WithExternalConnecter(&myTypeConnector{kube: mgr.GetClient(), newServiceFn: newNoOpService}),
managed.WithInitializers(managed.NewNameAsExternalName(mgr.GetClient())),
managed.WithLogger(l.WithValues("controller", name)),
managed.WithRecorder(event.NewAPIRecorder(mgr.GetEventRecorderFor(name))))
return ctrl.NewControllerManagedBy(mgr).
Named(name).
For(&v1alpha1.MyType{}).
Complete(r)
}
type myTypeConnector struct {
kube client.Client
newServiceFn func() (interface{}, error)
}
func (c *myTypeConnector) Connect(ctx context.Context, mg resource.Managed) (managed.ExternalClient, error) {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return nil, errors.New(errNotMyType)
}
provider := &apisv1alpha1.Provider{}
if err := c.kube.Get(ctx, meta.NamespacedNameOf(cr.Spec.ProviderReference), provider); err != nil {
return nil, errors.Wrap(err, errProviderNotRetrieved)
}
if provider.GetCredentialsSecretReference() == nil {
return nil, errors.New(errProviderSecretNil)
}
secret := &v1.Secret{}
n := types.NamespacedName{Namespace: provider.Spec.CredentialsSecretRef.Namespace, Name: provider.Spec.CredentialsSecretRef.Name}
if err := c.kube.Get(ctx, n, secret); err != nil {
return nil, errors.Wrap(err, errProviderSecretNotRetrieved)
}
s, err := c.newServiceFn()
if err != nil {
return nil, errors.Wrap(err, errNewClient)
}
return &myTypeExternal{kube: c.kube, service: s}, nil
}
type myTypeExternal struct {
kube client.Client
service interface{}
}
func (c *myTypeExternal) Observe(ctx context.Context, mg resource.Managed) (managed.ExternalObservation, error) {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return managed.ExternalObservation{}, errors.New(errNotMyType)
}
fmt.Printf("Observing: %+v", cr)
return managed.ExternalObservation{
ResourceExists: true,
ResourceUpToDate: true,
// ConnectionDetails: getConnectionDetails(cr, instance),
}, nil
}
func (c *myTypeExternal) Create(ctx context.Context, mg resource.Managed) (managed.ExternalCreation, error) {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return managed.ExternalCreation{}, errors.New(errNotMyType)
}
fmt.Printf("Creating: %+v", cr)
return managed.ExternalCreation{}, nil
}
func (c *myTypeExternal) Update(ctx context.Context, mg resource.Managed) (managed.ExternalUpdate, error) {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return managed.ExternalUpdate{}, errors.New(errNotMyType)
}
fmt.Printf("Updating: %+v", cr)
return managed.ExternalUpdate{}, nil
}
func (c *myTypeExternal) Delete(ctx context.Context, mg resource.Managed) error {
cr, ok := mg.(*v1alpha1.MyType)
if !ok {
return errors.New(errNotMyType)
}
fmt.Printf("Deleting: %+v", cr)
return nil
}

View File

@ -0,0 +1,38 @@
/*
Copyright 2020 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 controller
import (
ctrl "sigs.k8s.io/controller-runtime"
"github.com/crossplane/crossplane-runtime/pkg/logging"
"github.com/crossplanebook/provider-template/pkg/controller/sample"
)
// Setup creates all Template controllers with the supplied logger and adds them to
// the supplied manager.
func Setup(mgr ctrl.Manager, l logging.Logger) error {
for _, setup := range []func(ctrl.Manager, logging.Logger) error{
sample.SetupMyType,
} {
if err := setup(mgr, l); err != nil {
return err
}
}
return nil
}