summaryrefslogtreecommitdiff
path: root/src/talks/ansible-cloud/index.html
diff options
context:
space:
mode:
Diffstat (limited to 'src/talks/ansible-cloud/index.html')
-rw-r--r--src/talks/ansible-cloud/index.html792
1 files changed, 792 insertions, 0 deletions
diff --git a/src/talks/ansible-cloud/index.html b/src/talks/ansible-cloud/index.html
new file mode 100644
index 0000000..37e66c6
--- /dev/null
+++ b/src/talks/ansible-cloud/index.html
@@ -0,0 +1,792 @@
1<!doctype html>
2<html lang="en">
3
4 <head>
5 <meta charset="utf-8">
6
7 <title>NoOps with Ansible and Puppet</title>
8
9 <meta name="author" content="Monty Taylor" />
10
11 <meta name="apple-mobile-web-app-capable" content="yes" />
12 <meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
13
14 <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
15
16 <link rel="stylesheet" href="/css/reveal.css">
17 <link rel="stylesheet" href="/css/theme/openstack.css" id="theme">
18
19 <!-- For syntax highlighting -->
20 <link rel="stylesheet" href="/lib/css/zenburn.css">
21
22 <!-- If the query includes 'print-pdf', include the PDF print sheet -->
23 <script>
24 var link = document.createElement('link');
25 link.rel = 'stylesheet';
26 link.type = 'text/css';
27 link.href =
28 window.location.search.match(/print-pdf/gi) ? '/css/print/pdf.css' :
29 '/css/print/paper.css';
30 document.getElementsByTagName('head')[0].appendChild(link);
31 </script>
32 </head>
33 <body>
34 <body>
35
36 <div class="background">
37 <img alt="" id="head-icon" width="218" height="67"
38 src="/images/openstack-cloud-software-horizontal-small.png" /></div>
39
40
41 <div class="reveal">
42 <div class="slides">
43
44 <section data-state="cover">
45 <img src="/images/openstack-cloud-software-vertical-large.png"
46 alt="OpenStack" id="cover"/>
47
48 <h1><span xmlns:dct="http://purl.org/dc/terms/"
49 href="http://purl.org/dc/dcmitype/InteractiveResource"
50 property="dct:title"
51 rel="dct:type">
52 NoOps with Ansible and Puppet
53 </span></h1>
54 <h3 xmlns:cc="http://creativecommons.org/ns#"
55 property="cc:attributionName">Monty Taylor</h3>
56 <h4><a xmlns:cc="http://creativecommons.org/ns#"
57 rel="cc:attributionURL"
58 href='http://inaugust.com/talks/ansible-cloud.html'>http://inaugust.com/talks/ansible-cloud.html</a> </h4>
59 <h3> twitter: @e_monty </h3>
60 </section>
61
62 <section id="who-am-i" class="slide level2">
63 <h1>Who am I?</h1>
64 <ul>
65 <li>Distinguished Technologist at HP</li>
66 <li>OpenStack Technical Committee</li>
67 <li>OpenStack Foundation Board of Directors</li>
68 <li>OpenStack Developer Infrastructure Core Team</li>
69 <li>Former Consultant for MySQL, Inc</li>
70 <li>Former Drizzle Core Developer</li>
71 </ul>
72 </section>
73
74 <section id="what-are-we-going-to-talk-about" class="slide level2">
75 <h1>What are we going to talk about?</h1>
76 <ul>
77 <li>NoOps</li>
78 <li>Cloud Applications</li>
79 <li>Puppet</li>
80 <li>Ansible</li>
81 </ul>
82 </section>
83
84 <section id="no-ops" class="slide level2">
85 <h1>NoOps</h1>
86 <p class="fragment">NoOps means developers can code and let a service deploy, manage and scale their code</p>
87 <p class="fragment">I don't want to "do ops"</p>
88 <p class="fragment">I want to change the system by landing commits</p>
89 <p class="fragment">If I have to use my root access, it's a bug</p>
90 </section>
91
92 <section id="cloud-native" class="slide level2">
93 <h1>Cloud Native</h1>
94 <ul>
95 <li>Ephemeral Compute</li>
96 <li>Data services</li>
97 <li>Design your applications to be resilient via scale out</li>
98 </ul>
99 </section>
100
101 <section id="cloud-scale-out" class="slide level2">
102 <h1>Cloud Scale Out</h1>
103 <ul>
104 <li>Forget HA of one system</li>
105 <li>Forget long-lived systems</li>
106 <li>Shared-nothing for EVERYTHING</li>
107 </ul>
108 </section>
109
110 <section id="cloud-scale-out-is-great-for-new-applications" class="slide level2">
111 <h1>Cloud Scale Out is great for new applications</h1>
112 </section>
113
114 <section id="what-about-existing-applications" class="slide level2">
115 <h1>What about existing applications?</h1>
116 </section>
117
118 <section>
119 <section id="openstack-infra" data-transition='zoom'>
120 <h1>OpenStack Infra</h1>
121 </section>
122
123 <section id="tooling-automation-and-ci-for-openstack-project" class="slide level2" data-transition='zoom'>
124 <h1>Tooling, Automation and CI for OpenStack Project</h1>
125 </section>
126
127 <section id="developers" class="slide level2" data-transition='zoom'>
128 <h1>2000 Developers</h1>
129 </section>
130
131 <section id="gated-commits" class="slide level2" data-transition='zoom'>
132 <h1>Gated Commits</h1>
133 <p>Every commit is fully integration tested (twice) before landing</p>
134 </section>
135
136 <section id="each-test-runs-on-a-single-use-cloud-slave" class="slide level2" data-transition='zoom'>
137 <h1>Each Test Runs on a Single Use Cloud Slave</h1>
138 <p>This is that "cloud scale out" part</p>
139 </section>
140
141 <section id="million-test-jobs-in-the-last-6-months" class="slide level2" data-transition='zoom'>
142 <h1>1.7 Million Test Jobs in the last 6 Months</h1>
143 </section>
144
145 <section id="15-million-tests-in-december" class="slide level2" data-transition='zoom'>
146 <h1>15 Million Tests in December</h1>
147 </section>
148
149 <section id="terabytes-of-log-data-in-six-months" class="slide level2" data-transition='zoom'>
150 <h1>18 Terabytes of Log Data in six months</h1>
151 </section>
152
153 <section id="we-have-no-servers" class="slide level2" data-transition='zoom'>
154 <h1>We have no servers</h1>
155 <p>It all runs across HP and Rackspace Public Clouds.</p>
156 </section>
157
158 </section>
159
160 <section id="architecture" class="slide level2">
161 <h1>Architecture</h1>
162 <p><img src="/images/infra_architecture.jpg" alt="image" /></p>
163 </section>
164
165 <section id="it-didnt-start-this-way" class="slide level2">
166 <h1>It didn't start this way</h1>
167 <p><img src="/images/original.jpg" alt="image" /></p>
168 </section>
169
170 <section id="step-one-puppet" class="titleslide slide level1">
171 <h1>Step One: Puppet</h1>
172 </section>
173
174 <section id="overview" class="slide level2">
175 <h1>Overview</h1>
176 <ul>
177 <li>Open Source Config Management System</li>
178 <li>Written in Ruby</li>
179 <li>Models intended state</li>
180 <li>Wants to own entire system</li>
181 </ul>
182 </section>
183
184 <section id="config-management-is-great" class="slide level2">
185 <h1>Config Management is Great</h1>
186 <ul>
187 <li>Repeatable and consistent machines</li>
188 <li>Code Review</li>
189 <li>Collaboration from non-root users</li>
190 <li>Less repetition for me</li>
191 <li>Open Source Infrastructure</li>
192 <li><a href="http://git.openstack.org/cgit/openstack-infra/system-config/">http://git.openstack.org/cgit/openstack-infra/system-config/</a></li>
193 <li><a href="http://puppetdb.openstack.org/">http://puppetdb.openstack.org/</a></li>
194 </ul>
195 </section>
196
197 <section id="ruby-dsl" class="slide level2">
198 <h1>Ruby DSL</h1>
199 <pre><code>
200package { 'git':
201 ensure =&gt; 'present',
202}
203 </code></pre>
204 </section>
205
206 <section id="leaky-abstraction" class="slide level2">
207 <h1>Leaky Abstraction</h1>
208 <pre><code>
209if !defined(Package['git']) {
210 package { 'git':
211 ensure =&gt; 'present',
212 }
213}
214 </code></pre>
215 </section>
216
217 <section id="three-ways-to-run" class="slide level2">
218 <h1>Three ways to run</h1>
219 <ul>
220 <li>puppet apply</li>
221 <li>puppetmaster + puppet agent daemons</li>
222 <li>puppetmaster + puppet agent non-daemon</li>
223 </ul>
224 </section>
225
226 <section id="managing-users-and-ssh-keys" class="slide level2">
227 <h1>Managing users and ssh keys</h1>
228 <pre><code>
229define user::virtual::localuser(
230 $realname,
231 $groups = [ 'sudo', 'admin', ],
232 $sshkeys = '',
233 $key_id = '',
234 $old_keys = [],
235 $shell = '/bin/bash',
236 $home = "/home/${title}",
237 $managehome = true
238) {
239
240 group { $title:
241 ensure =&gt; present,
242 }
243 </code></pre>
244 </section>
245
246 <section id="managing-users-and-ssh-keys-2" class="slide level2">
247 <h1>Managing users and ssh keys (cont.)</h1>
248 <pre><code>
249 user { $title:
250 ensure =&gt; present,
251 comment =&gt; $realname,
252 gid =&gt; $title,
253 groups =&gt; $groups,
254 home =&gt; $home,
255 managehome =&gt; $managehome,
256 membership =&gt; 'minimum',
257 shell =&gt; $shell,
258 require =&gt; Group[$title],
259 }
260 </code></pre>
261 </section>
262
263 <section id="managing-users-and-ssh-keys-3" class="slide level2">
264 <h1>Managing users and ssh keys (cont.)</h1>
265 <pre><code>
266 ssh_authorized_key { $key_id:
267 ensure =&gt; present,
268 key =&gt; $sshkeys,
269 user =&gt; $title,
270 type =&gt; 'ssh-rsa',
271 }
272
273 if ( $old_keys != [] ) {
274 ssh_authorized_key { $old_keys:
275 ensure =&gt; absent,
276 user =&gt; $title,
277 }
278 }
279}
280 </code></pre>
281 </section>
282
283 <section id="our-code-is-open-source-right-what-about-passwords-and-keys-..." class="slide level2">
284 <h1>Our code is Open Source, right? What about passwords and keys ...</h1>
285 </section>
286
287 <section id="hiera" class="slide level2">
288 <h1>hiera</h1>
289 <ul>
290 <li>Simple YAML database, sits on puppetmaster</li>
291 <li>Use it for secret data</li>
292 <li>puppet code is still complete</li>
293 </ul>
294 <pre><code>
295node default {
296 class { 'openstack_project::server':
297 sysadmins =&gt; hiera('sysadmins', []),
298 }
299}
300 </code></pre>
301 <p>Breaks ability to use simple puppet apply</p>
302 </section>
303
304 <section id="step-two-ansible-for-orchestration" class="titleslide slide level1">
305 <h1>Step Two: Ansible for Orchestration</h1>
306 </section>
307
308 <section id="about-ansible" class="slide level2">
309 <h1>About Ansible</h1>
310 <ul>
311 <li>Open Source System Management tool</li>
312 <li>Written in Python</li>
313 <li>Sequence of steps to perform</li>
314 <li>Works over SSH</li>
315 <li>Incremental Adoption</li>
316 </ul>
317 </section>
318
319 <section>
320 <h1>ad-hoc operation</h1>
321 <pre>
322ansible '*' -m shell -p uptime
323 </pre>
324 </section>
325
326 <section id="yaml-syntax" class="slide level2">
327 <h1>YAML Syntax</h1>
328 <pre><code>
329- hosts: '*.slave.openstack.org'
330 tasks:
331 - shell: 'rm -rf ~jenkins/workspace/*{{ project }}*'
332 </code></pre>
333 <p>That's executed:</p>
334 <pre>
335ansible-playbook -f 10 /etc/ansible/clean_workspaces.yaml --extra-vars "project=$PROJECTNAME"
336 </pre>
337 </section>
338
339 <section id="ansible-organization" class="slide level2">
340 <h1>Ansible Organization</h1>
341 <ul>
342 <li>modules</li>
343 <li>plays</li>
344 <li>playbooks</li>
345 <li>roles</li>
346 </ul>
347 </section>
348
349 <section id="use-ansible-to-run-puppet" class="slide level2">
350 <h1>Use Ansible to Run Puppet!</h1>
351 </section>
352
353 <section id="puppet-module" class="slide level2">
354 <h1>puppet module</h1>
355 <pre><code>def main():
356 module = AnsibleModule(argument_spec=dict(
357 timeout=dict(default="30m"),
358 puppetmaster=dict(required=True),
359 show_diff=dict(default=False, aliases=['show-diff'], type='bool'),
360 ))
361 p = module.params
362
363 puppet_cmd = module.get_bin_path("puppet", False)
364 if not puppet_cmd:
365 module.fail_json(msg="Could not find puppet. Please ensure it is installed.")
366 </code></pre>
367 </section>
368
369 <section id="puppet-module-2" class="slide level2">
370 <h1>puppet module (cont)</h1>
371 <pre><code class="python">
372 cmd = ("timeout -s 9 %(timeout)s %(puppet_cmd)s agent --onetime"
373 " --server %(puppetmaster)s"
374 " --ignorecache --no-daemonize --no-usecacheonfailure --no-splay"
375 " --detailed-exitcodes --verbose") % dict(
376 timeout=pipes.quote(p['timeout']), puppet_cmd=PUPPET_CMD,
377 puppetmaster=pipes.quote(p['puppetmaster']))
378 if p['show_diff']:
379 cmd += " --show-diff"
380 rc, stdout, stderr = module.run_command(cmd)
381 </code></pre>
382 </section>
383
384 <section id="puppet-module-3" class="slide level2">
385 Please. Everyone. Marvel at the following logic
386 <pre><code>
387 if rc == 0: # success
388 module.exit_json(rc=rc, changed=False, stdout=stdout)
389 elif rc == 1:
390 # rc==1 could be because it's disabled OR there was a compilation failure
391 disabled = "administratively disabled" in stdout
392 if disabled:
393 msg = "puppet is disabled"
394 else:
395 msg = "puppet compilation failed"
396 module.fail_json(rc=rc, disabled=disabled, msg=msg, stdout=stdout, stderr=stderr)
397 elif rc == 2: # success with changes
398 module.exit_json(changed=True)
399 elif rc == 124: # timeout
400 module.exit_json(rc=rc, msg="%s timed out" % cmd, stdout=stdout, stderr=stderr)
401 else: # failure
402 module.fail_json(rc=rc, msg="%s failed" % (cmd), stdout=stdout, stderr=stderr)
403 </code></pre>
404 </section>
405
406 <section id="puppet-play" class="slide level2">
407 <h1>puppet play</h1>
408 <pre><code>
409- name: run puppet
410 puppet:
411 puppetmaster: "{{puppetmaster}}"
412 </code></pre>
413 </section>
414
415 <section id="puppet-role" class="slide level2">
416 <h1>puppet role</h1>
417 <p>roles/puppet/tasks/main.yml</p>
418 </section>
419
420 <section id="remote-puppet-playbook" class="slide level2">
421 <h1>remote puppet playbook</h1>
422 <pre><code>
423- hosts: git0*
424 gather_facts: false
425 max_fail_percentage: 1
426 roles:
427 - { role: puppet, puppetmaster: puppetmaster.openstack.org }
428- hosts: review.openstack.org
429 gather_facts: false
430 roles:
431 - { role: puppet, puppetmaster: puppetmaster.openstack.org }
432- hosts: "!review.openstack.org:!git0*:!afs*"
433 gather_facts: false
434 roles:
435 - { role: puppet, puppetmaster: puppetmaster.openstack.org }
436 </pre></code>
437 </section>
438
439 <section id="ansible-inventory" class="slide level2">
440 <h1>ansible inventory</h1>
441 <ul>
442 <li>List of servers to operate on</li>
443 <li>Optionally variables associated with each server</li>
444 <li>Optional groups of servers</li>
445 <li>Simple yaml file in /etc/ansible/hosts</li>
446 <li>Dynamic executable that returns JSON</li>
447 </ul>
448 </section>
449
450 <section id="ansible-inventory-from-file" class="slide level2">
451 <h1>Simple inventory</h1>
452 <pre>
453review.openstack.org
454git01.openstack.org
455git02.openstack.org
456pypi.dfw.openstack.org
457pypi.iad.openstack.org
458
459[pypi]
460pypi.dfw.openstack.org
461pypi.iad.openstack.org
462
463[git]
464git01.openstack.org
465git02.openstack.org
466 </pre>
467 </section>
468
469 <section id="ansible-inventory-from-puppet" class="slide level2">
470 <h1>ansible inventory from puppet certs</h1>
471 <pre><code>
472import json
473import subprocess
474
475output = [
476 x.split()[1][1:-1] for x in subprocess.check_output(
477 ["puppet","cert","list","-a"]).split('\n')
478 if x.startswith('+')
479]
480
481data = {
482 '_meta': {'hostvars': dict()},
483 'ungrouped': output,
484}
485print json.dumps(data, sort_keys=True, indent=2)
486 </code></pre>
487 </section>
488
489 <section>
490 <h1>Step Three: Ansible for Cloud Management</h1>
491 </section>
492
493 <section>
494 <h1>ansible and OpenStack</h1>
495 <ul>
496 <li>Ansible modules are just python</li>
497 <li>playbooks are lists of steps to take</li>
498 <li>Have plays/roles that provision servers</li>
499 <li>Infrastructure as code - for real!</li>
500 </ul>
501 </section>
502
503 <section>
504 <h1>Consider this data</h1>
505 <pre><code>
506pypi.dfw.openstack.org:
507 image_name: Ubuntu 12.04.4
508 flavor_ram: 2048
509 region: DFW
510 cloud: rackspace
511 volumes:
512 - size: 200
513 mount: /srv
514pypi.region-b.geo-1.openstack.org:
515 image_name: Ubuntu 12.04.4
516 flavor_ram: 2048
517 region: region-b.geo-1
518 cloud: hp
519 volumes:
520 - size: 200
521 mount: /srv
522 </code></pre>
523 </section>
524
525 <section>
526 <h1>Further consider this data</h1>
527 <pre><code>
528pypi:
529 image_name: Ubuntu 12.04.4
530 flavor_ram: 2048
531 volumes:
532 - size: 200
533 mount: /srv
534 hosts:
535 pypi.dfw:
536 region: DFW
537 pypi.iad:
538 region: IAD
539 pypi.ord:
540 region: ORD
541 pypi.region-b.geo-1:
542 cloud: hp
543 </code></pre>
544 </section>
545
546 <section>
547 <h1>Steps to launch a node</h1>
548 <ol>
549 <li>Create a compute instance</li>
550 <li>Wait for instance to exist</li>
551 <li>Create a floating IP</li>
552 <li>Attach floating IP to instance</li>
553 <li>Create one or more volumes</li>
554 <li>Attach volumes to instance</li>
555 <li>Wait for SSH to work</li>
556 <li>On host, format each volume</li>
557 <li>On host, mount each volume</li>
558 <li>On host, install config management software</li>
559 <li>On host, run config management software</li>
560 </ol>
561 </section>
562
563 <section>
564 <h1>Launch a node</h1>
565 <pre><code>
566---
567- name: Launch Node
568 os_compute:
569 cloud: "{{ cloud }}"
570 region_name: "{{ region_name }}"
571 name: "{{ name }}"
572 image_name: "{{ image_name }}"
573 flavor_ram: "{{ flavor_ram }}"
574 flavor_include: "{{ flavor_include }}"
575 meta:
576 group: "{{ group }}"
577 key_name: "{{ launch_keypair }}"
578 register: node
579- name: Create volumes
580 os_volume:
581 cloud: "{{ cloud }}"
582 size: "{{ item.size }}"
583 display_name: "{{ item.display_name }}"
584 with_items: volumes
585- name: Attach volumes
586 os_compute_volume:
587 cloud: "{{ cloud }}"
588 server_id: "{{ node.id }}"
589 volume_name: "{{ item.display_name }}"
590 with_items: volumes
591 register: attached_volumes
592- debug: var=attached_volumes
593- name: Re-request server to get up to date metadata after the volume loop
594 os_compute_facts:
595 cloud: "{{ cloud }}"
596 name: "{{ name }}"
597 when: attached_volumes.changed
598- name: Wait for SSH to work
599 wait_for: host={{ node.openstack.interface_ip }} port=22
600 when: node.changed == True
601- name: Add SSH host key to known hosts
602 shell: ssh-keyscan "{{ node.openstack.interface_ip|quote }}" &gt;&gt; ~/.ssh/known_hosts
603 when: node.changed == True
604- name: Add all instance public IPs to host group
605 add_host:
606 name: "{{ node.openstack.interface_ip }}"
607 groups: "{{ provision_group }}"
608 openstack: "{{ node.openstack }}"
609 when: attached_volumes|length == 0
610- name: Add all instance public IPs to host and volumes group
611 add_host:
612 name: "{{ node.openstack.interface_ip }}"
613 groups: "{{ provision_group }},hasvolumes"
614 openstack: "{{ node.openstack }}"
615 when: attached_volumes|length != 0
616 </code></pre>
617 </section>
618
619 <section>
620 <h1> Cloud based inventory </h1>
621 <ul>
622 <li> Just ask the cloud for the inventory </li>
623 <li> All of the meta-data the cloud knows is available </li>
624 <li> No need for puppetmaster now </li>
625 </ul>
626 </section>
627
628 <section>
629 <pre><code>
630 "pypi.dfw.openstack.org": {
631 "ansible_ssh_host": "23.253.237.8",
632 "openstack": {
633 "HUMAN_ID": true,
634 "NAME_ATTR": "name",
635 "OS-DCF:diskConfig": "MANUAL",
636 "OS-EXT-STS:power_state": 1,
637 "OS-EXT-STS:task_state": null,
638 "OS-EXT-STS:vm_state": "active",
639 "accessIPv4": "23.253.237.8",
640 "accessIPv6": "2001:4800:7817:104:d256:7a33:5187:7e1b",
641 "addresses": {
642 "private": [
643 {
644 "addr": "10.208.195.50",
645 "version": 4
646 }
647 ],
648 "public": [
649 {
650 "addr": "23.253.237.8",
651 "version": 4
652 },
653 {
654 "addr": "2001:4800:7817:104:d256:7a33:5187:7e1b",
655 "version": 6
656 }
657 ]
658 },
659 "cloud": "rax",
660 "config_drive": "",
661 "created": "2014-09-05T15:32:14Z",
662 "flavor": {
663 "id": "performance1-4",
664 "links": [
665 {
666 "href": "https://dfw.servers.api.rackspacecloud.com/610275/flavors/performance1-4",
667 "rel": "bookmark"
668 }
669 ],
670 "name": "4 GB Performance"
671 },
672 "hostId": "adb603d4566efe0392756c76dab38ffcba22099368837c7973321e77",
673 "human_id": "pypidfwopenstackorg",
674 "id": "de672205-9245-46b6-b3df-489ccf9e0c17",
675 "image": {
676 "id": "928e709d-35f0-47eb-b296-d18e1b0a76b7",
677 "links": [
678 {
679 "href": "https://dfw.servers.api.rackspacecloud.com/610275/images/928e709d-35f0-47eb-b296-d18e1b0a76b7",
680 "rel": "bookmark"
681 }
682 ]
683 },
684 "interface_ip": "23.253.237.8",
685 "key_name": "launch-node-root",
686 "links": [
687 {
688 "href": "https://dfw.servers.api.rackspacecloud.com/v2/610275/servers/de672205-9245-46b6-b3df-489ccf9e0c17",
689 "rel": "self"
690 },
691 {
692 "href": "https://dfw.servers.api.rackspacecloud.com/610275/servers/de672205-9245-46b6-b3df-489ccf9e0c17",
693 "rel": "bookmark"
694 }
695 ],
696 "metadata": {},
697 "name": "pypi.dfw.openstack.org",
698 "networks": {
699 "private": [
700 "10.208.195.50"
701 ],
702 "public": [
703 "23.253.237.8",
704 "2001:4800:7817:104:d256:7a33:5187:7e1b"
705 ]
706 },
707 "progress": 100,
708 "region": "DFW",
709 "status": "ACTIVE",
710 "tenant_id": "610275",
711 "updated": "2014-09-05T15:32:49Z",
712 "user_id": "156284",
713 "volumes": [
714 {
715 "HUMAN_ID": false,
716 "NAME_ATTR": "name",
717 "attachments": [
718 {
719 "device": "/dev/xvdb",
720 "host_name": null,
721 "id": "c6f5229c-1cc0-47c4-aab7-60db1f6cf8e8",
722 "server_id": "de672205-9245-46b6-b3df-489ccf9e0c17",
723 "volume_id": "c6f5229c-1cc0-47c4-aab7-60db1f6cf8e8"
724 }
725 ],
726 "availability_zone": "nova",
727 "bootable": "false",
728 "created_at": "2014-09-05T14:37:42.000000",
729 "device": "/dev/xvdb",
730 "display_description": null,
731 "display_name": "pypi.dfw.openstack.org/main01",
732 "human_id": null,
733 "id": "c6f5229c-1cc0-47c4-aab7-60db1f6cf8e8",
734 "metadata": {
735 "readonly": "False",
736 "storage-node": "1845027a-5e07-47a1-9572-3eea4716f726"
737 },
738 "os-vol-tenant-attr:tenant_id": "610275",
739 "size": 200,
740 "snapshot_id": null,
741 "source_volid": null,
742 "status": "in-use",
743 "volume_type": "SATA"
744 }
745 ]
746 }
747 },
748 </code></pre>
749 </section>
750
751 <section>
752 <h1> Wait - what about secrets? </h1>
753 <p class="fragment">ansible can just pass secrets to puppet apply as parameters </p>
754 </section>
755
756 <section>
757 <h1> Step Four: Just get rid of puppet ... </h1>
758 <p class="fragment">but that's another talk</p>
759 </section>
760
761 <section>
762 <h1> Thank you! </h1>
763 <p> http://inaugust.com/talks/ansible-cloud.html </p>
764 <h3>Monty Taylor</h3>
765 <h3> twitter: @e_monty </h3>
766 <h4> <a href='http://inaugust.com/talks/ansible-cloud.html'>http://inaugust.com/talks/ansible-cloud.html</a> </h4>
767 </section>
768
769 </div>
770 <div class="footer">
771 <a rel="license" href="http://creativecommons.org/licenses/by/4.0/">
772 <img alt="Creative Commons License"
773 style="border-width:0"
774 src="https://i.creativecommons.org/l/by/4.0/88x31.png" />
775 </a><br />
776 Licensed under a
777 <a rel="license"
778 href="http://creativecommons.org/licenses/by/4.0/">
779 Creative Commons Attribution 4.0 International License
780 </a>.
781 <br />
782 Source code available at <a href='http://git.inaugust.com/cgit/inaugust.com'>http://git.inaugust.com/cgit/inaugust.com</a>
783 </div>
784 </div>
785
786 <script src="/lib/js/head.min.js"></script>
787 <script src="/js/reveal.js"></script>
788
789 <script src="/js/this.js"></script>
790
791</body>
792</html>