Overview

About this video

What You'll Learn

  1. Explain Pulumi multi-language components through a Go provider and schema.json.
  2. Implement Kubernetes resources in Go, then regenerate language SDKs from the schema.
  3. Debug schema mismatches until the TypeScript package builds and deploys successfully.

Lee Briggs walks through Pulumi's multi-language component packages: writing a schema.json, implementing a Kubernetes deployment component in Go from the pulumi-component-provider-go-boilerplate, then generating and consuming SDKs from TypeScript.

Chapters

Jump to a chapter

  1. 0:00 Holding screen
  2. 0:40 Introductions
  3. 0:53 Introduction and Housekeeping
  4. 2:20 What are Pulumi Multi Language Components?
  5. 2:25 What are Pulumi Components?
  6. 4:26 The Solution: Multi-Language Components
  7. 6:20 Why Choose Go for Component Implementation
  8. 7:00 Building a Multi Language Component
  9. 8:56 Defining the Component Schema (schema.json)
  10. 1:12:18 Structuring the Go Provider Code
  11. 1:17:45 Implementing the Kubernetes Resources in Go
  12. 1:41:48 Making the Component Configurable
  13. 1:52:50 Reviewing the Process & Other Languages
  14. 2:02:40 Generating the SDKs & Debugging
  15. 2:40:50 Fixing the Schema/Code Mismatch & Successful Generation
  16. 2:46:50 Building and Installing the Component
  17. 3:08:00 Consuming the Component in TypeScript
  18. 3:22:30 Deploying with Pulumi Up (TypeScript)
  19. 3:38:30 Explaining the Multi-Language Mechanism
  20. 3:47:00 Debugging the Deployment Error (Input Passing)
  21. 3:59:50 Regenerating SDKs and Redeploying
  22. 4:15:00 Verifying the Deployment
  23. 4:25:15 Reviewing Generated SDKs
  24. 4:31:45 Use Cases and Benefits
  25. 4:39:30 Conclusion & Final Q&A
  26. 4:58:00 Outro
Transcript

Full transcript

Generated from the English captions. Timestamps jump the player to that moment.

Read the full transcript

0:53 Introduction and Housekeeping

0:53 Hello, and welcome to today's episode of Rawkode live. I am your host, Rawkode. Today, we're gonna do some dabbling and experimentation with some new Pulumi features that enable multi language packages. Before we get started with that, there's just a little bit of housekeeping. But first, if you're not subscribed to the channel, please do so now and remember to click the bell so you get loads of notifications for all new episodes as we explore the vast cloud native landscape together. And if you wanna chat and talk cloud native Kubernetes and NFN in between, we have a very active Discord server. Feel free to

1:26 pop in there, say hello, and I look forward to meeting you. Alright. Now joining me today to introduce me to this wonderful Pulumi awesomeness is a returning guest, Lee Briggs, man. How's it going? Not so bad. How are you? Yeah. I'm I'm doing well. I'm looking forward to seeing what new shiny stuff you've got kicked up for us today. Yeah. This is really new, so really, really on the cutting edge. I'm really excited about it. And I think probably best first step is to talk a little bit about what we're gonna be doing. Yeah. Well, why don't just for anyone who's

1:59 not aware of you, you tell us a little bit about you, and then we'll talk about the the thing. Sure. My name is Lee Briggs. I work at Pulumi as a developer advocate and formerly in the engineering team. I originally from The UK living here in Seattle in the West Coast Of The US. So it's good to hear a familiar British accent. Alright. Thank you for sharing. Okay. Now enlighten us. What awesome thing are we doing today? So we need to provide a bit of context here, especially if you've never kinda used Pulumi. Pulumi is obviously an infrastructure as code tool

2:25 What are Pulumi Components?

2:34 that allows you to use what I like to sell call cheering complete languages. So instead of using declarative languages like YAML, you can use imperative languages, but we declare the imperative language pushes towards a declarative state, which is super powerful. And, you know, our customers love it because it means their front end engineers who are familiar with TypeScript or their back end engineers who are maybe writing stuff in Go, they can use those same languages that they're using their application life cycle to actually define infrastructure as well. You we have a mechanism within Pulumi that

3:09 allows you to group all of the different infrastructure resources that you are defining into, what we call a component. And if you're familiar with stuff like Terraform, you might have might know of a module or if you are familiar with the CDK, you might be familiar with constructs. Components are our mechanism for, you know, creating reusable infrastructure. And what we usually see is the companies like to define like best practices in these components and then share them out within their organization. The problem with that is that up until now, when you've defined your component and let's say you've written it in our

3:49 TypeScript SDK, you can only really share that with other people using the TypeScript SDK. So, like, your ability to kind of like create community modules or maybe in large enterprises where you have multiple programming languages and you stack, you've had to rewrite it multiple times. And there's been a there's a couple of really great examples which, you know, where people have gone to the trouble of writing their their component SDK in Go and then TypeScript and then Python. But the maintenance overhead just kinda gets away from you really quickly because you happen to write things in three languages and you might

4:23 not know three languages. So a few weeks ago at our three point o launch event, we announced what we call multi language components, which quite honestly as a technical fee is so amazing. I don't fully understand like how it's possible. I mean, I understand the technical ability of it, but I'm still, like, blown away that we're basically able to do this. But what it means is that you can create a shareable component in one language, and it will generate the SDK for Pulumi in all of our supported languages. So that's what we're gonna be doing today.

4:26 The Solution: Multi-Language Components

4:56 We're gonna write a example component that will allow you to, like, define the best practices for a deployment. And I think we decided that the best way to kinda show this off is in the Kubernetes world where, like, if you have an internal Kubernetes platform, you probably wanna define best practices for a deployment within your organization, like the the required number of replicas and then just allow it to be configurable with just the image you wanna run. So we're gonna define that. We're gonna write it in go, and then we're gonna show how that that generates an SDK in four

5:30 different languages and see an example of deploying it in TypeScript. And if we have time, we'll do a Python example as well. So, it's gonna be a bit of a journey. I've written like two of these so far, and I'm still finding some of the, you know, some intricacies. But hopefully, we'll be able to kinda show off what the capabilities of this are, and we'll get an idea of how powerful it is. Awesome. The timing could could just generally couldn't be better because I've actually been working on something that could really leverage this. Like the cluster

6:01 API bindings that I've been working on. We're actually deploying Kubernetes clusters are all all done in TypeScript just because that's the language that I prefer to go. But the cloud native ecosystem is physical developers who wanna work in go. And if I can expose these bindings to them through that, that would be amazing. So I am super excited to see this work. So just a final thing, we're gonna be using the Go SDK today mainly because Go's ability to build binaries that you can then reshare is super, super powerful. So I like to write these in Go. You can write

6:20 Why Choose Go for Component Implementation

6:31 these components. If you're a Python developer or a TypeScript developer or a dot net developer, you can write these components in whatever language you think is best. But the the caveat is that, you know, the the end stream user will still need to have Node or Python installed if you write it in those languages. So Go is really nice for this because all you have to do is give the users a binary, and they're off to the races, basically. Nice. Alright. Show me the race. Okay. So we're I sent you a link before we started. We're gonna look at the

7:00 Building a Multi Language Component

7:03 Pulumi Go boilerplate provider. So this is on our GitHub repo. Yeah. I just gonna leave the Pulumi homepage up for ten more seconds because I think it looks so awesome these days with the the rebranding. You know? And I I love the rebranding and shout out to Zach Chase who, like, slaved away for hours and hours kind of putting this together and and coding it all up. I think it looks awesome too. So, yeah, really, really cool. So the starting point that we have already kinda done a little bit of we've got a template provider here

