 Yeah, hello everyone, as Marisa was saying, welcome to the Abbotcom, and as Mark was saying as well, it's very nice to see all developer faces here. We are developers ourselves, so it's a pleasure to be here and share experiences with you. And yeah, I would like to ask two more questions on top of the ones that Mark said in the beginning, which is, out of all the developers that are here, how many have to deal with Kubernetes, or YAML, or Docker Compose, or Docker files every day? There you go. Raise your hands. Come on. Nice. You're in the right session. I'm in the right session. And how many of you consider YAML developers? I mean, we forgot the most popular language out there, right? Woo! So many hands. YAML developers. Yeah, so just like, I mean, chill, enjoy the session, we want this to be very friendly and open. So let's... Do you have any jokes? Do you want to start with any jokes? I mean, I don't have any jokes myself, I'm not a joker, pretty much, but I do have some stories. Let's start with that. So we see this beautiful picture of Paris on a sunny day, but we are not coming from this beautiful place. We actually had to go through some nightmares to be here, you know? And it wasn't easy for us to actually get to the state. I mean, Mauricio and myself, I grew up, we have around 15 years in the industry, so we've seen it all. And we had to go through some pains in the process, you know? So, you know, what I like, and if you brought some kids, please don't lose them, because, you know, otherwise some bad things can happen. And ultimately, well, you know that the Kubernetes was supposed to be the promised land and then we landed on these things. Yeah, but jokes aside, the reason why we are here is because we've been through all this, like, cloud-native movement, I mean, it's like, we all agree that it's very useful and it allows us to, like, basically create more complex and scalable applications, but the reality is that we have been working on a Kubernetes-based declarative model on the past, I don't know, eight, nine years already, and a lot of the things that we have built around it are basically scoped to only that model, which basically limits us on the amount of things that we can actually do. So, why don't you tell these people Mauricio, why are we here today? Okay, yeah, so it's really important to clarify this, because I think that we come both from companies building tools, but here we wanted to talk a little bit more about solutions and concepts, right? Like, we will show some tools in action, but what we want you to take away from this is, like, conceptually how we can approach different problems. We know that companies are going into that platform engineering space. I wrote a book about it, so that's fine, but the whole idea here is that you don't really need to do a big bang approach where you said, tomorrow I will do platform engineering, right? Like, we wanted to show you some solutions that will organically take you there. That's the main point. So for that, we would like you to, like, stick to a core idea. I mean, as I said before, we've been doing software for a while, and I still remember the early days when I was like a Java developer maybe 15 years ago. I had, like, my Eclipse editor with my Tomcat thing, and the good thing that I liked about that is that I could reason pretty much about the whole system by only looking at the code, right? So I could jump from my functions, my classes, and then I could just produce a wire file and then send it to someone, and that wire file would go to production pretty much the same way that I would develop locally, right? So we would like you to, like, maybe try to go to that, you know, like, friendly or, like, that nice space during this presentation, because part of this presentation is going to be trying to take you there, but also admitting that all the complexity that we have around is something that we have to, like, basically embrace and use in a better, effective way. Yeah, so remember that, like, safe place where you have full control of all the things that you are doing, and you know how things will behave. That's, for me, it's pretty far, far away. So having said that, my name is Marcos Ilyeda. You can find me in X at Marcos Nils, software engineer at Dagger. I've been working on this, like, for a while already. Distributed systems, developer tools, platform engineering. And I do like open source a lot. I think that open source is the things that just connect us, right? Yeah. Right. So yeah, my name is Mauricio Salatino. I'm working for Diagrid with Mark. And yeah, I'm just working on the Dapper project, KNAT, captain, and a bunch of other things. I wrote a book about platform engineering on Kubernetes that it's not for operation people. It's not for, you know, it's just for developers to understand how the tools in the CNCF space and the clouding space can be combined to produce something that will help teams to go faster. I'm doing a book signing tomorrow if you're interested, but, you know, you will find it out. So let's get started, right? Yeah, having said that, we didn't do, like, a demo sacrifice, like a demo God sacrifice this week. I mean, I'm writing a Linux machine, mirroring my screen on Wayland and, you know, anything that happened here. Yeah. But I had a croissant before. Maybe that also works. That helps. Let's do it. So let's start with a simple application. What about that? And this is like, we took the application from Docker samples. This is a very well-known application. How many people knows this application? It's the voting app from Docker. OK, so I see some hands. But if you started with Kubernetes, maybe you haven't seen this. So it's a very simple application where you can cast boats and then see the results. But with the distributed architecture, so you have three services and Redis and PostgreSQL just to show that you can connect different languages with different infrastructure and everything works fantastically, right? But, you know, you want to say that? There is one important thing, which is we actually went to this application repository and then we counted the number of modifications in the files that have been changed since 2019 until 2023. And as you can see on the top right, the most amount of files that were changed are YAML files, which is basically Docker compose, Kubernetes manifest, and all that. And can anyone guess which is the second most changed file in this repository? Any guess? Bash? Any other ideas? No. YAML, of course, right? Yeah, and then you have C-sharp and, of course, Docker files with the number fourth. But yeah, basically, this reflects a little bit of what we were speaking, like joking in the beginning. The past years have been mostly around this experience. And I mean, we are developers. We like writing code, not writing YAML. So hopefully, we can show you a different way of doing this. Yeah, exactly. And no matter what you think about this, it's like when you look into this very, very simple application, you will see that you will need to learn about containers. As Marcos mentioned, if you go to that repository, there is YAML files for how do you start the application locally using Docker Compose, how do you deploy these to Kubernetes, how do you start different services, depending if you want to run some tests, how do you start infrastructure. So it gets quite complicated. For new people, that's kind of like a lot. Another thing that I've noticed into this very simple application is that it's bounded to the infrastructure that it's using. Like you have PostgreSQL and Redis. So different applications written in different languages will need to connect to these things by injecting kind of like having clients inside the code. Like the Redis client or the PostgreSQL driver. And that brings some complexity. But finally, because the applications are written in different languages, you need to make sure that if you start creating best practices internally, like between different teams, you can share those. And if you are coming from different communities, so for example, from Java to C sharp, sharing those best practices, it's pretty hard. And it's kind of complicated. And sometimes those mismatches in best practices are the things that cause the biggest issues. So if you look into the application, and if you look a little bit deeper into what happens when you deploy this application into Kubernetes, what you will see is that inside Kubernetes, you need way much more like load balancers and you need containers and you need to get things done. But let's talk a little bit about like what the application is doing. Can you show me the application, Marcos? Before going into the code because I want to show the application running. So the application looks like that. It's pretty simple. You cast the vote, the worker will process the votes and just expose the results in the other side of the screen, right? So you can see that Marcos is casting a vote and the application is reacting. Again, it takes a little bit of time because there is an asynchronous thing there processing the data and arranging it for the results. But if you're a developer, you want to see code, right? Like you want to see how this is done. And I don't want to see that right now. Which one do you want to see? I think that we need to go to the slides, yeah. There you go. So what happens here is that again, if you go to different languages and if you start looking into the code, there is complexity in there. So the question is how can we improve this? Like if we know that the application, even if it's simple, you need to understand how to deploy to Kubernetes, how to route traffic to it, how to connect to infrastructure depending where that infrastructure is running. It might be running inside the cluster or it might be running outside. How can we improve this? I think that my answer as a developer are always like APIs, right? So APIs is the answer. And that's why I wanted to talk a little bit about the Dapper project, right? Again, because we want to show kind of like a case where APIs will help you to abstract away complexity that is related to the environment. And in this case, basically Dapper stands for distributed application runtime. And it basically does that. It provides you some APIs for developers to basically build and code applications, distributed applications. The APIs that are exposed, again, are developer friendly for developers to do the things that they are trying to do without worrying about the complexity, about how the infrastructure is being set up. And we can see that in the Dapper building blocks that are basically different APIs that are provided by the Dapper project to abstract complexity on things that you want to do like state management or exchanging events between different applications. If you see in the other side, you can see workflows that are more complex behaviors that you can build using the basic building blocks. But again, as a developer, let's take a look at now at the code in GitHub. What I wanted to show here is that, as a developer, again, you are interested in storing your votes into a persistent storage. You are not very interested in knowing that that's going to Redis and how you are connecting to Redis. So what I'm showing here is that the result service, for example, here, it's using the Dapper APIs, GetState, to get the votes that are being already stored in a persistent storage. This application code is using Dapper, but that means that we are delegating, we are delegating the responsibility of connecting to PostgresQL or to Redis to Dapper, and it's not inside the application. So the application doesn't have any driver or any client. If you take a look at the Java application, which is pretty much the previous one was Go, and this is Java, it's using the same APIs to save the state into a persistent storage, like we don't know where. From an application point of view, we just want to store the votes somewhere. As you can see here, down there, we are also using publish event to emit events if we want to do that too. So simple APIs to perform things that you want to do in distributed applications. And from the operation point of view, so that's from the application developer. You can use APIs. From the operation point of view, what Dapper does, how Dapper works, is basically you install Dapper into your Kubernetes clusters, and then you annotate some of your application to say this application wants to use the Dapper APIs. Dapper will recognize that, and it will inject the Dapper side guard that will expose those APIs to the applications. On the bottom, you can see that we are using some Jamel files now to configure how to connect to the infrastructure that is provided. So if you want to connect to Redis, you define a Jamel component that says, my APIs will be implemented by Redis, and Dapper will connect to Redis and store the information there. The same with PostgreSQL. If you show quickly the cluster from an operation point of view, I just want to do like get namespaces. Yeah, get namespaces. You can see that Dapper is installed in my cluster. And if you do like get bots, like where we are seeing on top. Yeah, where we are seeing on top is that Dapper is injecting the second container there inside my pod. That's the Dapper side guard that is being injected. Finally, you can describe the components. If you can, like get described components just to see the simple configuration. And here I just want to highlight here, a state Redis is basically saying, okay, my implementation for the state store APIs is Redis, and I'm connecting to the Redis host that is listed there with the Redis password empty because I'm using a safe Redis instance. Cool, awesome. So this is one of the ways that you can abstract, connecting to different services, right? By using Dapper and leveraging on Dapper APIs which are programmable, right? It's like basically code that you can use. But Mauricio, I mean, we told this audience that, you know, you're here to actually try to like abstract or like simplify the way that you handle your applications. And now you're telling me that me to inject a Dapper sidecar into my application and then you showed Kubernetes that how do I even run this locally? So that's a very good question. It's running locally, but it took us quite some time, right? Yeah, like it's like a foreign Redis cluster, like a kind cluster and all that. So going back to the original idea of like this happy place where you have like a fast feedback loop and then you can just like write your application, spin up all the dependencies that you need. It usually starts like this, right? I have my like fast cycle loop. I just got, I have my IDE. I can compile the app and run it locally. And then all of a sudden someone comes to you and says, hey, we are using containers now. So we need to like do a little bit of like a band-aid thing where maybe you have to write like a Docker file and maybe you have to have like a little script here and there to actually start a Docker container and maybe connect to it. And you as a developer, you're fine with it because you know that it's gonna simplify the work for deploying the application to production. So it's not that bad. But then someone else comes and tells you, hey, now you need to like lift up like a more complex setup in your machine. I'm pretty sure that most of us been through this situation. And then that that a band-aid starts becoming like a bit more like a glue, right? So it's something that you can get rid of right now. You can like hack around it that much because you need to like basically follow specific steps to start all this locally. Until of course, we go to corneries and please don't even get me started on how you even test this on CI, right? Because it's like impossible. I mean, there's, I would assume that most of you are probably have two different approaches. So you have like your own local setup where you probably run, I don't know, uncivil, whatever tool you're using today to provision this locally. And then on CI, it's probably a completely different specification of probably YAML or maybe Jenkins or Gluby or something, where you basically spin up all these things in a different way through a different workflow, which actually never works. And now you have Kubernetes, right? So this makes the glue like even bigger and then you can't escape it. And then you enter into this like sad world of actually having to deal with this even if you are application developers. It's funny because we were in a meetup yesterday. And then there's someone who actually came and told me, hey, how do you, I told that person, how do you actually enable your developers to actually ship faster? And then he told me, oh, we just give them a Kubernetes cluster, it's in place. They have to learn QCTL, they have to learn Kubernetes and they need to like know the insights to actually make their application work. Not everybody can do that, right? Like it's cost-efficient, right? There's a lot of like cognitive knowledge to actually get all that thing. I mean, and you are developers, you care about like creating better applications, not like managing a Kubernetes cluster. Yep. But anyhow, if my slides continue, and now Mauricio comes to us and tells us, hey, not only that, but then you need to add sidecars to all these things, which is this new dapper thing that's gonna allow you to basically make the service communication better. I mean, we want to embrace this complexity, but we need a way to handle it, right? Exactly. So this is the point where I tell Mauricio, I mean, that's it, man. I'm done with that. I mean, I'm gonna retire to a farm and probably grow tomatoes or something because I can't really deal with this complexity anymore. That's like fun. But wait, wait, we are here to tell this audience that there are some solutions, right? There are some solutions that are more like developer friendly and will allow you to actually make this better. So entering Dagger, how many people know about Dagger? Can you raise hands pretty quick? Okay. Cool. Not many, which is great because you're here to actually learn this. So basically, Dagger is CI as code and a lot more things. And you're gonna know why it's a lot more things in this presentation. But basically what Dagger allows you is to transform your messy scripts, like even if you run them locally or in CI, into clean code pipelines that you can run the same way locally and in CI. So the idea behind Dagger is that you forget about the push and pray, what we call the push and pray drama, which is around like, oh, I basically hug my code locally and then I push it and then I wait for the CI to run and then it fails and I need to go back to my code and then I'd say, okay, get commit, fix me and then try again. But the important thing here, which generally gets not enough attention, it's the word code, right? So the fact that you can encode all these pipelines by using like a programming language, it actually opens the door and solves a lot of issues, which is, okay, how do you share, like the functionality that you're doing? As you share any other collaboration, right? How do you distribute that? Your programming language already has like a distribution method, right? You have a package manager, you have a registry in maybe a lot of places. How do you even test your pipeline? Your programming language already has a testing framework, so a lot of things are basically for free the moment that you start embracing this code paradigm. And who is Dagger 4? Well, actually, Dagger is for developers, right? So you can be like a platform developer, you can be like an SRE, you can be also like a developer advocate that is also like trying to show solutions to customers. The good thing about Dagger is because you can encode all these logic in order to like spin up your environments or maybe test them in CI as well. The good thing is that you can encode them by code and run them the same everywhere. It's basically a tool that is very friendly for anyone to actually grab and use. So before jumping into the API side of Dagger, I would like to show you how we are gonna change this vote application that Mauricio was showing us that only running Kubernetes by mostly leveraging Dagger. So let's go to the voting app. So I'm gonna go to the repository. I'm gonna show you the worker component that Mauricio was showing. And I'm gonna go into the worker folder and you're gonna see that I have like a Dagger.json and a Dagger folder here. The Dagger.json basically defines what a Dagger module is. Dagger is presented as a solution that allows you to encode these pipelines in modules and functions. So the first thing that you're gonna notice in this example is that I have a Dagger module that actually has other dependencies. I'm gonna get into that in a minute. But the important thing for you is to understand is that this is a Dagger module that is written in TypeScript and uses this Dagger version and basically loads the Dagger source code from this source folder, which is in the parent that you can see here. If I go into the Dagger pipeline itself, in this case you're gonna see that it's written in TypeScript and the most important thing, like the basic construct of Dagger is that you can encode all these logic in functions. So for this worker component particularly, I have the serve function, which basically starts my worker service. And then I have the build function that as you can see, receives a directory where my source code lives. And then it also receives optionally, because I have these optional syntax here, optionally it receives a service, a ready service and a post-release service, which if you remember the architecture diagram, like basically this worker depends on both services. So I can optionally specify them here. And if I don't specify them, this is where the Dagger specific API comes into place, where I can actually define a container from this particular image, I can expose a port and then I can start and inject this service into my application, right? The most important part of this build pipeline is that my application is written in C-sharp. And instead of like having a Docker file and having a compose file that actually stitches all that together, I have a single place which is defined as code using the Dagger APIs, right? Where I can like define these containers the same way that I was doing before, but with real code. And then I can also attach these services that this container needs in the same place. Yeah, and if you ask me as a developer, right? I like the idea of being able to codify how do I work with my applications. I don't think that I like that much the idea of writing pipelines for like the CI space because that's probably managed by a different team. But in this case, I believe that what Marcos is showing here will allow you to define the developer experience for developers working with these complex applications. Yeah, so now I can show you if I go to the terminal and then I go to the worker.net directory. Since I'm in this module and in a Dagger module I can do Dagger functions. And this is gonna basically show all the available functions that I have for this app. And then I can, I need to stop Mauricio's application. First, and then I can do Dagger serve, which is the function that I showed before. I need to specify a directory, which is where my source code live, which is dot and then up, Dagger call, sorry. Dagger call serve up. What this is gonna do, this is gonna basically pull the containers that I showed you before. This is gonna start the application locally using the Postgres and various services that I've shown before. And this is already fetching boats, even though it says it fails, it's not failing, it's some internal things. But this is actually working, right? So I didn't have to like touch any Docker files or anything at all, I just called the Dagger functions. So jumping quickly into the other module, I want to show you really quickly the result module, which is this one. In this case, this is the result application where we see the voting results. This is also a Dagger module, but in this case, you're gonna see that the module is defined in Go and has like two different dependencies, the Dapper dependency and the Go dependency. So if I go to the code really quick here, and this is the module concept that I wanted to show you. Again, same API as you saw before, containers with n-barrel, but in this case in written in Go. And the most important thing here is that we are using the Dapper Dagger module, which basically is a function that I'm pulling from a different place, right? It doesn't matter in which language this function is written on because it's gonna work in the Dagger ecosystem. And then I can call functions on this module that allow me to basically extend my application in some sort of way. In this case, I'm bringing the Dapper module that is gonna automatically launch this container and then this Dapper container and inject it into the next of my application. So I define this by code basically. As you can see, same structure as the previous component. I have a build and a serve. And what I want to show you here is that I can do, where I'm in the dot net. So I'm gonna go back to the result. Go result and I'm gonna do Dagger functions. In this case, this module provides me with three functions. I can build, I can serve and I can test. So I can show you how I can test this application really fast. Yeah. Dagger call, test. I'm calling the app. And the last thing that I'm gonna show you is that I can do Dagger call, the local and then serve. Yeah. Serve up. So what this is gonna do is gonna basically start the voting application. It's gonna expose a port in my local machine. So this is basically running Redis. It's running Dapper. It's running all the dependencies that I need. It's already exposing a port in my machine so I can do localhost 3000. And then I have the application running locally, right? Yeah. No YAML, no Docker files. No Kubernetes. No Kubernetes. Yeah, that's local. Like I have the same setup that Maurice was showing in Kubernetes, but running locally. Yeah. Go slides. We closed it up. Yeah, we need to speed it up a little bit. Yeah. So the important thing here is that Dagger gives you APIs. As you saw in the code, like briefly in the code that I showed you, you have the container API, director API, file API, secrets. These are like the building blocks, right? We like to say internally that Dagger is a tool that allows you to like gives you like some sort of like DevOps operating system where you have like the core APIs. But the important thing here is that you can start building your personal experiences on top of this API by extending this with your personal APIs. So you can like define APIs like, I don't know, application or maybe whatever you need internally in your company. So you can use Dagger to extend this and basically build your own developer experience. How does it look in CI? The same way that I did in the terminal, I basically did like Dagger call test. You basically take this to like whatever CI you have and then you can just like running in the same way. This is the power of Dagger, right? You can run it locally and in CI using the same experience. Yeah. So, and this is basically the final diagram. The way that we switch this application is we basically modularize everything and now you have like a Dagger module for all the things. And I can quickly show you. Just need to finish here. Yeah. And wrapping up the presentation. Yeah, we need to wrap up. Just to close. So I can do like, I have like the top level module which basically uses all the modules that I showed you before and I'm gonna do Dagger call. Yeah. The Dagger call vote up. So what this is gonna do, this is basically gonna start everything. So it's gonna start the... So up. So the vote up returns a service and the service requires like a sub command which is like basically start a service. And this is gonna run everything. It's gonna run the front end, the worker, the result service. And it's gonna wire everything together and just like allow me to like run it locally in the same way. Yeah. So I can open this up, local host CD80. Boom. And you have this running. Yeah. There you go. So this is really good. I think that like, we have worked on this like together. The main idea here is again, just to bring Dapper like the Dapper experience that it's pretty polished when you run in Kubernetes clusters, closer to developers and the local development loop lifecycle, right? Like the idea that you can start Dapper applications locally. It's just one example of the things that you can achieve by using these tools. What Marco showed about the APIs, I think it's the same message. Like on the Kubernetes side, we're trying to obstruct away infrastructure from applications. What Marco's is showing here is that we can create like more complex developer experiences for local development that can match like more like complex environments like running inside the Kubernetes cluster. I think that, yeah. I think that, yeah. Again, it's like we are just bringing the complexity closer to the developer, but in a way that it's obstructed away. So they don't need to worry about it. You have a question for me. I have a question. Yeah, well, so I send you, what was the question? You send me a PR? Well, that's not a question. I send you a PR. Can you check it out? That's the question. If I can check it out. Can you check it out? Well, he sent me a PR. So I have like with some changes to my application. The thing is that I need to check out the code. You know, that's very messy, but I'm gonna leverage the power of Dagger to actually show you something very cool. So I show you before that my application as part of its API requires a directory, right? In this case, where the source code is gonna be like brought in. But I never told you what that directory could be, right? That directory could be like, I don't know, maybe a Git sort of repo. Maybe like a branch in my Git repo, right? Yeah, exactly. And because the Dagger modules are already published in GitHub, I can actually pull from those modules directly and use them regardless of the environment that I have in my local machine, right? So the only thing that I need is Dagger. And in this case, I'm gonna be calling the same function that I showed you before. But in this particular example, the function is being pulled from GitHub directly, not from my local machine. Then I'm gonna call the same voteup function. And the directory is gonna be like a full qualified GitHub URL with the branch name that Mauricio told me. So let's see if this works. Yeah, and I think that that's... I don't need to have the source code of my application for this example. This is basically pulling everything dynamically and on demand. And if the demo gods are with us. Yeah, and I think that the main thing that he's trying to show here is that we can create changes for our application in branches and then we can just quickly create preview environments with very, very complex setups by reusing all these module definitions. And this is quick because Dagger has like a caching system. If you want to learn more about that, you can go to the site. So to wrap it up. There you go. Let's see what the new options we have now. There you go. So do we vote for code? So what should we vote? What do you say? Do you prefer doing code or YAML? Do I go with YAML? Code, code, let's do code. Nice, okay, and now we can code. So yeah, with Dagger you can have like immediate preview environments with just like a single function code. There you go. And you can have that for local development. So that's great. That also like starts the whole dapper thing. So without like further ado, like takeaways, like you know, hiding complexity behind APIs. APIs are the answers if you are developers, right? Like try to find the right APIs for abstracting your complexity in your companies, no matter which tools you are using. Building experiences for your team is becoming more and more important if you want to reduce complexity and cognitive load for people working with all these tools. And yeah, again, like just try to help teams to be more productive. And as Mark was saying in the beginning, this is about developers and software developers. So thank you very much.