You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

192 lines
4.9 KiB

/*
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
}