7:34 that we call the x y z provider. And what it's basically doing is showing you an example of creating a static site in AWS. But the whole point of this is to start off with something that allows us to kind of build something out. So you already fought this into Rawkode Pulumi dash production app, which we see here. So the first thing that we need to do is we need to kinda go through a bunch of this stuff and just update the name from x y z into what we're gonna call production app. So the

8:08 first thing I would do is open up the make file. And you'll see at the top there the pack is x y z, so we'll change that to production app. And then below that in project, you need to make sure the project is Rawkode rather than Pulumi. And then we'll just scroll down and make sure there's no other missing pieces. I don't think there is. And just to quickly go through what this is doing, this is just a make file that is going to generate all of the SDKs once we finish building this out and then also install them

8:43 locally so that we can test it. So you'll see it's gonna generate what we call a provider binary, and then it's also gonna generate all of the different SDKs. So this is what we're obviously gonna be using in a few moments. Next step is we're gonna open up schema dot JSON. So this defines the shape of the actual component itself. So it defines inputs that you're gonna put into the actual no. We're gonna do it manual, Paul. We're gonna do it we're gonna do it so that people understand what is happening. We're gonna do it the right way.

8:56 Defining the Component Schema (schema.json)

9:17 So this defines the inputs and the outputs of the actual component. So this is gonna allow us to set configurable values for our users and also what things that they might want to use elsewhere. So we're gonna call that production app and then on line four, we're gonna switch x y z to production app as well. And then instead of static page, we'll call it deployment, I think. So an an an a deployment of a production app. And then the input properties, we're just gonna clear that map out for the time being, think is probably the best

9:48 way to go ahead, go about this. So it's actually starting at line six. Sorry. And I don't wanna kinda, you know, over over Do we need empty out the required inputs too? Yes. We're gonna click. So that's gonna be an empty array and then all of the yeah. All of the required properties. Okay. So this is just like JSON declaration that says this is the thing that we're creating. These are the inputs that it has, and then this is the other stuff that can be layered on the top to customize it in some way. Is that like like

10:20 like a function signature in a weird kind of way? Yeah. That's that's probably a good good way of putting it. Yeah. So I'm also just gonna clear out this index content here because that we're we're gonna fill that out in a few seconds. So this is gonna show us, like, all of the things that the users are gonna be able to configure and then also the things that they might wanna pass to other Pulumi resources later. So for example, you might wanna generate the deployment name and all that kind of stuff. We're not gonna use this today,

10:47 but, you know, it's just a a nice thing to know later on. And so the next step, we're gonna define all of the language dependencies. And obviously, for our example, we've got c sharp. We're gonna in the example, we're using AWS. We're not gonna use that. We're gonna use Kubernetes. So on line 14, we're gonna change that to Kubernetes and then it's actually three dot star. Go, we're gonna change the import base path to our name. So Rawkode Pulumi production app. Yeah. Don't forget the Rawkode there. And then at the end of the x y z

11:21 is also production app. Yep. No JS dependencies update the AWS to Kubernetes three point o dot o and then finally Python again. And what's great about working at Pulumi is you get to learn all the different dependency management systems and how one of how they all did how work differently. So you're kinda dealing with so many different SDKs at a time. You know, you end up kind of learning the intricacies of setup dot pie and all that kind of stuff. So I think There we go. Yeah. We are working on some authoring improvements here. So

12:00 we're hoping that we're working on a way that this will automatically get generated. But for the time being, it's actually kinda nice being able to kinda do this manually because you get to kinda think about a little bit about what you're doing. But then I don't get to show off my wonderful, you know, command line knowledge. So the the next thing that we're gonna do yeah. I mean, that that that's probably at this point, we could just to go ahead and do that. The I'm sure we're we're good. Right? Yes. Okay. And so then the final thing that we're

12:33 doing here, is we're gonna actually update the, the directory. So if you go back to your, yeah. So in the provider directory, there's go dot mod. At the top, the module name is gonna be Rawkode Pulumi production app. I don't know if you wanna go for go one sixteen. That definitely works. And then the Pulumi package and SDK is gonna be three point three point one. And you'll need to yeah. You'll need to yank the there we go. Perfect. Okay. We'll keep going. And now we're just gonna update some directory names. So if you go

13:23 to your workspace again in the package directory. Sorry. No. In the my apologies. In the command directory. Yeah. Rename those and then rename resource as well. And then I think there's got some imports in there as well, so you'll need to drill down into there. So this, this is all fine. What this is doing is it's reading in that schema and it's gonna emit the SDK from the schema. And then here. Looks like a c m s oh, there we go. There we go. I'm sure we've missed one of these, but we'll we'll figure it out. And then don't

14:17 forget the online 20 as well. Don't forget the Rawkode for Pulumi in the that's it. Yeah. And the import name as well. Kinda manual at the moment. You know, we we we are working on the author and experience for sure. So anything in the examples or SDK is gonna be fine. All of the stuff that we're really looking for is in the provider thing here. So we are gonna be looking at the provider package in a moment. So what I would recommend is just blowing away the SDK directory because we're gonna regenerate that every single time. What about the example

14:53 directory? And that as well. Yeah. That's probably easier. You sure? Yes. We're not they we're not gonna be using that just yet. I promise. Alright. We could ignore the read me. So that means we got just a provider one now. So let's jump back. Yeah. So yep. It's in command, I think, in the provider command. Sorry. The there's there's two command directories. There's command and then provider command. Oh, there we have provider package. Alright. Okay. Yeah. Yeah. There is one. Production app. Question after deployment. Right? That's right. Yeah. And that's it. So, what we're gonna do now is we're gonna

15:51 rename the static page. Go into into productionapp.co. I'll gonna rename that. I I I like to call it deployment.co because that's what we're be And then if we open that up okay. So this is where we're actually gonna do all of the logic that we're actually going to kind of do use to create our provider. So currently, we're using the AWS provider. We can completely remove, line 18, and just do because we because the the the Kubernetes provider's laid out slightly differently. And you, you're way ahead of me already. So you Yeah. But I to make you to me

16:32 no. To me, that actually shows that it's relatively intuitive. So yes. So we're gonna create a deployment with deployment arcs. We haven't decided that we're gonna have index content yet, so let's get rid of all of that. And then line twenty nine and twenty and 30, we can get rid of those because those are gonna be the actual outputs that we're gonna create. We're not gonna do new static page. We're gonna do new deployment. Okay. So I should just rename it rather than delete it? Yeah. Just rename it. Yeah. And that takes deployment args on line 32.

17:08 And then we also redirect to deployment args there. And then 37. It's not it's just a component is a new in yeah. And then here you can see where where we register our component. That will be production app index deployment. There we go. We're not gonna be creating a bucket, we can get rid of that. And you can see that this is all just gonna be creating leave that leave that. We're gonna need that in a few moments. So what you wanna be removing and I can probably jump in here and help. I'm making you do all the work.

17:49 Yeah. Try to step back and relax. Alright. You've already done it. So then the final thing that we're gonna remove is this register resource output is gonna be the thing that we're gonna export in our production app. We're not gonna export anything. So this can be just an empty Pulumi map. So lines forty four and forty five can can go. Beautiful. Okay. So what is that? Like five minutes and we have bootstrapped our provider and we're ready to actually, add some stuff to this now to actually make it useful. So we need to do a few imports.

18:25 What we'll need to a question just now? Absolutely. Alright. We got a we Paul has answered it in the comments, but let's get Andreas a good answer. So no, no offense, Paul. I love you really. But Andrea is asking, does that mean Oh, that went away fast. Stay. Does that mean that consuming several public components might require to have node and Python available even if the stack itself is defined and go lang. So you're basically generating API stubs. I don't know why that keeps disappearing. Yes, basically. So like the language that you're actually using, like if you're consuming this component

