<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:taxo="http://purl.org/rss/1.0/modules/taxonomy/" version="2.0">
  <channel>
    <title>topic Re: Using the Morpheus Terraform Provider and Spec Templates in HPE Morpheus Enterprise</title>
    <link>https://community.hpe.com/t5/hpe-morpheus-enterprise/using-the-morpheus-terraform-provider-and-spec-templates/m-p/7248846#M2020</link>
    <description>&lt;P&gt;&lt;IMG src="https://emoji.discourse-cdn.com/twitter/heart_on_fire.png?v=12" title=":heart_on_fire:" class="emoji only-emoji" alt=":heart_on_fire:" loading="lazy" width="20" height="20" /&gt;&lt;/P&gt;
&lt;P&gt;There, a better emoji.  Nice write up!&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/150141iD556DFA08574E724/image-size/large?v=v2&amp;amp;px=2000" role="button" title="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif" alt="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif" /&gt;&lt;/span&gt;&lt;/P&gt;</description>
    <pubDate>Thu, 28 Jul 2022 19:17:06 GMT</pubDate>
    <dc:creator>cbunge</dc:creator>
    <dc:date>2022-07-28T19:17:06Z</dc:date>
    <item>
      <title>Using the Morpheus Terraform Provider and Spec Templates</title>
      <link>https://community.hpe.com/t5/hpe-morpheus-enterprise/using-the-morpheus-terraform-provider-and-spec-templates/m-p/7248845#M2019</link>
      <description>&lt;P&gt;In my lab, I wanted to setup Dynamic DNS (DDNS) so I did not need to pay for a static IP address from my ISP, because I’m cheap &lt;IMG src="https://emoji.discourse-cdn.com/twitter/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20" /&gt;   There are a few projects that can accomplish this, in my case I was looking to use &lt;A href="https://crazymax.dev/ddns-route53/"&gt;ddns-route53&lt;/A&gt;, since my DNS zone is stored in AWS Route53.&lt;/P&gt;
&lt;P&gt;My goal was to make it completely automated by code from start to finish, using Morpheus.  I’m using a vSphere VM in this case to deploy the software, although a container and other options are available as well.  Morpheus supports importing your Terraform code as-is into a &lt;A href="https://docs.morpheusdata.com/en/latest/library/blueprints/blueprints.html#terraform-blueprints"&gt;Terraform App Blueprint&lt;/A&gt; but I decided to use &lt;A href="https://docs.morpheusdata.com/en/latest/library/templates/templates.html#spec-templates"&gt;Terraform Spec Templates&lt;/A&gt; in Morpheus, which will still import your code but allow the use of the native &lt;A href="https://docs.morpheusdata.com/en/latest/troubleshooting/Variables_Examples.html"&gt;variables that Morpheus provides&lt;/A&gt;.  Adding this functionality will augment and simplify our deployment.&lt;/P&gt;
&lt;P&gt;Additionally, I wanted to have as much functionality as possible from Morpheus, so I also used the &lt;A href="https://github.com/gomorpheus/terraform-provider-morpheus"&gt;Morpheus Terraform Provider&lt;/A&gt;, which allows the use of Morpheus resources in your Terraform configuration.  API calls are fully available for Morpheus but if you are experienced with using Terraform, you may want use the same technology.&lt;/P&gt;
&lt;H2&gt;
&lt;A name="the-code-1" class="anchor" href="#the-code-1"&gt;&lt;/A&gt;The Code&lt;/H2&gt;
&lt;P&gt;Of course, all of the TF code could be placed into a single file but I prefer organization of the files.  There are four files we’ll see below:&lt;/P&gt;
&lt;UL&gt;
&lt;LI&gt;provider.tf&lt;/LI&gt;
&lt;LI&gt;setupVM.tf&lt;/LI&gt;
&lt;LI&gt;setupAWS.tf&lt;/LI&gt;
&lt;LI&gt;variables.tf&lt;BR /&gt;
&lt;BR /&gt;
&lt;/LI&gt;
&lt;/UL&gt;
&lt;P&gt;&lt;CODE style="background : #f0f1f2;"&gt;provider.tf&lt;/CODE&gt; file:&lt;/P&gt;
&lt;PRE style="background : #f0f1f2;"&gt;&lt;CODE class="lang-auto"&gt;terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~&amp;gt; 3.0"
    }
    morpheus = {
      source  = "morpheusdata.com/gomorpheus/morpheus"
      version = "0.4.1"
    }
  }
  backend "s3" {
    # Replace this with your bucket name
    bucket         = "terraform-state-bucketname"
    key            = "global/s3/terraform.tfstate"
    region         = "us-east-1"
    # Replace this with your DynamoDB table name
    dynamodb_table = "terraform-state"
    encrypt        = true
    access_key = "&amp;lt;%=cypher.read('secret/awsautomation').tokenize('|')[0]%&amp;gt;"
    secret_key = "&amp;lt;%=cypher.read('secret/awsautomation').tokenize('|')[1]%&amp;gt;"
  }
}

