microBean Helm v2. released

I’m pleased to announce version of the microbean-helm project: a toolkit in Java for working with Helm, the Kubernetes package manager.  This release is available from Maven Central.  The Helm version tracked is 2.6.2.

This release adds the ability to write out charts from their Java representations.  This feature joins the ability to read charts from a variety of different sources and to perform operations on the releases they represent, faithfully replicating the business logic contained in the helm binary itself, in addition to taking advantage of the business logic already present in the Tiller server.

This should provide the foundation for a Maven plugin, which I’ll be working on next.


microBean Helm Released: Helm from Java

I’m quite proud to announce the release of version of microBean Helm, a Java library that works with Kubernetes Helm charts and releases.  It is available from Maven Central immediately.

With this library, Java developers can now create and maintain Helm releases programmatically.

The Github repository contains more information as does the documentation site.  Have a look at the ReleaseManager and AbstractChartLoader classes to get a quick sense of what this project is all about.  Happy Helming…from Java!

MicroBean Helm: Charts.install(URL) now works

I’ve just released another snapshot of my microbean-helm project.

The latest addition is a façade class named Charts.

Among other things, it functions as a simple entry point into the common Helm-like operations you might want to do from within your Java program or library.

Have a look at the install() methods.  These install a Helm chart into a Kubernetes cluster given a URL to the chart location in one relatively easy invocation.  Happy Helming from Java!

MicroBean Helm: Helm from Java

I’ve just released another snapshot version of my MicroBean Helm project on the way to another real release.  (Helm is the package manager for Kubernetes.)

With this latest snapshot, you can install Tiller into your Kubernetes cluster like this (as before):

final TillerInstaller tillerInstaller = new TillerInstaller();
tillerInstaller.init(true /* yes, upgrade if a new version is available */)

Then you can load a chart from a directory like this:

final ChartLoader chartLoader = new DirectoryChartLoader();
final Chart chart = chartLoader.load(someChartDirectory);

…or from a tarball like this:

final ChartLoader chartLoader = new TapeArchiveChartLoader();
final Chart chart = chartLoader.load(new TarInputStream(new GZIPInputStream(Files.newInputStream("someChart.tgz"))));

Then, armed with that Chart, you can create an InstallReleaseRequest with it (as before):

final InstallReleaseRequest.Builder builder = InstallReleaseRequest.newBuilder();
final InstallReleaseRequest request = builder.build();

Then you can install the chart (as before):

final Tiller tiller = new Tiller(new DefaultKubernetesClient());
final ReleaseServiceGrpc.ReleaseServiceBlockingStub stub = tiller.getReleaseServiceBlockingStub();
final Tiller.InstallReleaseResponse response = stub.installRelease(request);
final ReleaseOuterClass.Release release = response.getRelease();

Full API documentation is online. More on the way. Teaser: there are many ways in the Java ecosystem to load a chart.

Helm from Java, Part 5

I’ve amended my prior class diagram to reflect the fact that ChartVersion “is a” Metadata:


Metadata is a generated structure—part of the Tiller API—that represents an actual Helm Chart.yaml file.

Why is this important?  Because now you can see the concepts: an IndexFile is basically a collection of all the Chart.yamls conceptually held (usually in gzip archives) by a ChartRepository.  And a ChartRepository is really not much more than an IndexFile.  This whole structure can be greatly simplified.

The way I see it, the fact that this notional collection of Chart.yamls is a file is incidental, and hence IndexFile is a very poor name indeed.  Structurally, all it is is a collection of things.  We can also tell that because of the Get() function signature, an item in that collection is uniquely identified (or at least should be!) by a name and a version.  This means that this notional collection of Chart.yamls is a set (and not, say, a list, or some sort of other collection type that permits duplicates).

Next, we can tell from the Add() function that really what you’re doing with this function is creating a new ChartVersion structure and adding it.  That furthers our suspicion that really what we’re dealing with here is some sort of collection type of ChartVersions, and nothing else.

