Skip to content

Commit

Permalink
feat: Update the Golang Dockerfilegenerator transformer to support mu…
Browse files Browse the repository at this point in the history
…lti-arch build (#943)

Signed-off-by: Akash Nayak <akash19nayak@gmail.com>
  • Loading branch information
Akash-Nayak authored Jan 15, 2023
1 parent 1cb2304 commit e86cbfe
Show file tree
Hide file tree
Showing 5 changed files with 105 additions and 19 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
apiVersion: move2kube.konveyor.io/v1alpha1
kind: GolangVersionsMapping
metadata:
name: GolangVersionsMapping
spec:
golangVersions:
- version: "1.18"
imageTag: "1.18"
- version: "1.17"
imageTag: "1.17"
- version: "1.16"
imageTag: "1.16.12"
- version: "1.15"
imageTag: "1.15.14"
- version: "1.14"
imageTag: "1.14.12"
- version: "1.13"
imageTag: "1.13.15"
- version: "1.12"
imageTag: "1.12.8"
Original file line number Diff line number Diff line change
Expand Up @@ -13,22 +13,14 @@
# limitations under the License.

# Build App
FROM registry.access.redhat.com/ubi8/ubi:latest AS builder
WORKDIR /temp
ENV GOPATH=/go
ENV PATH=$GOPATH/bin:/usr/local/go/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
RUN curl -o go.tar.gz https://dl.google.com/go/go{{ .GoVersion }}.linux-amd64.tar.gz
RUN tar -xzf go.tar.gz && mv go /usr/local/
RUN yum install git make -y
RUN mkdir -p $GOPATH/src $GOPATH/bin && chmod -R 777 $GOPATH
FROM registry.access.redhat.com/ubi8/go-toolset:{{ .GolangImageTag }} AS builder
WORKDIR /{{ .AppName }}
COPY . .
RUN go build -o {{ .AppName }}
RUN cp ./{{ .AppName }} /bin/{{ .AppName }}
RUN go build -o ./bin/{{ .AppName }}

# Run App
FROM registry.access.redhat.com/ubi8/ubi-minimal:8.3-201
COPY --from=builder /bin/{{ .AppName }} /bin/{{ .AppName }}
COPY --from=builder /{{ .AppName }}/bin/{{ .AppName }} /bin/{{ .AppName }}
{{- range $port := .Ports }}
EXPOSE {{ $port }}
{{- end }}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,5 @@ spec:
disabled: false
config:
defaultGoVersion: "1.18"
externalFiles:
"./mappings/golangversions.yaml" : mappings/golangversions.yaml
1 change: 1 addition & 0 deletions assets/filepermissions.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@
"built-in/transformers/dockerfilegenerator/common/Dockerfile.license" : 0644
"built-in/transformers/dockerfilegenerator/dotnetcore/templates/Dockerfile" : 0644
"built-in/transformers/dockerfilegenerator/dotnetcore/transformer.yaml" : 0644
"built-in/transformers/dockerfilegenerator/golang/mappings/golangversions.yaml" : 0644
"built-in/transformers/dockerfilegenerator/golang/templates/Dockerfile" : 0644
"built-in/transformers/dockerfilegenerator/golang/transformer.yaml" : 0644
"built-in/transformers/dockerfilegenerator/java/earanalyser/transformer.yaml" : 0644
Expand Down
87 changes: 79 additions & 8 deletions transformer/dockerfilegenerator/golangdockerfiletransformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,36 +20,55 @@ import (
"fmt"
"os"
"path/filepath"
"sort"

"github.com/konveyor/move2kube/common"
"github.com/konveyor/move2kube/environment"
"github.com/konveyor/move2kube/types"
irtypes "github.com/konveyor/move2kube/types/ir"
"github.com/konveyor/move2kube/types/qaengine/commonqa"
transformertypes "github.com/konveyor/move2kube/types/transformer"
"github.com/konveyor/move2kube/types/transformer/artifacts"
"github.com/sirupsen/logrus"
"golang.org/x/mod/modfile"
"golang.org/x/mod/module"
"golang.org/x/mod/semver"
)

const (
defaultGoVersion = "1.18"
golangVersionMappingFilePath = "mappings/golangversions.yaml"
// GolangModFilePathType points to the go.mod file path
GolangModFilePathType transformertypes.PathType = "GoModFilePath"
// GolangVersionsMappingKind defines kind of GolangVersionMappingKind
GolangVersionsMappingKind types.Kind = "GolangVersionsMapping"
)

// GolangVersionsMapping stores the Go versions mapping
type GolangVersionsMapping struct {
types.TypeMeta `yaml:",inline"`
types.ObjectMeta `yaml:"metadata,omitempty"`
Spec GolangVersionsMappingSpec `yaml:"spec,omitempty"`
}

// GolangVersionsMappingSpec stores the Go version spec
type GolangVersionsMappingSpec struct {
DisableSort bool `yaml:"disableSort"`
GolangVersions []map[string]string `yaml:"golangVersions"`
}

// GolangDockerfileGenerator implements the Transformer interface
type GolangDockerfileGenerator struct {
Config transformertypes.Transformer
Env *environment.Environment
GolangConfig *GolangDockerfileYamlConfig
Spec GolangVersionsMappingSpec
}

// GolangTemplateConfig implements Golang config interface
type GolangTemplateConfig struct {
Ports []int32
AppName string
GoVersion string
Ports []int32
AppName string
GolangImageTag string
}

// GolangDockerfileYamlConfig represents the configuration of the Golang dockerfile
Expand All @@ -67,9 +86,21 @@ func (t *GolangDockerfileGenerator) Init(tc transformertypes.Transformer, env *e
logrus.Errorf("unable to load config for Transformer %+v into %T : %s", t.Config.Spec.Config, t.GolangConfig, err)
return err
}
// load the version mapping file
mappingFilePath := filepath.Join(t.Env.GetEnvironmentContext(), golangVersionMappingFilePath)
spec, err := LoadGolangVersionMappingsFile(mappingFilePath)
if err != nil {
return fmt.Errorf("failed to load the Golang version mappings file at path %s . Error: %q", golangVersionMappingFilePath, err)
}
t.Spec = spec
if t.GolangConfig.DefaultGoVersion == "" {
t.GolangConfig.DefaultGoVersion = defaultGoVersion
if len(t.Spec.GolangVersions) != 0 {
if _, ok := t.Spec.GolangVersions[0][versionKey]; ok {
t.GolangConfig.DefaultGoVersion = t.Spec.GolangVersions[0][versionKey]
}
}
}
logrus.Debugf("Extracted Golang versions from Go version mappings file - %+v", t.Spec)
return nil
}

