Using the Knative sample repository¶
The Knative project provides a sample repository that contains a template for a basic event source controller and a receive adapter.
Prerequisites¶
- You are familiar with Kubernetes and Go development.
- You have installed Git.
- You have installed Go.
- You have cloned the
sample-source
repository.
Optional:
Sample files overview¶
Receiver adapter files¶
-
cmd/receive_adapter/main.go
- Translates resource variables to the underlying adapter structure, so that they can be passed into the Knative system. -
pkg/adapter/adapter.go
- The functions that support receiver adapter translation of events to CloudEvents.
Controller files¶
-
cmd/controller/main.go
- Passes the event source'sNewController
implementation to the sharedmain
method. -
pkg/reconciler/sample/controller.go
- TheNewController
implementation that is passed to the sharedmain
method.
CRD files¶
pkg/apis/samples/VERSION/samplesource_types.go
- The schema for the underlying API types, which provide the variables to be defined in the resource YAML file.
Reconciler files¶
-
pkg/reconciler/sample/samplesource.go
- The reconciliation functions for the receive adapter. -
pkg/apis/samples/VERSION/samplesource_lifecycle.go
- Contains status information for the event source’s reconciliation details:- Source ready
- Sink provided
- Deployed
- EventType provided
- Kubernetes resources correct
Procedure¶
-
Define the types required in the resource’s schema in
pkg/apis/samples/v1alpha1/samplesource_types.go
.This includes the fields that are required in the resource YAML, as well as those referenced in the controller using the source’s clientset and API:
// +genclient // +genreconciler // +k8s:deepcopy-gen:interfaces=k8s.io/apimachinery/pkg/runtime.Object // +k8s:openapi-gen=true type SampleSource struct { metav1.TypeMeta `json:",inline"` // +optional metav1.ObjectMeta `json:"metadata,omitempty"` // Spec holds the desired state of the SampleSource (from the client). Spec SampleSourceSpec `json:"spec"` // Status communicates the observed state of the SampleSource (from the controller). // +optional Status SampleSourceStatus `json:"status,omitempty"` } // SampleSourceSpec holds the desired state of the SampleSource (from the client). type SampleSourceSpec struct { // inherits duck/v1 SourceSpec, which currently provides: // * Sink - a reference to an object that will resolve to a domain name or // a URI directly to use as the sink. // * CloudEventOverrides - defines overrides to control the output format // and modifications of the event sent to the sink. duckv1.SourceSpec `json:",inline"` // ServiceAccountName holds the name of the Kubernetes service account // as which the underlying K8s resources should be run. If unspecified // this will default to the "default" service account for the namespace // in which the SampleSource exists. // +optional ServiceAccountName string `json:"serviceAccountName,omitempty"` // Interval is the time interval between events. // // The string format is a sequence of decimal numbers, each with optional // fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m". Valid time // units are "ns", "us" (or "µs"), "ms", "s", "m", "h". If unspecified // this will default to "10s". Interval string `json:"interval"` } // SampleSourceStatus communicates the observed state of the SampleSource (from the controller). type SampleSourceStatus struct { duckv1.Status `json:",inline"` // SinkURI is the current active sink URI that has been configured // for the SampleSource. // +optional SinkURI *apis.URL `json:"sinkUri,omitempty"` }
-
Define the lifecycle to be reflected in the
status
andSinkURI
fields:const ( // SampleConditionReady has status True when the SampleSource is ready to send events. SampleConditionReady = apis.ConditionReady // ... )
-
Set the lifecycle conditions by defining the functions to be called from the reconciler functions. This is typically done in
pkg/apis/samples/VERSION/samplesource_lifecycle.go
:// InitializeConditions sets relevant unset conditions to Unknown state. func (s *SampleSourceStatus) InitializeConditions() { SampleCondSet.Manage(s).InitializeConditions() } ... // MarkSink sets the condition that the source has a sink configured. func (s *SampleSourceStatus) MarkSink(uri *apis.URL) { s.SinkURI = uri if len(uri.String()) > 0 { SampleCondSet.Manage(s).MarkTrue(SampleConditionSinkProvided) } else { SampleCondSet.Manage(s).MarkUnknown(SampleConditionSinkProvided, "SinkEmpty", "Sink has resolved to empty.%s", "") } } // MarkNoSink sets the condition that the source does not have a sink configured. func (s *SampleSourceStatus) MarkNoSink(reason, messageFormat string, messageA ...interface{}) { SampleCondSet.Manage(s).MarkFalse(SampleConditionSinkProvided, reason, messageFormat, messageA...) }