Knative – Creating an event source https://knative.dev/v0.23-docs/eventing/sources/creating-event-sources/ Recent content in Creating an event source on Knative Hugo -- gohugo.io V0.23-Docs: Writing an event source using Javascript https://knative.dev/v0.23-docs/eventing/sources/creating-event-sources/writing-event-source-easy-way/ Mon, 01 Jan 0001 00:00:00 +0000 https://knative.dev/v0.23-docs/eventing/sources/creating-event-sources/writing-event-source-easy-way/ <p>This tutorial provides instructions to build an event source in Javascript and implement it with a ContainerSource or SinkBinding.</p> <ul> <li>Using a <a href="../../containersource">ContainerSource</a> is a simple way to turn any dispatcher container into a Knative event source.</li> <li>Using <a href="../../sinkbinding">SinkBinding</a> provides a framework for injecting environment variables into any Kubernetes resource that has a <code>spec.template</code> and is <a href="https://pkg.go.dev/knative.dev/pkg/apis/duck/v1#PodSpecable">PodSpecable</a>.</li> </ul> <p>ContainerSource and SinkBinding both work by injecting environment variables to an application. Injected environment variables at minimum contain the URL of a sink that will receive events.</p> <h2 id="bootstrapping">Bootstrapping</h2> <p>Create the project and add the dependencies:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">npm init npm install cloudevents-sdk@2.0.1 --save </code></pre></div><p><strong>NOTE:</strong> Due to this <a href="https://github.com/cloudevents/sdk-javascript/issues/191">bug</a>, you must use version 2.0.1 of the Javascript SDK or newer.</p> <h2 id="using-containersource">Using ContainerSource</h2> <p>A ContainerSource creates a container for your event source image and manages this container.</p> <p>The sink URL to post the events will be made available to the application through the <code>K_SINK</code> environment variable by the ContainerSource.</p> <h3 id="example">Example</h3> <p>The following example event source emits an event to the sink every 1000 milliseconds:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-javascript" data-lang="javascript"><span style="color:#8f5902;font-style:italic">// File - index.js </span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#204a87;font-weight:bold">const</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">CloudEvent</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">HTTPEmitter</span> <span style="color:#000;font-weight:bold">}</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">require</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;cloudevents-sdk&#34;</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#204a87;font-weight:bold">let</span> <span style="color:#000">sinkUrl</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#000">process</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">env</span><span style="color:#000;font-weight:bold">[</span><span style="color:#4e9a06">&#39;K_SINK&#39;</span><span style="color:#000;font-weight:bold">];</span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">log</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Sink URL is &#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#000">sinkUrl</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#204a87;font-weight:bold">let</span> <span style="color:#000">emitter</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">HTTPEmitter</span><span style="color:#000;font-weight:bold">({</span> <span style="color:#000">url</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000">sinkUrl</span> <span style="color:#000;font-weight:bold">});</span> <span style="color:#204a87;font-weight:bold">let</span> <span style="color:#000">eventIndex</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#0000cf;font-weight:bold">0</span><span style="color:#000;font-weight:bold">;</span> <span style="color:#000">setInterval</span><span style="color:#000;font-weight:bold">(</span><span style="color:#204a87;font-weight:bold">function</span> <span style="color:#000;font-weight:bold">()</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">log</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Emitting event #&#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#ce5c00;font-weight:bold">++</span><span style="color:#000">eventIndex</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#204a87;font-weight:bold">let</span> <span style="color:#000">myevent</span> <span style="color:#ce5c00;font-weight:bold">=</span> <span style="color:#204a87;font-weight:bold">new</span> <span style="color:#000">CloudEvent</span><span style="color:#000;font-weight:bold">({</span> <span style="color:#000">source</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;urn:event:from:my-api/resource/123&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">type</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;your.event.source.type&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">id</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;your-event-id&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">dataContentType</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;application/json&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#000">data</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#000;font-weight:bold">{</span><span style="color:#4e9a06">&#34;hello&#34;</span><span style="color:#ce5c00;font-weight:bold">:</span> <span style="color:#4e9a06">&#34;World &#34;</span> <span style="color:#ce5c00;font-weight:bold">+</span> <span style="color:#000">eventIndex</span><span style="color:#000;font-weight:bold">},</span> <span style="color:#000;font-weight:bold">});</span> <span style="color:#8f5902;font-style:italic">// Emit the event </span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">emitter</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">send</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">myevent</span><span style="color:#000;font-weight:bold">)</span> <span style="color:#000;font-weight:bold">.</span><span style="color:#000">then</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">response</span> <span style="color:#000;font-weight:bold">=&gt;</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#8f5902;font-style:italic">// Treat the response </span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">log</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Event posted successfully&#34;</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">log</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">response</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">data</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000;font-weight:bold">})</span> <span style="color:#000;font-weight:bold">.</span><span style="color:#204a87;font-weight:bold">catch</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">err</span> <span style="color:#000;font-weight:bold">=&gt;</span> <span style="color:#000;font-weight:bold">{</span> <span style="color:#8f5902;font-style:italic">// Deal with errors </span><span style="color:#8f5902;font-style:italic"></span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">log</span><span style="color:#000;font-weight:bold">(</span><span style="color:#4e9a06">&#34;Error during event post&#34;</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000">console</span><span style="color:#000;font-weight:bold">.</span><span style="color:#000">error</span><span style="color:#000;font-weight:bold">(</span><span style="color:#000">err</span><span style="color:#000;font-weight:bold">);</span> <span style="color:#000;font-weight:bold">});</span> <span style="color:#000;font-weight:bold">},</span> <span style="color:#0000cf;font-weight:bold">1000</span><span style="color:#000;font-weight:bold">);</span> </code></pre></div><div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-dockerfile" data-lang="dockerfile"><span style="color:#8f5902;font-style:italic"># File - Dockerfile</span><span style="color:#a40000"> </span><span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">FROM</span><span style="color:#4e9a06"> node:10</span><span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">WORKDIR</span><span style="color:#4e9a06"> /usr/src/app</span><span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">COPY</span> package*.json ./<span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">RUN</span> npm install<span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">COPY</span> . .<span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">EXPOSE</span><span style="color:#4e9a06"> 8080</span><span style="color:#a40000"> </span><span style="color:#a40000"></span><span style="color:#204a87;font-weight:bold">CMD</span> <span style="color:#000;font-weight:bold">[</span> <span style="color:#4e9a06">&#34;node&#34;</span><span style="color:#000;font-weight:bold">,</span> <span style="color:#4e9a06">&#34;index.js&#34;</span> <span style="color:#000;font-weight:bold">]</span><span style="color:#a40000"> </span><span style="color:#a40000"> </span></code></pre></div><p>The example code uses <em>Binary</em> mode for CloudEvents. To employ structured code, change <code>let binding = new v1.BinaryHTTPEmitter(config);</code> to <code>let binding = new v1.StructuredHTTPEmitter(config);</code>.</p> <p>Binary mode is used in most cases because:</p> <ul> <li>It is faster in terms of serialization and deserialization.</li> <li>It works better with CloudEvent-aware proxies, such as Knative Channels, and can simply check the header instead of parsing the payload.</li> </ul> <h3 id="procedure">Procedure</h3> <ol> <li> <p>Build and push the image:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">docker build . -t path/to/image/registry/node-knative-heartbeat-source:v1 docker push path/to/image/registry/node-knative-heartbeat-source:v1 </code></pre></div></li> <li> <p>Create the event display service which logs any CloudEvents posted to it:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">serving.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Service</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">event-display</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">template</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">containers</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span>- <span style="color:#204a87;font-weight:bold">image</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">docker.io/aliok/event_display-864884f202126ec3150c5fcef437d90c@sha256:93cb4dcda8fee80a1f68662ae6bf20301471b046ede628f3c3f94f39752fbe08</span><span style="color:#f8f8f8;text-decoration:underline"> </span></code></pre></div></li> <li> <p>Create the ContainerSource object:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">sources.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">ContainerSource</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">test-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">template</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">containers</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span>- <span style="color:#204a87;font-weight:bold">image</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">path/to/image/registry/node-knative-heartbeat-source:v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">sink</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">ref</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">serving.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Service</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">event-display</span><span style="color:#f8f8f8;text-decoration:underline"> </span></code></pre></div></li> <li> <p>Check the logs of the event display service. You will see a new message is pushed every second:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">$ kubectl logs -l serving.knative.dev/service<span style="color:#ce5c00;font-weight:bold">=</span>event-display -c user-container ☁️ cloudevents.Event Validation: valid Context Attributes, specversion: 1.0 type: your.event.source.type source: urn:event:from:your-api/resource/123 id: your-event-id datacontenttype: application/json Data, <span style="color:#ce5c00;font-weight:bold">{</span> <span style="color:#4e9a06">&#34;hello&#34;</span>: <span style="color:#4e9a06">&#34;World 1&#34;</span> <span style="color:#ce5c00;font-weight:bold">}</span> </code></pre></div></li> <li> <p>Optional: If you are interested in seeing what is injected into the event source as a <code>K_SINK</code>, you can check the logs:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">$ kubectl logs test-heartbeats-deployment-7575c888c7-85w5t Sink URL is http://event-display.default.svc.cluster.local Emitting event <span style="color:#8f5902;font-style:italic">#1</span> Emitting event <span style="color:#8f5902;font-style:italic">#2</span> Event posted successfully Event posted successfully </code></pre></div></li> </ol> <h2 id="using-sinkbinding">Using SinkBinding</h2> <p>SinkBinding does not create any containers. It injects the sink information to an already existing Kubernetes resources. This is a flexible approach as you can use any Kubernetes PodSpecable object as an event source, such as Deployment, Job, or Knative services.</p> <h3 id="procedure-1">Procedure</h3> <ol> <li> <p>Create an event display service:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">serving.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Service</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">event-display</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">template</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">containers</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span>- <span style="color:#204a87;font-weight:bold">image</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">docker.io/aliok/event_display-864884f202126ec3150c5fcef437d90c@sha256:93cb4dcda8fee80a1f68662ae6bf20301471b046ede628f3c3f94f39752fbe08</span><span style="color:#f8f8f8;text-decoration:underline"> </span></code></pre></div></li> <li> <p>Create a Kubernetes deployment that runs the event source:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">apps/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Deployment</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats-deployment</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">labels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">app</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">replicas</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">2</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">selector</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">app</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">template</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">labels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">app</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">containers</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span>- <span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">image</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">path/to/image/registry/node-knative-heartbeat-source:v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">ports</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span>- <span style="color:#204a87;font-weight:bold">containerPort</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#0000cf;font-weight:bold">8080</span><span style="color:#f8f8f8;text-decoration:underline"> </span></code></pre></div></li> <li> <p>Because the SinkBinding has not yet been created, you will see an error message, because the <code>K_SINK</code> environment variable is not yet injected:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">$ kubectl logs node-heartbeats-deployment-9ffbb644b-llkzk Sink URL is undefined Emitting event <span style="color:#8f5902;font-style:italic">#1</span> Error during event post TypeError <span style="color:#ce5c00;font-weight:bold">[</span>ERR_INVALID_ARG_TYPE<span style="color:#ce5c00;font-weight:bold">]</span>: The <span style="color:#4e9a06">&#34;url&#34;</span> argument must be of <span style="color:#204a87">type</span> string. Received <span style="color:#204a87">type</span> undefined </code></pre></div></li> <li> <p>Create the SinkBinding object:</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-yaml" data-lang="yaml"><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">sources.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">SinkBinding</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">metadata</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">bind-node-heartbeat</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"></span><span style="color:#204a87;font-weight:bold">spec</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">subject</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">apps/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Deployment</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">selector</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">matchLabels</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">app</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">node-heartbeats</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">sink</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">ref</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">apiVersion</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">serving.knative.dev/v1</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">kind</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">Service</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#204a87;font-weight:bold">name</span><span style="color:#000;font-weight:bold">:</span><span style="color:#f8f8f8;text-decoration:underline"> </span><span style="color:#000">event-display</span><span style="color:#f8f8f8;text-decoration:underline"> </span></code></pre></div><p>You will see the pods are recreated and this time the <code>K_SINK</code> environment variable is injected.</p> <p>Also note that since the <code>replicas</code> is set to 2, there will be 2 pods that are posting events to the sink.</p> <div class="highlight"><pre style="background-color:#f8f8f8;-moz-tab-size:4;-o-tab-size:4;tab-size:4"><code class="language-bash" data-lang="bash">$ kubectl logs event-display-dpplv-deployment-67c9949cf9-bvjvk -c user-container ☁️ cloudevents.Event Validation: valid Context Attributes, specversion: 1.0 type: your.event.source.type source: urn:event:from:your-api/resource/123 id: your-event-id datacontenttype: application/json Data, <span style="color:#ce5c00;font-weight:bold">{</span> <span style="color:#4e9a06">&#34;hello&#34;</span>: <span style="color:#4e9a06">&#34;World 1&#34;</span> <span style="color:#ce5c00;font-weight:bold">}</span> ☁️ cloudevents.Event Validation: valid Context Attributes, specversion: 1.0 type: your.event.source.type source: urn:event:from:your-api/resource/123 id: your-event-id datacontenttype: application/json Data, <span style="color:#ce5c00;font-weight:bold">{</span> <span style="color:#4e9a06">&#34;hello&#34;</span>: <span style="color:#4e9a06">&#34;World 1&#34;</span> <span style="color:#ce5c00;font-weight:bold">}</span> </code></pre></div></li> </ol> V0.23-Docs: Creating an event source by using the sample event source https://knative.dev/v0.23-docs/eventing/sources/creating-event-sources/writing-event-source/ Mon, 01 Jan 0001 00:00:00 +0000 https://knative.dev/v0.23-docs/eventing/sources/creating-event-sources/writing-event-source/ <p>This guide explains how to create your own event source for Knative Eventing by using a <a href="https://github.com/knative-sandbox/sample-source">sample repository</a>, and explains the key concepts behind each required component. Documentation for the default <a href="../../sources/">Knative event sources</a> can be used as an additional reference.</p> <p>After completing the provided tutorial, you will have created a basic event source controller and a receive adapter. Events can be viewed by using the <code>event_display</code> Knative service.</p> <!--TODO: Provide links to docs about what the event source controller and receiver adapter are--> <!-- Is Go required? Is this for all Knative development or just event source creation?--> <h2 id="prerequisites">Prerequisites</h2> <ul> <li>You are familiar with Kubernetes and Go development.</li> <li>You have installed Git.</li> <li>You have installed Go.</li> <li>Clone the <a href="https://github.com/knative-sandbox/sample-source">sample source</a>. <!--optional?--></li> </ul> <!-- add links, versions if required--> <!---TODO: decide...Maybe don't list these if they're optional, unless they're called out in a procedure--> <p>Optional:</p> <ul> <li>Install the <a href="https://github.com/google/ko/">ko</a> CLI tool.</li> <li>Install the <a href="https://kubernetes.io/docs/tasks/tools/install-kubectl/">kubectl</a> CLI tool.</li> <li>Set up <a href="https://github.com/kubernetes/minikube">minikube</a>.</li> </ul> <h2 id="steps">Steps</h2> <ol> <li><a href="./01-theory">Separation of Concerns</a></li> <li><a href="./02-lifecycle-and-types">API Definition</a></li> <li><a href="./03-controller">Controller</a></li> <li><a href="./04-reconciler">Reconciler</a></li> <li><a href="./05-receive-adapter">Receive Adapter</a></li> <li><a href="./06-yaml">Example YAML</a></li> <li><a href="./07-knative-sandbox">Moving the event source to the <code>knative-sandbox</code> organization</a></li> </ol>