19:02 in Python, are you consuming this this component in TypeScript, you'll need those available to actually kind of create the the infrastructure. Because we're writing this in Go, you'll need to have the also the actual Pulumi binary locally installed as well. And we'll generate that and put it in the path. But you like, because we're defining it in Go, if you wanna consume this in TypeScript, you will not need Python as an example. Right? So this is relatively common for some of our larger customers who have, like, clean laptops and they're like, we want this specific

19:32 version of this specific, you know, language. You'll only need the language you're consuming it in. You don't need all of Pulumi supported languages installed to use this because we're writing it in Go. Okay. So hopefully that answers the question. Okay. So what we're gonna do now is we're gonna use the Kubernetes SDK to actually define a a namespace, a deployment, and a service. This is just a hypothetical production app. So I'm gonna copy these for you into the dependencies so that you I don't have to tell you to type them all out. So these are all of the different types

20:12 of dependencies. If you scroll up to where the dependencies are, we're gonna be using apps v one. If you are familiar with Kubernetes, this will look pretty familiar. It's basically just the Kubernetes API. And we're gonna use apps v one, call v one, which is where the namespaces are, and meta v one for all the different types and stuff. So I've imported those for us. The next thing that we're going to do is go back down to our new deployment. Well, if we scroll down a little bit. Yep. And this is just where we're gonna

20:42 start to actually define all of the stuff that we want. So what I like to do here is like set up some labels that we're gonna pass to all of these resources because it kinda shows that you don't have to kinda repeat yourself. So below where the arguments is on line 39 just to create a new variable labels. And we're gonna do Pulumi dot string map. And we're gonna add some labels of app. So the actual It these don't actually need to be a Pulumi dot string. So it's just a, app.kubernetes.i0 forward slash app is what I like to

21:29 call that label. Sorry. I'm not I'm not doing a great job of yeah. And then the this value is a Pulumi dot string. But what we're actually gonna do is just pass the name from the actual deployment. So we'll do Pulumi dot string name, and that comes from here. And I don't know if you can see me highlighting in the Versus code because I've turned the livestream off, but cool. So then that's gonna come from there. And then also we're gonna do app dot production. And, again, this is just a nice label to pass through to everything dot instance

22:03 for slash name Pulumi dot string name. Oh, apparently, I have not learned to type this morning. So then we could just pass these to all the different different, resources that we're gonna create, which is nice and simple. Next thing we're gonna do is we're gonna create a namespace error. And this is where we start to use our dependencies. And I think you're gonna have to go get them so that we get all of the type hints. Alright. Let's comment now so it's happy at least. Yeah. Oh, I'm in the wrong directory. Right? So that was a Yes. It's a provider. It's

22:48 in the provider directory. And, yeah, we've got a go mod. Uh-oh. Okay. Interesting. There we go. I never understand go mode. I just keep typing commands until something works. I think you've just described my whole career. So then we should hopefully get the type hints now. So if we and I'll let you. Yeah. And so then it will be New namespace. Yeah. That takes the first argument is the context or CTX. So that's the Pulumi context. And then All of these take the yep. Then the name and then it's an as it's pointed to call v one

23:34 and ampersand. Sorry. Call v one dot namespace args. Like so. Yep. Then we need to specify some metadata. So yep. Let's populate that and that takes an meta v one object meta args, and then we'll put the name, I think it's capital n, Pulumi dot string name. And then the labels obviously can come from the actual labels variable. I've forgotten how to go. I've been writing Rust all week. Bear with me. Yeah. You've gone you've gone full hipster then. What is missing here? Oh, why have I got two? That'll be it. And there's another one at the end there.

24:36 There you go. Okay. So then we're doing go, so we need to check the error. Of course. What I like to do here is I like to so this object returns two things. It returns a deployment and it returns an error. So we're just gonna return nil. And then what I like to do is actually return a little bit more helpful error. So I do format dot error f. Sorry. It looks a little bit like yeah. There we are. Error creating namespace colon percent v. I do percent v because it's nice. And then the actual error.

25:21 And that and I think we'll need to import format as well. Yeah. Yeah. It looks like it's Versus code. We should be good. So that would create our namespace for us. Let's create our deployment. We will use the namespace later, but for this the deployment, we're not actually gonna use the variables. So we're gonna do empty variables. So error equals and it's just equals. Yeah. I'll let you take over from here. Oh, alright. So we want a core v one. It's v one because it's a deployment rather than core v one. What did we import?

26:09 Oh, it's it's yanked our definition. Let me let me grab It is apps v one. Right? Yeah. It is. But it's actually the import has disappeared because I'm guessing we're not using it. So I've added it back at the top there. Dot new deployment. Yep. And then of course that takes a context, a name, and then and apps v one deployment args. And, like, if you're if you're familiar with Go, this all starts to seem a bit, familiar after a while. Like, but the deployment object is a little bit more complicated so that I think you've missed a I think you've

26:48 added an erroneous space there on 56. Let me get rid of that for you. So then that takes metadata as well. So we'll start with the metadata in caps, and it's object meta v one object meta rags. I think you need a pointer. So let me add that for you. Okay. And then she we're gonna get the we're gonna grab the namespace that this deployment deploys in from the namespace variable. And this is Pulumi's outputs at work. So it will be namespace, and you can kind of finish it off from there, dot metadata. So it looks like this. So it's metadata

27:37 dot a You want the name of it, of course, not the object. And then you actually need to get the element as well. So it like that. So if you're not familiar with Pulumi, this is the way that we create dependencies between two different objects. So we're getting what we call the output, the the name from this namespace. We're getting that output and we're passing it to a new resource. This allows Pulumi to know that it needs to create the namespace first and then create the deployment second. And this is how we're able to use

28:08 imperative languages and create this dependency graph, which is super powerful. So then we're gonna define the spec, and this would be and apps v one dot deployment spec args. And this is where, the ability to do, you know, strongly type languages comes really handy because you, you know, you're getting all of the like, it it's really hard. It's surprisingly hard to make a mistake here, because it's telling us what it needs. Label select to ask. Match labels is the labels. And you're probably understanding why I set up those those very the the variable now because, like,

29:00 you can obviously make mistakes there. And then we want replicas. And this is kinda where I like to point out that because we ask the people authoring this SDK are the experts, we want this to be a hypothetical production application. And we know that a production application is not one replica. Right? Like, we know that. We don't wanna make this configurable. So let's hard code it so that all of the people consuming this particular, component, they're always going to have a highly available application. So we'll make replicas of three, and we're not gonna let them actually, you know,

29:36 let our consumers modify this, if that makes sense. Obviously, we are going to be adding arguments to this at some point, but, like, I guess the point I'm trying to get across here is, like, when we're defining these components, the the my thought process is that you only should have input arguments that you actually want your users to be able to to modify and consume. Okay. So we're gonna do a template and call v one pod template args. More metadata because Kubernetes loves its metadata. Object meta as labels, labels, and then the spec for the actual pod.

30:26 Pod spec. And this is where we're actually gonna be defining the container. And this I think is let's see if this is correct. Pod spec arcs. Yep. Containers. That takes an array of containers. So I'm calling one container. And this live share is really hard. It's just that it's just that little delay, from, like, doing things locally is, an interesting I think all viewing one container array. And the reason that we have to do these, special types with Pulumi, is because these values are like, this is not a a standard kind of slice, and it's because these values are, like, computed.

