From 27088aa9a7b75f73aebe90139b6de2105cc82927 Mon Sep 17 00:00:00 2001 From: Frank Schreiner Date: Wed, 18 Oct 2017 10:18:57 +0000 Subject: [PATCH] [backend] container upload more flexible With this patch you can configure the container upload with skopeo more flexible. * You can define regex for the project names to be uploadeded * You can define multiple registries to upload to. --- src/backend/BSConfig.pm.template | 32 +++++++++ src/backend/bs_publish | 117 ++++++++++++++++++++++++------- 2 files changed, 124 insertions(+), 25 deletions(-) diff --git a/src/backend/BSConfig.pm.template b/src/backend/BSConfig.pm.template index a8c254bfcaa..f19c88cb704 100644 --- a/src/backend/BSConfig.pm.template +++ b/src/backend/BSConfig.pm.template @@ -238,4 +238,36 @@ our $servicedispatch = 1; # repository_base => '', # }; +# our $container_registries = { +# 'registry.example.com' => { +# host => '', +# port => '', +# user => '', +# password => '', +# repository_base => '', +# }, +# 'staging-registry.example.com' => { +# host => '', +# port => '', +# user => '', +# password => '', +# repository_base => '', +# }, +# hub.docker.com => { +# host => '', +# port => '', +# user => '', +# password => '', +# repository_base => '', +# }, +#}; +# +# our $publish_containers = [ +# # key: regex to match projid +# # value: ArrayRef with identifiers for registries configured in $container_registries +# 'SUSE:.*' => [ 'registry.example.com', 'hub.docker.com' ], +# '.*:branches:.*' => [ 'staging-registry.example.com' ], +# ]; + + 1; diff --git a/src/backend/bs_publish b/src/backend/bs_publish index 3ed1ce7cc29..78a17d8be4f 100755 --- a/src/backend/bs_publish +++ b/src/backend/bs_publish @@ -2466,52 +2466,85 @@ sub upload_container { my ($dir, $containerinfo, $file, $projid, $repoid, $arch) = @_; # jump out if no config - return unless $BSConfig::docker_registry; + return unless $BSConfig::publish_containers; + + my @registries; + my @s = @{$BSConfig::publish_containers}; + while (@s) { + my ($k, $v) = splice(@s, 0, 2); + if ($projid =~ /^$k/) { + $v = [ $v ] unless ref $v; + @registries = @$v; + last; + } + } - # set default and check config for docker registry - my $dr = $BSConfig::docker_registry; - ## set default port - my $port = $dr->{port} || 443; + return if !@registries; - # check if minimal config items are set - if (!$dr->{host} || !$dr->{user} || !$dr->{password}) { - BSUtil::printlog( - "No valid config found for docker registry: ". - "$dr->{host}/$dr->{user}/$dr->{password} (host/user/password)" - ); - return; + my @valid_registries; + for my $registry (@registries) { + my $registry_config = check_registry_config($registry); + push(@valid_registries, $registry_config) if $registry_config; } # check if containerinfo is valid and get info for container BSUtil::printlog("Checking containerinfo for $dir/$containerinfo"); my $info = BSRepServer::Containerinfo::readcontainerinfo($dir, $containerinfo); + if (! $info) { + BSUtil::printlog("No valid containerinfo found"); + return; + } + + if (!@{$info->{tags} || []}) { + BSUtil::printlog("container is not tagged, skipping upload"); + return; + } + + my $src = "$dir/$file"; + my $tempfile = decompress_container($src); + + for my $config ( @valid_registries ) { + upload_to_registry($config, $info, $tempfile, $projid, $repoid, $arch); + } + +} + +=head2 upload_to_registry - upload decompressed file + + Parameters: + config - validated config for registry + info - content of containerinfo file + tempfile - path to decompressed container tar file + + Returns: + nothing + +=cut + +sub upload_to_registry { + my ($config, $info, $tempfile, $projid, $repoid, $arch) = @_; # TODO: should be more general to implement own upload # prepare url for skopeo my $name = lc($info->{name}); - my $delimiter = $dr->{repository_delimiter} || '/'; - my $repository_base = $dr->{repository_base} || '/'; + my $delimiter = $config->{repository_delimiter} || '/'; + my $repository_base = $config->{repository_base} || '/'; $projid =~ s/:/$delimiter/g; $repoid =~ s/:/$delimiter/g; - if (!@{$info->{tags} || []}) { - BSUtil::printlog("container is not tagged, skipping upload"); - return; - } my $tag = $info->{tags}->[0]; - my $uploader = $dr->{uploader} || 'skopeo'; + my $uploader = $config->{uploader} || 'skopeo'; if ($uploader eq 'skopeo') { - my $dst = "docker://$dr->{host}:$port".lc("$repository_base$projid/$repoid/$arch/$tag"); - - my $src = "$dir/$file"; - my $tempfile = decompress_container($src); - + my $dst = "docker://$config->{host}:" . + ($config->{port} || 443) . + lc("$repository_base$projid/$repoid/$arch/$tag"); #### # FIXME: Find solution to remove credentials from the cli options + # HINT: https://github.com/projectatomic/skopeo/issues/434 must be solved first #### - my @cmd = ("skopeo", "copy", "--dest-creds", "$dr->{user}:$dr->{password}", "docker-archive:$tempfile", $dst); + my @cmd = ("skopeo", "copy", "--dest-creds", "$config->{user}:$config->{password}", "docker-archive:$tempfile", $dst); BSUtil::printlog("Uploading: '$cmd[0] $cmd[1] $cmd[2] XXX:XXX $cmd[4] $cmd[5]'"); my $result = qsystem(@cmd); @@ -2523,6 +2556,40 @@ sub upload_container { } } +=head2 check_registry_config - check for valid registry config and set default values + + Parameters: + registry - identifier for registry to be searched in $BSConfig::container_registries + + Returns: + config - valid config for registry + +=cut + +sub check_registry_config { + my ($registry) = @_; + + # avoid "used only once" warnings + my $cr = $BSConfig::container_registries->{$registry} || $BSConfig::container_registries->{$registry}; + if (ref($cr) ne 'HASH') { + BSUtil::printlog( + "No or invalid config found for container registry: '$registry'" + ); + return; + } + + # check if minimal config items are set + if (!$cr->{host} || !$cr->{user} || !$cr->{password}) { + BSUtil::printlog( + "No valid config found for container registry: ". + "$cr->{host}/$cr->{user}/$cr->{password} (host/user/password)" + ); + return; + } + + return $cr; +} + =head2 decompress_container - decompress or copy container into a temporary file Function returns path to the temporay file