Skip to content

Commit

Permalink
feat: add bsf dockerfile digests command
Browse files Browse the repository at this point in the history
Signed-off-by: hanshal101 <[email protected]>
  • Loading branch information
hanshal101 authored and hanshal101 committed Jul 13, 2024
1 parent 328645e commit c77b246
Show file tree
Hide file tree
Showing 3 changed files with 142 additions and 10 deletions.
3 changes: 1 addition & 2 deletions cmd/dockerfile/df.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,11 +10,10 @@ import (
)

var (
output, platform string
platform string
)

func init() {
DFCmd.Flags().StringVarP(&output, "output", "o", "", "location of the dockerfile generated")
DFCmd.Flags().StringVarP(&platform, "platform", "p", "", "The platform to build the image for")
DFCmd.AddCommand(DGCmd)
}
Expand Down
131 changes: 131 additions & 0 deletions cmd/dockerfile/digest_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
package dockerfile

import (
"bytes"
"testing"
)

func TestReadByte(t *testing.T) {
testCases := []struct {
name string
input []byte
expected []string
}{
{
name: "Test 1",
input: []byte(`
FROM ubuntu:latest
FROM nginx:1.19.10
# Comment line for Testing
FROM golang:1.16.5-alpine3.13
`),
expected: []string{"ubuntu:latest", "nginx:1.19.10", "golang:1.16.5-alpine3.13"},
},
{
name: "Test 2",
input: []byte(""),
expected: []string{},
},
{
name: "Test 3",
input: []byte(`
# Testing ....
RUN apt-get update
`),
expected: []string{},
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
lines, err := readByte(tc.input)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}

if !equalSlice(lines, tc.expected) {
t.Errorf("got %v; expected %v", lines, tc.expected)
}
})
}
}

func equalSlice(a, b []string) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if a[i] != b[i] {
return false
}
}
return true
}

func TestUpdatedockerfileWithDigests(t *testing.T) {
testCases := []struct {
name string
inputData []byte
digestMap map[string]string
expectedData []byte
}{
{
name: "Test 1",
inputData: []byte(`
FROM ubuntu:20.04
`),
digestMap: map[string]string{
"ubuntu:20.04": "sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc",
},
expectedData: []byte(`
FROM ubuntu@sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc
`),
},
{
name: "Test 2",
inputData: []byte(`
FROM ubuntu:20.04
FROM python:3.9-slim
FROM node:14
FROM node:latest AS build
`),
digestMap: map[string]string{
"ubuntu:20.04": "sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc",
"node:14": "sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6fd8461aa",
"node:latest": "sha256:c8a559f733bf1f9b3c1d05b97d9a9c7e5d3647c99abedaf5cdd3b54c9cbb8eff",
},
expectedData: []byte(`
FROM ubuntu@sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc
FROM python:3.9-slim
FROM node@sha256:a158d3b9b4e3fa813fa6c8c590b8f0a860e015ad4e59bbce5744d2f6fd8461aa
FROM node@sha256:c8a559f733bf1f9b3c1d05b97d9a9c7e5d3647c99abedaf5cdd3b54c9cbb8eff AS build
`),
},
{
name: "Test 3",
inputData: []byte(`
FROM busybox:latest
RUN apt-get update
`),
digestMap: map[string]string{
"ubuntu:20.04": "sha256:0b897358ff6624825fb50d20ffb605ab0eaea77ced0adb8c6a4b756513dec6fc",
},
expectedData: []byte(`
FROM busybox:latest
RUN apt-get update
`),
},
}

for _, tc := range testCases {
t.Run(tc.name, func(t *testing.T) {
result, err := updateDockerfileWithDigests(tc.inputData, tc.digestMap)
if err != nil {
t.Fatalf("unexpected error: %v", err)
}
if !bytes.Equal(result, tc.expectedData) {
t.Errorf("got %s; expected %s", result, tc.expectedData)
}
})
}
}
18 changes: 10 additions & 8 deletions cmd/dockerfile/digests.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package dockerfile

import (
"bufio"
"bytes"
"fmt"
"os"
"regexp"
Expand All @@ -26,32 +27,32 @@ var DGCmd = &cobra.Command{
dockerfile := args[0]
file, err := os.ReadFile(dockerfile)
if err != nil {
fmt.Printf("Error opening Dockerfile: %v\n", err)
fmt.Println(styles.ErrorStyle.Render("error:", "opening dockerfile:", err.Error()))
os.Exit(1)
}

var dgMap = map[string]string{}
var dgMap = make(map[string]string)

line, err := readByte(file)
if err != nil {
fmt.Printf("Error in readByte %v\n", err)
fmt.Println(styles.ErrorStyle.Render("error in parsing Dockerfile contents", err.Error()))
os.Exit(1)
}

dgMap, err = getDigest(line)
if err != nil {
fmt.Printf("Error retrieving digest %v\n", err)
fmt.Println(styles.ErrorStyle.Render("Error retrieving digest", err.Error()))
os.Exit(1)
}

updatedData, err := updateDockerfileWithDigests(file, dgMap)
if err != nil {
fmt.Printf("Error updating Dockerfile with digests: %v\n", err)
fmt.Println(styles.ErrorStyle.Render("Error updating Dockerfile with digests", err.Error()))
os.Exit(1)
}

if err := os.WriteFile(dockerfile, updatedData, 0644); err != nil {
fmt.Printf("Error writing updated Dockerfile: %v\n", err)
fmt.Println(styles.ErrorStyle.Render("Error writing updated Dockerfile", err.Error()))
os.Exit(1)
}
},
Expand Down Expand Up @@ -84,7 +85,7 @@ func getDigest(lines []string) (map[string]string, error) {
}

func readByte(file []byte) ([]string, error) {
scanner := bufio.NewScanner(strings.NewReader(string(file)))
scanner := bufio.NewScanner(bytes.NewReader(file))
re := regexp.MustCompile(`FROM\s+(\S+):(\S+)`)
var lines []string

Expand All @@ -106,7 +107,8 @@ func updateDockerfileWithDigests(data []byte, digestMap map[string]string) ([]by
for scanner.Scan() {
line := scanner.Text()
for tag, digest := range digestMap {
line = strings.Replace(line, tag, digest, 1)
img := strings.Split(tag, ":")
line = strings.Replace(line, tag, img[0]+"@"+digest, 1)
}
updatedLines = append(updatedLines, line)
}
Expand Down

0 comments on commit c77b246

Please sign in to comment.