31:21 So we don't know them upfront. Call v one container args. And I'm gonna let you this is your show, so I'm gonna let you finish round this one out. So we're gonna take the name of the actual container will be Pulumi dot string. And let's hard code this for now, the image. So what we'll do is we'll hard code the we'll make that name. Our main is fine. Yeah. NGINX is fine. Ports. That takes a and call v one. Let me just check. Yeah. Core one container port and put array. So And call v one

32:05 container port array. And then and call v one container port axe. And container port, let's call that 80, I guess. Pulumi dot int 80. Yeah. Okay. And then there's one. There we go. So this is your deployment and your and your namespace. Final thing is the service. If you hopefully, the the cluster that you set up can support low balance of services. I assume it can. Should be alright. We'll give it a we'll give it a try. So we're gonna define a service, and we're not gonna use this. So equals call v one new service.

33:12 And, of course, that takes a context. It takes a name, and then it's an call v one service r. Oh. Metadata, of course. Of course. And I think we can just Copy that, I think. Yeah. Make our lives a little easier and copy this. You know? It's just occurring to me that when we what we could have done is set up a, a variable for that, but this is go. It likes to be the verbose, of course. Ports and call v one service port array. Got a a way for Mark. Hey, Mark. Thanks for joining.

34:03 And call v one service part. Part is Pulumi dot int 80. And I always forget this is the actual part that the load balancer listens on. So target port is Pulumi dot n 80 as well. I think oh, we need a type as well. Yes. Right now, that's just gonna be a cluster IP service, which is okay. Let me not string. We can always remove this if that's this doesn't work. Because we're just showing how it doesn't have to be. It doesn't actually have to be a production ready application. So this is a cluster API cluster running

34:54 bare metal on Equinix metal running metal LB, the Equinix metal CCM. I mean, there's a whole bunch of stuff here that's configured. I'm sure I got it all right and the load balancer will work, but we'll see. Well, if it's got my LLB, it should work. Right? And we have a problem here and I'm not sure. Yeah. It was just a comma. I fixed it. I'm still getting an error on line one or two. Maybe my live share is not updating. It makes it alright. Okay. Well, we'll see how it works. So this is this is defined all of our

35:28 infrastructure. Right? So we could generate this SDK and then we could actually consume it, but it's not really very usable. Right? Because we're obviously gonna wanna deploy more than just NGINX. Right? So here is where we start to kind of set up some of the parts that allow us to, you know, allow us to make it configurable. So we're gonna scroll all the way back up to our production app arcs. Sorry. Our deployment arcs. Yep. And this is where we're gonna actually start to add the the two things that I can think of that we need to

36:02 allow to be configurable is the image. So what part of the struct will create an image, and we'll do and this is a type of Pulumi dot string input. And I think your colon has vanished at the end there. And then we also need to put a a type on this. So the way this looks is, and I'll fill this in so that we can, so this is oops. Oh, man. Versus code is giving me a nightmare. So what we need to do is add very similar to what we would do with JSON. We need to do

36:38 something like this. So that just will that means that when we read the the schema in, this is the value that it's gonna read from that schema dot JSON. So we're gonna need to update that in a few moments. And then the other argument that we're gonna want is the port. So let's we'll make configurable to our users. Pulumi dot int input. Yep. Pulumi. There we go. And so now we can actually pass this stuff to our deployment as well. So if we scroll back to our deployment I'm worried that go format hasn't kicked in.

37:18 That normally means that we have an error. Yeah. We've got I know we asked a break point. Do have a break point? It'll I did not add a break point. I don't even know what they are. Right. Okay. I'll assume it's fine. I don't see any any When this builds, it'll tell us what it'll tell us what the problem is. Oh, no. Now I've got an error on that line. Okay. I didn't have that error there. So we're missing a comma somewhere. We're missing the closed bracket, I think. Alright. There we go. Hang on. Let me Did it format the

37:53 top? I did. Okay. We're good. We're good. See, look, this is x. This is what this is programming at work. It's weird that I justify whether my code is gonna work or not, whether the format kicks in or not. The format doesn't kick kick in, I know that I've broken something. So now we're actually gonna pass those arguments to our to our deployment. So if you scroll back down to where we defined it defined NGINX, we can change that image to args dot image. And then the container port here on 79, we can do args dot port.

38:35 Easy. So now we need to update the schema so that we can actually tell Pulumi that these are required when we generate the SDK. So if we go back to our schema Oh, yep. That that's right. The JSON. Yeah. So this is where these input properties come in. And so what this needs to look like and I need to actually look at a reference example here because we're still I'm just making Yes. No. No. You're you're basically right. But we they need to be lower case because that's what's on the actual thing. And then here is where we define a

39:10 map of properties. So we're gonna do image. We need to define what the type is because, obviously, we generate strongly typed libraries. So we do string like so. And then we get to add a description for the type hints. And, hopefully, you can see, like, this is this is what are gonna allow our users to get a little bit more information when they're using this. So the the image to deploy in your production ready application, And it's JSON, so it doesn't want a comma there. And then port type is integer description. The part your application

39:59 listens on in your Docker. It's not technically Docker anymore, so we'll just go, in your image. Container image. Yeah. Container image. Yeah. That makes sense. So these are the things that are gonna define what our input types are. This properties thing here, we're not gonna use this today, but this properties is the thing that will allow you to say if you've used Pulumi before, like, all the outputs that we have, like, you can also define outputs. So if we wanted to, we could say, like, return the load balancer that has been created that you might wanna use in different things.

40:35 We're not gonna do that, in this particular case because it's supposed to be a relatively simple example. So I think I think that's everything, but we'll find out when we start to do some of the fun generation stuff. So if you go back to your terminal Can can we just summarize what we've what we've done there? I'll summarize it to you and you can tell me if I got anything incorrect. Sounds good. Alright. So we are using the Pulumi component provider GoBoilerPlate repository. This can be used as a template to provide the base for any multi language Pulumi

41:07 component. Yes. What we did there was just really go through and do some rudimentary changes. We were modifying the x y z, which is the example name for the component to be our production app, and then we modified the static page, which is just one of the resources that the boilerplate or provider starts with, and we've modified that to consume the Kubernetes API provider deployment and a service. And we've exposed through this little JSON schema style document, the ability to understand what input properties there are as well as which ones are required, And then we've just done a little bit

41:41 of glue inside of the the Go code to actually create those resources. Yes. That's exactly what we've done. That's exactly what we've done. And the process is exactly the same for all of the different languages. If you wanna write one of these in Python, you're basically gonna do the same thing. You're gonna define a schema that looks that the you know, if you are familiar with, like, TypeScript and you basically, I think of them as interfaces. So this schema is the interface that, like, the the consumable interface for all of the different, like the shape of this thing that

42:11 we're gonna do to find. As our boiler plate think it's t s. It's t s not not TypeScript. Yeah. So is there a boiler plate for all the supported languages in Pulumi then that people can just go and use as a template and get started with their language of choice. Right? Okay. I think the only one missing right now is .net. I think we've got that that on the way. But Python p we got a p y. And if you go and look at the provider in the TypeScript example, you'll see that, like, inside here,

42:41 this is like the go binary. So if you go into command we're still using the same go binaries to generate all of this stuff, but if you come back up to the root level. Yep. I'm actually, like, completely blanking on where the actual TypeScript code is here. Let me just have a look. I looked at the Python one before we started. Oh, there's TypeScript in here. It's under provider command resource. And then it was There we go. Yeah. We got some TypeScript here. So you should see setting it's doing very similar things. It's gonna read the the bunch

43:19 of different stuff and then the actual static page is defined there. And so again, like, the the only caveat with this is that your downstream users will still need to have TypeScript on node installed. So as part of your as part of your we are looking at some examples like you can embed these TypeScript files into you know, you can bundle these up as TypeScript binaries and all that kind of stuff. We're looking at different ways to make that easier. But it's essentially your downstream users because this is obviously gonna invoke this Pulumi program. You'll

