 Hi, my name is Alexandre Bourgen. I work at 10scores.com with my two great partners over there. And I've given part of my code to type fast to Rory for the previous presentation. But I'll put mine on debug mode, so that I'll try to do it fast, but it might have some errors. So this presentation is about Ansible, which is a great deployment solution. It's written in Python. We're going to have some Python code, but it's really some, it tries to be language-anostic. So this is, who knows Puppet? Raise your hand if you know Puppet. Raise your hand if you know Chef. CF engine. It's of that category. It's to do deployment in machines or instances or servers. Things like that. It's very cool. It's written by the guy named MpDahan, which wrote Cobbler. And he worked at Puppet Labs, went out of there, and wrote something awesome. That's Ansible. So written in Python, the only dependency you have on your machine is actually Python YAML and Python GINJA for the templates. And it runs in a push mode, on the contrary of Puppet. So it pushes through SSH, so you don't need to deploy another PKI, through SSH. And the only dependencies on the nodes is actually Python itself, because it's going to push the modules, execute them, and interact using JSON. So it's completely language independent in the sense how the modules are written. So we're going to try to go that. It's going to be a demo. And we're going to use, if you have any question, you stop me, and I've named Rory, if he doesn't understand, he screams and says, I don't understand. So you have a responsibility. Thank you. So the installation, so I'm going to go in zoo. That's where we're going to work. And we normally get cloned. I'm going to copy the Ansible checkout here. Whoops. OK, move. Yes. OK, I have Ansible checkout. So I would get cloned. That's what I'd get. And that's mostly all I need to have Ansible installed on my machine. And I would need, though, to have Python, YAML, and Python JINJ as a dependency. Those two things, if we want to speed up things and deploy to a lot more servers faster, we don't get into that. They're not required for starter. And then that's how we'll activate, it's a simple environment, change the path. And that'll activate the Ansible environment. So if we try that, it would be like Ansible checkout, hacking, and sit up. And then we'd have Ansible with all their executables. So Ansible's to develop and test modules. Ansible Playbook is what you use to deploy. The Playbook is like the Chef cookbook thing, or puppet smush, I don't remember. So Playbook is going to run thing. You can reverse the pattern with Ansible pull. We're not going to go into that today. So to start, we're going to create, actually I'm going to copy the little activate script here. Vim, no. So that's a little script we can use to set the host's file. And that host file is our inventory. That's where we have our list of servers. And we can even have a script that goes and pulls that from EC2. And then you'll have variables and all the hosts set in the inventory. Then we activate, we change the PS, and we'll load the insecure private. I'm going to use Vagrant just to provision the virtual machine, OK? Not used to that one. And I have a little Vagrant file here. The only thing I need, shoot, see? There's a debug mode here. So I change precise, and I have downloaded that. So I can just use Vagrant up when the machine launches. And so it launches a new machine plane. So we can test a lot of iteration of our Ansible. We're not going to do that much today. And now it's booting. It's going to forward port 2222 on local hosts. I can connect to it. And we're going to write our first host file, zoo hosts. And so the host file, we're going to call that moonodes, OK? Or no, zoo nodes, so that it's better. And the machine is going to be here. And I can set variables 123bo. And also, I want to have a special SSH port variable that will tell that machine to connect on that port. That's used internally. So we could use this way, or we could define variables for that group in vars, OK? And that way, we'd be able to connect to that machine. Everyone, all that group through port 2222, OK? Now, next thing, we want a playbook. That's the simplest thing you can get. The playbook we're going to call zoo nodes a playbook. You don't need the playbook extension. It's just that to differentiate. OK, so an empty, it's good. OK, so here, we're going to specify zoo nodes. That means this play here, you see that's YAML. Who doesn't know YAML syntax? OK, good. You go read about it. So the dash, that means that there's a list. This is the first play, which is an ordered sequence of tasks that are going to be run to ensure, in a depth-potent way, what's going to be on the remote server. So we're going to define hosts here. We're going to say we want to execute sudo but connect as vagrant user, OK? And we're going to have a series of tasks here. First one, let's say write to slash tmp. And the action will be shell echo boo. And let's say I want to push there, myvar. A lot of oo stuff, huh? So that's what we have here, myvar. And that's going to all bubble up and stack. If you have variables attached to the instance and into the group, then other variables will gather all the way. And that will be usable inside your playbook. But it's all managed from the central node, which pushes action over there, OK? And what do we want to do right now? Ansible playbook and zoo nodes. Do you think it's going to work? Password. Password. What are you talking about? OK, so zoo nodes. Zoo nodes doesn't work. See, I changed one thing and then it's out. So let me show you. We can here connect zoo vagrant SSH. Now we're in the box, OK? If you go to slash tmp, there's nothing there. Play, recap, hosudo. Oh, wait a minute there. Sorry? Sorry. So you define a host called zoo nodes. Yep. And then you pass the playbook in and da, da, da, da. Sorry. You define a host called zoo nodes. You pass the playbook in and it identifies you have the host zoo nodes and it reads the playbook to figure out what to do with the zoo nodes. Ansible playbook. Sorry, I'm not listening to you. OK, let's try this. I didn't activate the thing. So I'm going to activate it. So actually, it'll use the host file in the current directory. Otherwise, it uses ansible. You can have slash etc slash ansible. So right now, I'm going to use the current host. Sorry for that. So this is going to run, connect to the first step. It's going to gather facts, then run the task, write the thing over there, and then. So you'll see that. We're going to get into that. So first step, see, we didn't specify anything for gathering. In fact, it's implied. We can disable that by going to the playbook here and say gather facts false. This way, next time, it's not going to be run. And see that task, it wrote change because it returned that it did a modification. But let's look at that gather change step. It's actually a simple step. That's a zoo node. That's how we test one module. That gather step step, gather fact step, is the setup module. And we're going to tell on the command line to use sudo and use vagran because we're not going through the playbook here. We're testing the module directly. And that will return. See, it'll connect to the machine, run the setup module. And that will return a series of facts. See, that's the protocol. Any module that returns things is going to be JSON. And the specific thing about ansible facts is that it's going to add all these variables to the inventory so that you can use that. In every place, you can use them in some variables. In 10 places, you're going to deploy. So let's say we want to modify. So all these variables are there. And you have also the information about the module. Did it change something or not? That's how you ensure it in potency. So each module will verify things. Does it need to change anything? It'll change and return. It has changed. Otherwise, it'll say, nothing's changed. So what we could do here, we could have another step and say write MOTD and action. Let's say we'll say templates. So recently, we could get rid off of the action. Because you notice here, shell is actually the module name and the rest of the parameters. So we can nowadays use shell directly here. So we can take out action just so you're not confused when you see other things. So SRC is going to be template. And MOTD and destination is going to be ATC and MOTD. Got it? Templates, we're going to create that little file here, make the directory templates. And we could say welcome to our machine. And then we'll have many things here. OK. So let's say we'll see we have in the list all sorts like Ansible LSB. That's what normally we get in MOTD, the number of the machine. We want to keep those information because they're important. So we're going to fetch them and inject them back into the MOTD. So Ansible LSB. So note here, this is Jinja2, simply. So it uses semantics of Jinja2, and Ansible system, and then Ansible kernel, and then Ansible, what is that, architecture. You got that? So you're being controlled by Ansible. OK, a problem called Alex. Something like that. And then we're going to push that. Did I add the step? Yes. So normally that template thing is going to run it as a template, inject variables, parse them, and then push that over there. And what if I run it first time, not this one? So see? That's bad, oh, typo. LSB is undefined. Oh, you know why? I disabled gather facts. So it doesn't go and grab those variables and inject them. So if I take that out, it'll go, gather the facts, and then those variables will be available to be injected in the template. So you might have those kind of dependencies. Run that. It says change for MOTD. But if I log out and log back in, see welcome, you're being controlled, problem Alex. OK, we have these things. And that'll reflect the information from that particular machine. Got it? If I run that again, next time, see MOTD changed. No, it's OK. It verified, check MD5 hash on both sides. I don't need to upload, so it didn't transfer anything. So that's where you get the idempitency. Have any questions? No, there's no pseudo-password. OK. So he was asking, where's the pseudo-password? That Vagrant machine has admin privileges, so it gives you, just like Ubuntu machines on EC2, you don't have to provide a password. Otherwise, we'd be using SSH keys instead. We're not going to use that password-patching thing. Can you set the ownership and permissions of the file? Yeah, of course. So the template here, if I show you Ansible Module template, it has all those things and also the file, which you can set with the permissions and everything. It'll ensure, even the file hasn't changed. It'll ensure the permission with chmod. It looks like that, chmod, and then owner, and then all those things. So you can set those things and they'll be fixed. So that would be done with most especially file, but template supports that as a kind of fallback. It extends the thing. So no more questions right now? After, sorry. So we'll have, let me just show you NTP, we'll say action pkg NTP. And we'll tell the state here. And then action service, we'll say name NTP. That's how we specify things. Enabled, yes, state started. Oops. And then we'd have, for example, name create abrogé user, and we'd have user, and we say name abrogé. And over here, we could authorize, authorize, whoosh. See the demo. It's a beta version of his software. You're on location, and it's not OK? Yeah? OK, we'll check that. So abrogé, and we'll say the key here. We can specify that special who ha. And it'll go and grab the file on the disk. It'll push that as a parameter, just like I typed it in here. So it's going to read it. And what do you think it's going to work? I'm not sure. Let's try that. Nope. So name is for documentation purpose. If you don't put a name, it's going to use the full line. So I suggest you base that out a little bit because people are going to need to maintain that. And say, give out your intention. That person might be you, huh? Never remember. So that'll install NTP. It'll use the apt thing and send everything there. So can I go and SSH to that local machine? It was a blank machine, so obviously didn't have that, port 2222. See, I can log in right now, and I'm being controlled. OK? And NTP. See? It's running. Great. OK, so next step. Any questions? That apt command, that's built-in to answer? Yeah, so those things are built-in. The only dependency on the node part I said it was Python, that's if you want to use the standard modules. Otherwise, you can have a series of bash modules that you'll use to fit your purpose. There's a yum module there. There's a full list I can show you at the end, or you can read your own on your own. OK, good question, boy. OK, now let's write a little module. That's the interesting part. So see that module? It goes over there. How can you write something like that? I would like to have something that says, like, set the hostname, buddy, OK? And then we'll say set hostname, and a hostname will be Zoomoo Boo. OK, that's a great one. So how would we make that? Set hostname doesn't exist with Ansible. So we're going to write it. We're going to put that in library underneath our thing. And we'll say set hostname, OK? Directory. OK, I have a little snippet. You grab that piece of code. That's where Python has a little advantage here. OK, Python mode. OK, you can inject a little part of Ansible's code right into your, see those comments here? When Ansible reads that, it'll inject that module common, which declares Ansible module. It has the logic to decipher the JSON, and then has a simple thing to transfer JSON. So it does help you with required, and it returns error messages. Please set that thing. And it has a couple of things. So that's kind of a stub you can get. And if you use Ansible-doc, you can define some documentation and send it out to Ansible for your own purposes. OK, so what we do here will be quite simple. We want one parameter, right? Hostname. First thing we want to do, we want to know, what's the actual hostname? So we're going to fetch data. Look, do we need to change anything? Change it. Otherwise, well, not change it, but alert the control center that we don't want to do that. So current hostname would be kind of run hostname, right? And then we're going to grab standard outputs, strip the rest. And wanted hostname will grab from the module, param's hostname. So that's the one here. And then we could verify if current hostname equals wanted hostname, then we'll output something. Say change false. Got it? Otherwise, exit, that's loaded here by the module. Otherwise, we'll run actually hostname with the one we want. So wanted, OK, run, boom. And we'll module exit JSON, change true with message, change hostname, format hostname, wanted. Got it? You think that will run? I mean, it's quite simple, right? You check. That's all you need for idempotency. It's very simple. And you can write that in any language. Let's try that. You think it'll work? Whoa, changed, OK. What about the hostname in there? So it's zoomuboo. What if I do it again? Great, so it did not change this time. You saw that going? First time changed. Second time, OK, don't need to change anything. OK, any questions? I thought I'd be finished by then. No questions? Yeah, of course. So if you have a set of hosts, you'll go into your host. Let's say I want to do that and replicate that one here. We have this one here, and then, I don't know, poomoo zoo. And if you run this, it'll run on both in parallel. So obviously, you might write concurrent stuff here, but it'll go everything in parallel. And you can have a kind of a rotate thing. So if you have 30 hosts, you can say, I want to do that by batch. Run the full thing for 15 hosts, then continue with the 15 next hosts. So there's also ways to tag your things. You can, so let me show you in the zoo modes. Oh, one thing, that could get pretty full pretty fast, right? So what we'll do, we can put that in common.yaml, OK? And copy all those tasks, put them here. How many space do you think? Three? OK, good. And then, we'll have here an include, task common. So here, nothing has changed. But you can regroup things, and you call those ordered set of tasks one place, OK? Now, if you want to tag your things, you could say, OK, I want to repeat this one here. You could say, OK, when I update my app, I want to do that. Or you have a git module that's going to pull out a git. If you want to update your app, you don't want to go back and install all its dependencies and compile everything. Just update, I don't know, the git repository. So you'd tag certain steps, and on the command line, you could go here and say tags, update app. It's going to run only things, except gather facts, that are tagged in there. So you can select just a subset of things to do certain operations, which is pretty cool. So this blows away fabric and all its funniness. Also, if you want to install many things, let's say, or we could say with items, boo, moo, zoo. And then use that here as item. And what will happen, so I'll do that without the tags, it'll go and execute these steps many times. See, and that'll be executed many times. And you can have full Python structure there. So the animal thing. So you can have dot item, dot, blah, blah, blah, and have full construct of data structures. Yes? Yeah, there's a dot if I decide. I didn't go over there. So there's a system that has handlers. You can say handlers, whoops, handlers, and then include or define name or restart Bob. And that's going to be an action like service name, name Bob, state restarted, OK, something like that. And then at some place, you can have the task to say notify, or like a shell, boo, something like that. And then notify, restart Bob. And that'll keep the order of notifications and at the end of the playbook is going to call all those restarters. And only once if they've been notified many times, OK? Otherwise, you can hand code that with in your common things. You could say, OK, the output from that or the output from, I don't know, authorize, cure, create user, you can say register to this long variable. And after that step, I don't know if you can see that, after that step, you'll be able to use dollar this long variable to introspect anything that was inside the JSON. So dot change, for example. And in the next step, there's another little tag like that specific, that's only if. And you could put any Python conditional there and you can verify, oh, do I need, has that changed or that changed, then have conditionals to execute or not, like a shell to restart, a command, a simple command. So there's a lot of flexibility there. OK, I think that's going to be it, unless there's some very, yes, fast. Error handling, if you want to debug, and then you can test your own modules. So you see everything, it's scp-ing, running over there, downloading, you can have all the details, and you normally test the module itself. So you can have the JSON output or any output, as a matter of fact, going through a standard out. You can do that remote or locally also. It's pretty well designed. The guy's pretty awesome. Yes, yes, am I all right? OK, fast, fast.