# Configure the AWS Provider
provider "aws" {
  region = "us-east-1"
  access_key = "&amp;lt;%=cypher.read('secret/awsautomation').tokenize('|')[0]%&amp;gt;"
  secret_key = "&amp;lt;%=cypher.read('secret/awsautomation').tokenize('|')[1]%&amp;gt;"
}

provider "morpheus" {
  url      = "&amp;lt;%=cypher.read('secret/morpheusCreds').tokenize('|')[0]%&amp;gt;"
  username = "&amp;lt;%=cypher.read('secret/morpheusCreds').tokenize('|')[1]%&amp;gt;"
  password = "&amp;lt;%=cypher.read('secret/morpheusCreds').tokenize('|')[2]%&amp;gt;"
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;There are a few items to note in the &lt;CODE style="background : #f0f1f2;"&gt;providers.tf&lt;/CODE&gt; above.  As mentioned, we are using the &lt;A href="https://github.com/gomorpheus/terraform-provider-morpheus"&gt;Morpheus Terraform Provider&lt;/A&gt;, which you can see the configuration listed in the &lt;CODE style="background : #f0f1f2;"&gt;required_providers&lt;/CODE&gt; section.&lt;/P&gt;
&lt;P&gt;My existing deployments have used an S3 backend for the state file, so I continued to use it here as well.  However, Morpheus can manage your state file for you, using a backend is not required and can make it more complex.  Having Morpheus manage this is much easier by just omitting a backend configuration.&lt;/P&gt;
&lt;P&gt;However, if you use backends, you may be familiar with not being able to use TF variables in the backend configuration.  There are tools out there to try and overcome this, or using -backend-config at the command line or a backend file.  One great feature for using &lt;STRONG&gt;Spec Templates&lt;/STRONG&gt; is that we can use the &lt;A href="https://docs.morpheusdata.com/en/latest/troubleshooting/Variables_Examples.html"&gt;Morpheus variables&lt;/A&gt;, which get translated prior to running the TF code.  When Terraform is run, it looks like hard coded values to the backend configuration, so there are no complaints to be seen.  You’ll see additional usage of variables being used in the providers to get other credentials from &lt;A href="https://docs.morpheusdata.com/en/latest/tools/cypher.html"&gt;Cypher&lt;/A&gt;.  This is an example of the contents of the &lt;CODE style="background : #f0f1f2;"&gt;secret/morpheusCreds&lt;/CODE&gt; Cypher seen above:&lt;/P&gt;
&lt;P&gt;&lt;CODE style="background : #f0f1f2;"&gt;&lt;A href="https://morpheus.example.local|username|password" target="_blank"&gt;https://morpheus.example.local|username|password&lt;/A&gt;&lt;/CODE&gt;&lt;/P&gt;
&lt;P&gt;The two Cyphers seen in the file were requirements that had to be created prior to deployment, so Terraform could automate against my AWS environment and my Morpheus environment.  The Morpheus Terraform Provider uses OAuth for authentication in the example above but &lt;A href="https://github.com/gomorpheus/terraform-provider-morpheus/blob/master/docs/guides/auth.md"&gt;other authentication options&lt;/A&gt; are available.&lt;/P&gt;
&lt;BR /&gt;
&lt;P&gt;&lt;CODE style="background : #f0f1f2;"&gt;setupVM.tf&lt;/CODE&gt; file:&lt;/P&gt;
&lt;PRE style="background : #f0f1f2;"&gt;&lt;CODE class="lang-auto"&gt;data "morpheus_group" "morpheus_group" {
  name = "All Clouds"
}

data "morpheus_cloud" "morpheus_cloud" {
  name = "VMware - Lab"
}

data "morpheus_resource_pool" "vsphere_resource_pool" {
  name = "Cluster01"
  cloud_id = data.morpheus_cloud.morpheus_cloud.id
}

data "morpheus_instance_type" "ubuntu_instance_type" {
  name = "Demo - Ubuntu"
}

data "morpheus_instance_layout" "ubuntu_layout" {
  name = "Demo - Ubuntu VMware"
}

data "morpheus_network" "dhcp_network" {
  name = "VLAN100-Servers-DHCP"
}

data "morpheus_plan" "cpu1gb1_plan" {
  name = "1 CPU, 1GB Memory"
}

resource "morpheus_vsphere_instance" "tf_example_vsphere_instance" {
  name               = var.vm_name
  description        = "Terraform instance example"
  group_id           = data.morpheus_group.morpheus_group.id
  cloud_id           = data.morpheus_cloud.morpheus_cloud.id
  resource_pool_id   = data.morpheus_resource_pool.vsphere_resource_pool.id
  instance_type_id   = data.morpheus_instance_type.ubuntu_instance_type.id
  instance_layout_id = data.morpheus_instance_layout.ubuntu_layout.id
  plan_id            = data.morpheus_plan.cpu1gb1_plan.id
  workflow_id        = 6
  environment        = "dev"
  
  labels             = ["ubuntu", "terraform"]

  interfaces {
    network_id = data.morpheus_network.dhcp_network.id
  }

  tags = {
    name        = var.vm_name
    deploy_type = "terraform"
    os_type     = "ubuntu"
  }

  evar {
    name   = "application"
    value  = "demo"
    export = true
    masked = true
  }
  depends_on = [aws_iam_access_key.ddns_key]
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;In the &lt;CODE style="background : #f0f1f2;"&gt;setupVM.tf&lt;/CODE&gt; above, you can see the &lt;A href="https://github.com/gomorpheus/terraform-provider-morpheus"&gt;Morpheus Terraform Provider&lt;/A&gt; in action.  As I mentioned in the beginning, the reason we want to use the Morpheus provider, instead of the standard vSphere provider, is because we can use many of the Morpheus features we are accustom to during normal provisioning.  For example, agent install, workflow execution, configurations, etc.  If we used the standard vSphere provider, we’d need to do additional manual work or code to setup the agents and configuration.&lt;/P&gt;
&lt;P&gt;As seen above, you can use data sources to provide the data to your resources or just had code the values in if preferred.  You can configure many of the items we see daily in Morpheus when provisioning.&lt;BR /&gt;
&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&lt;CODE style="background : #f0f1f2;"&gt;setupAWS.tf&lt;/CODE&gt; file:&lt;/P&gt;
&lt;PRE style="background : #f0f1f2;"&gt;&lt;CODE class="lang-auto"&gt;resource "aws_iam_user" "ddns_user" {
  name = "ddns_user"
  path = "/lab/"
}

resource "aws_iam_access_key" "ddns_key" {
  user = aws_iam_user.ddns_user.name
  provisioner "local-exec" {
    # Configure Cypher
    command = &amp;lt;&amp;lt;-EOT
      $morpheusUrl = '&amp;lt;%=morpheus.applianceUrl%&amp;gt;'
      $morpheusUsername = '&amp;lt;%=cypher.read('secret/morpheusCreds').tokenize('|')[1]%&amp;gt;'
      $morpheusPassword = '&amp;lt;%=cypher.read('secret/morpheusCreds').tokenize('|')[2]%&amp;gt;'
      $awsAccessId = '${aws_iam_access_key.ddns_key.id}'
      $awsAccessSecret = '${aws_iam_access_key.ddns_key.secret}'
      $access_token=(Invoke-RestMethod -Method POST -Uri "$($morpheusUrl)oauth/token?grant_type=password&amp;amp;scope=write&amp;amp;client_id=morph-api" -Body @{username="$morpheusUsername";password="$morpheusPassword"} -ContentType 'application/x-www-form-urlencoded' -SkipCertificateCheck).access_token
      Invoke-RestMethod -Method POST -Uri "$($morpheusUrl)api/cypher/secret/ddns?type=string" -Headers @{Authorization="BEARER $access_token"} -ContentType 'application/json' -Body (@{value="$($awsAccessId)|$($awsAccessSecret)"}|ConvertTo-Json) -SkipCertificateCheck
  EOT
    interpreter = ["pwsh", "-Command"]
  }
}

resource "aws_iam_user_policy" "ddns_policy" {
  name = "ddns_policy"
  user = aws_iam_user.ddns_user.name

  policy = &amp;lt;&amp;lt;EOF
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Action": [
                "route53:ChangeResourceRecordSets"
            ],
            "Effect": "Allow",
            "Resource": "arn:aws:route53:::hostedzone/${var.hosted_zone_id}"
        }
    ]
}
EOF
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;In the &lt;CODE style="background : #f0f1f2;"&gt;setupAWS.tf&lt;/CODE&gt; above, we see some of the same that we’ve seen, such as being able to use variables from Morpheus to be able to get secrets and other data, to keep our code as secure as possible but also portable, if needed.&lt;/P&gt;
&lt;P&gt;In this example, we are using the standard AWS provider and creating an AWS user, access key, and policy so the service can update the DNS record as needed.&lt;/P&gt;
&lt;H4&gt;
&lt;A name="note-2" class="anchor" href="#note-2"&gt;&lt;/A&gt;Note:&lt;/H4&gt;
&lt;P&gt;At the time of this writing the current version of the Morpheus Terraform Provider is v0.4.0 and does not support Cypher but many additional resources are coming soon.  In the example above, we are using the &lt;A href="https://www.terraform.io/language/resources/provisioners/local-exec"&gt;local-exec Creation-Time Provisioner&lt;/A&gt; to create Cypher objects in Morpheus &lt;A href="https://apidocs.morpheusdata.com/#write-a-cypher"&gt;via the API&lt;/A&gt;.  This Cypher is added so it can be used in the future with helping setup the service on the VM.&lt;BR /&gt;
&lt;BR /&gt;&lt;/P&gt;
&lt;P&gt;&lt;CODE style="background : #f0f1f2;"&gt;variables.tf&lt;/CODE&gt; file:&lt;/P&gt;
&lt;PRE style="background : #f0f1f2;"&gt;&lt;CODE class="lang-auto"&gt;variable "vm_name" {
  type = string
}

