 Yeah, we'll give people a couple minutes to come in before we get started. In the meantime, you can add yourself to the attendees on the agenda that I just posted in chat. All right, it looks like we have quite a few people so we can get started. Hello everyone, this is the air gap to a working group from CNCFC gap delivery Friday, May 15. Our agenda is posted in chat, feel free to add yourself as attendee. Today we have a demo from Carolyn from Microsoft for CNAB and Porter. So I'll let her take over and in just a few minutes. But before that, I just wanted to see if anyone had any other announcements or parking lot items for after the demo to discuss in today's meeting. Great. Well, Carolyn, I see you here so feel free to take over a final note that this meeting is recorded so don't say anything you don't want on the internet forever. And with that, Carolyn, it's all yours. I'm Carolyn fans like I work on the data slabs team under the Azure group of Microsoft. And I've been working for a while on something called cloud native application bundles, which delightfully shortens the CNAB. And specifically I've been working on the implementation of that so CNAB specification. There's a couple different implementations of that you may have heard of Docker app is one and another one is called Porter. And I wanted to show this to you today and it's kind of relevant to your group, because it understands how to work with your gap networks. You will see my screen. Okay. Okay. So, I, I know, I don't know how much time we have for the demo, but I just want to explain at a really high level what CNAB and Porter like, I'm going to kind of use them a little synomously but not quite the same but you do. And it takes everything that you need to deploy your application and puts it in a bundle and allows you to version it and be able to distribute it using OCI registries Docker registries and be able to bring it over air gaps for example, and be able to work with it using a single command. So even if inside your bundle, you may have many different tools. Maybe you're using Docker inside your bundle, maybe using Helm Terraform, maybe cloud specific tools like you're using GCE or you're using AWS Azure or something like that you're using a whole bunch of different scripts. You're able to work with your application's deployment as a logical unit and be able to put all the logic for managing not only the deployment like the installation, but upgrade, maybe discreet actions that you do on that deployment, like doing a dump of logs or like database dumps, things like that, checking the status and the health of your system, anything like it'll run any command, it'll do anything, it's whatever you put inside of it, it's just a packaging system with versioning and security and things like that. And it allows you to work with it as a single unit. So what I wanted to show specifically was how to take a bundle that already exists and it references things on a network, you know, references things in Docker Hub, for example, and then be able to move that bundle over an air gap and then be able to rehydrate it and then use it again. So this is an example of a Porter bundle. Use this gamble. Maybe you're happy, maybe you're sad. And so this defines my bundle that I made just for y'all called whale gap. And it sneaks a whale size bundle through an air gap. And it's designed to be published, like I said to an OCR registry. So this is set up by default to publish to Docker Hub here it goes to get Porter whale gap, and its version so this is set to be zero one auto. And I'm going to skip over some of this stuff and just kind of go to the meat of what is this bundle do. This bundle has, because like bundles by itself just pack a junior unit. So what's inside of it inside of it, I've put Helen. You use anything inside your bundle. You don't have to use it's not tied to Kubernetes whatsoever. But I decide to use home. And it's heavily templated. So I'm deploying a chart that I made called whale gap. And my charts right here on my file system. And it has a couple parameters that I'm passing in through my bundle itself and that's something that's kind of built into CNAM is the ability to pass to the bundle. I'd like as a user I could pass a parameter to it and then it can make it all the way through into the bundle so I can alter what it's doing when it's doing the installation. And the other thing you know is how needs a cube config file, it needs a credential. So that's the other thing I've done is I've defined that my bundle is going to need when it's installed a cube config file and it says where we're going to find it. So, it's going to install this whale gap thing. And then it also knows how to upgrade will get and knows how to uninstall it. I could have had a whole bunch more but we're trying to keep it really small for the demo here. Um, a quick dumb question. Of course no dumb questions. So when you say helm, is it assuming that the helm binary is on the disk similar to the, the keep config file and keep controllers there or do you bundle up with it. Yeah, so that was the next thing is so porter and bundles itself bundles bring everything you need in order to install your application inside of itself. Right now, like a bundle can have multiple different runtimes. But at the moment, it's just Docker containers. So a bundle has two components to it. It has a definition of what the bundle is. So I said there's YAML but it actually comes down to this this is CNAB right now like you saw Porter before this is CNAB. And this is the definition of what the bundle is. But the other part of what makes a bundle is the Docker file, the invocation image essentially is the installer that goes with it. It's considered a utility Docker container that has helm, it has cube CTL, it has certificates that you may need scripts, the charts file, like all my files anything else that I may have to do my installation all get shoved into this container here. So this is a generated Docker file Porter generates it. Part of CNAB generation is not that's I meant like CNAB is one thing Porter is another, but so Porter generated this Docker file for you, just based on the fact that you said mix and helm. If you'd wanted to like make an artisanal Docker file, like more power to you, but so it made it for you and installed helm anywhere to get it, you could have told it which version you wanted it can auto detect what you're using and get one for you. But also put on cube CTL to it needs it just for a couple extra things. And it will also copy all the files that are on your in your directory. So it automatically brought in the charts that you had. So helping to question. Yeah, that's perfect. Thanks. Yeah, okay. So the idea with bundles in general is that literally everything you need to run it is right there. So as long as you have a CNAB tool. So it could be there's a couple out there they said Docker app, there's Porter, there's duffel they all know how to run these there they work because there's a spark they work for all of them, as long as you have one of those tools on your phone system. And you have the runtime. In this case it's Docker. You have everything you need to run a bundle no matter what's inside that bundle. So I have a quick question so the mix ins here so helm is a built in mix in for Porter that. Yeah, it is anyone can make a mix and you know we've made a bunch that are like, obvious. Like we could have Kubernetes we could have Docker compose is a new one. There's a terraform. Ansible. I don't have ansible. Yeah, that'd be a cool one to have. Um, so no one can make them. It's just a binary that understands how to talk on standard and standard out. Actually, there is an ansible mix in that somebody else has contributed. Sorry. There is an ansible mix in that someone else has contributed it's just not in the standard location. Oh really. Mm hmm. Do we have it listed in our little search yet. I'm quite sure we don't, but I know where it is and we'll wire it up. I had that for me Ralph, that'd be great. Betcha. Yeah. Yeah, so anyone can make one. There's no such thing as like an official one or not official one. If it, if it's on your file system, it'll work. Basically the mix in though as a kind of a client side or build time plug in then. And then at the runtime inside the Docker image that gets generated and you don't have to worry about the mix in it anymore because that's all built in. It kind of sucks it in I guess. Yeah. Yeah. Yeah. Yeah. There's two levels of mix in, actually. There's two binaries for every mix in. There's a client side, which understands, for example, Darwin Linux Mac. And it understands how to do things like. Injecting these lines into your Docker file. Because it knows like this is what it takes to get helm inside of a Docker file. And you still need that helm binary, the mix in binary mix and acts as an adapter between understanding CNAB. Because there's, there's some templating going on. There's some environment variables or things that are specific to the specification going on inside of this. This Docker container. And then it then handles making calls, maybe to a command line tool, potentially to an endpoint, like maybe it's talking directly to a cloud provider, or it could be doing something just as like I've made a mix in that just prints things to the terminal, like to the console. It could do anything actually. So there's always two pieces to it. A client side, like a build time and a runtime. Got it. And that's a, that's a porter specific thing. Not a CNAB thing. It just kind of helps you make a bundle quickly using existing tools out there. Otherwise, you could, you could make a bundle just by writing a, like a really big bash script. But the nice thing about porter, like the reason why we did it this way is it gives you a lot of inspectible metadata that you could use to enforce or do quick find replace and, and kind of set policy and things like that. It's more fun to work with this way, instead of having to like reinvent the wheel over and over again. It has a lot of built in air handling and kind of smarts understanding how bundles work and more desired state configuration as opposed to maybe commands that it's fine to fail versus if I'm going to mash upgrade over and over and over again until it works. Maybe you want it to work a little bit differently inside a bundle versus as an imperative tool. So Sean was asking a good question. So do the mix ins for install and upgrade need to be the same kind. Same technology. I'm sorry. The mix ins for install and upgrade need to be the same. So do you have to use helm for both of them. In this case, you could use Kubernetes for the, like, delete or something or sure. Yeah, okay. You have full control over everything that happens under install or upgrade. Porter has no opinion. Porter at its heart is like a workflow execution engine. And it'll just do whatever is in the animal. It has a couple of linters to make sure that you don't really shoot yourself in the foot, but it doesn't understand what helm is, for example, it doesn't have Kubernetes. Right. So these verbs like install and upgrade those are those are Porter specific verbs those are, those are specific to CNAP actually CNAP understands what install upgrade and uninstall is. You can also define your own custom ones like you could make one called status. If I had my indenting right, you can make one called status and you could do like a home command here. Or you could just, you could just go into bash, for example, and start doing your own things. I wanted to create a backup operator or something like that I could create a backup. You could do your own things from here. And then you could then just call these commands yourself. The idea behind CNAP is extremely flexible. It's whatever you need to be able to do. There's very little. There's absolutely no opinion about what you have to do or understanding about what any of the tools are inside of your bundle. Cool. Yeah. So I want to talk a little bit about the air gap part about this because one thing I'm doing here that you don't always see with helm is I'm passing in some extra parameters and set parameters here. I'm giving it very specifically what repository and what digest to use when I do my home install. And that's for a very particular reason when I move my bundle across the air gap. I won't have access to Docker hub anymore. I'm going to have to be able to install by pointing to a repository. A registry like that's on the other side of the air gap so I need to be able to swap that out. So when you're writing like how has one way of doing this depending on what you're using like some other technology needs some other way to do this little switcheroo. So that's how I'm handling this with home. Now has built in the concept though that for images, you need to be able to do this switcheroo of being able to copy images from one registry to another and it has this baked in called image relocation mapping. So in the images section, I can give like a tag to my image. And so my image is called will say D here. And I say it's a Docker image, and it's originally coming from Carolyn vs will say D and here's the digest and I'm using digest. Because I don't trust tags tags can be forced pushed and from one day to the next right. I could be getting different content. I don't want that. Can you also add the tag for like documentation purposes. I could use the tag. Um, like as a comment, I guess. Porter supports just putting a tag in and will resolve the digest for you. But at the spec level it just supports the digest. So what this lets me do is that when I put this in here. When I make the bundle. It will put this image it'll grab it from the the registry and actually put it inside the bundle to so the whole things portable so let's take a look and see what that that actually looks like so. When I run Porter I have this command archive. And I want to make. There's different ways to work with bundles I'm showing you a way called stick bundle. This is the normal way, but this is the air gap way. So I'm going to make will gap. And when you archive it, it just makes. And I am going to get it from the registry where this is pushed. So is that get Porter will gap. Zero one that's that zero. Okay. And I'm not going to have this command because this is a demo and it actually takes a little bit of time because it's 500 megabytes. So it's right here actually will gap TGZ. Okay, so let me copy this over somewhere. So let's move this over to town broke record. Let's just take a look at this and see what it looks like. Oh, let's make my direct inverse. So, let's see what gets put inside of this stick bundle. So first, this is the senior part. So the definition of the bundle. Okay. And again, this is just the translation of everything that was in that animal file to the standard spec format and has everything about it like the credentials, the parameters, a description and it also has a listing of what images are used inside of this bundle like this is what we were just looking at a minute ago. The other piece that's in this zip follow is a listing of all the different like a manifest sorry of all the different images that are contained here. And we have two different images. One is invocation image or the installer for the bundle. Okay, and this is something that's always present with any bundle. And as you can see it originally came from Docker hub, right, this is where I had published it from and when I archived it that's where I pulled it from. But the other thing it has is remember I had that images section inside my bundle. So because of that when I archived it. It also pulled down the image I was using inside my bundle so that I'd be able to bring it over the air gap. And it said okay I'm you're using Karen will say D in this specific digest. So then in these blogs are actually all the layers of all the Docker images I'm using, and this lets me move it across the air gap, and then we publish it somewhere else to another registry. So is there a way to mirror a bundle to from one registry to another rather than having to copy it to a TGZ and as an intermediary. Yeah, yeah, um there's a copy command. So I could have done Porter copy, and then given it two different tags. And it'll actually just shuffle them over. So I could rename it from one to the other so I do. I can give it a source in the destination is over asking about. Yep. Okay. Yeah, it'll just rename it and bring everything over and everything is referencing from one to the other. So, I'm trying to figure out how do you so one of the problem one of the things I was going to devil next because something called scope your words were. Yeah, all lamenting on the portability of digests. So you you basically what you said earlier was the digest is a parameter, the digest is parameterized. And so is the image name. And so I'm assuming that you either you must be updating those because the digest is changing. Yeah. Okay, that's why we're injecting both. Yeah, okay. Yeah. Can I just add something real quick conversation. Technically, we rely on the fact that between on the same registry the content digest should not change if you push the same content. But we do have the option for the user to accept the fact that if the digest changes, the actual digest of the whole bundle is going to change and essentially it's going to be a different content if if something changed in your bundle so essentially, by default, if any digest is different. This is going to error out and tell you that something is different in the bundle you can choose to override that and it will generate a different bundle. Does that answer the question. Yeah, I think so. Well, the art is that you can copy bundles across any compliant registry. And if the content digest is the same for every single image in your bundle, the content digest of the bundle is going to stay the same. So do you require then scheme it to be to images, I assume. Sorry, sorry. You require them schema to be to images like the doctor images to make sure that like when I'm pushing between registries that the shop doesn't change. I'm in trouble with v1. I just tried that yesterday. And it wasn't working. That might be why I had to make a new image with v2 and order to get it to work. Yeah, no, I just wondering if that was a constraint. Yeah, I don't know if it was an intentional constraint, but it doesn't work. Because I found a wonderful image that used Wales. It was like four years old and like perfect. I'll use it and then it's gonna work. So I had to make a new one to get my Wales on. So is this multi architecture enabled. So can I have fat manifest for the Porter images and have different architecture groups for that, or do they have to be tagged independently. Trying to think about that. I know that Porter right now is specific to one architecture because we've had no tasks for anything other than one architecture. Do you know when pushing the bundle to a registry, architecture is taken into account. So it's generated in the bundle you can specify an index that points to a multi arch image. I'm not exactly sure if that front time that's hooked up yet, but technically it should support it. Yeah. So basically if you're going to do a copy then you're going to probably just you're gonna have to do a copy multiple times for each architecture and it probably doesn't do a recruiter, you know, full tree copy of all the architectures I'm imagining. That's kind of the default behavior of a lot of tools. I'm just curious they don't have the answer right now. Which is the default behavior there. The full copy tree for multi arch or just one most. Yeah, most tools ignore they like if you look for you, you get a fat manifest back or manifest index. It'll go ahead and grab the architecture of your Docker demon. And then it'll just grab that one and move that across specifically the tool that pushes a bundle to an OCI registry is multi architecture enabled. So it will copy all architectures of an image across registries if they're present. But I'm not sure about the runtime bits. Yeah, that's the question is a word's kind of stumped on the runtime. I have to maybe look it up and get back to you. It's not a question of like do not want to support it is this question of like, did it get coded. Yeah, I would expect it to work properly on all our architectures in the future, whether it does now or not is a great question we should test it. Some I unrelated question. Do you preserve the original layers of the images you're pulling in when you're generating the bundle itself. As in, like if I have, if I have the you know 20 bundles and they all have the same exact like, you know, three images or you know whatever. At the bundle level. Do I get that the merging of those layers or will it differentiate because they're pulled in separately, you know. I guess it's for me it's you know, right now our Docker images when we pulled them off into like a tarball the transfer air gap and ends up being to be terrified because we don't achieve any you know, we minify until we, you know, rehydrate I guess and so from a bundling perspective, if we can bundle, and, you know, and we're, we're achieving something similar. I'm, I worry about, then now we're saving at that same Docker image 20 times instead of once when we, you know, when we pull it over. Are you, you're talking about like so if two different images share a certain subset of layers. Are we getting multiple copies of those layers. Well, so, well, I guess. Yeah, yeah, I guess well it'd be more yeah like if you're if I'm taking let's say you know alpine into two different bundles. And then the bundle itself turns into an OCI compliant, you know, image or whatever. If I push that into, you know, V2 registry are the images are the layers from that alpine dedupt, or because it's been bundled, it gets, you know, gets kind of messed up and so they have different layers and therefore I don't achieve, you know, so that alpine is essentially taking double space because it's wrapped in bundle. We preserve the original layers. Take a look here. These are the layers that came out of the registry and we don't alter them. Yeah, since you're not putting them in subdirectories for each image, you're naturally going to use the same cached layer right if it's already there I assume. Yeah. The assumption though is that when you've archived the bundle, you're ready to distribute it to the air gap environment so you're not as much what at least the current thinking is that the moment you archive it is prior to using it. If you want to move a large number of bundles between two different environments, then you might want to look into running a registry in your private environment and pushing. Yeah, and that's, yeah, that's what I guess I'm asking. So we do run the registry. So when I, when I carry all those bundles over, and I pushed all the bundles to a registry, do I get that, that layer advantage? Yeah, that's a good question. When you push the bundle to an OTI registry, we just copy images. So if the layers are there or if even complete images are already in the registry, we don't copy them anymore. Yeah. Okay, so the image layers are at the same level as the bundle layers is I guess the question. Yep. Technology wise, you know, layers are portable between Docker registries. It's just the manifests, the top benefits for them that are. Right. Yeah, I guess I was just wondering if the layers for the images were being like, you know, they're embedded into the bundle until they're lost is I guess what the question was. Yeah, flattened. Yeah. This ties into how our bundle is represented in an OTI registry, which I will not get into very much detail, but is an OTI index, ultimately, and it points to multiple artifacts. Gotcha. Yeah, it's not something specific. So like I think most are all of the layers already here. So if I try to do this, it should go pretty quick because all the layers are there. Yeah. See, it instead of taking like really long time because I said it was 500 megabytes. It went really quick because the layers were there recognize it and then all I had to push like one thing. So then also from a holistic standpoint like from a higher level standpoint it's really easy to realize that when you decide you're going to drag a whole bunch of layers across an air gap. The package is going to be big. You don't have a way to avoid that. So you need to. Oh, for sure. It's on the, it's, it's the transport layer that's, that's the big thing. And once you jump into the registry, you get the basic registry behavior that you see. Right. So if you have a bastion server, you won't have that problem because you can just do a copy. Yeah. Yeah, but I guess from a bundling perspective, you, you're, you're transferring it's significant more amount of data if two bundles share the same image because they've been tarred separately, right? Yes. You know, Yeah. I don't want to just complete the last little. Yeah, sorry. Yeah. How to kind of switch a room works when we come across the area. So I did the publish here. And so previously I was on that other registry. I can't really do a full like isolated network here because I'm going to you online. Let's move it to another registry. Okay. And I have a Kubernetes cluster here. That's pointed to use this registry. And so I'd like to do then is do a quarter install. And I'd like to give it my creds. I've just already pointed to use this credential as my cluster. And then I want to install this bundle. Oh, that's real. Without saying that was going to happen. Let's say that to me. No, it's just the demo gods. I'll make you work. Oh, I know what happens. Sorry about that. It really helps if you say that you're installing a tag. There you go. Let's try that again. Okay. Okay. Now, now, now that having messed it up and then putting the tags that you it's making it obvious that it works. This is where we want to highlight here is that we did the switcheroo. Okay, we told it what the new digest was when we did the helm install, and we also told it this is the new repository we want to use. So that it's not pointing anymore to Docker hub. It's grabbing it off of the new registry on the other side of the air gap. And I just want to prove it to you. So let's take a look at the pod that it's spun up. Okay, so let's do it. Let's take a look at this. And we can see. When you publish this Porter image to your local repo, it injected the new digests as it discovered them. No, never mind. They're, they're embedded. Yeah, they're embedded in that archive, right? Yeah. And when I ran that publish command, Porter publish, if we do a little bit scrolling here. I ran Porter publish. And what it did is it went through every single one of those those blobs right and went through the manifest. And it went here are the images that are inside of this, this zip file. And then it published those to the registry on the other side. So it grabbed it went through all the different layers reassembled it made an image and pushed it all back up. All right, so it's preserving the manifest then and so it is preserving the digest then. Digests are specific to the registry. No, it, if, if, okay, if, if, if the registry is OCI compliant, they should preserve the digests. And in this case it's, I think it's Azure Container Registry which does preserve between Docker Hub and ACR they're both OCI compliant in this case. And most of the time, all most registries strive to, towards keeping the digest. So I think in this case they're actually preserved the image digests. Okay. So anyway, the install process is what's actually pushing the images into that registry, so they can be consumed by the cluster. Be pulled. The pay off here. The publish install just tells just tells helm to tell Kubernetes to pull them. I thought you just said publish only published the porter image but you're saying it's also publishing the embedded images. It's everything that's used by your application so it includes the application image. They get translated to the same like namespaces and all that kind of whatever paths path components were in the image names. Yep. Okay. Yeah, that's where the relocation map that Carolyn was mentioning. Yeah, I got it. Okay. So just to prove to you that it actually worked. We have a functioning whale gap on the other side. Let's come over here. Take a look at it. And this is working. Yay. Yeah, it did. It did rename it. So previously it was called my image. That was running. My image was called. Carolyn vs will gap. And so now it's get Porter Azure acr will gap. So it did rename it. It took like the registry swapped out the registry's names but then preserved the final path part. Yeah, so basically someone's going to build a mix in their technology is going to have to have basically top down awareness of all the image references so it can do this proper translation then. So it's going to have to publish all of their images as values. So the mix and didn't need to understand this. The templating handled subbing this in. So the mix and just needed a way to accept the templated values. So helm was pretty easy because it had set right and it just allowed me to insert repository digest. Depending on what else it is you're trying to do it. I'm just saying you have to have both right so your back end technology has to be built in such a way to accept those as parameters. Yes, and the mix and has to be able to accept those parameters and pass them on. Correct. Yeah, you need to be able to wait up to send these through all the way. Yep. Yeah. It would be really great. If mix ins could understand what was being used and be able to help report this back to Porter so that you're not having to fill this out by hand. But you know with helm it's kind of like, you know, this information could have been anywhere. So you kind of have to type it in yourself, but you kind of dictate the fact that the repository and the digest or the tag I'll have to be an independent fields they can't just be one field and parse style or anything like that. It's separate because of how the chart was written. Okay. So if I take a look at my chart real quick, and I go to my templates deployment here. I want to figure out where they relate where the where the magic is for the automatic where the API. Yeah, this wasn't magic it was just it just had to do with like, this was how the chart was written. It had it split into a repository and a digest. If it was a single value that I could have put in like if I go look at the values here. If it had been just a single thing, then I could have done a single thing, but most charts have it done this way instead so you can easily swap out just the version used, you know just the tag. Honestly, most charts are written by tag instead of digest to which is problematic but yeah I've yeah we've just gone done an entire rewrite of all of our software to not do that anymore we're just doing an image ref. And that actually was one of my questions, do you have to use digest in this in this regard like, do we have to basically go back and change all of our things to use the tags or will it preserve the tags. You could have done this. Okay, you could have done that. And Porter would have figured it out for you. You just lose the extra assurance. It may have been forced pushed. Right, it doesn't take the tags with the manifest when you grab a digest. So what what portal do here is it will at build time when you build the bundle. It will resolve this tag to the digest. And then when it builds the bundle. Because everything turns into a bundle at the end of the day. It has to be resolved to a content digest so it'll make it an immutable digest for you, right. Right. Yeah, so it's easy to get the tag right but when I so you so when I so when I when I re hydrate this in my air gap environment is the why does it does it add the tag to the upstream registry or not. No. So then my home chart would fail because it would need it would need to digest instead of a tag. The home chart wouldn't fail because it still would have this tag. Oh, yeah, I see what you're saying. That's a really good point then it's a rather easy fix on when we're pushing the bundle. Yeah, you have to tag it with something though don't you. Otherwise, they're both summer registries will just leave it if they're untagged. So this is a reference the no CI index after you pushed it. But it's not not not of the tag form that the original repository had it. And so, the real. So this is a great thing to point out, sort of at the stage we're at right now. The expectation is that if you're pulling something from online across an air gap that you're doing that with some desire to have confidence it's precisely the same artifact. And so the original implementation is based on digest because that's the only way we can give you any kind of verification or validation that you're really installing precisely the same thing that you had an online environment. They don't give you that help. They're just they just don't give you enough confidence, but alternatively, you know you could, we could actually, you know, you could re tag them. But we're expecting that sort of least at least in the current situation we're sort of expecting that the bundle owner would actually understand that because you have to sort of build it a certain way to make it a thick bundle. The owner would understand that modifying the chart inside the bundle to accept digest would probably be part of their workload and their workflow. Where my concern is is this is a huge issue we've had in general is many many operators will hard code tags into go code that especially if they're helpers like you know I need busy box 1.2.8 or 1.2.8 and it's hard coded because that's the helper and who doesn't have busy box and so they don't allow you override that you can override a lot of the other ones but if that tag you know image doesn't exist. It doesn't have it's like you know I need to do a bash script or whatever and so that's an issue we've we've ran into a lot. They actually had opened up a bunch of PRs but it just you know it's something that it's a bunch of extra work if you know that sounds horrible and if you have individual people that I need to go beat up to do the right thing. Like that sounds just awful. They usually give you the ability to change the registry but not the tag or digest. But we've even well often it'll just say you know busy box with no registry and it assumes that it resolves and we've solved that using you know we use container D and we do mirrors so like you know docker.io and whatever it goes to our registry so. Yeah handle it that way and we also you know turned off force pushing on our registries you know in in our in our environment so we have some resemblance of you know it hasn't been force push but yeah it's it's not perfect but it's just you know it's more. I'm just trying to understand like we can't adopt this until we basically go all in with digest is what it sounds like. That's a really good point yeah and it just we've never actually had the requirement for a digest for the pushed images for the relocated images until now so it's a rather easy fix on on our side when pushing. It's a large change, honestly, to add the tag. No and an earlier version of the pushing functionality actually tagged images was just didn't port it over because no one actually needed it until now so thanks for pointing that out. Yeah. I have a quick question. I think you mentioned something when you showed the bundle.json that that was. Is that the that's the actual spec that CNAB conforms to and Porter creates that is that what I'm saying is that I'm saying so when you said that at the spec level it only supports digest that's what you that's what we're kind of talking about here is. Yeah, you can do a bunch of stuff with tags, but this spec in this bundle JSON doesn't have any ability to do anything with tags is that okay. Yeah, thank you. Porter Porter has a tag there, and then it resolves the content guide us for you and then that's what it's using to fill us in. But because we don't have this. This is what we want to add. And so this probably means that if I'm using a different implementation I think it's like duffel or one of the other ones that I could only expect to use digest right like. Cool. It's the only way of making sure you're running the same. Yeah, yeah, yeah. Yeah. Stop trying to auto complete for me. There we go. Yeah. It's a great conversation because I say it's very interesting to hear the problems that you run into such that we can think about how to handle. That's all I had to show by the way I know we didn't really touch much on like how CNAB works in general but I hope we filled in enough of the blanks that you see how the air gap scenario works. I mean, I think this has been awesome and I really appreciate it. Do you mean could do you know enough to give it a quick run down like Porter versus the competition like you know what you know how do you, what, what did you guys, you know, what's your, you know, interpretation of the spec versus others and, and how there's differences. So, like I said, there's there's three public implementations right now. There's duffel, which is the, it's the reference implementation of the specification. So that means that it's, it's not really, it's more intended to vet the spec and not really intended to be like a, it's not really actively developed. I'll put it that way. Rado, you can check me if I'm wrong. People work on it when we're changing the spec. You know what I mean. And then we'll make changes and make sure that it supports the spec. But beyond that there isn't ongoing development on it. And the way duffel works is you edit the Docker file yourself, see whatever you need inside of that installer invocation image you put in there. And then you're given a bash script, a run script, and whatever you put in there. That's what it'll do. And that's just running install upgrade or uninstall or custom action. But there isn't any, like auto magic, or like building blocks, like Porter or Docker app. But at the same time, like there's since there's no opinion you can do whatever you want. The other one is Docker app, which is very similar to Docker compose basically. It's more focused on the deployment of services that were already defined using Docker compose. And then so it conforms to the spec and everything, but deploying infrastructure isn't really, it's not really focused on that. So deploying. For example, like, say like an S3 bucket. And then what it's intended for. I'm not even sure if you could do that to be honest with Docker app. Someone fact check me there. Right. Ralph. That's not what it's not really good strengths. Right. Awesome. So then, then there's Porter and Porter is really built around being able to reuse and adapt existing DevOps tools and existing tools that we use to do everything. And it's essentially like a set of workflow execution engine to be able to plug them all together and adapt them so that you can pass inputs like parameters and credentials and outputs between them. So if one step with an install created a cube config, you can pass along to the next one or maybe it made a database connection stream. It's basically allows you to pass information between them and kind of string together a series of steps between all your different tools that probably weren't meant to work together. And hopefully make something a little bit easier to manage and deal with error conditions edge cases and make something a little more robust than a monolithic bash script. And that's kind of the intent is that instead of making something that replaces or is a giant wrapper script around, like how in terraform and QB CTL, it gives you a little bit more easier ways to work with them. I think you said that's very actively developed because I have paid to work on it. So I think you said at this in the beginning I want to make sure so I think the porter executable the client tool that does use Docker directly right so you have to have Docker installed because it interacts with that. Um, it needs to be able to connect to a Docker connection either. So he's a local Docker socket, or it needs to connect to a remote one. So for example, we run Porter in Azure cloud shell. And at that point it's a remote Docker engine that we connect to. Okay, and is it have to be Docker is any. It's a would I guess would podman work is the question. It just needs to be OCI. Sorry, I say Docker when I should say I just want to clarify. And so I guess my next question is if I don't want to take everyone's time so does anyone have questions because I've asked a lot. Okay, cool. So is there any concept of like, so well so when you when you deploy a bundle. Does it have any like chaining or is there any dependency management with it of select one of our we wrote an internal tool right because we essentially need is to you installed pretty early on because it has a mutating And if you don't have the mutating web book before you install things, nothing is mutated. Does portal bundles have any kind of concept of that or not really. Yeah, yeah. Um, so we have the only one that implements it is Porter at the moment. We have a beginning of a spec for dependencies in the scene of a spec. And so Porter let's you specify one level deep, who you're depending on. So my canonical example is I have a WordPress bundle, and I depend on my my SQL bundle, for example. I will run the my SQL bundle first and then pass outputs up to the WordPress bundle because it needs that connection string, you know, and then it will then use that and then tie them together and then you can work with them as a unit. I'm going to bring that to more mature level. So it's in the next over the summer, we're going to be working to really bring more scenarios to the dependency spot being able to have more level and able to order your dependencies and you know, to satisfy dependencies from something that we say installed weeks ago and things like that. There's a little bit of work we need to do. That's happening right now to be able to enable these scenarios but yes. Sorry, long answer. Yes. I'm interested by the way Porter is for contributors, or just people who have ideas like everything you're seeing right now is super exciting for me. And if you want to hop on our slack work in CF slack, or you just want to like open an issue and drop ideas or leave comments. If you really want feedback, or I don't know anything any engagement would be amazing because I don't know you're all you're doing the things that we're really interested in learning more about. Yeah, so just one more time I have to ask a dumb question that may be missed at the beginning, the relationship of part of the seed nav is the same team that's essentially working on two independently, or different people completely. So, my team helped start found something, pick a verb, the CNAP specification, but it was collaborative between a whole bunch of different companies and a number of people on my team are maintainers for the CNAP specification myself included. And then I'm like found crater of Porter. Um, so, okay, there's really in the CNAP and making bundles Porter just exists to be an implementation of CNAP, essentially. Okay, so I wrote my competing version of this. You know, but I had to do it at the same time CNAP came out, though it wasn't quite ready for the scenarios we had. So it's interesting because you and I have taken different angles. Okay, so mine's mine's called the case specification called application. Whatever it man stands for container applications for enterprises. Anyway, so it's out there and get to but it has a whole different perspective and how what the opinionated parts and the unappreciated unappreciated parts are. So, yeah, it's interesting, you know, it's like an 80% overlap maybe. Let's take a look at this more closely again. Yeah, I, I think this is an area that really does need a lot more innovation and people just using it, trying it in different environments and production and seeing what really works when like you meet reality, if that makes sense. And it's definitely like this is v1. I think v2 will look very different. Speaking of things people should be using I just want to point out that there's also a security spec that we are actively working on so if you're interested in that part. We're going to get with the tough and in total upstream specifications and we're working on having working implementations for both of these. So just, if you're interested in this, feel free to ping us in the CNAP channel, or tough or in total channels. For the purposes of air gap right you should probably describe just the high level set of features that come even to air gap environments. I'm not exactly sure whether we have the time for that or not that's why I just wanted to briefly point it out. If we do have the time I'm happy to. Basically, you can do supply chain signing, and then bring that metadata along with you. And if you have the right access to the original metadata server you can you can validate the supply chain and arbitrary. Yeah, essentially there's two parts of it one which is signing the bundle itself using notary service just like just like you would sign a regular container image. We're just using no tree in the same way as Docker content trust so you're signing a bundle in the same way and then the second part which is, if you have if you have a supply chain layout using in total you can bring that up into the notary metadata as well so we can have both of them specifically for air gap you still need to have access to the original notary instance where you push the signature, but that's something that's going to change with notary v2. If you're interested in that I'm very happy to chat to Sean kind of was in the call as well. Yes, thank you thank you for the summer. Great design will have anything else before we close out. Awesome well thank you very much Carolyn and everyone else from Microsoft that time didn't we really appreciate it this is interesting. And Chris are you so able to demo next week, or I can scope you'll be much easier. It's really small compared to this so if you have other topics I would definitely pile them on. Okay, sounds good. Maybe we could have a follow up discussion now that people can play around with Porter and and see what people think. Great thanks everyone have a great weekend. Bye.