Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 56 additions & 0 deletions apis/core/v1alpha1/adopted_resource.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
// 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"
)

// AdoptedResourceSpec defines the desired state of the AdoptedResource.
type AdoptedResourceSpec struct {
// +kubebuilder:validation:Required
Kubernetes *TargetKubernetesResource `json:"kubernetes"`
// +kubebuilder:validation:Required
AWS *AWSIdentifiers `json:"aws"`
}

// AdoptedResourceStatus defines the observed status of the AdoptedResource.
type AdoptedResourceStatus struct {
// A collection of `ackv1alpha1.Condition` objects that describe the various
// terminal states of the adopted resource CR and its target custom resource
Conditions []*Condition `json:"conditions"`
}

// AdoptedResource is the schema for the AdoptedResource API.
// +kubebuilder:object:root=true
// +kubebuilder:subresource:status
type AdoptedResource struct {
metav1.TypeMeta `json:",inline"`
metav1.ObjectMeta `json:"metadata,omitempty"`
Spec AdoptedResourceSpec `json:"spec,omitempty"`
Status AdoptedResourceStatus `json:"status,omitempty"`
}

// AdoptedResourceList defines a list of AdoptedResources.
// +kubebuilder:object:root=true
// +kubebuilder:printcolumn:name="AdoptionStatus",type=string,JSONPath=`.status.adoptionStatus`
type AdoptedResourceList struct {
metav1.TypeMeta `json:",inline"`
metav1.ListMeta `json:"metadata,omitempty"`
Items []AdoptedResource `json:"items"`
}

func init() {
SchemeBuilder.Register(&AdoptedResource{}, &AdoptedResourceList{})
}
13 changes: 6 additions & 7 deletions apis/core/v1alpha1/annotations.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ package v1alpha1
const (
// AnnotationPrefix is the prefix for all ACK annotations
AnnotationPrefix = "services.k8s.aws/"
// AnnotationARN is an annotation whose value is an Amazon Resource Name,
// which is a globally-unique identifier, for the backend AWS service API
// resource. If this annotation is SET on a CR, that means the user is
// AnnotationAdopted is an annotation whose value is a boolean value,
// If this annotation is set to true on a CR, that means the user is
// indicating to the ACK service controller that it should expect a backend
// AWS service API resource to already exist (and that ACK should "adopt"
// the resource into its management). If this annotation is NOT SET on a
// CR, that means the user expects the ACK service controller to create the
// backend AWS service API resource.
AnnotationARN = AnnotationPrefix + "arn"
// the resource into its management). If this annotation is set to false on
// a CR, that means the user expects the ACK service controller to create
// the backend AWS service API resource.
AnnotationAdopted = AnnotationPrefix + "adopted"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Been thinking more about this annotation and whether we really need it. I'm not so sure we do, at least in a boolean form. A couple questions that highlight my concerns:

  1. If this annotation is not present on a CR, what does that mean?

  2. Above, it states "If this annotation is set to false on a CR, that means the user expects the ACK service controller to create the backend AWS service API resource." But this isn't really true, right? It's not the annotation's presence or lack of presence that dictates whether the service controller takes some action. Instead, it's the creation of an AdoptedResource CR explicitly by the Kubernetes user that is the signal for a service controller to grab the latest observed state of the referred-to resource instead of calling the API's Create operation.

  3. Given 2), would it make more sense to add an annotation called services.k8s.aws/adopted-on that is a timestamp of when the AdoptedResourceReconciler successfully created the resource CR after pulling the latest observed state from the AWS API?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, I could see more value in this becoming a timestamp. It was initially a boolean so that you could easily run a filter of services.k8s.aws/adopted=='true' on all resource annotations, but I understand that timestamp probably provide that plus more.
This annotation isn't being used by any system, it really is just informational to the user.

