SlideShare ist ein Scribd-Unternehmen logo
1 von 59
Downloaden Sie, um offline zu lesen
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.

Weitere ähnliche Inhalte

Mehr von 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
 

Mehr von 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!
 

Kürzlich hochgeladen

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfIngrid Airi González
 
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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersNicole Novielli
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Farhan Tariq
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality AssuranceInflectra
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .Alan Dix
 
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
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsRavi Sanghani
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsPixlogix Infotech
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Strongerpanagenda
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxLoriGlavin3
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfpanagenda
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demoHarshalMandlekar2
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesThousandEyes
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024BookNet Canada
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxLoriGlavin3
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxLoriGlavin3
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rick Flair
 
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
 

Kürzlich hochgeladen (20)

Generative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdfGenerative Artificial Intelligence: How generative AI works.pdf
Generative Artificial Intelligence: How generative AI works.pdf
 
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
 
A Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software DevelopersA Journey Into the Emotions of Software Developers
A Journey Into the Emotions of Software Developers
 
Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...Genislab builds better products and faster go-to-market with Lean project man...
Genislab builds better products and faster go-to-market with Lean project man...
 
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance[Webinar] SpiraTest - Setting New Standards in Quality Assurance
[Webinar] SpiraTest - Setting New Standards in Quality Assurance
 
From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .From Family Reminiscence to Scholarly Archive .
From Family Reminiscence to Scholarly Archive .
 
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
 
Potential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and InsightsPotential of AI (Generative AI) in Business: Learnings and Insights
Potential of AI (Generative AI) in Business: Learnings and Insights
 
The Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and ConsThe Ultimate Guide to Choosing WordPress Pros and Cons
The Ultimate Guide to Choosing WordPress Pros and Cons
 
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better StrongerModern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
Modern Roaming for Notes and Nomad – Cheaper Faster Better Stronger
 
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptxPasskey Providers and Enabling Portability: FIDO Paris Seminar.pptx
Passkey Providers and Enabling Portability: FIDO Paris Seminar.pptx
 
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdfSo einfach geht modernes Roaming fuer Notes und Nomad.pdf
So einfach geht modernes Roaming fuer Notes und Nomad.pdf
 
Sample pptx for embedding into website for demo
Sample pptx for embedding into website for demoSample pptx for embedding into website for demo
Sample pptx for embedding into website for demo
 
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyesHow to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
How to Effectively Monitor SD-WAN and SASE Environments with ThousandEyes
 
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
New from BookNet Canada for 2024: Loan Stars - Tech Forum 2024
 
The State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptxThe State of Passkeys with FIDO Alliance.pptx
The State of Passkeys with FIDO Alliance.pptx
 
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptxThe Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
The Role of FIDO in a Cyber Secure Netherlands: FIDO Paris Seminar.pptx
 
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
 
Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...Rise of the Machines: Known As Drones...
Rise of the Machines: Known As Drones...
 
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
 

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