Skip to content

Commit

Permalink
feat!: create separate list and query sub-commands
Browse files Browse the repository at this point in the history
  • Loading branch information
shivjm committed Nov 8, 2021
1 parent 58e6c28 commit 52e2059
Show file tree
Hide file tree
Showing 6 changed files with 153 additions and 69 deletions.
4 changes: 4 additions & 0 deletions Dockerfile
Expand Up @@ -4,6 +4,10 @@ WORKDIR /app

COPY go.mod go.sum main.go ./

COPY pkg ./pkg

COPY cmd ./cmd

RUN CGO_ENABLED=0 GOOS=linux go build -tags netgo -ldflags '-w' .

FROM scratch
Expand Down
48 changes: 48 additions & 0 deletions cmd/list.go
@@ -0,0 +1,48 @@
package cmd

import (
"encoding/json"
"fmt"
"log"

"github.com/asottile/dockerfile"
"github.com/shivjm/dockerfile-image-tags/pkg/images"
"github.com/shivjm/dockerfile-image-tags/pkg/input"
"github.com/spf13/cobra"
)

var (
listCmd = &cobra.Command{
Use: "list",
Short: "List images and tags",
Long: "Print a list of the images and tags in the Dockerfile as a JSON array. Every `FROM` instruction in the file corresponds to an entry in the array, so the same image might appear multiple times, with the same or different tags. A special marker (default: `?`) will be returned if the tag is not specified.",
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
file, err := input.GetInput(args)

if err != nil {
log.Fatalf("Could not read Dockerfile: %s", err)
}

parsed, err := dockerfile.ParseReader(file)

if err != nil {
log.Fatalf("Could not parse Dockerfile: %s\n", err)
}

allImages := images.GetImages(parsed, unknownMarker)

val, err := json.Marshal(allImages)

if err != nil {
log.Fatalf("Could not serialize images as JSON: %s\n", err)
}

fmt.Println(string(val))
},
}
)

func init() {
rootCmd.AddCommand(listCmd)
}
65 changes: 65 additions & 0 deletions cmd/query.go
@@ -0,0 +1,65 @@
package cmd

import (
"fmt"
"log"
"os"

"github.com/asottile/dockerfile"
"github.com/shivjm/dockerfile-image-tags/pkg/images"
"github.com/shivjm/dockerfile-image-tags/pkg/input"
"github.com/spf13/cobra"
)

var (
occurrence int

queryCmd = &cobra.Command{
Use: "query",
Short: "Find single image tag",
Long: "Print the tag for a specific image if found, exit with an error otherwise. The image may appear multiple times in the Dockerfile, in which case `occurrence` (default: 1) specifies which instance to return the tag for.",
Args: cobra.RangeArgs(1, 2),
Run: func(cmd *cobra.Command, args []string) {
var file *os.File
var query string

if len(args) == 2 {
f, err := input.GetInput(args[0:1])

if err != nil {
log.Fatalf("Could not read Dockerfile: %s", err)
}

file = f
query = args[1]
} else {
f, _ := input.GetInput([]string{})

file = f
query = args[0]
}

parsed, err := dockerfile.ParseReader(file)

if err != nil {
log.Fatalf("Could not parse Dockerfile: %s\n", err)
}

allImages := images.GetImages(parsed, unknownMarker)

tag, err := images.GetSingleTag(allImages, query, occurrence)

if err != nil {
log.Fatalf("Could not find image in Dockerfile: %s", query)
}

fmt.Println(tag)
},
}
)

func init() {
queryCmd.Flags().IntVarP(&occurrence, "occurrence", "n", 1, "which occurrence of image to return tag for")

rootCmd.AddCommand(queryCmd)
}
22 changes: 22 additions & 0 deletions cmd/root.go
@@ -0,0 +1,22 @@
package cmd

import (
"github.com/spf13/cobra"
)

var (
unknownMarker string

rootCmd = &cobra.Command{
Use: "dockerfile-image-tags",
Short: "List or query images and tags used in a Dockerfile.",
}
)

func Execute() error {
return rootCmd.Execute()
}

