Week 14 - Infrastructure as Code

Why use Infrastructure as Code

IaC concepts

Azure Bicep

Bicep in practice

Deploy Bicep from CI/CD

Practice

Assignment

Gotchas & Pitfalls

Glossary: Week 14

Career relevance: Week 14

History of IaC

Slides (PDF)

Practice

This is an end-of-week synthesis page, not a chapter-by-chapter drill. Work through it after Why use Infrastructure as Code, IaC concepts, Azure Bicep, Bicep in practice, and Deploy Bicep from CI/CD.

Every exercise builds on the same template (main.bicep, then a modules/storage.bicep sibling) rather than starting fresh each time. That ladder is the same shape as the assignment: deploy, env-parameterize, modularize with a nested container, preview, commit a Bicep workflow, tear down, write up.

One deliberate reset: Exercise 4 starts from the chapter state again, without the environment parameter you add in Exercise 2. That is not a mistake. Environment tags come back as Task 1 of the assignment, on top of the module split. If you keep working in your own file instead of switching branches, keep the environment parameter: nothing later removes it.

<aside> πŸ“ Practice exercises are recommended but optional. They are the fastest way to turn this week's reading into a skill you can show in an interview.

</aside>

Clone the reference repo once for local az work on Exercises 1 to 5, 7, and 8. Exercise 6 uses your assignment fork instead.

<aside> πŸ“¦ Reference repo: Clone azure-bicep-reference once if you have not already. Chapter starters are week-14-ch-3-bicep / week-14-ch-4-bicep. Each practice exercise below that needs Bicep has a matching week-14-practice-exercise-* branch with EXERCISE.md at the repo root, plus a -solution branch to compare when you are stuck. Do not put Actions secrets on the reference repo.

</aside>

git clone <https://github.com/lassebenni/azure-bicep-reference.git>
cd azure-bicep-reference
git switch week-14-practice-exercise-deploy-storage   # then read EXERCISE.md

Before you start:

az login
export CLASS_RG=rg-hyf-students   # replace if your teacher gave a different name

Confirm az account show points at the shared HYF subscription, and that you can deploy into $CLASS_RG (students cannot create resource groups themselves). Use a unique storage name (lowercase, 3 to 24 chars) so you do not collide with classmates.

If it names a different subscription, or an N/A(tenant level account) entry, you are pointed somewhere else. List what you have and pick the shared one:

az account list --all --output table
az account set --subscription "<the shared HYF subscription>"

Anyone with a personal Azure for Students subscription will hit this: the CLI keeps one default across every tenant you have signed into, and it is not always the one you want.

Because $CLASS_RG is shared, every what-if you run below also lists your classmates' accounts with a * (Ignore). Those lines are not yours and will not change: read only the line carrying your own sthyf… name. Reading a noisy preview covers the rest of the symbols.

<aside> πŸ’‘ Using AI to help: Paste your main.bicep (no secrets) and ask an LLM to suggest a module split or a what-if-friendly parameter set. Always run az deployment group what-if yourself before you apply anything. (⚠️ no real data, no PII)

</aside>

Suggested pacing

<aside> πŸ’­ If you get blocked for more than 20 minutes, write what you tried, ask for help, and continue with the next exercise. This is professional behavior, not failure.

</aside>

Where the exercises live

Exercise Primary chapter(s) What you produce
1: Deploy a single resource Azure Bicep Storage account from main.bicep + portal Deployments row
2: Parameterize for environments Azure Bicep, IaC concepts, Bicep in practice One account; Environment tag flipped via parameter + what-if
3: Spot and correct drift IaC concepts Hand-made drift that what-if reports and a re-deploy erases
4: Modularize, nest, and preview Bicep in practice modules/storage.bicep + nested raw + idempotent what-if
5: Keep a secret out of the file Bicep in practice @secure() param; no secret string in git
6: Commit a Bicep workflow Deploy Bicep from CI/CD .github/workflows/bicep.yml on your assignment fork
7: Tear down Bicep in practice Practice storage account deleted; $CLASS_RG still exists
8: The write-up Why use Infrastructure as Code, IaC concepts Half-page teammate note (portfolio material)

Attempt each exercise yourself first, then check the walkthrough toggle or the -solution branch. Do not open solution branches before trying: they are for catching up, not for skipping the thinking.

Exercise 1: deploy a single resource

Concepts: Bicep resource, az deployment group create, portal Deployments view.

Primary chapter(s): Azure Bicep

<aside> πŸ“¦ Branch: week-14-practice-exercise-deploy-storage with EXERCISE.md; compare against week-14-practice-exercise-deploy-storage-solution.

</aside>

Write a Bicep template that creates one storage account, and deploy it with az deployment group create --resource-group "$CLASS_RG" .... Confirm it reports Succeeded and find the deployment in the portal's Deployments view.

