Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Iac/oci tf cookbook #35

Open
wants to merge 5 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 70 additions & 0 deletions oci-tf-cookbook/ad-by-number.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
---
title: Get the AD name by user-friendly number
series: oci-tf-cookbook
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source, terraform, iac, devops]
solution_names: [Administrative Domain - get AD name by the AD number,AD - get AD name by the AD number,IAM - get AD name by the number]
---

## Problem
Rather than use the AD name, it'd be nice to use the AD number.

## Solution
Use a handy [data source](https://registry.terraform.io/providers/hashicorp/oci/latest/docs/data-sources/identity_availability_domains) to make this happen:
```
data "oci_identity_availability_domains" "this" {
compartment_id = var.tenancy_ocid
}
```

Then within your resource definition(s), use the data source:
```
resource "oci_core_instance" "this" {
availability_domain = data.oci_identity_availability_domains.ads.availability_domains[0].name
...
}
```

This could be abbreviated with a local, such as:
```
locals {
ad_names = { for y in data.oci_identity_availability_domains.this.availability_domains :
index(data.oci_identity_availability_domains.this.availability_domains, y) => y.name
}
}
```

This can be used as follows:
```
resource "oci_core_instance" "this" {
availability_domain = local.ad_names[0]
...
}
```

Note that this uses zero-index array, with index 0 being AD 1, index 1 being AD 2, etc.:

| Index # | AD # | Example |
|---------|------|---------|
| 0 | 1 | local.ad_names[0] |
| 1 | 2 | local.ad_names[1] |
| 2 | 3 | local.ad_names[2] |

If you'd like the index to match the AD number, change the local as-follows:

```
locals {
ad_names = { for y in data.oci_identity_availability_domains.this.availability_domains :
index(data.oci_identity_availability_domains.this.availability_domains, y) + 1 => y.name
}
}
```

Then use it as follows:

```
local.ad_names[1] # AD 1
local.ad_names[2] # AD 2
local.ad_names[3] # AD 3
```
49 changes: 49 additions & 0 deletions oci-tf-cookbook/ad-ocid-by-number.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
title: Get the AD OCID by AD number
series: oci-tf-cookbook
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source, terraform, iac, devops]
solution_names: [Administrative Domain - getting OCID by AD number, AD - getting OCID by AD number, IAM - getting the AD OCID programmatically]
---

## Problem
There are times when it's necessary to get the OCID of an Administrative Domain (AD). How can this be done?

## Solution
This is similar to the solution for getting the name of an AD by friendly number. Instead of getting the name, we'll get the OCID.

```
# Get all availability domains for the region
data "oci_identity_availability_domains" "ads" {
compartment_id = var.tenancy_ocid
}
```

Now use it within your resource definition(s):

```
# Then use it to get a single AD name based on the index:
...
availability_domain_id = data.oci_identity_availability_domains.ads.availability_domains[0].id
...
}
```

This can also be refactored into a local:

```
locals {
ad_ids = { for y in data.oci_identity_availability_domains.this.availability_domains :
index(data.oci_identity_availability_domains.this.availability_domains, y) => y.id
}
}
```

Then used like so:
```
...
availability_domain_id = local.ad_ids[0]
...
}
```
62 changes: 62 additions & 0 deletions oci-tf-cookbook/compute-image-by-name-most-recent.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
---
title: Get the most recent Compute Image OCID
series: oci-tf-cookbook
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source, terraform, iac, devops]
solution_names: [Compute - get the latest compute image OCID for a given distro, Compute image - get the latest distro OCID,Image - get latest compute image OCID]
---

## Problem
While it's possible to get the OCID of a compute instance image by name, it can often be ideal to always use the latest image (whatever it may be). How can this be done?

## Solution
```
data "oci_core_images" "latest_ol8" {
compartment_id = var.tenancy_ocid
operating_system = "Oracle Linux"
operating_system_version = 8.0
shape = "VM.Standard2.1"
state = "AVAILABLE"
sort_by = "TIMECREATED"
sort_order = "DESC"
}

resource "oci_core_instance" "my_compute" {
...

source_details {
source_id = data.oci_core_images.latest_ol8.images[0].id
source_type = "image"
}

...
}
```

The shape, OS, etc. can all be customized. The key here is to use the sort attributes to allow you to select the first element in the returned results. This gives you an idea of what you can do to solve this need!

To make this a bit cleaner, a local could be defined:

```
locals {
latest_ol8_image_id = data.oci_core_images.latest_ol8.images[0].id
}
```

Then you can use it like:

```
resource "oci_core_instance" "my_compute" {
...

source_details {
source_id = local.latest_ol8_image_id
source_type = "image"
}

...
}
```

Just a bit cleaner!
47 changes: 47 additions & 0 deletions oci-tf-cookbook/compute-image-by-name.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
---
title: Get Compute Image OCID by Name
series: oci-tf-cookbook
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source, terraform, iac, devops]
solution_names: [Compute - get compute image OCID by name, Compute image - get OCID by name,Image - get compute image OCID by name]
---

