{"id":1094,"date":"2021-07-24T10:32:19","date_gmt":"2021-07-24T17:32:19","guid":{"rendered":"https:\/\/bullyrooks.com\/?p=1094"},"modified":"2021-07-25T06:53:50","modified_gmt":"2021-07-25T13:53:50","slug":"terraform-setup-and-first-install","status":"publish","type":"post","link":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/terraform-setup-and-first-install\/","title":{"rendered":"Terraform Setup and First Install"},"content":{"rendered":"\n<p>Terraform is a system that allows you to define your infrastructure in a series of configuration files.  These configuration files are linked to a provider library which will execute the infrastructure create, update and teardown commands on the platform you want to deploy to.  This is called &#8220;Infrastructure as Code&#8221; (or IaC) which has the benefits (and drawbacks?) that code has<\/p>\n\n\n\n<ul class=\"wp-block-list\"><li>Repeatability<\/li><li>Versioning<\/li><li>etc&#8230;<\/li><\/ul>\n\n\n\n<p>We&#8217;re going to define (in configuration) the steps that we just executed (create a lambda and the configuration associated with it, create an API Gateway trigger and associate it to the lambda, etc&#8230;) and then use a single command via terraform to install them.  Additionally, since terraform understands the state of the system we can also execute a single command to tear down everything we just did (which is useful for things like uninstalling everything to keep costs down)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Installation and Configuration of Terraform<\/h2>\n\n\n\n<p>HashiCorp (the developers of Terraform) <a href=\"https:\/\/learn.hashicorp.com\/tutorials\/terraform\/install-cli\">have the installation guide<\/a>.  I&#8217;m using windows, so I&#8217;ll be using chocolatey.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>C:\\WINDOWS\\system32>choco install terraform\r\nChocolatey v0.10.15\r\nInstalling the following packages:\r\nterraform\r\nBy installing you accept licenses for the packages.\r\nProgress: Downloading terraform 1.0.2... 100%\n...\n The install of terraform was successful.\r\n  Software installed to 'C:\\ProgramData\\chocolatey\\lib\\terraform\\tools'\r\n\r\nChocolatey installed 1\/1 packages.\r\n See the log for details (C:\\ProgramData\\chocolatey\\logs\\chocolatey.log).<\/code><\/pre>\n\n\n\n<p>In order to be safe with regards to security, I will also be creating a credentials file to log into AWS.  Create a file in your home <code>.aws\/<\/code> directory (for windows that will be usually <code>c:\/Users\/${your_name}\/.aws<\/code>) called <code>credentials<\/code>.  In that file, put your access and secret keys from AWS in this format:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ cat credentials\r\n&#91;default]\r\naws_access_key_id = AKIASXXXXXXXXXMSHFU\r\naws_secret_access_key = XXXXXXXXXXC8Yi\r\n\r<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Create the Terraform Configuration<\/h2>\n\n\n\n<p>Now navigate back to your project directory and let&#8217;s start a new branch<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git checkout -b terraform-local\r\nSwitched to a new branch 'terraform-local'\r<\/code><\/pre>\n\n\n\n<p>Create a directory called <code>\/tf<\/code> off the root of the project and create a file called <code>variables.tf<\/code> with this content<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>variable \"aws_region\" {\r\n  default = \"us-east-1\"\r\n}\r\nvariable \"app-name\" {\r\n  default = \"helloWorld-lambda\"\r\n}\r\n<\/code><\/pre>\n\n\n\n<p>Next, create another file called <code>main.tf<\/code> with this content<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>provider \"aws\" {\r\n  region = \"${var.aws_region}\"\r\n  shared_credentials_file = \"\/Users\/<span class=\"has-inline-color has-vivid-red-color\">${your_name}<\/span>\/.aws\/credentials\"\r\n}\r\n\r\n\r\n#Assume the role needed to create the lambda\r\nresource \"aws_iam_role\" \"iam_for_helloWorld_lambda\" {\r\n  name = \"iam_for_helloWorld_lambda\"\r\n\r\n  assume_role_policy = &lt;&lt;EOF\r\n{\r\n  \"Version\": \"2012-10-17\",\r\n  \"Statement\": &#91;\r\n    {\r\n      \"Action\": \"sts:AssumeRole\",\r\n      \"Principal\": {\r\n        \"Service\": \"lambda.amazonaws.com\"\r\n      },\r\n      \"Effect\": \"Allow\",\r\n      \"Sid\": \"\"\r\n    }\r\n  ]\r\n}\r\nEOF\r\n}\r\n\r\n#create the lambda from the code in the s3 bucket.  Make sure that all of the policies are in place before\r\n#we attempt to create this\r\nresource \"aws_lambda_function\" \"tf-helloWorld\" {\r\n  function_name = \"helloWorld-lambda\"\r\n  filename = \"..\/target\/helloworld-lambda-0.0.1-SNAPSHOT-aws.jar\"\r\n  role = aws_iam_role.iam_for_helloWorld_lambda.arn\r\n  handler = \"org.springframework.cloud.function.adapter.aws.SpringBootApiGatewayRequestHandler::handleRequest\"\r\n  memory_size = 512\r\n  timeout = 15\r\n\r\n  runtime = \"java11\"\r\n\r\n  depends_on = &#91;\r\n    aws_iam_role_policy_attachment.helloWorld-log-attach,\r\n    aws_cloudwatch_log_group.helloWorld-logs,\r\n  ]\r\n\r\n  environment {\r\n    variables = {\r\n      FUNCTION_NAME = \"apiFunction\"\r\n    }\r\n  }\r\n}\r\n\r\n#create a log group for the lambda\r\nresource \"aws_cloudwatch_log_group\" \"helloWorld-logs\" {\r\n  name = \"\/aws\/lambda\/${var.app-name}\"\r\n\r\n  retention_in_days = 30\r\n}\r\n\r\n#create a policy to be able to write the logs\r\nresource \"aws_iam_policy\" \"helloWorld-logs\" {\r\n  name = \"helloWorld_lambda_logging\"\r\n  path = \"\/\"\r\n  description = \"IAM policy for logging from a lambda\"\r\n\r\n  policy = &lt;&lt;EOF\r\n{\r\n  \"Version\": \"2012-10-17\",\r\n  \"Statement\": &#91;\r\n    {\r\n      \"Action\": &#91;\r\n        \"logs:CreateLogGroup\",\r\n        \"logs:CreateLogStream\",\r\n        \"logs:PutLogEvents\"\r\n      ],\r\n      \"Resource\": \"arn:aws:logs:*:*:*\",\r\n      \"Effect\": \"Allow\"\r\n    }\r\n  ]\r\n}\r\nEOF\r\n}\r\n\r\n#associate the log policy privileges to the lambda iam\r\nresource \"aws_iam_role_policy_attachment\" \"helloWorld-log-attach\" {\r\n  role = aws_iam_role.iam_for_helloWorld_lambda.name\r\n  policy_arn = aws_iam_policy.helloWorld-logs.arn\r\n}\r\n\r\n# Now, we need an API to expose those functions publicly\r\nresource \"aws_apigatewayv2_api\" \"helloWorld-api\" {\r\n  name = \"Hello API\"\r\n  protocol_type = \"HTTP\"\r\n  target = aws_lambda_function.tf-helloWorld.invoke_arn\r\n}\r\n\r\nresource \"aws_lambda_permission\" \"helloWorld-permission\" {\r\n  action = \"lambda:InvokeFunction\"\r\n  function_name = aws_lambda_function.tf-helloWorld.arn\r\n  principal = \"apigateway.amazonaws.com\"\r\n\r\n  source_arn = \"${aws_apigatewayv2_api.helloWorld-api.execution_arn}\/*\/*\"\r\n}<\/code><\/pre>\n\n\n\n<p>There&#8217;s a lot here, but I&#8217;ll walk you through what each clause is doing:<\/p>\n\n\n\n<p><strong><code>provider<\/code><\/strong> : tells terraform that we&#8217;re going to be using AWS commands, so download and install the AWS provider libraries that are needed, also configures our credentials<\/p>\n\n\n\n<p><strong><code>aws_iam_role<\/code><\/strong> : grant access to the lambda functions (create, in our case) to our script<\/p>\n\n\n\n<p><strong><code>aws_lambda_function<\/code><\/strong> : this is the lambda create statement.  Note that we&#8217;re pulling from the local file system.  Also, the <code>depends_on<\/code> which tells terraform to go ahead and execute those clauses first (its declarative, doesn&#8217;t execute from top down).  This should look familiar because of the manual install we did before.<\/p>\n\n\n\n<p><strong><code>aws_cloudwatch_log_group<\/code><\/strong> : we&#8217;re going to do some logging, so create a place to store them<\/p>\n\n\n\n<p><strong><code>resource \"aws_iam_policy\" \"helloWorld-logs\"<\/code><\/strong> : define access to write to the logs<\/p>\n\n\n\n<p><strong><code>resource \"aws_iam_role_policy_attachment\" \"helloWorld-log-attach\"<\/code><\/strong> : give permission for the lambda to use the policy we just created (so it can write)<\/p>\n\n\n\n<p><strong><code>aws_apigatewayv2_api<\/code><\/strong> : define an API Gateway instance<\/p>\n\n\n\n<p><strong><code>aws_lambda_permission<\/code><\/strong> : give permission to the API Gateway to trigger the lambda<\/p>\n\n\n\n<p>That&#8217;s a lot of stuff!  AWS console is doing a bunch of this stuff behind the scenes for you, but pulling it out into terraform means that you can evolve it (and we will in this course) in a safe way with version control.  <\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Initialize and Execute Terraform<\/h2>\n\n\n\n<p>Now we need to tell Terraform to get ready to execute our code.  Terraform needs to pull in the libraries that we&#8217;re going to use (AWS provider) and prepare to execute.  From the <code>\/tf<\/code> directory execute this command:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ terraform init\r\n\r\nInitializing the backend...\r\n\r\nInitializing provider plugins...\r\n- Finding latest version of hashicorp\/aws...\r\n- Installing hashicorp\/aws v3.51.0...\r\n- Installed hashicorp\/aws v3.51.0 (signed by HashiCorp)\r\n...\nTerraform has been successfully initialized!<\/code><\/pre>\n\n\n\n<p>If at this point you execute terraform plan, you&#8217;ll see what terraform plans to execute:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ terraform plan\r\n\r\nTerraform used the selected providers to generate the following execution plan. Resource actions are indicated with the following symbols:\r\n  + create\r\n\r\nTerraform will perform the following actions:\r\n\r\n  # aws_apigatewayv2_api.helloWorld-api will be created\r\n  + resource \"aws_apigatewayv2_api\" \"helloWorld-api\" {\r\n...\nPlan: 7 to add, 0 to change, 0 to destroy.<\/code><\/pre>\n\n\n\n<p>Lets go ahead and execute it<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ terraform apply\n...\naws_cloudwatch_log_group.helloWorld-logs: Creating...\r\naws_iam_policy.helloWorld-logs: Creating...\r\naws_iam_role.iam_for_helloWorld_lambda: Creating...\r\naws_iam_policy.helloWorld-logs: Creation complete after 1s &#91;id=arn:aws:iam::282457041796:policy\/helloWorld_lambda_logging]\r\naws_cloudwatch_log_group.helloWorld-logs: Creation complete after 1s &#91;id=\/aws\/lambda\/helloWorld]\r\naws_iam_role.iam_for_helloWorld_lambda: Creation complete after 1s &#91;id=iam_for_helloWorld_lambda]\r\naws_iam_role_policy_attachment.helloWorld-log-attach: Creating...\r\naws_iam_role_policy_attachment.helloWorld-log-attach: Creation complete after 1s &#91;id=iam_for_helloWorld_lambda-20210724164455618400000001]\r\naws_lambda_function.tf-helloWorld: Creating...\r\naws_lambda_function.tf-helloWorld: Still creating... &#91;10s elapsed]\r\naws_lambda_function.tf-helloWorld: Still creating... &#91;20s elapsed]\r\naws_lambda_function.tf-helloWorld: Still creating... &#91;30s elapsed]\r\naws_lambda_function.tf-helloWorld: Still creating... &#91;40s elapsed]\r\naws_lambda_function.tf-helloWorld: Creation complete after 49s &#91;id=helloWorld-lambda]\r\naws_apigatewayv2_api.helloWorld-api: Creating...\r\naws_apigatewayv2_api.helloWorld-api: Creation complete after 1s &#91;id=m812gnu7x9]\r\naws_lambda_permission.helloWorld-permission: Creating...\r\naws_lambda_permission.helloWorld-permission: Creation complete after 0s &#91;id=terraform-20210724164545966500000002]\r\n\r\nApply complete! Resources: 7 added, 0 changed, 0 destroyed.\r<\/code><\/pre>\n\n\n\n<p>Now lets checkout the lambda page in the console and see if we&#8217;ve got a new lambda<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"43\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-18-1024x46.png?resize=960%2C43&#038;ssl=1\" alt=\"\" class=\"wp-image-1095\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-18.png?resize=1024%2C46&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-18.png?resize=300%2C14&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-18.png?resize=768%2C35&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-18.png?w=1196&amp;ssl=1 1196w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>Now lets grab the API from the lambda trigger<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"553\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19-1024x590.png?resize=960%2C553&#038;ssl=1\" alt=\"\" class=\"wp-image-1096\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=1024%2C590&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=300%2C173&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?resize=768%2C443&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-19.png?w=1142&amp;ssl=1 1142w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>If we paste that into our postman, we can see it respond with success:<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"960\" height=\"270\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-21-1024x288.png?resize=960%2C270&#038;ssl=1\" alt=\"\" class=\"wp-image-1098\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-21.png?resize=1024%2C288&amp;ssl=1 1024w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-21.png?resize=300%2C84&amp;ssl=1 300w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-21.png?resize=768%2C216&amp;ssl=1 768w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-21.png?w=1308&amp;ssl=1 1308w\" sizes=\"auto, (max-width: 960px) 100vw, 960px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Terraform State<\/h2>\n\n\n\n<p>If you review the directory structure in <code>\/tf<\/code> now you should see some interesting stuff:<\/p>\n\n\n\n<figure class=\"wp-block-image size-full\"><img loading=\"lazy\" decoding=\"async\" width=\"415\" height=\"260\" src=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-22.png?resize=415%2C260&#038;ssl=1\" alt=\"\" class=\"wp-image-1099\" srcset=\"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-22.png?w=415&amp;ssl=1 415w, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-22.png?resize=300%2C188&amp;ssl=1 300w\" sizes=\"auto, (max-width: 415px) 100vw, 415px\" data-recalc-dims=\"1\" \/><\/figure>\n\n\n\n<p>the provider registry is similar to maven repository, its a local copy of all of the providers that you needed to execute (<code>terraform init<\/code> created this)<\/p>\n\n\n\n<p>Also, you&#8217;ll see two files <code>terraform.tfstate<\/code> and <code>.terraform.lock.hcl<\/code>.  These files are created by <code>terraform apply<\/code> to track the current state of the system you&#8217;ve created.  Any modifications will be reviewed against the state before being applied and only the changes will be made.  Additionally, this lock file prevents other users from wiping out your changes.  <\/p>\n\n\n\n<p>we can see this in action by executing <code>terraform plan<\/code> again:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ terraform plan\n...\nNo changes. Your infrastructure matches the configuration.<\/code><\/pre>\n\n\n\n<p>While this is nice, its not going to help us out when we want to deploy in an automated fashion because our pipeline will create its own terraform state which will conflict with our local version.  In the next step in the course we&#8217;ll see how to make a &#8216;central&#8217; state and lock file in the cloud so that everyone can be executing against the same plan.<\/p>\n\n\n\n<p>For now, lets blow away our application<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>$ terraform destroy\n...\naws_lambda_permission.helloWorld-permission: Destroying... &#91;id=terraform-20210724164545966500000002]\naws_lambda_permission.helloWorld-permission: Destruction complete after 1s\naws_apigatewayv2_api.helloWorld-api: Destroying... &#91;id=m812gnu7x9]\naws_apigatewayv2_api.helloWorld-api: Destruction complete after 1s\naws_lambda_function.tf-helloWorld: Destroying... &#91;id=helloWorld-lambda]\naws_lambda_function.tf-helloWorld: Destruction complete after 0s\naws_iam_role_policy_attachment.helloWorld-log-attach: Destroying... &#91;id=iam_for_helloWorld_lambda-20210724164455618400000001]\naws_cloudwatch_log_group.helloWorld-logs: Destroying... &#91;id=\/aws\/lambda\/helloWorld]\naws_iam_role_policy_attachment.helloWorld-log-attach: Destruction complete after 0s\naws_cloudwatch_log_group.helloWorld-logs: Destruction complete after 0s\naws_iam_policy.helloWorld-logs: Destroying... &#91;id=arn:aws:iam::282457041796:policy\/helloWorld_lambda_logging]\naws_iam_role.iam_for_helloWorld_lambda: Destroying... &#91;id=iam_for_helloWorld_lambda]\naws_iam_policy.helloWorld-logs: Destruction complete after 1s\naws_iam_role.iam_for_helloWorld_lambda: Destruction complete after 1s\n\nDestroy complete! Resources: 7 destroyed.<\/code><\/pre>\n\n\n\n<p>we also do not want to check in our state files, so update our <code>.gitignore<\/code> to ignore them (<a href=\"https:\/\/github.com\/github\/gitignore\/blob\/master\/Terraform.gitignore\">from here<\/a>)<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code># Local .terraform directories\r\n**\/.terraform\/*\r\n\r\n# .tfstate files\r\n*.tfstate\r\n*.tfstate.*\r\n*.terraform.lock.*\r\n\r\n# Crash log files\r\ncrash.log\r\n\r\n# Exclude all .tfvars files, which are likely to contain sentitive data, such as\r\n# password, private keys, and other secrets. These should not be part of version\r\n# control as they are data points which are potentially sensitive and subject\r\n# to change depending on the environment.\r\n#\r\n*.tfvars\r\n\r\n# Ignore override files as they are usually used to override resources locally and so\r\n# are not checked in\r\noverride.tf\r\noverride.tf.json\r\n*_override.tf\r\n*_override.tf.json\r\n\r\n# Include override files you do wish to add to version control using negated pattern\r\n#\r\n# !example_override.tf\r\n\r\n# Include tfplan files to ignore the plan output of command: terraform plan -out=tfplan\r\n# example: *tfplan*\r\n\r\n# Ignore CLI configuration files\r\n.terraformrc\r\nterraform.rc<\/code><\/pre>\n\n\n\n<h2 class=\"wp-block-heading\">Commit and Merge<\/h2>\n\n\n\n<pre class=\"wp-block-code\"><code>$ git status\n$ git add .\n$ git commit -m \"first terraform files\"\n$ git push --set-upstream origin terraform-local\n$ git checkout main\n$ git merge terraform-local\n$ git push<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<div class=\"entry-summary\">\nTerraform is a system that allows you to define your infrastructure in&hellip;\n<\/div>\n<div class=\"link-more\"><a href=\"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/terraform-setup-and-first-install\/\" class=\"more-link\">Continue reading<span class=\"screen-reader-text\"> &ldquo;Terraform Setup and First Install&rdquo;<\/span>&hellip;<\/a><\/div>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[41],"tags":[142,146,77,148,44,147,144,143,50,42,43,145],"course":[141],"class_list":["post-1094","post","type-post","status-publish","format-standard","hentry","category-software-development","tag-aws","tag-aws-gateway","tag-cicd","tag-functions","tag-github","tag-github-actions","tag-java","tag-lambda","tag-maven","tag-spring","tag-spring-boot","tag-terraform","course-spring-boot-lambda-on-aws","entry"],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":1102,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/terraform-centralized-state-management\/","url_meta":{"origin":1094,"position":0},"title":"Terraform Centralized State Management","author":"Bullyrook","date":"July 24, 2021","format":false,"excerpt":"As we saw in the last course Terraform will manage the state of your application, but by default it stores this locally. This is not ideal for us and will cause problems when we try to work with others or create a continuous deployment pipeline. Now we'll create a way\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-23.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-23.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-23.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-23.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-23.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":1115,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/automated-terraform-deploy-using-github-actions\/","url_meta":{"origin":1094,"position":1},"title":"Automated Terraform Deploy Using Github Actions","author":"Bullyrook","date":"July 24, 2021","format":false,"excerpt":"Now we just need to build and deploy our application automatically so that whenever we push changes to the main branch, they'll automatically become available through our endpoint. Create Our Artifact Storage We're going to use a 'poor man's artifactory' to store our compiled .jar files. With our current build\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-34.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":1081,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/24\/spring-boot-lambda-api-implementation\/","url_meta":{"origin":1094,"position":2},"title":"Spring Boot Lambda API Implementation","author":"Bullyrook","date":"July 24, 2021","format":false,"excerpt":"We've got a 'working' lambda now, but we can't actually use it anywhere. The easiest thing to do at this point is add an API Gateway trigger to our function as a new lambda. This will require a little bit of work to make an API Gateway adapter to our\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-10.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1133,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/25\/confirming-the-continuous-deployment-pipeline\/","url_meta":{"origin":1094,"position":3},"title":"Confirming the Continuous Deployment Pipeline","author":"Bullyrook","date":"July 25, 2021","format":false,"excerpt":"Lets verify that changes to our application will be automatically available when they're pushed up. Update the Application Let's start a new branch $ git checkout -b \"greeting-change\" Now update our service to return a different greeting: @Component public class HelloWorldService { public HelloWorld helloWorld(String name) { return HelloWorld.builder() .response(\"G'Day,\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-48.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-48.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-48.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-48.png?resize=1050%2C600&ssl=1 3x"},"classes":[]},{"id":1065,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/23\/spring-boot-lambda-prerequisites\/","url_meta":{"origin":1094,"position":4},"title":"Spring Boot Lambda Prerequisites","author":"Bullyrook","date":"July 23, 2021","format":false,"excerpt":"In this course we're going to build a very simple spring boot lambda, deploy it manually to AWS to make sure that it works and then automate the deployment using Terraform and github actions. This will allow us to automatically build and deploy changes from a commit to the main\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":1069,"url":"https:\/\/bullyrooks.com\/index.php\/2021\/07\/23\/spring-boot-lambda-implementation\/","url_meta":{"origin":1094,"position":5},"title":"Spring Boot Lambda Implementation","author":"Bullyrook","date":"July 23, 2021","format":false,"excerpt":"Now we're going to add some code. I'm going to follow my ports and adapters method of building a DTO and value object that I've used previously. Yes, its a bit of overkill for this project (especially a hello world example), but if you're using this course as a springboard\u2026","rel":"","context":"In &quot;Software Development&quot;","block_context":{"text":"Software Development","link":"https:\/\/bullyrooks.com\/index.php\/category\/software-development\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-4.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-4.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/bullyrooks.com\/wp-content\/uploads\/2021\/07\/image-4.png?resize=700%2C400&ssl=1 2x"},"classes":[]}],"_links":{"self":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1094","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/comments?post=1094"}],"version-history":[{"count":2,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1094\/revisions"}],"predecessor-version":[{"id":1101,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/posts\/1094\/revisions\/1101"}],"wp:attachment":[{"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/media?parent=1094"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/categories?post=1094"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/tags?post=1094"},{"taxonomy":"course","embeddable":true,"href":"https:\/\/bullyrooks.com\/index.php\/wp-json\/wp\/v2\/course?post=1094"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}