Expand Down Expand Up @@ -152,15 +183,31 @@ func (t *GolangDockerfileGenerator) Transform(newArtifacts []transformertypes.Ar
logrus.Debugf("Didn't find the Go version in the go.mod file at path %s, selecting Go version %s", a.Paths[GolangModFilePathType][0], t.GolangConfig.DefaultGoVersion)
modFile.Go.Version = t.GolangConfig.DefaultGoVersion
}
golangVersionToImageTagMapping := make(map[string]string)
for _, golangVersion := range t.Spec.GolangVersions {
if imageTag, ok := golangVersion[imageTagKey]; ok {
golangVersionToImageTagMapping[golangVersion[versionKey]] = imageTag
}
}
logrus.Debugf("Extracted Golang version-image tag mappings are %+v", golangVersionToImageTagMapping)
var golangImageTag string
imageTag, ok := golangVersionToImageTagMapping[modFile.Go.Version]
if ok {
golangImageTag = imageTag
logrus.Debugf("Selected Golang image tag is - %s", golangImageTag)
} else {
golangImageTag = golangVersionToImageTagMapping[t.GolangConfig.DefaultGoVersion]
logrus.Warnf("Could not find a matching Golang version in the mapping. Selecting image tag %s corresponding to the default Golang version %s", golangImageTag, t.GolangConfig.DefaultGoVersion)
}
detectedPorts := ir.GetAllServicePorts()
if len(detectedPorts) == 0 {
detectedPorts = append(detectedPorts, common.DefaultServicePort)
}
detectedPorts = commonqa.GetPortsForService(detectedPorts, `"`+a.Name+`"`)
golangConfig := GolangTemplateConfig{
AppName: a.Name,
Ports: detectedPorts,
GoVersion: modFile.Go.Version,
AppName: a.Name,
Ports: detectedPorts,
GolangImageTag: golangImageTag,
}

pathMappings = append(pathMappings, transformertypes.PathMapping{
Expand Down Expand Up @@ -199,3 +246,27 @@ func (t *GolangDockerfileGenerator) Transform(newArtifacts []transformertypes.Ar
}
return pathMappings, artifactsCreated, nil
}

// LoadGolangVersionMappingsFile loads the Golang version mappings file
func LoadGolangVersionMappingsFile(mappingFilePath string) (GolangVersionsMappingSpec, error) {
mappingFile := GolangVersionsMapping{}
if err := common.ReadMove2KubeYaml(mappingFilePath, &mappingFile); err != nil {
return mappingFile.Spec, fmt.Errorf("failed to load the Golang versions mapping file at path %s . Error: %q", mappingFilePath, err)
}
// validate the file
if len(mappingFile.Spec.GolangVersions) == 0 {
return mappingFile.Spec, fmt.Errorf("the Golang version mappings file at path %s is invalid. Atleast one Go version should be specified", mappingFilePath)
}
for i, v := range mappingFile.Spec.GolangVersions {
if _, ok := v[versionKey]; !ok {
return mappingFile.Spec, fmt.Errorf("the Golang version is missing from the object %#v at the %dth index in the array", mappingFile.Spec.GolangVersions[i], i)
}
}
// sort the list using semantic version comparison
if !mappingFile.Spec.DisableSort {
sort.SliceStable(mappingFile.Spec.GolangVersions, func(i, j int) bool {
return semver.Compare(mappingFile.Spec.GolangVersions[i][versionKey], mappingFile.Spec.GolangVersions[j][versionKey]) == 1
})
}
return mappingFile.Spec, nil
}

0 comments on commit e86cbfe

Please sign in to comment.