We use analytics and cookies to understand site traffic. Information about your use of our site is shared with Google for that purpose. Learn more.
Defining a custom resource definition as the source
We'll use Kubebuilder to generate a new Kubernetes Custom Resource Definition for our source. Check out the Kubebuilder book to learn more about Kubebuilder.
Create the Source CRD Skeleton
When in doubt, the Kubebuilder Quick Start docs are likely more current than these instructions.
Use the kubebuilder create api
command to create the API definition for a new
CRD and a controller to reconcile it.
You'll need to choose the following:
-
A group name. This is the resource group that will contain the resource. It's prepended to the domain name chosen earlier to produce the fully-qualified resource name. The reference project uses
sources
. -
A version name. This is the initial version string for the CRD. It's usually
v1alpha1
for new resources. The reference project usesv1alpha1
. -
A kind name. This is the unqualified type name of the resource. The reference project uses
SampleSource
.The fully-qualified name of the reference resource is
samplesources.sources.knative.dev
, and itsapiVersion
issources.knative.dev/v1alpha1
.
kubebuilder create api --group sources --version v1alpha1 --kind SampleSource
This command will ask if you want to create the resource and controller. Answer yes to both to generate scaffolding to edit in future steps.
The result of this command in the reference project can be viewed at https://github.com/grantr/sample-source/pull/2.
Add Fields to Source Type Definition
Locate the Spec
and Status
types generated by Kubebuilder. In the reference
project, these types are defined in
pkg/apis/sources/v1alpha1/samplesource_types.go
.
Add a Sink
field to the Spec
type. Its type should be
*corev1.ObjectReference
. You'll also need to import the Go package
k8s.io/api/core/v1
as corev1
.
type SampleSourceSpec struct {
// Sink is a reference to an object that will resolve to a domain name to use
// as the sink.
// +optional
Sink *corev1.ObjectReference `json:"sink,omitempty"`
}
Add a SinkURI
string field to the Status
type.
type SampleSourceStatus struct {
// SinkURI is the current active sink URI that has been configured for the SampleSource.
// +optional
SinkURI string `json:"sinkURI,omitempty"`
}
Run dep ensure
to add the new library to vendor
if necessary.
dep ensure
Run make
to regenerate the deepcopy code in zz_generated.deepcopy.go
and the
CRD's OpenAPI schema.
make
Update type tests
Locate the type tests file. In the reference project, this is
samplesource_types_test.go
in the same directory as samplesource_types.go
.
Edit the created
object to include a Spec
declaring a Sink
.
created := &SampleSource{
ObjectMeta: metav1.ObjectMeta{
Name: "foo",
Namespace: "default",
},
Spec: SampleSourceSpec{
Sink: &corev1.ObjectReference{
Name: "fooservice",
APIVersion: "v1",
Kind: "Service",
},
},
}
Edit the updated
object, setting SinkURI
in its Status
.
// Test Updating the Labels and Status
updated := fetched.DeepCopy()
updated.Labels = map[string]string{"hello": "world"}
updated.Status = SampleSourceStatus{
SinkURI: "http://example.com",
}
Run make
to run tests and calculate the coverage percentage for all packages
in pkg
and cmd
.
make
go test ./pkg/... ./cmd/... -coverprofile cover.out
? github.com/knative/sample-source/pkg/apis [no test files]
? github.com/knative/sample-source/pkg/apis/sources [no test files]
ok github.com/knative/sample-source/pkg/apis/sources/v1alpha1 8.528s coverage: 33.3% of statements
? github.com/knative/sample-source/pkg/controller [no test files]
ok github.com/knative/sample-source/pkg/controller/samplesource 9.151s coverage: 67.6% of statements
? github.com/knative/sample-source/pkg/webhook [no test files]
? github.com/knative/sample-source/cmd/manager [no test files]
These edits in the reference project can be viewed at https://github.com/grantr/sample-source/pull/3.
Enable the Status subresource
The Status subresource allows controllers to update only the Status field without updating the Spec field. Since controllers should not update the Spec of their watched objects, this makes controllers safer and easier to write by ensuring they never update Spec accidentally.
This feature became beta in Kubernetes 1.11, so it might not work properly with older versions.
Add the Kubebuilder status subresource annotation to the struct defining the
object. In the reference project, this is in
pkg/apis/sources/v1alpha1/samplesource_types.go
.
// SampleSource is the Schema for the samplesources API
// +k8s:openapi-gen=true
// +kubebuilder:subresource:status
type SampleSource struct {
// ...
}
Run make
to regenerate the CRD yaml.
make
Update tests to use the Status subresource
Now update the tests to use the Status subresource to set SinkURI. This now needs to be separate from the labels update.
// Test Updating the Labels
updated := fetched.DeepCopy()
updated.Labels = map[string]string{"hello": "world"}
g.Expect(c.Update(context.TODO(), updated)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched).To(gomega.Equal(updated))
// Test Updating the Status via subresource
updated.Status = SampleSourceStatus{
SinkURI: "http://example.com",
}
// DeepCopy is required here because the Status update will set the SelfLink
// to reference to /status subresource instead of the original resource.
statusupdated := updated.DeepCopy()
g.Expect(c.Status().Update(context.TODO(), statusupdated)).NotTo(gomega.HaveOccurred())
g.Expect(c.Get(context.TODO(), key, fetched)).NotTo(gomega.HaveOccurred())
g.Expect(fetched.Status).To(gomega.Equal(updated.Status))
Run make
to verify tests pass.
make
These edits in the reference project can be viewed at https://github.com/grantr/sample-source/pull/4.
Next: Reconcile Sources
Feedback
Was this page helpful?
Glad to hear it! Please tell us how we can improve.
Sorry to hear that. Please tell us how we can improve.