<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0"><channel><title><![CDATA[Kai Siren's Blog]]></title><description><![CDATA[⚙⚒ lights out, platform's green, agents are working the line ⚒⚙]]></description><link>https://coilysiren.me</link><generator>GatsbyJS</generator><lastBuildDate>Fri, 24 Jul 2026 10:16:33 GMT</lastBuildDate><author><![CDATA[@coilysiren]]></author><item><title><![CDATA[Stochastic Design Iteration]]></title><description><![CDATA[A pattern for co-authoring a markdown design doc with an LLM: the human is the static guiding force, the LLM is the stochastic writer, and the artifact gets sharpened across many small passes into something more pure and specific than the human would have written alone.]]></description><link>https://coilysiren.me/posts/stochastic-design-iteration/</link><guid isPermaLink="false">https://coilysiren.me/posts/stochastic-design-iteration/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Sun, 19 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;There&apos;s a collaboration pattern I&apos;ve been leaning on. A single human author with strong underlying intent pairs with an LLM to co-author a markdown design doc. Across many small passes, the doc gets sharpened. It drifts toward a form that&apos;s more pure and more specific, a more refined representation of what the author meant in the first place. I call it &lt;strong&gt;stochastic design iteration&lt;/strong&gt;.&lt;/p&gt;
&lt;h2&gt;Human collaboration and machine collaboration operate at different wavelengths&lt;/h2&gt;
&lt;p&gt;Human design review has a long wavelength. You send somebody a doc, they sit with it for a day or two, they come back with a handful of notes that each pack real judgment. Good for sanity checks, calibration against someone else&apos;s taste, catching the drift you can&apos;t see yourself. Bad for working through the fifteen slightly-different shapes a section could take.&lt;/p&gt;
&lt;p&gt;LLM collaboration has a short wavelength. You can ask for five rewrites of a paragraph in the next ninety seconds, compare them, keep the best phrase from each, splice them together, and rewrite again. The LLM has no ego about its phrasing and no strong opinions about which framing to prefer. That sounds like a weakness. You won&apos;t get a &quot;this whole section is the wrong idea&quot; push like you would from a trusted reviewer. But for the drift-toward-refinement case the lack of strong opinions is exactly the property you want. The LLM is willing to keep generating.&lt;/p&gt;
&lt;p&gt;The two modes are complementary, not substitutable. Human review layers on top of a doc that&apos;s already been through many stochastic passes. The stochastic passes do the grinding that human review shouldn&apos;t have to do. The pattern I&apos;m describing here is specifically about the short-wavelength half.&lt;/p&gt;
&lt;h2&gt;The LLM is the stochastic one. The human is the static guiding force&lt;/h2&gt;
&lt;p&gt;In this pattern the LLM does the writing. It proposes language, shape, section boundaries, alternative framings. It generates variance. On any given pass, what it produces is partly what you asked for and partly a random draw from the latent space near your prompt.&lt;/p&gt;
&lt;p&gt;The human&apos;s job is not to write. The human&apos;s job is to hold the intent steady while the LLM produces variations, then to accept, reject, redirect, and recombine. You&apos;re a filter on the LLM&apos;s distribution. Over many passes, the artifact gets purified. The sections that drift off-intent get caught and corrected. The sections that drift toward a sharper phrasing than you had get kept. What stays is the residue of many filtered drafts.&lt;/p&gt;
&lt;p&gt;The LLM&apos;s propensity to hallucinate is not a bug in this pattern. It&apos;s load-bearing. A fresh random assertion in the middle of a section you thought was settled forces you to ask &quot;wait, is that true? is that what I meant? would the reader read it that way?&quot; The doc gets put under disruptive pressure that the human is responsible for correcting, and the act of correcting it refines the surrounding material at the same time. A model that only ever paraphrased your input would grind out nothing. There&apos;d be no perturbation to push back against. The stochastic noise is the mechanism.&lt;/p&gt;
&lt;p&gt;If you don&apos;t have strong ideas, the output will be slop. But the output would have been slop without an LLM too. The pattern doesn&apos;t invent signal where none exists. Human intent, focus, and strategy stay load-bearing. The LLM creates no ideas of its own. It sharpens the ones you bring.&lt;/p&gt;
&lt;h2&gt;Affinity with ADHD&lt;/h2&gt;
&lt;p&gt;The iteration style has, for me, a strong affinity with ADHD. It&apos;s very easy to start a cycle: edit a section, ask the LLM for variants, skim the variants, pick one, move on. The friction is low enough that starting another cycle later feels like nothing, too. Between cycles, both parties (the human and the LLM) routinely lose the tactical direction. You&apos;ll come back an hour later and not remember why this section was framed the way it was. The LLM has no memory of it either.&lt;/p&gt;
&lt;p&gt;That loss is actually the feature. Losing tactical forces you back up to strategic. When you re-enter the cycle cold, the only thing you have to orient to is the intent of the doc, not the micro-decisions of the last edit. The strategic layer is what gets reinforced by the forgetting. The micro-decisions that were worth keeping will regenerate under pressure from the strategic frame. The ones that weren&apos;t just quietly don&apos;t come back. This is the opposite of how a long-session human collaboration goes, where tactical memory accumulates and starts overdetermining the structure.&lt;/p&gt;
&lt;h2&gt;What this pattern opens up&lt;/h2&gt;
&lt;p&gt;Historically, single-voice design-doc quality took decades of solo focus from one unusually disciplined author. Think of long-stewarded open-source projects like Salvatore Sanfilippo&apos;s &lt;a href=&quot;https://github.com/redis/redis&quot;&gt;Redis&lt;/a&gt;, Daniel Stenberg&apos;s &lt;a href=&quot;https://github.com/curl/curl&quot;&gt;curl&lt;/a&gt;, or Yukihiro Matsumoto&apos;s &lt;a href=&quot;https://github.com/ruby/ruby&quot;&gt;Ruby&lt;/a&gt;. Stochastic design iteration short-circuits that. Docs I&apos;ve produced this way are at a quality level I could not have reached on my own, through any amount of solo effort. The pattern doesn&apos;t make me a better writer. It makes the marathon of iteration tractable, so the quality I could always aim for actually lands on the page. The class of people who can now produce this caliber of writing is much larger than it was.&lt;/p&gt;
&lt;h2&gt;A concrete example from LUCA&lt;/h2&gt;
&lt;p&gt;I&apos;ve been designing a project called LUCA (a prototype of an agent-driven &quot;dark factory&quot; for building small platforms) this way. One section went through three visible passes over about a week, each answering the same question: &quot;how do we harden our built application?&quot;&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;&lt;strong&gt;Pass 1: hand wave.&lt;/strong&gt; A &lt;strong&gt;Worker&lt;/strong&gt; sub-agent builds, and then an &lt;strong&gt;Attacker&lt;/strong&gt; sub-agent attacks.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pass 2: hard cap.&lt;/strong&gt; Worker builds and Attacker attacks alternate in cycles, capped at 4 total cycles, then the orchestrator halts. The finer question of how to interleave (attack on every merge vs. attack after N merges) gets deferred.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pass 3: release-candidate orchestration.&lt;/strong&gt; A separate &lt;strong&gt;ReleaseOrchestrator&lt;/strong&gt; sub-agent cuts release candidates on a trigger and runs each one through the Gauntlet triple exactly once: &lt;strong&gt;Attacker&lt;/strong&gt; proposes attack plans, &lt;strong&gt;Inspector&lt;/strong&gt; sharpens them, &lt;strong&gt;HoldoutEvaluator&lt;/strong&gt; judges against hidden invariants the Worker never sees. Failing scenarios commit back into the test set as permanent constraints.&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;The underlying intent never changed across the three passes. The mechanism got progressively more refined: a hand-wave, then a hard cap, then an architecture where the failure mode can&apos;t recur in the shape the cap was there to prevent. The third version is the one I meant the whole time. I just couldn&apos;t express it with sufficient detail on the first pass.&lt;/p&gt;
&lt;h2&gt;Nearby patterns this is not quite&lt;/h2&gt;
&lt;p&gt;A few named things sit in the neighborhood and are worth distinguishing from:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Prompt engineering.&lt;/strong&gt; Refining a prompt so a single LLM call produces a better single output. Stochastic design iteration refines the doc, not the prompt. Prompts are disposable scratch.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Agentic writing.&lt;/strong&gt; An LLM autonomously edits a doc across many passes with minimal human intervention. The human sets a goal and the agent drives until it thinks it&apos;s done. Stochastic design iteration is the opposite polarity: the human is in every loop, and the human&apos;s filtering is what makes the thing converge.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Pair programming.&lt;/strong&gt; Two humans, real-time, one driving. The output artifact ends up somewhere in the middle between the two humans. In the majority of cases this is good for refining an existing artifact, but doing it with an incomplete idea can disrupt the intent to such an extent that it can&apos;t even form a solid shape.&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;What makes it &quot;iteration&quot; rather than &quot;prompting&quot;&lt;/h2&gt;
&lt;p&gt;The difference is that the doc is the durable artifact and the prompts are disposable. A prompt-engineering loop treats the prompt as the thing being refined. A stochastic-design-iteration loop treats the doc as the thing being refined, and each prompt is a local tool for shifting one section&apos;s center of mass. Over a month of passes, you don&apos;t have a repo full of prompts. You have a much better doc, and the prompts that produced it are gone.&lt;/p&gt;
&lt;p&gt;The doc that comes out the other side might be closer to what the author meant than anything they&apos;d have written alone. If it is, it&apos;s because the process helped the human keep up the marathon: round after round after round of edits that no solo writer would have had the stamina for. The LLM&apos;s low-friction short-wavelength cycle is what makes that marathon tractable. The human&apos;s unyielding intent is what points the cycle somewhere worth going.&lt;/p&gt;
&lt;h2&gt;An example prompt&lt;/h2&gt;
&lt;p&gt;The prompt has to be intentionally vague. You&apos;re not telling the LLM what to write. You&apos;re pointing it at a wide area of the doc and asking it to surface things. The narrower the prompt, the less variance you get, and variance is the whole reason you&apos;re running this loop.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Perform stochastic design iteration on &amp;#x3C; some document &gt;. I have run this prompt a few times - you intentionally have no memory of previous rounds.&lt;/p&gt;
&lt;p&gt;Pick any set of sections or components you think would benefit from another pass - you decide how many, you decide which. For each, propose a meaningful change: rename, rewrite, down-scope, expand, retire, whatever makes sense.&lt;/p&gt;
&lt;p&gt;Be specific and tactical. Your goal is to move the needle in a very particular way, and you decide which way that is. I&apos;ll reject most of what you return. The small fraction that lands is the point.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;A few things to notice.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;You decide how many, you decide which.&quot;&lt;/strong&gt; If I pick the sections, I&apos;ve pre-filtered the proposals to match my current mental model, which is exactly the thing I&apos;m trying to disrupt. Delegating scope makes the model responsible for noticing what I wouldn&apos;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;Whatever makes sense.&quot;&lt;/strong&gt; The trailing phrase is intentional. The shape of the list tells the LLM that unnamed moves are welcome, and it sometimes comes back with one I wouldn&apos;t have named.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;You intentionally have no memory of previous rounds.&quot;&lt;/strong&gt; This is load-bearing. A long-running session drifts along whatever gradient the human has been pulling on. Fresh context forces the LLM to re-read the doc cold and propose from there. The doc accumulates the iteration history. The conversation doesn&apos;t.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;&quot;Be specific and tactical. You decide which way.&quot;&lt;/strong&gt; This is the move that activates the stochastic part. A model asked for &quot;improvements&quot; defaults to paraphrase. It&apos;s the safe answer. Forcing it to commit to a direction, and to own the choice, is what produces actual departures for the human to filter.&lt;/p&gt;
&lt;h2&gt;In summary&lt;/h2&gt;
&lt;p&gt;Stochastic design iteration is not a thing the LLM does for you. It&apos;s a thing you do with an LLM, on purpose, round after round, until the intent you started with is actually on the page.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[3 Cloud Standoff: IAM Across AWS, GCP, and Azure]]></title><description><![CDATA[A practical mapping of identity fundamentals across AWS, GCP, and Azure. What the words mean in each cloud, and where the mental models diverge.]]></description><link>https://coilysiren.me/posts/3-cloud-standoff/</link><guid isPermaLink="false">https://coilysiren.me/posts/3-cloud-standoff/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Mon, 13 Apr 2026 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The hardest part of moving between clouds isn&apos;t the compute or the networking. It&apos;s figuring out what &quot;identity&quot; even means in a given ecosystem. Maybe your company acquired something that runs on GCP. Maybe the data science team got a budget for Azure OpenAI. Maybe you&apos;re just tired of AWS. Either way, you have to relearn IAM from scratch, and the vocabulary is a minefield.&lt;/p&gt;
&lt;p&gt;This post maps the three clouds against each other. I&apos;ll walk through each cloud&apos;s identity fundamentals, then line them up adjacent to each other, and finally call out the places where the mental models genuinely diverge (as opposed to just using different words for the same thing).&lt;/p&gt;
&lt;p&gt;This post assumes you already understand IAM in at least one cloud. If you don&apos;t, start with &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html&quot;&gt;the AWS IAM docs&lt;/a&gt;. They&apos;re the most thorough and the concepts transfer reasonably well.&lt;/p&gt;
&lt;h2&gt;The fundamentals, by cloud&lt;/h2&gt;
&lt;h3&gt;AWS&lt;/h3&gt;
&lt;p&gt;AWS has the oldest and most-copied identity model, so it&apos;s a reasonable starting point.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;IAM User&lt;/strong&gt;. A long-lived identity, usually with an access key ID and secret access key. Meant for humans before SSO existed, and for machines that live outside AWS. Today, best practice is to have as few of these as possible.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Role&lt;/strong&gt;. An identity with &lt;em&gt;no&lt;/em&gt; long-lived credentials. You &lt;em&gt;assume&lt;/em&gt; a role via STS (&lt;code class=&quot;language-text&quot;&gt;sts:AssumeRole&lt;/code&gt;), which hands you back temporary credentials (typically valid for one hour). Roles have a &lt;em&gt;trust policy&lt;/em&gt; that says who&apos;s allowed to assume them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Group&lt;/strong&gt;. A bag of users, used only for attaching policies. Groups are not identities; you can&apos;t &quot;log in as&quot; a group.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Instance Profile&lt;/strong&gt;. A wrapper around a role that lets an EC2 instance use it. The EC2 metadata service (IMDS) hands out temporary credentials based on the attached instance profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Policy&lt;/strong&gt;. The permission document itself. Attached to users, groups, roles, or (for some services) to resources directly.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Identity Center&lt;/strong&gt; (formerly AWS SSO). The modern way to give humans access. It federates from an external IdP and vends short-lived role sessions.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The basic AWS idea: &lt;strong&gt;roles are portable identities that nothing owns&lt;/strong&gt;. An EC2 instance, a Lambda function, a pod in EKS, and a user from another AWS account can all assume the same role.&lt;/p&gt;
&lt;h3&gt;GCP&lt;/h3&gt;
&lt;p&gt;GCP&apos;s identity model looks superficially similar to AWS, but the center of gravity is in a totally different place.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;Google Account / Workspace User&lt;/strong&gt;. A human identity, managed entirely outside your GCP project (in Google Workspace or Cloud Identity). You can&apos;t create one &quot;inside&quot; a project the way you create an IAM user in AWS.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Account&lt;/strong&gt;. GCP&apos;s machine identity. This is the one that trips people up, because a service account is simultaneously:
&lt;ol&gt;
&lt;li&gt;An &lt;em&gt;identity&lt;/em&gt; (it has an email like &lt;code class=&quot;language-text&quot;&gt;my-sa@my-project.iam.gserviceaccount.com&lt;/code&gt; and can be granted roles on resources), and&lt;/li&gt;
&lt;li&gt;A &lt;em&gt;resource&lt;/em&gt; (you can be granted roles &lt;em&gt;on&lt;/em&gt; the service account itself, such as &lt;code class=&quot;language-text&quot;&gt;roles/iam.serviceAccountTokenCreator&lt;/code&gt; to impersonate it).&lt;/li&gt;
&lt;/ol&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Google Group&lt;/strong&gt;. A bag of users. Same idea as AWS IAM groups, but managed in Workspace rather than in GCP itself.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Role&lt;/strong&gt;. In GCP, a &quot;role&quot; is &lt;em&gt;not&lt;/em&gt; an identity. It&apos;s a collection of permissions (what AWS would call a managed policy). Roles come in three flavors: basic (Owner/Editor/Viewer, avoid these), predefined (per-service, curated by Google), and custom.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;IAM Binding / Allow Policy&lt;/strong&gt;. The grant itself. On each resource, there&apos;s an &quot;allow policy&quot; that says &quot;principal X has role Y on this resource.&quot; This is the opposite direction from AWS, where policies are usually attached to the principal.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Workload Identity Federation&lt;/strong&gt;. Lets external identities (like a GitHub Actions OIDC token or an AWS IAM role) act as a GCP service account without a long-lived JSON key.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The basic GCP idea: &lt;strong&gt;permissions are granted on resources, not on principals&lt;/strong&gt;. You walk up to a resource and say &quot;who can do what here.&quot; That&apos;s the opposite of AWS, where you walk up to a principal and ask &quot;what can this identity do.&quot;&lt;/p&gt;
&lt;h3&gt;Azure&lt;/h3&gt;
&lt;p&gt;Azure has the most confusing vocabulary of the three, largely because the identity layer (Entra ID, formerly Azure AD) and the resource layer (Azure Resource Manager) were duct taped together later.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;User&lt;/strong&gt;. A human identity in an Entra ID tenant. Managed at the tenant level, not the subscription level.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;App Registration&lt;/strong&gt;. The &lt;em&gt;definition&lt;/em&gt; of an application in Entra ID. It lives in the tenant where the app was created (&quot;home tenant&quot;) and describes the app&apos;s identity, permissions, and secrets. This is just a blueprint, it&apos;s not the thing that actually signs in.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Service Principal&lt;/strong&gt;. The &lt;em&gt;instance&lt;/em&gt; of an app registration in a given tenant. The service principal is what actually gets assigned permissions and signs in. If you see the Azure portal distinguish between &quot;App registrations&quot; and &quot;Enterprise applications,&quot; that&apos;s this split: app registrations are definitions, enterprise applications are service principals.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Managed Identity&lt;/strong&gt;. A service principal whose credentials are managed entirely by Azure. You never see a secret. Comes in two flavors: &lt;em&gt;system-assigned&lt;/em&gt; (tied 1:1 to the lifecycle of a single Azure resource) and &lt;em&gt;user-assigned&lt;/em&gt; (a standalone resource you can attach to multiple things).&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure RBAC Role&lt;/strong&gt;. Like GCP, this is a permission set, not an identity. Comes as built-in roles (curated by Microsoft) or custom roles.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Role Assignment&lt;/strong&gt;. The three-tuple of &lt;code class=&quot;language-text&quot;&gt;(principal, role, scope)&lt;/code&gt; that actually grants access. Scope can be management group, subscription, resource group, or individual resource.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The basic Azure idea: &lt;strong&gt;identity and resource access are two separate systems stitched together by role assignments&lt;/strong&gt;. The identity lives in Entra ID; the thing it&apos;s allowed to do lives in Azure RBAC; the role assignment is the bridge.&lt;/p&gt;
&lt;h2&gt;The adjacent view&lt;/h2&gt;
&lt;p&gt;Here&apos;s the side-by-side mapping. Rows are concepts; cells are the closest equivalent in each cloud.&lt;/p&gt;
&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Concept&lt;/th&gt;
&lt;th&gt;AWS&lt;/th&gt;
&lt;th&gt;GCP&lt;/th&gt;
&lt;th&gt;Azure&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Human identity&lt;/td&gt;
&lt;td&gt;IAM User &lt;em&gt;or&lt;/em&gt; Identity Center user&lt;/td&gt;
&lt;td&gt;Google / Workspace account&lt;/td&gt;
&lt;td&gt;Entra ID user&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Grouping of humans&lt;/td&gt;
&lt;td&gt;IAM Group&lt;/td&gt;
&lt;td&gt;Google Group&lt;/td&gt;
&lt;td&gt;Entra ID security group&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Long-lived machine identity&lt;/td&gt;
&lt;td&gt;IAM User with access keys&lt;/td&gt;
&lt;td&gt;Service Account with JSON key&lt;/td&gt;
&lt;td&gt;Service Principal with client secret or certificate&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Credential-less workload identity&lt;/td&gt;
&lt;td&gt;IAM Role (via instance profile, IRSA, etc.)&lt;/td&gt;
&lt;td&gt;Service Account attached to a workload&lt;/td&gt;
&lt;td&gt;Managed Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permission set / definition&lt;/td&gt;
&lt;td&gt;Managed or inline IAM policy&lt;/td&gt;
&lt;td&gt;IAM Role (predefined or custom)&lt;/td&gt;
&lt;td&gt;Azure RBAC role definition&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Permission grant&lt;/td&gt;
&lt;td&gt;Policy attached to principal (or resource)&lt;/td&gt;
&lt;td&gt;IAM binding on a resource&lt;/td&gt;
&lt;td&gt;Role assignment &lt;code class=&quot;language-text&quot;&gt;(principal, role, scope)&lt;/code&gt;&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;&quot;Assume another identity&quot;&lt;/td&gt;
&lt;td&gt;&lt;code class=&quot;language-text&quot;&gt;sts:AssumeRole&lt;/code&gt;&lt;/td&gt;
&lt;td&gt;Service account impersonation&lt;/td&gt;
&lt;td&gt;No direct equivalent (see below)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Federation from external IdP&lt;/td&gt;
&lt;td&gt;IAM Identity Center, SAML, OIDC provider&lt;/td&gt;
&lt;td&gt;Workload Identity Federation&lt;/td&gt;
&lt;td&gt;Entra ID external federation / B2B&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Temporary credentials source&lt;/td&gt;
&lt;td&gt;STS&lt;/td&gt;
&lt;td&gt;Metadata server (OAuth2 access tokens)&lt;/td&gt;
&lt;td&gt;IMDS (bearer tokens)&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Kubernetes workload identity&lt;/td&gt;
&lt;td&gt;IRSA or EKS Pod Identity&lt;/td&gt;
&lt;td&gt;GKE Workload Identity&lt;/td&gt;
&lt;td&gt;Entra Workload Identity&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Cross-boundary access&lt;/td&gt;
&lt;td&gt;Role trust policy allowing external account&lt;/td&gt;
&lt;td&gt;Grant role to principal from another project&lt;/td&gt;
&lt;td&gt;Guest users or multi-tenant app registrations&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;
&lt;h2&gt;Where the mental models actually diverge&lt;/h2&gt;
&lt;p&gt;The table above makes things look tidier than they are. If you&apos;re going to get tripped up, it&apos;ll be on one of the following.&lt;/p&gt;
&lt;h3&gt;1. Which direction do permissions flow?&lt;/h3&gt;
&lt;p&gt;This is the biggest one.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS&lt;/strong&gt;: Policies mostly attach to the &lt;em&gt;principal&lt;/em&gt;. &quot;This user / role can do X, Y, Z across these resources.&quot; Resource-based policies (S3 bucket policies, KMS key policies, etc.) exist as an escape hatch, but the default direction is principal-first.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GCP&lt;/strong&gt;: Bindings attach to the &lt;em&gt;resource&lt;/em&gt;. Every resource has an allow policy listing which principals have which roles. You almost never &quot;look up what a service account can do&quot; as a top-level operation. You look up resources and see who&apos;s on them.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure&lt;/strong&gt;: Role assignments are a three-tuple stored in the subscription. You can query them by principal, by role, or by scope with roughly equal effort. In practice, most teams think about them resource-first, like GCP.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Why this matters: your mental debugging process is different. In AWS, &quot;why can&apos;t this thing do X?&quot; usually starts with &lt;code class=&quot;language-text&quot;&gt;aws iam get-role-policy&lt;/code&gt;. In GCP, it usually starts with &lt;code class=&quot;language-text&quot;&gt;gcloud projects get-iam-policy&lt;/code&gt; on the &lt;em&gt;target&lt;/em&gt; resource. In Azure, it&apos;s &lt;code class=&quot;language-text&quot;&gt;az role assignment list --assignee &amp;lt;principal&gt;&lt;/code&gt; or &lt;code class=&quot;language-text&quot;&gt;--scope &amp;lt;resource&gt;&lt;/code&gt;.&lt;/p&gt;
&lt;h3&gt;2. Is the machine identity an &quot;it&quot; or a &quot;thing&quot;?&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS IAM roles&lt;/strong&gt; are abstract. Nothing owns them. Multiple EC2 instances, Lambdas, and EKS pods can all assume the same role simultaneously, and the role doesn&apos;t know or care.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GCP service accounts&lt;/strong&gt; are real resources. They live in a project, they have an email, you can grant IAM roles &lt;em&gt;on&lt;/em&gt; them (like &lt;code class=&quot;language-text&quot;&gt;roles/iam.serviceAccountUser&lt;/code&gt; to let someone attach the SA to a VM), and you can impersonate them if you have the right permission. They feel more like &quot;a user that happens to be a robot&quot; than AWS&apos;s &quot;a hat anyone can wear.&quot;&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure managed identities&lt;/strong&gt; sit in the middle. System-assigned managed identities are tied to the lifecycle of exactly one Azure resource. Delete the VM, the identity is gone. User-assigned managed identities are standalone Azure resources that you can attach to multiple things, which makes them closer to AWS roles.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;If you&apos;re coming from AWS and expect to &quot;just assume the role from wherever,&quot; GCP and Azure will feel more constrained. If you&apos;re coming from GCP and expect your identity to have an email you can grant things to, AWS roles will feel invisible in a way that&apos;s hard to get used to.&lt;/p&gt;
&lt;h3&gt;3. Where does &quot;a machine&apos;s identity&quot; actually come from at runtime?&lt;/h3&gt;
&lt;p&gt;All three clouds have a metadata endpoint that hands out short-lived credentials to workloads running on their compute. The mechanism is remarkably similar across all three:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS&lt;/strong&gt;: IMDSv2 at &lt;code class=&quot;language-text&quot;&gt;169.254.169.254&lt;/code&gt;, returns STS credentials for the attached instance profile.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GCP&lt;/strong&gt;: Metadata server at &lt;code class=&quot;language-text&quot;&gt;metadata.google.internal&lt;/code&gt; (also &lt;code class=&quot;language-text&quot;&gt;169.254.169.254&lt;/code&gt;), returns OAuth2 access tokens for the attached service account.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure&lt;/strong&gt;: IMDS at &lt;code class=&quot;language-text&quot;&gt;169.254.169.254&lt;/code&gt;, returns bearer tokens for the attached managed identity.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;They all default to a roughly one-hour token lifetime. They all require the SDK (or your own code) to refresh before expiry. They all fail in subtle ways if the workload&apos;s network egress to &lt;code class=&quot;language-text&quot;&gt;169.254.169.254&lt;/code&gt; is blocked, which is a fun thing to remember the first time you put a service mesh in front of a pod.&lt;/p&gt;
&lt;h3&gt;4. Kubernetes workload identity is a zoo&lt;/h3&gt;
&lt;p&gt;If you run Kubernetes on any of these, you&apos;ll eventually need to map a Kubernetes service account (KSA) to a cloud identity, so that pods can call cloud APIs without a mounted secret.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS&lt;/strong&gt; has two options that both work. &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html&quot;&gt;IRSA&lt;/a&gt; uses an OIDC provider on the EKS cluster; pods get STS tokens via a projected service account token. &lt;a href=&quot;https://docs.aws.amazon.com/eks/latest/userguide/pod-identity.html&quot;&gt;EKS Pod Identity&lt;/a&gt; is the newer mechanism that removes the OIDC provider setup. IRSA is still more widely deployed.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GCP&lt;/strong&gt; has &lt;a href=&quot;https://cloud.google.com/kubernetes-engine/docs/concepts/workload-identity&quot;&gt;Workload Identity&lt;/a&gt;, which maps a KSA to a GCP service account via an annotation. Under the hood it&apos;s also OIDC-based, but you don&apos;t manage the provider.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure&lt;/strong&gt; has &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/aks/workload-identity-overview&quot;&gt;Entra Workload Identity&lt;/a&gt;, which replaced the deprecated AAD Pod Identity. Like the others, it&apos;s OIDC-based. AKS publishes an issuer, and the federated credential on an Entra app or managed identity trusts tokens from that issuer bound to a specific KSA.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All three are &quot;the same idea&quot; (projected service account tokens + OIDC federation), but each has its own setup tax. Expect to do some real reading the first time you touch a new one.&lt;/p&gt;
&lt;h3&gt;5. Long-lived credentials: dangerous in different ways&lt;/h3&gt;
&lt;p&gt;Every cloud has a &quot;here be dragons&quot; credential type:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;AWS IAM user access keys&lt;/strong&gt; are the oldest of these, and the worst-behaved. They live forever, they&apos;re often committed to git, and they&apos;re the reason &lt;a href=&quot;https://github.com/gitleaks/gitleaks&quot;&gt;gitleaks&lt;/a&gt; exists. Modern AWS guidance is: don&apos;t create them at all. Use Identity Center for humans and roles for machines.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;GCP service account JSON keys&lt;/strong&gt; are the same problem in a different wrapper. They look innocuous (just a JSON file!) but they&apos;re long-lived bearer tokens that bypass every &quot;no external access&quot; control you have. &lt;a href=&quot;https://cloud.google.com/iam/docs/service-account-creds&quot;&gt;GCP now disables key creation by default at the org level&lt;/a&gt;, and for good reason. Prefer impersonation or Workload Identity Federation.&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;Azure service principal client secrets&lt;/strong&gt; have the same failure mode. Prefer certificate-based auth or (ideally) managed identities, which never expose a credential in the first place.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The common thread: any time you&apos;re holding a credential that doesn&apos;t have an expiry measured in hours, you&apos;re holding a bomb.&lt;/p&gt;
&lt;h2&gt;A worked example: &quot;give this CI job read access to one bucket&quot;&lt;/h2&gt;
&lt;p&gt;To make the differences concrete, here&apos;s the same task expressed three ways.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;AWS&lt;/strong&gt;: create an IAM role with a policy granting &lt;code class=&quot;language-text&quot;&gt;s3:GetObject&lt;/code&gt; on &lt;code class=&quot;language-text&quot;&gt;arn:aws:s3:::my-bucket/*&lt;/code&gt;, and a trust policy that allows your CI&apos;s OIDC provider (e.g. &lt;code class=&quot;language-text&quot;&gt;token.actions.githubusercontent.com&lt;/code&gt;) to assume it for a specific repo/branch. The CI job calls &lt;code class=&quot;language-text&quot;&gt;sts:AssumeRoleWithWebIdentity&lt;/code&gt; and gets temporary credentials.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GCP&lt;/strong&gt;: create a Workload Identity Pool and Provider for your CI&apos;s OIDC issuer. Grant the external identity (e.g. a specific GitHub repo) the &lt;code class=&quot;language-text&quot;&gt;roles/storage.objectViewer&lt;/code&gt; role directly on the bucket, or have it impersonate a service account that has the role. The CI job exchanges its OIDC token for a GCP access token at the STS endpoint.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Azure&lt;/strong&gt;: create an app registration (or user-assigned managed identity) with a federated credential trusting your CI&apos;s OIDC issuer for a specific repo/branch. Give the resulting service principal the &lt;code class=&quot;language-text&quot;&gt;Storage Blob Data Reader&lt;/code&gt; role, scoped to the storage account or container. The CI job exchanges its OIDC token for an Azure access token.&lt;/p&gt;
&lt;p&gt;Notice the shape is identical: OIDC issuer, federation trust, role grant, scoped resource. The words and the order of operations are all different. This is why &quot;I know AWS IAM, how hard can GCP be?&quot; is a trap. The concepts transfer, but the muscle memory doesn&apos;t.&lt;/p&gt;
&lt;h2&gt;Where to go next&lt;/h2&gt;
&lt;p&gt;An adjacent view only gets you to the point of being able to read signs. To actually &lt;em&gt;work&lt;/em&gt; in a second cloud, go read the primary docs for its identity system end to end:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;AWS: &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/introduction.html&quot;&gt;IAM User Guide&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;GCP: &lt;a href=&quot;https://cloud.google.com/iam/docs/overview&quot;&gt;IAM overview&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;Azure: &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/role-based-access-control/overview&quot;&gt;Azure RBAC overview&lt;/a&gt; &lt;em&gt;and&lt;/em&gt; &lt;a href=&quot;https://learn.microsoft.com/en-us/entra/fundamentals/whatis&quot;&gt;Entra ID fundamentals&lt;/a&gt;. You need both, because they&apos;re genuinely two separate systems.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And when you get stuck debugging a permission error in a cloud you don&apos;t live in full-time, remember which direction that cloud flows permissions. Half the &quot;why isn&apos;t this working&quot; problems across clouds come from looking at the wrong end of the grant.&lt;/p&gt;
&lt;hr&gt;
&lt;p&gt;&lt;em&gt;This post was drafted autonomously by Claude (Opus 4.6), then edited by me for tone and voice. The technical claims are mine to stand behind. If you find an error, &lt;a href=&quot;https://github.com/coilysiren&quot;&gt;let me know&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Deploying Azure OpenAI via Terraform]]></title><description><![CDATA[An end to end description of how to get Azure OpenAI deployed via Terraform]]></description><link>https://coilysiren.me/posts/azure-openai-terraform/</link><guid isPermaLink="false">https://coilysiren.me/posts/azure-openai-terraform/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Wed, 11 Oct 2023 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;This post is aimed at reasonably experienced engineers who are deploying Azure OpenAI for their day job. It assumes you&apos;re familiar with:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;cloud deployments in general&lt;/li&gt;
&lt;li&gt;terraform specifically&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;As such, this post functions primarily as a reference for the terraform configuration you would need. If you are looking for a more basic understanding of how terraform works, &lt;a href=&quot;https://developer.hashicorp.com/terraform/tutorials&quot;&gt;then Hashicorp has some great tutorials for you!&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Prerequisites&lt;/h2&gt;
&lt;p&gt;In order to get started here, you need to have already done a few things:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://developer.hashicorp.com/terraform/tutorials/state&quot;&gt;Setup terraform locally with the state backend that most fits your needs&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Signed up for an Azure account.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Circa October 2023: a simple personal Azure account will not work here. The Azure OpenAI signup process requires that your Azure account have enterprise support. I would not recommend creating a totally new Azure account as a part of this process.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/microsoft-365/enterprise/subscriptions-licenses-accounts-and-tenants-for-microsoft-cloud-offerings?view=o365-worldwide&quot;&gt;Created a subscription within Azure&lt;/a&gt;. This post assumes you are using a paid subscription, which will need to be setup by someone in your company with billing permissions.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/&quot;&gt;Installed the Azure CLI&lt;/a&gt;, &lt;a href=&quot;https://learn.microsoft.com/en-us/cli/azure/authenticate-azure-cli&quot;&gt;and logged into it&lt;/a&gt;.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Been granted an Azure role &lt;a href=&quot;https://learn.microsoft.com/en-us/azure/role-based-access-control/built-in-roles&quot;&gt;like the Contributor role&lt;/a&gt; that allows you perform the relevant API actions within Azure. While it would be ideal to mention the fine grain access control you need to perform these actions, that is out of scope for this blog post. Someone with the &lt;code class=&quot;language-text&quot;&gt;Owner&lt;/code&gt; role on your subscription should be able to grant you the &lt;code class=&quot;language-text&quot;&gt;Contributor&lt;/code&gt; role.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The above steps will likely require the assistance of your finance and IT teams. Feel free to come back to this post once you&apos;ve finished coordinating with them!&lt;/p&gt;
&lt;p&gt;After setting up all of the above, then the should have all the fundamentals you need to deploy things! Lets go...&lt;/p&gt;
&lt;h2&gt;Security Preface&lt;/h2&gt;
&lt;p&gt;...okay wait.&lt;/p&gt;
&lt;p&gt;Before I mention the terraform itself, I must give an important caveat. The terraform configuration describes here is in its &lt;strong&gt;&lt;em&gt;least secure configuration&lt;/em&gt;&lt;/strong&gt;. Specifically, its in its least secure configuration with regards to network security. If you are following this configuration as-is, then you should only be doing so as a prototype. Essentially you deploying this to prove to your stakeholders, &lt;em&gt;&quot;yes I have the skills required to deploy Azure OpenAI via Terraform&quot;&lt;/em&gt;. You must then follow-up via starting work up the network security improvements.&lt;/p&gt;
&lt;p&gt;Having said that. Lets go...&lt;/p&gt;
&lt;h2&gt;Terraform Configuration&lt;/h2&gt;
&lt;p&gt;...deploy this thing! This blog post presents the configuration as two terraform files. This is for display simplicity, and you really shouldn&apos;t be just stuffing everything into two adjacent files like this. The files have the following folder structure:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# folder structure&lt;/span&gt;

terraform/main.tf
terraform/modules/azure-openai/main.tf&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;And here are the files:&lt;/p&gt;
&lt;!-- author note: my queendom for a HCL syntax highlighter... --&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# file: terraform/main.tf&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Set required versions.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;required_providers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;azurerm&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;source&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hashicorp/azurerm&quot;&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~&gt; 3&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Configure your Azure authentication. At my job we use multiple providers with&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# the `alias` key to configure prod vs non-prod resources.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;provider&lt;span class=&quot;token type variable&quot;&gt; &quot;azurerm&quot; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;features&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Here we init our module which contains all of our actual resources. The keys&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# here (eg. stage, vnet_cidr, etc) are all defined in our next file.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# docs: https://developer.hashicorp.com/terraform/language/modules&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;module&lt;span class=&quot;token type variable&quot;&gt; &quot;azure_openai&quot; &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;source&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;modules/azure-openai&quot;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# eg. prod, staging, dev, etc...&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;stage&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;prod&quot;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# Pick somewhere close to you, or close to your customers.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# Use the following command to get locations:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   $ az account list-locations -o table&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;westus&quot;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# The SKU is the pricing tier. I haven&apos;t been able to find a page or command&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# that provides a flat list of all the available SKUs. This page describes some&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# of them, though:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# https://learn.microsoft.com/en-us/azure/search/search-limits-quotas-capacity&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;cognitive_sku&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;S0&quot;&lt;/span&gt;

  &lt;span class=&quot;token comment&quot;&gt;# This configuration is for our network architecture. A complete description&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# of what these numbers mean, and how to set them, is beyond the scope of this&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# post. But I will try my best to describe it in brief!&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# A &quot;vnet&quot; is a virtual network group. This network group needs an address,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# similar to a street address. The &quot;cidr&quot; is that address, represented as a range.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# A &quot;subnet&quot; or &quot;sub network&quot; is simply a sub group of the broader vnet.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# A vnet is like a house. The vnet cdir is the address to that house. The&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# subnets are individual rooms within that house. The subnet cidr is the address&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# for each room. The cidrs are all ranges, so the subnet cidrs are ranges contained&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# within the vnet range. You can use a website like https://cidr.xyz/ to confirm this.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# ...This was a lot. It deserves its own post...!&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;vnet_cidr&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10.0.0.0/19&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet0_cidr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10.0.0.0/24&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet1_cidr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10.0.1.0/24&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet2_cidr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10.0.10.0/24&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet3_cidr&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;10.0.11.0/24&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;hcl&quot;&gt;&lt;pre class=&quot;language-hcl&quot;&gt;&lt;code class=&quot;language-hcl&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# file: terraform/modules/azure-openai/main.tf&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Set required versions. The module probably doesn&apos;t need to do this&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# when the parent context is already doing it. But it&apos;s here anyway, can&apos;t hurt.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;terraform&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token keyword&quot;&gt;required_providers&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;azurerm&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;source&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;hashicorp/azurerm&quot;&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;~&gt; 3&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# These variables are the inputs for our module. Their context us best understood&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# by looking at where they are used inside this module.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# docs: https://developer.hashicorp.com/terraform/language/values/variables&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;stage&quot;          &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;location&quot;       &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;cognitive_sku&quot;  &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;vnet_cidr&quot;      &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;subnet0_cidr&quot;   &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;subnet1_cidr&quot;   &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;subnet2_cidr&quot;   &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;variable&lt;span class=&quot;token type variable&quot;&gt; &quot;subnet3_cidr&quot;   &lt;/span&gt;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt; &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; string &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;###########&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# PREFACE #&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;###########&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# Past this point, documentation is mostly non-existent on my part.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# This is primarily due to the wall clock time I had available to write this post.&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# All of these resources do deserve documentation to some extent!&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;####################&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# SHARED RESOURCES #&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;####################&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/resource_group&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_resource_group&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; var.location
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/virtual_network&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_virtual_network&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;address_space&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;var.vnet_cidr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/route_table&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_route_table&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/route&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_route&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;local&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;local&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;route_table_name&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefix&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; var.vnet_cidr
  &lt;span class=&quot;token property&quot;&gt;next_hop_type&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;VnetLocal&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/route&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_route&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;internet&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;internet&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;route_table_name&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefix&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0.0.0.0/0&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;next_hop_type&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Internet&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;####################&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# PUBLIC RESOURCES #&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;####################&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet2&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet2&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;virtual_network_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_virtual_network.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefixes&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;var.subnet2_cidr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet3&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet3&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;virtual_network_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_virtual_network.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefixes&lt;/span&gt;     &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;var.subnet3_cidr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_route_table_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_route_table_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet2&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet2.id
  &lt;span class=&quot;token property&quot;&gt;route_table_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_route_table_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_route_table_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet3&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet3.id
  &lt;span class=&quot;token property&quot;&gt;route_table_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;#####################&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# PRIVATE RESOURCES #&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#####################&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                                          &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet0&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;virtual_network_name&lt;/span&gt;                          &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_virtual_network.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefixes&lt;/span&gt;                              &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;var.subnet0_cidr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;service_endpoints&lt;/span&gt;                             &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Microsoft.CognitiveServices&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;private_link_service_network_policies_enabled&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                                          &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet1&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;virtual_network_name&lt;/span&gt;                          &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_virtual_network.default.name
  &lt;span class=&quot;token property&quot;&gt;address_prefixes&lt;/span&gt;                              &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;var.subnet1_cidr&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;service_endpoints&lt;/span&gt;                             &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;Microsoft.CognitiveServices&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;private_link_service_network_policies_enabled&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_route_table_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_route_table_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet0.id
  &lt;span class=&quot;token property&quot;&gt;route_table_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_route_table_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_route_table_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;subnet1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet1.id
  &lt;span class=&quot;token property&quot;&gt;route_table_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_route_table.default.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_public_ip&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-nat0&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;allocation_method&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Static&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;sku&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Standard&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_nat_gateway&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-nat0&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;sku_name&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Standard&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway_public_ip_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_nat_gateway_public_ip_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;nat_gateway_id&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_nat_gateway.nat0.id
  &lt;span class=&quot;token property&quot;&gt;public_ip_address_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_public_ip.nat0.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_nat_gateway_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_nat_gateway_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet0.id
  &lt;span class=&quot;token property&quot;&gt;nat_gateway_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_nat_gateway.nat0.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/public_ip&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_public_ip&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-nat1&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;allocation_method&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Static&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;sku&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Standard&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_nat_gateway&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-nat1&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;sku_name&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Standard&quot;&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/nat_gateway_public_ip_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_nat_gateway_public_ip_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;nat_gateway_id&lt;/span&gt;       &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_nat_gateway.nat1.id
  &lt;span class=&quot;token property&quot;&gt;public_ip_address_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_public_ip.nat1.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/subnet_nat_gateway_association&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_subnet_nat_gateway_association&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;nat1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;      &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet1.id
  &lt;span class=&quot;token property&quot;&gt;nat_gateway_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_nat_gateway.nat1.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_private_dns_zone&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;openai&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;.privatelink.openai.azure.com&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_dns_zone_virtual_network_link&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_private_dns_zone_virtual_network_link&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;openai&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;   &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;private_dns_zone_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_private_dns_zone.openai.name
  &lt;span class=&quot;token property&quot;&gt;virtual_network_id&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_virtual_network.default.id
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_private_endpoint&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private0&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-private0&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet0.id

  &lt;span class=&quot;token keyword&quot;&gt;private_service_connection&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-private0&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;private_connection_resource_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_cognitive_account.private.id
    &lt;span class=&quot;token property&quot;&gt;subresource_names&lt;/span&gt;              &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;is_manual_connection&lt;/span&gt;           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private_dns_zone_group&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;private_dns_zone_ids&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;azurerm_private_dns_zone.openai.id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/private_endpoint&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_private_endpoint&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private1&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-private1&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;            &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt;           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet1.id

  &lt;span class=&quot;token keyword&quot;&gt;private_service_connection&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-private1&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;private_connection_resource_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_cognitive_account.private.id
    &lt;span class=&quot;token property&quot;&gt;subresource_names&lt;/span&gt;              &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;&lt;span class=&quot;token string&quot;&gt;&quot;account&quot;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;is_manual_connection&lt;/span&gt;           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;private_dns_zone_group&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;default&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;private_dns_zone_ids&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;azurerm_private_dns_zone.openai.id&lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;#######################&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;# COGNITIVE RESOURCES #&lt;/span&gt;
&lt;span class=&quot;token comment&quot;&gt;#######################&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/cognitive_account&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_cognitive_account&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                               &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;location&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.location
  &lt;span class=&quot;token property&quot;&gt;resource_group_name&lt;/span&gt;                &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_resource_group.default.name
  &lt;span class=&quot;token property&quot;&gt;kind&lt;/span&gt;                               &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;OpenAI&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;sku_name&lt;/span&gt;                           &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; var.cognitive_sku
  &lt;span class=&quot;token property&quot;&gt;outbound_network_access_restricted&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;false&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;local_auth_enabled&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;

  &lt;span class=&quot;token property&quot;&gt;public_network_access_enabled&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token boolean&quot;&gt;true&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# public_network_access_enabled is a misleading setting name. It is best understood in&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# connection with the network_acls.defeault_action setting. Here&apos;s effect of various&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# combinations of these two settings:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# public_network_access_enabled: true, default_action: Allow&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   - Accessible anyhere from the internet. THIS IS DANGEROUS.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# public_network_access_enabled: true, default_action: Deny&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   - Accessible from the specified IP ranges in `ip_rules`.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# public_network_access_enabled: false, default_action: Allow&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   - Adding `ip_rules` has no effect, they&apos;re fake news.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# public_network_access_enabled: false, default_action: Deny&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#   - Same as above.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# At a high level, this setting needs only to be `true` when you haven&apos;t yet&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# setup private network ingress points from your primary network group (vnet, VPC, VPN, etc)&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# to this new vnet. Explaining that in detail is beyond the scope of this post!&lt;/span&gt;

  &lt;span class=&quot;token property&quot;&gt;custom_subdomain_name&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;-v1&quot;&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# custom_subdomain_name has a version incrementor because it&apos;s a global resource,&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# and doesn&apos;t always get deleted immediately when the resource is destroyed.&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# The error message you get will look something like:&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# &gt; The subdomain name ... is not available as it&apos;s already used by a resource&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
  &lt;span class=&quot;token comment&quot;&gt;# When I get that message, I simply increment the version.&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;network_acls&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;default_action&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Deny&quot;&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;##########################################&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# !!! IMPORTANT SECURITY ACTION ITEM !!! #&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;##########################################&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# This is a &quot;prototype&quot; configuration where you just grab your IP address&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# via `$ curl http://ifconfig.me` and stick it right this file. This is bad&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# security practice and is only fit for proving to your stackholders that&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# you are skilled enough to deploy Azure OpenAI via terraform.&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# What you want to do, is setup a peering connection from your main network groups&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# to the new network groups created by this terraform file. You will need&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# to setup the peering connection to support network requests from humans&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# (via a VPN or similar) and network requests from automated services&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# (via another network group, like a different vnet).&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;#&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# Once you do that, you can set `public_network_access_enabled = false`,&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# because the network requests will be coming from private IPs routed through&lt;/span&gt;
    &lt;span class=&quot;token comment&quot;&gt;# your peering connection. Then you will set these ip_rules to private cidrs.&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;ip_rules&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;[&lt;/span&gt;
      &lt;span class=&quot;token string&quot;&gt;&quot;255.255.255.255&quot;&lt;/span&gt;, &lt;span class=&quot;token comment&quot;&gt;# &amp;lt;= !!! your IP address goes here !!!&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;]&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual_network_rules&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet0.id
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
    &lt;span class=&quot;token keyword&quot;&gt;virtual_network_rules&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
      &lt;span class=&quot;token property&quot;&gt;subnet_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_subnet.subnet1.id
    &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# docs: https://registry.terraform.io/providers/hashicorp/azurerm/latest/docs/resources/cognitive_deployment&lt;/span&gt;
&lt;span class=&quot;token keyword&quot;&gt;resource &lt;span class=&quot;token type variable&quot;&gt;&quot;azurerm_cognitive_deployment&quot;&lt;/span&gt;&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;private&quot;&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;                 &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;azure-openai-&lt;span class=&quot;token interpolation&quot;&gt;&lt;span class=&quot;token punctuation&quot;&gt;$&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;&lt;span class=&quot;token keyword&quot;&gt;var&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;token type variable&quot;&gt;stage&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/span&gt;&quot;&lt;/span&gt;
  &lt;span class=&quot;token property&quot;&gt;cognitive_account_id&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; azurerm_cognitive_account.private.id
  &lt;span class=&quot;token keyword&quot;&gt;model&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;format&lt;/span&gt;  &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;OpenAI&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;name&lt;/span&gt;    &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;gpt-35-turbo&quot;&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;version&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;0301&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;

  &lt;span class=&quot;token keyword&quot;&gt;scale&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token property&quot;&gt;type&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;Standard&quot;&lt;/span&gt;
  &lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;All of that! Should be deploy-able with a &lt;code class=&quot;language-text&quot;&gt;terraform init &amp;amp;&amp;amp; terraform apply&lt;/code&gt; without requiring much additional configuration. With, of course, the significant except of putting your IP address into the &lt;code class=&quot;language-text&quot;&gt;ip_rules&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;I don&apos;t expect this example will quite work so easily if you are working with existing architecture. If you&apos;re looking for another example terraform configuration to compare against your architecture, I would recommend this Github repo from Azure:&lt;/p&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/Azure-Samples/azure-openai-terraform-deployment-sample&quot;&gt;https://github.com/Azure-Samples/azure-openai-terraform-deployment-sample&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Good luck! And do follow-up with those network security improvements, dear reader.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[On Permissions Models for Cloud Platform Providers]]></title><description><![CDATA[If I were doing permissions for a cloud platform provider, I'd do them like this!]]></description><link>https://coilysiren.me/posts/on-permissions-models-for-cloud-platform-providers/</link><guid isPermaLink="false">https://coilysiren.me/posts/on-permissions-models-for-cloud-platform-providers/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Sun, 12 Jan 2020 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I was &lt;a href=&quot;https://twitter.com/coilysiren/status/1215860950684667904&quot;&gt;recently reflecting&lt;/a&gt; on the fact that &lt;a href=&quot;https://aws.amazon.com/iam/&quot;&gt;AWS IAM&lt;/a&gt; has the best permissions model on the market, and wondering why I think most other platforms have such a dramatically inferior setup. I had never put much thought into this prior, so my first conclusion was &lt;em&gt;&quot;wow everyone but Amazon is bad at this!&quot;&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Except that&apos;s not actually how the world works 🙂 In reality there are concrete tradeoffs and decisions that lead to products being in a certain state. And in situations like this? A well designed foundation will get you 90% of the way there. With that context I imagined: how would I design a platform such that future people working on it &lt;em&gt;(eg. without my direct assistance)&lt;/em&gt; would replicate the success and effectiveness of IAM? This post is me taking a shot at that.&lt;/p&gt;
&lt;h2&gt;Guiding Principles&lt;/h2&gt;
&lt;p&gt;To start, there&apos;s a few principles we want to establish. The principles establish the direction and essence of our foundation, and all of the large design choices will flow from the principles. Some of the principles are lifted verbatim from AWS, which is to be expected since AWS is the clear leader in it&apos;s realm. Here they are:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://news.ycombinator.com/item?id=18916406&quot;&gt;all services must interact exclusively through public APIs&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;all service endpoints and clients must be created and validated with code generation&lt;/li&gt;
&lt;li&gt;all service operations must take fully qualified unique resource identifiers (RSIDs) as inputs&lt;/li&gt;
&lt;li&gt;all service operations must only use the resources passed in as RSIDs during their operation&lt;/li&gt;
&lt;li&gt;every unique independent resource within a service must be able to by specified via a RSID&lt;/li&gt;
&lt;li&gt;if a resource is a child of another resource, that must be encoded into the RSID&lt;/li&gt;
&lt;li&gt;every resource is a child of a &quot;organization&quot;, which generally presents a company&lt;/li&gt;
&lt;li&gt;every unique independent action that can be taken on a service must have a unique action identifier (ACID)&lt;/li&gt;
&lt;li&gt;ACIDs must follow the Create Read Update Delete (CRUD) naming scheme, but may also include additional verbs such as &quot;List&quot;&lt;/li&gt;
&lt;li&gt;IAM is the only service that gets any degree of special treatment&lt;/li&gt;
&lt;li&gt;the code generation must wrap every service operation with the same IAM checks&lt;/li&gt;
&lt;li&gt;the platform must be capable of running itself&lt;/li&gt;
&lt;li&gt;service usage can be simplified for customers by creating aliases that group operations, but never by compromising on the functionality of the operations themselves&lt;/li&gt;
&lt;li&gt;everything defaults to allowing no access&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;An example case&lt;/h2&gt;
&lt;p&gt;With the principles above, I want to detail an example case. Say our cloud platform (&lt;code class=&quot;language-text&quot;&gt;cloudOps&lt;/code&gt;) just launched, and we want to provide a database service (&lt;code class=&quot;language-text&quot;&gt;kittenDB&lt;/code&gt;) to our clients. Our platform itself also runs on that same database service! How do we go about setting that up? We start by defining all the RSIDs and ACIDs for both our permissions service (&lt;code class=&quot;language-text&quot;&gt;IAM&lt;/code&gt;) and our database service (&lt;code class=&quot;language-text&quot;&gt;kittenDB&lt;/code&gt;), both for our use and for use by our clients.&lt;/p&gt;
&lt;p&gt;Service IAM has 3 resources: &quot;users&quot;, &quot;policies&quot;, and &quot;organizations&quot;. Policies can be granted to users and organizations. The complete layout of ids is like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RSID::IAM::{{ organization }}::/organization/*
RSID::IAM::{{ organization }}::/user/*
RSID::IAM::{{ organization }}::/policy/*
RSID::IAM::{{ organization }}::/policy/{{ policy }}/user/*
RSID::IAM::{{ organization }}::/policy/{{ policy }}/organization/*

ACID::IAM::create-organization
ACID::IAM::list-organization
ACID::IAM::read-organization
ACID::IAM::update-organization
ACID::IAM::delete-organization

ACID::IAM::create-user
ACID::IAM::list-user
ACID::IAM::read-user
ACID::IAM::update-user
ACID::IAM::delete-user

ACID::IAM::create-policy
ACID::IAM::list-policy
ACID::IAM::read-policy
ACID::IAM::update-policy
ACID::IAM::delete-policy

ACID::IAM::attach-policy-to-user
ACID::IAM::attach-policy-to-organization&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;Service kittenDB has 2 resources: &quot;maps&quot; and &quot;entries&quot;, in addition to the database itself. Entries are contained with maps. The complete layout of ids is like so:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;RSID::KITTENDB::{{ organization }}::/database/*
RSID::KITTENDB::{{ organization }}::/map/*
RSID::KITTENDB::{{ organization }}::/map/{{ map }}/entry/*

ACID::KITTENDB::create-database
ACID::KITTENDB::read-database
ACID::KITTENDB::update-database
ACID::KITTENDB::delete-database

ACID::KITTENDB::create-map
ACID::KITTENDB::read-map
ACID::KITTENDB::update-map
ACID::KITTENDB::delete-map

ACID::KITTENDB::create-entry-in-map
ACID::KITTENDB::read-entry-in-map
ACID::KITTENDB::update-entry-in-map
ACID::KITTENDB::delete-entry-in-map&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Platform Bootstrapping&lt;/h2&gt;
&lt;p&gt;The very very first thing we need to do, is allow the platform to manage itself. And in the beginning... there is no platform! So someone at cloudOps need to run some commands to spin up the very first kittenDB instance. We&apos;ll assume this some employee on the physical cloudDB server running &lt;code class=&quot;language-text&quot;&gt;make build&lt;/code&gt; after doing &lt;code class=&quot;language-text&quot;&gt;git clone kittenDB ...&lt;/code&gt; or whatever.&lt;/p&gt;
&lt;p&gt;From there we have to &quot;hand load&quot; a few policies into the database. Our goal here is to do all of the manual direct-to-database work required in order to let our users utilize the platform. It&apos;s important to recall here that cloudOps is using kittenDB as it&apos;s database, and every action requires a database call, so for even very mundane actions like &quot;organization creation&quot; we need to start defining access policies. We&apos;ll do this with a single instance &quot;global policy&quot; that applies to everyone. It&apos;ll look like this:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# in case you&apos;re unacquainted, this is cloudformation syntax!&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;GlobalPolicy&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;global-policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::Policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;allow-creating-organizations&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for any organization name&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::*::/organization/*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow seeing if an organization of that name exists&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::list-organization&quot;&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow creating an organization with that name&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::create-organization&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;This would translate to API calls that, in a CLI for example, would look like this&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;text&quot;&gt;&lt;pre class=&quot;language-text&quot;&gt;&lt;code class=&quot;language-text&quot;&gt;cloud-ops iam create-organization --name &quot;my-new-organization&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;More Policy Definitions&lt;/h2&gt;
&lt;p&gt;The last section described the most basic action for the platform: organization creation. From there we have a few more &quot;personas&quot; we need to consider. The personas represent either a distinct state for a given user, or a &quot;machine user&quot; created for a specific purpose. At any rate, they all need policies!&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# this is for an &quot;admin&quot; user for the organization&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;OrgAdmin&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;org-admin&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::Policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;allow-managing-my-organization&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for anything within my organization&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::my-new-organization::*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow me to do anything&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::*&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;allow-database-access&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for a database within my organization&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow &quot;database&quot; level actions such as creating and deleting&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# the database, but not reading its contents&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*database*&quot;&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# this is for an &quot;operator&quot; user for the organization, such as an engineer&lt;/span&gt;
&lt;span class=&quot;token key atrule&quot;&gt;OrgOperator&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;org-operator&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::Policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;allow-database-access&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for a database within my organization&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow me to see anything I might need to for debugging&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*list*&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*read*&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# these are for two distinct types of &quot;machine user&quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;MachineUserReadAccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;machine-read-access&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::Policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;database-read&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for a database within my organization&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow read actions&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*read*&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*list*&quot;&lt;/span&gt;

&lt;span class=&quot;token key atrule&quot;&gt;MachineUserWriteAccess&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;machine-write-access&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Type&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;IAM::Policy&quot;&lt;/span&gt;
    &lt;span class=&quot;token key atrule&quot;&gt;Properties&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;database-read&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for a database within my organization&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow read actions&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*read*&quot;&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*list*&quot;&lt;/span&gt;
            &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;database-contents-write&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# for the contents of my organization&apos;s database&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::/map/*&quot;&lt;/span&gt;
              &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
                &lt;span class=&quot;token comment&quot;&gt;# allow all actions&lt;/span&gt;
                &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;These policies would be pre-populated in the user&apos;s new organization, so they could assign them to people as needed. So you would create your new organization, and be presented with a list of policies like:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;org-admin&lt;/li&gt;
&lt;li&gt;org-operator&lt;/li&gt;
&lt;li&gt;machine-read-access&lt;/li&gt;
&lt;li&gt;machine-write-access&lt;/li&gt;
&lt;li&gt;etc etc&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The policies would be editable and for whatever specific purpose the user requires. A fairly common one would likely be giving read / write access only to certain paths:&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;yaml&quot;&gt;&lt;pre class=&quot;language-yaml&quot;&gt;&lt;code class=&quot;language-yaml&quot;&gt;&lt;span class=&quot;token key atrule&quot;&gt;Rules&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;read-shared-paths&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# for all shared paths&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::/map/shared/*&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# allow read actions&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*read*&quot;&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*list*&quot;&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token key atrule&quot;&gt;Name&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;write-my-shared-paths&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;Resources&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# for my shared paths&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::my-new-organization::/map/shared/my-paths/*&quot;&lt;/span&gt;
      &lt;span class=&quot;token key atrule&quot;&gt;Actions&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt;
        &lt;span class=&quot;token comment&quot;&gt;# allow all actions&lt;/span&gt;
        &lt;span class=&quot;token punctuation&quot;&gt;-&lt;/span&gt; &lt;span class=&quot;token string&quot;&gt;&quot;KITTENDB::*&quot;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h2&gt;Implementation Challenges&lt;/h2&gt;
&lt;p&gt;This is an &quot;overview&quot; level description of how one would setup a system like this, but there are a great many things that represent implementation challenges. Including:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;given the auto-generated stub kittenDB API endpoints, how do you implement the actual logic?&lt;/li&gt;
&lt;li&gt;given how &quot;hot&quot; the code and data paths will be for the IAM access systems, how do you keep performance high?&lt;/li&gt;
&lt;li&gt;how do you resolve intersecting / conflicting access policies, ideally in such a way that users can debug them?&lt;/li&gt;
&lt;li&gt;how do you consistently ensure that every single API endpoint effectively communicates to the user when there&apos;s a permissions issue?&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Those are all &quot;tactical&quot; level challenges that will remain relevant for the entire course of the business. You&apos;ll need people dedicated to solving them, and also people working on expanding cloudOps out horizontally to support more types of data stores. That said! All of that ongoing work would happen on top of the existing strong fundamental permissions model, and you would be well suited to provide high flexibility access control for any client&apos;s business needs. You could also look into expanding the permissions model for more fine grain cases 👀 such as &lt;a href=&quot;https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_elements_condition.html&quot;&gt;attribute and tag based conditions&lt;/a&gt;.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Golang PR Field Notes (Part 3)]]></title><description><![CDATA[In this part, we start building foundational knowledge.]]></description><link>https://coilysiren.me/posts/golang-pr-notes-3/</link><guid isPermaLink="false">https://coilysiren.me/posts/golang-pr-notes-3/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Sun, 29 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;if you&apos;re looking for part 2, &lt;a href=&quot;https://coilysiren.me/posts/2019-12-26-golang-pr-field-notes-part-2/&quot;&gt;it&apos;s back this way &amp;#x3C;===&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;When we last saw our protagonist&lt;/h2&gt;
&lt;p&gt;The last time we were here, we took the time to identify some concepts we may need to understand, in order to do our work. That list of concepts is very long, and the actual relevance of the individual concepts varies fairly dramatically.&lt;/p&gt;
&lt;p&gt;Today, we&apos;re going to build up the knowledge we don&apos;t have, and start identifying and defining our &quot;foundational concepts&quot;. Those are the things we &lt;em&gt;absolutely need to understand&lt;/em&gt; in order to do any well grounded work in this space.&lt;/p&gt;
&lt;h2&gt;The foundational concepts&lt;/h2&gt;
&lt;p&gt;Judging from how they were mentioned and the frequency of mentions, here&apos;s what I think I need to understand first. I&apos;ve included links to the place where they appear in the golang issue tracker, links to various places on the internet that contain definitions or helpful information, and finally my personal re-definition of the term.&lt;/p&gt;
&lt;h3&gt;high level programming concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;code compilation&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://en.wikipedia.org/wiki/Compiler&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;In a general sense, &lt;strong&gt;code compilation&lt;/strong&gt; is any process of turning one programming language into another. It&apos;s most common specific usage is in turning a high level language (like python or go) into a low level language (like assembly or machine code) to create an executable.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;compiler optimization&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://en.wikipedia.org/wiki/Optimizing_compiler&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;compiler optimization&lt;/strong&gt; is the practice of trying to optimize the process of code compilation for any of the following attributes: compile time, code output size, memory requirements, and power consumption.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;assembly code&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://en.wikipedia.org/wiki/Code_generation_(compiler)&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;assembly code&lt;/strong&gt; is the code that computers actually know how to read. Most compilers work by turning some source code into some machine code, where the target machine code is often an assembly language. It&apos;s possible, but very annoying, to write assembly code directly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;computer processor concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;inter process communication (IPC)&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220172384&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Inter-process_communication&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;by &quot;default&quot; processes share no memory and cannot directly communicate with each other. &lt;strong&gt;IPC&lt;/strong&gt; is a set of techniques on can use to share data between processes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;semaphore&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220172384&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Semaphore_(programming)&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;a &lt;strong&gt;semaphore&lt;/strong&gt; is a construct that is used to control access to shared data across multiple concurrent processes. Semaphores are conceptually related to UNIX pipes, although it&apos;s unclear to me if pipes specifically are semaphores. In general, semaphores become required for certain kinds of complex work across multiple processes.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;instruction cache (icache)&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/29067#issuecomment-443887583&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/CPU_cache#ICACHE&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;a cache is a place where you store things so that you can access them more quickly. An &lt;strong&gt;icache&lt;/strong&gt; is a cache for instructions to be run by the CPU. Instructions in this context are lines of source code that are compiled to some machine code. CPUs may have some mechanism for moving instructions into / out of the icache, but that&apos;s a subject for another day.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;registers&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-399196221&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Processor_register&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;processor &lt;strong&gt;registers&lt;/strong&gt; are a type of cache used by the CPU. They are the top of the pyramid in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Memory_hierarchy&quot;&gt;memory hierarchy&lt;/a&gt;, which is to say that they are the fastest memory location available to the CPU. Registers are very very small, their maximum size typically being registered in bits. The amount of memory available to registers (~32 bits) can be contrasted with the memory available to RAM (~8GB, so 10^9 larger) and the memory available to hard drives (~1TB, so 10^12 larger)&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;general compilation concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bounds checks&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/25862&quot;&gt;2&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Bounds_checking&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;bounds checking&lt;/strong&gt; is a process via which a CPU can check that a variable meets some conditions before it is used. One common type of bounds checking is range checking, where a variable is checked to see if it fits into a given type, like a u8 (unsigned 8 bit int) or i16 (signed 16 bit int). Another common type of bounds checking is index checking, where an index to an array is checked to see if it actually fits in that array.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;compiled function nodes / abstract syntax trees (ASTs)&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Abstract_syntax_tree&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;ASTs&lt;/strong&gt; are an abstract representation of some source code, generally created by some kind of parser or compiler. ASTs represent certain elements as nodes in the tree, such as functions, if statements, and comparisons. The term &lt;strong&gt;compiled function node&lt;/strong&gt; can refer to either the literal individual node in an AST representing the function, or the individual function node and all of it&apos;s children in the tree.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;inlining functions&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Inline_expansion&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;this concept primarily relates to compiler optimization. For some parent function that calls some child function, the child function can either be represented as a separate function &quot;node&quot; - or it can be &lt;strong&gt;inlined&lt;/strong&gt; into the parent &lt;strong&gt;function&lt;/strong&gt; in a manner functionally equivalent to copy pasting. The dynamics of when something should vs should not be inlined are a matter of long and frequent discussion within golang, in particular &lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;in this issue&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;intrinsic functions&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-417111586&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Intrinsic_function&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;intrinsic functions&lt;/strong&gt; are special and fancy functions within a language, that have some extra tricks that leverage more low level processor / memory resources. They&apos;re sometimes written directly in assembly, and are often architecture specific (eg. like specific to AMD processors).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;compilation concepts with large impact on golang&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;static single assignment (SSA)&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/8893#issuecomment-134458436&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15736#issue-155612156&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-256149722&quot;&gt;3&lt;/a&gt;) (&lt;a href=&quot;https://godoc.org/golang.org/x/tools/go/ssa&quot;&gt;godoc&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Static_single_assignment_form&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;SSA&lt;/strong&gt; is a compiler design mechanism, wherein each variable is assigned to be assigned once and only once. In SSA, if a new value is assigned to a variable then a new version of that variable if created. SSA is primarily used for compiler optimization, since the guarantee of &quot;a variable&apos;s value will never change&quot; can enable a variety of compiler optimization algorithms.&lt;/li&gt;
&lt;li&gt;golang has a large &lt;a href=&quot;https://godoc.org/golang.org/x/tools/go/ssa&quot;&gt;SSA package&lt;/a&gt; that does various activities related to SSA.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;binary files / executables&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-66074026&quot;&gt;1&lt;/a&gt; &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-470268217&quot;&gt;2&lt;/a&gt; &lt;a href=&quot;https://github.com/golang/go/issues/20070#issuecomment-296292391&quot;&gt;3&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Executable&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;An &lt;strong&gt;executable&lt;/strong&gt; is a file that can be run by a machine in order to do some task. Executable files contrast most sharply with data files, which do not contain task instructions and instead contain information. Many executables are &lt;strong&gt;binary files&lt;/strong&gt; mean to be run by a machine directly, although the term executable can also be applied to the source code files of scripting languages (like python, and &lt;em&gt;unlike go&lt;/em&gt;).&lt;/li&gt;
&lt;li&gt;In golang care has been taken to make the generation of executable binary files both fast and reliable.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;*.o&lt;/code&gt; object files&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144125808&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-339211682&quot;&gt;2&lt;/a&gt;) (&lt;a href=&quot;https://go.googlesource.com/proposal/+/master/design/14386-zip-package-archives.md&quot;&gt;googlesource&lt;/a&gt;) (wikipedia &lt;a href=&quot;https://en.wikipedia.org/wiki/Object_file&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://en.wikipedia.org/wiki/Object_code&quot;&gt;2&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;object files&lt;/strong&gt; are the output of a compiler, and it&apos;s contents are usually in a machine language such as binary. Object files usually contain data points that a linker can use to fill in code from other places.&lt;/li&gt;
&lt;li&gt;Go&apos;s compiler produces object files as one of the compiler outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;&lt;code class=&quot;language-text&quot;&gt;*.a&lt;/code&gt; files&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/4719&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-380967328&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220173676&quot;&gt;3&lt;/a&gt;) (&lt;a href=&quot;https://stackoverflow.com/questions/15551293/what-are-a-files-in-go&quot;&gt;stackoverflow&lt;/a&gt;) (&lt;a href=&quot;https://go.googlesource.com/proposal/+/master/design/14386-zip-package-archives.md&quot;&gt;googlesource&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Ar_(Unix)&quot;&gt;wikipedia&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;Go&apos;s &lt;code class=&quot;language-text&quot;&gt;*.a&lt;/code&gt; files are package archive files, they were originally in the &lt;a href=&quot;https://en.wikipedia.org/wiki/Ar_(Unix)&quot;&gt;ar archive format&lt;/a&gt;. There was at some point &lt;a href=&quot;https://github.com/golang/go/issues/14386&quot;&gt;a proposal&lt;/a&gt; to change them to the more standard zip file format. Archive files contain compiled package code, and additionally some debugging information.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;file linking / static vs dynamic linking&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/14271&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144125808&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-240319812&quot;&gt;3&lt;/a&gt;) (&lt;a href=&quot;https://en.wikipedia.org/wiki/Static_library&quot;&gt;wikipedia&lt;/a&gt;) (stackoverflow &lt;a href=&quot;https://stackoverflow.com/questions/26418883/golang-how-to-link-c-objects-using-cgo-ofiles&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://stackoverflow.com/questions/1993390/static-linking-vs-dynamic-linking&quot;&gt;2&lt;/a&gt;) (&lt;a href=&quot;https://www.reddit.com/r/golang/comments/53nl4b/why_all_go_binaries_are_staticallylinked/&quot;&gt;reddit&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;linking&lt;/strong&gt; is the process by which an object file can request that other code be inserted into it. &lt;strong&gt;dynamic linking&lt;/strong&gt; is a linking process where the linking is not truly resolved until runtime, creating a dependency on external files (like DDLs). &lt;strong&gt;static linking&lt;/strong&gt; is a linking process where any links are resolved at compile time, creating a fully self-contained object.&lt;/li&gt;
&lt;li&gt;static linking is the better choice in like 99% of all cases.&lt;/li&gt;
&lt;li&gt;golang&apos;s compiler uses static linking, either exclusively or by default (I&apos;m not sure which).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;export data&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/15752&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15734&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/20070&quot;&gt;3&lt;/a&gt;) (godoc &lt;a href=&quot;https://godoc.org/golang.org/x/tools/go/internal/gcimporter&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://godoc.org/golang.org/x/tools/go/gcexportdata&quot;&gt;2&lt;/a&gt;, &lt;a href=&quot;https://godoc.org/golang.org/x/tools/cmd/godex&quot;&gt;3&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;the literal reference for &lt;em&gt;&quot;the &lt;strong&gt;data&lt;/strong&gt; that is &lt;strong&gt;exported&lt;/strong&gt; from a package&quot;&lt;/em&gt;.&lt;/li&gt;
&lt;li&gt;it&apos;s usage within golang is golang specific, because there are standard library tools (linked above) in golang built around managing export data. Those tools are responsible for the format and content of the export data.&lt;/li&gt;
&lt;li&gt;that said, the term itself is fairly generic since &quot;exported data&quot; can mean an entire universe of things.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;general computer science concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;runes&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/27148#issuecomment-415131187&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://stackoverflow.com/questions/19310700/what-is-a-rune&quot;&gt;stackoverflow&lt;/a&gt;) (&lt;a href=&quot;https://blog.golang.org/strings&quot;&gt;blog.golang.org&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;runes&lt;/strong&gt; are integer values that point to particular unicode code points.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;the stack vs the heap&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-400841088&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://stackoverflow.com/questions/79923/what-and-where-are-the-stack-and-heap&quot;&gt;stackoverflow&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;the &lt;strong&gt;stack&lt;/strong&gt; is an area of memory that uses last-in-first-out access patterns, and is used for rapid access to small data. The term stack can be remembered by thinking of someone quickly stacking a pile of plates as they&apos;re being washed.&lt;/li&gt;
&lt;li&gt;the &lt;strong&gt;heap&lt;/strong&gt; is an area of memory where access is done in an ad-hoc manner, and is used for longer term access to large data. In general, high level scripting languages (ex. ruby and python) allocate most / all of their memory of the heap, for the sake of simplicity at the cost of performance. The term heap can be remembered by thinking of a large pile (eg. a &quot;heap&quot;) of objects scattered about randomly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;golang general concepts&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;goroutines&lt;/strong&gt; &lt;em&gt;(github &lt;a href=&quot;https://github.com/golang/go/issues/27345&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-400843932&quot;&gt;2&lt;/a&gt;) (&lt;a href=&quot;https://gobyexample.com/goroutines&quot;&gt;gobyexample&lt;/a&gt;) (&lt;a href=&quot;https://www.golang-book.com/books/intro/10&quot;&gt;golang-book&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;goroutines&lt;/strong&gt; are &lt;a href=&quot;https://codeburst.io/why-goroutines-are-not-lightweight-threads-7c460c1f155f&quot;&gt;not threads&lt;/a&gt; 😅. They&apos;re go&apos;s concurrency model. goroutines are to go as processes are to a CPU.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;strong&gt;buffering and channels&lt;/strong&gt; &lt;em&gt;(&lt;a href=&quot;https://github.com/golang/go/issues/27345#issuecomment-419254790&quot;&gt;github&lt;/a&gt;) (&lt;a href=&quot;https://gobyexample.com/channel-buffering&quot;&gt;gobyexample&lt;/a&gt;) (&lt;a href=&quot;https://stackoverflow.com/questions/22747711/what-is-the-use-of-buffered-channels-in-go&quot;&gt;stackoverflow&lt;/a&gt;) (&lt;a href=&quot;https://medium.com/capital-one-tech/buffered-channels-in-go-what-are-they-good-for-43703871828&quot;&gt;medium&lt;/a&gt;) (&lt;a href=&quot;https://tour.golang.org/concurrency/3&quot;&gt;tour.golang.org&lt;/a&gt;)&lt;/em&gt;
&lt;ul&gt;
&lt;li&gt;&lt;strong&gt;channels&lt;/strong&gt; are like IPC except for goroutines. They allow communication and synchronization between goroutines. &lt;strong&gt;buffering&lt;/strong&gt; allows channels to act asynchronously by creating little pools (buffers) that each side can interact with without blocking.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Wow! What have we learned?&lt;/h2&gt;
&lt;p&gt;...everything 😆. Interestingly, a lot (most?) of these concepts were concepts that I already had some awareness of, I just wasn&apos;t able to define them. Now empowered with these definitions, when I read issues like &lt;a href=&quot;https://github.com/golang/go/issues/15752&quot;&gt;https://github.com/golang/go/issues/15752&lt;/a&gt; I have a much much stronger understanding of what&apos;s being described.&lt;/p&gt;
&lt;h2&gt;Up next&lt;/h2&gt;
&lt;p&gt;Now that I know &lt;strong&gt;a ton&lt;/strong&gt; more about this space, I can more accurately judge whether or not a particular github issue is a good fit for me to work on. There are several types of issues that I now know aren&apos;t quite a good fit for a first-timer, for example this issue about &lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;improving inlining&lt;/a&gt;. In my next post I&apos;ll setup a more targeted framework for determining who approachable the various issues are, and (🤞🏽ideally🤞🏽) pick one to start working on.&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Golang PR Field Notes (Part 2)]]></title><description><![CDATA[Today we do concept exploration! Tomorrow is concept definition.]]></description><link>https://coilysiren.me/posts/golang-pr-notes-2/</link><guid isPermaLink="false">https://coilysiren.me/posts/golang-pr-notes-2/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Thu, 26 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;if you&apos;re looking for part 1, &lt;a href=&quot;https://coilysiren.me/posts/2019-12-25-golang-pr-field-notes-part-1/&quot;&gt;it&apos;s back this way &amp;#x3C;===&lt;/a&gt;&lt;/p&gt;
&lt;h2&gt;Starting up again&lt;/h2&gt;
&lt;p&gt;Something I under-estimated, is how amazingly useful having my notes &lt;a href=&quot;https://coilysiren.me/posts/2019-12-25-golang-pr-field-notes-part-1/&quot;&gt;from yesterday&lt;/a&gt; would be. Having written so much down gives me a much stronger launching pad for furthering my knowledge, particularly when the alternative is having to remember everything.&lt;/p&gt;
&lt;p&gt;To kick off the day, here&apos;s the list of questions I need to answer:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;what does it mean to build a dependent package, and when do we know that a dependent package needs to be rebuilt?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how many more types of code change do we need to make change the export data?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;what are object files?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do we know when object files are stale?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do we change the export data when object files are stale?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do executables relate to needing to rebuild dependent packages?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;what does it mean to re-link executables?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I need to be able to answer all those questions before I can confidently make any movement here, but I actually don&apos;t want to start on that yet. What I want to do first is do more requirements gathering, because the issue we&apos;re looking at has links to other issues that may contain relevant information.&lt;/p&gt;
&lt;h2&gt;Looking through related issues&lt;/h2&gt;
&lt;p&gt;Related issues often contain context that&apos;s required to fully understand the origin issue. When working in very large repos when potentially complex histories, I read all the issues out two steps from the origin issue. So if I&apos;ve started on issue #101 which mentions #102 which mentions #103 which mentions #104, I&apos;ll read all of #101, #102, and #103 (eg. and not #104). This is essentially a triage mechanism, in a repo as large as golang I could probably spend an entire calendar year just reading issues.&lt;/p&gt;
&lt;p&gt;So here are all the issues mentioned up to 2 steps out, in order of their creation.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/4719&quot;&gt;https://github.com/golang/go/issues/4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/9887&quot;&gt;https://github.com/golang/go/issues/9887&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/8893&quot;&gt;https://github.com/golang/go/issues/8893&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/11193&quot;&gt;https://github.com/golang/go/issues/11193&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/14271&quot;&gt;https://github.com/golang/go/issues/14271&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15681&quot;&gt;https://github.com/golang/go/issues/15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15734&quot;&gt;https://github.com/golang/go/issues/15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15736&quot;&gt;https://github.com/golang/go/issues/15736&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15752&quot;&gt;https://github.com/golang/go/issues/15752&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15756&quot;&gt;https://github.com/golang/go/issues/15756&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15799&quot;&gt;https://github.com/golang/go/issues/15799&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15913&quot;&gt;https://github.com/golang/go/issues/15913&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/17566&quot;&gt;https://github.com/golang/go/issues/17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/17751&quot;&gt;https://github.com/golang/go/issues/17751&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/18981&quot;&gt;https://github.com/golang/go/issues/18981&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/19340&quot;&gt;https://github.com/golang/go/issues/19340&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/20070&quot;&gt;https://github.com/golang/go/issues/20070&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/20137&quot;&gt;https://github.com/golang/go/issues/20137&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/20512&quot;&gt;https://github.com/golang/go/issues/20512&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/20579&quot;&gt;https://github.com/golang/go/issues/20579&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/25056&quot;&gt;https://github.com/golang/go/issues/25056&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/25862&quot;&gt;https://github.com/golang/go/issues/25862&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/25999&quot;&gt;https://github.com/golang/go/issues/25999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/26534&quot;&gt;https://github.com/golang/go/issues/26534&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/27148&quot;&gt;https://github.com/golang/go/issues/27148&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/27345&quot;&gt;https://github.com/golang/go/issues/27345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/28314&quot;&gt;https://github.com/golang/go/issues/28314&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues/29067&quot;&gt;https://github.com/golang/go/issues/29067&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;There&apos;s a lot of them ^^ some of the linked issues are near / exact matches of my search criteria &lt;a href=&quot;https://coilysiren.me/posts/2019-12-25-golang-pr-field-notes-part-1/&quot;&gt;from yesterday&lt;/a&gt;. This is a good sign, it tells me that even if I can&apos;t solve my origin issue, that I&apos;ll be able to use the context I&apos;m gaining to look into a nearby issue.&lt;/p&gt;
&lt;h2&gt;Concept discovery&lt;/h2&gt;
&lt;p&gt;Now what? Well, we need to look through the issues to look for a few things. Red flags, yellow flag, potential PRs that might solve the origin issue, and concepts I don&apos;t understand. The unknown concepts are going to be what requires the most work here, I&apos;ll need to list them out and add gain concrete understanding of them all before I can do any &quot;real work&quot;. Scanning through the issues, here&apos;s those concepts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what is the difference between &lt;code class=&quot;language-text&quot;&gt;$GOROOT/pkg&lt;/code&gt;, &lt;code class=&quot;language-text&quot;&gt;$GOPATH/pkg&lt;/code&gt;? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issue-51282533&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is *.a cache? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issue-51282533&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does &quot;lazy cleaning&quot; mean? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issue-51282533&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are *.a binaries? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-66074024&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are binary-only packages? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-66074026&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the difference between go build and go install? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144121444&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how could go&apos;s build system work without a pkg directory? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144121444&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are object files, what does it mean to link object files? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144125808&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is gb? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-144199351&quot;&gt;#4719&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/14271#issue-132335366&quot;&gt;#14271&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is cgo, what does it mean to be cgo-enabled? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-341861487&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does compilation specifically mean for go? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-470268217&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how do binaries relate to source code? via &lt;a href=&quot;https://github.com/golang/go/issues/4719#issuecomment-470268217&quot;&gt;#4719&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Short pause. Certain people are referenced in these issues a TON. I&apos;m getting the impression that programming languages are only really written by a very small number of people (less than a dozen) who have a lot of support infrastructure (of hundreds or thousands). At any rate, back to concepts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how does go compilation differ from cgo compilation? via &lt;a href=&quot;https://github.com/golang/go/issues/9887#issue-57753156&quot;&gt;#9887&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;does golang support compilation to multiple different target languages, eg. C, C++, and Fortran? if so, why? via &lt;a href=&quot;https://github.com/golang/go/issues/9887#issuecomment-456852196&quot;&gt;#9887&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does the go tool &quot;scheduling work&quot; mean? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issue-51288838&quot;&gt;#8893&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does topological mean, and how could it lead to suboptimal parallelization? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issue-51288838&quot;&gt;#8893&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is critical path scheduling? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issue-51288838&quot;&gt;#8893&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;why is cgo compilation heavy? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issuecomment-73424189&quot;&gt;#8893&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Another aside -- I think I just spotted &lt;a href=&quot;https://github.com/golang/go/issues/8893#issuecomment-100422418&quot;&gt;a remnant&lt;/a&gt; of the point at which golang switched to compiling itself. A quick google and I now know that go was originally written &lt;a href=&quot;https://docs.google.com/document/d/1P3BLR31VA8cvLJLfMibSuTdwTuF7WWLux71CYD0eeD8/preview?pli=1&quot;&gt;in C&lt;/a&gt;. Back to concepts!&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what is asm compilation? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issuecomment-101070036&quot;&gt;#8893&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-256156430&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is SSA? via &lt;a href=&quot;https://github.com/golang/go/issues/8893#issuecomment-134458436&quot;&gt;#8893&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/15736#issue-155612156&quot;&gt;#15736&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-256149722&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how do you avoid recompiling a package every time you run tests? via &lt;a href=&quot;https://github.com/golang/go/issues/11193#issuecomment-229522796&quot;&gt;#11193&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to compile versus to link? via &lt;a href=&quot;https://github.com/golang/go/issues/14271#issue-132335366&quot;&gt;#14271&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is cmd/go? via &lt;a href=&quot;https://github.com/golang/go/issues/14271#issue-132335366&quot;&gt;#14271&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is bazel? via &lt;a href=&quot;https://github.com/golang/go/issues/14271#issuecomment-181840701&quot;&gt;#14271&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Did you know -- if you&apos;re spending hours reading GitHub issues in the winter, you can concurrently be applying lotion to your dry skin? It&apos;s true! Anyways.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what are go:cgo_import_dynamic directives? via &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-239866168&quot;&gt;#15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the relationship between golang and C? what is the relationship between c compilations and the linker? via &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-240319812&quot;&gt;#15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how do .a files relate to .o files? via &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-380967328&quot;&gt;#15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are .c files? via &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-380967328&quot;&gt;#15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;does golang use gcc? via &lt;a href=&quot;https://github.com/golang/go/issues/15681#issuecomment-380967328&quot;&gt;#15681&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the difference between export data and machine code? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issue-155608860&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are inlined functions? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issue-155608860&quot;&gt;#15734&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to walk a function? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issue-155608860&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a semaphore? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220172384&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a VFS? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220172384&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how do processes communicate with each other? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220172384&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;how does export data relate to .a files? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-220173676&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the relationship between export data and objects? via &lt;a href=&quot;https://github.com/golang/go/issues/15734#issuecomment-339211682&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is cmd/go? via &lt;a href=&quot;https://github.com/golang/go/issues/15736#issue-155612156&quot;&gt;#15734&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Something I&apos;ve noticed while writing this, is that the detail amount of time I can spend reading before encountering a new unknown concept is increasing. I&apos;m also gaining some understanding of the unknown concepts simply via seeing them mentioned in context, eg. without needing to look up their definitions. That said, the next step will definitely be to look up definitions ^^. Alright, back to concepts.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;how are go&apos;s cmds organized, eg. cmd/go vs cmd/compile, etc? via &lt;a href=&quot;https://github.com/golang/go/issues/15736#issuecomment-220181188&quot;&gt;#15736&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is typechecking? via &lt;a href=&quot;https://github.com/golang/go/issues/15756#issue-155838129&quot;&gt;#15756&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is escape analysis? via &lt;a href=&quot;https://github.com/golang/go/issues/15756#issue-155838129&quot;&gt;#15756&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what steps are required for compilation? via &lt;a href=&quot;https://github.com/golang/go/issues/15756#issue-155838129&quot;&gt;#15756&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to &quot;rebuild even when target is up to date&quot; eg. what is the target of builds? via &lt;a href=&quot;https://github.com/golang/go/issues/15799#issue-156283605&quot;&gt;#15799&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is yyerrorn? via &lt;a href=&quot;https://github.com/golang/go/issues/15913#issue-157781645&quot;&gt;#15913&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a gc node? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are OKEY and OAPPEND nodes? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to inline during compilation? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are bounds checks? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt; and &lt;a href=&quot;https://github.com/golang/go/issues/25862#issue-331945781&quot;&gt;#25862&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does &quot;generating code&quot; mean in the context of compilation? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what would be the benefit of inlining performance critical functions? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the cost of inlining a function? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issue-184877974&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a pragma? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-256139958&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is closure conversion? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-256149722&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to export a function? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-262118244&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is zero-cost control flow abstraction? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-385211150&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is an intrinsic? via &lt;a href=&quot;https://github.com/golang/go/issues/17566#issuecomment-417111586&quot;&gt;#17566&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I just went through an entire (long) issue without noticing any new concepts! Exciting.&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;what is the binary export format? via &lt;a href=&quot;https://github.com/golang/go/issues/20070#issuecomment-296292391&quot;&gt;#20070&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a package archive? via &lt;a href=&quot;https://github.com/golang/go/issues/20579#issue-233602713&quot;&gt;#20579&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are registers? via &lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-399196221&quot;&gt;#25999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to spill a register? via &lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-399199303&quot;&gt;#25999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is the stack, and how does it relate to optimization? via &lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-400841088&quot;&gt;#25999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what does it mean to preempt a goroutine with signals? via &lt;a href=&quot;https://github.com/golang/go/issues/25999#issuecomment-400843932&quot;&gt;#25999&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what are runes? via &lt;a href=&quot;https://github.com/golang/go/issues/27148#issuecomment-415131187&quot;&gt;#27148&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a goroutine? via &lt;a href=&quot;https://github.com/golang/go/issues/27345#issue-355263332&quot;&gt;#27345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is an unbuffered channel? via &lt;a href=&quot;https://github.com/golang/go/issues/27345#issuecomment-419254790&quot;&gt;#27345&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is BCE? via &lt;a href=&quot;https://github.com/golang/go/issues/28314&quot;&gt;#28314&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is morestack? via &lt;a href=&quot;https://github.com/golang/go/issues/29067&quot;&gt;#29067&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is a branch target buffer, what are backwards versus forward branches? via &lt;a href=&quot;https://github.com/golang/go/issues/29067#issuecomment-443587472&quot;&gt;#29067&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;what is icache? via &lt;a href=&quot;https://github.com/golang/go/issues/29067#issuecomment-443887583&quot;&gt;#29067&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Wow that was exhausting&lt;/h2&gt;
&lt;p&gt;So here&apos;s what we did:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dropped into the golang issue tracker with a specific learning goal in mind&lt;/li&gt;
&lt;li&gt;found a specific issue, and walked through all the related issue for concepts that need to be learned&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;And here&apos;s what we will do next:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;define and understand most (not all) of the concepts, focusing on hotspots&lt;/li&gt;
&lt;li&gt;return to the original issue, and determine if we have enough information to create a fix (likely yes, 90% confidence)&lt;/li&gt;
&lt;li&gt;start working on a fix&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;That&apos;ll come later! For today, I&apos;m headed back to video games.&lt;/p&gt;
&lt;h2&gt;Up next&lt;/h2&gt;
&lt;p&gt;===&gt; &lt;a href=&quot;https://coilysiren.me/posts/2019-12-29-golang-pr-field-notes-part-3/&quot;&gt;part 3 is this way&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Golang PR Field Notes (Part 1)]]></title><description><![CDATA[I'm writing these notes as a part of my grand quest to make a performance improvement to Golang!]]></description><link>https://coilysiren.me/posts/golang-pr-notes-1/</link><guid isPermaLink="false">https://coilysiren.me/posts/golang-pr-notes-1/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Wed, 25 Dec 2019 00:00:00 GMT</pubDate><content:encoded>&lt;h2&gt;Identifying an issue&lt;/h2&gt;
&lt;p&gt;I started with of the following search:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;open issues&lt;/li&gt;
&lt;li&gt;that need a fix&lt;/li&gt;
&lt;li&gt;that don&apos;t have a CL (eg. &lt;a href=&quot;https://news.ycombinator.com/item?id=20891103&quot;&gt;a changelist&lt;/a&gt;)&lt;/li&gt;
&lt;li&gt;that aren&apos;t planned to be fixed by the go team&lt;/li&gt;
&lt;li&gt;about toolspeed&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;a href=&quot;https://github.com/golang/go/issues?utf8=%E2%9C%93&amp;#x26;q=is%3Aopen+label%3AToolSpeed+label%3ANeedsFix+NOT+%22golang.org%2Fcl%22+milestone%3AUnplanned+&quot;&gt;From this url&lt;/a&gt;. There were a few considerations that went into that search. In my experience with open source, and also under the guidance of go&apos;s &lt;a href=&quot;https://golang.org/doc/contribute.html#before_contributing&quot;&gt;contributing guide&lt;/a&gt;, I determined that &lt;em&gt;&quot;open issues that will take a fix, but no fix is planned&quot;&lt;/em&gt; is the best path for contribution. They essentially say &lt;em&gt;&quot;we will take a fix that looks like this, if anyone drops in to create it&quot;&lt;/em&gt;. The golang issue tracker separates &quot;backlog&quot; from &quot;unplanned&quot;, which I learned about here =&gt; &lt;a href=&quot;https://github.com/golang/go/issues/34376&quot;&gt;https://github.com/golang/go/issues/34376&lt;/a&gt;. I assume that a backlog issue may have someone on the golang team drop in and sweep it out from under me, whereas unplanned issues are free game essentially indefinitely. I&apos;ve had a variant of that happen to me before, where I created a PR for django and then a maintainer decided to &lt;a href=&quot;https://github.com/django/django/pull/9016#issuecomment-373777203&quot;&gt;take some of my work and start their own PR&lt;/a&gt;. So, I&apos;m painfully allergic to that happening again here.&lt;/p&gt;
&lt;p&gt;The focus on toolspeed is inspired by my learning goals, I go into that briefly on twitter here =&gt; &lt;a href=&quot;https://twitter.com/coilysiren/status/1209628089346490368&quot;&gt;https://twitter.com/coilysiren/status/1209628089346490368&lt;/a&gt;. There&apos;s another label that fits my learning goal, the &quot;performance&quot; label. Here&apos;s both the toolspeed and performance searches, mostly for my future reference:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues?utf8=%E2%9C%93&amp;#x26;q=is%3Aopen+label%3AToolSpeed+label%3ANeedsFix+NOT+%22golang.org%2Fcl%22+milestone%3AUnplanned+&quot;&gt;toolspeed&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/golang/go/issues?q=is%3Aopen+label%3ANeedsFix+NOT+%22golang.org%2Fcl%22+milestone%3AUnplanned+label%3APerformance&quot;&gt;performance&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;h2&gt;Short aside on labeling&lt;/h2&gt;
&lt;p&gt;If you can&apos;t tell from my methodology here, accurately labeling issues is critically import for new contributors. When I first drop into a repo, &lt;a href=&quot;https://github.com/golang/go/labels&quot;&gt;the labels&lt;/a&gt; are the first thing I look at. There&apos;s a lot of new information to ingest when entering a repo, and often the labels are the best &quot;front door&quot;.&lt;/p&gt;
&lt;p&gt;This makes accurately labeling issues a fairly high priority concern for repository maintainers, in my opinion. I was very happy to see &lt;a href=&quot;https://discuss.python.org/t/proposal-create-bug-triage-team-on-github/992&quot;&gt;a cpython proposal&lt;/a&gt; by &lt;a href=&quot;https://twitter.com/mariatta&quot;&gt;Mariatta&lt;/a&gt; on creating a &quot;bug triage&quot; role. Essentially the entire job of that role is to apply labels. I would totally apply to that role, if contributing to cpython looked like it would helpful for my career. But it&apos;s looking like golang is going to be where my interests lie, so that&apos;s why you&apos;re reading a post about golang.&lt;/p&gt;
&lt;h2&gt;Exploring the issue&lt;/h2&gt;
&lt;p&gt;So, with the previously mentioned search as my guide, I went for the first issue that looked the most approachable. &quot;Approachable&quot; here is a subjective definition, it translates roughly to &quot;do I feel capable of doing this&quot;. The issue I picked was:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;&lt;a href=&quot;https://github.com/golang/go/issues/15752&quot;&gt;https://github.com/golang/go/issues/15752&lt;/a&gt;&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;cmd/go: only rebuild dependent packages when export data has changed&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From the title, I determined that the issue relies on core understanding of two concepts:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;dependent packages (which I understand)&lt;/li&gt;
&lt;li&gt;export data (which is unknown to me)&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This prompts our focus to revolve around the &quot;export data&quot; concept. There is a particular dependency in this issue on &quot;the export data changing&quot; which is a pre-requisite for making any enhancements based on that fact. That is, in order to create any logic that relies on diffs in the export data, we have to be able to fully trust that diffs in the export data are sufficiently reliable to make decisions. We can state that fact without first even having an understanding of what &quot;export data&quot; is.&lt;/p&gt;
&lt;p&gt;The export data reliability point comes up in the issues description, specifically in this line&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not sure how often it happens that code changes don&apos;t impact export data (or how cheap that is to detect), but when it does happen, that could save a bunch of computation.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;From this context I&apos;m able to determine that &quot;export data&quot; means something like &quot;metadata about a function&quot;. I assume that the export data contains some basic information about a function of package, such as last edited time / file size / function signatures / etc.&lt;/p&gt;
&lt;p&gt;There&apos;s one part here that&apos;s particularly important to emphasize&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Not sure how often it happens that code changes don&apos;t impact export data&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;So golang teams&apos; current understanding is that it&apos;s unknown if the export data is currently reliable enough to make decisions based on it. At this point, I&apos;m starting to reframe the issue into two separate tasks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;only rebuild dependent packages when export data has changed &lt;em&gt;(the original task)&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;change the export data for a dependent package whenever that package needs to be rebuilt &lt;em&gt;(a derived task from the above)&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;This surfaces another question, specifically: &lt;em&gt;&lt;strong&gt;what does it mean to build a dependent package, and when do we know that a dependent package needs to be rebuilt?&lt;/strong&gt;&lt;/em&gt; Being able to answer that question is a pre-requisite to writing code for the conditional rebuilding of dependent packages. This creates a set of subtasks, specifically&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;change the export data during (case 1)&lt;/li&gt;
&lt;li&gt;change the export data during (case 2)&lt;/li&gt;
&lt;li&gt;etc...&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;Further comments give more information about the export data concept&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;the plan would be to do something like check the SHA of the export data. If that hasn&apos;t changed, then the &lt;strong&gt;downstream compilation won&apos;t change&lt;/strong&gt;.&lt;/p&gt;
&lt;p&gt;...&lt;/p&gt;
&lt;p&gt;Yeah, I was just thinking that you&apos;d store the SHA1 of the export data of&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;all imported packages in the .a file and only recompile if any of them had
changed. No sense trying to be too sophisticated.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I don&apos;t know often this would be useful. Certainly sometimes (especially in&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;a &lt;strong&gt;&quot;add more and more debug prints&quot;&lt;/strong&gt; cycle)&lt;/p&gt;
&lt;p&gt;Emphasis mine. So part of the goal is to avoid rebuilding a dependent package if you&apos;ve made trivial internal changes to it, like for example adding some debugging prints.&lt;/p&gt;
&lt;p&gt;Further down the thread I&apos;m seeing several people mention that they&apos;re working on some portion of this (&lt;a href=&quot;https://github.com/golang/go/issues/15752#issuecomment-220458227&quot;&gt;1&lt;/a&gt;, &lt;a href=&quot;https://github.com/golang/go/issues/15752#issuecomment-313510033&quot;&gt;2&lt;/a&gt;) which gives me some pause. But those comments are from years ago, so I believe I&apos;m in the clear.&lt;/p&gt;
&lt;p&gt;Another comment by the author further reinforces the direction I believe this should be approached from&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Is this now just (“just”) a matter of only hashing the export data when determining whether object files are stale?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;specifically my note about &lt;em&gt;change the export data during...&lt;/em&gt; above. This comment surfaces some new questions, specifically:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;what are object files?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do we know when object files are stale?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do we change the export data when object files are stale?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;The final comment in this issue is a wildcard for me, it says&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;I think it&apos;s a little bit more than that because you still need to re-link any executables?&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;This statement is hard for me to parse, and raises several questions:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;how do executables relate to needing to rebuild dependent packages?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;li&gt;&lt;em&gt;&lt;strong&gt;what does it mean to re-link executables?&lt;/strong&gt;&lt;/em&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;I know that executables are a type of asset produced by a build process. Specifically I believe that &lt;code class=&quot;language-text&quot;&gt;go build ...&lt;/code&gt; produces executables. It was my understanding that go build produced a single &lt;a href=&quot;https://en.wikipedia.org/wiki/Static_library#Linking_and_loading&quot;&gt;statically linked&lt;/a&gt; executable, but I now believe that understanding is incorrect. My new understanding is that &lt;code class=&quot;language-text&quot;&gt;go build ...&lt;/code&gt; possibly creates multiple executables, perhaps one for each package? If you were conditionally rebuilding executables based on export data, then you would end up with multiple executables where some of them are outdated and need to be pointed to new links? I&apos;ll be sure to investigate this.&lt;/p&gt;
&lt;h2&gt;Next steps&lt;/h2&gt;
&lt;p&gt;So far we&apos;ve identified the following:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;there is a problem I can solve here&lt;/li&gt;
&lt;li&gt;the desired solution has some performance impact&lt;/li&gt;
&lt;li&gt;I don&apos;t currently possess all the knowledge I need to solve them problem, but the amount of knowledge that I need to gain feels reasonable&lt;/li&gt;
&lt;li&gt;there is some active work on this issue, but not so much active work that my contributions would be invalidated&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;In summary, there&apos;s work to do! My next step is to double down on investigating this issue, and gain any surrounding context that I might need.&lt;/p&gt;
&lt;h2&gt;Up next&lt;/h2&gt;
&lt;p&gt;===&gt; &lt;a href=&quot;https://coilysiren.me/posts/2019-12-26-golang-pr-field-notes-part-2/&quot;&gt;part 2 is this way&lt;/a&gt;&lt;/p&gt;</content:encoded></item><item><title><![CDATA[The Maintainer - Aspect of Code Janitor]]></title><description><![CDATA[The code janitor is a servant leader of the codebase.]]></description><link>https://coilysiren.me/posts/code-janitor/</link><guid isPermaLink="false">https://coilysiren.me/posts/code-janitor/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Sat, 27 Jul 2019 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;The code janitor is a servant leadership of a codebase. They use their skills primarily to increase the software engineering velocity of the team as a whole / increase the stability of the code. Their roles are such:&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Encourage continually better code pratices&lt;/strong&gt; in your coworkers. If they mention writing code they haven&apos;t pushed to a remote branch, get them to push that branch! If they push code without tests, get them to write tests! Continually iterate on best practices for branching and test coverage. Good branching enables good review and helps avoid duplication of work. The benefits of good tests are a subject for another post ^^. &quot;Better code practices&quot; is a continously moving target, so the code janitor must also be tuned into a technical community to stay up to date on them.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Proactively review =&gt; merge&lt;/strong&gt; the pull requests of coworkers / community members. Coworker&apos;s PRs should all be reviewed at least every 24 hours. Community member&apos;s PRs should be reviewed all be reviewed at least every 7 days. If you&apos;re approaching a time limit and aren&apos;t sure what feedback to give, really push yourself to surface why a pull request shouldn&apos;t be merged.  Continuous proactive reviews are a powerful tool for surfacing people&apos;s blockers.&lt;/p&gt;
&lt;p&gt;As a special case for reviews and merges, the code janitor should &lt;strong&gt;maintain a requirements bot&lt;/strong&gt;. The benefits of a requirements bot are described in &lt;a href=&quot;https://coilysiren.me/post/requirements-maint&quot;&gt;another post&lt;/a&gt;. The timelines for requirements updates should be relative to the &lt;a href=&quot;https://semver.org/&quot;&gt;semver&lt;/a&gt; range of the update, and the type of update. For example, security patches should be merged within 24 hours.&lt;/p&gt;
&lt;p&gt;Tangentially related to maintaining your current set of requirements, is &lt;strong&gt;watching for competitor libraries&lt;/strong&gt;. When your team&apos;s use of a tool is non-standard / non-ideal, its often a good target for being replaced by a competitor. For the majority of your libraries this won&apos;t be an option, but there&apos;s some cases where its easily possible. Switching my team&apos;s &lt;a href=&quot;https://github.com/ambv/black&quot;&gt;code formatter&lt;/a&gt; and &lt;a href=&quot;https://github.com/mochajs/mocha&quot;&gt;test framework&lt;/a&gt; are two examples of this. A good code janitor developes a sense for where / when these switches can happen, and is keyed into the communities where these libraries are created.&lt;/p&gt;
&lt;p&gt;Watch how your coworkers are interacting with the linter config. Ask your coworkers how they are interacting with the linter config! Be very receptive to &lt;strong&gt;changing the linter config&lt;/strong&gt; over time, as personal styles shift. Definitely change linter config whenever you get a new coworker of at least median skill level, they know what works well for them. The gold standard is config that minizes the time programmers spend thinking about formatting, while also completely preventing the possibility of Formatting Wars.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Driving refactor plans&lt;/strong&gt;, such as:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;renames&lt;/li&gt;
&lt;li&gt;merging projects / splitting projects apart&lt;/li&gt;
&lt;li&gt;open sourcing all of / parts of a project&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;strong&gt;Identifying technical debt&lt;/strong&gt;, and surfacing the relative priority of reducing that debt to team managers. Issues of technical debt can often be hard to communicate, so part of this work should involve configuring tools that assist in objective code analysis. This very related to driving refactor plans.&lt;/p&gt;
&lt;p&gt;There&apos;s more to say here, but this post is long and the day is short. I hope this helps you become a better project maintainer!&lt;/p&gt;</content:encoded></item><item><title><![CDATA[Heroku + Django Pipeline + Sass]]></title><description><![CDATA[A currently existing django project, hosted on heroku, with a bunch of css]]></description><link>https://coilysiren.me/posts/heroku-django-sass/</link><guid isPermaLink="false">https://coilysiren.me/posts/heroku-django-sass/</guid><dc:creator><![CDATA[@coilysiren]]></dc:creator><pubDate>Thu, 30 Mar 2017 00:00:00 GMT</pubDate><content:encoded>&lt;h3&gt;What you have&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;A currently existing django project, hosted on heroku, with a bunch of css&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;What you want&lt;/h3&gt;
&lt;ul&gt;
&lt;li&gt;to have your css compiled from sass&lt;/li&gt;
&lt;li&gt;for that compilation to be done with ruby, during the heroku build&lt;/li&gt;
&lt;/ul&gt;
&lt;h3&gt;How you get it&lt;/h3&gt;
&lt;p&gt;heroku setup&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# bash&lt;/span&gt;

heroku buildpacks:add heroku/ruby &lt;span class=&quot;token parameter variable&quot;&gt;--index&lt;/span&gt; &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt; &lt;span class=&quot;token parameter variable&quot;&gt;--app&lt;/span&gt; &lt;span class=&quot;token variable&quot;&gt;$APP_NAME&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;django pipeline setup&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;python&quot;&gt;&lt;pre class=&quot;language-python&quot;&gt;&lt;code class=&quot;language-python&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# config/settings/base.py&lt;/span&gt;

&lt;span class=&quot;token comment&quot;&gt;# snipped to only the relevant bit, see django pipeline&apos;s docs for the rest&lt;/span&gt;
PIPELINE &lt;span class=&quot;token operator&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;{&lt;/span&gt;
    &lt;span class=&quot;token string&quot;&gt;&apos;COMPILERS&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;:&lt;/span&gt; &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;
        &lt;span class=&quot;token string&quot;&gt;&apos;pipeline.compilers.sass.SASSCompiler&apos;&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
    &lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;&lt;span class=&quot;token punctuation&quot;&gt;,&lt;/span&gt;
&lt;span class=&quot;token punctuation&quot;&gt;}&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;sass setup&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;ruby&quot;&gt;&lt;pre class=&quot;language-ruby&quot;&gt;&lt;code class=&quot;language-ruby&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# Gemfile&lt;/span&gt;

source &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;https://rubygems.org&quot;&lt;/span&gt;&lt;/span&gt;
ruby &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&apos;2.3.3&apos;&lt;/span&gt;&lt;/span&gt;

gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;sass&quot;&lt;/span&gt;&lt;/span&gt;
gem &lt;span class=&quot;token string-literal&quot;&gt;&lt;span class=&quot;token string&quot;&gt;&quot;susy&quot;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;h4&gt;Ok but that didn&apos;t work&lt;/h4&gt;
&lt;p&gt;or at least it didn&apos;t for me, I got this (formatted for readability) error&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;pipeline.exceptions.CompilerError: &lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;filter object at 0x133&lt;span class=&quot;token operator&quot;&gt;&lt;span class=&quot;token file-descriptor important&quot;&gt;7&lt;/span&gt;&gt;&lt;/span&gt; &lt;span class=&quot;token builtin class-name&quot;&gt;exit&lt;/span&gt; code &lt;span class=&quot;token number&quot;&gt;1&lt;/span&gt;
b&quot;/tmp/DIR/vendor/ruby-2.3.3/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in &lt;span class=&quot;token variable&quot;&gt;&lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;require&apos;:
    cannot load such &lt;span class=&quot;token function&quot;&gt;file&lt;/span&gt; -- bundler/setup &lt;span class=&quot;token punctuation&quot;&gt;(&lt;/span&gt;LoadError&lt;span class=&quot;token punctuation&quot;&gt;)&lt;/span&gt;
    from /tmp/DIR/vendor/ruby-2.3.3/lib/ruby/2.3.0/rubygems/core_ext/kernel_require.rb:55:in &lt;span class=&quot;token variable&quot;&gt;`&lt;/span&gt;&lt;/span&gt;require&apos;
    from /tmp/DIR/vendor/bundle/bin/sass:15:in `&lt;span class=&quot;token operator&quot;&gt;&amp;lt;&lt;/span&gt;main&lt;span class=&quot;token operator&quot;&gt;&gt;&lt;/span&gt;&quot;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;From that message, it occurred to me that maybe python wasn&apos;t calling the right &lt;code class=&quot;language-text&quot;&gt;sass&lt;/code&gt;. Which inspired the following &quot;fix&quot;&lt;/p&gt;
&lt;h4&gt;How you get it, but for real this time&lt;/h4&gt;
&lt;p&gt;Install your gems to whatever &lt;code class=&quot;language-text&quot;&gt;ruby&lt;/code&gt; / &lt;code class=&quot;language-text&quot;&gt;sass&lt;/code&gt; the python buildpack is calling&lt;/p&gt;
&lt;div class=&quot;gatsby-highlight&quot; data-language=&quot;bash&quot;&gt;&lt;pre class=&quot;language-bash&quot;&gt;&lt;code class=&quot;language-bash&quot;&gt;&lt;span class=&quot;token comment&quot;&gt;# bin/pre_compile&lt;/span&gt;
gem &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt; bundler
bundle &lt;span class=&quot;token function&quot;&gt;install&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;
&lt;p&gt;(&lt;code class=&quot;language-text&quot;&gt;pre_compile&lt;/code&gt; is a hook for the python buildpack)&lt;/p&gt;
&lt;p&gt;Does this mean &lt;code class=&quot;language-text&quot;&gt;heroku buildpacks:add heroku/ruby --index 1&lt;/code&gt; is unused? Someone investigate this and &lt;a href=&quot;https://twitter.com/coilysiren&quot;&gt;let me know&lt;/a&gt;.&lt;/p&gt;
&lt;h3&gt;Get this fixed for good!&lt;/h3&gt;
&lt;p&gt;One of the devs of the projects below will know what&apos;s up&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/jazzband/django-pipeline&quot;&gt;https://github.com/jazzband/django-pipeline&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/heroku/heroku-buildpack-ruby&quot;&gt;https://github.com/heroku/heroku-buildpack-ruby&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href=&quot;https://github.com/heroku/heroku-buildpack-python&quot;&gt;https://github.com/heroku/heroku-buildpack-python&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;But if you want a fix for your project, the &lt;code class=&quot;language-text&quot;&gt;pre_compile&lt;/code&gt; script will work fine&lt;/p&gt;</content:encoded></item></channel></rss>