variable "hosted_zone_id" {
    type = string
}
&lt;/CODE&gt;&lt;/PRE&gt;
&lt;P&gt;Finally, we see the &lt;CODE style="background : #f0f1f2;"&gt;variables.tf&lt;/CODE&gt; file, which contain the variables to help customize our configuration, which we’ve seen referenced in the previous files.  Nothing magical here, just some organization &lt;IMG src="https://emoji.discourse-cdn.com/twitter/slight_smile.png?v=12" title=":slight_smile:" class="emoji" alt=":slight_smile:" loading="lazy" width="20" height="20" /&gt;&lt;/P&gt;
&lt;H2&gt;
&lt;A name="spec-templates-3" class="anchor" href="#spec-templates-3"&gt;&lt;/A&gt;Spec Templates&lt;/H2&gt;
&lt;P&gt;Now that we have seen the code that will do the magic, we want to add these as &lt;A href="https://docs.morpheusdata.com/en/latest/library/templates/templates.html#spec-templates"&gt;Spec Templates&lt;/A&gt; from a repository and then to an &lt;A href="https://docs.morpheusdata.com/en/latest/library/blueprints/blueprints.html#terraform-blueprints"&gt;Terraform App Blueprint&lt;/A&gt;.&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Navigate to:&lt;BR /&gt;
&lt;STRONG&gt;Library &amp;gt; Templates &amp;gt; Spec Templates tab&lt;/STRONG&gt;
&lt;/LI&gt;
&lt;LI&gt;Click the “Add” button to begin the adding of a new Spec Template&lt;/LI&gt;
&lt;LI&gt;Fill in the fields as appropriate, see below for an example:&lt;BR /&gt;
&lt;DIV class="lightbox-wrapper"&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="image"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/150593iB137C0C9474D582A/image-size/large?v=v2&amp;amp;px=2000" role="button" title="4e55ffe1201dd53b9103da4cc159aa41b27a637e.png" alt="4e55ffe1201dd53b9103da4cc159aa41b27a637e.png" /&gt;&lt;/span&gt;&lt;/DIV&gt;
&lt;/LI&gt;
&lt;LI&gt;Repeat the process for each file that should be added for this deployment&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;
&lt;A name="app-blueprint-4" class="anchor" href="#app-blueprint-4"&gt;&lt;/A&gt;App Blueprint&lt;/H2&gt;
&lt;P&gt;Once all the Spec Templates have been added to Morpheus, it is time to create an App Blueprint and add the Spec Templates to it&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Navigate to:&lt;BR /&gt;
&lt;STRONG&gt;Library &amp;gt; Blueprints &amp;gt; App Blueprints tab&lt;/STRONG&gt;
&lt;/LI&gt;
&lt;LI&gt;Click the “Add” button to begin the adding of a new Terraform Blueprint&lt;/LI&gt;
&lt;LI&gt;Fill in the fields as appropriate, see below for an example:&lt;BR /&gt;
&lt;DIV class="lightbox-wrapper"&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="image"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/149679iA2AA30944203E40B/image-size/large?v=v2&amp;amp;px=2000" role="button" title="ff0d38845df2d947e842c7a07241b64208abe3aa.png" alt="ff0d38845df2d947e842c7a07241b64208abe3aa.png" /&gt;&lt;/span&gt;&lt;/DIV&gt;
&lt;/LI&gt;
&lt;/OL&gt;
&lt;H2&gt;
&lt;A name="deploy-blueprint-5" class="anchor" href="#deploy-blueprint-5"&gt;&lt;/A&gt;Deploy Blueprint&lt;/H2&gt;
&lt;P&gt;Finally, after the Blueprint has been created, it is time to deploy it!&lt;/P&gt;
&lt;OL&gt;
&lt;LI&gt;Navigate to:&lt;BR /&gt;
&lt;STRONG&gt;Provisioning &amp;gt; Apps&lt;/STRONG&gt;
&lt;/LI&gt;
&lt;LI&gt;Click the “Add” button and choose the blueprint created previously&lt;/LI&gt;
&lt;LI&gt;Choose the Morpheus group and Cloud this should be added to for organization&lt;/LI&gt;
&lt;LI&gt;Finally, enter the values for your variables and continue through the wizard&lt;/LI&gt;
&lt;LI&gt;The App will be seen in:&lt;BR /&gt;
&lt;STRONG&gt;Provisioning &amp;gt; Apps&lt;/STRONG&gt;
&lt;/LI&gt;
&lt;/OL&gt;
&lt;P&gt;Once these items are provisioned, you can setup the service for ddns-route53 in the operating system, following their documentation.  In my case, I have created an &lt;A href="https://docs.ansible.com/ansible/latest/user_guide/playbooks_intro.html"&gt;Ansible Playbook&lt;/A&gt; that is integrated into Morpheus, to help configure this server completely.  The playbook uses the Cypher created in the &lt;CODE style="background : #f0f1f2;"&gt;setupAWS.tf&lt;/CODE&gt; configuration, so two different technologies can be used to both create and bootstrap your deployments.&lt;/P&gt;
&lt;P&gt;See those next steps in the &lt;A href="https://discuss.morpheusdata.com/t/using-terraform-and-ansible-together/"&gt;Using Terraform and Ansible Together&lt;/A&gt; post!&lt;/P&gt;</description>
      <pubDate>Thu, 28 Jul 2022 19:10:49 GMT</pubDate>
      <guid>https://community.hpe.com/t5/hpe-morpheus-enterprise/using-the-morpheus-terraform-provider-and-spec-templates/m-p/7248845#M2019</guid>
      <dc:creator>KoreyG</dc:creator>
      <dc:date>2022-07-28T19:10:49Z</dc:date>
    </item>
    <item>
      <title>Re: Using the Morpheus Terraform Provider and Spec Templates</title>
      <link>https://community.hpe.com/t5/hpe-morpheus-enterprise/using-the-morpheus-terraform-provider-and-spec-templates/m-p/7248846#M2020</link>
      <description>&lt;P&gt;&lt;IMG src="https://emoji.discourse-cdn.com/twitter/heart_on_fire.png?v=12" title=":heart_on_fire:" class="emoji only-emoji" alt=":heart_on_fire:" loading="lazy" width="20" height="20" /&gt;&lt;/P&gt;
&lt;P&gt;There, a better emoji.  Nice write up!&lt;/P&gt;
&lt;P&gt;&lt;span class="lia-inline-image-display-wrapper" image-alt="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif"&gt;&lt;img src="https://community.hpe.com/t5/image/serverpage/image-id/150141iD556DFA08574E724/image-size/large?v=v2&amp;amp;px=2000" role="button" title="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif" alt="edbf7dc9491f28e2d20a2096ed8a0363a22b3bf2.gif" /&gt;&lt;/span&gt;&lt;/P&gt;</description>
      <pubDate>Thu, 28 Jul 2022 19:17:06 GMT</pubDate>
      <guid>https://community.hpe.com/t5/hpe-morpheus-enterprise/using-the-morpheus-terraform-provider-and-spec-templates/m-p/7248846#M2020</guid>
      <dc:creator>cbunge</dc:creator>
      <dc:date>2022-07-28T19:17:06Z</dc:date>
    </item>
  </channel>
</rss>