43:52 still need to have TypeScript installed. Yeah. I wonder if you could just embed like a node runtime. I think there is a couple of go versions into into binary. Of course, the size of that may be a little bit ridiculous at that point. We have our hackathon coming up. I'm gonna come up with some wild and crazy ideas for things we can do here, hopefully. And then there's the Python one as well. So if you do p y dash boiler p y dash boilerplate. Again, in provider. I don't think I've ever looked at a hyphen.

44:25 So the actual code is in x y v provider at the top there. Alright. And then static page at the bottom. I have strong opinions about Python, which I won't share here because I may get I may get piled on on Twitter. But, yeah, like, if you wanna write it in Python, then go nuts. Well, that that's the joy, right, of of why we wanna use Pulumi over any other tools like this. Is that flexibility to stick to the languages, run times, and tool chains that I'm already familiar with? Like, I don't have to go and learn anything

44:58 new. So, you know, whatever your poison is, go for it. My my my perspective as well is the, you know, application developers especially like they're a lot of cases, they're they're kinda getting exposed to cloud environments and cloud engineering environments. That's already super confusing. And then when you add a new kind of like declarative YAML document on top of it that they might not understand, you know, it's it's a massive learning curve. Like imagine somebody especially I always kind of compare it to as infrastructure engineer. Imagine if somebody told me that I had to learn front end and

45:31 back end at the same time. Like, you're just throwing things at me that I don't really understand. So it's it's a it's like my perspective has always been using these familiar languages is a really nice way to kind of gradually introduce people to new concepts, but using something that they already know. It's it's a much better way of learning in my experience. Oh, yeah. Definitely. Alrighty. So I think we should generate this. Now let's generate this. So let's go to a terminal and we should be able to do and I need to remember the make it's actually

46:02 we do we use the make file. Yeah. So we need to first run make generate, which will generate all of our SDKs and it's also gonna tell us if there's any problems. Can I just can I just go for it? Let's go for it. Yeah. I'm in the wrong directory. You're you're in the wrong directory. Alright. No. I'm not feeling as brief anymore, I'm just gonna do generate. I've lost my confidence. This is kinda this will show you what's actually happening here. We're running go run to actually generate the we're passing the schema in, and it's allowing us to generate the Go

46:37 SDK, and it's gonna generate the TypeScript test again, all that kind of stuff. It's taking longer than I expected. Excellent. We have an error. This is what we love to see. So let's have a look at what we've done wrong here. An assertion has failed. Oh, this is a lovely error. We've obviously made a mistake. So if if, it it's happening in the SDK portion. I'm just gonna look the code real quick. I'm sorry. You can say I got it wrong. I won't be offended. There must be a problem in the schema itself. We have an error here. Yeah. Haven't updated

47:22 any of this, actually. We haven't updated anything below here. And in fact Did we forget some do we forget something? Let me look at my example that I wrote of three weeks ago. And Paul Stack says the token is incorrect. The token is incorrect. Gonna give us a bit more of a bit more help here, Paul. I'm half tempted to just bring him in here at this point. Yeah. Come on, Paul. Show us what's wrong. Which token? Does he see that from the error message? Let's see. We got main dot go. The token is incorrect. I'm gonna

48:14 Maybe something in the schema. I think the code looks alright and it's not I think it was something in the schema as well. Yeah. Is it did we get the token wrong production app index? Paul asks, where is our declaration of the type? Are you being cryptic on on purpose? I I we both know Paul well enough to know that he probably is. Okay. So where is our declaration of the type? Declaration of the type? Alright. Let's turn this into crystal me style deployment. Start the fence, please. This is our declaration of what a deployment is. Are we

49:06 missing anything in a struct? Nope. That so that struct will output the that that would have usually that would have the outputs. So, no, that that should be absolutely fine. Okay. We're getting some more hints from our a good friend here who suggest that we open schema dot JSON. We take a look at the resources. What is the first item? It is what I expect it to be, to be fair. Yeah. Is component true, input properties. I actually have a working version of this as well and it looks exactly the same. So we've missed something.

49:50 Can you rerun the make again? I wanna take a look another look at the error. Yeah. I'll send Paul a link. He can just jump in for five minutes if he wants. So this is in command production app provider. Alright. Command. I love it when we get just random random extra guests. Well, until he learns how to articulate his thoughts properly through the chat system in order for the other that we are suffering in a live stream. Yeah. Said So what I think he's what I think he's talking about if you go back to the

50:44 if you go back to the Versus Code, I'm in main provider. So if you look here And January resource one. No. That was January. So this is where the error is coming from on line 24 production app, but it looks right to me. Or maybe that should be deployment. I think that might be no. That's the provider name. Interesting. This is the full this is the great thing about using brand new stuff, when you are in a livestream. I'm I'm pretty confident we'll get this working. Alright. Well, PR is asking, did we remember to sacrifice our first born to the demo

51:33 gods? I mean, no. I knew I've got something. Didn't quite Okay. Sorry. What was your hypothesis there? So let's look at this error message. I'd like to understand what assertions is the generator doing here against our schema and our code. So it's looking at the actual provider name at the top of the schema dot JSON. Which is our production app here? Yeah. My I think what what I'd like to try is let's try changing, if you go back to index here? That's just like the actual place in the Pulumi resource model where it lives. That's the

52:20 only thing that it's not, that is that I know that is definitely shouldn't be changed. I think we should try calling it deployment, like the actual token name in the in the previous file. So in the yeah. Let's try changing that to deployment, on '24. Yeah. Let's give that a try. Well, this is no complaining about Pulumi schema. That's because of the that's because it doesn't exist yet. The the it will generate a schema dot go file when this step works. Alright. Okay. It seems to be the same. What okay. Like, my my idea here.

53:18 Hey, Paul. Hey, folks. So, Leo, I think the issue is that your import bay bay bay base pass may not be correct in your Pulumi schema. It's trying to tokenize what's coming out of, further down that that list, and it's it doesn't seem as though it's correct. Oh, I see what you're saying. Okay. So you're saying that line 31 on this schema Yes. You think that the that should be deployment at the end there, so lowercase deployment? So Not necessarily deployment. It needs to be the name of the actual SDK that's that you're trying to generate.

54:03 So, like, for example, for me, I my input base path would be github.com/stack72/PulumiGCPcloudrunglobal/SDK/go/GCPcloudrunglobal. So it it all depends on what you're actually trying to generate at the back end. Yeah. I think I think he's right. That needs to be deployment. Give that another try. I think I think that's probably The funny thing is Lee hates it if I'm right. I do hate it if you're right. Absolutely. So what I'm gonna recommend here is I'm gonna get this closer to the to the version that we actually had working. So I'm gonna change this to production app and then

54:45 because, you know, because I knew this was gonna I knew this was gonna happen. If you what I had this was as production app, app ads, production app, because these are all just structs at the end of the day. Let me look at my example. New Which file are you modifying just now? I am in the actual provider that we created. So although it's it's bouncing me around a little bit. So I'm gonna do new production app. Production app. Is really great because we can feed this back to, the team as like like, this error message

55:42 is just not very helpful. So we'd obviously need to open an issue for that, make sure that we get that right. So this is what I when I when I ran through this yesterday to make sure that this was actually gonna work, I actually called this production app ARG rather than production app and deployment. And again, it's just structs, but I think we've missed a token somewhere like Paul said. So let's give that another try and see what happens. Oh, wait. I know. Oh, I know. I've just figured out what it is. I know exactly what it is.

