Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Infrastructure as Code with Terraform and Friends

Paul Hinze
January 12, 2016

Infrastructure as Code with Terraform and Friends

Chicago DevOps Meetup

Infrastructure as Code with Terraform and Friends

We have long since passed the time when it was feasible for human beings to manually provision, configure, and manage infrastructure. Automation is clearly the way forward, as we have known for years. However, it is difficult to determine how to effectively utilize automation in a way that reduces complexity rather than contributes to it. An automated mess is only marginally better than a manual mess.

Infrastructure as Code is a holistic approach to automation that seeks to reign in the ever-increasing complexity of modern infrastructure by borrowing practices from the software development community.

In this talk, we'll start with a discussion of the concepts central to Infrastructure as Code. Then we'll take a tour of the various tools, technologies, and practices that help us interact with infrastructure as code. Finally, we'll take a deeper dive to look at concrete examples from Terraform, the project I work on full time.

Paul Hinze

January 12, 2016
Tweet

More Decks by Paul Hinze

Other Decks in Technology

Transcript

  1. HASHICORP 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538

    params[:account][:settings].try(:delete, key) 539 end 540 end 541 542 if params[:account][:settings] && params[:account][:settings].has_key?(:trusted_referers) 543 if trusted_referers = params[:account][:settings].delete(:trusted_referers) 544 @account.trusted_referers = trusted_referers if @account.root_account? 545 end 546 end 547 548 if sis_id = params[:account].delete(:sis_source_id) 549 if [email protected]_account? && sis_id != @account.sis_source_id && @account.root_account.grant 550 if sis_id == '' 551 @account.sis_source_id = nil 552 else 553 @account.sis_source_id = sis_id 554 end 555 end 556 end 557 558 process_external_integration_keys 559 560 can_edit_email = params[:account][:settings].try(:delete, :edit_institution_email) 561 if @account.root_account? && !can_edit_email.nil? 562 @account[:settings][:edit_institution_email] = value_to_boolean(can_edit_email) 563 end 564 565 if @account.update_attributes(params[:account]) 566 format.html { redirect_to account_settings_url(@account) } 567 format.json { render :json => @account } 568 else 569 flash[:error] = t(:update_failed_notice, "Account settings update failed") 570 format.html { redirect_to account_settings_url(@account) } 571 format.json { render :json => @account.errors, :status => :bad_request } 572 end 573 end 574 end 575 end 576 577 def settings 578 if authorized_action(@account, @current_user, :read) 579 @available_reports = AccountReport.available_reports if @account.grants_right?(@current_user, @se 580 if @available_reports 581 @last_complete_reports = {} 582 @last_reports = {} 583 if AccountReport.connection.adapter_name == 'PostgreSQL' 584 scope = @account.account_reports.select("DISTINCT ON (report_type) account_reports.*").order( 585 @last_complete_reports = scope.last_complete_of_type(@available_reports.keys, nil).preload(:a 586 @last_reports = scope.last_of_type(@available_reports.keys, nil).index_by(&:report_type) 587 else 588 @available_reports.keys.each do |report| 589 @last_complete_reports[report] = @account.account_reports.last_complete_of_type(report).fir 590 @last_reports[report] = @account.account_reports.last_of_type(report).first 591 end 592 end 593 end 594 load_course_right_side 595 @account_users = @account.account_users 596 ActiveRecord::Associations::Preloader.new(@account_users, user: :communication_channels).run 597 order_hash = {} 598 @account.available_account_roles.each_with_index do |role, idx| 599 order_hash[role.id] = idx 600 end 601 @account_users = @account_users.select(&:user).sort_by{|au| [order_hash[au.role_id] || CanvasSort 602 @alerts = @account.alerts HASHICORP
  2. HASHICORP 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538

    params[:account][:settings].try(:delete, key) 539 end 540 end 541 542 if params[:account][:settings] && params[:account][:settings].has_key?(:trusted_referers) 543 if trusted_referers = params[:account][:settings].delete(:trusted_referers) 544 @account.trusted_referers = trusted_referers if @account.root_account? 545 end 546 end 547 548 if sis_id = params[:account].delete(:sis_source_id) 549 if [email protected]_account? && sis_id != @account.sis_source_id && @account.root_account.grant 550 if sis_id == '' 551 @account.sis_source_id = nil 552 else 553 @account.sis_source_id = sis_id 554 end 555 end 556 end 557 558 process_external_integration_keys 559 560 can_edit_email = params[:account][:settings].try(:delete, :edit_institution_email) 561 if @account.root_account? && !can_edit_email.nil? 562 @account[:settings][:edit_institution_email] = value_to_boolean(can_edit_email) 563 end 564 565 if @account.update_attributes(params[:account]) 566 format.html { redirect_to account_settings_url(@account) } 567 format.json { render :json => @account } 568 else 569 flash[:error] = t(:update_failed_notice, "Account settings update failed") 570 format.html { redirect_to account_settings_url(@account) } 571 format.json { render :json => @account.errors, :status => :bad_request } 572 end 573 end 574 end 575 end 576 577 def settings 578 if authorized_action(@account, @current_user, :read) 579 @available_reports = AccountReport.available_reports if @account.grants_right?(@current_user, @se 580 if @available_reports 581 @last_complete_reports = {} 582 @last_reports = {} 583 if AccountReport.connection.adapter_name == 'PostgreSQL' 584 scope = @account.account_reports.select("DISTINCT ON (report_type) account_reports.*").order( 585 @last_complete_reports = scope.last_complete_of_type(@available_reports.keys, nil).preload(:a 586 @last_reports = scope.last_of_type(@available_reports.keys, nil).index_by(&:report_type) 587 else 588 @available_reports.keys.each do |report| 589 @last_complete_reports[report] = @account.account_reports.last_complete_of_type(report).fir 590 @last_reports[report] = @account.account_reports.last_of_type(report).first 591 end 592 end 593 end 594 load_course_right_side 595 @account_users = @account.account_users 596 ActiveRecord::Associations::Preloader.new(@account_users, user: :communication_channels).run 597 order_hash = {} 598 @account.available_account_roles.each_with_index do |role, idx| 599 order_hash[role.id] = idx 600 end 601 @account_users = @account_users.select(&:user).sort_by{|au| [order_hash[au.role_id] || CanvasSort 602 @alerts = @account.alerts HASHICORP Infrastructure as Code
  3. HASHICORP 535 :global_includes, 536 :gmail_domain 537 ].each do |key| 538

    params[:account][:settings].try(:delete, key) 539 end 540 end 541 542 if params[:account][:settings] && params[:account][:settings].has_key?(:trusted_referers) 543 if trusted_referers = params[:account][:settings].delete(:trusted_referers) 544 @account.trusted_referers = trusted_referers if @account.root_account? 545 end 546 end 547 548 if sis_id = params[:account].delete(:sis_source_id) 549 if [email protected]_account? && sis_id != @account.sis_source_id && @account.root_account.grant 550 if sis_id == '' 551 @account.sis_source_id = nil 552 else 553 @account.sis_source_id = sis_id 554 end 555 end 556 end 557 558 process_external_integration_keys 559 560 can_edit_email = params[:account][:settings].try(:delete, :edit_institution_email) 561 if @account.root_account? && !can_edit_email.nil? 562 @account[:settings][:edit_institution_email] = value_to_boolean(can_edit_email) 563 end 564 565 if @account.update_attributes(params[:account]) 566 format.html { redirect_to account_settings_url(@account) } 567 format.json { render :json => @account } 568 else 569 flash[:error] = t(:update_failed_notice, "Account settings update failed") 570 format.html { redirect_to account_settings_url(@account) } 571 format.json { render :json => @account.errors, :status => :bad_request } 572 end 573 end 574 end 575 end 576 577 def settings 578 if authorized_action(@account, @current_user, :read) 579 @available_reports = AccountReport.available_reports if @account.grants_right?(@current_user, @se 580 if @available_reports 581 @last_complete_reports = {} 582 @last_reports = {} 583 if AccountReport.connection.adapter_name == 'PostgreSQL' 584 scope = @account.account_reports.select("DISTINCT ON (report_type) account_reports.*").order( 585 @last_complete_reports = scope.last_complete_of_type(@available_reports.keys, nil).preload(:a 586 @last_reports = scope.last_of_type(@available_reports.keys, nil).index_by(&:report_type) 587 else 588 @available_reports.keys.each do |report| 589 @last_complete_reports[report] = @account.account_reports.last_complete_of_type(report).fir 590 @last_reports[report] = @account.account_reports.last_of_type(report).first 591 end 592 end 593 end 594 load_course_right_side 595 @account_users = @account.account_users 596 ActiveRecord::Associations::Preloader.new(@account_users, user: :communication_channels).run 597 order_hash = {} 598 @account.available_account_roles.each_with_index do |role, idx| 599 order_hash[role.id] = idx 600 end 601 @account_users = @account_users.select(&:user).sort_by{|au| [order_hash[au.role_id] || CanvasSort 602 @alerts = @account.alerts HASHICORP
  4. HASHICORP Ansible, Chef, Puppet, ... Server ConfiguraDon ArDfact ProducDon Aminator,

    Packer, Docker Build, ... Infrastructure OrchestraDon CloudFormaDon, Terraform, ... Automated VerificaDon ServerSpec, Test Kitchen, ...
  5. HASHICORP main.tf provider "aws" { region = "us-east-1" } resource

    "aws_instance" "web" { ami = "ami-b82176d2" instance_type = "t1.micro" tags { Name = "hello-terraform" } }
  6. HASHICORP Config: User-Provided State: View of Reality Diff: {State -

    Config} Plan: Presents Diff Apply: Resolves Diff Concepts