|
|
@ -18,11 +18,15 @@ limitations under the License. |
|
|
|
package dockerfile |
|
|
|
|
|
|
|
import ( |
|
|
|
"errors" |
|
|
|
"fmt" |
|
|
|
"os" |
|
|
|
"strings" |
|
|
|
|
|
|
|
log "github.com/sirupsen/logrus" |
|
|
|
|
|
|
|
buildkitDockerfile "github.com/moby/buildkit/frontend/dockerfile/parser" |
|
|
|
buildkitDockerfileInstructions "github.com/moby/buildkit/frontend/dockerfile/instructions" |
|
|
|
buildkitDockerfileParser "github.com/moby/buildkit/frontend/dockerfile/parser" |
|
|
|
|
|
|
|
"sothr.com/warricksothr/pinned-package-updater/internal/parser" |
|
|
|
) |
|
|
@ -41,11 +45,91 @@ func Parse(dockerfilePath string) (parser.ParseResult, error) { |
|
|
|
} |
|
|
|
}(dockerfile) |
|
|
|
|
|
|
|
_, err = buildkitDockerfile.Parse(dockerfile) |
|
|
|
dockerfileParseResults, err := buildkitDockerfileParser.Parse(dockerfile) |
|
|
|
if err != nil { |
|
|
|
log.Fatalf("Unexpected error parsing Dockerfile %s: %s", dockerfilePath, err) |
|
|
|
return parser.ParseResult{}, err |
|
|
|
} |
|
|
|
|
|
|
|
return parser.ParseResult{}, nil |
|
|
|
dockerfileParseResult, err := parseDockerfileAST(dockerfileParseResults.AST) |
|
|
|
if err != nil { |
|
|
|
log.Fatalf("Unexpected error while parsing AST for %s: %s", dockerfilePath, err) |
|
|
|
return parser.ParseResult{}, err |
|
|
|
} |
|
|
|
|
|
|
|
return dockerfileParseResult, nil |
|
|
|
} |
|
|
|
|
|
|
|
type ASTStage struct { |
|
|
|
children []*buildkitDockerfileParser.Node |
|
|
|
} |
|
|
|
|
|
|
|
// parseDockerfileAST Read the parsed AST and extract the required information from each stage
|
|
|
|
func parseDockerfileAST(dockerfileAST *buildkitDockerfileParser.Node) (parser.ParseResult, error) { |
|
|
|
|
|
|
|
dockerfileStages, _, err := buildkitDockerfileInstructions.Parse(dockerfileAST) |
|
|
|
if err != nil { |
|
|
|
log.Fatal("Unexpected error while parsing Dockerfile Instructions") |
|
|
|
return parser.ParseResult{}, err |
|
|
|
} |
|
|
|
|
|
|
|
var stages []*parser.Stage |
|
|
|
for stageIndex, stage := range dockerfileStages { |
|
|
|
stage, err := parseDockerfileStage(stage) |
|
|
|
if err != nil { |
|
|
|
log.Fatal("Unexpected error while parsing stage %d", stageIndex) |
|
|
|
return parser.ParseResult{}, err |
|
|
|
} |
|
|
|
stages = append(stages, &stage) |
|
|
|
} |
|
|
|
|
|
|
|
return parser.ParseResult{Stages: stages}, nil |
|
|
|
} |
|
|
|
|
|
|
|
func parseDockerfileStage(dockerfileStage buildkitDockerfileInstructions.Stage) (parser.Stage, error) { |
|
|
|
|
|
|
|
imageParts := strings.Split(dockerfileStage.BaseName, ":") |
|
|
|
|
|
|
|
if len(imageParts) < 2 { |
|
|
|
message := fmt.Sprintf("Not enough information in image (%s) to determine base", imageParts) |
|
|
|
log.Fatal(message) |
|
|
|
return parser.Stage{}, errors.New(message) |
|
|
|
} |
|
|
|
|
|
|
|
name := dockerfileStage.Name |
|
|
|
image := parser.Image{ |
|
|
|
Name: imageParts[0], |
|
|
|
Tag: imageParts[1], |
|
|
|
} |
|
|
|
|
|
|
|
repositories, err := parseRepositoriesFromDockerfileStage(dockerfileStage) |
|
|
|
if err != nil { |
|
|
|
message := fmt.Sprintf("Unexpected error while parsing repositories from stage") |
|
|
|
log.Fatal(message) |
|
|
|
return parser.Stage{}, errors.New(message) |
|
|
|
} |
|
|
|
|
|
|
|
packages, err := parsePackagesFromDockerfileStage(dockerfileStage) |
|
|
|
if err != nil { |
|
|
|
message := fmt.Sprintf("Unexpected error while parsing packages from stage") |
|
|
|
log.Fatal(message) |
|
|
|
return parser.Stage{}, errors.New(message) |
|
|
|
} |
|
|
|
|
|
|
|
return parser.Stage{ |
|
|
|
Name: name, |
|
|
|
Image: &image, |
|
|
|
Repositories: repositories, |
|
|
|
Packages: packages, |
|
|
|
}, nil |
|
|
|
} |
|
|
|
|
|
|
|
func parsePackagesFromDockerfileStage(_ buildkitDockerfileInstructions.Stage) ([]*parser.Package, error) { |
|
|
|
var packages []*parser.Package |
|
|
|
return packages, nil |
|
|
|
} |
|
|
|
|
|
|
|
func parseRepositoriesFromDockerfileStage(_ buildkitDockerfileInstructions.Stage) ([]*parser.Repository, error) { |
|
|
|
var repositories []*parser.Repository |
|
|
|
return repositories, nil |
|
|
|
} |