56:12 So if you see where I am right now Yeah. I'm following you. So this is the problem. If you scroll down, you still got a reference to static pay we still got a reference to static page ARGs here. So this should be we've changed it. That should be production app ARGs, and then this needs to be new production. Yeah. Line 29 has a static page on it too. 29. Construct. Oh, no. Construct deployment is still Construct it just yeah. Just rename that function to construct deployment. Alright. There we go. There we go. That, I think, is what the problem was.

57:04 That does not look correct. Still getting an error. Yeah. Well, probably we've probably messed yeah. We've messed one change in back. So deployment dot goal lane 58 has that deployment RX on it. Oh, no. That's no. That's correct. Because that's the actual Oh, yeah. That's the actual deployment. Yes. What about this one here, Lane 30 9 at the end? Looks wrong. Yeah. That looks like that's like it should be production app because it's gonna return an instance of a production app. So let's try that again. No. Come on. Yeah. Let's look for red squiggles. Oh, there's a big one.

58:01 So we can't register component resource because there's no new deployment. This is a production app. And I'm I'm remembering now the exhibit the reason why I call this production app in rather than deployment is so that I could search for errors, because we're using the Kubernetes SDK and deployment and it returned a bunch of stuff. So that should be a production app. Alright. There you go. No more red. Come on. We could do this. I mean, I don't have any confidence in me, but I know you two will get it. Let's see. Let's use the s code here.

58:43 It's normally quite good at telling us where the reds are. Everything looks alright. So as the code's not complaining and goes language server's happy, maybe now it's a schema thing. Maybe. I'm also gonna can you rename deployment. Code to production app with a capital a just to make sure that it's like So After all this, it will be it'll be it'll be a yes. So just rename that to production app with a capital a. There we go. And let's take a final look at the scuba dot JSON. Yeah. This still has deployment here. So that needs to be deployment. That's the

59:28 actual, that's the resource that's gonna be generated. So that's that's okay. I'm just going through this line by line at the moment. Required inputs. Nah. Yeah. No. That's right. I'm gonna try it. I believe in you. Yep. I'm wrong. Can you do me a favor? Can you git git commit what we have? And like I have a working instance of this and so I'm gonna start copying code over to see what we've missed. Oh, yeah. Of course. Yeah. Go for it. So just get add everything? Yeah. Get add. Just get just do an initial commit.

1:00:27 YOLO and push. Did I clone my fork? Yeah. Did I? Yeah. Well, that's not gonna work. Yeah. I don't think you need to push it. Just having it locally is probably good enough. Alright. I thought you wanted to maybe No. No. No. I'm just I'm gonna do a git diff when we when I start copying stuff over. Oh, yeah. Cool. Basically. Makes sense. So this is my schema dot JSON, and the only difference here is that I added an output. So I'm gonna save that. Mhmm. And if you go git diff now to see what the differences are.

1:01:15 Did you save it? Oh, no. I didn't. Alright. So the description's changed. Image reports the other way around, but other than that, there's no gold definition anymore. It's a little bit further down. Alright. There we are. So that's so you can see the package name and the import base path are obviously set to things that I would have. If you generate that, see what happens. It's probably gonna fail because the import's wrong. Nope. It works. So what? What's different here? So the descriptions, the input property ordering, none of that can matter. Right? The output URL and a fussed about

1:02:07 I don't think that's important. So it must be just So that was I obviously didn't get a chance to actually get this done last night, but the idea here is that this production app will output a URL from our load balancer. And so eventually, we'll get to the point where we can update this. So I would recommend here is let's update the import base path to actually remove my name and do a Rawkode instead of my GitHub username Jack Storm and then rerun it. But now that we have this in Git, I can go and have a look and see

1:02:37 what was different, basically. So let's rerun that. That works. Must just have been a typo. See, this is the problem. Like, what we're actually hoping to do is actually emit this JSON scheme rather than build it manually so you can't make these mistakes. I think this is a great example of, like, why using these kind of, like, untyped documents can be so difficult. The only part of this that we had trouble with is this untyped part. So let's also remove, the properties and required outputs, because we're not gonna use those. So if we open up our,

1:03:15 so that property sees an empty map and then require yeah. And then so we should be able to rerun that. No. It's good. Oh, Paul left us. Thanks for saying bye. See you later, Paul. Thanks for your help. Okay. Yeah. No. We appreciate it. So that's the so that's the schema that's generated. So now we should be able to do make build as well. So what this is gonna do is it's gonna, sorry. Go ahead. I just was I I liked what you were saying there as I was trying to type and and kinda think at the same time. But, like, the

1:03:54 schema can be inferred from the canonical implementation, and you're working on generating the schema from, like, the ghost structs or the type script. Yes. Okay. Awesome. That's exactly what you said. Like, so the ghost that part of the reason why we got that Pulumi definition on the ghost structure is we should we we are working on kinda generating the schema manually. I mean, I guess you could implement a validator on the scheme as well, but, like, I think it's kinda telling that the one part of this that we had to have handwrite basically without any type hints caused a

1:04:23 bunch of problems. And it's still not clear what that problem was. I hope you're gonna git commit this so I can go back and look at it later. Yeah. I'll push it up. Don't worry. So just to talk about what's actually happening here. So you obviously don't have dot net installed. So let's just update the make file and not generate the dot net part. K. So on build, we do not want dot net SDK. And we don't wanna install it either. So if you look at the make make file as well while that's running, we'll do remove

1:04:55 install.net Yep. So, yeah, again, to just talk a lot a little bit while what's happening here. Like, what this is doing is it's building us a binary that we will then distribute to our users. Usually, you would install this with Pulumi plug in install, and that will get easy need either needs to be in your Pulumi directory or in the actual path of your, you know, on your machine. So it's doing a go, it's doing a go build, and it's actually generating the schema. If you look after the r and minus r f, it's gonna clear out your bin directory.

1:05:30 It's gonna generate the actual schema, which ends up being a go file, which is why we were getting that error early for Pulumi schema. And then it's gonna build a binary that you would distribute. And now here is the point where it's gonna generate all the different SDKs. So the Python and Node JS SDKs. So are these like, you know, when I you know, say I wanted to ship this now, like, I'm just pushing the code to get hub and go developers can import it from that source for TypeScript. And my publishing to NPM for Python, I'm publishing to pipeline.

1:06:01 Right. Okay. That's exactly it. Yeah. So you would need to jet you would need to push the packages to all of your respective package managers. You also need to distribute a binary to the users. And we are working right now on automatically generating automatically being able to grab that binary from when you do the NPM install or the PIP install. This already happens with Pulumi, for all of our kind of, like, multi language providers. When you do NPM install at Pulumi Kubernetes, it pulls down the binary for you. And so you'll be able to do,

1:06:34 you know, be able to do the same process basically. These actually end up looking just like those by those, like, Pulumi providers. So it's a binary and then an SDK. I see you running in the install command now. So this should create a Yarn linkable package for us that we can then use in our example. Alright. So does that mean we wanna create a Pulumi TypeScript application now to be able to consume? I generally put in an example so that everybody can see what it looks like. So I'll do make make directory examples and then

1:07:07 TypeScript. Okay. New directory example TypeScript. And we wanna add Pulumi new in this? Yes. K. Example. TypeScript. Pulumi new. TypeScript. Just TypeScript. I just do put I just do Pulumi new TypeScript here. Yeah. That should work. Let's see how that installs there. Okay. That's done. So now you should be able to run Yarnlink. And the reason that I told you to update so obviously, you wanna put you can't publish this to the app Pulumiorg. So now you would publish this to at Rawkode in NPM. So we can Yarnlink that package inside that example. Yep. Fighter? No.

