SlideShare a Scribd company logo
1 of 59
Download to read offline
Copyright © 2018 HashiCorp HashiCorp
Infrastructure as Code
With Terraform
Copyright © 2018 HashiCorp HashiCorp
Everything as Code
With Terraform
Copyright © 2018 HashiCorp HashiCorp
Infrastructure as Code
With Terraform
Copyright © 2018 HashiCorp HashiCorp
Infrastructure as Code
With Terraform
Maturity
Manual Everything
Basic Automation
#!/bin/bash
Machine Virtualization
*aaS
Datacenter-as-Computer
Maturity
Capability Complexity
475 def update
476 return update_api if api_request?
477
478 if authorized_action(@account, @current_user, :manage_account_settings)
479 respond_to do |format|
480
481 custom_help_links = params[:account].delete :custom_help_links
482 if custom_help_links
483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete
484 hash = index_with_hash[1]
485 hash.delete('state')
486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"]
487 hash
488 end
489 end
490
491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host])
492 enable_user_notes = params[:account].delete :enable_user_notes
493 allow_sis_import = params[:account].delete :allow_sis_import
494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou
495 unless @account.grants_right? @current_user, :manage_storage_quotas
496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb,
497 :default_user_storage_quota, :default_user_storage_quota_mb,
498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account]
499 end
500 if params[:account][:services]
501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a
502 @account.set_service_availability(key, value == '1')
503 end
504 params[:account].delete :services
505 end
506 if @account.grants_right?(@current_user, :manage_site_settings)
507 # If the setting is present (update is called from 2 different settings forms, one for notifi
508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op
509 # If set to default, remove the custom name so it doesn't get saved
510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting
511 end
512
513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain)
514 if @account.feature_enabled?(:google_docs_domain_restriction) &&
515 @account.root_account? &&
516 !@account.site_admin?
517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain :
518 end
519
520 @account.enable_user_notes = enable_user_notes if enable_user_notes
521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account?
522 if @account.site_admin? && params[:account][:settings]
523 # these shouldn't get set for the site admin account
524 params[:account][:settings].delete(:enable_alerts)
525 params[:account][:settings].delete(:enable_eportfolios)
526 end
527 else
528 # must have :manage_site_settings to update these
529 [ :admins_can_change_passwords,
530 :admins_can_view_notifications,
531 :enable_alerts,
532 :enable_eportfolios,
533 :enable_profiles,
534 :show_scheduler,
535 :global_includes,
536 :gmail_domain
537 ].each do |key|
538 params[:account][:settings].try(:delete, key)
475 def update
476 return update_api if api_request?
477
478 if authorized_action(@account, @current_user, :manage_account_settings)
479 respond_to do |format|
480
481 custom_help_links = params[:account].delete :custom_help_links
482 if custom_help_links
483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete
484 hash = index_with_hash[1]
485 hash.delete('state')
486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"]
487 hash
488 end
489 end
490
491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host])
492 enable_user_notes = params[:account].delete :enable_user_notes
493 allow_sis_import = params[:account].delete :allow_sis_import
494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou
495 unless @account.grants_right? @current_user, :manage_storage_quotas
496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb,
497 :default_user_storage_quota, :default_user_storage_quota_mb,
498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account]
499 end
500 if params[:account][:services]
501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a
502 @account.set_service_availability(key, value == '1')
503 end
504 params[:account].delete :services
505 end
506 if @account.grants_right?(@current_user, :manage_site_settings)
507 # If the setting is present (update is called from 2 different settings forms, one for notifi
508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op
509 # If set to default, remove the custom name so it doesn't get saved
510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting
511 end
512
513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain)
514 if @account.feature_enabled?(:google_docs_domain_restriction) &&
515 @account.root_account? &&
516 !@account.site_admin?
517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain :
518 end
519
520 @account.enable_user_notes = enable_user_notes if enable_user_notes
521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account?
522 if @account.site_admin? && params[:account][:settings]
523 # these shouldn't get set for the site admin account
524 params[:account][:settings].delete(:enable_alerts)
525 params[:account][:settings].delete(:enable_eportfolios)
526 end
527 else
528 # must have :manage_site_settings to update these
529 [ :admins_can_change_passwords,
530 :admins_can_view_notifications,
531 :enable_alerts,
532 :enable_eportfolios,
533 :enable_profiles,
534 :show_scheduler,
535 :global_includes,
536 :gmail_domain
537 ].each do |key|
538 params[:account][:settings].try(:delete, key)
Infrastructure as Code
475 def update
476 return update_api if api_request?
477
478 if authorized_action(@account, @current_user, :manage_account_settings)
479 respond_to do |format|
480
481 custom_help_links = params[:account].delete :custom_help_links
482 if custom_help_links
483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete
484 hash = index_with_hash[1]
485 hash.delete('state')
486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"]
487 hash
488 end
489 end
490
491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host])
492 enable_user_notes = params[:account].delete :enable_user_notes
493 allow_sis_import = params[:account].delete :allow_sis_import
494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou
495 unless @account.grants_right? @current_user, :manage_storage_quotas
496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb,
497 :default_user_storage_quota, :default_user_storage_quota_mb,
498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account]
499 end
500 if params[:account][:services]
501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a
502 @account.set_service_availability(key, value == '1')
503 end
504 params[:account].delete :services
505 end
506 if @account.grants_right?(@current_user, :manage_site_settings)
507 # If the setting is present (update is called from 2 different settings forms, one for notifi
508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op
509 # If set to default, remove the custom name so it doesn't get saved
510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting
511 end
512
513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain)
514 if @account.feature_enabled?(:google_docs_domain_restriction) &&
515 @account.root_account? &&
516 !@account.site_admin?
517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain :
518 end
519
520 @account.enable_user_notes = enable_user_notes if enable_user_notes
521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account?
522 if @account.site_admin? && params[:account][:settings]
523 # these shouldn't get set for the site admin account
524 params[:account][:settings].delete(:enable_alerts)
525 params[:account][:settings].delete(:enable_eportfolios)
526 end
527 else
528 # must have :manage_site_settings to update these
529 [ :admins_can_change_passwords,
530 :admins_can_view_notifications,
531 :enable_alerts,
532 :enable_eportfolios,
533 :enable_profiles,
534 :show_scheduler,
535 :global_includes,
536 :gmail_domain
537 ].each do |key|
538 params[:account][:settings].try(:delete, key)
Infrastructure as Code
Source of knowledge
Supports versioning, collaboration
Executable
475 def update
476 return update_api if api_request?
477
478 if authorized_action(@account, @current_user, :manage_account_settings)
479 respond_to do |format|
480
481 custom_help_links = params[:account].delete :custom_help_links
482 if custom_help_links
483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete
484 hash = index_with_hash[1]
485 hash.delete('state')
486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"]
487 hash
488 end
489 end
490
491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host])
492 enable_user_notes = params[:account].delete :enable_user_notes
493 allow_sis_import = params[:account].delete :allow_sis_import
494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou
495 unless @account.grants_right? @current_user, :manage_storage_quotas
496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb,
497 :default_user_storage_quota, :default_user_storage_quota_mb,
498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account]
499 end
500 if params[:account][:services]
501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a
502 @account.set_service_availability(key, value == '1')
503 end
504 params[:account].delete :services
505 end
506 if @account.grants_right?(@current_user, :manage_site_settings)
507 # If the setting is present (update is called from 2 different settings forms, one for notifi
508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op
509 # If set to default, remove the custom name so it doesn't get saved
510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting
511 end
512
513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain)
514 if @account.feature_enabled?(:google_docs_domain_restriction) &&
515 @account.root_account? &&
516 !@account.site_admin?
517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain :
518 end
519
520 @account.enable_user_notes = enable_user_notes if enable_user_notes
521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account?
522 if @account.site_admin? && params[:account][:settings]
523 # these shouldn't get set for the site admin account
524 params[:account][:settings].delete(:enable_alerts)
525 params[:account][:settings].delete(:enable_eportfolios)
526 end
527 else
528 # must have :manage_site_settings to update these
529 [ :admins_can_change_passwords,
530 :admins_can_view_notifications,
531 :enable_alerts,
532 :enable_eportfolios,
533 :enable_profiles,
534 :show_scheduler,
535 :global_includes,
536 :gmail_domain
537 ].each do |key|
538 params[:account][:settings].try(:delete, key)
Copyright © 2018 HashiCorp HashiCorp
Infrastructure as Code
With Terraform
Terraform
Tool to manage anything with an API as code
Open source (> 12,000 stars, > 1,000 contributors)
Support for over 100 providers, including all major
clouds: AWS, Azure, GCP, and more.
Goals
Unify the view of resources using infra as code
Expose a way for individuals and teams to safely and
predictably change infrastructure
Manage anything with an API
resource "aws_instance" "web" {
ami = "ami-b123125"
}
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${aws_instance.web.public_ip}"
type = "A"
}
C O D E E D I T O R
resource "aws_instance" "web" {
ami = "ami-b123125"
}
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${aws_instance.web.public_ip}"
type = "A"
}
C O D E E D I T O R
resource "aws_instance" "web" {
ami = "ami-b123125"
}
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${aws_instance.web.public_ip}"
type = "A"
}
C O D E E D I T O R
resource "aws_instance" "web" {
ami = "ami-b123125"
}
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${aws_instance.web.public_ip}"
type = "A"
}
C O D E E D I T O R
Configuration
Declarative: what you want, vs how to do it
Human-friendly, JSON compatible
Versionable, VCS-friendly
resource "aws_instance" "web" {
- ami = "ami-b123125"
+ ami = "ami-c345123"
}
resource "dnsimple_record" "hello" {
domain = "example.com"
name = "test"
value = "${aws_instance.web.public_ip}"
type = "A"
}
C O D E E D I T O R
Command: terraform plan
The plan shows you what will happen
You can save plans to guarantee what will happen
Plans show reasons for certain actions (such as re-
create)
Prior to Terraform, users had to guess change ordering,
parallelization, and rollout effect
Command: terraform plan
+ resource will be created
- resource will be destroyed
~ resource will be updated in-place
-/+ resources will be destroyed and re-created
T E R M I N A L
$ terraform plan
+ aws_instance.web
ami: "ami-db24d8b6"
availability_zone: "<computed>"
ebs_block_device.#: "<computed>"
ephemeral_block_device.#: "<computed>"
instance_state: "<computed>"
instance_type: "t2.micro"
key_name: "<computed>"
network_interface_id: "<computed>"
placement_group: "<computed>"
private_dns: "<computed>"
private_ip: "<computed>"
public_dns: "<computed>"
public_ip: "<computed>"
# ...
Command: terraform apply
Executes changes in order based on the resource graph
Parallelizes changes when possible
Handles and recovers transient errors
Runs plan first unless given a serialized plan file
T E R M I N A L
$ terraform apply
aws_instance.web: Creating...
ami: "" => "ami-db24d8b6"
# ...
source_dest_check: "" => "true"
subnet_id: "" => "subnet-f6e6a5dc"
aws_instance.web: Still creating... (10s elapsed)
aws_instance.web: Still creating... (20s elapsed)
aws_instance.web: Creation complete
Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
A Workflow for Safe Infrastructure
"terraform apply"
The make things happen command (after confirm)
Tell Terraform what you want, sit back and let
Terraform make it a reality.
Modules
Reusable packages of Terraform configuration
Enable broader usage of Terraform
Share and discover: https://registry.terraform.io/
module "consul" {
source = "hashicorp/consul/aws"
version = "~> 0.3.0"
}
output "servers" {
value = "${module.consul.asg_name_servers}
}
C O D E E D I T O R
Copyright © 2018 HashiCorp HashiCorp
Everything as Code
With Terraform
Providers
Integration point
Expose resources, such as "aws_instance"
Can be created for anything with an API
Easy to write, great beginner Go project
resource "TYPE" "NAME" {
CONFIG
}
C O D E E D I T O R
resource "TYPE" "NAME" {
CONFIG
}
C O D E E D I T O R
Terraform's Internals
Core
Providers
Upstream APIsPlugins
Terraform's Internals
Core
Providers
Upstream APIsPlugins
Diff()
Apply()
Refresh()
Create()
Read()
Update()
Delete()
Terraform's Internals
Core
Providers
Upstream APIsPlugins
Diff()
Apply()
Refresh()
Create()
Read()
Update()
Delete()
Terraform's Internals
Config: Target Reality
State: Current Reality
Diff: {Config - State}
Plan: Presents Diff
Apply: Resolves Diff
FOR

