-
Notifications
You must be signed in to change notification settings - Fork 267
Custom controller framework #4
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
I'd vote for I believe it is a younger project to
|
+1 for kubebuilder feels much more kube native and I expect will see significantly more support and growth in the next year |
My vote is obviously with |
|
Adds a document discussing options for code generation and a diagram with how a multi-phase hybrid custom+controller-runtime generator might work. Issue #4
Adds a document discussing options for code generation and a diagram with how a multi-phase hybrid custom+controller-runtime generator might work. Issue #4
Adds a document discussing options for code generation and a diagram with how a multi-phase hybrid custom+controller-runtime generator might work. Issue #4
Hi folks! I'm the tech lead for https://github.com/crossplane/stack-aws - a project very similar to what it sounds like you're planning with the Service Operator. We went with controller-runtime and have been quite happy with our choice. Rather than take a pure code generation/scaffolding approach we built a series of generic reconcilers that reconcile a "shape" (or duck type) of Kubernetes custom resource. These are packaged in crossplane-runtime, and could be reused by a project like the Service Operator if you so desired. The general pattern is that there's a "reconciler scaffold" that handles all the parts of reconciling a Kubernetes CR with an AWS API that are mostly the same from API to API. This reconciler wraps an type ExternalClient interface {
// Observe the external resource the supplied Managed resource represents,
// if any. Observe implementations must not modify the external resource,
// but may update the supplied Managed resource to reflect the state of the
// external resource.
Observe(ctx context.Context, mg resource.Managed) (ExternalObservation, error)
// Create an external resource per the specifications of the supplied
// Managed resource. Called when Observe reports that the associated
// external resource does not exist.
Create(ctx context.Context, mg resource.Managed) (ExternalCreation, error)
// Update the external resource represented by the supplied Managed
// resource, if necessary. Called unless Observe reports that the
// associated external resource is up to date.
Update(ctx context.Context, mg resource.Managed) (ExternalUpdate, error)
// Delete the external resource upon deletion of its associated Managed
// resource. Called when the managed resource has been deleted.
Delete(ctx context.Context, mg resource.Managed) error
} Our ElastiCache ReplicationGroup controller is a good example of a reconciler for a moderately complex AWS API that uses this pattern. |
Adds a new `ack-generate` CLI tool that can generate the Go files for CRD types. The `ack-generate types` command accepts an OpenAPI3/Swagger document, parses out the top-level resources in the API and constructs the files with Go structs representing the CRDs/Kinds in the API. ``` $ go run cmd/ack-generate/main.go types < /tmp/sns.swagger.yaml // Copyright Amazon.com Inc. or its affiliates. All Rights Reserved. // // Licensed under the Apache License, Version 2.0 (the "License"). You may // not use this file except in compliance with the License. A copy of the // License is located at // // http://aws.amazon.com/apache2.0/ // // or in the "license" file accompanying this file. This file 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" ) type Endpoint struct { Attributes map[string]string `json:"Attributes,omitempty"` EndpointArn string `json:"EndpointArn,omitempty"` } type Subscription struct { Endpoint string `json:"Endpoint,omitempty"` Owner string `json:"Owner,omitempty"` Protocol string `json:"Protocol,omitempty"` SubscriptionArn string `json:"SubscriptionArn,omitempty"` TopicArn string `json:"TopicArn,omitempty"` } type KMSOptInRequired struct { Message string `json:"message,omitempty"` } type Tag struct { Key string `json:"Key,omitempty"` Value string `json:"Value,omitempty"` } type MessageAttributeValue struct { BinaryValue string `json:"BinaryValue,omitempty"` DataType string `json:"DataType,omitempty"` StringValue string `json:"StringValue,omitempty"` } // PlatformEndpointSpec defines the desired state of PlatformEndpoint type PlatformEndpointSpec struct { // The Arn attr is on all AWS service API CRs. It represents the Amazon // Resource Name for the object. CRs of this Kind that are created without // an Arn attr will be created by the controller. CRs of this Kind that // are created with a non-nil Arn attr are considered by the controller to // already exist in the backend AWS service API. Arn string `json:"arn,omitempty"` Attributes map[string]string `json:"Attributes,omitempty"` CustomUserData string `json:"CustomUserData,omitempty"` PlatformApplicationArn string `json:"PlatformApplicationArn,omitempty"` Token string `json:"Token,omitempty"` } // PlatformEndpointStatus defines the observed state of PlatformEndpoint type PlatformEndpointStatus struct { EndpointArn string `json:"EndpointArn,omitempty"` } // PlatformEndpoint is the Schema for the PlatformEndpoints API type PlatformEndpoint struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec PlatformEndpointSpec `json:"spec,omitempty"` Status PlatformEndpointStatus `json:"status,omitempty"` } // PlatformEndpointList contains a list of PlatformEndpoint type PlatformEndpointList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []PlatformEndpoint `json:"items"` } // TopicSpec defines the desired state of Topic type TopicSpec struct { // The Arn attr is on all AWS service API CRs. It represents the Amazon // Resource Name for the object. CRs of this Kind that are created without // an Arn attr will be created by the controller. CRs of this Kind that // are created with a non-nil Arn attr are considered by the controller to // already exist in the backend AWS service API. Arn string `json:"arn,omitempty"` Attributes map[string]string `json:"Attributes,omitempty"` Name string `json:"Name,omitempty"` Tags []*Tags `json:"Tags,omitempty"` } // TopicStatus defines the observed state of Topic type TopicStatus struct { TopicArn string `json:"TopicArn,omitempty"` } // Topic is the Schema for the Topics API type Topic struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec TopicSpec `json:"spec,omitempty"` Status TopicStatus `json:"status,omitempty"` } // TopicList contains a list of Topic type TopicList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []Topic `json:"items"` } // PlatformApplicationSpec defines the desired state of PlatformApplication type PlatformApplicationSpec struct { // The Arn attr is on all AWS service API CRs. It represents the Amazon // Resource Name for the object. CRs of this Kind that are created without // an Arn attr will be created by the controller. CRs of this Kind that // are created with a non-nil Arn attr are considered by the controller to // already exist in the backend AWS service API. Arn string `json:"arn,omitempty"` Attributes map[string]string `json:"Attributes,omitempty"` Name string `json:"Name,omitempty"` Platform string `json:"Platform,omitempty"` } // PlatformApplicationStatus defines the observed state of PlatformApplication type PlatformApplicationStatus struct { PlatformApplicationArn string `json:"PlatformApplicationArn,omitempty"` } // PlatformApplication is the Schema for the PlatformApplications API type PlatformApplication struct { metav1.TypeMeta `json:",inline"` metav1.ObjectMeta `json:"metadata,omitempty"` Spec PlatformApplicationSpec `json:"spec,omitempty"` Status PlatformApplicationStatus `json:"status,omitempty"` } // PlatformApplicationList contains a list of PlatformApplication type PlatformApplicationList struct { metav1.TypeMeta `json:",inline"` metav1.ListMeta `json:"metadata,omitempty"` Items []PlatformApplication `json:"items"` } func init() { SchemeBuilder.Register(&PlatformEndpoint{}, &PlatformEndpointList{}) SchemeBuilder.Register(&Topic{}, &TopicList{}) SchemeBuilder.Register(&PlatformApplication{}, &PlatformApplicationList{}) } ``` Issue #4 Produces the types.go file that can be fed into `controller-gen crds`
@negz so sorry for being so uncommunicative about this! Not sure if you've been following along with our progress on the mvp branch, but we've been slogging along slowly but surely. Last Friday I pushed up a pull request that adds a good chunk of the controller implementation generation. Would be awesome to get your comments on it. I can certainly see our teams collaborating on a bunch of common runtime stuff, for the record! |
Nice, thanks @jaypipes! I'll take a look this week. Would you be interested in setting up a call at some point to swap notes? |
absolutely @negz I would be more than happy to do that. My schedule next week is pretty open. Catch me on Slack and we'll schedule a time. :) |
Closing this out. We ended up going with a custom code generator + controller-gen tooling. |
Uh oh!
There was an error while loading. Please reload this page.
This design issue is about how custom controllers are written in ASO. The goal is to select a widely used framework that has a low barrier to contributing to ASO. Usage of requirements key words as per RFC 2119.
Scope
In scope for this issue is the selection of the custom controller framework, that is, a Go-based framework supporting the creation of custom controllers used in ASO. Out of scope for this issue is the question how the business logic (managing AWS services) in the custom controllers is implemented, see #5 for this.
Input
Relevant candidates:
Input from roadmap issue aws/containers-roadmap#456:
Requirements
The text was updated successfully, but these errors were encountered: