<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Luca Sepe</title>
    <description>The latest articles on DEV Community by Luca Sepe (@lucasepe).</description>
    <link>https://dev.to/lucasepe</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F136288%2F54d99794-8165-46e2-9198-2106a0b95d99.png</url>
      <title>DEV Community: Luca Sepe</title>
      <link>https://dev.to/lucasepe</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/lucasepe"/>
    <language>en</language>
    <item>
      <title>I'm building a read-only context engine for Kubernetes and AI agents</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Mon, 15 Jun 2026 08:03:09 +0000</pubDate>
      <link>https://dev.to/lucasepe/im-building-a-read-only-context-engine-for-kubernetes-and-ai-agents-40nh</link>
      <guid>https://dev.to/lucasepe/im-building-a-read-only-context-engine-for-kubernetes-and-ai-agents-40nh</guid>
      <description>&lt;p&gt;Kubernetes gives us an incredibly powerful API.&lt;/p&gt;

&lt;p&gt;It also gives us a familiar debugging ritual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kubectl get pods
kubectl describe pod ...
kubectl get svc ...
kubectl get endpointslices ...
kubectl get deployment ...
kubectl get events ...
kubectl get application.argoproj.io ...
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then we mentally stitch the result together.&lt;/p&gt;

&lt;p&gt;Which workload owns this Pod? Which Service routes to it? Are there ready endpoints? Is the namespace unhealthy because of one bad Deployment, a missing backend, warning Events, or something else? &lt;/p&gt;

&lt;p&gt;Which facts should I paste into an incident, attach to a CI failure, or give to an AI assistant before asking it to reason?&lt;/p&gt;

&lt;p&gt;I started building &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; because I wanted a small tool for that missing middle layer: not raw YAML, not a dashboard, not an auto-remediation system.&lt;/p&gt;

&lt;p&gt;Just structured Kubernetes context.&lt;/p&gt;

&lt;h2&gt;
  
  
  The short version
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; is a read-only Kubernetes context engine for humans, scripts, and AI agents.&lt;/p&gt;

&lt;p&gt;It turns live Kubernetes API state into a compact model of:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;entities: Pods, Services, workloads, Nodes, PVCs, ConfigMaps, Secrets, and supported CRDs&lt;/li&gt;
&lt;li&gt;relations: ownership, selection, scheduling, service routing, and dependencies&lt;/li&gt;
&lt;li&gt;signals: factual observations such as unhealthy Pods, missing endpoints, warning Events, failed readiness, or degraded workloads&lt;/li&gt;
&lt;li&gt;graphs: dependency and ownership views around supported resources&lt;/li&gt;
&lt;li&gt;dumps: deterministic namespace snapshots for automation, incident review, and agent grounding&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The design goal is intentionally conservative:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;read cluster state, normalize facts, avoid speculative root-cause claims.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;That boundary matters.&lt;/p&gt;

&lt;p&gt;I do not want &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; to be a tool that confidently invents explanations. I want it to provide the evidence layer that humans, automation, and AI agents can use before reasoning.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why another Kubernetes tool?
&lt;/h2&gt;

&lt;p&gt;Most Kubernetes tools are optimized for one of a few jobs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;kubectl&lt;/code&gt; exposes the raw API very well&lt;/li&gt;
&lt;li&gt;dashboards make current state visible&lt;/li&gt;
&lt;li&gt;monitoring systems track metrics and alerts over time&lt;/li&gt;
&lt;li&gt;logging systems answer "what happened in the process?"&lt;/li&gt;
&lt;li&gt;GitOps tools understand desired state and sync status&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Those are all useful. I use them too.&lt;/p&gt;

&lt;p&gt;But during debugging, there is still a recurring gap between "I can query every object" and "I have a compact operational picture of what is connected to what."&lt;/p&gt;

&lt;p&gt;For example, when looking at a Service, I often care less about the complete YAML and more about questions like:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Which EndpointSlices back this Service?&lt;/li&gt;
&lt;li&gt;Which endpoints are ready?&lt;/li&gt;
&lt;li&gt;Which Pods do those endpoints point to?&lt;/li&gt;
&lt;li&gt;Who owns those Pods?&lt;/li&gt;
&lt;li&gt;Which Nodes are involved?&lt;/li&gt;
&lt;li&gt;Are there obvious factual signals, such as missing endpoints or no ready Pods?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is the kind of context &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; tries to assemble.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kctx trace service payments-api &lt;span class="nt"&gt;--namespace&lt;/span&gt; payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a namespace-level view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kctx health namespace payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For a focused resource view:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kctx explain pod api-xyz &lt;span class="nt"&gt;--namespace&lt;/span&gt; payments
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And when you need a deterministic JSON snapshot for automation or incident review:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kctx dump namespace payments &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; payments-dump.json
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  The important constraint: read-only
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; does not mutate Kubernetes resources.&lt;/p&gt;

&lt;p&gt;It does not:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;restart workloads&lt;/li&gt;
&lt;li&gt;apply manifests&lt;/li&gt;
&lt;li&gt;patch resources&lt;/li&gt;
&lt;li&gt;delete anything&lt;/li&gt;
&lt;li&gt;perform remediation&lt;/li&gt;
&lt;li&gt;claim to know the root cause&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That is not because remediation is uninteresting. It is because I think the context layer should be boring, auditable, and safe before anything else is built on top of it.&lt;/p&gt;

&lt;p&gt;This becomes even more important when AI agents enter the picture.&lt;/p&gt;

&lt;p&gt;If an agent needs Kubernetes context, I would rather give it a narrow read-only tool that returns structured facts than hand it broad cluster access and hope the prompt is enough of a safety boundary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Kubernetes context for AI agents
&lt;/h2&gt;

&lt;p&gt;One of the areas I am experimenting with is exposing &lt;code&gt;kctx&lt;/code&gt; through the Model Context Protocol.&lt;/p&gt;

&lt;p&gt;Current serve modes include:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;kctx serve &lt;span class="nt"&gt;--mode&lt;/span&gt; mcp
kctx serve &lt;span class="nt"&gt;--mode&lt;/span&gt; mcp-sse
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The MCP tools currently cover the same core context operations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;code&gt;get_namespace_health&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;explain_resource&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;trace_service&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;get_pod_graph&lt;/code&gt;&lt;/li&gt;
&lt;li&gt;&lt;code&gt;dump_namespace&lt;/code&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The idea is simple: let an AI assistant ask for Kubernetes context without giving it mutation capabilities.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;No remediation.&lt;/li&gt;
&lt;li&gt;No raw YAML firehose.&lt;/li&gt;
&lt;li&gt;No root-cause guessing dressed up as certainty.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Just compact operational facts that can be used as evidence.&lt;/p&gt;

&lt;p&gt;There is also an MCP/SSE release test guide for anyone who wants to try this with a local kind cluster, the released Helm chart, Online Boutique, ngrok, Codex, Claude Code, or ChatGPT Developer Mode:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/kctx/tree/main/docs/kctx-mcp-sse-release-test-guide.pdf" rel="noopener noreferrer"&gt;https://github.com/lucasepe/kctx/tree/main/docs/kctx-mcp-sse-release-test-guide.pdf&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Important note: the MCP/SSE endpoint is read-only, but built-in AuthN/AuthZ is not production-ready yet. Treat it as local-lab or trusted-network tooling for now, or put it behind an external access-control layer.&lt;/p&gt;

&lt;h2&gt;
  
  
  CRDs need semantics, not wishful thinking
&lt;/h2&gt;

&lt;p&gt;Another design choice: &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; does not pretend that every custom resource can be understood generically.&lt;/p&gt;

&lt;p&gt;Kubernetes discovery can tell you that a CRD exists. It cannot tell you what that CRD means operationally.&lt;/p&gt;

&lt;p&gt;So &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; uses explicit adapters for ecosystem-specific resources. An adapter can translate a CRD into the same core model used by the rest of the project: resource identity, compact status, related entities, relations, signals, and graph nodes or edges.&lt;/p&gt;

&lt;p&gt;The current adapter set includes:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Argo CD &lt;code&gt;Application&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;Argo CD &lt;code&gt;AppProject&lt;/code&gt;
&lt;/li&gt;
&lt;li&gt;cert-manager &lt;code&gt;Certificate&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;That approach is slower than saying "we support every CRD", but I think it is more honest. If a tool is going to describe operational context, it should know what it is describing.&lt;/p&gt;

&lt;h2&gt;
  
  
  JSON first, because scripts and agents need contracts
&lt;/h2&gt;

&lt;p&gt;The CLI and HTTP API emit versioned JSON by default.&lt;/p&gt;

&lt;p&gt;Responses include a schema version and kind, for example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"schemaVersion"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"kctx.io/v1alpha1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"kind"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"NamespaceHealth"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The repository includes machine-readable JSON schemas under:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;schemas/kctx.io/v1alpha1
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That part may sound less exciting than graphs or agents, but it is one of the pieces I care about most.&lt;/p&gt;

&lt;p&gt;If humans are the only users, text output can be enough. If scripts, CI systems, incident tooling, and AI agents are also users, the output needs a contract.&lt;/p&gt;

&lt;h2&gt;
  
  
  Data safety
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt;` is designed to provide operational context, not sensitive data.&lt;/p&gt;

&lt;p&gt;It avoids returning raw manifests, Secret data, ConfigMap data, raw environment variables, logs, and workload metrics.&lt;/p&gt;

&lt;p&gt;Supported outputs also pass metadata and Kubernetes messages through a small redaction policy for common secret-bearing keys and text patterns.&lt;/p&gt;

&lt;p&gt;This is not a magic privacy shield, but it is an intentional boundary in the design.&lt;/p&gt;

&lt;h2&gt;
  
  
  A tiny example workflow
&lt;/h2&gt;

&lt;p&gt;Install:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
curl -fsSL https://raw.githubusercontent.com/lucasepe/kctx/main/install.sh | bash&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Run against your current Kubernetes context:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
kctx health namespace default&lt;br&gt;
kctx explain pod &amp;lt;pod-name&amp;gt; --namespace default&lt;br&gt;
kctx trace service &amp;lt;service-name&amp;gt; --namespace default&lt;br&gt;
kctx graph pod &amp;lt;pod-name&amp;gt; --namespace default --render mermaid&lt;br&gt;
kctx dump namespace default&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or run the read-only HTTP server:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
kctx serve&lt;br&gt;
curl http://localhost:8080/health/namespace/default&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Or install the in-cluster server with Helm:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
VERSION=0.3.0&lt;br&gt;
helm upgrade --install kctx \&lt;br&gt;
  "https://github.com/lucasepe/kctx/releases/download/v${VERSION}/kctx-${VERSION}.tgz" \&lt;br&gt;
  --namespace kctx-system \&lt;br&gt;
  --create-namespace&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then:&lt;/p&gt;

&lt;p&gt;&lt;code&gt;&lt;/code&gt;&lt;code&gt;bash&lt;br&gt;
kubectl -n kctx-system port-forward svc/kctx 8080:8080&lt;br&gt;
curl http://localhost:8080/health/namespace/default&lt;br&gt;
&lt;/code&gt;&lt;code&gt;&lt;/code&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  What I am looking for
&lt;/h2&gt;

&lt;p&gt;The project is still under active development. It is useful today, but I am still hardening packaging, production deployment guidance, auth boundaries for server mode, and client compatibility around MCP/SSE.&lt;/p&gt;

&lt;p&gt;I would love feedback from SREs, platform engineers, Kubernetes operators, and people experimenting with AI-assisted operations.&lt;/p&gt;

&lt;p&gt;In particular:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Does the output feel like useful operational context?&lt;/li&gt;
&lt;li&gt;Are the signals too noisy, too sparse, or missing obvious facts?&lt;/li&gt;
&lt;li&gt;Which CRDs would be most valuable to support next?&lt;/li&gt;
&lt;li&gt;Does the JSON contract work for your scripts or internal tools?&lt;/li&gt;
&lt;li&gt;Does the MCP interface fit how you want AI agents to inspect infrastructure?&lt;/li&gt;
&lt;li&gt;Where does the install, Helm chart, or local test flow feel confusing?&lt;/li&gt;
&lt;li&gt;What would make you trust a tool like this in a production debugging workflow?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you try the MCP/SSE path, I am especially interested in:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;OS and Kubernetes/kind version&lt;/li&gt;
&lt;li&gt;AI client and version&lt;/li&gt;
&lt;li&gt;transport used: localhost, port-forward, ngrok, or internal URL&lt;/li&gt;
&lt;li&gt;whether the standalone smoke test passed&lt;/li&gt;
&lt;li&gt;whether the AI client discovered and called the tools&lt;/li&gt;
&lt;li&gt;any rough edges in the responses&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  The repo
&lt;/h2&gt;

&lt;p&gt;GitHub:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;https://github.com/lucasepe/kctx&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If this idea resonates with you, a star would help the project reach more Kubernetes and platform people.&lt;/p&gt;

&lt;p&gt;But even more useful: open an issue, tell me where the model feels wrong, or share a debugging scenario where structured context would have saved time.&lt;/p&gt;

&lt;p&gt;That is the kind of feedback that can make &lt;a href="https://github.com/lucasepe/kctx" rel="noopener noreferrer"&gt;&lt;code&gt;kctx&lt;/code&gt;&lt;/a&gt; sharper.&lt;/p&gt;

</description>
      <category>kubernetes</category>
      <category>sre</category>
      <category>opensource</category>
      <category>ai</category>
    </item>
    <item>
      <title>An opinionated way to build and maintain complex YAML documents</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Mon, 21 Mar 2022 19:56:41 +0000</pubDate>
      <link>https://dev.to/lucasepe/an-opinionated-way-to-build-and-maintain-complex-yaml-documents-3plb</link>
      <guid>https://dev.to/lucasepe/an-opinionated-way-to-build-and-maintain-complex-yaml-documents-3plb</guid>
      <description>&lt;h2&gt;
  
  
  &lt;code&gt;dirty&lt;/code&gt; - Directory to YAML
&lt;/h2&gt;

&lt;p&gt;Create YAML documents from a directory tree.&lt;/p&gt;

&lt;p&gt;Build a YAML document from a directory tree containing YAML fragments.&lt;/p&gt;

&lt;p&gt;It is useful everywhere complex YAML configuration is employed: &lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;CI pipelines &lt;/li&gt;
&lt;li&gt;Crossplane Compositions &lt;/li&gt;
&lt;li&gt;Kubernetes manifests, etc.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For instance, Kubernetes resources can be complex, and in turn make the YAML very verbose.&lt;/p&gt;

&lt;p&gt;The aim is to make the document easier to reason about and maintain.&lt;/p&gt;

&lt;h3&gt;
  
  
  How to use
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;dirty&lt;/code&gt; parses a directory tree:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;a directory is a yaml key&lt;/li&gt;
&lt;li&gt;a file (a yaml fragment) has content that is rendered at the current indentation level&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check this Crossplane Composition as example: &lt;a href="https://github.com/lucasepe/dirty/tree/main/testdata/platform-ref-aws/cluster/eks" rel="noopener noreferrer"&gt;https://github.com/lucasepe/dirty/tree/main/testdata/platform-ref-aws/cluster/eks&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here the repo link:  &lt;a href="https://github.com/lucasepe/dirty" rel="noopener noreferrer"&gt;https://github.com/lucasepe/dirty&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Regards,&lt;br&gt;
Luca&lt;/p&gt;

</description>
      <category>go</category>
      <category>yaml</category>
      <category>devops</category>
      <category>kubernetes</category>
    </item>
    <item>
      <title>Watch and react to Kubernetes objects changes</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Fri, 18 Mar 2022 12:47:11 +0000</pubDate>
      <link>https://dev.to/lucasepe/watch-and-react-to-kubernetes-objects-changes-3kcg</link>
      <guid>https://dev.to/lucasepe/watch-and-react-to-kubernetes-objects-changes-3kcg</guid>
      <description>&lt;p&gt;The Kubernetes API server exposes a REST interface consumable by any client.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kubernetes/client-go" rel="noopener noreferrer"&gt;client-go&lt;/a&gt; is the official client library for the Go programming language. It is used both internally by Kubernetes itself (for example, inside kubectl) as well as by numerous external consumers: operators, higher level frameworks and many more.&lt;/p&gt;

&lt;p&gt;Using this library you can write Go applications to access kubernetes' API Server and you can programmatically add, delete, modify, and check kubernetes resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/kubernetes/client-go" rel="noopener noreferrer"&gt;client-go&lt;/a&gt; introduces different types of clients such as: &lt;a href="https://github.com/kubernetes/client-go/blob/master/rest/client.go" rel="noopener noreferrer"&gt;RESTClient&lt;/a&gt;, &lt;a href="https://github.com/kubernetes/client-go/blob/master/kubernetes/clientset.go" rel="noopener noreferrer"&gt;Clientset&lt;/a&gt; and &lt;a href="https://github.com/kubernetes/client-go/tree/master/dynamic" rel="noopener noreferrer"&gt;dynamic.Interface&lt;/a&gt;. All these clients make available the &lt;em&gt;Watch&lt;/em&gt; verb, which offers an event interface that reacts to objects changes: add, update, delete, etc.&lt;/p&gt;

&lt;p&gt;In all cases, the returned object is an implementation of &lt;a href="https://github.com/kubernetes/apimachinery/blob/master/pkg/watch/watch.go" rel="noopener noreferrer"&gt;watch.Interface&lt;/a&gt; that looks like this:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklrze9r9vhx6suscv19p.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklrze9r9vhx6suscv19p.png" alt="watch.Interface" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let's implement a watcher for namespaces changes. The application will do these things:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;attempts to begin watching the namespaces resource getting a &lt;em&gt;watch.Interface&lt;/em&gt; on success&lt;/li&gt;
&lt;li&gt;iterates all the events produced by the watcher&lt;/li&gt;
&lt;li&gt;when an event is of type &lt;em&gt;"namespace added"&lt;/em&gt; adds a custom label patching the namespace&lt;/li&gt;
&lt;li&gt;when en event is of type &lt;em&gt;"namespace deleted"&lt;/em&gt; greet the namespace gone&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In this article I'll show you how to use &lt;a href="https://github.com/kubernetes/client-go/blob/master/rest/client.go" rel="noopener noreferrer"&gt;RESTClient&lt;/a&gt; to watch and then react to namespaces changes. &lt;/p&gt;

&lt;p&gt;Here the source code - you can grab all the code @ &lt;a href="https://github.com/lucasepe/using-client-go" rel="noopener noreferrer"&gt;https://github.com/lucasepe/using-client-go&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;


&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="s"&gt;"context"&lt;/span&gt;
  &lt;span class="s"&gt;"fmt"&lt;/span&gt;
  &lt;span class="s"&gt;"time"&lt;/span&gt;


  &lt;span class="n"&gt;corev1&lt;/span&gt; &lt;span class="s"&gt;"k8s.io/api/core/v1"&lt;/span&gt;
  &lt;span class="n"&gt;metav1&lt;/span&gt; &lt;span class="s"&gt;"k8s.io/apimachinery/pkg/apis/meta/v1"&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/apimachinery/pkg/types"&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/apimachinery/pkg/watch"&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/client-go/kubernetes/scheme"&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/client-go/rest"&lt;/span&gt;
  &lt;span class="s"&gt;"k8s.io/client-go/tools/clientcmd"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// Using the default configuration rules get the info &lt;/span&gt;
  &lt;span class="c"&gt;// to connect to the Kubernetes cluster&lt;/span&gt;
  &lt;span class="n"&gt;configLoader&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;clientcmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewNonInteractiveDeferredLoadingClientConfig&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;clientcmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDefaultClientConfigLoadingRules&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;clientcmd&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ConfigOverrides&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt;
  &lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// create the Config object&lt;/span&gt;
  &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;configLoader&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClientConfig&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// we want to use the core API (namespaces lives here)&lt;/span&gt;
  &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;APIPath&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"/api"&lt;/span&gt;
  &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GroupVersion&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;corev1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SchemeGroupVersion&lt;/span&gt;
  &lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NegotiatedSerializer&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Codecs&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithoutConversion&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

  &lt;span class="c"&gt;// create a RESTClient&lt;/span&gt;
  &lt;span class="n"&gt;rc&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rest&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;RESTClientFor&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cfg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// utility function to create a int64 pointer&lt;/span&gt;
  &lt;span class="n"&gt;i64Ptr&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="n"&gt;opts&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;metav1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ListOptions&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;TimeoutSeconds&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;i64Ptr&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;120&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;Watch&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;          &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// attempts to begin watching the namespaces&lt;/span&gt;
  &lt;span class="c"&gt;// returns a `watch.Interface`, or an error&lt;/span&gt;
  &lt;span class="n"&gt;watcher&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"namespaces"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;VersionedParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParameterCodec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Timeout&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Duration&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;opts&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TimeoutSeconds&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Watch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// the patch data, just add a custom label&lt;/span&gt;
  &lt;span class="n"&gt;pd&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;`{"metadata":{"labels":{"modified-by":"lucasepe"}}}`&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

  &lt;span class="c"&gt;// the patch type&lt;/span&gt;
  &lt;span class="n"&gt;pt&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;types&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;MergePatchType&lt;/span&gt;

  &lt;span class="c"&gt;// who did this patch?&lt;/span&gt;
  &lt;span class="n"&gt;po&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;metav1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;PatchOptions&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;FieldManager&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="s"&gt;"my-cool-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="c"&gt;// here we iterate all the events streamed by the watch.Interface&lt;/span&gt;
  &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;watcher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResultChan&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// retrieve the Namespace&lt;/span&gt;
    &lt;span class="n"&gt;item&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Object&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;corev1&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Namespace&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// when a namespace is deleted...&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Deleted&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="c"&gt;// let's say hello!&lt;/span&gt;
      &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"- '%s' %v ...bye bye&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// when a namespace is added...&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;watch&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Added&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
      &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"+ '%s' %v  "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetName&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;event&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

      &lt;span class="c"&gt;// try to patch it!&lt;/span&gt;
      &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rc&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Patch&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pt&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Resource&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"namespaces"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;item&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Name&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;VersionedParams&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;po&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;scheme&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParameterCodec&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Body&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pd&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Do&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;TODO&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
      &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;panic&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
      &lt;span class="p"&gt;}&lt;/span&gt;

      &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;" ...patched!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To see what the program does, open two terminal windows. &lt;/p&gt;

&lt;p&gt;In the first terminal run the code as usual:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go run main.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the second terminal create a namespace using &lt;code&gt;kubectl&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl create namespace demo-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In the first terminal you should see a new line like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+ 'demo-system' ADDED   ...patched!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Going back to the second terminal and typing:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ kubectl describe namespace demo-system

Name:         demo-syste
Labels:       kubernetes.io/metadata.name=demo-system
              modified-by=lucasepe
Annotations:  &amp;lt;none&amp;gt;
Status:       Active


No resource quota.


No LimitRange resource
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can see that the program added a new label to to the newly created namespace.&lt;/p&gt;

&lt;p&gt;Now deleting the namespace with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;kubectl delete namespace demo-system
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Going to the program terminal, you should see a new line:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;- 'demo-system' DELETED ...bye bye
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Using the &lt;a href="https://github.com/kubernetes/apimachinery/blob/master/pkg/watch/watch.go" rel="noopener noreferrer"&gt;watch.Interface&lt;/a&gt; interface directly is actually discouraged.&lt;/p&gt;

&lt;p&gt;For instance, since the server will close watch connections regularly, the &lt;em&gt;ResultChan&lt;/em&gt; channel can be closed at any time (due to an &lt;em&gt;io.EOF&lt;/em&gt; error).&lt;/p&gt;

&lt;p&gt;There are helpers to re-establishing a watch at the last-received &lt;em&gt;resourceVersion&lt;/em&gt;. &lt;a href="https://github.com/kubernetes/client-go/blob/master/tools/watch/retrywatcher.go" rel="noopener noreferrer"&gt;RetryWatcher&lt;/a&gt; will make sure that in case the underlying watcher is closed (e.g. due to API timeout or etcd timeout) it will get restarted from the last point without the consumer even knowing about it.&lt;/p&gt;

&lt;p&gt;But what if API server lost events because etcd erased all resource versions? &lt;/p&gt;

&lt;p&gt;In order to be resilient to etcd cache not having the resource version anymore - you would need to use Informers.&lt;/p&gt;

&lt;p&gt;If you want to discover much more about how to use the client-go library to do all kind of interaction with Kubernetes up to the step-by-step instruction about how to create a custom controller (operator) to manage your custom resource, you could eventually buy my notebook "Using client-go" here: &lt;a href="https://leanpub.com/using-client-go" rel="noopener noreferrer"&gt;https://leanpub.com/using-client-go&lt;/a&gt; - but take a peek first - download a free notebook excerpt with the TOC and some random page.&lt;/p&gt;

&lt;p&gt;Thank you for your time!&lt;/p&gt;

&lt;p&gt;All the best,&lt;/p&gt;

&lt;p&gt;Luca&lt;/p&gt;

</description>
      <category>go</category>
      <category>kubernetes</category>
      <category>clientgo</category>
      <category>cloudnative</category>
    </item>
    <item>
      <title>Craft beautiful geometric art using code.</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Fri, 01 Jan 2021 11:06:34 +0000</pubDate>
      <link>https://dev.to/lucasepe/craft-beautiful-geometric-art-using-code-8i8</link>
      <guid>https://dev.to/lucasepe/craft-beautiful-geometric-art-using-code-8i8</guid>
      <description>&lt;h1&gt;
  
  
  Craft beautiful geometric art using code.
&lt;/h1&gt;

&lt;p&gt;Use the code basics like loops, control flow and specialized functions to generate your geometry artworks.&lt;/p&gt;

&lt;h2&gt;
  
  
  Examples of g2D Geometry Art
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf6csld7lvw4qjzif40i.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fxf6csld7lvw4qjzif40i.png" width="256" height="256"&gt;&lt;/a&gt; &amp;nbsp; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fusv7rxho045e9encuh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F9fusv7rxho045e9encuh.png" width="256" height="256"&gt;&lt;/a&gt; &amp;nbsp; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfyxv7z5pl8951f8m7oh.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdfyxv7z5pl8951f8m7oh.png" width="256" height="256"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklllpbicp1l35v560the.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fklllpbicp1l35v560the.png" width="256" height="256"&gt;&lt;/a&gt; &amp;nbsp; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8bjvfsltvxwnw1nc3ea.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fq8bjvfsltvxwnw1nc3ea.png" width="256" height="256"&gt;&lt;/a&gt; &amp;nbsp; &lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk202k49lma1ebcvpk0e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Ftk202k49lma1ebcvpk0e.png" width="256" height="256"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Installation
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;a href="https://golang.org/doc/install" rel="noopener noreferrer"&gt;Go&lt;/a&gt; get
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go get &lt;span class="nt"&gt;-u&lt;/span&gt; github.com/lucasepe/g2d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Ready-To-Use Releases
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/g2d/releases/latest" rel="noopener noreferrer"&gt;Here you can find &lt;code&gt;g2d&lt;/code&gt; already compiled&lt;/a&gt; for:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;MacOS &lt;/li&gt;
&lt;li&gt;Linux &lt;/li&gt;
&lt;li&gt;Windows&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

&lt;p&gt;To execute a local &lt;code&gt;g2d&lt;/code&gt; script:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;g2d /path/to/my-script.g2d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To execute a &lt;code&gt;g2d&lt;/code&gt; script stored somewhere on the web:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;g2d http://my-cool-site.com/remote/path/to/my-script.g2d
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Use the &lt;code&gt;--directory&lt;/code&gt; (or the shorter &lt;code&gt;-d&lt;/code&gt;) flag to specify a destination folder for the generated PNG images.&lt;/p&gt;




&lt;h2&gt;
  
  
  The &lt;code&gt;g2D&lt;/code&gt; Programming Language Syntax
&lt;/h2&gt;

&lt;p&gt;Example-programs can be found beneath &lt;a href="https://github.com/lucasepe/g2d/blob/main/examples/" rel="noopener noreferrer"&gt;examples/&lt;/a&gt; which demonstrate these things, as well as parts of the standard-library.&lt;/p&gt;

&lt;h3&gt;
  
  
  Types
&lt;/h3&gt;

&lt;p&gt;g2D has the following data types: &lt;code&gt;bool&lt;/code&gt;, &lt;code&gt;int&lt;/code&gt;, &lt;code&gt;float&lt;/code&gt;, &lt;code&gt;str&lt;/code&gt;, &lt;code&gt;array&lt;/code&gt;, and &lt;code&gt;fn&lt;/code&gt;.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Type&lt;/th&gt;
&lt;th&gt;Syntax&lt;/th&gt;
&lt;th&gt;Notes&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;bool&lt;/td&gt;
&lt;td&gt;&lt;code&gt;true false&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;int&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0 42 1234 -5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;is a signed 64-bit integer&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;float&lt;/td&gt;
&lt;td&gt;&lt;code&gt;0.5 4.2 1.234 -5.5&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;is a 64-bit double-precision floating point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;str&lt;/td&gt;
&lt;td&gt;&lt;code&gt;"" "foo" "\"quotes\" and a\nline break"&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;are immutable arrays of bytes&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;array&lt;/td&gt;
&lt;td&gt;&lt;code&gt;[] [1, 2] [1, 2, 3]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;grow-able arrays (&lt;em&gt;use the &lt;code&gt;append()&lt;/code&gt; builtin&lt;/em&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;fn&lt;/td&gt;
&lt;td&gt;&lt;code&gt;fn(a, b) { ... }&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;defines a custom function&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Bindings
&lt;/h3&gt;

&lt;p&gt;Variables are bounded using the &lt;code&gt;:=&lt;/code&gt; operator.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;1.2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Variables may be integers, floats, strings, or arrays/hashes.&lt;/p&gt;

&lt;p&gt;To update a variable you can simply specify the equals &lt;code&gt;=&lt;/code&gt; operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;    &lt;span class="c"&gt;// Binding&lt;/span&gt;
&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt; &lt;span class="c"&gt;// Updating&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Arithmetic operations
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2D&lt;/code&gt; supports all the basic arithmetic operation of &lt;code&gt;int&lt;/code&gt; and &lt;code&gt;float&lt;/code&gt; types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;

&lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;
&lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;
&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;d&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Builtin containers
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2d&lt;/code&gt; has one builtin containers: &lt;code&gt;array&lt;/code&gt;.&lt;/p&gt;

&lt;h4&gt;
  
  
  Arrays
&lt;/h4&gt;

&lt;p&gt;An array is a list which organizes items by linear sequence.  Arrays can hold multiple types.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2.3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"hello!"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Hello World"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;3.13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Adding to an array is done via the &lt;code&gt;push&lt;/code&gt; builtin function:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"another"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You can iterate over the contents of an array like so:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
&lt;span class="n"&gt;while&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="s"&gt;"Array index "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" contains "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With the definition we included that produces this output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Array index 0 contains 1
Array index 1 contains 2.3
Array index 2 contains hello!
Array index 3 contains another
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Functions
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2D&lt;/code&gt; uses &lt;code&gt;fn&lt;/code&gt; to define a function which will be assigned to a variable for naming/invocation purposes:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;sum&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c"&gt;// Outputs: 8&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2.5&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="m"&gt;7.5&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c"&gt;// Outputs: 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Functions can be passed as values to others functions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;addTwo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; 
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;tot&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;addTwo&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;68&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;sum&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;            &lt;span class="c"&gt;// Outputs: 71&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Functions inside functions&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;multiplier&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;x&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;q&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="n"&gt;multThree&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;multiplier&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multThree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Outputs: 6&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multThree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;3&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Outputs: 9&lt;/span&gt;
&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;multThree&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;4&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Outputs: 12&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  If-else statements
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2D&lt;/code&gt; supports &lt;code&gt;if-else&lt;/code&gt; statements.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;)&lt;/span&gt;  &lt;span class="c"&gt;// Outputs: 2&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Switch Statements
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2D&lt;/code&gt; supports the &lt;code&gt;switch&lt;/code&gt; and &lt;code&gt;case&lt;/code&gt; expressions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;switch&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;randi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" is even"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" is odd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  While Loops
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;g2D&lt;/code&gt; supports only one looping construct, the &lt;code&gt;while&lt;/code&gt; loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;30&lt;/span&gt;
&lt;span class="n"&gt;while&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;" "&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c"&gt;// 30 20 10&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  Builtin functions
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Core
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;exit([status])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;exits the program immediately with the optional status or 0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;input([prompt]&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;reads a line from standard input optionally printing the specified prompt&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;print(...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;output a string to stdout&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;printf(pattern, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;output a string to stdout (formatted according the specified pattern)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sprintf(pattern, ...)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;like &lt;code&gt;printf(...)&lt;/code&gt; but returns a &lt;em&gt;string&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;bool(val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converts value to a bool&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;float(val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converts decimal value str to &lt;em&gt;float&lt;/em&gt; - if &lt;em&gt;val&lt;/em&gt; is invalid returns &lt;em&gt;null&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;int(val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converts decimal value str to &lt;em&gt;int&lt;/em&gt; - if &lt;em&gt;val&lt;/em&gt; is invalid returns &lt;em&gt;null&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;str(val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the string representation of &lt;em&gt;val&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;len(iterable)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the length of the iterable (&lt;em&gt;string&lt;/em&gt; or &lt;em&gt;array&lt;/em&gt;)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;append(array, val)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns a new array with value pushed onto the end of array&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Calculation
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;abs(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the absolute value of &lt;em&gt;x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;atan(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the arc tangent, in radians, of &lt;em&gt;x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;atan2(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the arc tangent of &lt;em&gt;y/x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;cos(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the cosine of the radian argument &lt;em&gt;x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;degrees(angle)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converts radians into degrees&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;hypot(p, q)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns &lt;code&gt;sqrt(p*p + q*q)&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lerp(start, stop, amt)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;calculates a number between two numbers at a specific increment&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;map(v, b1, e1, b2, e2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;re-maps a number from one range to another&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;max(v1....vn)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the largest value in a sequence of numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;min(v1....vn)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the smallest value in a sequence of numbers&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pow(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns &lt;code&gt;x**y&lt;/code&gt;, the base &lt;em&gt;x&lt;/em&gt; exponential of &lt;em&gt;y&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sin(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the sine of the radian argument &lt;em&gt;x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;sqrt(x)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the square root of &lt;em&gt;x&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;radians(angle)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;converts a degree measurement to its corresponding value in radians&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;randf([min], [max])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns a random float between min and max - by default min=0.0 and max=1.0&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;randi([min], [max])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns a random int between min and max&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Basic graphic functions
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;size(w,[h])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the size of the drawing; when both &lt;em&gt;w&lt;/em&gt; and &lt;em&gt;h&lt;/em&gt; are specified creates a rectangular image otherwise creates a squared one&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;viewport(xMin, xMax, yMin, yMax, xOffset, yOffset)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets up user-defined coordinate system; performs a screen reset (drawings are cleared)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;clear()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;fills the entire image with the current color; clear all drawings&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fillColor(hexcolor)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the fill color to the specified &lt;em&gt;hexcolor&lt;/em&gt;; example &lt;em&gt;fillColor("#ff0000")&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fillColor(r, g, b, [a])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the fill color to &lt;em&gt;r,g,b,a&lt;/em&gt; values - should be between 0 and 255, inclusive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strokeColor(hexcolor)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the stroke color to the specified &lt;em&gt;hexcolor&lt;/em&gt;; example &lt;em&gt;strokeColor("#ff0000")&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strokeColor(r, g, b, [a])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the stroke color to &lt;em&gt;r,g,b,a&lt;/em&gt; values - should be between 0 and 255, inclusive&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;strokeWeight(weight)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the stroke thickness to the specified &lt;em&gt;width&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;dashes([s1, s2, ...sn])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the current dash pattern to use (call with zero arguments to disable dashes)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;stroke()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;strokes the current path with the current stroek color and line width the path is cleared after this operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fill()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;fills the current path with the current fill color; open subpaths are implicity closed.&lt;br&gt; The path is cleared after this operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fillAndStroke()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;fills the current path with the current fill color and strokes it with the current stroke color; the path is cleared after this operation&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;push()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;saves the current state of the graphic context by pushing it onto a stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;pop()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;restores the last saved graphic context state from the stack&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;snapshot([filename])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;creates a PNG image with the current drawings. &lt;br&gt;If &lt;em&gt;filename&lt;/em&gt; is omitted, it will be autogenerated with a progressive counter, that will be incremented on each &lt;br&gt; &lt;code&gt;snapshot()&lt;/code&gt; invocation; this is useful if you wants to generate an animation later (using all the generated PNG images).&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;xpos()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the current X position (if there is a current point)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ypos()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the current Y position (if there is a current point)&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Graphic primitives
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arc(x, y, r, sa, ea)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a circular arc centered at &lt;em&gt;(x, y)&lt;/em&gt; with a radius of &lt;em&gt;r&lt;/em&gt;.&lt;br&gt; The path starts at &lt;em&gt;sa&lt;/em&gt; angle_, ends at &lt;em&gt;ea&lt;/em&gt; angle, and travels in the direction given by anticlockwise&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;circle(x, y, r)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a circle centered at &lt;em&gt;[x, y]&lt;/em&gt; coordinates and with the radius &lt;em&gt;r&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;ellipse(x, y, rx ,ry)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws an ellipse centered at [x, y] coordinates and with the radii &lt;em&gt;rx&lt;/em&gt; and &lt;em&gt;ry&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;line(x1, y1, x2, y2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a line from point &lt;em&gt;(x1, y1)&lt;/em&gt; to point &lt;em&gt;(x2, y2)&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;point(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a point at specified coordinates (the size is equal to the stroke weight)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;quad(x1, y1, x2,y2, x3,y3, x4,y4)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a a four sided polygon using the provided vertices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rect(x, y, w, h, [tl, tr, br, bl])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a (w x h) rectangle with upper left corner located at &lt;em&gt;(x, y)&lt;/em&gt;.&lt;br&gt; If only one radius is specified, all the corners have the same bending, if &lt;em&gt;tl&lt;/em&gt;, &lt;em&gt;tr&lt;/em&gt;, &lt;em&gt;br&lt;/em&gt;, &lt;em&gt;bl&lt;/em&gt; are specified, each corner can have a different curvature&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;triangle(x1,y1, x2,y2, x3,y3)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a triangle using the provided vertices&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;star(cx, cy, n, or, ir)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws a star &lt;em&gt;cx&lt;/em&gt;, &lt;em&gt;cy&lt;/em&gt; is the center, &lt;em&gt;n&lt;/em&gt; the number of spikes, &lt;em&gt;or&lt;/em&gt; and &lt;em&gt;ir&lt;/em&gt; the outer and inner radius&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Paths
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;beginPath()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;starts a new path&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;closePath()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;adds a line segment from the current point to the beginning of the current subpath&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;moveTo(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the begin of a new subpath starting at the specified &lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt; point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;lineTo(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;adds a line segment to the current path starting at the current point&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;arcTo(x1, y1, x2, y2, r)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;adds a circular arc to the current sub-path, using the given control points and radius&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;quadraticCurveTo(x1, y1, x2, y2)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;adds a quadratic Bézier curve to the current sub-path; &lt;em&gt;x1&lt;/em&gt;, &lt;em&gt;y1&lt;/em&gt; is the control point and &lt;em&gt;x2&lt;/em&gt;, &lt;em&gt;y2&lt;/em&gt; is the end point&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Transform
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;rotate(angle, [x, y] )&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;updates the current matrix with a anticlockwise rotation; when &lt;em&gt;x, y&lt;/em&gt; are specified, rotation occurs about this point, otherwise rotation occurs about the origin (&lt;em&gt;angle&lt;/em&gt; is in radians)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;scale(sx, sy, [x, y])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;updates the current matrix with &lt;em&gt;sx&lt;/em&gt;, &lt;em&gt;sy&lt;/em&gt; scaling factor; when &lt;em&gt;x&lt;/em&gt;,&lt;em&gt;y&lt;/em&gt; are specified, scaling occurs about this point, otherwise scaling occurs about origin.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;translate(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;updates the current matrix with a translation to &lt;em&gt;x&lt;/em&gt; and &lt;em&gt;y&lt;/em&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;identity()&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;resets the current transformation matrix to the identity matrix&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;transform(x, y)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;multiplies the point &lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt; by the current matrix, returning a transformed position&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Text
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;text(str, x, y, [ax, ay])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws the specified text &lt;em&gt;str&lt;/em&gt; at the specified anchor point &lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt;; the anchor point is &lt;em&gt;x - w * ax&lt;/em&gt;, &lt;em&gt;y - h * ay&lt;/em&gt;, where &lt;em&gt;w&lt;/em&gt;, &lt;em&gt;h&lt;/em&gt; is the size of the text (by default &lt;em&gt;ax=0.5&lt;/em&gt;, &lt;em&gt;ay=0.5&lt;/em&gt; to center the text at the specified point)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;textWidth(str)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;returns the rendered width of the specified text &lt;em&gt;str&lt;/em&gt; given the current font face&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;fontSize(size)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;sets the font height&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

&lt;h3&gt;
  
  
  Images
&lt;/h3&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Function&lt;/th&gt;
&lt;th&gt;Description&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imageGet(path/to/png)&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;loads a PNG image from the local filesystem&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&lt;code&gt;imageAt(im, x, y, [ax, ay])&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;draws the specified image &lt;em&gt;im&lt;/em&gt; at the specified anchor point &lt;em&gt;x&lt;/em&gt;, &lt;em&gt;y&lt;/em&gt;; (&lt;em&gt;ax&lt;/em&gt; and &lt;em&gt;ay&lt;/em&gt; are the x and y offsets) use ax=0.5, ay=0.5 to center the image at the specified point&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;

</description>
      <category>generative</category>
      <category>geometric</category>
      <category>art</category>
      <category>coding</category>
    </item>
    <item>
      <title>Create (not just) diagrams stitching images on a grid using HCL (like terraform!)</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Sun, 09 Aug 2020 06:25:25 +0000</pubDate>
      <link>https://dev.to/lucasepe/create-not-just-diagrams-stitching-images-on-a-grid-using-hcl-like-terraform-1hb3</link>
      <guid>https://dev.to/lucasepe/create-not-just-diagrams-stitching-images-on-a-grid-using-hcl-like-terraform-1hb3</guid>
      <description>&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;   _           _   _
  |_|_ _ _____| |_| |___     
  | | | |     | . | | -_|   
 _| |___|_|_|_|___|_|___|            
|___|
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/lucasepe/jumble" rel="noopener noreferrer"&gt;https://github.com/lucasepe/jumble&lt;/a&gt;&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Create (not just) diagrams stitching, connecting  and labelling &lt;br&gt;
images on a grid using HCL syntax (like terraform!).&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;515 Embedded cloud architecture icons! Ready to use!&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;225 AWS icons (uri = assets://aws_[KIND])&lt;/li&gt;
&lt;li&gt;182 Azure icons (uri = assets://azure_[KIND])&lt;/li&gt;
&lt;li&gt;108 Google Cloud icons (uri = assets://google_[KIND])
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight hcl"&gt;&lt;code&gt;&lt;span class="c1"&gt;# AWS Lambda Authorizer&lt;/span&gt;
&lt;span class="nx"&gt;tile&lt;/span&gt; &lt;span class="s2"&gt;"icon"&lt;/span&gt; &lt;span class="s2"&gt;"lambda1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;row&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${subtract(row("&lt;/span&gt;&lt;span class="nx"&gt;agw&lt;/span&gt;&lt;span class="s2"&gt;"), 1)}"&lt;/span&gt;
    &lt;span class="nx"&gt;col&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"${subtract(col("&lt;/span&gt;&lt;span class="nx"&gt;agw&lt;/span&gt;&lt;span class="s2"&gt;"), 2)}"&lt;/span&gt;
    &lt;span class="nx"&gt;uri&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s2"&gt;"assets://aws_lambda"&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;or you can use your local icons (uri = /path/to/my/ic.png)&lt;/li&gt;
&lt;li&gt;or you can use remote icons (uri = &lt;a href="http://a.domain.com/img/ic.png" rel="noopener noreferrer"&gt;http://a.domain.com/img/ic.png&lt;/a&gt;)&lt;/li&gt;
&lt;/ul&gt;

</description>
      <category>go</category>
      <category>hcl</category>
      <category>cloud</category>
      <category>diagrams</category>
    </item>
    <item>
      <title>A commandline tool that generate High Level microservice &amp; serverless Architecture diagrams</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Sat, 06 Jun 2020 07:14:43 +0000</pubDate>
      <link>https://dev.to/lucasepe/a-commandline-tool-that-generate-high-level-microservice-serverless-architecture-diagrams-40hp</link>
      <guid>https://dev.to/lucasepe/a-commandline-tool-that-generate-high-level-microservice-serverless-architecture-diagrams-40hp</guid>
      <description>&lt;p&gt;A commandline tool that generate High Level microservice &amp;amp; serverless Architecture diagrams using a declarative syntax defined in a YAML file.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/lucasepe/draft" rel="noopener noreferrer"&gt;https://github.com/lucasepe/draft&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Why?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;to quickly scketch HL Arks 

&lt;ul&gt;
&lt;li&gt; to change the diagrams without pain (point, click drag..etc.)&lt;/li&gt;
&lt;li&gt; to share diagrams using just a plain YAML file&lt;/li&gt;
&lt;li&gt; the "terminal" is my playground :-D&lt;/li&gt;
&lt;li&gt; but..above all..to do something funny and relaxing in Go! &lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Please check it out and let me know what do you think!&lt;/p&gt;

&lt;p&gt;All the best,&lt;br&gt;
Luca&lt;/p&gt;

</description>
      <category>go</category>
      <category>architecture</category>
      <category>design</category>
      <category>microservices</category>
    </item>
    <item>
      <title>Maps in Go</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Sat, 30 May 2020 07:35:50 +0000</pubDate>
      <link>https://dev.to/lucasepe/maps-in-go-4eg1</link>
      <guid>https://dev.to/lucasepe/maps-in-go-4eg1</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/23e0659acf1c4208893651dd3bbfd0f7"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
    <item>
      <title>Slices in Go</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Wed, 27 May 2020 16:56:13 +0000</pubDate>
      <link>https://dev.to/lucasepe/slices-in-go-5cdg</link>
      <guid>https://dev.to/lucasepe/slices-in-go-5cdg</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/20326b1317994426848ebe53166aa499"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
    <item>
      <title>A Simple Overview of Arrays in Go</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Tue, 26 May 2020 16:34:39 +0000</pubDate>
      <link>https://dev.to/lucasepe/a-simple-overview-of-arrays-in-go-314h</link>
      <guid>https://dev.to/lucasepe/a-simple-overview-of-arrays-in-go-314h</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/4c5ff8f22e014eba943e1d7abd9b7c61"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
    <item>
      <title>Pointers in Go</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Tue, 26 May 2020 06:37:46 +0000</pubDate>
      <link>https://dev.to/lucasepe/pointers-in-go-2g3l</link>
      <guid>https://dev.to/lucasepe/pointers-in-go-2g3l</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/368a1937220842098448a24bcd60414e"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
    <item>
      <title>Structs types in Go</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Sat, 23 May 2020 15:53:02 +0000</pubDate>
      <link>https://dev.to/lucasepe/structs-types-in-go-14ld</link>
      <guid>https://dev.to/lucasepe/structs-types-in-go-14ld</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/ea262b447bb84aeaa71ec5258fea4cfe"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
    <item>
      <title>Constant and Variables</title>
      <dc:creator>Luca Sepe</dc:creator>
      <pubDate>Sat, 23 May 2020 15:50:47 +0000</pubDate>
      <link>https://dev.to/lucasepe/constant-and-variables-m48</link>
      <guid>https://dev.to/lucasepe/constant-and-variables-m48</guid>
      <description>&lt;p&gt;&lt;iframe class="speakerdeck-iframe ltag_speakerdeck" src="https://speakerdeck.com/player/c680fa45fe7e498d88e4245b287ac06b"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>learning</category>
      <category>go</category>
      <category>coding</category>
      <category>language</category>
    </item>
  </channel>
</rss>
