From 23888910ddcf6386f24dc80f0e7b766207994d31 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Wed, 21 Feb 2024 11:15:38 -0500 Subject: [PATCH 1/6] :bug: Treat tags that are inherited from archetype assessments as assessment tags rather than archetype tags (#603) Prior to this commit, tags that applications inherited due to their archetypes' assessments were categorized as archetype tags rather than assessment tags. This corrects the categorization, and in addition fixes some bugs where tags could be inherited from archived assessments. Fixes https://issues.redhat.com/browse/MTA-1972 Signed-off-by: Sam Lucidi --- assessment/application.go | 52 ++++++++++++++++++++++----------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/assessment/application.go b/assessment/application.go index 2335222e9..42163cdec 100644 --- a/assessment/application.go +++ b/assessment/application.go @@ -56,8 +56,7 @@ func (r *ApplicationResolver) Archetypes() (archetypes []Archetype, err error) { return } -// ArchetypeTags returns the list of tags that the application should inherit from the archetypes it is a member of, -// including any tags that would be inherited due to answers given to the archetypes' assessments. +// ArchetypeTags returns the list of tags that the application should inherit from the archetypes it is a member of. func (r *ApplicationResolver) ArchetypeTags() (tags []model.Tag, err error) { archetypes, err := r.Archetypes() if err != nil { @@ -72,19 +71,6 @@ func (r *ApplicationResolver) ArchetypeTags() (tags []model.Tag, err error) { tags = append(tags, t) } } - // if an application has any of its own assessments then it should not - // inherit assessment tags from any of its archetypes. - if len(r.application.Assessments) == 0 { - for _, assessment := range a.Assessments { - aTags := r.tagResolver.Assessment(assessment) - for _, t := range aTags { - if _, found := seenTags[t.ID]; !found { - seenTags[t.ID] = true - tags = append(tags, t) - } - } - } - } } return } @@ -100,15 +86,37 @@ func (r *ApplicationResolver) RequiredAssessments() (required []Assessment) { } // AssessmentTags returns the list of tags that the application should inherit from the answers given -// to its assessments. +// to its assessments or those of its archetypes. Archetype assessments are only inherited if the application +// does not have any answers to required questionnaires. func (r *ApplicationResolver) AssessmentTags() (tags []model.Tag) { seenTags := make(map[uint]bool) - for _, assessment := range r.RequiredAssessments() { - aTags := r.tagResolver.Assessment(assessment) - for _, t := range aTags { - if _, found := seenTags[t.ID]; !found { - seenTags[t.ID] = true - tags = append(tags, t) + if len(r.RequiredAssessments()) > 0 { + for _, assessment := range r.RequiredAssessments() { + aTags := r.tagResolver.Assessment(assessment) + for _, t := range aTags { + if _, found := seenTags[t.ID]; !found { + seenTags[t.ID] = true + tags = append(tags, t) + } + } + } + return + } + + archetypes, err := r.Archetypes() + if err != nil { + return + } + for _, a := range archetypes { + for _, assessment := range a.Assessments { + if r.questionnaireResolver.Required(assessment.QuestionnaireID) { + aTags := r.tagResolver.Assessment(assessment) + for _, t := range aTags { + if _, found := seenTags[t.ID]; !found { + seenTags[t.ID] = true + tags = append(tags, t) + } + } } } } From da36be0cac7931e757ae3f1351ba572a1d6e153a Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 27 Feb 2024 08:13:10 -0500 Subject: [PATCH 2/6] :bug: [MTA-1726] Migration Waves: require start and end date, require end > start (#604) Fixes https://issues.redhat.com/browse/MTA-1726 Signed-off-by: Sam Lucidi --- api/migrationwave.go | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/api/migrationwave.go b/api/migrationwave.go index 24835e5e9..8651a369e 100644 --- a/api/migrationwave.go +++ b/api/migrationwave.go @@ -182,8 +182,8 @@ func (h MigrationWaveHandler) Delete(ctx *gin.Context) { type MigrationWave struct { Resource `yaml:",inline"` Name string `json:"name"` - StartDate time.Time `json:"startDate" yaml:"startDate"` - EndDate time.Time `json:"endDate" yaml:"endDate"` + StartDate time.Time `json:"startDate" yaml:"startDate" binding:"required"` + EndDate time.Time `json:"endDate" yaml:"endDate" binding:"required,gtfield=StartDate"` Applications []Ref `json:"applications"` Stakeholders []Ref `json:"stakeholders"` StakeholderGroups []Ref `json:"stakeholderGroups" yaml:"stakeholderGroups"` From 789ce580d9bb0acbf0eff4525a9ea61a323a1884 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Wed, 28 Feb 2024 08:12:01 -0600 Subject: [PATCH 3/6] :bug: Return empty list when latest analysis does not exist. (#602) Return empty list of issues when no latest analysis. But still 404 when application not found. https://issues.redhat.com/browse/MTA-2047 Signed-off-by: Jeff Ortel --- api/analysis.go | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/api/analysis.go b/api/analysis.go index b8b5a12be..8350fe3a0 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -917,13 +917,25 @@ func (h AnalysisHandler) AppIssueReports(ctx *gin.Context) { model.Issue Files int } - // Latest id := h.pk(ctx) + err := h.DB(ctx).First(&model.Application{}, id).Error + if err != nil { + _ = ctx.Error(err) + return + } + // Latest analysis := &model.Analysis{} db := h.DB(ctx).Where("ApplicationID", id) - result := db.Last(analysis) - if result.Error != nil { - _ = ctx.Error(result.Error) + err = db.Last(analysis).Error + if err != nil { + if errors.Is(err, gorm.ErrRecordNotFound) { + h.Respond( + ctx, + http.StatusOK, + resources) + } else { + _ = ctx.Error(err) + } return } // Filter From 35af44a6794fb8c02a22d637e15c27b86de2e0ec Mon Sep 17 00:00:00 2001 From: David Zager Date: Tue, 5 Mar 2024 11:16:20 -0500 Subject: [PATCH 4/6] :seedling: add cherry-pick workflow for pr-closed event (#612) Signed-off-by: David Zager --- .github/workflows/pr-closed.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/pr-closed.yaml diff --git a/.github/workflows/pr-closed.yaml b/.github/workflows/pr-closed.yaml new file mode 100644 index 000000000..41afa19e6 --- /dev/null +++ b/.github/workflows/pr-closed.yaml @@ -0,0 +1,16 @@ +name: PR Closed + +on: + pull_request_target: + branches: + - main + types: + - closed + +jobs: + cherry_pick_job: + permissions: + pull-requests: write + contents: write + if: github.event.pull_request.merged == true + uses: konveyor/release-tools/.github/workflows/cherry-pick.yml@main From db831380a5f30be290a4c87cff32d32a30db452c Mon Sep 17 00:00:00 2001 From: Shawn Hurley Date: Fri, 15 Mar 2024 15:48:39 -0400 Subject: [PATCH 5/6] :ghost: update dependcies with CVE's (#614) Signed-off-by: Shawn Hurley --- go.mod | 24 +++++++++++------------ go.sum | 62 ++++++++++++++++++++++++---------------------------------- 2 files changed, 37 insertions(+), 49 deletions(-) diff --git a/go.mod b/go.mod index ea271b33d..78e352050 100644 --- a/go.mod +++ b/go.mod @@ -5,9 +5,9 @@ go 1.20 require ( github.com/Nerzal/gocloak/v10 v10.0.1 github.com/andygrunwald/go-jira v1.16.0 - github.com/gin-gonic/gin v1.9.0 + github.com/gin-gonic/gin v1.9.1 github.com/go-logr/logr v1.2.4 - github.com/go-playground/validator/v10 v10.13.0 + github.com/go-playground/validator/v10 v10.14.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.3.0 github.com/jortel/go-utils v0.1.2 @@ -18,7 +18,6 @@ require ( github.com/swaggo/swag v1.16.1 golang.org/x/sys v0.13.0 gopkg.in/yaml.v2 v2.4.0 - gorm.io/datatypes v1.2.0 gorm.io/driver/sqlite v1.5.2 gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 k8s.io/api v0.25.0 @@ -32,7 +31,7 @@ require ( require ( github.com/KyleBanks/depth v1.2.1 // indirect github.com/beorn7/perks v1.0.1 // indirect - github.com/bytedance/sonic v1.8.0 // indirect + github.com/bytedance/sonic v1.9.1 // indirect github.com/cespare/xxhash/v2 v2.2.0 // indirect github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect github.com/davecgh/go-spew v1.1.1 // indirect @@ -40,6 +39,7 @@ require ( github.com/evanphx/json-patch/v5 v5.6.0 // indirect github.com/fatih/structs v1.1.0 // indirect github.com/fsnotify/fsnotify v1.6.0 // indirect + github.com/gabriel-vasile/mimetype v1.4.2 // indirect github.com/gin-contrib/sse v0.1.0 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonreference v0.20.1 // indirect @@ -48,8 +48,7 @@ require ( github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect github.com/go-resty/resty/v2 v2.6.0 // indirect - github.com/go-sql-driver/mysql v1.7.0 // indirect - github.com/goccy/go-json v0.10.0 // indirect + github.com/goccy/go-json v0.10.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect github.com/golang/protobuf v1.5.3 // indirect @@ -62,16 +61,16 @@ require ( github.com/jinzhu/now v1.1.5 // indirect github.com/josharian/intern v1.0.0 // indirect github.com/json-iterator/go v1.1.12 // indirect - github.com/klauspost/cpuid/v2 v2.0.9 // indirect + github.com/klauspost/cpuid/v2 v2.2.4 // indirect github.com/leodido/go-urn v1.2.4 // indirect github.com/mailru/easyjson v0.7.7 // indirect - github.com/mattn/go-isatty v0.0.17 // indirect + github.com/mattn/go-isatty v0.0.19 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/opentracing/opentracing-go v1.2.0 // indirect - github.com/pelletier/go-toml/v2 v2.0.6 // indirect + github.com/pelletier/go-toml/v2 v2.0.8 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/prometheus/client_model v0.3.0 // indirect github.com/prometheus/common v0.42.0 // indirect @@ -82,9 +81,9 @@ require ( github.com/spf13/pflag v1.0.5 // indirect github.com/trivago/tgo v1.0.7 // indirect github.com/twitchyliquid64/golang-asm v0.15.1 // indirect - github.com/ugorji/go/codec v1.2.9 // indirect + github.com/ugorji/go/codec v1.2.11 // indirect go.uber.org/zap v1.24.0 // indirect - golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect + golang.org/x/arch v0.3.0 // indirect golang.org/x/crypto v0.14.0 // indirect golang.org/x/net v0.17.0 // indirect golang.org/x/oauth2 v0.5.0 // indirect @@ -94,10 +93,9 @@ require ( golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect - google.golang.org/protobuf v1.30.0 // indirect + google.golang.org/protobuf v1.33.0 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect - gorm.io/driver/mysql v1.4.7 // indirect k8s.io/component-base v0.25.0 // indirect k8s.io/klog/v2 v2.70.1 // indirect k8s.io/kube-openapi v0.0.0-20220803162953-67bda5d908f1 // indirect diff --git a/go.sum b/go.sum index 1369f5f6f..444b42cfe 100644 --- a/go.sum +++ b/go.sum @@ -11,8 +11,8 @@ github.com/andygrunwald/go-jira v1.16.0/go.mod h1:UQH4IBVxIYWbgagc0LF/k9FRs9xjIi github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM= -github.com/bytedance/sonic v1.8.0 h1:ea0Xadu+sHlu7x5O3gKhRpQ1IKiMrSiHttPF0ybECuA= -github.com/bytedance/sonic v1.8.0/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= +github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s= +github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -37,10 +37,12 @@ github.com/fatih/structs v1.1.0 h1:Q7juDM0QtcnhCpeyLGQKyg4TOIghuNXrkL32pHAUMxo= github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= +github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= +github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= -github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8= -github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k= +github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg= +github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU= github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas= github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ= @@ -64,23 +66,19 @@ github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/o github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY= github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY= github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY= -github.com/go-playground/validator/v10 v10.13.0 h1:cFRQdfaSMCOSfGCCLB20MHvuoHb/s5G8L5pu2ppK5AQ= -github.com/go-playground/validator/v10 v10.13.0/go.mod h1:dwu7+CG8/CtBiJFZDz4e+5Upb6OLw04gtBYw0mcG/z4= +github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js= +github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU= github.com/go-resty/resty/v2 v2.6.0 h1:joIR5PNLM2EFqqESUjCMGXrWmXNHEU9CEiK813oKYS4= github.com/go-resty/resty/v2 v2.6.0/go.mod h1:PwvJS6hvaPkjtjNg9ph+VrSD92bi5Zq73w/BIH7cC3Q= -github.com/go-sql-driver/mysql v1.7.0 h1:ueSltNNllEqE3qcWBTD0iQd3IpL/6U+mJxLkazJ7YPc= -github.com/go-sql-driver/mysql v1.7.0/go.mod h1:OXbVy3sEdcQ2Doequ6Z5BW6fXNQTmx+9S1MCJN5yJMI= github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 h1:tfuBGBXKqDEevZMzYi5KSi8KkcZtzBcTgAUUtapy0OI= -github.com/goccy/go-json v0.10.0 h1:mXKd9Qw4NuzShiRlOXKews24ufknHO7gx30lsDyokKA= -github.com/goccy/go-json v0.10.0/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= +github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU= +github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-jwt/jwt/v4 v4.1.0/go.mod h1:/xlHOz8bRuivTWchD4jCa+NbatV+wEUSzwAxVc6locg= github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= -github.com/golang-sql/civil v0.0.0-20220223132316-b832511892a9 h1:au07oEsX2xN0ktxqI+Sida1w446QrXBRJ0nee3SNZlA= -github.com/golang-sql/sqlexp v0.1.0 h1:ZCD6MBpcuOVfGVqsEmY5/4FtYiKz6tSyUv9LPEDei6A= github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da h1:oI5xCqsCo564l8iNU+DwB5epxmsaqB+rhGL0m5jtYqE= github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc= @@ -120,13 +118,9 @@ github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/imdario/mergo v0.3.12 h1:b6R2BslTbIEToALKP7LxUvijTsNI9TAe80pLWN2g/HU= github.com/imdario/mergo v0.3.12/go.mod h1:jmQim1M+e3UYxmgPu/WyfjB3N3VflVyUjjjwH0dnCYA= -github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= -github.com/jackc/pgservicefile v0.0.0-20221227161230-091c0ba34f0a h1:bbPeKD0xmW/Y25WS6cokEszi5g+S0QxI/d45PkRi7Nk= -github.com/jackc/pgx/v5 v5.3.0 h1:/NQi8KHMpKWHInxXesC8yD4DhkXPrVhmnwYkjp9AmBA= github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI= github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E= github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc= -github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ= github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8= github.com/jortel/go-utils v0.1.2 h1:R0TcGRCcwoL793CymcKC5AF9idWXT2cR6eQ2xpBUsoI= @@ -137,8 +131,9 @@ github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnr github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= -github.com/klauspost/cpuid/v2 v2.0.9 h1:lgaqFMSdTdQYdZ04uHyN2d/eKdOMyi2YLSvlQIBFYa4= github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg= +github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk= +github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY= github.com/konveyor/tackle2-seed v0.0.0-20231025181853-8ce94f70f744 h1:/FkxudKacnx6eHscDiSFT5iLgJCswGFpMWmflOM/85U= github.com/konveyor/tackle2-seed v0.0.0-20231025181853-8ce94f70f744/go.mod h1:wt9Zb1l1PAd+XxW03KTp8z4dth3DkCDsRrcdZSWTyjA= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= @@ -156,13 +151,12 @@ github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= -github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng= -github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= +github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= +github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-sqlite3 v1.14.17 h1:mCRHCLDUBXgpKAqIKsaAaAsrAlbkeomtRFKXh2L6YIM= github.com/mattn/go-sqlite3 v1.14.17/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg= github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= -github.com/microsoft/go-mssqldb v0.17.0 h1:Fto83dMZPnYv1Zwx5vHHxpNraeEaUlQ/hhHLgZiaenE= github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= @@ -178,8 +172,8 @@ github.com/onsi/gomega v1.27.6 h1:ENqfyGeS5AX/rlXDd/ETokDz93u0YufY1Pgxuy/PvWE= github.com/onsi/gomega v1.27.6/go.mod h1:PIQNjfQwkP3aQAH7lf7j87O/5FiNr+ZR8+ipb+qQlhg= github.com/opentracing/opentracing-go v1.2.0 h1:uEJPy/1a5RIPAJ0Ov+OIO8OxWu77jEv+1B0VhjKrZUs= github.com/opentracing/opentracing-go v1.2.0/go.mod h1:GxEUsuufX4nBwe+T+Wl9TAgYrxe9dPLANfrWvHYVTgc= -github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU= -github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek= +github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ= +github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= @@ -214,16 +208,17 @@ github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/ github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= -github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= +github.com/stretchr/testify v1.8.3 h1:RP3t2pwF7cMEbC1dqtB6poj3niw/9gnV4Cjg5oW5gtY= +github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/swaggo/swag v1.16.1 h1:fTNRhKstPKxcnoKsytm4sahr8FaYzUcT7i1/3nd/fBg= github.com/swaggo/swag v1.16.1/go.mod h1:9/LMvHycG3NFHfR6LwvikHv5iFvmPADQ359cKikGxto= github.com/trivago/tgo v1.0.7 h1:uaWH/XIy9aWYWpjm2CU3RpcqZXmX2ysQ9/Go+d9gyrM= github.com/trivago/tgo v1.0.7/go.mod h1:w4dpD+3tzNIIiIfkWWa85w5/B77tlvdZckQ+6PkFnhc= github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI= github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08= -github.com/ugorji/go/codec v1.2.9 h1:rmenucSohSTiyL09Y+l2OCk+FrMxGMzho2+tjr5ticU= -github.com/ugorji/go/codec v1.2.9/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= +github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= +github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw= @@ -231,8 +226,9 @@ go.uber.org/goleak v1.1.12 h1:gZAh5/EyT/HQwlpkCy6wTpqfH9H8Lz8zbm3dZh+OyzA= go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= -golang.org/x/arch v0.0.0-20210923205945-b76863e36670 h1:18EFjUmQOcUvxNYSkA6jO9VAiXCnxFY6NyDX0bHDmkU= golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= +golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k= +golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= @@ -280,9 +276,10 @@ golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7w golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.13.0 h1:Af8nKPmuFypiUBjVoU9V20FiaFXOcuZI21p0ycVYYGE= golang.org/x/sys v0.13.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= @@ -335,8 +332,8 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.24.0/go.mod h1:r/3tXBNzIEhYS9I1OUVjXDlt8tc493IdKGjtUeSXeh4= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= -google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= +google.golang.org/protobuf v1.33.0 h1:uNO2rsAINq/JlFpSdYEKIZ0uKD/R9cpdv0T+yoGwGmI= +google.golang.org/protobuf v1.33.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= @@ -356,15 +353,8 @@ gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= -gorm.io/datatypes v1.2.0 h1:5YT+eokWdIxhJgWHdrb2zYUimyk0+TaFth+7a0ybzco= -gorm.io/datatypes v1.2.0/go.mod h1:o1dh0ZvjIjhH/bngTpypG6lVRJ5chTBxE09FH/71k04= -gorm.io/driver/mysql v1.4.7 h1:rY46lkCspzGHn7+IYsNpSfEv9tA+SU4SkkB+GFX125Y= -gorm.io/driver/mysql v1.4.7/go.mod h1:SxzItlnT1cb6e1e4ZRpgJN2VYtcqJgqnHxWr4wsP8oc= -gorm.io/driver/postgres v1.5.0 h1:u2FXTy14l45qc3UeCJ7QaAXZmZfDDv0YrthvmRq1l0U= gorm.io/driver/sqlite v1.5.2 h1:TpQ+/dqCY4uCigCFyrfnrJnrW9zjpelWVoEVNy5qJkc= gorm.io/driver/sqlite v1.5.2/go.mod h1:qxAuCol+2r6PannQDpOP1FP6ag3mKi4esLnB/jHed+4= -gorm.io/driver/sqlserver v1.4.1 h1:t4r4r6Jam5E6ejqP7N82qAJIJAht27EGT41HyPfXRw0= -gorm.io/gorm v1.23.8/go.mod h1:l2lP/RyAtc1ynaTjFksBde/O8v9oOGIApu2/xRitmZk= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55 h1:sC1Xj4TYrLqg1n3AN10w871An7wJM0gzgcm8jkIkECQ= gorm.io/gorm v1.25.2-0.20230530020048-26663ab9bf55/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k= honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4= From 60f7a95df554be48a525b9e492d1ef28d559c613 Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Wed, 20 Mar 2024 16:20:19 +0100 Subject: [PATCH 6/6] :seedling: Update export/import tool for Konveyor 0.3 (#615) Updating "tackle" python CLI to be able export&import Konveyor 0.3 Hub API with pathfinder replacement APIs. Doesn't mean to be full Hub export, but targeting demo lab data import use-case. --------- Signed-off-by: Marek Aufart --- hack/tool/tackle | 260 ++++++----------------------------------------- 1 file changed, 30 insertions(+), 230 deletions(-) diff --git a/hack/tool/tackle b/hack/tool/tackle index ae8244061..6d8919333 100755 --- a/hack/tool/tackle +++ b/hack/tool/tackle @@ -215,8 +215,6 @@ def apiFilePost(url, token, filePath, ignoreErrors=False): return resp.text def tackle2path(obj): - if 'assessment' in obj: - return "/hub/pathfinder/%s" % obj.replace("--", "/") # Nested path decoding (e.g. assessments/assessment-risk) return "/hub/%s" % obj def loadDump(path, fallback_value = []): @@ -244,7 +242,7 @@ def cmdWanted(args, action): class TackleTool: # TYPES order matters for import/upload to Tackle2 - TYPES = ['tagcategories', 'tags', 'jobfunctions', 'stakeholdergroups', 'stakeholders', 'businessservices', 'identities', 'applications', 'proxies', 'dependencies', 'assessments', 'reviews'] + TYPES = ['tagcategories', 'tags', 'jobfunctions', 'stakeholdergroups', 'stakeholders', 'businessservices', 'identities', 'applications', 'proxies', 'dependencies', 'questionnaires', 'archetypes', 'assessments', 'reviews'] NOT_IMPORTED_TYPES = ['taskgroups', 'tasks'] TACKLE2_SEED_TYPES = ['tagcategories', 'tags', 'jobfunctions'] @@ -303,163 +301,24 @@ class TackleTool: # Gather Tackle 2 API objects def dumpTackle2(self): - ### TAG TYPES & TAGS ### - collection = apiJSON(self.tackle2Url + "/hub/tagcategories", self.tackle2Token) - for tt2 in collection: - # Temp holder for tags - tags = [] - # Prepare TagCategories's Tags - for tag2 in tt2['tags']: - tag = Tackle2Object() - tag.id = tag2['id'] - tag.name = tag2['name'] - # TagCategories is injected from TagCategory processing few lines below - self.add('tags', tag) - tags.append(tag) - # Prepare TagCategory - tt = Tackle2Object() - tt.id = tt2['id'] - tt.name = tt2['name'] - tt.colour = tt2['colour'] - tt.rank = tt2['rank'] - tt.username = tt2['username'] - for tag in tags: - tag.category = copy.deepcopy(tt) - tt.tags = tags - self.add('tagcategories', tt) - - ### APPLICATION ### - collection = apiJSON(self.tackle2Url + "/hub/applications", self.tackle2Token) - for app2 in collection: - # Temp holder for tags - tags = [] - # Prepare Tags - debugPrint(app2) - if app2['tags']: - for tag2 in app2['tags']: - appTag = self.findById('tags', int(tag2['id'])) - # Use imported Tag, creating a new one to cut association to Tag type - tag = Tackle2Object() - tag.id = appTag.id - tag.name = appTag.name - tags.append(tag) - # Prepare Application - app = Tackle2Object(app2) - app.name = app2['name'] - app.description = app2['description'] - app.tags = tags - app.businessService = app2['businessService'] - app.repository = app2['repository'] - app.binary = app2['binary'] - app.identities = app2['identities'] - self.add('temp-buckets', {'owner': "applications/%s" % app.id}) - self.add('applications', app) - - ### DEPENDENCIES ### - collection = apiJSON(self.tackle2Url + "/hub/dependencies", self.tackle2Token) - for dep2 in collection: - # Prepare Dependency - dep = Tackle2Object(dep2) - dep.to = {'id': dep2['to']['id'], 'name': dep2['to']['name']} - setattr(dep, 'from', {'id': dep2['from']['id'], 'name': dep2['from']['name']}) # Cannot use "from" as an attribute name directly - self.add('dependencies', dep) - - - ### APPLICATION REVIEW ### - collection = apiJSON(self.tackle2Url + "/hub/reviews", self.tackle2Token) - for rew2 in collection: - rev = Tackle2Object(rew2) - rev.proposedAction = rew2['proposedAction'] - rev.effortEstimate = rew2['effortEstimate'] - rev.businessCriticality = rew2['businessCriticality'] - rev.workPriority = rew2['workPriority'] - rev.comments = rew2['comments'] - rev.application = rew2['application'] - self.add('reviews', rev) - - ### ASSESSMENTS & RISKS (per Application) ### - for app in self.data['applications']: - collection = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments?applicationId=%d" % app.id, self.tackle2Token) - for assm2 in collection: - # Prepare Assessment - assm = Tackle2Object() - assm.id = assm2['id'] - assm.applicationId = assm2['applicationId'] - assm.status = assm2['status'] - # Prepare Assessment questions and answers - asqa2 = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments/%d" % assm.id, self.tackle2Token) - asqa = Tackle2Object() - asqa.id = asqa2['id'] - asqa.applicationId = asqa2['applicationId'] - asqa.status = asqa2['status'] - asqa.stakeholders = asqa2['stakeholders'] - asqa.stakeholderGroups = asqa2['stakeholderGroups'] - asqa.questionnaire = asqa2['questionnaire'] - self.add('assessments', asqa) - - ### STAKEHOLDER ### - collection = apiJSON(self.tackle2Url + "/hub/stakeholders", self.tackle2Token) - for sh2 in collection: - # Prepare StakeHolder - sh = Tackle2Object(sh2) - sh.name = sh2['name'] - sh.email = sh2['email'] - sh.groups = sh2['stakeholderGroups'] - sh.jobFunction = sh2['jobFunction'] - self.add('stakeholders', sh) - - ### STAKEHOLDER GROUPS ### - collection = apiJSON(self.tackle2Url + "/hub/stakeholdergroups", self.tackle2Token) - for shg2 in collection: - # Prepare StakeholderGroup - shg = Tackle2Object(shg2) - shg.name = shg2['name'] - shg.description = shg2['description'] - self.add('stakeholdergroups', shg) - - ### JOB FUNCTION ### - collection = apiJSON(self.tackle2Url + "/hub/jobfunctions", self.tackle2Token) - for jf2 in collection: - # Prepare JobFunction - jf = Tackle2Object(jf2) - jf.name = jf2['name'] - jf.stakeholders = jf2['stakeholders'] - self.add('jobfunctions', jf) - - ### BUSINESS SERVICE ### - collection = apiJSON(self.tackle2Url + "/hub/businessservices", self.tackle2Token) - for bs2 in collection: - bs = Tackle2Object(bs2) - bs.name = bs2['name'] - bs.description = bs2['description'] - bs.owner = bs2['owner'] # Stakeholder - self.add('businessservices', bs) - - ### IDENTITY ### - collection = apiJSON(self.tackle2Url + "/hub/identities?decrypted=1", self.tackle2Token) - for id2 in collection: - id = Tackle2Object(id2) - id.kind = id2['kind'] - id.name = id2['name'] - id.description = id2['description'] - id.user = id2['user'] - id.password = self.encrypt(id2['password']) - id.key = self.encrypt(id2['key']) - id.settings = self.encrypt(id2['settings']) - self.add('identities', id) - - ### PROXY ### - collection = apiJSON(self.tackle2Url + "/hub/proxies", self.tackle2Token) - for pr2 in collection: - pr = Tackle2Object(pr2) - pr.enabled = pr2['enabled'] - pr.kind = pr2['kind'] - pr.host = pr2['host'] - pr.port = pr2['port'] - pr.excluded = pr2['excluded'] - pr.identity = pr2['identity'] - self.add('proxies', pr) + ensureDataDir(self.dataDir) + for t in self.TYPES: + print("Exporting %s.." % t) + if t == "identities": + dictCollection = apiJSON(self.tackle2Url + "/hub/identities?decrypted=1", self.tackle2Token) + for dictObj in dictCollection: + dictObj['key'] = self.encrypt(dictObj['key']) + dictObj['password'] = self.encrypt(dictObj['password']) + dictObj['settings'] = self.encrypt(dictObj['settings']) + else: + dictCollection = apiJSON(self.tackle2Url + tackle2path(t), self.tackle2Token) + + # Remove legacy locked questionnaire from export to not cause conflict in import (should be 1st one) + if t == "questionnaires": + dictCollection = dictCollection[1:] + # Save data locally + saveJSON(os.path.join(self.dataDir, t), dictCollection) def dumpTackle2Buckets(self): bucketDir = "%s/buckets" % self.dataDir @@ -490,18 +349,8 @@ class TackleTool: return self.data[type].append(item) - def store(self): - ensureDataDir(self.dataDir) - for t in self.TYPES: - saveJSON(os.path.join(self.dataDir, t), self.data[t]) - def uploadTackle2(self, ignoreErrors=False): - # Hub objects for t in self.TYPES: - # Skip separated imported objects - if "assessment" in t: - continue # Pathfinder objects are imported separately - dictCollection = loadDump(os.path.join(self.dataDir, t + '.json')) print("Uploading %s.." % t) for dictObj in dictCollection: @@ -511,37 +360,18 @@ class TackleTool: dictObj['password'] = self.decrypt(dictObj['password']) dictObj['settings'] = self.decrypt(dictObj['settings']) + if "stakeholdergroups" in t: + dictObj['stakeholders'] = [] # empty stakeholders to not create it with parent stakeholdergroup, but in separate call + + path = tackle2path(t) + if "assessments" in t: + if 'application' in dictObj: + path = tackle2path("applications/%d/assessments" % dictObj['application']['id']) + elif 'archetype' in dictObj: + path = tackle2path("archetypes/%d/assessments" % dictObj['archetype']['id']) debugPrint(dictObj) - apiJSON(self.tackle2Url + tackle2path(t), self.tackle2Token, dictObj, method='POST', ignoreErrors=ignoreErrors) - - # Assessments / Pathfinder stuff import - dictCollection = loadDump(os.path.join(self.dataDir, 'assessments.json')) - print("Uploading assessments..") - for assmnt1 in dictCollection: - # Start the assessment - assmnt2 = apiJSON(self.tackle2Url + tackle2path('assessments'), self.tackle2Token, data={"applicationId": assmnt1['applicationId']}, method='POST', ignoreErrors=ignoreErrors) - # Populate the assessment questionnaire - assmnt2 = apiJSON(self.tackle2Url + tackle2path("assessments/%d" % assmnt2['id']), self.tackle2Token, ignoreErrors=ignoreErrors) - # Fill the assessment going through assessment to be imported and setting values to the newly created in Tackle2 (IDs changed, pairing with Order) - for category in assmnt1['questionnaire']['categories']: - debugPrint("Category %s" % category["order"]) - for question in category['questions']: - debugPrint("Question %s" % question["order"]) - for option in question['options']: - debugPrint("Option %s" % option) - if option['checked'] == True: - # Find corresponding option in newly created assessment and check it - destCategory = next(cat for cat in assmnt2['questionnaire']['categories'] if cat['order'] == category['order']) - destQuestion = next(que for que in destCategory['questions'] if que['order'] == question['order']) - destOption = next(opt for opt in destQuestion['options'] if opt['order'] == option['order']) - debugPrint("Checking Tackle2 assessment option: %s" % destOption) - destOption['checked'] = True - # Set remaining assessment attributes - assmnt2['status'] = assmnt1['status'] - assmnt2['stakeholders'] = assmnt1['stakeholders'] - assmnt2['stakeholderGroups'] = assmnt1['stakeholderGroups'] - # Push the updated assessment - apiJSON(self.tackle2Url + tackle2path("assessments/%d" % assmnt2['id']), self.tackle2Token, data=assmnt2, method='PATCH', ignoreErrors=ignoreErrors) + apiJSON(self.tackle2Url + path, self.tackle2Token, dictObj, method='POST', ignoreErrors=ignoreErrors) + # Migrate Pathfinder Assessment to Konveyor (expecting Pathfinder hard-coded questionnaire ID=1) def migrateAssessments(self, pathfinderUrl, ignoreErrors=False): @@ -613,20 +443,10 @@ class TackleTool: # Duplication checks for t in self.TYPES: - # Pathfinder objects are dependent on Application which was checked before (and its check'd require iterating applications) - if "assessment" in t: - continue print("Checking %s in destination Tackle2.." % t) destCollection = apiJSON(self.tackle2Url + tackle2path(t), self.tackle2Token) localCollection = loadDump(os.path.join(self.dataDir, t + '.json')) for importObj in localCollection: - # Pathfinder resources are dependent on Application, cheking it via applicationId - if t == "applications": - # Check Application's Assessments first - asmnts = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments?applicationId=%d" % importObj['id'], self.tackle2Token, ignoreErrors=True) - if len(asmnts) > 0: - print("ERROR: Pathfinder assessment for application ID %d already exists. Clean it before running the import with: tackle clean" % importObj['id']) - exit(1) for destObj in destCollection: if importObj['id'] == destObj['id']: print("ERROR: Resource %s/%d \"%s\" already exists in Tackle2 destination as \"%s\". Clean it before running the import with: tackle clean" % (t, importObj['id'], importObj['name'], destObj['name'])) @@ -637,15 +457,6 @@ class TackleTool: for t in self.TYPES: dictCollection = loadDump(os.path.join(self.dataDir, t + '.json')) for dictObj in dictCollection: - if "assessment" in t: - continue - # Pathfinder resources are dependent on Application - if t == "applications": - # Delete related Application's Assessment resources first - collection = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments?applicationId=%d" % dictObj['id'], self.tackle2Token, ignoreErrors=True) - for assm in collection: - print("Trying delete assessment %s for applicationId=%s" % (assm['id'], dictObj['id'])) - apiJSON("%s/hub/pathfinder/assessments/%s" % (self.tackle2Url, assm['id']), self.tackle2Token, method='DELETE', ignoreErrors=True) # Hub resources print("Trying delete %s/%s" % (t, dictObj['id'])) apiJSON("%s/hub/%s/%d" % (self.tackle2Url, t, dictObj['id']), self.tackle2Token, method='DELETE', ignoreErrors=True) @@ -653,17 +464,8 @@ class TackleTool: def cleanAllTackle2(self): self.TYPES.reverse() for t in self.NOT_IMPORTED_TYPES + self.TYPES: - # Pathfinder resources are dependent on Application, skip it - if "assessment" in t: - continue destCollection = apiJSON(self.tackle2Url + tackle2path(t), self.tackle2Token) for dictObj in destCollection: - if t == "applications": - # Delete related Application's Assessment resources first - collection = apiJSON(self.tackle2Url + "/hub/pathfinder/assessments?applicationId=%d" % dictObj['id'], self.tackle2Token, ignoreErrors=True) - for assm in collection: - print("Deleting assessment %s for applicationId=%s" % (assm['id'], dictObj['id'])) - apiJSON("%s/hub/pathfinder/assessments/%s" % (self.tackle2Url, assm['id']), self.tackle2Token, method='DELETE', ignoreErrors=True) # Hub resources print("Deleting %s/%s" % (t, dictObj['id'])) apiJSON("%s/hub/%s/%d" % (self.tackle2Url, t, dictObj['id']), self.tackle2Token, method='DELETE', ignoreErrors=True) @@ -740,10 +542,8 @@ if cmdWanted(args, "export"): tool = TackleTool(args.data_dir, '', '', c['url'], token2, c['encryption_passphase']) # Run the export expecting clean destination - print("Exporting Tackle 2 objects (this might take a while..)") + print("Exporting Tackle 2 objects into %s (this might take a while..)" % args.data_dir) tool.dumpTackle2() - print("Writing JSON data files into %s" % args.data_dir) - tool.store() tool.saveManifest() if args.skipBuckets: print("Skipping Buckets file content export.")