From c8f35b435c8240ccc45d4534b92c0f0e92c9254c Mon Sep 17 00:00:00 2001
From: Marco Emilio Poleggi <marco-emilio.poleggi@hesge.ch>
Date: Wed, 2 Feb 2022 17:44:28 +0100
Subject: [PATCH] OpenStack: added TP-style readme (no solution) and bits

---
 .gitattributes                      |   1 +
 AWS/outputs.tf                      |   2 +-
 OpenStack/conf/clouds.yaml.api_cred |  10 +
 OpenStack/conf/clouds.yaml.app_cred |  12 +
 OpenStack/main.tf                   |   1 +
 OpenStack/main.tf.advnc             | Bin 0 -> 1509 bytes
 OpenStack/outputs.tf                |   9 +
 README-OpenStack.md                 | 472 ++--------------------------
 README.md                           |   2 +-
 9 files changed, 55 insertions(+), 454 deletions(-)
 create mode 100644 OpenStack/conf/clouds.yaml.api_cred
 create mode 100644 OpenStack/conf/clouds.yaml.app_cred
 create mode 120000 OpenStack/main.tf
 create mode 100644 OpenStack/main.tf.advnc
 create mode 100644 OpenStack/outputs.tf

diff --git a/.gitattributes b/.gitattributes
index 946c916..87cdcf4 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -1 +1,2 @@
 AWS/main.tf.advnc filter=git-crypt diff=git-crypt
+OpenStack/main.tf.advnc filter=git-crypt diff=git-crypt
diff --git a/AWS/outputs.tf b/AWS/outputs.tf
index 68dd48b..3cd2c9e 100644
--- a/AWS/outputs.tf
+++ b/AWS/outputs.tf
@@ -9,10 +9,10 @@ output "instance_public_ip" {
 }
 
 output "public_ip" {
+  description = "Public IP address of the EC2 instance"
   value       = aws_instance.app_server.public_ip
 }
 
 output "instance_tags" {
-  description = "Public IP address of the EC2 instance"
   value       = aws_instance.app_server.tags_all
 }
diff --git a/OpenStack/conf/clouds.yaml.api_cred b/OpenStack/conf/clouds.yaml.api_cred
new file mode 100644
index 0000000..32777c9
--- /dev/null
+++ b/OpenStack/conf/clouds.yaml.api_cred
@@ -0,0 +1,10 @@
+# Project-agnostic -- API credentials
+clouds:
+  engines:
+    auth:
+      auth_url: https://keystone.cloud.switch.ch:5000/v3
+      username: "<your-user-name>"
+      password: "<your-password"
+      user_domain_name: "Default"
+    interface: "public"
+    identity_api_version: 3
diff --git a/OpenStack/conf/clouds.yaml.app_cred b/OpenStack/conf/clouds.yaml.app_cred
new file mode 100644
index 0000000..6021f0b
--- /dev/null
+++ b/OpenStack/conf/clouds.yaml.app_cred
@@ -0,0 +1,12 @@
+# Project-specific -- application credentials.
+clouds:
+  Cloud-MA-IaC:
+    auth:
+      auth_url: https://keystone.cloud.switch.ch:5000/v3
+      application_credential_id: "<your-app-cred-ID>"
+      application_credential_secret: "<your-app-cred-secret>"
+      user_domain_name: Default
+      project_domain_name: Default
+    interface: "public"
+    identity_api_version: 3
+    auth_type: "v3applicationcredential"
diff --git a/OpenStack/main.tf b/OpenStack/main.tf
new file mode 120000
index 0000000..3a0d56a
--- /dev/null
+++ b/OpenStack/main.tf
@@ -0,0 +1 @@
+main.tf.advnc
\ No newline at end of file
diff --git a/OpenStack/main.tf.advnc b/OpenStack/main.tf.advnc
new file mode 100644
index 0000000000000000000000000000000000000000..c5ace7adaf62c2938ad383b304302acd56fd4f13
GIT binary patch
literal 1509
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

literal 0
HcmV?d00001

diff --git a/OpenStack/outputs.tf b/OpenStack/outputs.tf
new file mode 100644
index 0000000..61dcb53
--- /dev/null
+++ b/OpenStack/outputs.tf
@@ -0,0 +1,9 @@
+output "instance_id" {
+  description = "ID of the instance"
+  value       = openstack_compute_instance_v2.app_server.id
+}
+
+output "instance_public_ip" {
+  description = "Public IP address of instance"
+  value       = openstack_networking_floatingip_v2.fip_1.address
+}
diff --git a/README-OpenStack.md b/README-OpenStack.md
index 3e47c0e..c262cac 100644
--- a/README-OpenStack.md
+++ b/README-OpenStack.md
@@ -1,6 +1,4 @@
-## Lab: Cloud provisioning/orchestration - Terraform and AWS
-
-Lab with Terraform and any Cloud
+## Lab: Cloud provisioning/orchestration - Terraform and OpenStack
 
 Lab template for a Cloud provisioning/orchestration exercise with Terraform
 (TF) and OpenStack/SwitchEngines.
