Slide 1

Slide 1 text

Graph Theory to Applying Infrastructure as Code HashiConf EU 2016

Slide 2

Slide 2 text

Infrastructure as Code Graph Theory to Applying

Slide 3

Slide 3 text

Maturity

Slide 4

Slide 4 text

Manual Everything

Slide 5

Slide 5 text

Basic Automa>on #!/bin/bash

Slide 6

Slide 6 text

Machine Virtualiza>on

Slide 7

Slide 7 text

Commodi>za>on of Infrastructure

Slide 8

Slide 8 text

Datacenter-as-Computer

Slide 9

Slide 9 text

No content

Slide 10

Slide 10 text

No content

Slide 11

Slide 11 text

No content

Slide 12

Slide 12 text

Capability Complexity

Slide 13

Slide 13 text

No content

Slide 14

Slide 14 text

Managing Complexity A strategy for

Slide 15

Slide 15 text

No content

Slide 16

Slide 16 text

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

Slide 17

Slide 17 text

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 HASHICORP

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

Graph Theory to Applying Infrastructure as Code

Slide 20

Slide 20 text

Discrete Mathema>cs Combinatorics Graph Theory

Slide 21

Slide 21 text

Vertex / Node

Slide 22

Slide 22 text

Edge

Slide 23

Slide 23 text

Directed Edge

Slide 24

Slide 24 text

Directed Graph

Slide 25

Slide 25 text

Cycle

Slide 26

Slide 26 text

Directed Acyclic Graph (DAG)

Slide 27

Slide 27 text

Walk 1 2 3 4 5

Slide 28

Slide 28 text

Parallel Walk 1 3 2 2 3

Slide 29

Slide 29 text

Graph Transform T G G'

Slide 30

Slide 30 text

No content

Slide 31

Slide 31 text

Graph Theory to Applying Infrastructure as Code HashiConf EU 2016

Slide 32

Slide 32 text

Terraform's Internals: Structure Core Providers Providers Providers Upstream APIs Plugins

Slide 33

Slide 33 text

Terraform's Internals: Provider API Separa>on Core Providers Providers Providers Upstream APIs Plugins Diff() Apply() Refresh() Create() Read() Update() Delete()

Slide 34

Slide 34 text

Terraform's Internals: Core Concepts Config: Target Reality State: Current Reality Diff: {Config - State} Plan: Presents Diff Apply: Resolves Diff

Slide 35

Slide 35 text

Terraform's Internals: Core Packages Core dag config terraform reads makes

Slide 36

Slide 36 text

Terraform's Internals: Core Packages Core dag config terraform reads makes

Slide 37

Slide 37 text

Building the Graph T T T

Slide 38

Slide 38 text

Building the Graph Config ConfigTransformer T

Slide 39

Slide 39 text

Building the Graph aws_instance aws_elb dnsimple_record aws dnsimple

Slide 40

Slide 40 text

Building the Graph ProviderTransformer T

Slide 41

Slide 41 text

Building the Graph aws_instance aws_elb dnsimple_record aws dnsimple

Slide 42

Slide 42 text

Building the Graph T T T

Slide 43

Slide 43 text

Building the Graph T T RootTransformer R

Slide 44

Slide 44 text

Building the Graph aws_instance aws_elb dnsimple_record aws dnsimple root

Slide 45

Slide 45 text

Walking The Graph aws_instance aws_elb dnsimple_record aws dnsimple root 1 2 2 3 3 4

Slide 46

Slide 46 text

What do we get from the graph?

Slide 47

Slide 47 text

Separa>on of Concerns Core dag terraform

Slide 48

Slide 48 text

Parallel Walk

Slide 49

Slide 49 text

Solu>ons to Borrow Transitive Reduction

Slide 50

Slide 50 text

Solid Theore>cal Grounding + Room to Mature & Explore

Slide 51

Slide 51 text

Graph Theory to Applying Infrastructure as Code HashiConf EU 2016

Slide 52

Slide 52 text

by Jason Santos via CloudcraZ A[ribu>ons