Skip to content

Commit c8164a0

Browse files
feat: Allow overriding the default QA Mappings file (#1158)
feat: Allow overriding the default QA Mappings file chore: Moved ports questions to a separate category fix: Categories disabled in the QA mappings file were not being respected --------- Signed-off-by: Akash Nayak <[email protected]> Co-authored-by: Harikrishnan Balagopal <[email protected]>
1 parent 2697164 commit c8164a0

File tree

7 files changed

+192
-130
lines changed

7 files changed

+192
-130
lines changed

assets/built-in/qa/qamappings.yaml

+80-72
Original file line numberDiff line numberDiff line change
@@ -1,72 +1,80 @@
1-
categories:
2-
- name: imageregistry
3-
# or use the flags --enable imageregistry/--disable imageregistry
4-
enabled: true
5-
questions:
6-
- move2kube.target.imageregistry.url
7-
- move2kube.target.imageregistry.namespace
8-
- move2kube.target.imageregistry.*.logintype
9-
- move2kube.target.imageregistry.*.password
10-
- name: sshkeys
11-
enabled: true
12-
questions:
13-
- move2kube.repo.keys.*.key
14-
- move2kube.repo.keys.pub.domain.*.pubkey
15-
- move2kube.repo.keys.pub.load
16-
- move2kube.repo.keys.load
17-
- move2kube.repo.keys.paths
18-
- move2kube.repo.keys.priv.*.password
19-
- name: storage
20-
enabled: true
21-
questions:
22-
- move2kube.storage.type.*.options
23-
- name: sourceanalyzer
24-
enabled: true
25-
questions:
26-
- move2kube.services.*.enable
27-
- move2kube.services.*.statefulset
28-
- move2kube.services.*.containerizationoption
29-
- move2kube.services.*.childProjects.*.publishprofile
30-
- move2kube.services.*.apacheconfig
31-
- move2kube.services.*.pythonmainfile
32-
- move2kube.services.*.pythonstartingfile
33-
- move2kube.services.*.dockerfileType
34-
- move2kube.services.*.childModules.*.enable
35-
- move2kube.services.*.childProjects.*.enable
36-
- move2kube.services.*.childModules.*.springBootProfiles
37-
- move2kube.services.*.mavenProfiles
38-
- name: cluster
39-
enabled: true
40-
questions:
41-
- move2kube.target.*.clustertype
42-
- move2kube.minreplicas
43-
- name: network
44-
enabled: true
45-
questions:
46-
- move2kube.services.*.*.servicetype
47-
- move2kube.services.*.*.urlpath
48-
- move2kube.services.*.ports
49-
- move2kube.services.*.port
50-
- move2kube.target.*.ingress.ingressclassname
51-
- move2kube.target.*.ingress.host
52-
- move2kube.target.*.ingress.tls
53-
- name: git
54-
enabled: true
55-
questions:
56-
- move2kube.vcs.git.name
57-
- move2kube.vcs.git.username
58-
- move2kube.vcs.git.email
59-
- move2kube.vcs.git.pass
60-
- name: cicd
61-
enabled: true
62-
questions:
63-
- move2kube.target.cicd.tekton.gitreposshsecret
64-
- move2kube.target.cicd.tekton.gitrepobasicauthsecret
65-
- move2kube.target.cicd.tekton.registrypushsecret
66-
- move2kube.transformers.kubernetes.argocd.namespace
67-
- name: transformers
68-
enabled: true
69-
questions:
70-
- move2kube.transformerselector
71-
- move2kube.spawncontainers
72-
- move2kube.transformers.types
1+
apiVersion: move2kube.konveyor.io/v1alpha1
2+
kind: QAMappings
3+
metadata:
4+
name: DefaultQA-Mappings
5+
spec:
6+
categories:
7+
- name: imageregistry
8+
# or use the flags --enable imageregistry/--disable imageregistry
9+
enabled: true
10+
questions:
11+
- move2kube.target.imageregistry.url
12+
- move2kube.target.imageregistry.namespace
13+
- move2kube.target.imageregistry.*.logintype
14+
- move2kube.target.imageregistry.*.password
15+
- name: sshkeys
16+
enabled: true
17+
questions:
18+
- move2kube.repo.keys.*.key
19+
- move2kube.repo.keys.pub.domain.*.pubkey
20+
- move2kube.repo.keys.pub.load
21+
- move2kube.repo.keys.load
22+
- move2kube.repo.keys.paths
23+
- move2kube.repo.keys.priv.*.password
24+
- name: storage
25+
enabled: true
26+
questions:
27+
- move2kube.storage.type.*.options
28+
- name: sourceanalyzer
29+
enabled: true
30+
questions:
31+
- move2kube.services.*.enable
32+
- move2kube.services.*.statefulset
33+
- move2kube.services.*.containerizationoption
34+
- move2kube.services.*.childProjects.*.publishprofile
35+
- move2kube.services.*.apacheconfig
36+
- move2kube.services.*.pythonmainfile
37+
- move2kube.services.*.pythonstartingfile
38+
- move2kube.services.*.dockerfileType
39+
- move2kube.services.*.childModules.*.enable
40+
- move2kube.services.*.childProjects.*.enable
41+
- move2kube.services.*.childModules.*.springBootProfiles
42+
- move2kube.services.*.mavenProfiles
43+
- name: cluster
44+
enabled: true
45+
questions:
46+
- move2kube.target.*.clustertype
47+
- move2kube.minreplicas
48+
- name: network
49+
enabled: true
50+
questions:
51+
- move2kube.services.*.*.servicetype
52+
- move2kube.services.*.*.urlpath
53+
- move2kube.target.*.ingress.ingressclassname
54+
- move2kube.target.*.ingress.host
55+
- move2kube.target.*.ingress.tls
56+
- name: ports
57+
enabled: true
58+
questions:
59+
- move2kube.services.*.ports
60+
- move2kube.services.*.port
61+
- name: git
62+
enabled: true
63+
questions:
64+
- move2kube.vcs.git.name
65+
- move2kube.vcs.git.username
66+
- move2kube.vcs.git.email
67+
- move2kube.vcs.git.pass
68+
- name: cicd
69+
enabled: true
70+
questions:
71+
- move2kube.target.cicd.tekton.gitreposshsecret
72+
- move2kube.target.cicd.tekton.gitrepobasicauthsecret
73+
- move2kube.target.cicd.tekton.registrypushsecret
74+
- move2kube.transformers.kubernetes.argocd.namespace
75+
- name: transformers
76+
enabled: true
77+
questions:
78+
- move2kube.transformerselector
79+
- move2kube.spawncontainers
80+
- move2kube.transformers.types

cmd/flags.go

+4
Original file line numberDiff line numberDiff line change
@@ -77,4 +77,8 @@ type qaflags struct {
7777
preSets []string
7878
// persistPasswords sets whether to persist the password or not
7979
persistPasswords bool
80+
// qaEnabledCategories contains list of categories to be enabled
81+
qaEnabledCategories []string
82+
// qaDisabledCategories contains list of categories to be disabled
83+
qaDisabledCategories []string
8084
}

cmd/transform.go

+11-46
Original file line numberDiff line numberDiff line change
@@ -23,17 +23,14 @@ import (
2323
"path/filepath"
2424
"runtime/pprof"
2525

26-
"github.com/konveyor/move2kube/assets"
2726
"github.com/konveyor/move2kube/common"
2827
"github.com/konveyor/move2kube/common/download"
2928
"github.com/konveyor/move2kube/common/vcs"
3029
"github.com/konveyor/move2kube/lib"
3130
"github.com/konveyor/move2kube/types/plan"
32-
"github.com/konveyor/move2kube/types/qaengine"
3331
"github.com/sirupsen/logrus"
3432
"github.com/spf13/cobra"
3533
"github.com/spf13/viper"
36-
"gopkg.in/yaml.v3"
3734
)
3835

3936
type transformFlags struct {
@@ -59,10 +56,8 @@ type transformFlags struct {
5956
// maxIterations is the maximum number of iterations to allow before aborting with an error
6057
maxIterations int
6158
// CustomizationsPaths contains the path to the customizations directory
62-
customizationsPath string
63-
transformerSelector string
64-
qaEnabledCategories []string
65-
qaDisabledCategories []string
59+
customizationsPath string
60+
transformerSelector string
6661
}
6762

6863
func transformHandler(cmd *cobra.Command, flags transformFlags) {
@@ -133,46 +128,9 @@ func transformHandler(cmd *cobra.Command, flags transformFlags) {
133128
}
134129
}
135130

136-
// qa-disable and qa=enable are mutually exclusive
137-
if len(flags.qaEnabledCategories) > 0 && len(flags.qaDisabledCategories) > 0 {
138-
logrus.Fatalf("--qa-enable and --qa-disable cannot be used together.\n")
139-
}
140-
141-
// Read the QA categories from the QA mapping file
142-
var qaMapping qaengine.QAMapping
143-
qaMappingFilepath := filepath.Join("built-in/qa", "qamappings.yaml")
144-
file, err := assets.AssetsDir.ReadFile(qaMappingFilepath)
145-
if err != nil {
146-
logrus.Fatalf("failed to read qa-mapping file at %s. Error: %q\n", qaMappingFilepath, err)
147-
}
148-
149-
if err := yaml.Unmarshal(file, &qaMapping); err != nil {
150-
logrus.Fatalf("failed to decode qa-mapping file. Error: %q\n", err)
151-
}
152-
153-
for _, mapping := range qaMapping.Categories {
154-
common.QACategoryMap[mapping.Name] = mapping.Questions
155-
}
156-
common.QACategoryMap["default"] = []string{}
157-
common.QACategoryMap["external"] = []string{}
158-
159131
// Global settings
160132
common.IgnoreEnvironment = flags.ignoreEnv
161133
common.DisableLocalExecution = flags.disableLocalExecution
162-
// if --qa-enable is passed, all categories are disabled by default. Otherwise, only categories passed to --qa-disable
163-
// are disabled
164-
if len(flags.qaEnabledCategories) > 0 {
165-
for k := range common.QACategoryMap {
166-
if !common.IsStringPresent(flags.qaEnabledCategories, k) {
167-
common.DisabledCategories = append(common.DisabledCategories, k)
168-
}
169-
}
170-
} else {
171-
for _, cat := range flags.qaDisabledCategories {
172-
common.DisabledCategories = append(common.DisabledCategories, cat)
173-
}
174-
}
175-
176134
// Parameter cleaning and curate plan
177135
transformationPlan := plan.Plan{}
178136
preExistingPlan := false
@@ -182,7 +140,7 @@ func transformHandler(cmd *cobra.Command, flags transformFlags) {
182140
_, err = os.Stat(flags.planfile)
183141
}
184142
if err != nil {
185-
logrus.Debugf("No plan file found.")
143+
logrus.Infof("No plan file found.")
186144
if cmd.Flags().Changed(planFlag) {
187145
logrus.Fatalf("Error while accessing plan file at path %s Error: %q", flags.planfile, err)
188146
}
@@ -201,6 +159,11 @@ func transformHandler(cmd *cobra.Command, flags transformFlags) {
201159
logrus.Fatalf("Failed to create the output directory at path %s Error: %q", flags.outpath, err)
202160
}
203161
}
162+
if flags.customizationsPath != "" {
163+
if err := lib.CheckAndCopyCustomizations(flags.customizationsPath); err != nil {
164+
logrus.Fatalf("Failed to check and copy the customizations. Error: %q", err)
165+
}
166+
}
204167
startQA(flags.qaflags)
205168
logrus.Debugf("Creating a new plan.")
206169
transformationPlan, err = lib.CreatePlan(ctx, flags.srcpath, flags.outpath, flags.customizationsPath, flags.transformerSelector, flags.name)
@@ -240,7 +203,9 @@ func transformHandler(cmd *cobra.Command, flags transformFlags) {
240203
if transformationPlan.Spec.SourceDir != "" {
241204
checkSourcePath(transformationPlan.Spec.SourceDir)
242205
}
243-
lib.CheckAndCopyCustomizations(transformationPlan.Spec.CustomizationsDir)
206+
if err := lib.CheckAndCopyCustomizations(transformationPlan.Spec.CustomizationsDir); err != nil {
207+
logrus.Fatalf("Failed to check and copy the customizations. Error: %q", err)
208+
}
244209
if !isRemoteOutPath {
245210
flags.outpath = filepath.Join(flags.outpath, transformationPlan.Name)
246211
checkOutputPath(flags.outpath, flags.overwrite)

cmd/utils.go

+79
Original file line numberDiff line numberDiff line change
@@ -18,16 +18,20 @@ package cmd
1818

1919
import (
2020
"encoding/json"
21+
"fmt"
2122
"net/http"
2223
"os"
2324
"path/filepath"
2425
"strings"
2526

2627
"github.com/gorilla/mux"
28+
"github.com/konveyor/move2kube/assets"
2729
"github.com/konveyor/move2kube/common"
2830
"github.com/konveyor/move2kube/qaengine"
31+
qaenginetypes "github.com/konveyor/move2kube/types/qaengine"
2932
"github.com/sirupsen/logrus"
3033
"github.com/spf13/cast"
34+
"gopkg.in/yaml.v3"
3135
)
3236

3337
// checkSourcePath checks if the source path is an existing directory.
@@ -82,7 +86,82 @@ Exiting.`, outpath, overwriteFlag, outputFlag)
8286
logrus.Infof("Output directory '%s' exists. The contents might get overwritten.", outpath)
8387
}
8488

89+
func getCustomMappingFilePath() (qaenginetypes.QAMappings, error) {
90+
// Read the QA categories from the QA mapping file
91+
var qaMapping qaenginetypes.QAMappings
92+
customizationsDir := filepath.Join(common.AssetsPath, "custom")
93+
_, err := os.Stat(customizationsDir)
94+
if err == nil {
95+
yamlPaths, err := common.GetFilesByExt(customizationsDir, []string{".yml", ".yaml"})
96+
if err != nil {
97+
return qaMapping, fmt.Errorf("failed to look for yaml files in the directory '%s' . Error: %w", customizationsDir, err)
98+
}
99+
for _, yamlPath := range yamlPaths {
100+
if err := common.ReadMove2KubeYaml(yamlPath, &qaMapping); err != nil {
101+
logrus.Debugf("failed to read the mappings file metadata from the yaml file at path '%s' . Error: %q", yamlPath, err)
102+
continue
103+
}
104+
if qaMapping.Kind != qaenginetypes.QAMappingsKind {
105+
logrus.Debugf(
106+
"the file at path '%s' is not a valid cluster metadata. Expected kind: '%s' Actual kind: '%s'",
107+
yamlPath, qaenginetypes.QAMappingsKind, qaMapping.Kind,
108+
)
109+
continue
110+
}
111+
logrus.Infof("Found custom QA mappings file '%s' at path '%s'", qaMapping.ObjectMeta.Name, yamlPath)
112+
return qaMapping, nil
113+
}
114+
}
115+
logrus.Infof("Using the default QA mappings file")
116+
qaMappingFilepath := filepath.Join("built-in/qa", "qamappings.yaml")
117+
file, err := assets.AssetsDir.ReadFile(qaMappingFilepath)
118+
if err != nil {
119+
return qaMapping, fmt.Errorf("failed to read the mappings file metadata from the yaml file at path '%s' . Error: %w", qaMappingFilepath, err)
120+
}
121+
if err := yaml.Unmarshal(file, &qaMapping); err != nil {
122+
return qaMapping, fmt.Errorf("failed to decode qa-mapping file. Error: %w", err)
123+
}
124+
return qaMapping, nil
125+
}
126+
127+
func initDisabledCategories(flags qaflags) {
128+
// qa-disable and qa=enable are mutually exclusive
129+
if len(flags.qaEnabledCategories) > 0 && len(flags.qaDisabledCategories) > 0 {
130+
logrus.Fatalf("--qa-enable and --qa-disable cannot be used together.\n")
131+
}
132+
// Read the QA categories from the QA mapping file
133+
qaMapping, err := getCustomMappingFilePath()
134+
if err != nil {
135+
logrus.Fatalf("failed to read the QAMappings file. Error: %q", err)
136+
}
137+
for _, category := range qaMapping.Spec.Categories {
138+
common.QACategoryMap[category.Name] = category.Questions
139+
}
140+
common.QACategoryMap["default"] = []string{}
141+
common.QACategoryMap["external"] = []string{}
142+
// if --qa-enable is passed, all categories are disabled by default. Otherwise, only categories passed to --qa-disable
143+
// are disabled
144+
for _, category := range qaMapping.Spec.Categories {
145+
if !category.Enabled {
146+
common.DisabledCategories = append(common.DisabledCategories, category.Name)
147+
}
148+
}
149+
if len(flags.qaEnabledCategories) > 0 {
150+
for k := range common.QACategoryMap {
151+
if !common.IsStringPresent(flags.qaEnabledCategories, k) {
152+
common.DisabledCategories = append(common.DisabledCategories, k)
153+
}
154+
}
155+
} else {
156+
common.DisabledCategories = append(common.DisabledCategories, flags.qaDisabledCategories...)
157+
}
158+
if len(common.DisabledCategories) > 0 {
159+
logrus.Infof("Disabling the questions in the following categories: %v", common.DisabledCategories)
160+
}
161+
}
162+
85163
func startQA(flags qaflags) {
164+
initDisabledCategories(flags)
86165
qaengine.StartEngine(flags.qaskip, flags.qaport, flags.qadisablecli)
87166
if flags.configOut == "" {
88167
qaengine.SetupConfigFile("", flags.setconfigs, flags.configs, flags.preSets, flags.persistPasswords)

lib/planner.go

-5
Original file line numberDiff line numberDiff line change
@@ -54,11 +54,6 @@ func CreatePlan(ctx context.Context, inputPath, outputPath string, customization
5454
if remoteOutputFSPath != "" {
5555
outputFSPath = remoteOutputFSPath
5656
}
57-
if customizationsPath != "" {
58-
if err := CheckAndCopyCustomizations(customizationsPath); err != nil {
59-
return plan, fmt.Errorf("failed to check and copy the customizations. Error: %w", err)
60-
}
61-
}
6257
transformerSelectorObj, err := metav1.ParseToLabelSelector(transformerSelector)
6358
if err != nil {
6459
return plan, fmt.Errorf("failed to parse the string '%s' as a transformer selector. Error: %w", transformerSelector, err)

lib/utils.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ func CheckAndCopyCustomizations(customizationsPath string) error {
6767
// check if the customization path has files other than YAMLs
6868
yamls, err := common.GetYamlsWithTypeMeta(customizationsFSPath, TransformerTypeMeta)
6969
if err == nil && len(yamls) == 0 {
70-
logrus.Warnf("no manifests for external transformers found in %s, the transformers won't be loaded.", customizationsFSPath)
70+
logrus.Infof("No manifests for external transformers found in the customizations directory '%s'.", customizationsFSPath)
7171
}
7272
if err = CopyCustomizationsAssetsData(customizationsFSPath); err != nil {
7373
return fmt.Errorf("failed to copy the customizations data from the directory '%s' . Error: %w", customizationsFSPath, err)

0 commit comments

Comments
 (0)