Transcript from the "Locals" Lesson
>> So now that we've done that, the next thing we wanna do is, we wanna explore something called using dynamic configurations, okay? Now what exactly does that mean? Well, let's look at our code really quickly here. So if you notice, my code has module project and module workspace.
[00:00:19] Can anyone tell me what I would have to do if I wanted to create another workspace? What do you guys think I'd have to? What would be the most straightforward way of creating another workspace? Can anyone tell me?
>> Yeah, copy-paste, yeah, exactly. And so, I go like this.
[00:00:36] This is the most common way of doing it, right here. And then what else would I have to do? Copy-paste might not be enough. I said that there was one other caveat, right?
>> You have to edit it?
>> Yep, and what do I have to edit?
>> Probably the description and name.
>> But what is identical here that might be a conflict?
>> Product ID?
>> Close, but it's a little bit more literal, look on lines 11 and 21.
>> You cannot have the same module with the same name.
>> Exactly, and what would that do? What would happen if I had the same module with the same name twice?
[00:01:08] What do you guys think would happen? Do you think it would work?
>> It would override the first one with the second one?
>> It'd conflict. It could actually fail. Terraform would say, hey, you've got two things with the same name. So if I do Terraform. Now just to note, you don't have to do validate with doppler, because validate doesn't actually communicate with anything, but then there you go.
[00:01:25] Sure enough it says, hey, you've got duplicate module here. Can't do it, right? So what we wanna do is, if this is the approach we wanna take, we need to start doing things like, okay, let's make this one example. A, right, and then that kind of becomes the process, right?
[00:01:44] But it's very tedious. What happens if you wanna update all of these names, right? Then you have to go through one by one by one by one by one to do that. It's very cumbersome and honestly just annoying to do. So there is another approach to this. And I at least like to call it dynamic configurations, right?
[00:02:03] The idea is, is that we do have HCL, right? We do have a [LAUGH] pseudo-programming language available to us, right? It is really what's called a domain-specific language, which is the idea of a language that's not a general purpose, you can't create APIs and services with it. But it's a language used to build things, right?
[00:02:24] And so we can lean on that code or that language to be able to make this a bit more dynamic and easy for us. So what we wanna do is, is we're gonna introduce a new concept called, oops, sorry. We're gonna introduce a new concept called locals. And we're gonna create a file, [LAUGH] [INAUDIBLE], called locals.tf, right?
[00:02:47] So again, we're gonna create a file called locals.tf, right? Then what we're gonna do is, is we're going to open that file. Now, locals, or what I'm showing you right now, is a concept in Terraform that allows you to essentially create variables locally, right? Now Terraform has a configuration approach to how it defines things.
[00:03:10] So you're always gonna have a meta-argument, and then some brackets, and then some attributes in those brackets, right? Whether it be a local, whether it be a resource, whether it be a module, whether it be whatever, this syntax is pretty much always what you're gonna end up doing.
[00:03:26] So let's think about configuration here. What do we need to configure? From a resource perspective, if I pull this up from left to right, what resources do we need to configure? And I'll give you a hint, their names are on line one and line nine [LAUGH]. What resources you guys think we need to configure here, if we try and look at it from that angle?
[00:03:54] It's actually very simple, it's project and workspace. We need to configure projects and workspaces, right? So the idea is, is that we're looking at these modules now as reusable for loops, almost, that we can create multiple projects with and multiple modules with. So how can we achieve that?
[00:04:16] Well, let's go ahead and go into locals, right? And what I'm gonna do is, I'm just gonna simply create a new set, I think is what it's called attribute set, called project. That is now going to be where I'm gonna put all of my projects, right? Then I also have a workspace.
[00:04:36] So now I'm gonna do workspace. Do the same thing, right? Now when I said before that we are literally trying to configure workspaces and projects, this is what I mean, right? We look over here and we say, well, this resource is meant to be a project. This resource is meant to be a workspace, but I'm gonna have tons of them, right?
[00:04:58] So maybe if there's a way to where I can only have to touch this once, right, but then really do all of my defining and variables over here. If you've ever used a programming language before, this is actually very common, right? You just make a variable or map or something like that, and you use it throughout your code.
[00:05:15] That's what we're doing, that's all we're doing. We're just making the unique part of the code and we're separating it so that we can easily configure it later through the logic, and we don't have to be worried about actual modules and stuff like that. So we have a project, right?
[00:05:35] Let me actually close this really quickly, reopen it, just so that my syntax, there we go. So we have a project, right? We have a project. And you'll notice that when you start using Terraform, if we go back to our main, it's mostly key value, right? So it's like you got a key, and then you have a value for that.
[00:05:55] It's mostly maps is really what I'm trying to get at here. And so if I wanted to, I could take two different approaches to this. I could say, okay, well, what I wanna do is, I wanna say, instead of using the name project, I actually wanna use the name fem-eci-, what is it, workspace.
[00:06:17] Yeah, workspace. Or no, sorry, project, right? And then I'm going to, one more time, do equals. And then create an attribute set for it, right? So now you can kind of start to get an idea of how we're constructing this configuration, or what we're now gonna call our DSL, or domain-specific language.
[00:06:43] So we're kind of building our own domain language or domain configuration on top of their language to make our lives easier. So what exactly, if I have a project, what values do you guys think I would have to put in here? What values from project do you think I would have to put in here that are needed for it?
>> Name and description.
>> Name and description. Why not the organization name?
>> That comes from a different variable.
>> Right, it does, but there's another reason why we don't wanna do that yet. What would you think that reason might be? Why would we not want to make organization name dynamic?
>> Okay, you don't want that to change, right, you want them all.
>> Exactly, you don't want it to change. I don't wanna have to, think about liter, [LAUGH] it's amazing. One of our community members from Stream loves to call DevOps the janitors [LAUGH] of engineering. It's kind of true.
[00:07:42] [LAUGH] You have to think about what you're gonna be sweeping and how much of it you wanna sweep man. And a lot of it is about thinking about, how much am I actually trying to put on myself versus how much can I make easily dynamic? So in this case,
>> So you're not gonna grab it from variables anymore then?
>> No, we are, but we're just gonna leave that there, right? Because in a normal programming paradigm, for example, right, if we did a iteration of a project so that we're creating multiple projects, we don't want the organization name to ever change, but we want the description in the name to change, right?
[00:08:20] So we do want those be configurable. Those become a part of our domain configuration, but anything that has to be static can stay. So what does that mean? Well, it means that now anybody can come into my automation. If I was to say, hey, I need a new project, could somebody make that for me really quickly?
[00:08:38] It's no longer even, what module, how do I? It's literally just coming in here and configuring it very simply. So in this case, what we'll do is, is we'll do description, oops.
>> Extreme description.
>> Yeah, but we're not gonna do name actually. Why might we not do name?
>> Is that implied with line three?
>> You mean line four.
>> Yes, it is. So it's key value. So you could save yourself even more time by just leaning on the logic of maps, right? So now I only need one value to configure my projects.
[00:09:22] That's it, right? If I want another project, That's it.
>> We need one key value.
>> What do you mean?
>> Wait, no, okay, you're right.
>> They can have redundant descriptions.
>> Yeah, the same description but-
>> That's fine, yeah, the only thing that needs to be unique is the name, basically, just so that they don't conflict each other.
[00:09:46] So we're gonna do this, right? Now that's our project. So what would be the key for my workspace then? Can anyone tell me? Come on, copilot, don't ruin it. Can anyone tell me? [LAUGH] Can anyone tell me what the name? Copilot, all right, it did it for me, all right.
[00:10:03] So anyways, the power of AI showed it for me. But we're gonna give it the same key as the name of the actual thing we're trying to create, right? This is how we start to make resources individual and unique, and for the specific things that we want. And because copilot, the AI, [LAUGH] was recognizing the patterns that I'm creating, it was able to easily take care of the rest of it for me.
[00:10:28] Now it didn't do, well, it did, but this is kind of up to you, okay? What might be one value we might actually want to add to this that's not there?
>> Project ID.
>> Project, yeah, project, exactly. You might not want every workspace to go to the same project, [LAUGH] right?
[00:10:53] Otherwise, that might not help you with organization whatsoever. So again, AI only go so far. [LAUGH] We do want to include project as well with this. And so, yeah, there you go, sure enough it can now see. But I want to note another thing, which is, I'm using strings as description and execution mode, but I'm using module.project.id as my project.
[00:11:23] Why am I doing that? Can anyone tell me? Why would I not just, I don't know, try and put a string there as well or something? So the dependency trees that we talked about before are just natively supported in the code anywhere. So if I set a value to something, and it's a resource that's going to be populated later, it doesn't matter where it is in the code, it will always make sure to calculate that dependency tree properly.
[00:11:58] This is something to think about when you're talking about creating dynamicness, right? Is you need to think about, okay, sure, I can use nothing but strings here, but I need to make sure that I actually have that dependency tree being set up properly. And so you might miss it if you don't actually have it in the right spot.
[00:12:19] And we do want it here because there might be multiple projects that we create first, right? And so the first thing that's gonna happen is because there's nothing in project that it depends on. It'll create the projects first, right? But then it'll also create the workspaces after that because we have the project ID being injected.
[00:12:38] Now again, it's using code, so it will take care of all the rest of it for us.
>> So where is that project ID coming from though?
>> It's coming from the module right here. So when this is created, module.project becomes module.project.
>> But where's the ID though?
>> The ID is in what's called an exported value, or an output. So if we go back to the Terraform workspace, right, this is a module that we're using. You're gonna notice that there's two concepts here. There's inputs, which is the values you give it, but then there's also outputs, right?
[00:13:17] Output variables are the variables that you can then use later in other parts of your code, right? So I'm gonna create a workspace, but I need to know maybe the idea of the workspace or things like that, then it would have an output for it. So for example, let's go to project, right?
[00:13:35] Output, look at that ID, right? Because I still need to get that ID for things I'm gonna use later.
>> So it's essentially it's being generated.
>> You're generating it with the, okay, so it's some just random string or something?
>> Yeah, exactly. It's whatever the provider uses, yeah.
[00:13:53] So this is the Terraform cloud ID of the project, yeah.
>> But this particular workspace that we're defining in locals. My mental model so far has been that main.tf is where our class definitions are, and locals.tf is where our particular instances of those classes are.
>> It'd be more like variables.
[00:14:13] Locals.tf is really just variables that get passed to your classes, right? And those are then being brought in as arguments, right? And then when you create a class, you then can export attributes, right? Same thing, a resource can export outputs that then you can reuse elsewhere, right? So for example, if we're using the class dynamic, instantiate your class, and then you say, okay, I need to make sure I export an ID.
[00:14:42] Well, then you say, this.id equals blah. Now it can be used elsewhere in your application code. That's the same kind of approach we're trying to do here with our automation.