Success: a storage account you created from a text file, not a portal form.

Exercise 2: parameterize for environments

Concepts: parameters, location default, environments via one template, what-if modify preview.

Primary chapter(s): Azure Bicep, IaC concepts, Bicep in practice

<aside> πŸ“¦ Branch: week-14-practice-exercise-env-tags with EXERCISE.md; compare against week-14-practice-exercise-env-tags-solution.

</aside>

Keep one storage account. Add parameters for storageName, location (default to the resource group's region), and environment (for example dev or prod). Set a tag on the account from that parameter, for example tags: { Environment: environment }.

  1. Deploy with environment=dev (and your unique storageName).
  2. Run az deployment group what-if with the same storageName and environment=prod. Read the diff: you should see a tag modification, not a new storage account (same shape as the modify screenshot in Bicep in practice).
  3. Deploy the prod parameter set.

That is the "one template, many environments" idea from IaC concepts: a parameter change, not a second resource.

Success: one storage account whose Environment tag you changed via a parameter; what-if showed the tag update before you applied it.

Exercise 3: spot and correct drift

Concepts: drift, what-if as detection, re-deploy as correction.

Primary chapter(s): IaC concepts

No new branch here. Keep the template from Exercise 2, the one with the environment parameter and the Environment tag, and keep the account you just deployed.

IaC concepts defined drift as the gap between your template and what is actually running. So far you have only seen what-if react to changes you made in the file. Now you make the gap from the other side, by hand, and watch Bicep find it.

  1. In the portal, open your sthyf… storage account, go to Tags, and change Environment to a value your template does not say, for example staging. Save. Your live infrastructure and your file now disagree.
  2. In the terminal, run az deployment group what-if with the same parameters you last deployed (environment=prod). Change nothing in the file.
  3. Read the output. You should see a ~ (modify) on the tag: the live value on one side, the value your template wants on the other. That is detection.
  4. Run az deployment group create with those same parameters. The template wins and the tag goes back to prod. That is correction.
  5. Run what-if one more time. Your account line reads = and the summary says 1 no change (plus any classmates' * lines).

This is the loop behind the rule in IaC concepts: change the file, never the portal. The portal edit did not survive the next deploy, and anyone reading your template would never have known it happened.

Success: you created drift by hand, what-if reported it before you touched anything, and a re-deploy erased it.

Exercise 4: modularize, nest, and preview

Concepts: modules, nested container, what-if, idempotent re-deploy.

Primary chapter(s): Bicep in practice

<aside> πŸ“¦ Branch: week-14-practice-exercise-modularize-nest with EXERCISE.md; compare against week-14-practice-exercise-modularize-nest-solution.

</aside>

Move the storage account into modules/storage.bicep and call it from main.bicep. Add the nested blob container under the account (default blob service + parent:), as in Bicep in practice. Before redeploying, run az deployment group what-if --resource-group "$CLASS_RG" ... and read the diff. Deploy, then run what-if again with no changes and confirm the storage account line reads =. The container lines stay noisy: see Reading a noisy preview.

<aside> ⚠️ If you switch to this exercise's branch and redeploy with the same storageName you used in Exercise 2, the Environment tag disappears: this template does not declare it, so Azure removes it. Read the what-if output before you apply. Either use a different storageName here, or carry your environment parameter over from Exercise 2.

</aside>

Success: module call in main.bicep; nested container visible in the portal; second what-if shows = on the storage account and no + create.

Exercise 5: keep a secret out of the file

Concepts: @secure() parameters, secrets discipline.

Primary chapter(s): Bicep in practice

<aside> πŸ“¦ Branch: week-14-practice-exercise-secure-param with EXERCISE.md; compare against week-14-practice-exercise-secure-param-solution.

</aside>

Add a @secure() parameter to your template (a dummy unused value is fine for practice; nothing here needs a real secret). Pass it at deploy time without writing the value into any committed file. Confirm the .bicep you would push to git contains no literal secret. The assignment expects this hygiene.

Success: @secure() in the template; no secret string in any file you would commit.

Exercise 6: commit a Bicep workflow

Concepts: GitHub Actions, PR what-if, merge create, AZURE_CREDENTIALS.

Primary chapter(s): Deploy Bicep from CI/CD

This exercise lives on your fork of c55-data-week-14, not on the reference clone. Confirm .github/workflows/bicep.yml from Deploy Bicep from CI/CD is committed (what-if on pull request, create on merge to main). If you skipped that chapter's Hands on, add that file now. A green Actions log is optional and makes most sense after you extend the Ch4-complete starter on that fork (assignment Tasks 1–3: environment tags + curated, then deploy).

Success: .github/workflows/bicep.yml is on the assignment fork and matches the Deploy Bicep from CI/CD shape (azure/login, what-if on PR, create on main).