Skip to content

Commit

Permalink
Add support for helm chart builds
Browse files Browse the repository at this point in the history
Building those is basically just extracting data and creating
a .helm.tar result.

Based on pull request #582 by Sumit Jamgade.
  • Loading branch information
mlschroe committed Jul 28, 2020
1 parent ac23a9f commit ab6f002
Show file tree
Hide file tree
Showing 4 changed files with 214 additions and 3 deletions.
10 changes: 9 additions & 1 deletion Build.pm
Expand Up @@ -39,6 +39,7 @@ our $do_snapcraft;
our $do_appimage;
our $do_docker;
our $do_fissile;
our $do_helm;

sub import {
for (@_) {
Expand All @@ -52,8 +53,9 @@ sub import {
$do_appimage = 1 if $_ eq ':appimage';
$do_docker = 1 if $_ eq ':docker';
$do_fissile = 1 if $_ eq ':fissile';
$do_helm = 1 if $_ eq ':helm';
}
$do_rpm = $do_deb = $do_kiwi = $do_arch = $do_collax = $do_livebuild = $do_snapcraft = $do_appimage = $do_docker = $do_fissile = 1 if !$do_rpm && !$do_deb && !$do_kiwi && !$do_arch && !$do_collax && !$do_livebuild && !$do_snapcraft && !$do_appimage && !$do_docker && !$do_fissile;
$do_rpm = $do_deb = $do_kiwi = $do_arch = $do_collax = $do_livebuild = $do_snapcraft = $do_appimage = $do_docker = $do_fissile = $do_helm = 1 if !$do_rpm && !$do_deb && !$do_kiwi && !$do_arch && !$do_collax && !$do_livebuild && !$do_snapcraft && !$do_appimage && !$do_docker && !$do_fissile && !$do_helm;

if ($do_deb) {
require Build::Deb;
Expand Down Expand Up @@ -82,6 +84,9 @@ sub import {
if ($do_fissile) {
require Build::Fissile;
}
if ($do_helm) {
require Build::Helm;
}
}

package Build::Features;
Expand Down Expand Up @@ -1635,6 +1640,7 @@ sub recipe2buildtype {
return 'fissile' if $recipe eq 'fissile.yml';
return 'preinstallimage' if $recipe eq '_preinstallimage';
return 'simpleimage' if $recipe eq 'simpleimage';
return 'helm' if $recipe eq 'Helmfile';
return undef;
}

Expand Down Expand Up @@ -1688,6 +1694,7 @@ sub parse {
return Build::Arch::parse($cf, $fn, @args) if $do_arch && $fnx eq 'PKGBUILD';
return Build::Collax::parse($cf, $fn, @args) if $do_collax && $fnx eq 'build.collax';
return parse_preinstallimage($cf, $fn, @args) if $fnx eq '_preinstallimage';
return Build::Helm::parse($cf, $fn, @args) if $fnx eq 'Helmfile';
return undef;
}

Expand All @@ -1706,6 +1713,7 @@ sub parse_typed {
return Build::Arch::parse($cf, $fn, @args) if $do_arch && $buildtype eq 'arch';
return Build::Collax::parse($cf, $fn, @args) if $do_collax && $buildtype eq 'collax';
return parse_preinstallimage($cf, $fn, @args) if $buildtype eq 'preinstallimage';
return Build::Helm::parse($cf, $fn, @args) if $buildtype eq 'helm';
return undef;
}

Expand Down
112 changes: 112 additions & 0 deletions Build/Helm.pm
@@ -0,0 +1,112 @@
################################################################
#
# Copyright (c) 2020 SUSE LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################

package Build::Helm;

use strict;

use Build::SimpleJSON;

# we do not want to parse the yaml file from the tar here, so just return some
# dummy result
sub parse {
my ($cf, $fn) = @_;
my $fd;
return {'error' => "$fn: $!"} unless open($fd, '<', $fn);
my $ret = { 'name' => 'helmchart', 'deps' => []};
while (<$fd>) {
chomp;
my @s = split(' ', $_);
next unless @s;
my $k = lc(shift(@s));
$ret->{'chartfile'} = $s[0] if @s && $k eq 'chart:';
push @{$ret->{'containertags'}}, @s if @s && $k eq 'tags:';
}
close $fd;
if (defined($ret->{'chartfile'})) {
return {'error' => "illegal chartfile"} unless $ret->{'chartfile'} ne '';
return {'error' => "illegal chartfile"} if $ret->{'chartfile'} =~ /[\/\000-\037]/;
return {'error' => "illegal chartfile"} if $ret->{'chartfile'} =~ /^\./;
}
return $ret;
}

sub show {
my ($release, $chartconfig);
while (@ARGV) {
if (@ARGV > 2 && $ARGV[0] eq '--release') {
(undef, $release) = splice(@ARGV, 0, 2);
} elsif (@ARGV > 2 && $ARGV[0] eq '--chartconfig') {
(undef, $chartconfig) = splice(@ARGV, 0, 2);
} else {
last;
}
}
my ($fn, $field) = @ARGV;
require YAML::XS;
$YAML::XS::LoadBlessed = 0;
my $d = {};
$d = parse({}, $fn) if $fn;
die("$d->{'error'}\n") if $d->{'error'};
my $d2 = {};
if ($chartconfig) {
$d2 = YAML::XS::LoadFile($chartconfig);
die unless $d2;
my $name = $d2->{'name'};
my $version = $d2->{'version'};
die("no name\n") unless defined $name;
die("bad name '$name'\n") if $name eq '';
die("bad name '$name'\n") if $name =~ /\//;
die("bad name '$name'\n") if $name =~ /^[-\.]/;
die("bad name '$name'\n") if $name =~ /[\/\000-\037]/;
die("no version\n") unless defined $version;
die("bad version '$version'\n") if $versioneq '';
die("bad version '$version'\n") if $version =~ /\//;
die("bad version '$version'\n") if $version =~ /[\/\000-\037]/;
if ($field eq 'manifest') {
my @tags = @{$d->{'containertags'} || []};
for (@tags) {
s/<NAME>/$name/g;
s/<VERSION>/$version/g;
s/<RELEASE>/$release/g;
}
my $manifest = {};
$manifest->{'name'} = $name;
$manifest->{'version'} = $version;
$manifest->{'tags'} = \@tags if @tags;
$manifest->{'chart'} = "$name-$version.tgz";
$manifest->{'_order'} = [ qw{name version tags chart} ];
print Build::SimpleJSON::unparse($manifest)."\n";
exit(0);
}
if ($field eq 'config') {
$d2->{'_order'} = [ qw{apiVersion name version kubeVersion description type keywords home sources dependencies maintainers icon appVersion deprecated annotations} ];
print Build::SimpleJSON::unparse($d2)."\n";
exit(0);
}
$d = $d2;
$d->{'nameversion'} = "$name-$version";
}
my $x = $d->{$field};
$x = [ $x ] unless ref $x;
print "@$x\n";
}

1;
5 changes: 3 additions & 2 deletions build-recipe
Expand Up @@ -25,7 +25,7 @@
BUILDTYPE=
KIWI_PARAMETERS=

for i in spec dsc kiwi arch collax preinstallimage simpleimage mock livebuild snapcraft debootstrap debbuild appimage docker podman fissile; do
for i in spec dsc kiwi arch collax preinstallimage simpleimage mock livebuild snapcraft debootstrap debbuild appimage docker podman fissile helm; do
. "$BUILD_DIR/build-recipe-$i"
done

Expand Down Expand Up @@ -86,6 +86,7 @@ recipe_set_buildtype() {
_preinstallimage) BUILDTYPE=preinstallimage ;;
simpleimage) BUILDTYPE=simpleimage ;;
*.livebuild) BUILDTYPE=livebuild ;;
Helmfile) BUILDTYPE=helm ;;
esac
if test -z "$BUILDTYPE" ; then
cleanup_and_exit 1 "I don't know how to build $RECIPEFILE"
Expand Down Expand Up @@ -138,7 +139,7 @@ expand_recipe_directories() {
snapcraft) types="snapcraft.yaml" ;;
esac
fi
types="$types .spec .dsc PKGBUILD Dockerfile build.collax .kiwi .src.rpm .nosrc.rpm simpleimage snapcraft.yaml"
types="$types .spec .dsc PKGBUILD Dockerfile build.collax .kiwi .src.rpm .nosrc.rpm simpleimage snapcraft.yaml Helmfile"
fi
for t in $types ; do
found=
Expand Down
90 changes: 90 additions & 0 deletions build-recipe-helm
@@ -0,0 +1,90 @@
################################################################
#
# Copyright (c) 2020 SUSE Linux LLC
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License version 2 or 3 as
# published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program (see the file COPYING); if not, write to the
# Free Software Foundation, Inc.,
# 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
#
################################################################