EVERY THING
Example: PagerDuty
On-call schedules as code
Notifications as code
Manage PagerDuty schedules, teams, and users

as code!
resource "pagerduty_team" "engineering" {
name = "Engineering"
description = "All engineering"
}
resource "pagerduty_user" "earline" {
name = "Earline Greenholt"
email = "125.greenholt.earline@graham.name"
teams = ["${pagerduty_team.engineering.id}"]
}
C O D E E D I T O R
resource "pagerduty_schedule" "foo" {
name = "Daily Engineering Rotation"
time_zone = "America/New_York"
layer {
name = "Night Shift"
...
users = ["${pagerduty_user.earline.id}"]
restriction {
type = "daily_restriction"
start_time_of_day = "08:00:00"
duration_seconds = 32400
}
}
}
C O D E E D I T O R
FOR

EVERY THING
Example: DataDog
Metrics as code
Notifications as code
Manage DataDog users, monitors, and timeboards

as code.
resource "datadog_timeboard" "redis" {
title = "Redis Timeboard (created via Terraform)"
read_only = true
graph {
title = "Redis latency (ms)"
viz = "timeseries"
request {
q = "avg:redis.info.latency_ms{$host}"
type = "bars"
}
}
}
C O D E E D I T O R
resource "datadog_monitor" "foo" {
name = "Name for monitor foo"
type = "metric alert"
message = "Monitor triggered. Notify:
@hipchat-channel"
escalation_message = "Escalation message @pagerduty"
query = "avg(last_1h):avg:cpu{host:foo} by {host} > 4"
thresholds {
ok = 0
warning = 2
warning_recovery = 1
critical = 4
critical_recovery = 3
}
C O D E E D I T O R
FOR

EVERY THING
Example: GitHub
Organization and teams as code
Issue labels as code
Etc.
HashiCorp uses this to manage provider repositories!
variable "issue_labels" {
default = {
"custom-label" = "533D99"
"documentation" = "FFB340"
"waiting-reply" = "CC6A14"
}
}
resource "github_issue_label" "test_repo" {
repository = "${github_repository.example-repo.id}"
count = "${length(var.issue_labels)}"
name = "${element(keys(var.issue_labels),
count.index)}"
color = "${element(values(var.issue_labels),
count.index)}"
}
C O D E E D I T O R
Learn More
All Providers