func init() {
rootCmd.PersistentFlags().StringVarP(&unknownMarker, "unknown-marker", "m", "?", "string to use to indicate unknown tag")
}
61 changes: 2 additions & 59 deletions main.go
@@ -1,66 +1,9 @@
package main

import (
"encoding/json"
"fmt"
"log"

"github.com/asottile/dockerfile"
"github.com/spf13/cobra"

"github.com/shivjm/dockerfile-image-tags/pkg/images"
"github.com/shivjm/dockerfile-image-tags/pkg/input"
"github.com/shivjm/dockerfile-image-tags/cmd"
)


func main() {
var unknownMarker string
var query string
var occurrence int

var rootCmd = &cobra.Command{
Use: "dockerfile-image-tags",
Short: "List or query images & tags used in a Dockerfile.",
Args: cobra.MaximumNArgs(1),
Run: func(cmd *cobra.Command, args []string) {
file, err := input.GetInput(args)

if err != nil {
log.Fatalf("Could not read Dockerfile: %s", err)
}

parsed, err := dockerfile.ParseReader(file)

if err != nil {
log.Fatalf("Could not parse Dockerfile: %s\n", err)
}

allImages := images.GetImages(parsed, unknownMarker)

val, err := json.Marshal(allImages)

if err != nil {
log.Fatalf("Could not serialize images as JSON: %s\n", err)
}

if query == "" {
fmt.Println(string(val))
} else {
tag, err := images.GetSingleTag(allImages, query, occurrence)

if err != nil {
log.Fatalf("Could not find image in Dockerfile: %s", query)
}

fmt.Println(tag)
}
},
}
rootCmd.Flags().StringVarP(&unknownMarker, "unknown-marker", "m", "?", "string to use to indicate unknown tags")
rootCmd.Flags().StringVarP(&query, "query", "q", "", "single image to return tag for (see `occurrence`)")
rootCmd.Flags().IntVarP(&occurrence, "occurrence", "n", 1, "which occurrence of image to return tag for")

if err := rootCmd.Execute(); err != nil {
log.Fatal(err)
}
cmd.Execute()
}
22 changes: 12 additions & 10 deletions main_test.go → pkg/images/images_test.go
@@ -1,16 +1,18 @@
package main
package images

import (
"testing"

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

"github.com/shivjm/dockerfile-image-tags/pkg/images"
const (
Dockerfile = "../../tests/Dockerfile.1"
)

func TestParsing(t *testing.T) {
expected := []images.Image{
expected := []Image{
{Name: "golang", Tag: "1.17.0-alpine"},
{Name: "common", Tag: " * "},
{Name: "common", Tag: "fixme"},
Expand All @@ -19,13 +21,13 @@ func TestParsing(t *testing.T) {
{Name: "quay.io/argoproj/argocd", Tag: "$ARGOCD_VERSION"},
}

commands, err := dockerfile.ParseFile("tests/Dockerfile.1")
commands, err := dockerfile.ParseFile(Dockerfile)

if err != nil {
t.Errorf("Could not open Dockerfile.1: %s", err)
t.Errorf("Could not open %s: %s", Dockerfile, err)
}

tags := images.GetImages(commands, " * ")
tags := GetImages(commands, " * ")

assert.Equal(t, expected, tags)
}
Expand All @@ -49,16 +51,16 @@ func TestQuery(t *testing.T) {
{query: "common", occurrence: 2, match: true, tag: "fixme"},
}

commands, err := dockerfile.ParseFile("tests/Dockerfile.1")
commands, err := dockerfile.ParseFile(Dockerfile)

if err != nil {
t.Errorf("Could not open Dockerfile.1: %s", err)
t.Errorf("Could not open %s: %s", Dockerfile, err)
}

tags := images.GetImages(commands, "?")
tags := GetImages(commands, "?")

for _, c := range cases {
result, err := images.GetSingleTag(tags, c.query, c.occurrence)
result, err := GetSingleTag(tags, c.query, c.occurrence)

if c.match {
assert.NoError(t, err, "must match %v", c.query)
Expand Down

0 comments on commit 52e2059

Please sign in to comment.