recipe_setup_helm() {
TOPDIR="/usr/src/packages"
test "$DO_INIT_TOPDIR" != false && rm -Rf "$BUILD_ROOT/$TOPDIR"
mkdir -p "$BUILD_ROOT$TOPDIR/SOURCES"
if test "$MYSRCDIR" = $BUILD_ROOT/.build-srcdir ; then
mv "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
else
if test -z "$LINKSOURCES" ; then
cp -dLR "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
else
cp -lR "$MYSRCDIR"/* $BUILD_ROOT$TOPDIR/SOURCES/
fi
if test "$?" != 0 ; then
cleanup_and_exit 1 "source copy failed"
fi
fi
}

recipe_prepare_helm() {
:
}

recipe_build_helm() {
TOPDIR=/usr/src/packages
mkdir -p "$BUILD_ROOT$TOPDIR/HELM"
local chartfile
chartfile=$(perl -I$BUILD_DIR -MBuild::Helm -e Build::Helm::show -- "$BUILD_ROOT/$TOPDIR/SOURCES/$RECIPEFILE" chartfile)
test -z "$chartfile" -a -e "$BUILD_ROOT$TOPDIR/SOURCES/chart.tar" && chartfile=chart.tar
test -z "$chartfile" -a -e "$BUILD_ROOT$TOPDIR/SOURCES/chart.tgz" && chartfile=chart.tgz
test -z "$chartfile" -a -e "$BUILD_ROOT$TOPDIR/SOURCES/chart.tar.gz" && chartfile=chart.tgz
test -e "$BUILD_ROOT$TOPDIR/SOURCES/$chartfile" || cleanup_and_exit 1 "$chartfile does not exist"
tar -xOf "$BUILD_ROOT$TOPDIR/SOURCES/$chartfile" Chart.yaml > "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml"
test -s "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml" || cleanup_and_exit 1 "chart does not include Chart.yaml"
# extract data from chart file
args=()
test -n "$RELEASE" && args=("${args[@]}" --release "$RELEASE")
perl -I$BUILD_DIR -MBuild::Helm -e 'Build::Helm::show' -- "${args[@]}" --chartconfig "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml" "$BUILD_ROOT/$TOPDIR/SOURCES/$RECIPEFILE" config > "$BUILD_ROOT$TOPDIR/HELM/config.json"
perl -I$BUILD_DIR -MBuild::Helm -e 'Build::Helm::show' -- "${args[@]}" --chartconfig "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml" "$BUILD_ROOT/$TOPDIR/SOURCES/$RECIPEFILE" manifest > "$BUILD_ROOT$TOPDIR/HELM/manifest.json"
local nameversion=$(perl -I$BUILD_DIR -MBuild::Helm -e 'Build::Helm::show' -- "${args[@]}" --chartconfig "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml" "$BUILD_ROOT/$TOPDIR/SOURCES/$RECIPEFILE" nameversion)
test -n "$nameversion" || cleanup_and_exit 1 "no nameversion";
# copy (and compress) chart
case $chartfile in
*.tar.gz | *.tgz)
cp "$BUILD_ROOT$TOPDIR/SOURCES/$chartfile" "$BUILD_ROOT$TOPDIR/HELM/$nameversion.tgz"
;;
*.tar)
gzip < "$BUILD_ROOT$TOPDIR/SOURCES/$chartfile" > "$BUILD_ROOT$TOPDIR/HELM/$nameversion.tgz"
;;
*)
cleanup_and_exit 1
;;
esac
# now create our helm.tar result
(cd "$BUILD_ROOT$TOPDIR/HELM" && tar -cf "$nameversion.helm.tar" manifest.json config.json "$nameversion.tgz")
# get rid of everything else
rm -rf "$BUILD_ROOT$TOPDIR/HELM/manifest.json"
rm -rf "$BUILD_ROOT$TOPDIR/HELM/config.json"
rm -rf "$BUILD_ROOT$TOPDIR/HELM/$nameversion.tgz"
rm -rf "$BUILD_ROOT$TOPDIR/HELM/Chart.yaml"
BUILD_SUCCEEDED=true
}

recipe_resultdirs_helm() {
echo HELM
}

recipe_cleanup_helm() {
:
}

0 comments on commit ab6f002

Please sign in to comment.