@ -5,16 +5,20 @@ import (
"fmt"
"os"
"path/filepath"
"strings"
"git.wegmueller.it/illumos/go-zone"
"git.wegmueller.it/opencloud/opencloud/image"
"git.wegmueller.it/opencloud/opencloud/image/build"
"git.wegmueller.it/opencloud/opencloud/image/oci"
"git.wegmueller.it/opencloud/opencloud/image/reference"
namesgenerator "git.wegmueller.it/opencloud/opencloud/namegenerator"
opcNet "git.wegmueller.it/opencloud/opencloud/net"
"git.wegmueller.it/opencloud/opencloud/pod"
"git.wegmueller.it/opencloud/opencloud/volume"
"github.com/docker/docker/pkg/fileutils"
"github.com/dustin/go-humanize"
specsv1 "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/opencontainers/runtime-spec/specs-go"
"github.com/sirupsen/logrus"
"github.com/ztrue/tracerr"
@ -97,7 +101,7 @@ func (h *Host) RunBuild(cfg *build.ImageConfig, opts *pod.Options) error {
func ( h * Host ) CreateBuildContainer ( config build . Image , options * pod . Options ) ( * pod . Container , error ) {
name := namesgenerator . GetRandomName ( 5 )
name := "build-" + namesgenerator . GetRandomName ( 5 )
ref := reference . NewReferenceString ( config . BaseImage )
logrus . Debugf ( "creating build container for %s" , config . Name )
// Either create a container from a base image
@ -112,7 +116,7 @@ func (h *Host) CreateBuildContainer(config build.Image, options *pod.Options) (*
if err = img . Load ( ) ; err != nil {
return nil , tracerr . Wrap ( err )
}
p m, err := pod . ContainerManifestFromImage ( ref , img )
m , err := pod . ContainerManifestFromImage ( ref , img )
if err != nil {
return nil , tracerr . Wrap ( err )
}
@ -124,8 +128,8 @@ func (h *Host) CreateBuildContainer(config build.Image, options *pod.Options) (*
if err != nil {
return nil , tracerr . Wrap ( err )
}
pm . Solaris . Anet = [ ] specs . SolarisAnet { anet }
container , err := pod . CreateContainer ( h . Dataset , p m, name , ref . Tag , img )
m . Spec . Solaris . Anet = [ ] specs . SolarisAnet { anet }
container , err := pod . CreateContainer ( h . Dataset , m , name , ref . Tag , img )
if err != nil {
return nil , tracerr . Wrap ( err )
}
@ -137,7 +141,7 @@ func (h *Host) CreateBuildContainer(config build.Image, options *pod.Options) (*
} else {
//or make an new empty one if the base image is image.EmptyImageName
logrus . Debug ( "creating an empty container" )
p m := pod . EmptyContainerManifest ( )
m := pod . EmptyContainerManifest ( )
net , err := opcNet . GetNetwork ( options . Network )
if err != nil {
return nil , tracerr . Wrap ( err )
@ -146,8 +150,8 @@ func (h *Host) CreateBuildContainer(config build.Image, options *pod.Options) (*
if err != nil {
return nil , tracerr . Wrap ( err )
}
pm . Solaris . Anet = [ ] specs . SolarisAnet { anet }
container , err := pod . CreateEmptyContainer ( h . Dataset , p m, name )
m . Spec . Solaris . Anet = [ ] specs . SolarisAnet { anet }
container , err := pod . CreateEmptyContainer ( h . Dataset , m , name )
if err != nil {
return nil , tracerr . Wrap ( err )
}
@ -218,6 +222,7 @@ func (h *Host) RunBuildHelperInContainer(config build.Image, container *pod.Cont
func ( h * Host ) ExportToImage ( imageName reference . Reference , container * pod . Container , imageConfig build . Image ) ( * image . Image , error ) {
//First lets search if we already have the same image with a new tag.
var i * image . Image
var wr * oci . Writer
//First load existing image with existing tags
if h . HasImage ( imageName ) {
logrus . Debugf ( "loading existing base image %s" , imageName . String ( ) )
@ -230,8 +235,8 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
//Get Parent image and top layer
if imageConfig . BaseImage == "" || imageConfig . BaseImage == image . EmptyImageName {
var err error
if i == nil {
var err error
i , err = image . CreateEmptyImage ( imageName , nil )
if err != nil {
return nil , tracerr . Wrap ( err )
@ -239,7 +244,7 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
}
//Create a OCI Image Writer
logrus . Debugf ( "Creating OCI Image for %s" , imageName )
wr , err : = i . NewOCIWriter ( )
wr , err = i . NewOCIWriter ( )
if err != nil {
return nil , tracerr . Wrap ( err )
}
@ -251,10 +256,7 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
if err = wr . AddTree ( container . Path ( "root" ) ) ; err != nil {
return nil , tracerr . Wrap ( err )
}
logrus . Info ( "successful" )
if err = wr . Close ( ) ; err != nil {
return nil , tracerr . Wrap ( err )
}
} else {
parentRef := reference . NewReferenceString ( imageConfig . BaseImage )
logrus . Infof ( "Creating diff between %s and %s" , parentRef , imageName )
@ -285,11 +287,13 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
//Create a OCI Image Writer
logrus . Debugf ( "Creating OCI Image for %s" , imageName )
wr , err : = i . NewOCIWriter ( )
wr , err = i . NewOCIWriter ( )
if err != nil {
return nil , tracerr . Wrap ( err )
}
wr . AddParentLayers ( tg . Layers )
if err = wr . NewLayer ( ) ; err != nil {
return nil , tracerr . Wrap ( err )
}
@ -298,15 +302,45 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
if err != nil {
return nil , tracerr . Wrap ( err )
}
}
wr . AddParentLayers ( tg . Layers )
specImageConfig := specsv1 . ImageConfig {
User : imageConfig . ServiceUser ,
ExposedPorts : toStringStruct ( imageConfig . ExposedPorts ) ,
Env : toStringSlice ( imageConfig . Environment , "=" ) ,
Entrypoint : imageConfig . Enytrpoints ,
Cmd : imageConfig . Command ,
WorkingDir : imageConfig . WorkingDir ,
Labels : imageConfig . Labels ,
}
logrus . Info ( "successful" )
if err = wr . Close ( ) ; err != nil {
return nil , tracerr . Wrap ( err )
wr . AddImageConfig ( specImageConfig )
logrus . Infof ( "saving volume metadata" )
for i , volBuildConfig := range imageConfig . Volumes {
vol := volume . Config {
Name : volBuildConfig . Name ,
MountPath : volBuildConfig . Path ,
Persist : volBuildConfig . Persist ,
Backup : volBuildConfig . Backup ,
Properties : volBuildConfig . Properties ,
}
if vol . Name == "" {
vol . Name = fmt . Sprintf ( "volume-%d" , i )
}
if err := wr . AddMetadata ( volume . MetadataKeyPrefix + strings . ReplaceAll ( vol . Name , "/" , "." ) + oci . AnnotationMetadataBlobSuffix , vol ) ; err != nil {
return nil , fmt . Errorf ( "could not export image %s: failed to save volume %s: %w" , imageConfig . Name , vol . Name , err )
}
}
logrus . Infof ( "finishing image" )
if err := wr . Close ( ) ; err != nil {
return nil , tracerr . Wrap ( err )
}
logrus . Info ( "successfully saved oci image" )
logrus . Info ( "importing OCI image into dataset" )
if err := i . ImportOCILayers ( true ) ; err != nil {
return nil , tracerr . Wrap ( err )
@ -315,3 +349,21 @@ func (h *Host) ExportToImage(imageName reference.Reference, container *pod.Conta
return i , nil
}
func toStringStruct ( stringSlice [ ] string ) map [ string ] struct { } {
retVal := make ( map [ string ] struct { } )
for _ , str := range stringSlice {
retVal [ str ] = struct { } { }
}
return retVal
}
func toStringSlice ( stringMap map [ string ] string , seperator string ) [ ] string {
retVal := make ( [ ] string , len ( stringMap ) )
i := 0
for key , value := range stringMap {
retVal [ i ] = fmt . Sprintf ( "%s%s%s" , key , seperator , value )
i ++
}
return retVal
}