If represented in Java, it really doesn’t need to be any more complicated than a Map.  In this case, it is a Map of ChartVersions (and hence Metadata instances) indexed by a key consisting of name and version.  So a ChartRepository too is really not much more than this Map located somewhere else, together with the information needed to talk to it.

Next, ChartVersion is also a poor name.  Something like ChartDescriptor is probably better: the fact that a Version attribute happens to be one of the things it logically contains doesn’t—it seems to me—elevate it to primacy here.  What this thing is is really a full description of the state of a Helm chart (the Metadata aspect of its nature) and some information about where you can find the real thing (the URLs attribute of its ChartVersion nature).

So instead of an IndexFile having many ChartVersions that it calls its Entries (?!), in Java I propose a Map (probably a SortedMap) of ChartDescriptors indexed by ChartDescriptorKey instances.  Obviously you can create one of these from an index.yaml file from a chart repository—but just as importantly you could create it from something else.

Helm from Java, Part 4

I’ve created a UML class diagram to help me decipher the main structures in the Go code of Helm around chart repositories and their related concepts:


For the most part I stayed true to UML notation.  Similarly-colored boxes are from the same source files:

A few interesting things stand out here.

First, from a conceptual standpoint, a ChartRepository is basically a glorified wrapper around an IndexFile, which is, in turn, a glorified wrapper around a set of ChartVersions.  A ChartVersion, in turn, is also a Metadata, which is a gRPC/Protocol Buffers object you’ve seen before (I didn’t indicate that relationship here on this diagram, but probably should have).  ChartVersions are stored (well, should be stored) within their containing IndexFile sorted by their version.  Go maybe doesn’t have the same concept as Java’s sorted collections and Comparators, so there’s some additional sorting logic that really you don’t need in the IndexFile concept.

ChartRepository instances are notionally “stored” in a RepoFile, but really what the RepoFile stores is a “pointer” to a ChartRepository—a primary key, of sorts—called, confusingly, an Entry.  More confusingly, a ChartRepository refers to its identifying Entry as its Config!  But if you think of an Entry as a primary key of a ChartRepository you should do OK.  A RepoFile is basically a pile of Entry instances, so, again, notionally, a collection of ChartRepository pointers.  (There is some question about why this data structure permits duplicate Entry instances (i.e. with the same Name but different contents); see Helm issue #2606 for details.)

I’m in the process of translating this to Java, and I think the resulting object model is going to look a lot cleaner, while delivering the same functionality, and permitting alternate implementations of chart storage and discovery.  Stay tuned.

Helm from Java, Part 3

If you use microbean-helm, you are exposed to the gRPC-colored view of the Tiller server.  (If you don’t know what I’m talking about, see part 1 and part 2.)

That view of things has a lot of gRPC cruft in it that for the most part you won’t be concerned with.  To help show you what the conceptual structure of the Tiller object model really is, I put together a UML class view of the main object model exposed by Tiller, eliminating the gRPC methods you’re not likely to use:


So fundamentally in the Helm/Tiller ecosystem, you’re working with charts, that, when installed, result in releases.  In the gRPC-generated object model, a Chart has a Metadata, several files, many values, and many Templates.

Each of these objects represents one of the items in the Helm chart file structure.  But, obviously, because with microbean-helm these are Java objects you can create them from any source you like.

Of note here is the use of Any for non-template files (like NOTES.txt).  While there are apparently lots of different ways to use this general purpose class, the Helm ecosystem appears to encode a chart file’s simple relative filename as the return value of its getTypeUrl() method, and its textual content as the return value of its getData() method. It’s not entirely clear whether Helm and Tiller got this right, but that is currently the behavior, so there you go.

It strikes me that, fuzzily, there are interesting opportunities here that involve microbean-helm, fabric8’s DefaultKubernetesClient, fabric8’s DockerClient, and so on to create Tiller-compatible charts but using plain Java.