Improving OS Configuration with Comtrya [DevOps Office Hours Ep. 05 -- Featuring David McKay]

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments
Captions
[Music] hello and welcome to the fifth ever episode of devops directive office hours today i am joined by david mckay also who goes by raw code on twitter and he has a youtube channel in which he covers lots of kubernetes he's a series in which he essentially has people break kubernetes clusters and then on screen live try to fix them so that's a super cool series welcome to the show david hi there it's a pleasure uh thank you for having me yeah glad to have you here and so today we're going to take a look at an open source project that you started and are working on called kumtraya can you tell us a little bit more about what that project is yes definitely so contraya is kind of essentially a configuration management tool and that you provide manifests and tell it the state of the system that you want and it's going to go away and try and do that for you so it's it's fair to consider it maybe something like angebo or puppet chef salt stack all those other great tools i think where come try is different is that it really focuses on localhost and being a tool for my dot files is what it started out as but you know it's kind of growing a little bit since then and just written a rust so you know bonus brownie points there right awesome awesome and so i'll i'll have you share out your screen and maybe you can pull up the documentation the github repo in the meantime i'll grab a link to your channel everyone should go check out david's channel it's a good one and i'll paste that in the chat cool awesome so yeah this screen that we we have here maybe zoom one click as well i should know better perfect yeah so this this web pitch here is the come try.dev it's it's our documentation and homepage kind of all in one uh i just i'll thank phil from our community he actually started the migration of this from my really crit attempt at docs at the start so i really appreciate his efforts there but we're continuing to improve our documentation it's one of those things that it's not the first thing you write in our project of course i'm more focused on delivering feature feature feature and but i am slowing down a little bit to focus on the dock so i hope they're useful we're going to use them today so i'll be making mental notes for any holes and gaps and things that i need to fix but yeah you can check out come try.dev get all the documentation this this is the inspiration of the name of the project this is harlan from sg1 yeah if you're not a stargate fan he was a robot that kind of kidnapped hd1 and created robot versions of them to live forever on his abandoned planet with him and it's just a cool name that i wanted to use our project for so long and i had the domains which helped so nice nice how how long did you own the domain before you populated it uh actually it wasn't it wasn't very long that was a relatively new one that i bought and i was like i need to use this or something and i've got loads of domains that i could have easily picked but yeah this one was fresh in my mind and i was like yeah let's do something with it perfect as far as installation goes we try to make it really easy one of the let me back up a little bit what are the goals of contria is really to provide a tool that is a binary that can run anywhere so well we do provide these little helpers uh you know carl bash scripts aren't for everybody but if you just want to get started quickly those do work and we also provide binaries on our github page we've got apple windows and x64 linux we do provide more binaries on some releases there are longer term releases we provide builds that are based on muscle seeds which work on bsd we provide builds our arm etc and there's a small bug and the cross compiler that we use from the rust project called cross that just means that it's difficult for me to do that on every release but i'm hoping that gets fixed and so come try we really do want to run on anything and in fact because it's written in russ it can we can actually compile it for android and for ios and for you know raspberry pi's and anything really cool cool you can get started with this wonderful carol bash one-liner that people always say is horrendous but a really good way to get started with a fresh project and so the plan for today is you're gonna kind of walk us through what the tool is give us a little demo and then we'll we'll brainstorm on some new feature to to start hacking on yes yeah yeah definitely uh yeah maybe i should just show you it working first or do you want to in fact let's cover a little bit more about the docs to get the vocabulary out and just so you're familiar with that and then we can yeah yeah perfect so the cli we just run contraya and provide a manifest location uh there's one really cool feature here that i'll talk about um is that two cool features i'm going to double down on myself here but one of the biggest problems that i had and i think i have this in the home page uh when i say here's alternatives and i talk about angel and soul stack one of the things that i love about ansible is that i can do anything with it and i have playbooks and i get really great output that tells me what it's doing right i have loads of love for hansel where it really fell down for me particularly for that local host setup was i just want to run like an individual task within a larger playbook that gets really difficult to the point where i was structuring my playbooks to only have a single task and then trying to compose them in this way and that's not great there's too much boilerplate involved there so one of the things i would i just had to have control do is like i want to be able just to do run this one manifest that's it ignore all the rest something else we'll come to come try and we can talk about this on the as we look at the issues and talk about maybe what we want to add is the ability to also label manifest and actions within manifest and just really target what i want to be able to run so that was really important to me the other thing that's really cool here is that i also want to be able to run from trial without actually having my manifest available locally there's use cases for this particularly cloud in it is the one that i use a lot and so whenever i spin up you know machines on amazon equinix metal google cloud for me my user data is now just a com trial with a remote url where it's going to pull it run all the manifest and then it's done cool so yeah those are those are two cool features that i think would be cool uh i'm sorry i've just seen wiley's comment who's trying to teach me angela no thanks walid you you can do that and ansible of course uh come try is just nicer and easier you'll believe me all right so this couple let's tackle the vocabulary so the manifest is kind of our our first building block and that just means a yaml file that's all a manifest is we have to provide a list of actions within a manifest that we wish contrary to execute and we just use this inline tag of an action with the name of the action to tell out which one to run so we only have a few actions available right now but there are enough to do most of the things i need to be able to do and we'll expand on that as we well as people start using come try for more weird things i'm sure yeah with the command or run action we just provide the command that we want to run so it's probably still a bit small manifest can also have dependencies so you can have a depends key here and then just list any other manifest that you need to execute first so come try does build a dag of all your manifests and the dependencies and we'll try to run them in a smart way one of the things i will be working on very soon is actually an asynchronous executor which will run any manifest at the same level at the same time based on the number of threads on your machine okay it's going to be stupid fast i mean it's already fast but it's going to get stupid fast and if we take a look at the actions this is what we have available thus far one we can run commands two we can provision fails and directories and the secret sauce of contraya is really great package management across a collection of providers so we've already looked at the command.run in that first example we'll just take a quick look at one of the fail examples so here you can see that we just say we want a failed.copy action we have a concept of a managed file which just means it's in a fails directory very much like ansible we'll see that as we take a look at my manifests we specify where we want to put it we have the ability to render that through our context this is just ginger style templating again hopefully familiar to anyone has used any of these other summer tools and then we can specify the permissions that we want available in the file directory symlinks are pretty much the same so i'm not really going to look at them just now but we will dive into packages because i think this is where things get a little bit more interesting and i'm trying to make sure that manifests work across any operating system you know i said come triac is just a binary that you can run almost anywhere so for me i am a serial operating system installer my mac i wipe it clean into a fresh install every 30 days without fail just boom done i also switch regularly between windows playing with wsl 2 and i also switch to linux where i run arch linux i i've got to say i run our linux it's like running arsenal but you know so i've never really spending too much time on a single operating system and i really want my dot files just to work regardless of where i am and that was really important to me as well what we'll do is we'll take a look at the different variations that you can use the package installer so this is the simplest one where we just say we want to run the package install action and i want to install something called curl that's it what's really cool about this is if i'm on debian or ubuntu it's going to detect that and try to use aptitude as the package manager if i'm on mac it's actually going to go okay you probably want homebrew and it will actually install homebrew for me if it's not there and then install curl and if i'm on windows it will use when get the new official package manager for windows and it will install the packages from there if they're available too it also supports less than text so you know you can group things in any logical fashion depending on your use case or just whatever you're trying to do and you can get very specific about the provider that you want to use so you know here are actually all the providers that we support out of the box uh debbie and variance aptitude if you're on freebsd i will use bsd pkg package i'm not sure mac homebrew although humber does work on linux 2. and it works out there out of the box with a contraya forgot the name of my own project when you get on windows and then of course arch support so it will try to use yeah and provide the we'll actually install input strap yeah for you too which is just a pac-man wrapper that supports the arch user repositories which if you're on arch you definitely just want access to yeah we can override the provider if we want next cool thing is that you can provide the repository so especially useful for ubuntu-based systems with ppas and homebrew which has taps so here i'm actually just installing queueblocks and telling it the tap name is here and it just handles it for me again i don't need to worry about any other stuff and then if you specify a dependency that doesn't exist on said platform does it just give you a warning or what what sort of happens in that case no you can't ask that question because the behavior is not ideal um you will get an error on your manifest run one of the things that we don't have the ability to do with the providers is block them from running on platforms so okay um i mean i'll cover all the caveats here but let's say you did this on a windows machine it will try to run brew and it will fail this manifest but failing that manifest just it will carry on you know it just kind of gets skipped and you'll get enough information to let you know why i couldn't run but we will talk about really cool stuff that we're working on to make that better cool okay now the variant support we have this is early days and we're working on making this a lot better i've got examples of the proposed syntax we're going to be looking at using common expression language from google i'm not sure if you're familiar with that but we can talk about that but right now you can just say i want to package install cube control and then on homebrew it's actually called kubernetes cli although this release does work so this is contrived but we can say that we have a variant overlay uh on macos where the name is actually going to be substituted here and actually this entire spec under the variant is all of the fields that are supported here so you can over you can actually have different repositories as well or even or even specify a provider for that install too and this again is one of the things that was really important to me is i just wanted to find my manifest once and yes i can do this with ansible and salt using ginger maps and other conditionals but i just want a nice declarative way of saying this is what i want and i really really discourage this but i will show it because there is an escape patch and that ginger is completely supported within the manifest so you can skip things um if you need to by just saying if user dot username is route and that will use any context of course user is the only context we have right now but i think you and i may add a new one on this episode so that is the that's it i think that's all of the actions that we have right now and all of the cool stuff that we provide with packages how does that look to you yeah that looks awesome could you could you pull up maybe your config and show us maybe what it looks like for a particular use case ah of course all right and while while you're doing that i'll go through a few comments we've got uh the fire flash from germany hello welcome donnie uh is another person who's been a guest on this show donnie roofs from the netherlands we've got some comments about ansible that you already addressed and then walid is is egging us on here we go enable bad practices i do say discouraged in the docks and it is there only as an escape hatch until i show you the new stuff that we're working on and we're adding new predicates to the manifest which will support only in where syntax i'll show you it um but yeah the jinja is just there like if you really need to do something bad i don't want come try to stop you so you can't do it um but that's one of those i think that's that's a really key feature in in almost any of these platforms right is having an escape patch so that if the person reaches the boundaries of what is supported they can extend it maybe in a hacky way temporarily and then maybe roll some changes into the upstream to to support their use case more officially yeah i think the challenge with all of these stuff all these tools building software is is that you know when you try to provide a record of api you're already expressing opinions that you have as the contributor and the maintainer of the project and it's in the minute you have a conflict of interest between what my priorities are and someone else's those escape patches are just mandatory at that point because i could say yeah you never do this this is how you install the package but there there's always education for sure i won't defend myself anymore the escape patch is there if you want all right let's take a look at uh something simple so this is these are my real dot files for for my systems and i've added an escape hatch here just to kind of show it working so we maybe i should delete it now that everyone thinks it's a horrible idea but it's there so this just says i want to install something this assumes that i'm only going to work on a mac so i'm just saying the repository is homebrew cask fonts and then we have a list of fonts that i want to install and this f condition just works if i wanted to but we'll remove it for now we can add it if we want to play with that later um so let me one of the other reasons that this all works this way is that you know there are uh plenty of tools out there to manage dot fails and in fact people always ask me why aren't you just using like brew bundle and having a profile and then doing that and i just think that the configuration with the declaration i want a package installed should always live together you'll see that i have espanzo here which is like a text expander clone but it's open source i'm writing a rust so of course i'm installing it but you know i have my files with my config next to my manifest it says this is how to install it and i always like to grip things that way like i don't want a brew fail in the root and then all of my dot files scattered around somewhere else like i really do think the structuring of that is important at least at least to me excuse me so here's one of the weird things that i think catches people out when they play become trial um manifest names are the name of the file so this manifest is i know that's really small on the sidebar so let me zoom in for a moment but you know the manifest name here is item two this one is mac os this one is slack we also do something this comes from salt stack but if you have a main.yaml inside of a directory then the name of the manifest will inherit the name of the directory so if i only want to run the expanso manifest it will be called expanso got it i think this is all you know pretty standard package install stuff there's nothing too crazy here uh we've got more repositories oh yeah and we have extra args so this is another one of these escape patches where uh and to install neil vem if you want to compile it from source rather than just like the bottle of the piled binaries from brew and we can use extra args and these past these are passed directly to the package manager provider that is going to be used by contrail and this just passes the head so this is essentially a uh brew install kneel them edge like so just useful and you can pass as many of those extra args as you want you can yeah yeah so yeah that again one of those another escape patches if you need them and you want to directly integrate of course one of the things you should do when you're doing that is probably hardcode the provider as well just so you don't pass a head to act and then get more errors but again my dot files right now are focused on macs just because i'm using them exclusively now here but i am now starting to roll those out to windows and bsd and thinner so and it will evolve especially as i'm adding more providers now okay i will show off just one more thing that i think is probably interesting is that we have a responso here with the repository and then the fail.link fail.link just means that the symlink is a fail but you can actually send them to an entire directory uh so if we pop up in my dev zed shells and you'll see here this whole directory is also assembling so let me just check that that works there we go or our includes is pulling out all the clips from adobe files shell i get available and then we can run from trial so i'm going to run it from here yeah so here's the m flag where i can just run fonts and i'll kind of walk you through the output before i run it for all things but this will filter down to a single manifest and then it tries to kind of give you a little bit of information to tell you what it's running now the log output is something that i probably change all the time i'm trying to work out just how much information to give you by default versus adding on you know verbose flags to increase that but right now because it's an early stage project i really want you to have a bit of confidence in what it's actually doing so we can see here that it's going to run a command with privileged false and it's going to run a bridge app one of the things and we'll see this when we take a look at the actions and the atoms that make up this kind of runtime is that contraire tries to do as little as possible at all times so it's going to check if it needs to do something before actually doing it i don't know how familiar you are with the guts of brew but i'm now getting very very familiar with how it works it's actually kind of difficult to work out where if a tap is already available at least using the brew cli so i've had to start kind of reverting to querying the disk so there's a few few hacks that we do with bro to kind of understand or just what we have to do but what's important is we did the brew tap because the plan on that says always do it and then there's nothing installed afterwards i'm going to uninstall our font and we will run our font again and what we should see is we have a second command now whereas okay we don't have this font installed so now we're going to run another command and off we go okay i still have a broken zed shell but let's give that one more minute before i fix it uh we will add one more action this time i will do a command.run with a command who am i command.run is special and that it will always run there's no planned step to work out if it should run so what we should see here is the brutap runs and why have i got an error am i here and i feel and that's awkward i've increased the verbosity by one we can see the context that are provided we can touch on that in a second ah okay that's a bug you need to provide a directory to run the command it's supposed to default to the current working directory um and i actually knew that was a bug and i just haven't fixed it so shame on me why is that still feeling let's try one more thing before i completely forget how everything works huh such file directory all right well i guess we're effecting a bug um yeah but what i wanted to show was that we could do privileged oh you have a typo in your command someone in the chat just pointed out who am i uh i hate myself so maybe yeah there we go who was that oh kevin thanks kevin the fire good good eyes good eyes that's that's the best part about live coding is that you've got many debuggers uh helping you yeah i was going to start debugging a bug that didn't exist all right let's run that again yeah cool there we go so ironic command we don't see any output we can increase the verbosity one more we'll get a lot more output and what we'll see is that we've got an extra code of zero we're starting out on standard out there we go and then standard error over zero and of course we can run this in privileged mode and so one of the things com triad tries to do is handle privileged elevations in a very sensible way which means that if we run this again i really can't we're hoping for root we're hoping for root uh is that how you spell perfect yeah right well i can do this maybe i'll copy and paste p-r-i-v-i-l yeah oh wait preference is the i can't remember how to do this let's check out the atom there go to the docks oh that's a good idea i've got talks for this so command of course i haven't documented it all right well we do have an action we can do a command we can take a look at run sudo shame on me uh like i said this is early days and i change stuff a lot so you need to kind of forgive me but pseudo true should get is what we want there we go there we go so we get a warning here saying look we have average elevation that is required we are going to kind of request your privileges just so you know why you're getting a password prompt and it's going to tell you what it's actually going to execute so there's no surprises that it's going to run you know maybe a crypto miner or whatever if you were very unlucky and we got it here so cool phew i know i'm forever going to add an alias of privileged pseudo action all right so we're starting a position where i have broken dot files will pop up in a terminal so let's just run everything here like so and you'll see because these um these dot files have been run regularly is that you should see nothing to be done nothing to be done to reconcile the manifest ninety percent of the time i do need to make that work for brewtap so you will only see brewtaps running and then eventually we will get uh the neo-vem head flag also will run every time it's just a brief thing but that said shall run yes it did so hopefully i open a new terminal my zed shell configuration kicks in it's going to download all of his plugins and my terminal will be back to now and that's come try nice that's that's cool yeah my i think you'll find that my uh maturity when it comes to configuring all this stuff automatically is is relatively low like i have my my oh my zsh shell installed and configured but i don't i don't redo it or change it very often so this is this is new to me i spend more time tweaking uh my dot files and my zed shell configuration properly than i do my actual day job but so i just i'm always trying to make things a little bit better uh i'll if you don't mind i'll just quickly show one more thing then while we're here yeah please so i said to the supports remote manifests so you know let's just i'm going to run fonts just to keep the run a little bit quicker but what it's going to do here is actually clone my dot files to a cache directory and then run the fonts against it you can see syncing the directory if it's already there in the cache it will do a pull and fetch and an update try and keep it up to date and then it runs through as well and so this is really good for user data especially when provisioning cloud machines yeah much i think it's nicer than cloud in it of course i do have a level of bias there but i just think it's easier to work with um and one of the things that you know we've been discussing there's a few contributors on the project now it's not just me thankfully but there's the ability to kind of like well what if i want to consume other people's configurations and like been able to drop in and just say i want your kubernetes config or your zl config or oh your vs code is really cool i'm going to grab that and be able to provide them through include syntax as well so lots of cool stuff coming hopefully uh i also mentioned predicate syntax uh do you mind if i should quickly run through what that will look like too yeah yeah please do and and i have one more question on the you're provisioning a cloud machine then you just put like the uh curl piped into shell plus one executable command and it grabs the remote config is that how you've been doing it yeah so my my there we go i can't type and talk at the same time my user data now looks like i'm trying.dev uh bash from trial https got it yeah yeah that's what i was saying you know those three lines are all i need now to provision a new cloud instance and then it works pretty well as long as the repository is open first or like available if it's behind any sort of authentication things get trickier but you know come try as an early project we could add support for filling secrets from certain locations and other stuff but we'll see how things go okay so let me finish hopefully you're not you're you're the set of things you're installing is not too sensitive hopefully yeah yeah i think if you're using come try you have to kind of work out your own usage there and make sure that you're you're happy with what's happening yeah definitely all right let's grab the maybe zell is just a good example it does a few things now let's do kubernetes so one of the challenges that you need the escape hatch for right now and i kind of touched on this when we were talking about the actions is that if i use the variant syntax and say on a mac os or linux or debian let's say debian i can override the command and do this uh or i can hard code the provider so let's add both of those as examples where i say provider is homebrew we're in a situation now where it's not going to run on all machines because there may not be a variant overlay for the machine that you run on which of course isn't a problem or a bug the other thing is that we hard coded our provider and there's no way to say that homebrew is only available on certain machines so you know don't run it otherwise we're going to get an error which again potentially a bug in your dot fails but come try wants to make this easier so let me share google cell google has this project called common let's try google has this project called cell which is a common expression language and it allows basically it's like a subset of javascript similar to what skylark is for python etc that allows you to do simple expressions that resolve to the true or false values not always true or false values but and what i want to use it for definitely the case but really what i want to be able to do here is to provide an only context and say well only run this where my operating system name is mac os and then now this action within the manifest will only run when the predicates under only are true we also want to modify the variant syntax to be a bit better than just this because it's not like i said come try has to run everywhere so what does debian mean well what about architecture and then the package name's different and then am i a rooters are not a root user like there's all these different constraints that you're going to need to hit that escape patch and i don't want you to use the escape patch so the variant syntax is going to change and in fact what we're going to see is a variant where a where clause again with the google expression language i'll just say name equals this and then we can overlay the list with different package names here and this is going to give us a lot more flexibility uh even when it comes to commands so you can imagine a situation where we've got all right and i'm going quite fast here hopefully i'll make sure yeah what is that second list under the variance so we've got a list of these packages we're installing starting at line four then we've got a a variant saying where mac os then this list starting on line 10 is the mac os specific packages that we don't want to install anywhere else exactly yes so this list here and well we run on every machine where there isn't a variant that matches the web predicate so anything that isn't mac this is what we install however when these are true we overlay this entire block onto this so this would become my terrible typing of data oh it uh eliminates the the ones that are in the list already so that we're getting into the details but yes there is a there is a strategy okay of like merge versus i got it yeah so all the flags are going to be there as a work in progress right now one of our contributors felipe is working on the saturday deserialization so that we don't break backwards compatibility with what we have now uh but still allow all of these new predicates on top of it so hopefully we'll be able to roll that out in the coming days or weeks we're very excited by it um and one of the things right now is variance only works on package.install and i've already realized in just like a few months of using come try that i just need variants everywhere so where we have command or run we can say command is who am i but then we're in a position where okay that doesn't exist on windows so i actually want variance across the entire stack and this would be some powershell thing that i don't know but and the same for fails you know what if i've got a failed.copy the pass on debian might be different from red hat definitely different on mac and then definitely different on windows we want to provide a ubiquitous and stable api to work across all these major operating systems and do what you want to do in a nice declarative fashion cool got it there's quite a lot there hopefully i didn't go too fast and that all made sense though no i'm following hopefully hopefully the folks in the audience are as well um but yeah that's that's super cool all right so should we add some features yeah should we pop into the issues tab i know you had a few pre-populated that might spark our spark our uh ideas can't believe that was pseudo or not privileged that's gonna that's gonna bug me right anyway yeah so we've got our um issues page here there's a nice simple one i added this afternoon and this is a request that i get regularly from people that are starting to evaluate come try and is that the context that we provide let me show you that and they want to show the context when you're executing or when where are they looking for that context and let me just move up the top why did i do double verbose that was my fault sorry there we go yeah so context and come try are variables that we make available to you within the either the ginger style templating or within the predicates that are coming so the only and where right now this is the extent of the context basically four values under a user key so we can tell you what what your username is we can tell you what your name is on the system we can tell you where your home directory is and we can tell you where the operating system expects conflict values to be stored and that is uh we have a really great discussion opened by one of our early adopters krillif uh who wants to be able to use context to get i know there's a lot of text i'll zoom in but you know i don't expect anyone to read it but what they're saying is like you know i use salt stack in the past i've used puppet you know salt has grains papa has fats there's all these pieces of the information all these all this information from the host that we want to be able to make available within the rendering or manifest system so i thought we could try something that would be nice and simple to get started introduce us to a little bit of rust and hopefully cover some of the primitives of how this all works and just expose what is the operating system and maybe architecture or something else to the context system we should be able to see that print out nicely at the top in our debug mode and then we'll know if we've been successful yeah and then that feature is a precursor to one of the filters you were showing earlier right of being able to say like os dot name or whatever exactly yeah right right now even if we did add the the serialization and semantics for the predicate you would only have access to username or home directory that's not going to get you what you need yeah no that that seems like a a good a good first bug or a first enhancement i suppose not a bug definitely i've already assigned it to myself so we know that we're working on this i say one other one to us too depending on how brave we feel uh but another common request that i get from people is that they want to be able to do like a github.binary action and it's going to go to the project get the latest binary install on the system and then chime out at plus x you know for cube control or kind or a terraform and all these other tools as an alternative to the package managers that you currently have exactly yeah so yeah i mean in theory we could make a package manager with a provider a github where it just pulls boundaries from our project but i think we'll we'll do something slightly more uh bespoke if we have the time and we're feeling brave because i'm not entirely sure we'll be successful trying to do this but we can definitely give our best bet yeah cool awesome well excuse me let's make sure i have all the recent codes and i just linked the come try uh github in the chat if anyone wants to go check out the the repo it is all there yeah i'm really close to 100 stars so you know if we can make that happen that would oh yeah i'll start right now 98. we got two more to go there's eight there's eight people watching we got to get to 100. that's easy awesome okay so we pulled our latest one here i'm going to add a work tree uh we'll call this branch feature uh what do we want to do a context os and we'll call this contacts os and then we have a new work tree we'll pop that open in code and now do you want to quick tour the code base yeah let's let's just jump in and and look at how everything's laid out maybe as a starting point cool well we have our main.rs this is obviously where everything starts we set up all of our logging we build our graph we pull down the manifest and it's only 380 lines of code it's probably still 300 lines of code more than i want on my main.rs but i have been slowly extracting stuff out to modules oh i think while he just said he was 100 made it nice awesome work team all right so we've got our main rs here this is where we do all the building of the the dag the graph that we can traverse and do the executor and we once spent a lot of time in there is verbose and complex to a certain degree but we don't have to worry about any of that because all the magic happens in our other directions and my computer is a little slow so i'm going to close some of these apps it should be okay okay so we've already seen that we have a manifest as a user kind of api and that you create a file we call that a manifest you can see here we've got the providers for loading it so right now we support local and get we could add more providers to there if people want to see their manifest come from other locations um but we don't need to touch that once we parse the manifest we get something called an action the action is again the end user api of the thing that you want to do that would be command.run directory.copy fail copy and link and then of course package install now one of the in the first version of contria the action files were getting really complicated we were doing all the rust code there and i just decided that if i really want people to contribute to this project i need to make that easier so through a lot of back and forwards uh talking to some of the early contributors i said okay well what if we had a concept of an atom like an atomic unit an operation something a contractor could do each half each atom has a really simple api one plan do i need to do this or can i skip it and the other one do the thing and that is it so now we're in a position where if we did if we do if we did if we do want to add a new action like get how binary github release whatever is that we only really need to admit some data structures and then the executors will handle the rest so let's see what that looks like i think fail.link might be a good one let's do copy link has a little bit extra complexity but we go through that too so the first thing that we have to do is just define what does this actually look like from a data structure point of view and this is the same api that you would enter in your manifest so from and to the permissions and whether we want to template it or not we can ignore this little bit of octal juggling that we do and just so that you can type in a decimal value we convert it to the octal that's linux permission stuff let's just ignore it but then we have this concept of a plan so you can plan an action and you can plan an atom a plan of actions returns a list of atoms and then you can query the atoms to see if they need to run we have a little bit of code which will render the action if we need to so you know if you do decide to template one of your files all the contexts are injected and rendered maybe something would have been easier but we'll keep going this is the important bit so this is the last statement and the plan for the action and all it's saying is i want to return a vector which is a an array slice and we return a slice of steps so all the steps that the executor will take and the steps contain an atom and then those atoms there is some control flow on top of that i know i'm getting really right into the the nets and grits of this please feel free to ask questions or just um tell me to skip it but um we want to be able to say do this thing which is an atomic operation and the initializers allow us to do anything before that to maybe stop the run if we don't need to do it or the finalizers allow us to then modify the control flow of any subsequent atom so and so the the copy action that we're on consists is composed of a make directory a clone path and a change permission and whatever other steps follow right is sort of what we're seeing here yeah so step one when we do a failed copy is first to make sure the parent location exists so we can actually put the file to there so we do a maker.p and i'm not happy with like whenever we see an exec here that means we're doing a command execution this just means that an atom is not going to run in every operating system that i would want it to like a maker probably won't work on a windows yeah so you know i am replacing these execs with uh native bindings but right now the makedown.p does exist unfortunately in fact it does run on bundles because i tested it but there are other operating systems but that may not work and so that will eventually be replaced with uh a rust function that has native bindings to each operating system and checks if that directory exists on that operating system exactly yes and that's what we do with every other step here so every other step here is an atom that has native operating system bindings very rust to do the job that needs to do they make there is just the last one that i haven't created a an atom to create a retriever we could maybe do that too we've got loads of options so next we define another data structure so the next step has an atom we can ignore initializes and finalizers for now but i can show you an example if you're if you're curious but we have a file create atom which just needs to know the path and it will go and create the file we then change the modifications on it telling it the path and then the mode and then we set the contents of the file and that is how we do a file copy using the atoms within the contraire system and the atoms you said are a relatively new concept right you i think you just made that refactor recently right yep for four days within the last week nice and i mean i can we can definitely take a look at the older code what you'll see is that with each of the actions like uh you know this is 140 lines 30 of its tests the rest is just the data structure and then there's this little bit of setup that only this action actually needs you know if we take a look at link uh all we're doing is checking whether the path exists and then emitting the data structure so this one's a lot simpler in fact there's a lot more tests than and sexual code i'll show you the initializers and the finalizers out of you know curiosity more than anything but the p the bsd package provider is a little bit special and that um it will output telling you if an installation will remove any other packages and normally we don't want to remove stuff unless you explicitly allow it so excuse me so if i scroll down to our install stage we have our first step which will run the pkg install with a kind of dry run dash n flag which says just go and look what will happen if i run this and then we modify the control flow by saying that stop if output contains remove so if our dry run tells us that the installation of this package will remove any other package show that error to the user and make they can make that decision if they want to remove it and then run it again or just ignore it and so the workflow would be manually remove it then rerun come trio and see what comes out of the install dash in yeah i mean i've i've gone back and forwards on this so many times now about adding a force flag to actions to build you know just just we don't care just do as i tell you and i always lean on like this is not configuration management for a server although we can use it for that that says your dot fails probably your local machine and i think we should probably be a bit more careful with that but i do go back and forth on it and tomorrow i may change my mind so for right now we try not to do anything destructive on the machine uh i don't do we have any initializers yes we have a command exists initializer let me show you the structure okay so these are all the actions these are the atoms and we have in our steps initializers and finalizers so this is the output contains one again is mostly test but it just allows us to check if an atom output is a string that contains a value we also have a command run or a command found which can tell an atom not to run if a command already exists so if i search for command fan uh i'm not actually using the initializer yet that explains it yeah so we could say already exists meaning that is in your path so if you executed it would execute the the program all right what do you mean by already exists yeah i think my intention was to use this for the sure is using it but for the homebrew provider where it would say if brew exists if doesn't exist go and install brew got it it can be used in that sense does this help an atom run or not and then there's a context where we'll be spending the next however long it takes us to implement it these are nice and simple you'll be glad to know all we need to do is provide a data structure that we can attach an implementation to it has to expose two functions one is a get prefix the prefix is how we reference that in the genja so user dot and then it returns a vector of key value pairs or key list pairs that can have the values that we want to return that's it yeah all right i feeling confident about all that code yeah i think i think we we just copy this file put in a new one called uh os dot rs that's exactly how i would do it first paste it so let's say touch on a little bit of the rust stuff here and this this this is my flow as well i do copy and paste to get all that boilerplate done so normally i would come in here let's say all right i'll leave one example comment it out i'll update this this is now called os and then do a search and replace on the other stuff you're not going to get your auto complete with the rush language server this way because rust is a module-based language so we actually need to come into mod.rs and we have to tell the language server that this now exists and that comment is actually specific to that so we'll leave that there and now we should be able to get our auto complete if i could type yeah and so that's always something that i kind of forget up uh forget at first you know so let me just ask a clarifying question there until you imported it into mod.rs rust your basically your vs code plugin didn't know where to find the rust language definition yeah the fail would never be compiled okay no autocomplete would work essentially it doesn't exist it's just a fail but because nothing links to it there's no references to it it's just orphaned it doesn't doesn't matter okay cool all right so we probably don't need access to durs which is a module for getting operating system directories we do need some context stuff here and we need to change our implementation here so let me cover a little bit about what we have right now this is the simplest context provider that we can have because it does nothing all right the way that rust is not a uh an object-oriented programming language so you know it's you know you don't have classes and we don't have uh inheritance or or any of those things what we do have is traits and the ability to attach methods very much like go does you know where go you would have a struct and then that chart can have methods that can be applied to it through a receiver syntax rust is a little bit like that where we can say we want to implement a trait for this data structure which just means on this data structure i can call any of these methods uh the trait that we are implementing here the context provider is defined here and this is like an interface so we're saying that we have this thing a trait called a context provider that must provide both of these functions with this signature so we have guarantees that we can always call this function on anything that implements a and in fact we could compile this right now and it would all just work but we we wouldn't see anything new if that why don't we do a run yeah so it's returning that empty vector of the context uh yeah so the prefix will be created yeah it will be created but there will be no values in it so i don't actually expect the output um to show anything uh once the compilation happens this is the downside to rust you get a lot of really great things with the way the memory safety works and the runtime safety but the compilation speeds are a little slow so we just need to give that 30 seconds hopefully i spend a lot of time looking at rush seas out we do get a nice little counter so we know that we were done the last few crates now maybe we should add something make it a bit more visually appealing yeah should we just hard code some string there yeah that's what i was thinking good call uh so we'll call this linux even though we know it's not and we'll call this os name there we go there's our very simple context provider five more and because it's compiling all of our dependencies hopefully it catches that change we just made as well but if we did have to compile it again it would only be that one fail to change it won't be as long and this is because they used a gitwork tree i probably should just have created the branch of my normal tree and then we probably wouldn't have had to get pale all again um [Music] all right vanilla says hello hello fennel welcome to the welcome to the stream all right so ah okay i forgot that uh we have a function so all all that we've done thus far is make a module available for compilation generated a working context provider but hard coded but we have a function that is called here where it loads the context providers and we just need to connect the glue here so we have to do a box new and then os context provider doesn't want auto complete no it's pulling on some random package let's try that again worth context there we go and this is a structure which has actually no values we're just using it as a type to attach those methods to it and it's complaining because mismatch types ah okay so well we're gonna we're gonna learn some rust now so uh i was going to tell you what the box was but now we're going to fix our first problem uh rust does type inference so when we have this it's actually assuming that we're getting a vector of user context providers so now i'm throwing in a new type and it's like oh wait i i don't know what this is anymore like why are you not a user context provider so now we need to update the type on the context providers yeah yeah so we have to actually tell it actually what we're getting is a down contact provider and if that's happy yep okay so let's try and cover this because this is some um i'll speak from my own experience when i was on a rush this stuff confused the hell out of me right but it's just the way that rust works so this isn't you know we're happy with the vector as a slice yep we have a box now a box is just a fixed size pointer in rust that says that i'm going to point to something else and that's because rust has to know the size of everything in memory and be able to kind of link to it and i am not an expert in yours if i see anything wrong oops i'm sorry rust people but we have to tell it that we have a a slice of pointers so they can allocate the right size of stuff too it can allocate the right space of memory for those planters to exist even though it's pointing to something of a random dynamic size which is what the dine is here and a context provider the reason this is a dynamic size is because this is a trait and we don't know which copy of it we're going to get these two structures could have completely different internals different fields different ends strings and booleans all have a different space in the heap so we have to tell it again that this is dynamic and we don't know what to expect yeah there's a little bit of type juggling and then presumably somewhere in the background it looks at the the two different types and says what's the largest it could be and allocates enough such that it can use either yeah i think and you know maybe i've been i even do some assumptions right now again and apologies russ developers and no more but uh yeah our slice gets fixed size pointers on the heap and then the other parts the other dynamic stuff will be stored in non-sequential memory where it could just be looked up and pointed to it and referenced is that's my understanding of that i think it's just because this is a slice you know like um it needs to know how to allocate space for that night because you know rust is trying to make sure that whenever we pass something to a function actually gets moved in memory so nothing else can reference it and then we have this concept of immutability and references the way that we work with the types is all weird and wonderful but just takes a little bit of getting used to it and i'm sure we'll touch on more of this as we explore the api a little bit more what's important right now is that we've added our new contact provider and it's going to show up right i don't know if that was a question or a statement but it's about both it's gonna show up for sure linux all right we now have added a new context provider that exposes some piece of information now we want to make this real now so let's jump into it with context provider and we have access to a create called os info that we're actually using in other patchwork tria so we'll use that here and it's got some functions got some functions i guess i'll import it pretty sure i can just do that i don't know why all right let me make it happy for a second first and work out why i'm not getting my i thought there was a function just get yeah yeah get let's try again then yeah i don't know what's going on let's try assignment variable so we'll call this our os info in fact that's not break the name get okay that's better i'm just going to blank this again for a second so this is again another one of the reasons i really like working with with rust is that we get rust analyzer which is doing all you can see all these little comments in my code where it's saying here are all the type inferences i've made so ed knows that we get back in info from osimple.get we can now use the autocomplete to say okay but what do i actually have access to so i mean i could just pull up the docks but if we just quickly take a look at this list and os type might be something that we want so let's click on that and it's going to return type which i can't click on there we go yeah which is an enum which has alpine amazon android all these different things here so that's probably a good thing for us to expose as the context yeah and it implements display which means we're actually going to get a string representation of it as well and not the enum value yeah yeah so we like type uh we got that from here is there is there also an architecture or something yeah we might need a new create for that but we're definitely going to take a look we'll drop this in it's complaining and it's telling us that we've got an enum and we have a string and that's because we're not writing it to anything so the display tray probably isn't kicking in but we can try encouraging that by wrapping it in a string from no it doesn't like that either all right let's try and do some juggling what we got i don't really want to just spread f on it that seems a bit painful i don't know if that will work no it doesn't like that either all right well we got access to so nothing so this is the only way to convert it to a string the only there's no like raw just get the name of the enum uh so we we could so one of the things that we could do is actually do a match statement on our os info west type uh and then we'd have to fill in all of the different versions and we could put our own thing but i'm going to try and avoid that right just trying to think of the best way to do it i'm stumped by a string juggle what about i have sprint f and rush to be oh yeah just start spreading f in general that's clever okay let me go rush where we can just format okay so there's a format macro which should have came to me much quicker and os info and this should put it through the trait for displaying it and give us what we need yeah phew and i'm starting first burn f cool in theory that's everything we need at least for the first piece of contact so if we run this again easy right easy peasy all right so you mentioned architecture um it's a there's also a version and a bitness i think on the info object that we might want uh okay so let's just add two more of these let the formatter do its thing and look at the api so that's another really annoying thing about rush language server as much as i have nice things to say about it there are some um weird things that you need to get familiar with is that you won't get auto complete within a macro like this so you'll need to just kind of jump back out so we got code name which is an option string let's do that first just because we've seen it and because this is an option we'll probably do a wrap or and which means we can just have a default value of unknown and what is the un what does the unwrap do sorry yes uh okay so let me show that api again so under codename you see here we get an option string which means we're going to get either the value none or we're going to get a string now because we're doing a format on this we just want to be able to make sure that we don't get essentially like a null pointer exception where it's like oh this is the none i can't print none because none is none so what we're saying is unwrap the unwrap the option and if there's no value which is the or return this instead but it's essentially just by default yep okay so what was the other api we've got bitness which is an enum as well so we're probably going to have to jump back into here maybe i should just pull up the docks instead of jumping around here aimlessly there's fitness okay so yeah we got unknown x32 and also displays that also implements display so we're going to use the exact same trick that we used for our os name and for bitness yep we just do this we don't need the format for this one i don't think because it should be a string already it should be a string yeah i just i don't know why my formatter didn't clean that up but we'll do that all right let's see if we got anything else useful in here you mentioned one more right i think version all right so we've got a version enum uh edition and maybe that's plenty for now yeah okay the fire flash says maybe also full information which is an os info i don't see a full yeah i'm not sure what specifically he's referencing all right so let's see version enum where it oh yeah i think we can the same as bitness we don't really get much more info uh seems to be oh no it's whether it's a rule that's one or whether it's like a 20.10 or a custom it doesn't ever implement it yeah then yeah okay it implements this place so we'll just throw it in and the last one was the addition which is uh just an option string again nice and easy for us to work with so let's add that into so we'll copy two more lines because she's n so we've got type name fitness i've not changed this one yet it was version and edition i should have done that other way because edition is an unwrap or unknown and this one is the enum with a display so we're just going to leave it like so oh red squiggles okay let's see oh okay so because it returns a there's a nice thing for us to cover uh let's talk about that in a second and assuming this is the same so there's multiple types of strings and uh and i'm really bad at typing and talking at the same time yeah there we go so sure what's your problem ah same again okay so yeah there's three different types of string rust so let's cover all of them there's abc which is a string which equals a string from blah blah there is def which is a string which equals a string and then there's another one which we can't i don't think i can just type it out but there's like a os string which he goes on with yeah i could do actually worcester is that oster okay so what's going on here this first one is a compiler level string which will be hard coded into the binary if i don't know if you've ever used the strings command on unix which can analyze a binary pull out all the strings and tell you the things that are inside of it they have a static lifetime which means they live for they're in memory for the entire time the program is run and these are great for things that never change and live inside of the code much like that string right there like you know like i'm not going to modify str it just exists it doesn't think then there's the second type of string which is a kind of trait based string like this where we do modify and it can be changed and it is mutable if we want it to be immutable and we can actually convert these between each other relatively easily in fact i could do into a string or like no yeah and i can do into so there's plenty of functions to help you jump between those districts and then because rust runs on so many different platforms there's a concept of an os string which is very specific to unix or to mac or to windows etc this is when you have input from the cli the terminal et cetera where you actually have to convert it from an os string into an arrow and the red squiggles that we got a minute ago were just me trying to pass in a uppercase string from a static lifetime string now one could argue these never change and i probably shouldn't be using an uppercase string but i'm not going to change the api on the stream so we're going to leave it like this we're going to jump over to our terminal and we're going to bask in the wonderfulness that is our new operating system contact hopefully there we go look at that isn't that wonderful why did we get unknown on name should we have gotten a name there isn't that supposed to be um oh maybe there is no code name yeah maybe that should probably be the os type is the name so that's going to be linux mac etc we'll just run that again too slow and now we have our name macros there's no code name we are 64-bit system with a version and an unknown edition exactly what we were looking for right and just to show what we can now do with this we don't have the predicate syntax that we were talking about but we do have my dot files let's pop them back open within the ginger templating uh yeah and we're going to go args but we'll change this to an echo we'll do args and we can do uh user dot username of it this is the name and then this is just one string so os dot i forgot what we called it name and we'll add yeah i think we have a name and we'll just keep this that keep it happy yeah okay uh we don't need our sudo here let's see if that works i think it should so cargo run dot fails font uh oh yeah we need two views we saw the command printed though there we go it was interpolated in the command itself ah there we go up online yeah yeah two lines up though it was it was there oh and i'm running again oh yeah okay we can see it three different ways now there we go so uh we've now added in your context we're pulling out and this is great right this is a really practical thing for us to add because now these contexts are available and within the gender template and syntax and of course when we have the predicates we can that means that we will have the ability to say only run this command on this system or this business etc that will be really useful for the github releases which i don't think we're going to have time to attempt now but you know if we wanted to pull down a github release we need to know the system and the architecture to get the right binary and now we have an ability to do that yeah cool relatively smooth yeah i was expecting i mean obviously i haven't written tests i'm sorry i'll write tests but uh i i think we should commit this together yeah yeah let's do it so where do i get at google is my pair programmer and uh the fireflash was suggesting if you parse os info into a string it would put all that info into one big string maybe i don't know ah yeah so we can confirm that by taking a look at the os info api so if we take a look at this info here we just want to know if it implements display yeah and it does so we could have that all in one available in the context as well for debugging purposes if available yeah a good idea i'm not getting much help here from gap can i just add co-authored by to the commit yeah okay let's do that okay add os context and get commit command i'm sure there's a nicer way to do this what's your email address on get hit uh sid.palace gmail.com i should switch it to my devops directive one but that works is that correct yeah yeah and hello to francesco welcome i will push this and open our blue okay and you now have your first contribution to come try the first of many i hope cool yeah i can uh what's the the policy on reviews do i need to go review it since you committed it uh we'll let the i haven't added any tests but i will go back and add them before i merge the the pull request and but once that's done we'll we'll get it merged and you'll show up in the contributor list and yeah that's a good day i think i'm happy with it yeah i mean i i've got more time if you want to work on tests now otherwise we could we could wrap up either way either way's fine with me it's up to you i mean i'd be interested to see sort of what what testing in rust looks like if it's not too too tricky to to add and so adding the test won't be tricky um the only thing that will be tricky is no it'll be fine uh let's see it's just because it's multi-os but we'll make it work but let's make sure that our test pass first so we're on cargo test it's going to have to do a compilation with extra symbols and debugging and stuff like that but it won't take too long and there's also you know dev dependencies that are only compiled in certain environments and i think there's 30 tests or something they should all be passing we haven't touched anything there so nothing should be broken which is what i'm hoping for yeah there we go yeah 29 tests now we want to write a test so test and rust are done as modules so and they just live alongside the code in the the main rust files yeah so there's two different ways of structuring this this this would be for unit tests where we would create a module within the file um this config test means that we only compile it and run it in test mode okay uh and it just means our tests are our unit tests are right next to the code that they're testing which is great um and then if we wanted more like acceptance tests or end-to-end tests then we would have a test directory uh out here which would run against the binary and just some other stuff but unit tests tend to live as a module next code that they're our testing we then use another macro called test or an annotation i can't remember attribute whatever rust calls them yeah attributes and then we can define a function so i can i can macros and we are going to need to test this on each of our test targets that we run in ci so we run it on mac we run it on windows and we run it on unix fun thing here is i don't really know what the values are going to be on the other two so i'm not going to know if they pass or fail until we push it to ci or i mean i guess we can always check the code as well so we can do that really because this is just a simple we're just returning some data structure we just want to really make sure that we get the keys that we expect and that on the operating system we get the right value there's no hardcoded things the tests aren't going to be great but they give us a little bit of confidence that we're doing the right thing and then we just want to consume our api so now let's last context equals our struct we then want to get our contacts which will actually be our os context dot what's the function called we can do get prefix why am i not getting auto complete oh because i have to fill in the module all right so that's actually the prefix but we'll move this to its own test and test and super there's just giving me every module in the current file or what is super giving me uh so super is the module above this so test this is actually if we were to imagine we were using this in another file it would be creates context os test super is going to be the os context which is the one above okay so we're just pulling in all the definitions there yeah which is this is pretty idiomatic in rust land and the test just pulling everything from there the actual the module that we want to test i want to test that we get the right prefix so if anyone ever change that the test will fail nice and simple test we're using the assert macro and we're going to say that we get a string of os from our prefix um yeah and we can run this oh yeah i don't have a thing yet copy the slate too okay so we can run this one test we make sure passes underscore oh because you're not using it exactly and i always like to make sure that my tests fail too so modify that again compilation times are fantastic all right cool so that feels i'm happy with that one so i'm going to save that we'll move on and now because i'm running on mac os i think that's the first one we should obviously test but we don't need to pull the prefix again what we will do is get the key value pairs and we can get those from get context and we've got a few assertions that we want to make here so the first one will be that we get i think the string was mac os and this is key value pairs get uh name yep let's see why it's complaining i really wish vs code would show you the adder above all of the documentation uh yes that's just the option uh so we're going to do an unwrap or and we'll do build which will fail i don't want to do unknown because that could be actually returned at some point and was well it's a vector of contact ah okay so we need to change that a little bit so we don't return a vector with a string key and a string value we have multiple different types of things that it could return so really what we're actually checking here is that we get string from name and then on the right hand side we get oh this is this is no trickier than i wanted it to be let's build this assertion again so if i do os name equals key value pairs dot get and we want to get uh it's not a name damn what are we trying to get out there uh so the problem it's not a problem the challenge is uh we have a vector of key value context yep and i guess i could always match against it but we can't like pull an individual one out let's take a look at this this is something that i created so it's an enum where you can either have key value or you can actually return a key that has a list of values [Music] so the best way for me to test that i get the right thing here is actually going to be to enumerate all of the key value pairs uh so we need to create an iterator and then we want to do uh we can either filter to pull out individual ones or we can just build the assertions into a closure so we could do a for each and then this gives us our context here yep and then we have a function where we we're going to have to match on the key and make sure we do the right assertion so we can do match on a contact ah i can't remember this structure now oh it's a tickle okay so zero no context dot zero i have to imagine the type of context i'll get there there we go so now we've got our two different types so now we know what we're dealing with now we know that we're always going to be dealing with key value context here we know that this is now the key value now we can build an assertion here and um if we did get a less context we're going to consider that to be an error for the time being because we don't expect this context provider to return one and the way that i do that is generally just by adding a true false just force it to fail so now we know that we have a key value context and we need to do the right assertion so what i'm going to do here is do another match on the k and this is going to be our key and i'm going to say that if i get a string from name a search eq that's where we want our mac os i hope so and you i think you may have touched on this earlier but the it can mac os within ci there's already some logic that will only test this one against uh mac os and likewise for the linux and likewise for windows yes so okay let me see if i can get this to stop yelling at me first i did a match key why are you complaining expected the triple structural variant feminine association uh what is key string all right i'll do a slightly less nicer way for the time being so we'll say f k equals name then a star i generally try and avoid f expressions but i'm not sure what i got wrong there so we'll just do it this way for a moment let's even get it to pass see if that's happy all right almost and no it's just because it's a reference cool i wonder if that's why the match was failing actually curiosity i need to know so reference no reference must be close ah okay we'll just put it back oh i've never lost my ear i've gone the wrong way uh okay so if we get a name i don't like this f but i'm not i'll fix it later i'd rather talk about the macros to match the test on the right platform so if the value is a reference string from mac mac os okay so we're doing a test if we get a key values pair this is one of the ones we expect let's just do another one and so we also have what was our context outputting uh bitness version edition what was the edition do you remember i was unknown yeah yeah i guess it's safe to assume the 64-bit is always going to be the bitness i don't know if m1s are going to do something different uh i mean if a raspberry pi uh you might have a 32-bit right yeah but this is on mac right now oh yeah sorry so hopefully we can get away with that and if i will make us fail just for a minute right so i always like to see my test fail but if i remember correctly this this had a space yeah so we want we only want this to run on a mac uh crap can i target max we're going to find that so let's look at the let's run the test get ahead of myself oh let's compile that okay tessense failed which is what we wanted to see and we can see here left and right don't match because of the space and where is our bitness you're running 65-bit mac os oh no because they're a certain does it exit before as soon as you fail one did it quit or is so in a test framework this a cert macro will do a panic and it will stop that test case as the other ones won't be done so now we can run this again we should see it fail for the 65 bit versus 64. i'm feeling confident so i'm just going to change this already i won't hit save yet there we go save and validate this and we'll run it one more time we should see our test passing and we have an unused variable here so let's get that removed um it's in my modules test there we go and testpass that's one now we can copy this and to windows what we want to say here is that we expect i have no idea i'm gonna ci tell me what that's supposed to be and for unix we'll do this uh our tests run on let's check that main.yaml i'm pretty sure it is ubuntu up into 2004 again i don't know what these are going to be exactly but i'll tweak as needed we now need an additional test macro here which just says only run this on unix we can do windows and i don't actually know if i can restrict that i might have to like add a conditional and the test actually query os type and make sure but we can check rust test config mac os and see if there's anything uh target os maybe that's exactly what we need whoa all right i'll just use the taper uh config target i get all complete on this no all right all right i'll look into that i don't know what we can do is a let os equals info get and then say if where and we want west type oh it's an enum he's hacky don't do this oh yeah i just need to yeah this is this is horrible but we're using the the package in the test well yeah i mean we're not testing this one so it's okay but yeah yeah i i'm positive there will be uh something from the rust compilation conflict framework that i can target just mac but for now we'll do this and theory i'm hoping i can run um cargo test here and then we'll push that i'll let ci do its thing it takes around 12 minutes that'll get me my windows values my linux values and then we have some degree of confidence that our create is doing what we want um now the unix one uh that's also gonna need us because mac counts as unix so they're targeting here that you can see from the language server protocol my windows test is great it's not gonna run on this architecture the unix one does because mac counts as that so we will drop this then and just do another horrible horrible piece of code where we say that os dot os type uh equals and we actually want linux for this test and hopefully all my tests pass on my mac and then we'll let ci do the rest good great add os context and we'll drop that corporally back in i would make you watch the the 12 minutes but you know you can obviously subscribe to this pr you can keep an eye on it we can get it merged and then we have some tests added to that so awesome what's your thoughts on russ then now you've kind of walked through this with me yeah i mean i it it reminds me of moving from javascript to typescript where like there's a little bit of pain up front where you got to get all your types working properly and it'll it'll whine at you but then once you have everything configured the ability to then automatically tell you when there's something wrong and help you when there's something wrong uh seems seems pretty powerful awesome and any sports don't come try out do you think it's something that you will use or is there any features that you would like to see added to it yeah i think so i mean i often when i have little configuration snippets that i need to run i just throw them in a make file and then run i can run one-off uh targets and so i think it's sort of a more holistic mature uh capability that will work cross-platform i know a lot of my viewers get mad when they see a make file and they're like i'm on windows what do i do and i say code use wsl um and so it could potentially be a solution there where uh cross-platform allowing people to use it on on whatever system they're on so yeah i think i think it's definitely a cool project awesome appreciate it yeah well thanks so much for coming on i was it was very informative for me i think uh we had some help from the the crowd as well so thanks for people who are tuning in and helping us debug our typos and everyone should definitely check out david's channel raw code if you're into devops and kubernetes uh and go check out the come try a project on github as well yeah any final words uh just you know i i hope that the goals of contraia align with with you know the people that are watching that are like okay that's that's what i want from configuration management and i hope that we can get more people contributing to adding more actions and and atoms and just that bell's now a really cool tool that will run anywhere and and help people i don't know like i think format in your operating system regularly is just a good habit to get in and trying to reduce the friction or the time to get productive again is important to me and hopefully others so come and help awesome yeah go get involved people all right take care all right have a great day thank you sid
Info
Channel: DevOps Directive
Views: 396
Rating: undefined out of 5
Keywords:
Id: KGqT7Kx616w
Channel Id: undefined
Length: 100min 21sec (6021 seconds)
Published: Tue May 25 2021
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.