// AnnotationOwnerAccountID is an annotation whose value is the identifier
// for the AWS account to which the resource belongs. If this annotation
// is set on a CR, the Kubernetes user is indicating that the ACK service
Expand Down
3 changes: 3 additions & 0 deletions apis/core/v1alpha1/conditions.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ import (
type ConditionType string

const (
// ConditionTypeAdopted indicates that the adopted resource custom resource
// has been successfully reconciled and the target has been created
ConditionTypeAdopted ConditionType = "ACK.Adopted"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this condition to be applied to the AdoptedResource CR or to the target resource CR? If the latter, then perhaps we don't need a services.k8s.aws/adopted-on annotation at all, since the Condition has a timestamp assocated with its creation.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This condition is currently being applied to the AdoptedResource CR to describe to the user that it has essentially reached the terminal condition.

// ConditionTypeResourceSynced indicates the state of the resource in the
// backend service is in sync with the ACK service controller
ConditionTypeResourceSynced ConditionType = "ACK.ResourceSynced"
Expand Down
30 changes: 30 additions & 0 deletions apis/core/v1alpha1/groupversion_info.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// 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 (
"k8s.io/apimachinery/pkg/runtime/schema"
"sigs.k8s.io/controller-runtime/pkg/scheme"
)

var (
// GroupVersion is the API Group Version used to register the objects
GroupVersion = schema.GroupVersion{Group: "services.k8s.aws", Version: "v1alpha1"}

// SchemeBuilder is used to add go types to the GroupVersionKind scheme
SchemeBuilder = &scheme.Builder{GroupVersion: GroupVersion}

// AddToScheme adds the types in this group-version to the given scheme.
AddToScheme = SchemeBuilder.AddToScheme
)
34 changes: 34 additions & 0 deletions apis/core/v1alpha1/identifiers.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
// 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

// AWSIdentifiers provide all unique ways to reference an AWS resource.
type AWSIdentifiers struct {
// ARN is the AWS Resource Name for the resource. It is a globally
// unique identifier.
ARN *AWSResourceName `json:"arn,omitempty"`
// NameOrId is a user-supplied string identifier for the resource. It may
// or may not be globally unique, depending on the type of resource.
NameOrID *string `json:"nameOrID,omitempty"`
}

// TargetKubernetesResource provides all the values necessary to identify a given ACK type
// and override any metadata values when creating a resource of that type.
type TargetKubernetesResource struct {
// +kubebuilder:validation:Required
Group *string `json:"group"`
// +kubebuilder:validation:Required
Kind *string `json:"kind"`
Metadata *PartialObjectMeta `json:"metadata,omitempty"`
}
92 changes: 92 additions & 0 deletions apis/core/v1alpha1/types.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
// 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"
)

// ObjectMeta is metadata that all persisted resources must have, which includes all objects
// users must create.
// It is not possible to use `metav1.ObjectMeta` inside spec, as the controller-gen
// automatically converts this to an arbitrary string-string map.
// https://github.com/kubernetes-sigs/controller-tools/issues/385
//
// Active discussion about inclusion of this field in the spec is happening in this PR:
// https://github.com/kubernetes-sigs/controller-tools/pull/395
//
// Until this is allowed, or if it never is, we will produce a subset of the object meta
// that contains only the fields which the user is allowed to modify in the metadata.
type PartialObjectMeta struct {
// Name must be unique within a namespace. Is required when creating resources, although
// some resources may allow a client to request the generation of an appropriate name
// automatically. Name is primarily intended for creation idempotence and configuration
// definition.
// Cannot be updated.
// More info: http://kubernetes.io/docs/user-guide/identifiers#names
// +optional
Name string `json:"name,omitempty" protobuf:"bytes,1,opt,name=name"`

// GenerateName is an optional prefix, used by the server, to generate a unique
// name ONLY IF the Name field has not been provided.
// If this field is used, the name returned to the client will be different
// than the name passed. This value will also be combined with a unique suffix.
// The provided value has the same validation rules as the Name field,
// and may be truncated by the length of the suffix required to make the value
// unique on the server.
//
// If this field is specified and the generated name exists, the server will
// NOT return a 409 - instead, it will either return 201 Created or 500 with Reason
// ServerTimeout indicating a unique name could not be found in the time allotted, and the client
// should retry (optionally after the time indicated in the Retry-After header).
//
// Applied only if Name is not specified.
// More info: https://git.k8s.io/community/contributors/devel/sig-architecture/api-conventions.md#idempotency
// +optional
GenerateName string `json:"generateName,omitempty" protobuf:"bytes,2,opt,name=generateName"`

// Namespace defines the space within each name must be unique. An empty namespace is
// equivalent to the "default" namespace, but "default" is the canonical representation.
// Not all objects are required to be scoped to a namespace - the value of this field for
// those objects will be empty.
//
// Must be a DNS_LABEL.
// Cannot be updated.
// More info: http://kubernetes.io/docs/user-guide/namespaces
// +optional
Namespace string `json:"namespace,omitempty" protobuf:"bytes,3,opt,name=namespace"`

// Map of string keys and values that can be used to organize and categorize
// (scope and select) objects. May match selectors of replication controllers
// and services.
// More info: http://kubernetes.io/docs/user-guide/labels
// +optional
Labels map[string]string `json:"labels,omitempty" protobuf:"bytes,4,rep,name=labels"`

// Annotations is an unstructured key value map stored with a resource that may be
// set by external tools to store and retrieve arbitrary metadata. They are not
// queryable and should be preserved when modifying objects.
// More info: http://kubernetes.io/docs/user-guide/annotations
// +optional
Annotations map[string]string `json:"annotations,omitempty" protobuf:"bytes,5,rep,name=annotations"`

// List of objects depended by this object. If ALL objects in the list have
// been deleted, this object will be garbage collected. If this object is managed by a controller,
// then an entry in this list will point to this controller, with the controller field set to true.
// There cannot be more than one managing controller.
// +optional
// +patchMergeKey=uid
// +patchStrategy=merge
OwnerReferences []metav1.OwnerReference `json:"ownerReferences,omitempty" patchStrategy:"merge" patchMergeKey:"uid" protobuf:"bytes,6,rep,name=ownerReferences"`
}
Loading