Skip to content

Commit

Permalink
fix and add unit tests
Browse files Browse the repository at this point in the history
Signed-off-by: Rakshit Gondwal <[email protected]>
  • Loading branch information
rakshitgondwal committed Jul 9, 2024
1 parent 100e2fa commit e1e33e9
Show file tree
Hide file tree
Showing 3 changed files with 162 additions and 58 deletions.
40 changes: 35 additions & 5 deletions cmd/oci/oci.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@ func init() {
OCICmd.Flags().BoolVarP(&loadPodman, "load-podman", "", false, "Load the image into podman")
OCICmd.Flags().BoolVarP(&push, "push", "", false, "Push the image to the registry")
OCICmd.Flags().BoolVarP(&devDeps, "dev", "", false, "Build base image for Dev Dependencies")
OCICmd.Flags().BoolVarP(&dfSwap, "df-swap", "", false, "Build base image for Dev Dependencies")
OCICmd.Flags().BoolVarP(&dfSwap, "df-swap", "", false, "Modify base images in Dockerfile")
OCICmd.Flags().StringVarP(&tag, "tag", "t", "", "The tag that will be replaced with original tag in Dockerfile")
OCICmd.Flags().StringVar(&path, "path", "", "The path to Dockerfile")
}
Expand Down Expand Up @@ -66,16 +66,14 @@ var OCICmd = &cobra.Command{

if dfSwap {
if tag != "" {
if err := builddocker.ModifyDockerfile(path, tag, devDeps); err != nil {
if err = modifyDockerfileWithTag(path, tag, devDeps); err != nil {
fmt.Println(styles.ErrorStyle.Render("error: ", err.Error()))
os.Exit(1)
}
fmt.Println(styles.SucessStyle.Render("dockerfile succesfully updated with tag:", tag))
os.Exit(1)
} else {
fmt.Println(styles.HintStyle.Render("hint:", "use --tag flag to define a tag"))
os.Exit(1)
}
os.Exit(1)
}

sc, fh, err := binit.GetBSFInitializers()
Expand Down Expand Up @@ -254,6 +252,38 @@ func ProcessPlatformAndConfig(plat string, envName string) (hcl2nix.OCIArtifact,
return artifact, plat, nil
}

func modifyDockerfileWithTag(path, tag string, devDeps bool) error {
var dockerfilePath string
if path != "" {
dockerfilePath = path + "/Dockerfile"
} else {
dockerfilePath = "./Dockerfile"
}

_, err := os.Stat(dockerfilePath)
if err != nil {
return err
}

file, err := os.Open(dockerfilePath)
if err != nil {
return err
}
defer file.Close()

resLines, err := builddocker.ModifyDockerfile(file, devDeps, tag)
if err != nil {
return err
}

err = os.WriteFile(dockerfilePath, []byte(strings.Join(resLines, "\n")), 0644)
if err != nil {
return err
}

return nil
}

func genOCIAttrName(env, platform string, artifact hcl2nix.OCIArtifact) string {
var arch string

Expand Down
100 changes: 47 additions & 53 deletions pkg/builddocker/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,80 +50,74 @@ func GenerateDockerfile(w io.Writer, env hcl2nix.OCIArtifact, platform string) e
}

// ModifyDockerfile modifies the Dockerfile with the specified tag
func ModifyDockerfile(path, tag string, dev bool) error {
var dockerfilePath string
if path != "" {
dockerfilePath = path + "/Dockerfile"
} else {
dockerfilePath = "./Dockerfile"
}

if _, err := os.Stat(dockerfilePath); os.IsNotExist(err) {
return fmt.Errorf("dockerfile not found")
func ModifyDockerfile(file *os.File, dev bool, tag string) ([]string, error) {
lines, err := readDockerFile(file)
if err != nil {
return nil, err
}

file, err := os.Open(dockerfilePath)
reslines, err := editDockerfile(lines, dev, tag)
if err != nil {
return fmt.Errorf("error opening Dockerfile: %v", err)
return nil, err
}
defer file.Close()

return reslines, nil
}

func readDockerFile(file *os.File) ([]string, error) {
scanner := bufio.NewScanner(file)
lines := []string{}
for scanner.Scan() {
lines = append(lines, scanner.Text())
}
if err := scanner.Err(); err != nil {
return fmt.Errorf("error reading Dockerfile: %v", err)
}

var searchTag string
if dev {
searchTag = "# bsfimage:dev"
} else {
searchTag = "# bsfimage:runtime"
return nil, fmt.Errorf("error reading Dockerfile: %v", err)
}
return lines, nil
}

var selectedFrom string
var selectedIndex int
for i, line := range lines {
if strings.Contains(line, searchTag) {
selectedFrom = line
selectedIndex = i
break
func editDockerfile(lines []string, dev bool, tag string) ([]string, error) {
var searchTag string
if dev {
searchTag = "# bsfimage:dev"
} else {
searchTag = "# bsfimage:runtime"
}
}

if selectedFrom == "" {
return fmt.Errorf("no FROM command found with tag %s", searchTag)
}
var selectedFrom string
var selectedIndex int
for i, line := range lines {
if strings.Contains(line, searchTag) {
selectedFrom = line
selectedIndex = i
break
}
}

fromParts := strings.Fields(selectedFrom)
if len(fromParts) < 2 {
return fmt.Errorf("invalid FROM command format")
}
if selectedFrom == "" {
return nil, fmt.Errorf("no FROM command found with tag %s", searchTag)
}

var newFrom string
if strings.Contains(fromParts[1], ":") {
imageParts := strings.Split(fromParts[1], ":")
newFrom = fmt.Sprintf("FROM %s:%s", imageParts[0], tag)
} else {
newFrom = fmt.Sprintf("FROM %s:%s", fromParts[1], tag)
}
for _, part := range fromParts[2:] {
newFrom = fmt.Sprintf("%s %s", newFrom, part)
}
fromParts := strings.Fields(selectedFrom)
if len(fromParts) < 2 {
return nil, fmt.Errorf("invalid FROM command format")
}

lines[selectedIndex] = newFrom
var newFrom string
if strings.Contains(fromParts[1], ":") {
imageParts := strings.Split(fromParts[1], ":")
newFrom = fmt.Sprintf("FROM %s:%s", imageParts[0], tag)
} else {
newFrom = fmt.Sprintf("FROM %s:%s", fromParts[1], tag)
}
for _, part := range fromParts[2:] {
newFrom = fmt.Sprintf("%s %s", newFrom, part)
}

err = os.WriteFile(dockerfilePath, []byte(strings.Join(lines, "\n")), 0644)
if err != nil {
return fmt.Errorf("error writing to Dockerfile: %v", err)
lines[selectedIndex] = newFrom
return lines, nil
}

return nil
}

func convertExportCfgToDockerfileCfg(env hcl2nix.OCIArtifact, platform string) dockerfileCfg {
switch platform {
case "linux/amd64":
Expand Down
80 changes: 80 additions & 0 deletions pkg/builddocker/build_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package builddocker

import (
"testing"

"github.com/stretchr/testify/assert"
)

func TestEditDockerFile(t *testing.T) {
tests := []struct {
name string
lines []string
isDev bool
tag string
expectedRes []string
expectError bool
}{
{
name: "Dev",
lines: []string{
"FROM ubuntu:18.04 # bsfimage:dev",
"RUN apt-get update",
},
isDev: true,
tag: "latest",
expectedRes: []string{
"FROM ubuntu:latest # bsfimage:dev",
"RUN apt-get update",
},
expectError: false,
},
{
name: "Runtime",
lines: []string{
"FROM ubuntu:18.04 # bsfimage:runtime",
"RUN apt-get update",
},
isDev: false,
tag: "latest",
expectedRes: []string{
"FROM ubuntu:latest # bsfimage:runtime",
"RUN apt-get update",
},
expectError: false,
},
{
name: "No FROM Command with bsf tag",
lines: []string{
"FROM ubuntu:latest",
"RUN apt-get update",
},
isDev: true,
tag: "latest",
expectedRes: nil,
expectError: true,
},
{
name: "No FROM Command",
lines: []string{
"RUN apt-get update",
},
isDev: true,
tag: "latest",
expectedRes: nil,
expectError: true,
},
}

for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
res, err := editDockerfile(tt.lines, tt.isDev, tt.tag)
if tt.expectError {
assert.Error(t, err)
} else {
assert.NoError(t, err)
assert.Equal(t, tt.expectedRes, res)
}
})
}
}

0 comments on commit e1e33e9

Please sign in to comment.