Skip to content

Commit

Permalink
feat: add multiple child project support to dot net core transformer …
Browse files Browse the repository at this point in the history
…as well (#837)

* feat: add multiple child project support to dot net core transformer as well

* fix: bug where sub keys where not quoted properly, especially when involving user input such as service names

* User input like service names, directory and file names need
to be quoted because they can contain special characters like spaces
and dots.

Signed-off-by: Harikrishnan Balagopal <[email protected]>
  • Loading branch information
HarikrishnanBalagopal authored Jul 28, 2022
1 parent d9b61f5 commit 607d042
Show file tree
Hide file tree
Showing 70 changed files with 932 additions and 692 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -12,32 +12,50 @@
# See the License for the specific language governing permissions and
# limitations under the License.

FROM mcr.microsoft.com/dotnet/sdk:{{ .DotNetVersion }} AS builder
{{ if .IncludeBuildStage }}

# Build Stage
FROM mcr.microsoft.com/dotnet/sdk:{{ .BuildStageImageTag }} AS {{ .BuildContainerName }}

{{- if .IsNodeJSProject }}
RUN apt-get update -y && \
apt-get install -y xz-utils && \
wget https://nodejs.org/dist/v16.16.0/node-v16.16.0-linux-x64.tar.xz && \
tar -xJf node-v16.16.0-linux-x64.tar.xz && \
mv node-v16.16.0-linux-x64 /node && \
rm node-v16.16.0-linux-x64.tar.xz
ENV PATH="$PATH:/node/bin"
{{- end }}

WORKDIR /src
COPY . .
RUN mkdir app
RUN dotnet restore {{ .CsprojFilePath }}
RUN dotnet restore

{{- if .IsNodeJSProject}}
RUN curl https://deb.nodesource.com/setup_10.x -o setup_10.x && \
bash setup_10.x && \
apt-get install -y build-essential nodejs
{{- if .PublishProfilePath }}
RUN dotnet publish /p:PublishProfile={{ .PublishProfilePath }} --no-restore
{{- else }}
RUN dotnet publish -c release --no-restore
{{- end }}

{{- if .PublishProfileFilePath }}
RUN dotnet publish {{ .CsprojFilePath }} /p:PublishProfile={{ .PublishProfileFilePath}} -o /src/app/publish
{{- else }}
RUN dotnet publish {{ .CsprojFilePath }} -c Release -o /src/app/publish
{{- end }}


{{ if .IncludeRunStage }}

# Run Stage
FROM mcr.microsoft.com/dotnet/aspnet:{{ .DotNetVersion }}
FROM mcr.microsoft.com/dotnet/aspnet:{{ .RunStageImageTag }}
ENV DOTNET_GENERATE_ASPNET_CERTIFICATE=false
WORKDIR /app
{{- range $port := .Ports }}
EXPOSE {{ $port }}

{{- range .Ports }}
EXPOSE {{ . }}
{{- end }}

{{- range $k, $v := .EnvVariables }}
ENV {{ $k }} {{ $v }}
{{- end }}

COPY {{ if .BuildContainerName }}--from={{ .BuildContainerName }}{{ end }} {{ .CopyFrom }} ./
CMD ["dotnet", "{{ .EntryPointPath }}"]

{{- end }}
{{- if .HTTPPort }}
ENV ASPNETCORE_URLS=http://+:{{ .HTTPPort }}
{{- end}}
COPY --from=builder /src/app/publish .
CMD ["dotnet", "{{ .CsprojFileName }}.dll"]
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ spec:
matchLabels:
move2kube.konveyor.io/earprocessor: "true"
question:
id: "move2kube.services.{{ .name }}.eartransformer"
description: "Select the transformer to use for service {{ .name }}"
id: 'move2kube.services."{{ .name }}".eartransformer'
description: 'Select the transformer to use for the "{{ .name }}" service'
Original file line number Diff line number Diff line change
Expand Up @@ -20,5 +20,5 @@ spec:
matchLabels:
move2kube.konveyor.io/warprocessor: "true"
question:
id: "move2kube.services.{{ .name }}.wartransformer"
description: "Select the transformer to use for service {{ .name }}"
id: 'move2kube.services."{{ .name }}".wartransformer'
description: 'Select the transformer to use for the "{{ .name }}" service'
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,10 @@ RUN msbuild /p:Configuration=Release
{{ if .IncludeRunStage }}
# Run Stage
FROM --platform=windows/amd64 mcr.microsoft.com/dotnet/framework/aspnet:{{ .RunStageImageTag }}
{{- range .Ports}}
EXPOSE {{.}}
{{- end}}
ENV DOTNET_GENERATE_ASPNET_CERTIFICATE=false
WORKDIR /inetpub/wwwroot
{{- range .Ports }}
EXPOSE {{ . }}
{{- end }}
COPY {{ if .BuildContainerName }}--from={{ .BuildContainerName }}{{ end }} {{ .CopyFrom }} ./
{{- end }}
2 changes: 1 addition & 1 deletion collector/clustercollector.go
Original file line number Diff line number Diff line change
Expand Up @@ -380,7 +380,7 @@ func (c *ClusterCollector) groupOrderPolicy(mapKindGV *map[string][]string) {
continue
}

if common.IsStringPresent(sortedGV, gv) {
if common.IsPresent(sortedGV, gv) {
continue
}

Expand Down
8 changes: 4 additions & 4 deletions common/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,13 +146,13 @@ const (
//ConfigImageRegistryNamespaceKey represents image registry namespace Key
ConfigImageRegistryNamespaceKey = ConfigImageRegistryKey + d + "namespace"
//ConfigImageRegistryLoginTypeKey represents image registry login type Key
ConfigImageRegistryLoginTypeKey = ConfigImageRegistryKey + d + "logintype"
ConfigImageRegistryLoginTypeKey = ConfigImageRegistryKey + d + "%s" + d + "logintype"
//ConfigImageRegistryPullSecretKey represents image registry pull secret Key
ConfigImageRegistryPullSecretKey = ConfigImageRegistryKey + d + "pullsecret"
ConfigImageRegistryPullSecretKey = ConfigImageRegistryKey + d + "%s" + d + "pullsecret"
//ConfigImageRegistryUserNameKey represents image registry login Username Key
ConfigImageRegistryUserNameKey = ConfigImageRegistryKey + d + "username"
ConfigImageRegistryUserNameKey = ConfigImageRegistryKey + d + "%s" + d + "username"
//ConfigImageRegistryPasswordKey represents image registry login Password Key
ConfigImageRegistryPasswordKey = ConfigImageRegistryKey + d + "password"
ConfigImageRegistryPasswordKey = ConfigImageRegistryKey + d + "%s" + d + "password"
//ConfigStoragesPVCForHostPathKey represents key for PVC for Host Path
ConfigStoragesPVCForHostPathKey = ConfigStoragesKey + d + "pvcforhostpath"
//ConfigStoragesPerClaimStorageClassKey represents key for having different storage class for claim
Expand Down
6 changes: 3 additions & 3 deletions common/pathconverters/pathconverters.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ func processTag(structT reflect.Type, structV reflect.Value, i int, oldCtx conte
if len(tagParts) == 4 && tagParts[0] == structTagCondition && tagParts[2] == structTagCheckField {
targetField := structV.FieldByName(tagParts[1]).String()
validValues := strings.Split(tagParts[3], ",")
ctx.ShouldConvert = common.IsStringPresent(validValues, targetField)
ctx.ShouldConvert = common.IsPresent(validValues, targetField)
return ctx, nil
}
return ctx, fmt.Errorf("failed to process the tag. Actual tag: %s", tag)
Expand All @@ -87,7 +87,7 @@ func process(value reflect.Value, ctx context) error {
if ctx.CurrentMapKey.Kind() != reflect.String {
return fmt.Errorf("map keys are not of kind string. Actual kind: %v", ctx.CurrentMapKey.Kind())
}
if !common.IsStringPresent(ctx.MapKeysToConvert, ctx.CurrentMapKey.String()) {
if !common.IsPresent(ctx.MapKeysToConvert, ctx.CurrentMapKey.String()) {
break
}
}
Expand Down Expand Up @@ -132,7 +132,7 @@ func process(value reflect.Value, ctx context) error {
if ctx.CurrentMapKey.Kind() != reflect.String {
return fmt.Errorf("map keys are not of kind string. Actual kind: %v", ctx.CurrentMapKey.Kind())
}
if !common.IsStringPresent(ctx.MapKeysToConvert, ctx.CurrentMapKey.String()) {
if !common.IsPresent(ctx.MapKeysToConvert, ctx.CurrentMapKey.String()) {
continue
}
}
Expand Down
57 changes: 37 additions & 20 deletions common/utils.go
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ import (
"github.com/konveyor/move2kube/types"
"github.com/mitchellh/mapstructure"
"github.com/sirupsen/logrus"
"github.com/spf13/cast"
"github.com/xrash/smetrics"
"gopkg.in/yaml.v3"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
Expand All @@ -51,6 +52,27 @@ import (
"k8s.io/apimachinery/pkg/runtime/schema"
)

// Map applies the given function over all the elements and returns a new slice with the results.
func Map[T1 interface{}, T2 interface{}](vs []T1, f func(T1) T2) []T2 {
var ws []T2
for _, v := range vs {
ws = append(ws, f(v))
}
return ws
}

// Filter returns the elements that satisfy the condition.
// It returns nil if none of the elements satisfy the condition.
func Filter[T comparable](vs []T, condition func(T) bool) []T {
var ws []T
for _, v := range vs {
if condition(v) {
ws = append(ws, v)
}
}
return ws
}

// FindIndex returns the index of the first element that satisfies the condition.
// It returns -1 if none of the elements satisfy the condition.
func FindIndex[T comparable](vs []T, condition func(T) bool) int {
Expand Down Expand Up @@ -564,44 +586,39 @@ func NormalizeForEnvironmentVariableName(envName string) string {
return newName
}

// IsStringPresent checks if a value is present in a slice
func IsStringPresent(list []string, value string) bool {
// IsPresent checks if a value is present in a slice
func IsPresent[C comparable](list []C, value C) bool {
for _, val := range list {
if strings.EqualFold(val, value) {
if val == value {
return true
}
}
return false
}

// IsPresent checks if a value is present in a slice
func IsPresent[C comparable](list []C, value C) bool {
// IsStringPresent is like IsPresent but does case-insensitive comparison of strings
func IsStringPresent(list []string, value string) bool {
for _, val := range list {
if val == value {
if strings.EqualFold(val, value) {
return true
}
}
return false
}

// MergeStringSlices merges two string slices
func MergeStringSlices(slice1 []string, slice2 ...string) []string {
for _, item := range slice2 {
if !IsStringPresent(slice1, item) {
slice1 = append(slice1, item)
// AppendIfNotPresent checks if a value is present in a slice and if not appends it to the slice
func AppendIfNotPresent[C comparable](list []C, values ...C) []C {
for _, value := range values {
if !IsPresent(list, value) {
list = append(list, value)
}
}
return slice1
return list
}

// MergeSlices merges two slices
func MergeSlices[C comparable](slice1 []C, slice2 []C) []C {
for _, item := range slice2 {
if !IsPresent(slice1, item) {
slice1 = append(slice1, item)
}
}
return slice1
return AppendIfNotPresent(slice1, slice2...)
}

// GetStringFromTemplate returns string for a template
Expand Down Expand Up @@ -669,7 +686,7 @@ func MergeStringSliceMaps(map1 map[string][]string, map2 map[string][]string) ma
return map1
}
for k, v := range map2 {
map1[k] = MergeStringSlices(map1[k], v...)
map1[k] = MergeSlices(map1[k], v)
}
return map1
}
Expand Down Expand Up @@ -1035,7 +1052,7 @@ func IsParent(child, parent string) bool {

// GetRandomString generates a random string
func GetRandomString() string {
return fmt.Sprintf("%d", rand.Intn(10000000))
return cast.ToString(rand.Intn(10000000))
}

// SplitOnDotExpectInsideQuotes splits a string on dot.
Expand Down
4 changes: 2 additions & 2 deletions environment/environment.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@ import (
"os"
"path/filepath"
"reflect"
"strconv"
"strings"
"text/template"

Expand All @@ -36,6 +35,7 @@ import (
environmenttypes "github.com/konveyor/move2kube/types/environment"
transformertypes "github.com/konveyor/move2kube/types/transformer"
"github.com/sirupsen/logrus"
"github.com/spf13/cast"
)

const (
Expand Down Expand Up @@ -109,7 +109,7 @@ func NewEnvironment(envInfo EnvInfo, grpcQAReceiver net.Addr, c environmenttypes
for _, envvar := range envvars {
envvarpair := strings.SplitN(envvar, "=", 2)
if len(envvarpair) > 0 && envVariableName == c.Image && len(envvarpair) > 1 {
_, err := strconv.Atoi(envvarpair[1])
_, err := cast.ToIntE(envvarpair[1])
if err != nil {
envInfo.Context = envvarpair[1]
env.Env, err = NewLocal(envInfo, grpcQAReceiver)
Expand Down
4 changes: 1 addition & 3 deletions qaengine/cliengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -120,9 +120,7 @@ func (*CliEngine) fetchMultiSelectAnswer(prob qatypes.Problem) (qatypes.Problem,
for _, lineAns := range strings.Split(multilineAns, "\n") {
lineAns = strings.TrimSpace(lineAns)
if lineAns != "" {
if !common.IsStringPresent(newAns, lineAns) {
newAns = append(newAns, lineAns)
}
newAns = common.AppendIfNotPresent(newAns, lineAns)
}
}
}
Expand Down
4 changes: 2 additions & 2 deletions qaengine/engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -323,7 +323,7 @@ func ValidateProblem(prob qatypes.Problem) error {
return fmt.Errorf("expected the defaults to be an array of strings for the QA multiselect problem: %+v\nError: %q", prob, err)
}
for _, def := range defaults {
if !common.IsStringPresent(prob.Options, def) {
if !common.IsPresent(prob.Options, def) {
return fmt.Errorf("one of the defaults [%s] is not present in the options for the QA multiselect problem: %+v", def, prob)
}
}
Expand All @@ -337,7 +337,7 @@ func ValidateProblem(prob qatypes.Problem) error {
if !ok {
return fmt.Errorf("expected the default to be a string for the QA select problem: %+v", prob)
}
if !common.IsStringPresent(prob.Options, def) {
if !common.IsPresent(prob.Options, def) {
return fmt.Errorf("the default [%s] is not present in the options for the QA select problem: %+v", def, prob)
}
}
Expand Down
4 changes: 1 addition & 3 deletions qaengine/httprestengine.go
Original file line number Diff line number Diff line change
Expand Up @@ -131,9 +131,7 @@ func (h *HTTPRESTEngine) FetchAnswer(prob qatypes.Problem) (qatypes.Problem, err
for _, lineAns := range strings.Split(multilineAns, "\n") {
lineAns = strings.TrimSpace(lineAns)
if lineAns != "" {
if !common.IsStringPresent(newAns, lineAns) {
newAns = append(newAns, lineAns)
}
newAns = common.AppendIfNotPresent(newAns, lineAns)
}
}
}
Expand Down
13 changes: 8 additions & 5 deletions transformer/cloudfoundrytransformer.go
Original file line number Diff line number Diff line change
Expand Up @@ -222,11 +222,14 @@ func (t *CloudFoundry) Transform(newArtifacts []transformertypes.Artifact, alrea
ir.Services[sConfig.ServiceName] = serviceConfig
}
if len(cConfig) != 0 {
quesKey := common.JoinQASubKeys(common.ConfigServicesKey, sConfig.ServiceName, common.ConfigContainerizationOptionServiceKeySegment)
containerizationOptions := qaengine.FetchMultiSelectAnswer(quesKey,
fmt.Sprintf("Select the transformer to use for containerization %s :", sConfig.ServiceName),
[]string{fmt.Sprintf("Select containerization option to use %s", sConfig.ServiceName)},
[]string{cConfig[0]}, cConfig)
quesKey := common.JoinQASubKeys(common.ConfigServicesKey, `"`+sConfig.ServiceName+`"`, common.ConfigContainerizationOptionServiceKeySegment)
containerizationOptions := qaengine.FetchMultiSelectAnswer(
quesKey,
fmt.Sprintf("Select the transformer to use for containerizing the '%s' service :", sConfig.ServiceName),
nil,
[]string{cConfig[0]},
cConfig,
)
secondaryArtifactsGenerated := false
for _, containerizationOption := range containerizationOptions {
containerizationArtifact := getContainerizationConfig(sConfig.ServiceName,
Expand Down
6 changes: 3 additions & 3 deletions transformer/compose/composeanalyser.go
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ func (t *ComposeAnalyser) getService(composeFilePath string, serviceName string,
Paths: map[transformertypes.PathType][]string{composeFilePathType: {composeFilePath}},
}
if imagepath, ok := imageMetadataPaths[serviceImage]; ok {
ct.Paths[imageInfoPathType] = common.MergeStringSlices(ct.Paths[imageInfoPathType], imagepath)
ct.Paths[imageInfoPathType] = common.AppendIfNotPresent(ct.Paths[imageInfoPathType], imagepath)
}
logrus.Debugf("Found a docker compose service : %s", serviceName)
if relContextPath != "" {
Expand All @@ -224,8 +224,8 @@ func (t *ComposeAnalyser) getService(composeFilePath string, serviceName string,
}
}
// Add reuse Dockerfile containerization option
ct.Paths[artifacts.DockerfilePathType] = common.MergeStringSlices(ct.Paths[artifacts.DockerfilePathType], dockerfilePath)
ct.Paths[artifacts.ServiceDirPathType] = common.MergeStringSlices(ct.Paths[artifacts.ServiceDirPathType], contextPath)
ct.Paths[artifacts.DockerfilePathType] = common.AppendIfNotPresent(ct.Paths[artifacts.DockerfilePathType], dockerfilePath)
ct.Paths[artifacts.ServiceDirPathType] = common.AppendIfNotPresent(ct.Paths[artifacts.ServiceDirPathType], contextPath)
}
return ct
}
Expand Down
2 changes: 1 addition & 1 deletion transformer/compose/v3.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func (c *v3Loader) convertToIR(filedir string, composeObject types.Config, servi
serviceContainer.TTY = composeServiceConfig.Tty

if len(composeServiceConfig.Ports) == 0 {
selectedPort := commonqa.GetPortForService(nil, serviceConfig.Name)
selectedPort := commonqa.GetPortForService(nil, `"`+serviceConfig.Name+`"`)
composeServiceConfig.Ports = []types.ServicePortConfig{{Protocol: "tcp", Target: uint32(selectedPort), Published: uint32(selectedPort)}}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ func (t *ContainerImagesPushScript) Transform(newArtifacts []transformertypes.Ar
if err != nil {
logrus.Errorf("Unable to read Image config : %s", err)
}
ipt.Images = common.MergeStringSlices(ipt.Images, images.ImageNames...)
ipt.Images = common.MergeSlices(ipt.Images, images.ImageNames)
}
if len(ipt.Images) == 0 {
return nil, nil, nil
Expand Down
Loading

0 comments on commit 607d042

Please sign in to comment.