terraform.io/docs/providers
Extending Terraform

terraform.io/docs/extend
Provider Development Program

terraform.io/guides/

terraform-provider-development-program.html
Thank You.

More Related Content

More from J On The Beach

When Cloud Native meets the Financial Sector
When Cloud Native meets the Financial SectorWhen Cloud Native meets the Financial Sector
When Cloud Native meets the Financial SectorJ On The Beach
 
The big data Universe. Literally.
The big data Universe. Literally.The big data Universe. Literally.
The big data Universe. Literally.J On The Beach
 
Streaming to a New Jakarta EE
Streaming to a New Jakarta EEStreaming to a New Jakarta EE
Streaming to a New Jakarta EEJ On The Beach
 
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...J On The Beach
 
Pushing AI to the Client with WebAssembly and Blazor
Pushing AI to the Client with WebAssembly and BlazorPushing AI to the Client with WebAssembly and Blazor
Pushing AI to the Client with WebAssembly and BlazorJ On The Beach
 
Axon Server went RAFTing
Axon Server went RAFTingAxon Server went RAFTing
Axon Server went RAFTingJ On The Beach
 
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...The Six Pitfalls of building a Microservices Architecture (and how to avoid t...
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...J On The Beach
 
Madaari : Ordering For The Monkeys
Madaari : Ordering For The MonkeysMadaari : Ordering For The Monkeys
Madaari : Ordering For The MonkeysJ On The Beach
 
Servers are doomed to fail
Servers are doomed to failServers are doomed to fail
Servers are doomed to failJ On The Beach
 
Interaction Protocols: It's all about good manners
Interaction Protocols: It's all about good mannersInteraction Protocols: It's all about good manners
Interaction Protocols: It's all about good mannersJ On The Beach
 
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...J On The Beach
 
Leadership at every level
Leadership at every levelLeadership at every level
Leadership at every levelJ On The Beach
 
Machine Learning: The Bare Math Behind Libraries
Machine Learning: The Bare Math Behind LibrariesMachine Learning: The Bare Math Behind Libraries
Machine Learning: The Bare Math Behind LibrariesJ On The Beach
 
Getting started with Deep Reinforcement Learning
Getting started with Deep Reinforcement LearningGetting started with Deep Reinforcement Learning
Getting started with Deep Reinforcement LearningJ On The Beach
 
Toward Predictability and Stability At The Edge Of Chaos
Toward Predictability and Stability At The Edge Of ChaosToward Predictability and Stability At The Edge Of Chaos
Toward Predictability and Stability At The Edge Of ChaosJ On The Beach
 
Numeric programming with spire
Numeric programming with spireNumeric programming with spire
Numeric programming with spireJ On The Beach
 
Istio Service Mesh & pragmatic microservices architecture
Istio Service Mesh & pragmatic microservices architectureIstio Service Mesh & pragmatic microservices architecture
Istio Service Mesh & pragmatic microservices architectureJ On The Beach
 
GraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster EverywhereGraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster EverywhereJ On The Beach
 
Continuous delivery in the real world
Continuous delivery in the real world Continuous delivery in the real world
Continuous delivery in the real world J On The Beach
 
Free the Functions with Fn project!
Free the Functions with Fn project!Free the Functions with Fn project!
Free the Functions with Fn project!J On The Beach
 

More from J On The Beach (20)

When Cloud Native meets the Financial Sector
When Cloud Native meets the Financial SectorWhen Cloud Native meets the Financial Sector
When Cloud Native meets the Financial Sector
 
The big data Universe. Literally.
The big data Universe. Literally.The big data Universe. Literally.
The big data Universe. Literally.
 
Streaming to a New Jakarta EE
Streaming to a New Jakarta EEStreaming to a New Jakarta EE
Streaming to a New Jakarta EE
 
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...
The TIPPSS Imperative for IoT - Ensuring Trust, Identity, Privacy, Protection...
 
Pushing AI to the Client with WebAssembly and Blazor
Pushing AI to the Client with WebAssembly and BlazorPushing AI to the Client with WebAssembly and Blazor
Pushing AI to the Client with WebAssembly and Blazor
 
Axon Server went RAFTing
Axon Server went RAFTingAxon Server went RAFTing
Axon Server went RAFTing
 
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...The Six Pitfalls of building a Microservices Architecture (and how to avoid t...
The Six Pitfalls of building a Microservices Architecture (and how to avoid t...
 
Madaari : Ordering For The Monkeys
Madaari : Ordering For The MonkeysMadaari : Ordering For The Monkeys
Madaari : Ordering For The Monkeys
 
Servers are doomed to fail
Servers are doomed to failServers are doomed to fail
Servers are doomed to fail
 
Interaction Protocols: It's all about good manners
Interaction Protocols: It's all about good mannersInteraction Protocols: It's all about good manners
Interaction Protocols: It's all about good manners
 
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...
A race of two compilers: GraalVM JIT versus HotSpot JIT C2. Which one offers ...
 
Leadership at every level
Leadership at every levelLeadership at every level
Leadership at every level
 
Machine Learning: The Bare Math Behind Libraries
Machine Learning: The Bare Math Behind LibrariesMachine Learning: The Bare Math Behind Libraries
Machine Learning: The Bare Math Behind Libraries
 
Getting started with Deep Reinforcement Learning
Getting started with Deep Reinforcement LearningGetting started with Deep Reinforcement Learning
Getting started with Deep Reinforcement Learning
 
Toward Predictability and Stability At The Edge Of Chaos
Toward Predictability and Stability At The Edge Of ChaosToward Predictability and Stability At The Edge Of Chaos
Toward Predictability and Stability At The Edge Of Chaos
 
Numeric programming with spire
Numeric programming with spireNumeric programming with spire
Numeric programming with spire
 
Istio Service Mesh & pragmatic microservices architecture
Istio Service Mesh & pragmatic microservices architectureIstio Service Mesh & pragmatic microservices architecture
Istio Service Mesh & pragmatic microservices architecture
 
GraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster EverywhereGraalVM: Run Programs Faster Everywhere
GraalVM: Run Programs Faster Everywhere
 
Continuous delivery in the real world
Continuous delivery in the real world Continuous delivery in the real world
Continuous delivery in the real world
 
Free the Functions with Fn project!
Free the Functions with Fn project!Free the Functions with Fn project!
Free the Functions with Fn project!
 

Recently uploaded

Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsNathaniel Shimoni
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxLoriGlavin3
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024Lorenzo Miniero
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteDianaGray10
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii SoldatenkoFwdays
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersRaghuram Pandurangan
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity PlanDatabarracks
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024Stephanie Beckett
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsSergiu Bodiu
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxLoriGlavin3
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxLoriGlavin3
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLScyllaDB
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxLoriGlavin3
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Manik S Magar
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek SchlawackFwdays
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embeddingZilliz
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????blackmambaettijean
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024BookNet Canada
 

Recently uploaded (20)

Time Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directionsTime Series Foundation Models - current state and future directions
Time Series Foundation Models - current state and future directions
 
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptxMerck Moving Beyond Passwords: FIDO Paris Seminar.pptx
Merck Moving Beyond Passwords: FIDO Paris Seminar.pptx
 
SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024SIP trunking in Janus @ Kamailio World 2024
SIP trunking in Janus @ Kamailio World 2024
 
Take control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test SuiteTake control of your SAP testing with UiPath Test Suite
Take control of your SAP testing with UiPath Test Suite
 
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko"Debugging python applications inside k8s environment", Andrii Soldatenko
"Debugging python applications inside k8s environment", Andrii Soldatenko
 
Generative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information DevelopersGenerative AI for Technical Writer or Information Developers
Generative AI for Technical Writer or Information Developers
 
How to write a Business Continuity Plan
How to write a Business Continuity PlanHow to write a Business Continuity Plan
How to write a Business Continuity Plan
 
What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024What's New in Teams Calling, Meetings and Devices March 2024
What's New in Teams Calling, Meetings and Devices March 2024
 
DevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platformsDevEX - reference for building teams, processes, and platforms
DevEX - reference for building teams, processes, and platforms
 
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptxThe Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
The Fit for Passkeys for Employee and Consumer Sign-ins: FIDO Paris Seminar.pptx
 
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptxDigital Identity is Under Attack: FIDO Paris Seminar.pptx
Digital Identity is Under Attack: FIDO Paris Seminar.pptx
 
Developer Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQLDeveloper Data Modeling Mistakes: From Postgres to NoSQL
Developer Data Modeling Mistakes: From Postgres to NoSQL
 
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptxUse of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
Use of FIDO in the Payments and Identity Landscape: FIDO Paris Seminar.pptx
 
Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!Anypoint Exchange: It’s Not Just a Repo!
Anypoint Exchange: It’s Not Just a Repo!
 
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
"Subclassing and Composition – A Pythonic Tour of Trade-Offs", Hynek Schlawack
 
Training state-of-the-art general text embedding
Training state-of-the-art general text embeddingTraining state-of-the-art general text embedding
Training state-of-the-art general text embedding
 
What is Artificial Intelligence?????????
What is Artificial Intelligence?????????What is Artificial Intelligence?????????
What is Artificial Intelligence?????????
 
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data PrivacyTrustArc Webinar - How to Build Consumer Trust Through Data Privacy
TrustArc Webinar - How to Build Consumer Trust Through Data Privacy
 
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
Transcript: New from BookNet Canada for 2024: BNC CataList - Tech Forum 2024
 

Infrastructure as Code with Terraform

  • 1. Copyright © 2018 HashiCorp HashiCorp Infrastructure as Code With Terraform
  • 2. Copyright © 2018 HashiCorp HashiCorp Everything as Code With Terraform
  • 3. Copyright © 2018 HashiCorp HashiCorp Infrastructure as Code With Terraform
  • 4.
  • 5.
  • 6. Copyright © 2018 HashiCorp HashiCorp Infrastructure as Code With Terraform
  • 11. *aaS
  • 14.
  • 16.
  • 17.
  • 18. 475 def update 476 return update_api if api_request? 477 478 if authorized_action(@account, @current_user, :manage_account_settings) 479 respond_to do |format| 480 481 custom_help_links = params[:account].delete :custom_help_links 482 if custom_help_links 483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete 484 hash = index_with_hash[1] 485 hash.delete('state') 486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"] 487 hash 488 end 489 end 490 491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host]) 492 enable_user_notes = params[:account].delete :enable_user_notes 493 allow_sis_import = params[:account].delete :allow_sis_import 494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou 495 unless @account.grants_right? @current_user, :manage_storage_quotas 496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb, 497 :default_user_storage_quota, :default_user_storage_quota_mb, 498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account] 499 end 500 if params[:account][:services] 501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a 502 @account.set_service_availability(key, value == '1') 503 end 504 params[:account].delete :services 505 end 506 if @account.grants_right?(@current_user, :manage_site_settings) 507 # If the setting is present (update is called from 2 different settings forms, one for notifi 508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op 509 # If set to default, remove the custom name so it doesn't get saved 510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting 511 end 512 513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain) 514 if @account.feature_enabled?(:google_docs_domain_restriction) && 515 @account.root_account? && 516 !@account.site_admin? 517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain : 518 end 519 520 @account.enable_user_notes = enable_user_notes if enable_user_notes 521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account? 522 if @account.site_admin? && params[:account][:settings] 523 # these shouldn't get set for the site admin account 524 params[:account][:settings].delete(:enable_alerts) 525 params[:account][:settings].delete(:enable_eportfolios) 526 end 527 else 528 # must have :manage_site_settings to update these 529 [ :admins_can_change_passwords, 530 :admins_can_view_notifications, 531 :enable_alerts, 532 :enable_eportfolios, 533 :enable_profiles, 534 :show_scheduler, 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538 params[:account][:settings].try(:delete, key)
  • 19. 475 def update 476 return update_api if api_request? 477 478 if authorized_action(@account, @current_user, :manage_account_settings) 479 respond_to do |format| 480 481 custom_help_links = params[:account].delete :custom_help_links 482 if custom_help_links 483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete 484 hash = index_with_hash[1] 485 hash.delete('state') 486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"] 487 hash 488 end 489 end 490 491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host]) 492 enable_user_notes = params[:account].delete :enable_user_notes 493 allow_sis_import = params[:account].delete :allow_sis_import 494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou 495 unless @account.grants_right? @current_user, :manage_storage_quotas 496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb, 497 :default_user_storage_quota, :default_user_storage_quota_mb, 498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account] 499 end 500 if params[:account][:services] 501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a 502 @account.set_service_availability(key, value == '1') 503 end 504 params[:account].delete :services 505 end 506 if @account.grants_right?(@current_user, :manage_site_settings) 507 # If the setting is present (update is called from 2 different settings forms, one for notifi 508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op 509 # If set to default, remove the custom name so it doesn't get saved 510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting 511 end 512 513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain) 514 if @account.feature_enabled?(:google_docs_domain_restriction) && 515 @account.root_account? && 516 !@account.site_admin? 517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain : 518 end 519 520 @account.enable_user_notes = enable_user_notes if enable_user_notes 521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account? 522 if @account.site_admin? && params[:account][:settings] 523 # these shouldn't get set for the site admin account 524 params[:account][:settings].delete(:enable_alerts) 525 params[:account][:settings].delete(:enable_eportfolios) 526 end 527 else 528 # must have :manage_site_settings to update these 529 [ :admins_can_change_passwords, 530 :admins_can_view_notifications, 531 :enable_alerts, 532 :enable_eportfolios, 533 :enable_profiles, 534 :show_scheduler, 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538 params[:account][:settings].try(:delete, key) Infrastructure as Code
  • 20. 475 def update 476 return update_api if api_request? 477 478 if authorized_action(@account, @current_user, :manage_account_settings) 479 respond_to do |format| 480 481 custom_help_links = params[:account].delete :custom_help_links 482 if custom_help_links 483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete 484 hash = index_with_hash[1] 485 hash.delete('state') 486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"] 487 hash 488 end 489 end 490 491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host]) 492 enable_user_notes = params[:account].delete :enable_user_notes 493 allow_sis_import = params[:account].delete :allow_sis_import 494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou 495 unless @account.grants_right? @current_user, :manage_storage_quotas 496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb, 497 :default_user_storage_quota, :default_user_storage_quota_mb, 498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account] 499 end 500 if params[:account][:services] 501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a 502 @account.set_service_availability(key, value == '1') 503 end 504 params[:account].delete :services 505 end 506 if @account.grants_right?(@current_user, :manage_site_settings) 507 # If the setting is present (update is called from 2 different settings forms, one for notifi 508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op 509 # If set to default, remove the custom name so it doesn't get saved 510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting 511 end 512 513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain) 514 if @account.feature_enabled?(:google_docs_domain_restriction) && 515 @account.root_account? && 516 !@account.site_admin? 517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain : 518 end 519 520 @account.enable_user_notes = enable_user_notes if enable_user_notes 521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account? 522 if @account.site_admin? && params[:account][:settings] 523 # these shouldn't get set for the site admin account 524 params[:account][:settings].delete(:enable_alerts) 525 params[:account][:settings].delete(:enable_eportfolios) 526 end 527 else 528 # must have :manage_site_settings to update these 529 [ :admins_can_change_passwords, 530 :admins_can_view_notifications, 531 :enable_alerts, 532 :enable_eportfolios, 533 :enable_profiles, 534 :show_scheduler, 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538 params[:account][:settings].try(:delete, key)
  • 21. Infrastructure as Code Source of knowledge Supports versioning, collaboration Executable
  • 22. 475 def update 476 return update_api if api_request? 477 478 if authorized_action(@account, @current_user, :manage_account_settings) 479 respond_to do |format| 480 481 custom_help_links = params[:account].delete :custom_help_links 482 if custom_help_links 483 @account.settings[:custom_help_links] = custom_help_links.select{|k, h| h['state'] != 'delete 484 hash = index_with_hash[1] 485 hash.delete('state') 486 hash.assert_valid_keys ["text", "subtext", "url", "available_to"] 487 hash 488 end 489 end 490 491 params[:account][:turnitin_host] = validated_turnitin_host(params[:account][:turnitin_host]) 492 enable_user_notes = params[:account].delete :enable_user_notes 493 allow_sis_import = params[:account].delete :allow_sis_import 494 params[:account].delete :default_user_storage_quota_mb unless @account.root_account? && !@accou 495 unless @account.grants_right? @current_user, :manage_storage_quotas 496 [:storage_quota, :default_storage_quota, :default_storage_quota_mb, 497 :default_user_storage_quota, :default_user_storage_quota_mb, 498 :default_group_storage_quota, :default_group_storage_quota_mb].each { |key| params[:account] 499 end 500 if params[:account][:services] 501 params[:account][:services].slice(*Account.services_exposed_to_ui_hash(nil, @current_user, @a 502 @account.set_service_availability(key, value == '1') 503 end 504 params[:account].delete :services 505 end 506 if @account.grants_right?(@current_user, :manage_site_settings) 507 # If the setting is present (update is called from 2 different settings forms, one for notifi 508 if params[:account][:settings] && params[:account][:settings][:outgoing_email_default_name_op 509 # If set to default, remove the custom name so it doesn't get saved 510 params[:account][:settings][:outgoing_email_default_name] = '' if params[:account][:setting 511 end 512 513 google_docs_domain = params[:account][:settings].try(:delete, :google_docs_domain) 514 if @account.feature_enabled?(:google_docs_domain_restriction) && 515 @account.root_account? && 516 !@account.site_admin? 517 @account.settings[:google_docs_domain] = google_docs_domain.present? ? google_docs_domain : 518 end 519 520 @account.enable_user_notes = enable_user_notes if enable_user_notes 521 @account.allow_sis_import = allow_sis_import if allow_sis_import && @account.root_account? 522 if @account.site_admin? && params[:account][:settings] 523 # these shouldn't get set for the site admin account 524 params[:account][:settings].delete(:enable_alerts) 525 params[:account][:settings].delete(:enable_eportfolios) 526 end 527 else 528 # must have :manage_site_settings to update these 529 [ :admins_can_change_passwords, 530 :admins_can_view_notifications, 531 :enable_alerts, 532 :enable_eportfolios, 533 :enable_profiles, 534 :show_scheduler, 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538 params[:account][:settings].try(:delete, key)
  • 23. Copyright © 2018 HashiCorp HashiCorp Infrastructure as Code With Terraform
  • 24. Terraform Tool to manage anything with an API as code Open source (> 12,000 stars, > 1,000 contributors) Support for over 100 providers, including all major clouds: AWS, Azure, GCP, and more.
  • 25. Goals Unify the view of resources using infra as code Expose a way for individuals and teams to safely and predictably change infrastructure Manage anything with an API
  • 26. resource "aws_instance" "web" { ami = "ami-b123125" } resource "dnsimple_record" "hello" { domain = "example.com" name = "test" value = "${aws_instance.web.public_ip}" type = "A" } C O D E E D I T O R
  • 27. resource "aws_instance" "web" { ami = "ami-b123125" } resource "dnsimple_record" "hello" { domain = "example.com" name = "test" value = "${aws_instance.web.public_ip}" type = "A" } C O D E E D I T O R
  • 28. resource "aws_instance" "web" { ami = "ami-b123125" } resource "dnsimple_record" "hello" { domain = "example.com" name = "test" value = "${aws_instance.web.public_ip}" type = "A" } C O D E E D I T O R
  • 29. resource "aws_instance" "web" { ami = "ami-b123125" } resource "dnsimple_record" "hello" { domain = "example.com" name = "test" value = "${aws_instance.web.public_ip}" type = "A" } C O D E E D I T O R
  • 30. Configuration Declarative: what you want, vs how to do it Human-friendly, JSON compatible Versionable, VCS-friendly
  • 31. resource "aws_instance" "web" { - ami = "ami-b123125" + ami = "ami-c345123" } resource "dnsimple_record" "hello" { domain = "example.com" name = "test" value = "${aws_instance.web.public_ip}" type = "A" } C O D E E D I T O R
  • 32. Command: terraform plan The plan shows you what will happen You can save plans to guarantee what will happen Plans show reasons for certain actions (such as re- create) Prior to Terraform, users had to guess change ordering, parallelization, and rollout effect
  • 33. Command: terraform plan + resource will be created - resource will be destroyed ~ resource will be updated in-place -/+ resources will be destroyed and re-created
  • 34. T E R M I N A L $ terraform plan + aws_instance.web ami: "ami-db24d8b6" availability_zone: "<computed>" ebs_block_device.#: "<computed>" ephemeral_block_device.#: "<computed>" instance_state: "<computed>" instance_type: "t2.micro" key_name: "<computed>" network_interface_id: "<computed>" placement_group: "<computed>" private_dns: "<computed>" private_ip: "<computed>" public_dns: "<computed>" public_ip: "<computed>" # ...
  • 35. Command: terraform apply Executes changes in order based on the resource graph Parallelizes changes when possible Handles and recovers transient errors Runs plan first unless given a serialized plan file
  • 36. T E R M I N A L $ terraform apply aws_instance.web: Creating... ami: "" => "ami-db24d8b6" # ... source_dest_check: "" => "true" subnet_id: "" => "subnet-f6e6a5dc" aws_instance.web: Still creating... (10s elapsed) aws_instance.web: Still creating... (20s elapsed) aws_instance.web: Creation complete Apply complete! Resources: 1 added, 0 changed, 0 destroyed.
  • 37. A Workflow for Safe Infrastructure "terraform apply" The make things happen command (after confirm) Tell Terraform what you want, sit back and let Terraform make it a reality.
  • 38. Modules Reusable packages of Terraform configuration Enable broader usage of Terraform Share and discover: https://registry.terraform.io/
  • 39. module "consul" { source = "hashicorp/consul/aws" version = "~> 0.3.0" } output "servers" { value = "${module.consul.asg_name_servers} } C O D E E D I T O R
  • 40. Copyright © 2018 HashiCorp HashiCorp Everything as Code With Terraform
  • 41.
  • 42.
  • 43. Providers Integration point Expose resources, such as "aws_instance" Can be created for anything with an API Easy to write, great beginner Go project
  • 44. resource "TYPE" "NAME" { CONFIG } C O D E E D I T O R
  • 45. resource "TYPE" "NAME" { CONFIG } C O D E E D I T O R
  • 49. Terraform's Internals Config: Target Reality State: Current Reality Diff: {Config - State} Plan: Presents Diff Apply: Resolves Diff
  • 50. FOR
 EVERY THING Example: PagerDuty On-call schedules as code Notifications as code Manage PagerDuty schedules, teams, and users
 as code!
  • 51. resource "pagerduty_team" "engineering" { name = "Engineering" description = "All engineering" } resource "pagerduty_user" "earline" { name = "Earline Greenholt" email = "125.greenholt.earline@graham.name" teams = ["${pagerduty_team.engineering.id}"] } C O D E E D I T O R
  • 52. resource "pagerduty_schedule" "foo" { name = "Daily Engineering Rotation" time_zone = "America/New_York" layer { name = "Night Shift" ... users = ["${pagerduty_user.earline.id}"] restriction { type = "daily_restriction" start_time_of_day = "08:00:00" duration_seconds = 32400 } } } C O D E E D I T O R
  • 53. FOR
 EVERY THING Example: DataDog Metrics as code Notifications as code Manage DataDog users, monitors, and timeboards
 as code.
  • 54. resource "datadog_timeboard" "redis" { title = "Redis Timeboard (created via Terraform)" read_only = true graph { title = "Redis latency (ms)" viz = "timeseries" request { q = "avg:redis.info.latency_ms{$host}" type = "bars" } } } C O D E E D I T O R
  • 55. resource "datadog_monitor" "foo" { name = "Name for monitor foo" type = "metric alert" message = "Monitor triggered. Notify: @hipchat-channel" escalation_message = "Escalation message @pagerduty" query = "avg(last_1h):avg:cpu{host:foo} by {host} > 4" thresholds { ok = 0 warning = 2 warning_recovery = 1 critical = 4 critical_recovery = 3 } C O D E E D I T O R
  • 56. FOR
 EVERY THING Example: GitHub Organization and teams as code Issue labels as code Etc. HashiCorp uses this to manage provider repositories!
  • 57. variable "issue_labels" { default = { "custom-label" = "533D99" "documentation" = "FFB340" "waiting-reply" = "CC6A14" } } resource "github_issue_label" "test_repo" { repository = "${github_repository.example-repo.id}" count = "${length(var.issue_labels)}" name = "${element(keys(var.issue_labels), count.index)}" color = "${element(values(var.issue_labels), count.index)}" } C O D E E D I T O R
  • 58. Learn More All Providers
 terraform.io/docs/providers Extending Terraform
 terraform.io/docs/extend Provider Development Program
 terraform.io/guides/
 terraform-provider-development-program.html