## Problem
OCI Compute Instances require the OCID of a Compute Image to be provided. Hard-coding an OCID is rather risky, as Compute Images should be changed/updated rather regularly (and each new image will have a new OCID). How can we get the OCID for a Compute Instance based on its friendly name, as found in [https://docs.oracle.com/en-us/iaas/images/](https://docs.oracle.com/en-us/iaas/images/)?

## Solution
```
data "oci_core_images" "this" {
compartment_id = var.compartment_ocid
filter {
name = "state"
values = ["AVAILABLE"]
}
}

locals {
list_images = { for s in data.oci_core_images.this.images :
s.display_name =>
{ id = s.id,
operating_system = s.operating_system
}
}
}

resource "oci_core_instance" "my_compute" {
...

source_details {
source_id = local.list_images[var.compute_image_name].id
source_type = "image"
}

...
}
```

The `var.compute_image_name` can be set to something like `Oracle-Linux-8.4-2021.10.20-0` (found at the time of this writing at [https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/](https://docs.oracle.com/en-us/iaas/images/oracle-linux-8x/)).

What have we done here? First, we retrieved the list of compute images (`data.oci_core_images.this`), then coerce this into a tuple, where the key is the name of the image. Lastly, we grabbed the OCID (`id`) from the tuple, based on the name given in the `var.compute_image_name` input variable).

56 changes: 56 additions & 0 deletions oci-tf-cookbook/get-home-region.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
---
title: Find the OCI home region programmatically
series: oci-tf-cookbook
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source, terraform, iac, devops]
solution_names: [IAM - get the home region programmatically,Region - get home region]
---

## Problem
Many OCI services have to interact with the home region, which might not be the region used by the primary OCI provider definition. Is it possible to programmatically determine the home OCI region of a tenancy?

## Solution
Yes it is! Typically the primary OCI provider will be a user-specified region, which might not be the home region. In these situations, it's necessary to programmatically determine the home region (which may or may not be the same).

```
data "oci_identity_tenancy" "tenant_details" {
tenancy_id = var.tenancy_ocid
}

data "oci_identity_regions" "home-region" {
filter {
name = "key"
values = [data.oci_identity_tenancy.tenant_details.home_region_key]
}
}

data "oci_identity_region_subscriptions" "home_region_subscriptions" {
tenancy_id = var.tenancy_ocid

filter {
name = "is_home_region"
values = [true]
}
}
```

Next setup a provider definition for the home region (the following assumes that you already have an OCI provider defined without an alias):

```
provider "oci" {
alias = "home"
region = data.oci_identity_region_subscriptions.home_region_subscriptions.region_subscriptions[0].region_name
tenancy_ocid = var.tenancy_ocid
...
}
```

From within the resource blocks that need to talk to the home region, specify this provider, like the following:

```
resource "oci_identity_tag_namespace" "this" {
provider = oci.home
...
}
```
83 changes: 83 additions & 0 deletions oci-tf-cookbook/index.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
---
layout: collection
title: OCI Terraform Cookbook
series: oci-tf-cookbook
description: Awesome tips| tricks and techniques for using Terraform with OCI.
thumbnail: assets/cookbook.jpg
author: tim-clegg
tags: [open-source| terraform| iac| devops]
---
{% img aligncenter assets/cookbook.jpg 400 400 "OCI Terraform Cookbook" "OCI Terraform Cookbook" %}
*(Photo by [Ron Lach](https://www.pexels.com/@ron-lach?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels) from [Pexels](https://www.pexels.com/photo/food-wood-dawn-coffee-8188946/?utm_content=attributionCopyText&utm_medium=referral&utm_source=pexels))*

We hope that you find these solutions of benefit as you build OCI solutions using Terraform. These are organized in a problem/solution format, with all of the problems being in the index (below). Happy coding!

Ps. These are designed to work with Oracle Cloud Infrastructure (OCI). If you don't have an OCI account get an OCI Always-Free account [here]({{site.urls.always_free }})!

{%- assign alphabet = "a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t,u,v,w,x,y,z" | split: "," -%}
{%- assign letters_with_content = "" -%}

{%- for letter in alphabet -%}
{%- for page in site.pages -%}
{%- if page.path contains 'collections/tutorials/oci-tf-cookbook'" -%}
{%- for name in page.solution_names -%}
{%- assign first_letter = name | slice: 0 | downcase -%}
{%- if first_letter == letter -%}
{%- unless letters_with_content contains letter -%}
{%- if letters_with_content != "" -%}
{%- assign letters_with_content = letters_with_content | append: "," | append: letter -%}
{%- else -%}
{%- assign letters_with_content = letter -%}
{%- endif -%}
{%- endunless -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}

{%- assign letters_to_render = letters_with_content | split: "," %}

<div id="nav">
<h1>Navigation</h1>
{%- for letter in letters_to_render -%}
<a href="#{{letter}}">{{letter}}</a>&nbsp;
{% endfor %}
</div>

# Solution Index
{%- for letter in letters_to_render %}
<div id="{{letter}}">
<h2>{{ letter }} &nbsp;<a href="#nav">top ^</a></h2>

{%- assign solution_names = "" -%}
{%- for page in site.pages -%}
{%- if page.path contains 'collections/tutorials/oci-tf-cookbook'" -%}
{%- for name in page.solution_names -%}
{%- assign fltr = name | slice: 0 | downcase -%}
{%- if fltr == letter -%}
{%- if solution_names != "" -%}
{%- assign solution_names = solution_names | append: "," | append: name -%}
{%- else -%}
{%- assign solution_names = name -%}
{%- endif -%}
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- assign solution_names = solution_names | split: "," | sort_natural -%}

{%- for name in solution_names -%}
{%- for page in site.pages -%}
{%- if page.path contains 'collections/tutorials/oci-tf-cookbook'" -%}
{%- for page_name in page.solution_names -%}
{%- if name == page_name -%}
<a href="{{ page.url }}">{{ name }}</a><br />
{%- endif -%}
{%- endfor -%}
{%- endif -%}
{%- endfor -%}
{%- endfor -%}

</div>
{%- endfor -%}
Loading