From 8b9cbd567ce13b72f1ba38026fff965237f751e1 Mon Sep 17 00:00:00 2001 From: Drew Short Date: Fri, 8 Oct 2021 13:39:21 -0500 Subject: [PATCH] Moved dockerfile parser and wired up check stage --- cmd/check.go | 29 ++++++++++++-- cmd/root.go | 20 +++++----- distribution/rhel.Dockerfile | 0 distribution/ubuntu.Dockerfile | 17 ++++++++ internal/parser/dockerfile.go | 30 -------------- internal/parser/dockerfile/dockerfile.go | 51 ++++++++++++++++++++++++ internal/parser/parser.go | 24 +++++++++++ 7 files changed, 128 insertions(+), 43 deletions(-) delete mode 100644 distribution/rhel.Dockerfile delete mode 100644 internal/parser/dockerfile.go create mode 100644 internal/parser/dockerfile/dockerfile.go diff --git a/cmd/check.go b/cmd/check.go index 616696f..d062848 100644 --- a/cmd/check.go +++ b/cmd/check.go @@ -17,9 +17,13 @@ limitations under the License. package cmd import ( - "fmt" + log "github.com/sirupsen/logrus" + "os" + "path" "github.com/spf13/cobra" + + "sothr.com/warricksothr/pinned-package-updater/internal/parser/dockerfile" ) // checkCmd represents the check command @@ -32,16 +36,33 @@ updates to satisfy the requirement of running the latest security version for th To run in standalone mode, provide a alpine.Dockerfile path to evaluate or rely on the default behavior which looks for a alpine.Dockerfile in the current directory. -pinned-package-updater check [alpine.Dockerfile] +pinned-package-updater check [Dockerfile, ...] To run in distributed mode, provide the remote address of the service that will provide information about the remote. -pinned-package-updater --remote
check [alpine.Dockerfile] +pinned-package-updater --remote
check [Dockerfile, ...] `, Run: func(cmd *cobra.Command, args []string) { - fmt.Println("check called") + + // Handle no Dockerfile path provided + if len(args) < 1 { + currentDirectory, currentDirectoryErr := os.Getwd() + cobra.CheckErr(currentDirectoryErr) + defaultDockerfilePath := path.Join(currentDirectory, "Dockerfile") + args = append(args, defaultDockerfilePath) + log.Debugf("No dockerfile path provided, attempting to use the default %s dockerfile", defaultDockerfilePath) + } + + // Aggregate the parsed updates + for _, dockerfilePath := range args { + log.Debugf("Parsing %s", dockerfilePath) + _, err := dockerfile.Parse(dockerfilePath) + if err != nil { + return + } + } }, } diff --git a/cmd/root.go b/cmd/root.go index 7150a60..248ef5e 100644 --- a/cmd/root.go +++ b/cmd/root.go @@ -18,16 +18,16 @@ package cmd import ( "fmt" - log "github.com/sirupsen/logrus" - "github.com/spf13/cobra" - "github.com/thediveo/enumflag" "os" + log "github.com/sirupsen/logrus" + + "github.com/spf13/cobra" "github.com/spf13/viper" + "github.com/thediveo/enumflag" ) -// https://pkg.go.dev/github.com/thediveo/enumflag#section-readme -// Custom enum for supported log output types +// LogFormat Custom enum for supported log output types https://pkg.go.dev/github.com/thediveo/enumflag#section-readme type LogFormat enumflag.Flag const ( @@ -40,10 +40,12 @@ var LogFormatIds = map[LogFormat][]string{ JSON: {"json"}, } -var configFile string -var remoteURL string -var logVerbosity int -var logFormat LogFormat +var ( + configFile string + remoteURL string + logVerbosity int + logFormat LogFormat +) // rootCmd represents the base command when called without any subcommands var rootCmd = &cobra.Command{ diff --git a/distribution/rhel.Dockerfile b/distribution/rhel.Dockerfile deleted file mode 100644 index e69de29..0000000 diff --git a/distribution/ubuntu.Dockerfile b/distribution/ubuntu.Dockerfile index e69de29..aa9ca07 100644 --- a/distribution/ubuntu.Dockerfile +++ b/distribution/ubuntu.Dockerfile @@ -0,0 +1,17 @@ +FROM golang:1.17-buster as builder + +ENV GO111MODULE=on + +WORKDIR /go/src/app +COPY . . + +RUN go build -v + +FROM ubuntu:20.04 AS server + +WORKDIR /app + +COPY --from=builder /go/src/app/pinned-package-updater . + +ENTRYPOINT ["/app/pinned-package-updater"] +CMD ["serve"] \ No newline at end of file diff --git a/internal/parser/dockerfile.go b/internal/parser/dockerfile.go deleted file mode 100644 index b936e84..0000000 --- a/internal/parser/dockerfile.go +++ /dev/null @@ -1,30 +0,0 @@ -/* -Copyright © 2021 Drew Short - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -// Package parser implements the required components for working with image definitions -package parser - -import ( - "github.com/moby/buildkit/frontend/dockerfile/parser" - "os" -) - -func parse(dockerfilePath string) { - dockerfile, err := os.Open(dockerfilePath) - defer dockerfile.Close() - - parseResult, err := parser.Parse(dockerfile) -} diff --git a/internal/parser/dockerfile/dockerfile.go b/internal/parser/dockerfile/dockerfile.go new file mode 100644 index 0000000..5af959d --- /dev/null +++ b/internal/parser/dockerfile/dockerfile.go @@ -0,0 +1,51 @@ +/* +Copyright © 2021 Drew Short + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +// Package dockerfile implements the required components for working with dockerfile image definitions +package dockerfile + +import ( + "os" + + log "github.com/sirupsen/logrus" + + buildkitDockerfile "github.com/moby/buildkit/frontend/dockerfile/parser" + + "sothr.com/warricksothr/pinned-package-updater/internal/parser" +) + +// Parse reads a Dockerfile, interprets the AST and returns information about the image(s) and package(s) defined +func Parse(dockerfilePath string) (parser.ParseResult, error) { + dockerfile, err := os.Open(dockerfilePath) + if err != nil { + log.Fatalf("Unexpected error reading file %s: %s", dockerfilePath, err) + return parser.ParseResult{}, err + } + defer func(dockerfile *os.File) { + err := dockerfile.Close() + if err != nil { + log.Error("Unexpected error closing file %s: %s", dockerfilePath, err) + } + }(dockerfile) + + _, err = buildkitDockerfile.Parse(dockerfile) + if err != nil { + log.Fatalf("Unexpected error parsing Dockerfile %s: %s", dockerfilePath, err) + return parser.ParseResult{}, err + } + + return parser.ParseResult{}, nil +} diff --git a/internal/parser/parser.go b/internal/parser/parser.go index 10c689f..6ae8b5e 100644 --- a/internal/parser/parser.go +++ b/internal/parser/parser.go @@ -16,3 +16,27 @@ limitations under the License. // Package parser implements the required components for working with image definitions package parser + +// ParseResult is the standard representation for am image declaration +type ParseResult struct { + stages []Stage +} + +// Stage is the representation of a stage in the image declaration +type Stage struct { + name string + image string + packages []Package + repositories []Repository +} + +// Package is the representation of an installed pinned package defined in an image stage declaration +type Package struct { + name string + version string +} + +// Repository is the representation of an added repository defined in a stage declaration +type Repository struct { + path string +}