66 "strings"
77
88 "github.com/google/uuid"
9+ "github.com/opencontainers/runtime-spec/specs-go"
910
1011 "github.com/werf/logboek"
1112 "github.com/werf/werf/pkg/buildah"
@@ -28,30 +29,32 @@ func (runtime *BuildahBackend) HasStapelBuildSupport() bool {
2829 return true
2930}
3031
31- // FIXME(stapel-to-buildah): proper deep implementation
32- func (runtime * BuildahBackend ) BuildStapelStage (ctx context.Context , baseImage string , opts BuildStapelStageOpts ) (string , error ) {
33- /*
34- 1. Create new temporary build container using 'from' and remain uniq container name.
35- 2. Mount container root to host and run all prepare-container-actions, then unmount.
36- 3. Run user instructions in container, mount volumes when build.
37- 4. Set specified labels into container.
38- 5. Save container name as builtID (ideally there is no need to commit an image here, because buildah allows to commit and push directly container, which would happen later).
39- */
32+ func (runtime * BuildahBackend ) getBuildahCommonOpts (ctx context.Context , suppressLog bool ) (opts buildah.CommonOpts ) {
33+ if ! suppressLog {
34+ opts .LogWriter = logboek .Context (ctx ).OutStream ()
35+ }
4036
41- containerID := uuid .New ().String ()
37+ return
38+ }
4239
43- _ , err := runtime .buildah .FromCommand (ctx , containerID , baseImage , buildah.FromCommandOpts {})
40+ func (runtime * BuildahBackend ) BuildStapelStage (ctx context.Context , baseImage string , opts BuildStapelStageOpts ) (string , error ) {
41+ containerID := fmt .Sprintf ("werf-stage-build-%s" , uuid .New ().String ())
42+
43+ _ , err := runtime .buildah .FromCommand (ctx , containerID , baseImage , buildah .FromCommandOpts (runtime .getBuildahCommonOpts (ctx , true )))
4444 if err != nil {
4545 return "" , fmt .Errorf ("unable to create container using base image %q: %s" , baseImage , err )
4646 }
4747
48+ // TODO(stapel-to-buildah): cleanup orphan build containers in werf-host-cleanup procedure
49+ // defer runtime.buildah.Rm(ctx, containerID, buildah.RmOpts{CommonOpts: runtime.getBuildahCommonOpts(ctx, true)})
50+
4851 if len (opts .PrepareContainerActions ) > 0 {
4952 err := func () error {
50- containerRoot , err := runtime .buildah .Mount (ctx , containerID , buildah.MountOpts {} )
53+ containerRoot , err := runtime .buildah .Mount (ctx , containerID , buildah .MountOpts ( runtime . getBuildahCommonOpts ( ctx , true )) )
5154 if err != nil {
5255 return fmt .Errorf ("unable to mount container %q root dir: %s" , containerID , err )
5356 }
54- defer runtime .buildah .Umount (ctx , containerRoot , buildah.UmountOpts {} )
57+ defer runtime .buildah .Umount (ctx , containerRoot , buildah .UmountOpts ( runtime . getBuildahCommonOpts ( ctx , true )) )
5558
5659 for _ , action := range opts .PrepareContainerActions {
5760 if err := action .PrepareContainer (containerRoot ); err != nil {
@@ -67,16 +70,44 @@ func (runtime *BuildahBackend) BuildStapelStage(ctx context.Context, baseImage s
6770 }
6871
6972 for _ , cmd := range opts .UserCommands {
70- if err := runtime .buildah .RunCommand (ctx , containerID , strings .Fields (cmd ), buildah.RunCommandOpts {}); err != nil {
73+ var mounts []specs.Mount
74+ for _ , volume := range opts .BuildVolumes {
75+ volumeParts := strings .SplitN (volume , ":" , 2 )
76+ if len (volumeParts ) != 2 {
77+ panic (fmt .Sprintf ("invalid volume %q: expected SOURCE:DESTINATION format" , volume ))
78+ }
79+
80+ mounts = append (mounts , specs.Mount {
81+ Type : "bind" ,
82+ Source : volumeParts [0 ],
83+ Destination : volumeParts [1 ],
84+ })
85+ }
86+
87+ // TODO(stapel-to-buildah): Consider support for shell script instead of separate run commands to allow shared
88+ // usage of shell variables and functions between multiple commands.
89+ // Maybe there is no need of such function, instead provide options to select shell in the werf.yaml.
90+ // Is it important to provide compatibility between docker-server-based werf.yaml and buildah-based?
91+ if err := runtime .buildah .RunCommand (ctx , containerID , []string {"sh" , "-c" , cmd }, buildah.RunCommandOpts {
92+ CommonOpts : runtime .getBuildahCommonOpts (ctx , false ),
93+ Mounts : mounts ,
94+ }); err != nil {
7195 return "" , fmt .Errorf ("unable to run %q: %s" , cmd , err )
7296 }
7397 }
7498
75- // TODO(stapel-to-buildah): use buildah.Change to set labels
76- fmt .Printf ("[DEBUG] Setting labels %v for build container %q\n " , opts .Labels , containerID )
99+ logboek .Context (ctx ).Debug ().LogF ("Setting labels %v for build container %q\n " , opts .Labels , containerID )
100+ if err := runtime .buildah .Config (ctx , containerID , buildah.ConfigOpts {
101+ CommonOpts : runtime .getBuildahCommonOpts (ctx , true ),
102+ Labels : opts .Labels ,
103+ }); err != nil {
104+ return "" , fmt .Errorf ("unable to set container %q config: %s" , containerID , err )
105+ }
77106
78- fmt .Printf ("[DEBUG] Committing container %q\n " , containerID )
79- imgID , err := runtime .buildah .Commit (ctx , containerID , buildah.CommitOpts {})
107+ // TODO(stapel-to-buildah): Save container name as builtID. There is no need to commit an image here,
108+ // because buildah allows to commit and push directly container, which would happen later.
109+ logboek .Context (ctx ).Debug ().LogF ("committing container %q\n " , containerID )
110+ imgID , err := runtime .buildah .Commit (ctx , containerID , buildah.CommitOpts {CommonOpts : runtime .getBuildahCommonOpts (ctx , true )})
80111 if err != nil {
81112 return "" , fmt .Errorf ("unable to commit container %q: %s" , containerID , err )
82113 }
0 commit comments