1:08:19 No. You just the just your own link is fine. It did it it's already in like, the install make, already did that. Right. And so then we can open up that example, that TypeScript example. Import all. Yarn link is magic. Don't pretend to try and understand understand it. At Rawkode. Wow. And then you should be able to do a const Rawkode. Yeah. Equals new. It's a it's a class. Right? Yeah. And then we also need a name, so let's just call this example. Yeah. So name and then args. So example, args. I don't think they're all complete. It's quite

1:09:15 kicked in there yet, but we know that it's a image. And it's cap, I think. Yeah. So then image which set in NGINX. I'm gonna use the Yarn as well first. It's because you're using Rawkode too many times. So you need to do if you go back to your Oh, yeah. So const. There we go. Yeah. I wonder if that fixes the yeah. There we go. Okay. So deploy engine x. We've got a report. So we should be able to Pulumi up this if you've got your Kubernetes. And again, this is a this is a

1:09:49 component resource. So you could pass providers to this if you wanted to. This is just a standard Pulumi application. Should be able to do Pulumi up. I do have a context set. There's no pods running. We run a Pulumi up. Oh, TypeScript. Wanted to just wanted to make you swear a bit, Avatar. Hey. Oh, I'm on. I was panicking then. Alright. So help me understand what this is actually doing. Right? We have linked to the Yarn generated SDK, which is generating types so that TypeScript is aware of what we have available to us. But as it as it calling out to

1:10:32 a gold binary, right, to do the actual deployment and the service and such. I am not the person to explain this, but I'm gonna have my very very best. Right? So what this is doing is it generates all of the actual, like, SDK and then just this registers inside the actual Pulumi engine. So that's what the binary is doing is it basically takes the TypeScript, converts it into like a a schema implementation, and then the Pulumi engine does all of the work. So that's why it's really useful to write these in Go because you can just distribute

1:11:05 that binary and it can call the go straight to the Pulumi engine. This is really, really kind of, like, deep technology, and I'm not gonna profess to understand quite how it works at its at its full level. And I even asked before I came on. Was like, somebody's gonna try and explain how this works to me because it is it's literal magic. Like, we've written a program in one, you know, we've written something in one language and we are able to consume it in another language. It's just wild to me. And this will work with Python. It will

1:11:40 work with Go. We've obviously made a mistake without Kubernetes definition rather than the actual Pulumi program. So if you do if you do a new terminal, new qctl, it's probably something silly. Kubectl get namespace? I don't know. Just pick up my yeah. It has created the namespace. Kubectl get p o minus yeah. Oh, wait. Why am I doing Get get get get But I think the service has been created. It's got a low it's actually got an IP, a load balancer IP, and stuff like that, but it's never gonna find any pods because, yeah, we've missed something in the spec.

1:12:18 Structuring the Go Provider Code

1:12:29 And we can wait for this to time out and see the error. I don't know if I'll get it either. Minutes. It's ten minutes, so it takes a little while. Right. So what I would do is control c out of that and then Pulumi destroy. Here we are. There we are. Required value for the container port. Or no. It looks like our actual types aren't coming through properly. So our input types aren't coming through properly. So I think there's a problem in these the the two things that we specified as arguments aren't actually coming through all the

1:13:06 propagating all the way through from the schema. So let's take a look at that, see if we can get it working. That's not the right file, is it? That's the other one. Yeah. It's in the No. One? It's in the production app. Yeah. That's the one. Yeah. Okay. Oh, you know what it is? I'll I'll I mean, maybe you can spot what it is. Yeah. You've already spotted it. Yeah. That's why. So you can see there the relationship between the schema and the actual strokes. It's because so we'll need to regenerate the SDK now. Yep.

1:13:46 So make generate, make build, make install. I've got this. I know what I'm doing. You're a hero, man. You're doing a better job at the developer advocacy part than I am at this point. So Well, Paul's given us some hints for this mistakes we're making along the way in the chat as well, but I'm just gonna ignore him because he left us. Alright. So we'll give us a few seconds. I don't think we need to change anything on our TypeScript side. Right? We're linking to the dependencies. So really, if we just run a Pulumi up again, hopefully, those two parameters are being

1:14:22 pulled through correctly and we'll get our deployment. Okay. Pretty magic if it works. I mean, like, obviously, the the this is the first alpha ish release of a very, very powerful thing. And part of the reason why I wanted to do this live with you is just to kinda get an idea of obviously, I'm pretty close to it. So I kind of know all the little things that we need to iron out, but being able to explain it and see those things. We've got a lot of you know, we've got some really exciting authoring improvements coming through as well.

1:14:57 So we expect this to kinda get better and better over time. Nice. I think it's definitely solving a real problem. Like I said, you know, I I work in cluster API bindings that are using Pulumi and TypeScript, and they're not consumable by people that don't wanna use TypeScript. And like right away, I could just see that I wanna go and do this and generate the type. So the implementation language is almost irrelevant to a certain point. Yeah. Absolutely. Alright. Let's go for it. Let's see. So it should tell us it it should tell us it wants to update the deployment because

1:15:33 that never got created. And the service has changed, so that sounds like it's a good sign. It worked. Let's create a replica check. Deployment initialization complete. So now it's waiting for the pods and images effect. It's already done. And if you so let's take a look at actually how how long have we got left? I wanna kinda run through some more. Yeah. Ten fifty minutes. So let's take a look at the SDK directory and see what actually happened here. So if we yeah. If we open up if you look at the SDK, we generated the things that all in dot and we

1:16:11 can write a go example as well probably. But you can see, look, if you look at the package dot JSON, it's just a standard NPM package, which is called Rawkode. This version gets like updated and it goes into the bin directory. So that's what we Yarn link. So if you open up that bin directory in Node. Js, you'll see that that should have the correct version. But you'll see, look, this is this has got all the types and stuff that's actually been generated for us. And if you actually look the thing that kind of is is crazy to me is

1:16:39 if you look at the deployment.d.ts or the deployment.js, all it's doing is deploying the the all it's doing is creating the actual shape of this thing. All of the work is actually done in the Pulumi engine. So it's not define it's not we're not generating a Pulumi program. We're just generating the types and the schema, and then the Pulumi engine does all of the work, which I think is just wild. Right? Like, I think it shows the power of the Pulumi engine to be able to to to show that you can kind of do these

1:17:11 things. And then there's also the Python SDK as well. So that obviously is is available to us. Your favorite one. Right? My favorite. What I'd like to do if we if we could see if we can get it work with with replace is do a go version of this as well. But again, like, this is the part this is just, you know, the the input types that we've got for each of the different SDKs. And that's basically it. Like, you know, we we've we've generated a consumable thing. And and some of the things that I keep thinking are like, I created a

1:17:44 Pulumi AWS load balancing controller multi language component, which I think is an amazing use case for this because if you think about AWS load balancing controller as an example, generally to install it, you're gonna need at least two different things to actually get it working. You're gonna need CloudFormation to deploy the AWS IAM roles and all that kind of stuff that it needs to use. And then also something like Helm or Kubernetes YAML to deploy the Kubernetes parts. With the AWS load balancing controller Pulumi multi language component, it just works. Like, it it deploys everything

1:17:45 Implementing the Kubernetes Resources in Go

1:18:19 in one go. And I'm really excited about creating things like production ready implementations of Helm charts is a really, really good example. You know, rather than kind of running a bunch of Redis replicas inside, you know, inside Kubernetes, you can use your cloud providers hosted Redis, to to be able to do that. And I think Paul already mentioned he did a amazing implementation of Google Cloud's Cloud Run multi language component, which allows you to just specify. All you need to do is specify an image, and it deploys a multi region global Cloud Run across all of Google Cloud's infrastructure

