|
|
/* Copyright © 2021 Drew Short <warrick@sothr.com>
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 ( "errors" "fmt" log "github.com/sirupsen/logrus" )
// ParseResult is the standard representation for am image declaration
type ParseResult struct { FilePath string Stages []*Stage }
// String implements fmt.Stringer interface
func (pr ParseResult) String() string { return fmt.Sprintf( "%s with %d stage(s)", pr.FilePath, len(pr.Stages), ) }
// Stage is the representation of a stage in the image declaration
type Stage struct { Index int Name string Image *Image Repositories []*Repository Packages []*Package StageLocation ContentLocation CommandLocations []*ContentLocation }
// String implements fmt.Stringer interface
func (s Stage) String() string { return fmt.Sprintf( "%d %s %s", s.Index, s.Name, s.Image, ) }
// ContentLocation information about where a specific set of information exists within the file/manifest
type ContentLocation struct { StartLine int StartCharacter int EndLine int EndCharacter int }
// String implements fmt.Stringer interface
func (cl ContentLocation) String() string { return fmt.Sprintf( "%d.%d:%d.%d", cl.StartLine, cl.StartCharacter, cl.EndLine, cl.EndCharacter, ) }
// Image is the representation of the reference to a container image layer
type Image struct { Name string Tag string }
// String implements fmt.Stringer interface
func (i Image) String() string { return fmt.Sprintf( "%s:%s", i.Name, i.Tag, ) }
// Package is the representation of an installed pinned package defined in an image stage declaration
type Package struct { Name string Version string }
// String implements fmt.Stringer interface
func (p Package) String() string { return fmt.Sprintf( "%s=%s", p.Name, p.Version, ) }
// Repository is the representation of an added repository defined in a stage declaration
type Repository struct { Information string }
// String implements fmt.Stringer interface
func (r Repository) String() string { return fmt.Sprintf( "%s", r.Information, ) }
// CommandParserType represents the recognized type of parser usable for a specific image
type CommandParserType int
const ( CommandParserTypeDebian CommandParserType = iota )
// commandParserTypeIds is a lookup map between CommandParserType and a representation string
var commandParserTypeIds = map[CommandParserType][]string{ CommandParserTypeDebian: {"debian"}, }
// findCommandParserTypeName lookup the command parser name by type enum
func findCommandParserTypeName(parserType CommandParserType) string { if parserTypeName, ok := commandParserTypeIds[parserType]; ok { return parserTypeName[0] } else { return "UNKNOWN" } }
var availableCommandParsers = map[CommandParserType]CommandParser{}
// CommandParser handles parsing commands from RUN arguments dependent on the base image type
type CommandParser interface { GetRepositories(logger *log.Entry, runCommand string) ([]*Repository, error) GetPinnedPackages(logger *log.Entry, runCommand string) ([]*Package, error) }
// InitCommandParsers exposes functionality to configure the behavior of mapping images to a CommandParser
func InitCommandParsers() error {
// Registering known parsers
availableCommandParsers[CommandParserTypeDebian] = newDebianCommandParser()
// TODO: Add dynamic loading from configuration
return nil }
func GetCommandParser(image Image) (*CommandParser, error) { parserType, err := determineParserForImage(image) if err != nil { log.WithFields(log.Fields{ "imageName": image.Name, "imageTag": image.Tag, "sourceError": err, }).Fatal("failed to determine a matching CommandParser for image") return nil, err }
if requestedCommandParser, ok := availableCommandParsers[parserType]; ok { return &requestedCommandParser, nil } else { message := "unable to identify command parser type" log.WithFields(log.Fields{ "commandParserType": findCommandParserTypeName(parserType), }).Fatal(message) return nil, errors.New(message) } }
// determineParserForImage matches image information to the correct CommandParserType
func determineParserForImage(_ Image) (CommandParserType, error) {
// TODO: Map image information to the list of command parsers supported
return CommandParserTypeDebian, nil }
|