 All right, I'm totally not going to follow this trend. I get five minutes and I have 25 slides. That's 12 seconds of slides. So stay with me, OK? Anybody here ever looked at the Kubernetes code base? Anybody? Quick, quick, quick. Yes, great. Have you found these gems, things like our staging repository, things like a bunch of sim links in vendor, things like a whole bunch of Go mod files scattered all over our code base, in fact, 30 of them? Don't worry. I will talk about all of these in a minute. Kubernetes is not your usual Go project. We kind of do things our own way, not always for really great reasons, but for a lot of history. So let me tell you a story. Once upon a time, we had a mono repo and everybody was happy the end, except for that one guy who wanted to import kates.io Kubernetes. Sorry, you're going to have a bad time. Kubernetes depends on approximately the entire internet. So as Kubernetes got popular, we built a client library, because it seemed reasonable that people would want to code against Kubernetes. So anybody who had to link our client library got this. So a funny story, when I was prepping this slide, I wanted to get a little chuckle there. And so I searched for the worst dependency graph I could find on Google Images. And I found this one. I was like, cool, I'm bringing this one in my slides. And I was like, what chaos is at the beginning of this? It's actually Kubernetes. So my point was made, I think. We wanted to publish small, focused repositories that people could use in the normal Go way with less dependency help. But we didn't want to give up our lovely mono repo. So that explains the staging directory. So we put all of this stuff in staging and we then export it through a robot, which publishes things into separate GitHub repositories. But preGo modules, the only way that you could go into doing this was with SimLinks. So we put a bunch of SimLinks in our vendor directory, which point back to our staging directory, which is that strange hell there. Did anybody know you can check SimLinks into Git? You can. So we also do a lot of code generation in Kubernetes. And we have a lovely little toolkit for this. We call GenGo. And we use GenGo. It predates Go modules. So it's written against Go's older tool chain libraries. We have generated about 33,000 lines of code in the Kubernetes code base. To tie it all together, because it all depends on GoPath and it's all preGo modules, we have this cute little script called Run in GoPath, which sets up a totally bogus GoPath. SimLinks all of our code into it, sets things up so we go as of 1.8 needed, and then it would run our tool in this GoPath. Tons of special case stuff in vendor directories. I threw one little example there where we said the staging directory into vendor so that the tools will work. And the truth is most of it works, but it's gross. So along came Go modules. And all of Go's tooling is broken when multiple modules are involved. There's just nothing that you can do that will make it work. I tried, I tried, I talked to the Go team, I begged and cried, none of it works. But the Go team, they heard us, they are awesome people, and enter Go workspaces. So they've given us a new way of describing this crazy setup that I have arranged in Kubernetes, how to use multiple modules at a time. And it's not exactly built for us, but it's perfect for us. So in theory, all I need is this Go.work file. And holy cow, it kind of works. I'm able to actually run Go across multiple modules at the same time. For example, I can run Golang CI lint across the whole code base all in one Go. So all that goop that I described before, we don't need most of it anymore. Some of it's actually broken now so it's time to clean the house. So step one, I enabled modules for our build. All hell breaks loose, all sorts of things fail. In reality, I'm doing this one piece at a time, but I'm fast forwarding because I've only got 12 seconds. Then I hacked up GenGo to use the new packages module, which is the new way of doing things, the module's compatible package. It's a pretty major change. My goal right now is to drill a hole all the way through the mountain. There's gonna be some debris left behind. I've got about 40 Fixmes in the code base so far. A lot of work to do still. Step three, convert all 13 of our code generation tools. Why do we have 13 tools? That would take more than the time I have. TLDR, they all need to be touched, every single one of them, and I'm only partly done with this step. Step four, everything got slow. Really slow, like 10 to 40x slow. What's going on? Well, the new packages library is very different. So we've talked to the Go team how to optimize for this stuff. My goal is that we get to plausibly acceptable performance. Step five, purge. Started deleting stuff, make all the references to GoPath go away. Hundreds and hundreds of touches. Step six, lots more cleanup to do. I have a running Go clean up file. So the status is I'm currently at 83, actually when I wrote this it was 83, now it's 88 commits. I'm not done yet, still going. I'm hoping that we'll get it into Kubernetes 127. I pity the fool who has to review it. Go X tools packages. I'm working with the Go team to see if I can justify making it a little bit faster, maybe doing it a little bit better. Lack of vendering, we gotta figure that one out. That's it, thank you.