1:18:57 in a single line of code. You know, like, it it's so powerful. And the other thing as well is if you are writing things like Terraform modules or all that kind of stuff or CDK constructs, you can essentially write these Pulumi multi language packages. And instead of kind of going into one ecosystem, either the HCL ecosystem or the AWS ecosystem, you can go to all of our supported language ecosystems and all of our supported cloud providers. So the reach is really, really, really far. Awesome. Very, very cool. Well, all of your bits work. I'm I'm

1:19:30 now really curious if my bit worked and whether I can actually browse to this application. And my fear is no, but damn. Maybe did we specify a port? We didn't specify a port. Oh, we did 80. Yes. And there's NGINX, so it should be working. Oh, well. Well, there's something for me to fix later. What I will do is just put forward to it. Least I can pretend some of my stuff works. 80. 80. 80. Hey. Look at that. It's the simple things that keep me happy. So what I what I'll be what I like if if you if you commit this

1:20:18 to Git hub, you know, this is a great like kind of like teaching example, like a nice and simple straightforward example of a multi language component. Again, one of the things that's missing here is you're probably going to want to pass the load balancer output to other Pulumi resources or maybe the namespace that's been created. So the next step will be to add those outputs, and that would again go in the schema. So you would say the URL, for example, is a great way of kind of exporting that thing. And then again, you can pass

1:20:45 these things and create dependencies between these things. So you could say, let's say you wanted to register a DNS name for the IP address, you could use another Pulumi provider like the cloud platform Cloudflare provider, pass that output into the DNS output and, you know, you're kind of off to the races basically. Nice. Awesome. Very, very cool and powerful system for working with Pulumi. It's really cool to see that and just I'm really impressed that it worked. Well, I mean, only like I said, they they I'm I'm pretty happy. The only problem we had a problem with is the is

1:21:22 the JSON schema. We know that there's improvements needed there and we're gonna you know, we're working hard on those those kind of improvements. But it just shows you handwrite something and you're gonna have problems, right? Like Yeah. But those things, right? Like improving the authoring experiences you measure. Those are just quality of life things. People can, you know, start to take advantage of multi language runtimes and packages now allowing them to, you know, just like you said, deploying to Kubernetes and Helm charts. Like, being able to have idiomatic or convention based approaches per organization or per team and satisfying that through Pulumi

1:21:58 packages is a pretty solid way to start to start doing that. Yeah. We've had we've had, like, large large customers who have large engineering organizations who are, you know, seeing the capabilities of this and realizing that, you know, it means that they can can bring in different organizations who perhaps don't want to write things in go, perhaps don't wanna write things in TypeScript. You know, they're they're multiplying their capabilities and it we have companies who customers who are creating internal SDKs that kind of abstracts all of the stuff away in similar way that we did

1:22:30 to allow them to kind of really provision infrastructure really, really quickly. Awesome. There's just two small questions if you're happy to take them and then I'll I'll link Would love to. Get back to your day. So, Fanny asks, is it open API schema, the schema dot JSON? No. It isn't. It's a it's a structure of the actual internal Pulumi, schema, which is not open API. It's all done over gRPC and protocol buffers. It's mainly just a it's just mainly just a declaration of what things look like. If if we think I don't think there would be much value in turning that into

1:23:06 an open API schema. We are documenting the skipper schema and maybe we could use open API to make sure that everybody knows what that looks like. But the best thing that you have right now is just to take a look in the example that we put together and kind of fill it out from there. I think you should abandon the JSON and and use queue for this, but I'm I'll I'll preach the q goodness to you another day. We got I'm still I'm still in the JSON at church. I haven't come out from that yet. So Alright. Last question, Andreas, who

1:23:34 also thanks us for the bleeding edge demo. I'm gonna show that again because, know, as I do appreciate you joining me today, Lee and walking us through this. But Andreas asked, is this the same quotes magic that allows us to use the providers as they're based on the same system as the providers being concerned for multi languages? That is exactly right. Yes. So what we've done here is we've taken the magic that we have with our providers that we use to like, when we bridge them from TerraForm providers, when we create the Kubernetes and as your native providers, it's the

1:24:04 same technology. And what we've done is just kind of extend it into Pulumi components, and we register those components inside the actual Pulumi engine. So the great thing about this is if and when we add another language and we're still talking internally about what that language might be and when that when that will be, I'm sure I'll get messages asking for Ruby and Java and all that kind of stuff after this. Rusty. Rusty, we haven't made decisions about this yet. But the point I'm gonna make is when we do add support for that language, updating to that version of the SDK, let's

1:24:38 say hypothetically hypothetically people, when we add Java support, all you'll need to do is update to the latest version of the SDK and it will generate those language bindings for you and you will get you know, every single time Pulumi will add a new language SDK in the same way that we get for the providers, like Java support will come in. You know, it will happen for the components as well. So it's exactly the same technology, super powerful, you know, magic, you know, Isaac Asimov said, you know, indistinguishable from magic. Awesome. Alright. Pulse taxes, can't wait to see those

1:25:13 Equinix metal packages. You're damn right. Those are coming soon. And we've got one last question from Andreas, and then that's it. I'm leaving it there. Andreas is asking, could you say some words about the isolation between two components from a runtime perspective? Read NPM dependencies. Does that make sense to you? I think so. If I'm not getting this right, Andres, then please feel free to reach out to me on Twitter at Brigzel. Essentially, the the the the runtime dependencies are basically because we built this in Go, we obviously need to actually bundle the Go dependencies into

1:25:45 the binary, which is know, from a user perspective, like, not completely transparent. They don't need to know about that. When we generated the SDK, if you remember, we looked at the schema dot JSON really early on and we defined what those runtime dependencies were because we know we're gonna use the Kubernetes SDK. And so that when we generate that SDK, for example, NPM or PIPE, it generates a package dot JSON with those dependencies in there. And so you as the user have full control over what dependencies the the thing needs. An example that I put to that I'm

1:26:18 putting together right now is, you know, you might one the things I'm gonna write one of these in Python, god forbid. But I'm also going to try and update the and it's gonna be an IAM type provider that uses parliament as a, you know, as a linter for those IAM profiles sorry, IAM policies. That will need to be installed when you actually kind of install the the component itself. But you have control over what the user installs. There's no cross dependencies between these things. So, you know, as a as a Go author, I don't need to tell them to install

1:26:53 any Go modules or Python modules. It's just the actual runtime that they're selecting. Selecting. Awesome. Alright. Thank you very much, Lee. It's always a pleasure to spend a bit of time with you even more so when you're showing me Pulumi awesomeness. If if anyone else does have any more questions, I've stuck Lee's Twitter handle on the screen. I'm sure he'd be more than happy to help you. He's also very active in the Pulumi Slack, which I would encourage you all to join and ask loads of awesome questions about this magic that is happening here. Any last words, Lee?

1:27:26 No. I I really appreciate, kind of spending time with you and not being under the pressure of fixing a Kubernetes cluster. So, yeah, it was really great, and I'm looking forward to kinda coming on next time we have more awesome features and showing them off. Awesome. I cannot wait. Alright. You enjoy the rest of your day. I'm gonna finish off today. I will speak to you soon. Everyone that watched, thank you. Have a great day. Awesome. Thanks. Bye. I just clicked finish, and it said video not found. So we're gonna do this lo fi. Bye bye.

Technologies featured

Meet the Cast

Weekly Cloud Native insights

Stay ahead in cloud native

Tutorials, deep dives, and curated events. No fluff.

Comments, transcript, and resources

More from Rawkode Live

View all 173 episodes

More about Pulumi

View all 9 videos
Kubernetes

More about Kubernetes

View all 172 videos