Skip to content

Commit 905aeb9

Browse files
committed
support for older versions of buildah, and some caching improvements
1 parent 471b2bb commit 905aeb9

File tree

11 files changed

+138
-145
lines changed

11 files changed

+138
-145
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@
2020
1. [Intro](#intro)
2121
2. [Usage](#usage)
2222
3. [Installation](#installation)
23-
4. [Credits](#credits)
23+
4. [Uninstalling](#uninstalling)
24+
5. [Known Issues](#known-issues)
25+
6. [Credits](#credits)
2426

2527
<!-- </details> -->
2628

@@ -99,7 +101,7 @@ If everything went well, your terminal prompt will be prefixed with `(devc)` (th
99101
Again simple, as devc is not running any demon processes, one can execute `deactivate` to deactivate the session, or `ctrl + d` combo to quit the terminal.
100102

101103
### 4. Removing the venv
102-
**In a normal usecase one can simply delete the env directory** from the UI after use. If you are using some advanced features on devc at env creation time, you may have to look into the `devc rm` command. refer the [manual](./misc/man.md)
104+
**In a normal usecase one can simply delete the env directory** from the UI after use (yeah for the CLI people, you got `rm -r` option as well).
103105

104106
## Installation
105107

@@ -162,7 +164,7 @@ In addition devc may have installed `buildah` and it's dependencies. You can sim
162164
* [Buildah](https://github.com/containers/buildah)
163165

164166
## Known Issues
165-
* Currently there is some problem regarding issuing apt update in ubuntu/deb based images
167+
* Currently there is some problem regarding issuing apt update in ubuntu/deb based images (gpg key update related issues)
166168
* Some mount points has to be refined. Think some of them are useless at times. (It's hard to generalize between different distros)
167169

168170
## TODOs

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
v1.0.0
1+
v1.1.0

cmd/rm.go

Lines changed: 0 additions & 20 deletions
This file was deleted.

cmd/root.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ func init() {
4242
rootCmd.AddCommand(loginCmd)
4343
rootCmd.AddCommand(logoutCmd)
4444
rootCmd.AddCommand(imagesCmd)
45-
rootCmd.AddCommand(rmCmd)
4645
rootCmd.AddCommand(rmiCmd)
4746
rootCmd.AddCommand(pullCmd)
4847
rootCmd.AddCommand(pruneCmd)

internal/builder/cli.go

Lines changed: 48 additions & 79 deletions
Original file line numberDiff line numberDiff line change
@@ -20,38 +20,51 @@ func Builder(opts *configs.BuildCmdOptions, args []string) {
2020
if err != nil {
2121
panic("[build error] error resolve path : " + err.Error())
2222
}
23-
var baseOptions = append(getGlobalBuildahOptions(abs, args[0]), getBuildOptions(abs, args[0])...)
24-
authFileOpts, err := getAuthFileOptions()
23+
_, err = os.Stat(filepath.Join(abs, args[0]))
24+
if err == nil {
25+
panic("[ERROR] directory already exists! '" + args[0] + "'")
26+
}
27+
var globalOptions = getGlobalBuildahOptions()
28+
imgName, buildOptions, err := getBuildOptions()
2529
if err != nil {
26-
panic("[devc error] : " + err.Error())
30+
panic("[devc error] getting builder options : " + err.Error())
2731
}
28-
baseOptions = append(baseOptions, authFileOpts...)
32+
buildOptions = append(globalOptions, buildOptions...)
2933
for i := 0; i < len(opts.BuildArgs); i++ {
30-
baseOptions = append(baseOptions, []string{"--build-arg", opts.BuildArgs[i]}...)
34+
buildOptions = append(buildOptions, []string{"--build-arg", opts.BuildArgs[i]}...)
3135
}
3236

3337
if len(opts.Containerfile) > 0 {
34-
baseOptions = append(baseOptions, "--file")
35-
baseOptions = append(baseOptions, filepath.Join(abs, opts.Containerfile))
38+
buildOptions = append(buildOptions, "--file")
39+
buildOptions = append(buildOptions, filepath.Join(abs, opts.Containerfile))
3640
}
37-
baseOptions = append(baseOptions, filepath.Join(abs, opts.Context))
41+
buildOptions = append(buildOptions, filepath.Join(abs, opts.Context))
3842

39-
// fmt.Println("options", buildCmd.Path, buildCmd.Args)
40-
err = runCommand(configs.Config.Buildah.Path, baseOptions)
43+
fmt.Println("[devc] building container..")
44+
err = runCommand(configs.Config.Buildah.Path, buildOptions)
4145
if err != nil {
42-
panic("[builder error] : " + err.Error())
46+
panic("[builder error] stage 1 : " + err.Error())
4347
}
44-
fmt.Println("[devc] container created")
48+
fmt.Println("[devc] image created..")
49+
fmt.Println("[devc] creating devc env ")
50+
51+
err = exportImageAsRootFs(imgName, filepath.Join(abs, args[0], configs.Config.EnvSettings.RootDir))
52+
if err != nil {
53+
panic("[devc] mount error : " + err.Error())
54+
}
55+
4556
err = env.SetupEnv(filepath.Join(abs, args[0]))
4657
if err != nil {
4758
panic("[setup error] : " + err.Error())
4859
}
4960
fmt.Printf("[devc] env created : %v\n", args[0])
5061
if !opts.KeepCache {
51-
err = clearBuildCache(args[0])
52-
if err != nil {
53-
panic("[finishup error] : " + err.Error())
54-
}
62+
defer func() {
63+
if v := recover(); v != nil {
64+
panic(fmt.Sprint("[finishup error] : ", v))
65+
}
66+
}()
67+
Rmi(&configs.RmiCmdOptions{}, []string{imgName})
5568
}
5669
fmt.Printf("\n[devc] tada! the env is all yours : [%v]\n", args[0])
5770
}
@@ -82,66 +95,43 @@ func Activate(opts *configs.ActivateCmdOptions, args []string) {
8295

8396
// pull images and create env
8497
func Pull(opts *configs.PullCmdOptions, args []string) {
85-
if len(args) != 2 {
86-
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
87-
}
88-
file, err := os.CreateTemp("", "pullcmd")
89-
if err != nil {
90-
panic("[pull error] : " + err.Error())
91-
}
92-
defer file.Close()
93-
defer os.Remove(file.Name())
94-
_, err = file.Write([]byte(fmt.Sprintf("FROM %v", args[0])))
95-
if err != nil {
96-
panic("[pull error] : " + err.Error())
97-
}
9898

9999
abs, err := filepath.Abs("")
100100
if err != nil {
101101
panic("[pull error] error resolve path : " + err.Error())
102102
}
103-
104-
var baseOptions = append(getGlobalBuildahOptions("", ""), getBuildOptions(abs, args[1])...)
105-
authFileOpts, err := getAuthFileOptions()
106-
if err != nil {
107-
panic("[devc error] : " + err.Error())
103+
_, err = os.Stat(filepath.Join(abs, args[1]))
104+
if err == nil {
105+
panic("[ERROR] directory already exists! '" + args[1] + "'")
108106
}
109-
baseOptions = append(baseOptions, authFileOpts...)
110-
111-
baseOptions = append(baseOptions, "--file")
112-
baseOptions = append(baseOptions, file.Name())
113-
baseOptions = append(baseOptions, ".")
114-
115-
// fmt.Println("options", buildCmd.Path, buildCmd.Args)
116-
err = runCommand(configs.Config.Buildah.Path, baseOptions)
107+
err = exportImageAsRootFs(args[0], filepath.Join(abs, args[1], configs.Config.EnvSettings.RootDir))
117108
if err != nil {
118-
panic("[pull error] : " + err.Error())
109+
panic("[devc] mount error : " + err.Error())
119110
}
120-
fmt.Println("[devc] container created..")
111+
121112
err = env.SetupEnv(filepath.Join(abs, args[1]))
122113
if err != nil {
123114
panic("[setup error] : " + err.Error())
124115
}
116+
fmt.Printf("[devc] env created : %v\n", args[1])
125117
if opts.NoCaching {
126-
baseOptions = getGlobalBuildahOptions("", "")
127-
baseOptions = append(baseOptions, "rmi")
128-
baseOptions = append(baseOptions, args[0])
129-
130-
err := runCommand(configs.Config.Buildah.Path, baseOptions)
131-
if err != nil {
132-
panic("[devc cleanup error] : " + err.Error())
133-
}
134-
fmt.Println("[devc] pull cache removed..")
118+
defer func() {
119+
if v := recover(); v != nil {
120+
panic(fmt.Sprint("[finishup error] : ", v))
121+
}
122+
}()
123+
Rmi(&configs.RmiCmdOptions{}, []string{args[0]})
135124
}
136125
fmt.Printf("\n[devc] tada! the env is all yours : [%v]\n", args[1])
126+
137127
}
138128

139129
// login to a registry
140130
func Login(opts *configs.LoginCmdOptions, args []string) {
141131
if len(args) != 1 {
142132
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
143133
}
144-
var baseOptions = getGlobalBuildahOptions("", "")
134+
var baseOptions = getGlobalBuildahOptions()
145135
baseOptions = append(baseOptions, "login")
146136
authFileOpts, err := getAuthFileOptions()
147137
if err != nil {
@@ -174,7 +164,7 @@ func Logout(opts *configs.LogoutCmdOptions, args []string) {
174164
if len(args) != 1 {
175165
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
176166
}
177-
var baseOptions = getGlobalBuildahOptions("", "")
167+
var baseOptions = getGlobalBuildahOptions()
178168
baseOptions = append(baseOptions, "logout")
179169
authFileOpts, err := getAuthFileOptions()
180170
if err != nil {
@@ -196,7 +186,7 @@ func Images(opts *configs.ImagesCmdOptions, args []string) {
196186
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
197187
}
198188

199-
var baseOptions = getGlobalBuildahOptions("", "")
189+
var baseOptions = getGlobalBuildahOptions()
200190
baseOptions = append(baseOptions, "images")
201191
// fmt.Println("options", buildCmd.Path, buildCmd.Args)
202192
err := runCommand(configs.Config.Buildah.Path, baseOptions)
@@ -210,7 +200,7 @@ func Prune(opts *configs.PruneCmdOptions, args []string) {
210200
if len(args) != 0 {
211201
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
212202
}
213-
err := clearBuildCache("")
203+
err := clearBuildCache()
214204
if err != nil {
215205
panic("[devc prune error] : " + err.Error())
216206
}
@@ -221,33 +211,12 @@ func Prune(opts *configs.PruneCmdOptions, args []string) {
221211
fmt.Println("[devc] system prune complete!")
222212
}
223213

224-
// Remove an existing devc env (simply deleting it will also work)
225-
func Rm(opts *configs.RmCmdOptions, args []string) {
226-
if len(args) != 1 {
227-
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
228-
}
229-
// check if it's a valid env
230-
_, err := os.Stat(filepath.Join(args[0], configs.Config.EnvSettings.DevcBin, "activate"))
231-
if err != nil {
232-
panic("[devc rm error] : seems not to be a devc environment")
233-
}
234-
err = clearBuildCache(args[0])
235-
if err != nil {
236-
panic("[devc rm error] : " + err.Error())
237-
}
238-
err = runCommand("rm", []string{"-rf", args[0]})
239-
if err != nil {
240-
panic("[devc rm error] : " + err.Error())
241-
}
242-
fmt.Println("[devc] env removed successfully!")
243-
}
244-
245214
// Remove a cached image (cache is only applicable for devc pull command)
246215
func Rmi(opts *configs.RmiCmdOptions, args []string) {
247216
if len(args) != 1 {
248217
panic("Invalid number of positional argument. Execute command with --help to get detailed usecase")
249218
}
250-
options := getGlobalBuildahOptions("", "")
219+
options := getGlobalBuildahOptions()
251220
options = append(options, "rmi")
252221
options = append(options, args[0])
253222

internal/builder/common.go

Lines changed: 14 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
package builder
22

33
import (
4-
"fmt"
4+
// "fmt"
55
"os"
66
"os/exec"
77
"path/filepath"
@@ -24,16 +24,9 @@ func runCommand(name string, cmd []string) (err error) {
2424
}
2525

2626
// provide global options for buildah
27-
// args:
28-
//
29-
// envPath - env path
30-
func getGlobalBuildahOptions(abs, envPath string) (cmd []string) {
27+
func getGlobalBuildahOptions() (cmd []string) {
3128
var rootPath string
32-
if len(envPath) > 0 {
33-
rootPath = filepath.Join(abs, envPath, configs.Config.EnvSettings.BuildDir)
34-
} else {
35-
rootPath = filepath.Join(configs.Config.CacheDir, configs.Config.CacheDirSettings.BuildahCache)
36-
}
29+
rootPath = filepath.Join(configs.Config.CacheDir, configs.Config.CacheDirSettings.BuildahCache)
3730
cmd = []string{
3831
"--root",
3932
rootPath,
@@ -55,25 +48,26 @@ func getAuthFileOptions() (cmd []string, err error) {
5548
}
5649

5750
// get bulid command options
58-
// args:
59-
//
60-
// envPath - env path
61-
func getBuildOptions(abs, envPath string) (cmd []string) {
51+
func getBuildOptions() (imageName string, cmd []string, err error) {
52+
var authFileOptions []string
53+
authFileOptions, err = getAuthFileOptions()
54+
imageName = utils.CreateRandomString()
6255
cmd = []string{
6356
"build",
57+
"--force-rm",
6458
"--rm",
6559
"--layers=false",
66-
fmt.Sprintf(
67-
"--output=type=local,dest=%v",
68-
filepath.Join(abs, envPath, configs.Config.EnvSettings.RootDir),
69-
),
60+
"--tag",
61+
imageName,
62+
authFileOptions[0],
63+
authFileOptions[1],
7064
}
7165
return
7266
}
7367

7468
// garbage collection
75-
func clearBuildCache(envPath string) (err error) {
76-
var options = getGlobalBuildahOptions("", envPath)
69+
func clearBuildCache() (err error) {
70+
var options = getGlobalBuildahOptions()
7771
options = append(options, "prune")
7872
options = append(options, "-af")
7973
err = runCommand(configs.Config.Buildah.Path, options)

internal/builder/mounting.go

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
package builder
2+
3+
import (
4+
"os"
5+
"path/filepath"
6+
"strings"
7+
8+
"github.com/bruttazz/devc/internal/configs"
9+
"github.com/bruttazz/devc/internal/utils"
10+
)
11+
12+
const rootfsExtracterScript string = `#!/bin/sh
13+
14+
ctrName=$( __BUILDAH_BASE_EXEC from __IMAGE_NAME )
15+
mountName=$( __BUILDAH_BASE_EXEC mount $ctrName )
16+
mkdir -p $(dirname __OUT_ROOT)
17+
cp -r $mountName __OUT_ROOT
18+
chmod -R u+rwx __OUT_ROOT
19+
__BUILDAH_BASE_EXEC umount $ctrName
20+
__BUILDAH_BASE_EXEC rm $ctrName
21+
`
22+
23+
func exportImageAsRootFs(imageName, outDirPath string) (err error) {
24+
var cmdLines = configs.Config.Buildah.Path + " " + strings.Join(getGlobalBuildahOptions(), " ")
25+
cmdLines = strings.ReplaceAll(rootfsExtracterScript, "__BUILDAH_BASE_EXEC", cmdLines)
26+
cmdLines = strings.ReplaceAll(cmdLines, "__IMAGE_NAME", imageName)
27+
cmdLines = strings.ReplaceAll(cmdLines, "__OUT_ROOT", outDirPath)
28+
29+
// actual tempfile got issue on forking the defer command gets to do something
30+
fileName := filepath.Join(configs.Config.CacheDir, "_temp_script_"+imageName+".sh")
31+
err = utils.WriteTextToFile(fileName, cmdLines)
32+
defer os.Remove(fileName)
33+
if err != nil {
34+
return
35+
}
36+
err = utils.MakeExecutable(fileName)
37+
if err != nil {
38+
return
39+
}
40+
err = runCommand(configs.Config.Buildah.Path, []string{
41+
"unshare",
42+
fileName,
43+
})
44+
return
45+
}

internal/configs/options.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -34,8 +34,5 @@ type PullCmdOptions struct {
3434
NoCaching bool
3535
}
3636

37-
type RmCmdOptions struct {
38-
}
39-
4037
type RmiCmdOptions struct {
4138
}

0 commit comments

Comments
 (0)