@@ -42,13 +40,18 @@ Please, refer to your OS documentation for the proper way to do so
      CLI](https://learn.hashicorp.com/tutorials/terraform/install-cli)
      v1.1.4. Skip the TF "Quick start tutorial" (Docker).
   1. [OpenStack CLI](https://docs.openstack.org/newton/user-guide/common/cli-install-openstack-command-line-clients.html) v5.7.0.
+  1. Grab or create a new project in your OpenStack account. The placeholder
+     used in this exercise is `<your-project-name>` with value `Cloud-MA-IaC`.
   1. Create a new [OpenStack Access
      Credentials](https://engines.switch.ch/horizon/identity/application_credentials/)
      and save as `~/.config/openstack/clouds.yaml`. With SwitchEngine, the
-     cloud name to use in this lab should be `engines`.
+     cloud name to use in this is `engines`. :warning: App credentials might
+     not work for some commands; [API
+     credentials](https://engines.switch.ch/horizon/project/api_access/clouds.yaml)
+     with explicit project name/ID setup might be better.
   1. Verify that your credentials are OK:
   ``` shell
-  lcl$ $ openstack --os-cloud=engines [application] credential list
+  lcl$ $ openstack --os-cloud=Cloud-MA-IaC [application] credential list
   ```
 
 ### Task #2: configure TF for OpenStack ###
@@ -58,7 +61,7 @@ Please, refer to your OS documentation for the proper way to do so
 <a name="image-query"></a>Find out the smallest image to use for a Debian server:
 
 ``` shell
-lcl$ openstack --os-cloud=engines image list --limit=20 --public --status=active  --sort-column=Size -c ID -c Name -c Size --long
+lcl$ openstack --os-cloud=Cloud-MA-IaC image list --limit=10 --public --status=active --sort-column=Size -c ID -c Name -c Size --long
 +--------------------------------------+-------------------------------------+-------------+
 | ID                                   | Name                                |        Size |
 +--------------------------------------+-------------------------------------+-------------+
@@ -82,66 +85,23 @@ Find out the smallest instance *flavor* that acommodates our Debian image.
 
 :bulb: Our flavor will be `m1.small` for the placeholder `<your-flavor>`.
 
-
-**@@@ RESTART FROM HERE @@@**
-
-Create a "sandbox" directory on your local machine `~/terraform/AWS/`. Inside
+Create a "sandbox" directory on your local machine `~/terraform/OpenStack/`. Inside
 it, create a file called `main.tf` (written in HCL language), the
-infrastructure *definition* file, with the following content:
-
-``` hcl
-terraform {
-  required_providers {
-    aws = {
-      source  = "hashicorp/aws"
-      version = "~> 3.27"
-    }
-  }
-
-  required_version = ">= 0.14.9"
-}
+infrastructure *definition* file, with the appropriate content to handle:
+  1. an instance,
+  1. a security group to allow SSH access,
+  1. a floating IP in the public pool associated to your instance.
 
-provider "aws" {
-  profile = "default"
-  region  = "us-east-1"
-}
-
-resource "aws_instance" "app_server" {
-  ami           = "<your-image-ID>"
-  instance_type = "t2.micro"
-
-  tags = {
-    Name = "ExampleAppServerInstance"
-  }
-}
-```
+Also, prepare an `~/terraform/OpenStack/outputs.tf` file with the appropriate
+contents to get the instance's public IP address (via `instance_public_ip`).
 
 Initialize your sandbox with:
 
 ``` shell
 lcl$ terraform init
-
-Initializing the backend...
-
-Initializing provider plugins...
-- Finding hashicorp/aws versions matching "~> 3.27"...
-- Installing hashicorp/aws v3.27.0...
-- Installed hashicorp/aws v3.27.0 (signed by HashiCorp)
-
-Terraform has created a lock file .terraform.lock.hcl to record the provider
-selections it made above. Include this file in your version control repository so
-that Terraform can guarantee to make the same selections by default when you run
-"terraform init" in the future.
-
-Terraform has been successfully initialized!
-...
 ```
 
-Have a look inside the newly created sub-directory
-`~/terraform/AWS/.terraform/`, you'll find the required `aws` provider module
-that has been downloaded during the initialization.
-
-It's good practice to format and validate your configuration:
+Format and validate your configuration:
 
 ``` shell
 lcl$ terraform fmt
@@ -150,406 +110,14 @@ lcl$ terraform validate
 Success! The configuration is valid.
 ```
 
-### Task #3: deploy your AWS infrastructure ###
-
-**Goal:** provision your AWS EC2 instance via TF.
-
-Run the following command, confirm by typing "yes" and observe it's output:
+Then apply!
 
 ``` shell
 lcl$ terraform apply
-
-Terraform used the selected providers to generate the following execution plan.
-Resource actions are indicated with the following symbols:
-  + create
-
-Terraform will perform the following actions:
-
-  # aws_instance.app_server will be created
-  + resource "aws_instance" "app_server" {
-      + ami                                  = "ami-0fa37863afb290840"
-      + arn                                  = (known after apply)
-      ...
-      + instance_type                        = "t2.micro"
-      ...
-      + tags                                 = {
-          + "Name" = "ExampleAppServerInstance"
-        }
-      ...
-
-Plan: 1 to add, 0 to change, 0 to destroy.
-
-Do you want to perform these actions?
-  Terraform will perform the actions described above.
-  Only 'yes' will be accepted to approve.
-
-  Enter a value: yes
-
-aws_instance.app_server: Creating...
-...
-aws_instance.app_server: Creation complete after 38s [id=i-0155ba9d77ee0a854]
-
-Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
-```
-
-The information shown above before the prompt for action is the `execution
-plan`: the `+` prefix mark things to add. Of course, many details are unknown
-until the corresponding resource is instantiated.
-
-:question: How many resources were created?
-
-You can verify via the AWS dashboard that one EC2 instance has been created.
-
-The state of the resources acted upon is locally stored. Let's see what's in
-our sandbox:
-``` shell
-lcl$ tree -a
-.
-├── .terraform
-│   └── providers
-...
-├── .terraform.lock.hcl
-├── main.tf
-└── terraform.tfstate
-```
-
-:question: What's in file `terraform.tfstate`? The answer comes from the
-following commands:
-
-``` shell
-lcl$ terraform state list
-aws_instance.app_server
-```
-It confirms that we're tracking one AWS instance. Let's dig a bit more:
-
-``` shell
-lcl$ terraform show
-# aws_instance.app_server:
-resource "aws_instance" "app_server" {
-    ami                                  = "ami-0fa37863afb290840"
-    arn                                  = "arn:aws:ec2:us-east-1:768034348959:instance/i-0155ba9d77ee0a854"
-    associate_public_ip_address          = true
-    availability_zone                    = "us-east-1e"
-    ...
-    id                                   = "i-0155ba9d77ee0a854"
-    instance_initiated_shutdown_behavior = "stop"
-    instance_state                       = "running"
-    instance_type                        = "t2.micro"
-    ...
-    private_dns                          = "ip-172-31-94-207.ec2.internal"
-    private_ip                           = "172.31.94.207"
-    public_dns                           = "ec2-3-94-184-169.compute-1.amazonaws.com"
-    public_ip                            = "3.94.184.169"
-    ...
-    tags                                 = {
-        "Name" = "ExampleAppServerInstance"
-    }
-    ...
-    vpc_security_group_ids               = [
-        "sg-0c420780b4f729d3e",
-    ]
-    ...
-}
-```
-
-The above command output provides useful runtime (state) information, like the
-instance IP's address. Indeed, there is a kind of *digital twin* stored inside
-the file `terraform.tfstate`.
-
-:question: Is that instance accessible via SSH? Give it a try. If not, why?
-
-Now, stop the running instance (its ID is shown above ;-):
-
-``` shell
-lcl$ aws ec2 stop-instances --instance-ids i-0155ba9d77ee0a854
-```
-
-wait some seconds and test again:
-
-``` shell
-lcl$ terraform show | grep instance_state
-   instance_state                       = "running"
-```
-
-How come? We just discovered that TF read only the local status of a
-resource. So, let's refresh it, and check again:
-
-``` shell
-lcl$ terraform refresh
-aws_instance.app_server: Refreshing state... [id=i-0155ba9d77ee0a854]
-lcl$ terraform show | grep instance_state
-    instance_state                       = "stopped"
-```
-
-Ah-ha!
-
-Hold on a second: our TF plan does not specify the desired status of a
-resource. What happens if we reapply the plan? Lets' try:
-
-``` shell
-lcl$ terraform apply -auto-approve
-aws_instance.app_server: Refreshing state... [id=i-0155ba9d77ee0a854]
-
-No changes. Your infrastructure matches the configuration.
-
-Terraform has compared your real infrastructure against your configuration and found no differences, so no changes are needed.
-
-Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
-lcl$ terraform show | grep instance_state
-    instance_state                       = "stopped"
-```
-
-:warning: Apply was run in `-auto-approve` (non interactive) mode which
-assumes "yes" to all questions. Use with care!
-
-From the above commands' output we see that
-  * the local state is refreshed before doing anything,
-  * no changes are applied, and
-  * huh?... the resource is still stopped.
-
-Concerning the last point above, think about the basic objectives of TF: as a
-provisioning tool it is concerned with the *existence* of a resource, not with
-its *runtime* state. This latter is the business of configuration management
-tools. :bulb: There is no way with TF to specify a resource's desired runtime
-state.
-
-
-### Task #4: change your infrastructure ###
-
-**Goal:** modify the resource created before, and learn how to apply changes
-to a Terraform project.
-
-Restart your managed instance:
-
-``` shell
-lcl$ aws ec2 start-instances --instance-ids i-0155ba9d77ee0a854
-```
-
-Refresh TF's view of the world:
-
-``` shell
-lcl$ terraform refresh
-aws_instance.app_server: Refreshing state... [id=i-0155ba9d77ee0a854]
-lcl$ terraform show | grep instance_state
-    instance_state                       = "running"
-```
-
-Replace the resource's `ami` in `main.tf` with the second one found from the
-[catalog query done above](#image-query) (or another one available with your
-account). Before applying our new plan, let's see what TF thinks of it:
-
-``` shell
-lcl$ terraform plan -out=change-AMI.tfplan
-aws_instance.app_server: Refreshing state... [id=i-0155ba9d77ee0a854]
-
-Terraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:
--/+ destroy and then create replacement
-
-Terraform will perform the following actions:
-
-  # aws_instance.app_server must be replaced
--/+ resource "aws_instance" "app_server" {
-      ~ ami                                  = "ami-0fa37863afb290840" -> "ami-0e2512bd9da751ea8" # forces replacement
-
-...
-
-Plan: 1 to add, 0 to change, 1 to destroy.
-
-Saved the plan to: change-AMI.tfplan
-
-To perform exactly these actions, run the following command to apply:
-    terraform apply "change-AMI.tfplan"
-```
-
-:bulb: Remarks:
-  * The change we want to apply is destructive!
-  * We saved our plan. :question: Why? It is not really necessary in a simple
-    scenario like ours, however a more complex IaC workflow might require plan
-    artifacts to be programmatically validated and versioned.
-
-Apply the saved plan:
-``` shell
-lcl$ terraform apply change-AMI.tfplan
-aws_instance.app_server: Destroying... [id=i-0155ba9d77ee0a854]
-...
-aws_instance.app_server: Destruction complete after 33s
-aws_instance.app_server: Creating...
-...
-aws_instance.app_server: Creation complete after 48s [id=i-0470db35749548101]
-```
-
-:bulb: What? Not asking for confirmation? Indeed, a saved plan is intended for
-automated workflows! Moreover, a saved plan will come handy for rolling back a
-broken infrastructure to the last working setup.
-
-:question: What if we did not save our plan, and called a plain apply command?
-Would the result be the same?
-
-
-### Task #5: input variables ###
-
-**Goal:** make a TF plan more flexible via input variables.
-
-Our original plan has all its content hard-coded. Let's make it more flexible
-with some input variables stored in a separate `variables.tf` file inside your
-TF sandbox:
-
-``` hcl
-variable "instance_name" {
-  description = "Value of the Name tag for the EC2 instance"
-  type        = string
-  default     = "AnotherAppServerInstance"
-}
-```
-
-Then modify the `main.tf` as follows:
-
-``` hcl
-resource "aws_instance" "app_server" {
-  ami           = "ami-0e2512bd9da751ea8"
-  instance_type = "t2.micro"
-
-  tags = {
--   Name = "ExampleAppServerInstance"
-+   Name = var.instance_name
-  }
-}
-```
-
-Apply the changes:
-``` shell
-lcl$ terraform apply -auto-approve
-aws_instance.app_server: Refreshing state... [id=i-0470db35749548101]
-...
-
-  ~ update in-place
-
-Terraform will perform the following actions:
-
-  # aws_instance.app_server will be updated in-place
-  ~ resource "aws_instance" "app_server" {
-        id                                   = "i-0470db35749548101"
-      ~ tags                                 = {
-          ~ "Name" = "ExampleAppServerInstance" -> "AnotherAppServerInstance"
-        }
-      ~ tags_all                             = {
-          ~ "Name" = "ExampleAppServerInstance" -> "AnotherAppServerInstance"
-        }
-...
-    }
-
-Plan: 0 to add, 1 to change, 0 to destroy.
-...
-Apply complete! Resources: 0 added, 1 changed, 0 destroyed.
-```
-
-:bulb: **Exercise:** input variables can also be passed on the `apply` command
-line. Find how to do that with another different value for the variable
-`instance_name`. :question: Would this last change be persistent if we rerun a
-plain `terraform apply`?
-
-
-### Task #6: queries with outputs ###
-
-**Goal:** use output values to query a provisioned infrastructure.
-
-We have seen in the previous tasks that the infrastructure's status can be
-displayed via `terraform show`: a rather clumsy way, if you just want to
-extract some specific information. A better programmatic way of querying your
-infrastructure makes use of "outputs". Put the following in a file called
-`~/terraform/AWS/outputs.tf`:
-
-``` hcl
-output "instance_id" {
-  description = "ID of the EC2 instance"
-  value       = aws_instance.app_server.id
-}
-
-output "instance_public_ip" {
-  description = "Public IP address of the EC2 instance"
-  value       = aws_instance.app_server.public_ip
-}
-```
-
-We have declared two outputs. As usual with TF, before querying their
-associated values, we need to apply the changes:
-
-``` shell
-lcl$ terraform apply -auto-approve
-...
-
-Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
-
-Outputs:
-
-instance_id = "i-0470db35749548101"
-instance_public_ip = "34.201.252.63"
-instance_tags = tomap({
-  "Name" = "AnotherAppServerInstance"
-})
-```
-
-So, we already got the needed information, but, within a workflow, it is more
-practical to do something like:
-
-``` shell
-lcl$ terraform output -json instance_tags
-{"Name":"AnotherAppServerInstance"}
 ```
 
-:question: What if the `Name` tag is changed outside TF? Try it.
-
-:question: What must be done to have TF respect that external change?
-
-:question: How to revert an external change via TF?
-
-
-### Task #7: SSH provisioning with Cloud-Init ###
-
-**Goal:** use Cloud-Init to provision an SSH access to your TF-managed
-instance.
-
-Did you try to SSH into the instance you created via TF? It cannot work,
-because we did not instructed TF about networks, users, keys or anything
-else. **This is left entirely to you as an exercise.** You need to:
-
-  1. Destroy your infrastructure. There's a special TF command for that.
-  1. Create an SSH key pair `tf-cloud-init`.
-  1. Create a new cloud-init file
-     `~/terraform/AWS/scripts/add-ssh.yaml` with the following content:
-     ``` yaml
-     #cloud-config
-     #^^^^^^^^^^^^
-     # DO NOT TOUCH the first line!
-     ---
-     groups:
-       - ubuntu: [root, sys]
-       - terraform
-
-     users:
-       - default
-       - name: terraform
-         gecos: terraform
-         primary_group: terraform
-         groups: users, admin
-         ssh_authorized_keys:
-           - <your-SSH-pub-key-on-one-line>
-     ```
-     :warning: **Mind that the first line of this file must spell exactly
-     `#cloud-config`**!
-  1. Modify the `main.tf` as follows:
-     1. add a `resource` block of type `"aws_security_group"` allowing ingress
-        ports 22 and 80 from any address, with any egress port open;
-     1. add a `data` block referencing the above authorization file as a
-        `"template_file"` type;
-     1. extend the `"aws_instance"` resource to:
-        1. associate a public IP address,
-        1. link the `data` block to a user data attribute;
-     1. add an output `"public_ip"`.
-
-When done, *init* your new plan, *validate* and *apply* it. Verify that you
-can SSH as user `terraform` (not the customary `ubuntu`) into your instance:
+Verify that you can SSH as user `debian` into your instance:
 
 ``` shell
-lcl$ ssh terraform@$(terraform output -raw public_ip) -i ../tf-cloud-init
+lcl$ ssh debian@$(terraform output -raw instance_public_ip) -i ../tf-cloud-init
 ```
diff --git a/README.md b/README.md
index f0ebdf5..015af97 100644
--- a/README.md
+++ b/README.md
@@ -541,5 +541,5 @@ When done, *init* your new plan, *validate* and *apply* it. Verify that you
 can SSH as user `terraform` (not the customary `ubuntu`) into your instance:
 
 ``` shell
-lcl$ ssh terraform@$(terraform output -raw public_ip) -i ../tf-cloud-init
+lcl$ ssh terraform@$(terraform output -raw instance_public_ip) -i ../tf-cloud-init
 ```
-- 
GitLab