From f8b66f29d21e4568a4c596037cef6db4fb555201 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 3 Oct 2023 14:09:14 -0400 Subject: [PATCH 01/56] :sparkles: Allow creating assessments "as-is" (#501) If the "sections" field of the assessment resource is populated when POSTing an assessment, then the sections will not be overridden by values from the questionnaire and the assessment will not be autofilled. Signed-off-by: Sam Lucidi --- api/application.go | 18 ++++++++++-------- api/archetype.go | 17 ++++++++++------- 2 files changed, 20 insertions(+), 15 deletions(-) diff --git a/api/application.go b/api/application.go index 833383885..2e048bfa4 100644 --- a/api/application.go +++ b/api/application.go @@ -1069,18 +1069,20 @@ func (h ApplicationHandler) AssessmentCreate(ctx *gin.Context) { return } m := r.Model() - m.Sections = q.Sections m.Thresholds = q.Thresholds m.RiskMessages = q.RiskMessages m.CreateUser = h.CurrentUser(ctx) - - resolver, err := assessment.NewTagResolver(h.DB(ctx)) - if err != nil { - _ = ctx.Error(err) - return + // if sections aren't nil that indicates that this assessment is being + // created "as-is" and should not have its sections populated or autofilled. + if m.Sections == nil { + m.Sections = q.Sections + resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) + if rErr != nil { + _ = ctx.Error(rErr) + return + } + assessment.PrepareForApplication(resolver, application, m) } - assessment.PrepareForApplication(resolver, application, m) - result = h.DB(ctx).Create(m) if result.Error != nil { _ = ctx.Error(result.Error) diff --git a/api/archetype.go b/api/archetype.go index 8f4488d99..690d7e324 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -283,17 +283,20 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) { return } m := r.Model() - m.Sections = q.Sections m.Thresholds = q.Thresholds m.RiskMessages = q.RiskMessages m.CreateUser = h.CurrentUser(ctx) - - resolver, err := assessment.NewTagResolver(h.DB(ctx)) - if err != nil { - _ = ctx.Error(err) - return + // if sections aren't nil that indicates that this assessment is being + // created "as-is" and should not have its sections populated or autofilled. + if m.Sections == nil { + m.Sections = q.Sections + resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) + if rErr != nil { + _ = ctx.Error(rErr) + return + } + assessment.PrepareForArchetype(resolver, archetype, m) } - assessment.PrepareForArchetype(resolver, archetype, m) result = h.DB(ctx).Create(m) if result.Error != nil { _ = ctx.Error(result.Error) From 6bb1e25b3961b39763d85c25aefc0f738e56d4b6 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 3 Oct 2023 14:09:55 -0400 Subject: [PATCH 02/56] :sparkles: Add `assessed` field to Archetype REST resource (#500) Fixes [https://issues.redhat.com/browse/MTA-1330](https://issues.redhat.com/browse/MTA-1330?filter=-1) Signed-off-by: Sam Lucidi --- api/archetype.go | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/api/archetype.go b/api/archetype.go index 690d7e324..5218ebc6e 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -64,9 +64,16 @@ func (h ArchetypeHandler) Get(ctx *gin.Context) { return } + resolver, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) + if err != nil { + _ = ctx.Error(err) + return + } + r := Archetype{} r.With(m) r.WithApplications(applications) + r.Assessed = resolver.Assessed(m.Assessments) h.Respond(ctx, http.StatusOK, r) } @@ -86,17 +93,25 @@ func (h ArchetypeHandler) List(ctx *gin.Context) { return } + resolver, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) + if err != nil { + _ = ctx.Error(err) + return + } + membership := assessment.NewMembershipResolver(h.DB(ctx)) resources := []Archetype{} for i := range list { + m := &list[i] r := Archetype{} - applications, err := membership.Applications(&list[i]) + applications, err := membership.Applications(m) if err != nil { _ = ctx.Error(err) return } - r.With(&list[i]) + r.With(m) r.WithApplications(applications) + r.Assessed = resolver.Assessed(m.Assessments) resources = append(resources, r) } @@ -320,6 +335,7 @@ type Archetype struct { StakeholderGroups []Ref `json:"stakeholderGroups" yaml:"stakeholderGroups"` Applications []Ref `json:"applications" yaml:"applications"` Assessments []Ref `json:"assessments" yaml:"assessments"` + Assessed bool `json:"assessed"` Review *Ref `json:"review"` } From 2c86e5f1cb98de92aa49b8aa581c15b2b3ec2f44 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Tue, 3 Oct 2023 13:23:10 -0500 Subject: [PATCH 03/56] :ghost: refactor migrations (#497) Process: 1. For each version(3-10): - Copy files from previous version unless redefined (already exists). - Remove the type alias (to previous version) in pkg.go. 2. For each version(2-10): - Consolidate files as defined in #426 . - Edit files to fix imports (just 3-4). fixes: #426 Signed-off-by: Jeff Ortel --- hack/next-migration.sh | 41 +- migration/migrate.go | 71 +++- migration/v10/model/analysis.go | 87 +++++ migration/v10/model/application.go | 301 +++++++++++++++ migration/v10/model/assessment.go | 41 ++ migration/v10/model/core.go | 357 ++++++++++++++++++ migration/v10/model/pkg.go | 42 +-- migration/v2/model/application.go | 173 +++++++++ .../v2/model/{review.go => assessment.go} | 0 migration/v2/model/base.go | 14 - migration/v2/model/bucket.go | 28 -- migration/v2/model/businessservice.go | 10 - migration/v2/model/core.go | 225 +++++++++++ migration/v2/model/dependency.go | 56 --- migration/v2/model/identity.go | 15 - migration/v2/model/import.go | 52 --- migration/v2/model/importsummary.go | 10 - migration/v2/model/importtag.go | 9 - migration/v2/model/jobfunction.go | 8 - migration/v2/model/proxy.go | 15 - migration/v2/model/setting.go | 7 - migration/v2/model/stakeholder.go | 11 - migration/v2/model/stakeholdergroup.go | 9 - migration/v2/model/tag.go | 9 - migration/v2/model/tagtype.go | 10 - migration/v2/model/task.go | 61 --- migration/v2/model/taskgroup.go | 91 ----- migration/v2/model/taskreport.go | 13 - migration/v3/migrate.go | 2 +- .../v3/model/{rulebundle.go => analysis.go} | 13 + migration/v3/model/application.go | 256 +++++++++++++ migration/v3/model/applicationtag.go | 19 - .../review.go => v3/model/assessment.go} | 4 +- migration/v3/model/bucket.go | 56 --- migration/v3/model/core.go | 273 ++++++++++++++ migration/v3/model/fact.go | 8 - migration/v3/model/file.go | 33 -- migration/v3/model/import.go | 52 --- migration/v3/model/importsummary.go | 10 - migration/v3/model/importtag.go | 9 - migration/v3/model/pkg.go | 20 - migration/v3/model/ruleset.go | 14 - migration/v3/model/tag.go | 9 - migration/v3/model/tagcategory.go | 10 - migration/v3/model/task.go | 59 --- migration/v3/model/taskgroup.go | 91 ----- migration/v3/model/ticket.go | 46 --- migration/v3/model/tracker.go | 17 - migration/v4/model/analysis.go | 30 ++ migration/v4/model/application.go | 270 +++++++++++++ migration/v4/model/applicationtag.go | 19 - migration/v4/model/assessment.go | 12 + migration/v4/model/businessservice.go | 10 - migration/v4/model/core.go | 273 ++++++++++++++ migration/v4/model/jobfunction.go | 8 - migration/v4/model/migrationwave.go | 13 - migration/v4/model/pkg.go | 34 -- migration/v4/model/stakeholder.go | 14 - migration/v4/model/stakeholdergroup.go | 10 - migration/v5/model/analysis.go | 29 ++ migration/v5/model/application.go | 255 +++++++++++++ migration/v5/model/applicationtag.go | 19 - migration/v5/model/assessment.go | 12 + migration/v5/model/businessservice.go | 10 - migration/v5/model/core.go | 337 +++++++++++++++++ migration/v5/model/fact.go | 9 - migration/v5/model/identity.go | 83 ---- migration/v5/model/jobfunction.go | 8 - migration/v5/model/migrationwave.go | 13 - migration/v5/model/pkg.go | 25 -- migration/v5/model/ruleset.go | 30 -- migration/v5/model/stakeholder.go | 14 - migration/v5/model/stakeholdergroup.go | 10 - migration/v5/model/ticket.go | 30 -- migration/v5/model/tracker.go | 17 - migration/v6/model/analysis.go | 66 ++++ migration/v6/model/application.go | 280 ++++++++++++++ migration/v6/model/assessment.go | 12 + migration/v6/model/core.go | 356 +++++++++++++++++ migration/v6/model/pkg.go | 32 +- migration/v6/model/ruleset.go | 67 ---- migration/v6/model/task.go | 92 ----- migration/v6/model/taskgroup.go | 91 ----- migration/v7/model/analysis.go | 131 +++++++ migration/v7/model/application.go | 258 +++++++++++++ migration/v7/model/applicationtag.go | 19 - migration/v7/model/assessment.go | 12 + migration/v7/model/businessservice.go | 10 - migration/v7/model/core.go | 357 ++++++++++++++++++ migration/v7/model/jobfunction.go | 9 - migration/v7/model/migrationwave.go | 13 - migration/v7/model/pkg.go | 29 +- migration/v7/model/ruleset.go | 68 ---- migration/v7/model/stakeholder.go | 14 - migration/v7/model/stakeholdergroup.go | 10 - migration/v7/model/tag.go | 10 - migration/v7/model/tagcategory.go | 11 - migration/v8/model/analysis.go | 151 ++++++++ migration/v8/model/application.go | 283 ++++++++++++++ migration/v8/model/assessment.go | 12 + migration/v8/model/core.go | 357 ++++++++++++++++++ migration/v8/model/pkg.go | 38 +- migration/v8/model/ruleset.go | 69 ---- migration/v8/model/target.go | 20 - migration/v9/model/analysis.go | 151 ++++++++ migration/v9/model/application.go | 275 ++++++++++++++ migration/v9/model/applicationtag.go | 19 - migration/v9/model/archetype.go | 14 - migration/v9/model/assessment.go | 13 + migration/v9/model/core.go | 357 ++++++++++++++++++ migration/v9/model/migrationwave.go | 13 - migration/v9/model/pkg.go | 35 +- migration/v9/model/stakeholder.go | 16 - migration/v9/model/stakeholdergroup.go | 12 - 114 files changed, 6114 insertions(+), 2029 deletions(-) create mode 100644 migration/v10/model/application.go create mode 100644 migration/v10/model/assessment.go create mode 100644 migration/v10/model/core.go rename migration/v2/model/{review.go => assessment.go} (100%) delete mode 100644 migration/v2/model/base.go delete mode 100644 migration/v2/model/bucket.go delete mode 100644 migration/v2/model/businessservice.go create mode 100644 migration/v2/model/core.go delete mode 100644 migration/v2/model/dependency.go delete mode 100644 migration/v2/model/identity.go delete mode 100644 migration/v2/model/import.go delete mode 100644 migration/v2/model/importsummary.go delete mode 100644 migration/v2/model/importtag.go delete mode 100644 migration/v2/model/jobfunction.go delete mode 100644 migration/v2/model/proxy.go delete mode 100644 migration/v2/model/setting.go delete mode 100644 migration/v2/model/stakeholder.go delete mode 100644 migration/v2/model/stakeholdergroup.go delete mode 100644 migration/v2/model/tag.go delete mode 100644 migration/v2/model/tagtype.go delete mode 100644 migration/v2/model/task.go delete mode 100644 migration/v2/model/taskgroup.go delete mode 100644 migration/v2/model/taskreport.go rename migration/v3/model/{rulebundle.go => analysis.go} (54%) delete mode 100644 migration/v3/model/applicationtag.go rename migration/{v9/model/review.go => v3/model/assessment.go} (69%) delete mode 100644 migration/v3/model/bucket.go create mode 100644 migration/v3/model/core.go delete mode 100644 migration/v3/model/fact.go delete mode 100644 migration/v3/model/file.go delete mode 100644 migration/v3/model/import.go delete mode 100644 migration/v3/model/importsummary.go delete mode 100644 migration/v3/model/importtag.go delete mode 100644 migration/v3/model/ruleset.go delete mode 100644 migration/v3/model/tag.go delete mode 100644 migration/v3/model/tagcategory.go delete mode 100644 migration/v3/model/task.go delete mode 100644 migration/v3/model/taskgroup.go delete mode 100644 migration/v3/model/ticket.go delete mode 100644 migration/v3/model/tracker.go create mode 100644 migration/v4/model/analysis.go delete mode 100644 migration/v4/model/applicationtag.go create mode 100644 migration/v4/model/assessment.go delete mode 100644 migration/v4/model/businessservice.go create mode 100644 migration/v4/model/core.go delete mode 100644 migration/v4/model/jobfunction.go delete mode 100644 migration/v4/model/migrationwave.go delete mode 100644 migration/v4/model/stakeholder.go delete mode 100644 migration/v4/model/stakeholdergroup.go delete mode 100644 migration/v5/model/applicationtag.go create mode 100644 migration/v5/model/assessment.go delete mode 100644 migration/v5/model/businessservice.go create mode 100644 migration/v5/model/core.go delete mode 100644 migration/v5/model/fact.go delete mode 100644 migration/v5/model/identity.go delete mode 100644 migration/v5/model/jobfunction.go delete mode 100644 migration/v5/model/migrationwave.go delete mode 100644 migration/v5/model/ruleset.go delete mode 100644 migration/v5/model/stakeholder.go delete mode 100644 migration/v5/model/stakeholdergroup.go delete mode 100644 migration/v5/model/ticket.go delete mode 100644 migration/v5/model/tracker.go create mode 100644 migration/v6/model/application.go create mode 100644 migration/v6/model/assessment.go create mode 100644 migration/v6/model/core.go delete mode 100644 migration/v6/model/ruleset.go delete mode 100644 migration/v6/model/task.go delete mode 100644 migration/v6/model/taskgroup.go create mode 100644 migration/v7/model/analysis.go delete mode 100644 migration/v7/model/applicationtag.go create mode 100644 migration/v7/model/assessment.go delete mode 100644 migration/v7/model/businessservice.go create mode 100644 migration/v7/model/core.go delete mode 100644 migration/v7/model/jobfunction.go delete mode 100644 migration/v7/model/migrationwave.go delete mode 100644 migration/v7/model/ruleset.go delete mode 100644 migration/v7/model/stakeholder.go delete mode 100644 migration/v7/model/stakeholdergroup.go delete mode 100644 migration/v7/model/tag.go delete mode 100644 migration/v7/model/tagcategory.go create mode 100644 migration/v8/model/analysis.go create mode 100644 migration/v8/model/application.go create mode 100644 migration/v8/model/assessment.go create mode 100644 migration/v8/model/core.go delete mode 100644 migration/v8/model/ruleset.go delete mode 100644 migration/v8/model/target.go create mode 100644 migration/v9/model/analysis.go delete mode 100644 migration/v9/model/applicationtag.go delete mode 100644 migration/v9/model/archetype.go create mode 100644 migration/v9/model/core.go delete mode 100644 migration/v9/model/migrationwave.go delete mode 100644 migration/v9/model/stakeholder.go delete mode 100644 migration/v9/model/stakeholdergroup.go diff --git a/hack/next-migration.sh b/hack/next-migration.sh index 87b026805..cec45a7b1 100755 --- a/hack/next-migration.sh +++ b/hack/next-migration.sh @@ -16,7 +16,7 @@ importRoot="github.com/konveyor/tackle2-hub/migration" # # Determine migration versions. # -migrations=($(find ${root} -maxdepth 1 -type d -name 'v*' -printf '%f\n' | sort)) +migrations=($(find ${root} -maxdepth 1 -type d -name 'v*' -printf '%f\n' | cut -c2-10 | sort -n)) current=${migrations[-1]} n=${current#"v"} @@ -31,9 +31,9 @@ echo "Current: ${currentDir}" echo "Next: ${nextDir}" # -# Create directores. +# New package. # -mkdir -p ${nextDir}/model +mkdir -p ${nextDir} # # Build migrate.go @@ -66,40 +66,9 @@ EOF echo "${migrate}" > ${file} # -# Build model/pkg.go +# Copy model # -file=${nextDir}/model/pkg.go -pkg=$(cat << EOF -package model - -import "${importRoot}/${current}/model" - -// -// JSON field (data) type. -type JSON = []byte -EOF -) - -echo "${pkg}" > ${file} - -echo "" >> ${file} -models=$(grep "type" model/pkg.go | grep "model") -echo "${models}" >> ${file} -echo -n " -// -// All builds all models. -// Models are enumerated such that each are listed after -// all the other models on which they may depend. -func All() []interface{} { - return []interface{}{ -" >> ${file} -models=$(grep "{}," ${currentDir}/model/pkg.go) -echo "${models}" | while read m -do - echo -e "\t\t${m}" >> ${file} -done -echo -e "\t}" >> ${file} -echo "}" >> ${file} +cp -r ${currentDir}/model ${nextDir} # # Register new migration. diff --git a/migration/migrate.go b/migration/migrate.go index dc2f53125..7f0e38258 100644 --- a/migration/migrate.go +++ b/migration/migrate.go @@ -6,7 +6,13 @@ import ( liberr "github.com/jortel/go-utils/error" "github.com/konveyor/tackle2-hub/database" "github.com/konveyor/tackle2-hub/model" + "github.com/konveyor/tackle2-hub/nas" "gorm.io/gorm" + "os" + "path" + "regexp" + "strconv" + "strings" ) // @@ -80,7 +86,11 @@ func Migrate(migrations []Migration) (err error) { err = liberr.Wrap(err, "version", ver) return } - + err = writeSchema(db, ver) + if err != nil { + err = liberr.Wrap(err, "version", ver) + return + } err = database.Close(db) if err != nil { err = liberr.Wrap(err, "version", ver) @@ -134,3 +144,62 @@ func autoMigrate(db *gorm.DB, models []interface{}) (err error) { } return } + +// +// writeSchema - writes the migrated schema to a file. +func writeSchema(db *gorm.DB, version int) (err error) { + var list []struct { + Type string `gorm:"column:type"` + Name string `gorm:"column:name"` + Table string `gorm:"column:tbl_name"` + RootPage int `gorm:"column:rootpage"` + SQL string `gorm:"column:sql"` + } + db = db.Table("sqlite_schema") + db = db.Order("1, 2") + err = db.Find(&list).Error + if err != nil { + return + } + dir := path.Join( + path.Dir(Settings.Hub.DB.Path), + "migration") + err = nas.MkDir(dir, 0755) + f, err := os.Create(path.Join(dir, strconv.Itoa(version))) + if err != nil { + return + } + defer func() { + _ = f.Close() + }() + pattern := regexp.MustCompile(`[,()]`) + SQL := func(in string) (out string) { + indent := "\n " + for { + m := pattern.FindStringIndex(in) + if m == nil { + out += in + break + } + out += indent + out += in[:m[0]] + out += indent + out += in[m[0]:m[1]] + in = in[m[1]:] + } + return + } + for _, m := range list { + s := strings.Join([]string{ + m.Type, + m.Name, + m.Table, + SQL(m.SQL), + }, "|") + _, err = f.WriteString(s + "\n") + if err != nil { + return + } + } + return +} diff --git a/migration/v10/model/analysis.go b/migration/v10/model/analysis.go index baa7781df..34efb6de2 100644 --- a/migration/v10/model/analysis.go +++ b/migration/v10/model/analysis.go @@ -1,5 +1,7 @@ package model +import "gorm.io/gorm" + // // Analysis report. type Analysis struct { @@ -76,3 +78,88 @@ type ArchivedIssue struct { Effort int `json:"effort"` Incidents int `json:"incidents"` } + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + UUID *string `gorm:"uniqueIndex"` + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Repository JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` + DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` +} + +func (r *RuleSet) Builtin() bool { + return r.UUID != nil +} + +// +// BeforeUpdate hook to avoid cyclic dependencies. +func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { + seen := make(map[uint]bool) + var nextDeps []RuleSet + var nextRuleSetIDs []uint + for _, dep := range r.DependsOn { + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + for len(nextRuleSetIDs) != 0 { + result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) + if result.Error != nil { + err = result.Error + return + } + nextRuleSetIDs = nextRuleSetIDs[:0] + for _, nextDep := range nextDeps { + for _, dep := range nextDep.DependsOn { + if seen[dep.ID] { + continue + } + if dep.ID == r.ID { + err = DependencyCyclicError{} + return + } + seen[dep.ID] = true + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + } + } + + return +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} + +// +// Target - analysis rule selector. +type Target struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex;not null"` + Description string + Choice bool + Labels JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + RuleSetID *uint `gorm:"index"` + RuleSet *RuleSet +} + +func (r *Target) Builtin() bool { + return r.UUID != nil +} diff --git a/migration/v10/model/application.go b/migration/v10/model/application.go new file mode 100644 index 000000000..64e1e52a2 --- /dev/null +++ b/migration/v10/model/application.go @@ -0,0 +1,301 @@ +package model + +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + +type Application struct { + Model + BucketOwner + Name string `gorm:"index;unique;not null"` + Description string + Review *Review `gorm:"constraint:OnDelete:CASCADE"` + Repository JSON `gorm:"type:json"` + Binary string + Facts []Fact `gorm:"constraint:OnDelete:CASCADE"` + Comments string + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + Tags []Tag `gorm:"many2many:ApplicationTags"` + Identities []Identity `gorm:"many2many:ApplicationIdentity;constraint:OnDelete:CASCADE"` + BusinessServiceID *uint `gorm:"index"` + BusinessService *BusinessService + OwnerID *uint `gorm:"index"` + Owner *Stakeholder `gorm:"foreignKey:OwnerID"` + Contributors []Stakeholder `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + Analyses []Analysis `gorm:"constraint:OnDelete:CASCADE"` + MigrationWaveID *uint `gorm:"index"` + MigrationWave *MigrationWave + Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` +} + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + UUID *string `gorm:"uniqueIndex"` + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"many2many:AssessmentStakeholders;constraint:OnDelete:CASCADE"` + Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"many2many:AssessmentStakeholderGroups;constraint:OnDelete:CASCADE"` + Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Archetype struct { + Model + Name string + Description string + Comments string + Review *Review `gorm:"constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` + CriteriaTags []Tag `gorm:"many2many:ArchetypeCriteriaTags;constraint:OnDelete:CASCADE"` + Tags []Tag `gorm:"many2many:ArchetypeTags;constraint:OnDelete:CASCADE"` + Stakeholders []Stakeholder `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v10/model/assessment.go b/migration/v10/model/assessment.go new file mode 100644 index 000000000..f3eeddfa0 --- /dev/null +++ b/migration/v10/model/assessment.go @@ -0,0 +1,41 @@ +package model + +type Questionnaire struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"unique"` + Description string + Required bool + Sections JSON `gorm:"type:json"` + Thresholds JSON `gorm:"type:json"` + RiskMessages JSON `gorm:"type:json"` + Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` +} + +type Assessment struct { + Model + ApplicationID *uint `gorm:"uniqueIndex:AssessmentA"` + Application *Application + ArchetypeID *uint `gorm:"uniqueIndex:AssessmentB"` + Archetype *Archetype + QuestionnaireID uint `gorm:"uniqueIndex:AssessmentA;uniqueIndex:AssessmentB"` + Questionnaire Questionnaire + Sections JSON `gorm:"type:json"` + Thresholds JSON `gorm:"type:json"` + RiskMessages JSON `gorm:"type:json"` + Stakeholders []Stakeholder `gorm:"many2many:AssessmentStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:AssessmentStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID *uint `gorm:"uniqueIndex"` + Application *Application + ArchetypeID *uint `gorm:"uniqueIndex"` + Archetype *Archetype +} diff --git a/migration/v10/model/core.go b/migration/v10/model/core.go new file mode 100644 index 000000000..c18e5663e --- /dev/null +++ b/migration/v10/model/core.go @@ -0,0 +1,357 @@ +package model + +import ( + "encoding/json" + "fmt" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Errors JSON + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil + m.Errors = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Error appends an error. +func (m *Task) Error(severity, description string, x ...interface{}) { + var list []TaskError + description = fmt.Sprintf(description, x...) + te := TaskError{Severity: severity, Description: description} + _ = json.Unmarshal(m.Errors, &list) + list = append(list, te) + m.Errors, _ = json.Marshal(list) +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +// +// TaskError used in Task.Errors. +type TaskError struct { + Severity string `json:"severity"` + Description string `json:"description"` +} + +type TaskReport struct { + Model + Status string + Errors JSON + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v10/model/pkg.go b/migration/v10/model/pkg.go index 4d66fc80b..46c071c59 100644 --- a/migration/v10/model/pkg.go +++ b/migration/v10/model/pkg.go @@ -1,47 +1,15 @@ package model -import "github.com/konveyor/tackle2-hub/migration/v9/model" +import "github.com/konveyor/tackle2-hub/settings" + +var ( + Settings = &settings.Settings +) // // JSON field (data) type. type JSON = []byte -type Model = model.Model -type Application = model.Application -type Archetype = model.Archetype -type Assessment = model.Assessment -type Bucket = model.Bucket -type BucketOwner = model.BucketOwner -type BusinessService = model.BusinessService -type Dependency = model.Dependency -type File = model.File -type Fact = model.Fact -type Identity = model.Identity -type Import = model.Import -type ImportSummary = model.ImportSummary -type ImportTag = model.ImportTag -type JobFunction = model.JobFunction -type MigrationWave = model.MigrationWave -type Proxy = model.Proxy -type Questionnaire = model.Questionnaire -type Review = model.Review -type Setting = model.Setting -type RuleSet = model.RuleSet -type Rule = model.Rule -type Stakeholder = model.Stakeholder -type StakeholderGroup = model.StakeholderGroup -type Tag = model.Tag -type TagCategory = model.TagCategory -type Target = model.Target -type Task = model.Task -type TaskGroup = model.TaskGroup -type TaskReport = model.TaskReport -type Ticket = model.Ticket -type Tracker = model.Tracker -type TTL = model.TTL -type ApplicationTag = model.ApplicationTag -type DependencyCyclicError = model.DependencyCyclicError - // // All builds all models. // Models are enumerated such that each are listed after diff --git a/migration/v2/model/application.go b/migration/v2/model/application.go index 5b8c6af09..1c17a8c8a 100644 --- a/migration/v2/model/application.go +++ b/migration/v2/model/application.go @@ -1,5 +1,11 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" +) + type Application struct { Model BucketOwner @@ -16,3 +22,170 @@ type Application struct { BusinessServiceID *uint `gorm:"index"` BusinessService *BusinessService } + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + TagTypeID uint `gorm:"uniqueIndex:tagA;index;not null"` + TagType TagType +} + +type TagType struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("tagType%v", i+1)] = tag.TagType + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + TagType string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v2/model/review.go b/migration/v2/model/assessment.go similarity index 100% rename from migration/v2/model/review.go rename to migration/v2/model/assessment.go diff --git a/migration/v2/model/base.go b/migration/v2/model/base.go deleted file mode 100644 index 9f52d75d0..000000000 --- a/migration/v2/model/base.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -import ( - "time" -) - -// -// Model Base model. -type Model struct { - ID uint `gorm:"<-:create;primaryKey"` - CreateTime time.Time `gorm:"<-:create;autoCreateTime"` - CreateUser string `gorm:"<-:create"` - UpdateUser string -} diff --git a/migration/v2/model/bucket.go b/migration/v2/model/bucket.go deleted file mode 100644 index a2bb9fd09..000000000 --- a/migration/v2/model/bucket.go +++ /dev/null @@ -1,28 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - liberr "github.com/jortel/go-utils/error" - "gorm.io/gorm" - "os" - "path" -) - -type BucketOwner struct { - Bucket string `gorm:"index"` -} - -func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { - uid := uuid.New() - m.Bucket = path.Join( - Settings.Hub.Bucket.Path, - uid.String()) - err = os.MkdirAll(m.Bucket, 0777) - if err != nil { - err = liberr.Wrap( - err, - "path", - m.Bucket) - } - return -} diff --git a/migration/v2/model/businessservice.go b/migration/v2/model/businessservice.go deleted file mode 100644 index 2eb888546..000000000 --- a/migration/v2/model/businessservice.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type BusinessService struct { - Model - Name string `gorm:"index;unique;not null"` - Description string - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - StakeholderID *uint `gorm:"index"` - Stakeholder *Stakeholder -} diff --git a/migration/v2/model/core.go b/migration/v2/model/core.go new file mode 100644 index 000000000..32ab4fb82 --- /dev/null +++ b/migration/v2/model/core.go @@ -0,0 +1,225 @@ +package model + +import ( + "encoding/json" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type BucketOwner struct { + Bucket string `gorm:"index"` +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Bucket = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Bucket, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Bucket) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON `gorm:"type:json"` + Data JSON `gorm:"type:json"` + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Error string + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + if m.TaskGroupID == nil { + err = m.BucketOwner.BeforeCreate(db) + } + m.Reset() + return +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON `gorm:"type:json"` + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON `gorm:"type:json"` + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.Bucket = m.Bucket + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +type TaskReport struct { + Model + Status string + Error string + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} diff --git a/migration/v2/model/dependency.go b/migration/v2/model/dependency.go deleted file mode 100644 index 6aa1974c9..000000000 --- a/migration/v2/model/dependency.go +++ /dev/null @@ -1,56 +0,0 @@ -package model - -import ( - "gorm.io/gorm" - "sync" -) - -// -// depMutex ensures Dependency.Create() is not executed concurrently. -var depMutex sync.Mutex - -type Dependency struct { - Model - ToID uint `gorm:"index"` - To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` - FromID uint `gorm:"index"` - From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` -} - -// -// Create a dependency synchronized using a mutex. -func (r *Dependency) Create(db *gorm.DB) (err error) { - depMutex.Lock() - defer depMutex.Unlock() - err = db.Create(r).Error - return -} - -// -// Validation Hook to avoid cyclic dependencies. -func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { - var nextDeps []*Dependency - var nextAppsIDs []uint - nextAppsIDs = append(nextAppsIDs, r.FromID) - for len(nextAppsIDs) != 0 { - db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) - nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity - for _, nextDep := range nextDeps { - if nextDep.FromID == r.ToID { - err = DependencyCyclicError{} - return - } - nextAppsIDs = append(nextAppsIDs, nextDep.FromID) - } - } - - return -} - -// -// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. -type DependencyCyclicError struct{} - -func (err DependencyCyclicError) Error() string { - return "cyclic dependencies are not allowed" -} diff --git a/migration/v2/model/identity.go b/migration/v2/model/identity.go deleted file mode 100644 index 8625c0a7c..000000000 --- a/migration/v2/model/identity.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -// -// Identity represents and identity with a set of credentials. -type Identity struct { - Model - Kind string `gorm:"not null"` - Name string `gorm:"not null"` - Description string - User string - Password string - Key string - Settings string - Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` -} diff --git a/migration/v2/model/import.go b/migration/v2/model/import.go deleted file mode 100644 index 6ccdd9fac..000000000 --- a/migration/v2/model/import.go +++ /dev/null @@ -1,52 +0,0 @@ -package model - -import "fmt" - -type Import struct { - Model - Filename string - ApplicationName string - BusinessService string - Comments string - Dependency string - DependencyDirection string - Description string - ErrorMessage string - IsValid bool - RecordType1 string - ImportSummary ImportSummary - ImportSummaryID uint `gorm:"index"` - Processed bool - ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` - BinaryGroup string - BinaryArtifact string - BinaryVersion string - BinaryPackaging string - RepositoryKind string - RepositoryURL string - RepositoryBranch string - RepositoryPath string -} - -func (r *Import) AsMap() (m map[string]interface{}) { - m = make(map[string]interface{}) - m["filename"] = r.Filename - m["applicationName"] = r.ApplicationName - // "Application Name" is necessary in order for - // the UI to display the error report correctly. - m["Application Name"] = r.ApplicationName - m["businessService"] = r.BusinessService - m["comments"] = r.Comments - m["dependency"] = r.Dependency - m["dependencyDirection"] = r.DependencyDirection - m["description"] = r.Description - m["errorMessage"] = r.ErrorMessage - m["isValid"] = r.IsValid - m["processed"] = r.Processed - m["recordType1"] = r.RecordType1 - for i, tag := range r.ImportTags { - m[fmt.Sprintf("tagType%v", i+1)] = tag.TagType - m[fmt.Sprintf("tag%v", i+1)] = tag.Name - } - return -} diff --git a/migration/v2/model/importsummary.go b/migration/v2/model/importsummary.go deleted file mode 100644 index f635f4de1..000000000 --- a/migration/v2/model/importsummary.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type ImportSummary struct { - Model - Content []byte - Filename string - ImportStatus string - Imports []Import `gorm:"constraint:OnDelete:CASCADE"` - CreateEntities bool -} diff --git a/migration/v2/model/importtag.go b/migration/v2/model/importtag.go deleted file mode 100644 index 2c55cc67b..000000000 --- a/migration/v2/model/importtag.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type ImportTag struct { - Model - Name string - TagType string - ImportID uint `gorm:"index"` - Import *Import -} diff --git a/migration/v2/model/jobfunction.go b/migration/v2/model/jobfunction.go deleted file mode 100644 index fc14c08d7..000000000 --- a/migration/v2/model/jobfunction.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type JobFunction struct { - Model - Username string - Name string `gorm:"index;unique;not null"` - Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` -} diff --git a/migration/v2/model/proxy.go b/migration/v2/model/proxy.go deleted file mode 100644 index 78794cc86..000000000 --- a/migration/v2/model/proxy.go +++ /dev/null @@ -1,15 +0,0 @@ -package model - -// -// Proxy configuration. -// kind = (http|https) -type Proxy struct { - Model - Enabled bool - Kind string `gorm:"uniqueIndex"` - Host string `gorm:"not null"` - Port int - Excluded JSON `gorm:"type:json"` - IdentityID *uint `gorm:"index"` - Identity *Identity -} diff --git a/migration/v2/model/setting.go b/migration/v2/model/setting.go deleted file mode 100644 index bd81324d1..000000000 --- a/migration/v2/model/setting.go +++ /dev/null @@ -1,7 +0,0 @@ -package model - -type Setting struct { - Model - Key string `gorm:"<-:create;uniqueIndex"` - Value JSON `gorm:"type:json"` -} diff --git a/migration/v2/model/stakeholder.go b/migration/v2/model/stakeholder.go deleted file mode 100644 index 99cb2973f..000000000 --- a/migration/v2/model/stakeholder.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type Stakeholder struct { - Model - Name string `gorm:"not null;"` - Email string `gorm:"index;unique;not null"` - Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` - JobFunctionID *uint `gorm:"index"` - JobFunction *JobFunction -} diff --git a/migration/v2/model/stakeholdergroup.go b/migration/v2/model/stakeholdergroup.go deleted file mode 100644 index 82ea86f3b..000000000 --- a/migration/v2/model/stakeholdergroup.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type StakeholderGroup struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Description string - Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v2/model/tag.go b/migration/v2/model/tag.go deleted file mode 100644 index 0203ef863..000000000 --- a/migration/v2/model/tag.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type Tag struct { - Model - Name string `gorm:"uniqueIndex:tagA;not null"` - Username string - TagTypeID uint `gorm:"uniqueIndex:tagA;index;not null"` - TagType TagType -} diff --git a/migration/v2/model/tagtype.go b/migration/v2/model/tagtype.go deleted file mode 100644 index fd1cab43f..000000000 --- a/migration/v2/model/tagtype.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type TagType struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Rank uint - Color string - Tags []Tag `gorm:"constraint:OnDelete:CASCADE"` -} diff --git a/migration/v2/model/task.go b/migration/v2/model/task.go deleted file mode 100644 index 235484ada..000000000 --- a/migration/v2/model/task.go +++ /dev/null @@ -1,61 +0,0 @@ -package model - -import ( - "gorm.io/gorm" - "time" -) - -type Task struct { - Model - BucketOwner - Name string `gorm:"index"` - Addon string `gorm:"index"` - Locator string `gorm:"index"` - Priority int - Image string - Variant string - Policy string - TTL JSON `gorm:"type:json"` - Data JSON `gorm:"type:json"` - Started *time.Time - Terminated *time.Time - State string `gorm:"index"` - Error string - Pod string `gorm:"index"` - Retries int - Canceled bool - Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` - ApplicationID *uint - Application *Application - TaskGroupID *uint `gorm:"<-:create"` - TaskGroup *TaskGroup -} - -func (m *Task) Reset() { - m.Started = nil - m.Terminated = nil - m.Report = nil -} - -func (m *Task) BeforeCreate(db *gorm.DB) (err error) { - if m.TaskGroupID == nil { - err = m.BucketOwner.BeforeCreate(db) - } - m.Reset() - return -} - -// -// Map alias. -type Map = map[string]interface{} - -// -// TTL time-to-live. -type TTL struct { - Created int `json:"created,omitempty"` - Pending int `json:"pending,omitempty"` - Postponed int `json:"postponed,omitempty"` - Running int `json:"running,omitempty"` - Succeeded int `json:"succeeded,omitempty"` - Failed int `json:"failed,omitempty"` -} diff --git a/migration/v2/model/taskgroup.go b/migration/v2/model/taskgroup.go deleted file mode 100644 index 2e58e74bc..000000000 --- a/migration/v2/model/taskgroup.go +++ /dev/null @@ -1,91 +0,0 @@ -package model - -import ( - "encoding/json" - liberr "github.com/jortel/go-utils/error" -) - -type TaskGroup struct { - Model - BucketOwner - Name string - Addon string - Data JSON `gorm:"type:json"` - Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` - List JSON `gorm:"type:json"` - State string -} - -// -// Propagate group data into the task. -func (m *TaskGroup) Propagate() (err error) { - for i := range m.Tasks { - task := &m.Tasks[i] - task.State = m.State - task.Bucket = m.Bucket - if task.Addon == "" { - task.Addon = m.Addon - } - if m.Data == nil { - continue - } - a := Map{} - err = json.Unmarshal(m.Data, &a) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - b := Map{} - err = json.Unmarshal(task.Data, &b) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - task.Data, _ = json.Marshal(m.merge(a, b)) - } - - return -} - -// -// merge maps B into A. -// The B map is the authority. -func (m *TaskGroup) merge(a, b Map) (out Map) { - if a == nil { - a = Map{} - } - if b == nil { - b = Map{} - } - out = Map{} - // - // Merge-in elements found in B and in A. - for k, v := range a { - out[k] = v - if bv, found := b[k]; found { - out[k] = bv - if av, cast := v.(Map); cast { - if bv, cast := bv.(Map); cast { - out[k] = m.merge(av, bv) - } else { - out[k] = bv - } - } - } - } - // - // Add elements found only in B. - for k, v := range b { - if _, found := a[k]; !found { - out[k] = v - } - } - - return -} diff --git a/migration/v2/model/taskreport.go b/migration/v2/model/taskreport.go deleted file mode 100644 index bd9393582..000000000 --- a/migration/v2/model/taskreport.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -type TaskReport struct { - Model - Status string - Error string - Total int - Completed int - Activity JSON `gorm:"type:json"` - Result JSON `gorm:"type:json"` - TaskID uint `gorm:"<-:create;uniqueIndex"` - Task *Task -} diff --git a/migration/v3/migrate.go b/migration/v3/migrate.go index 758be4e64..deed54cb4 100644 --- a/migration/v3/migrate.go +++ b/migration/v3/migrate.go @@ -17,7 +17,7 @@ type Migration struct{} func (r Migration) Apply(db *gorm.DB) (err error) { // // Tags/Categories. - err = db.Migrator().RenameTable(model.TagType{}, model.TagCategory{}) + err = db.Migrator().RenameTable(v2.TagType{}, model.TagCategory{}) if err != nil { err = liberr.Wrap(err) return diff --git a/migration/v3/model/rulebundle.go b/migration/v3/model/analysis.go similarity index 54% rename from migration/v3/model/rulebundle.go rename to migration/v3/model/analysis.go index ec4340df9..48e8dafdb 100644 --- a/migration/v3/model/rulebundle.go +++ b/migration/v3/model/analysis.go @@ -15,3 +15,16 @@ type RuleBundle struct { Identity *Identity RuleSets []RuleSet `gorm:"constraint:OnDelete:CASCADE"` } + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + Name string `gorm:"uniqueIndex:RuleSetA;not null"` + Description string + Metadata JSON `gorm:"type:json"` + RuleBundleID uint `gorm:"uniqueIndex:RuleSetA;not null"` + RuleBundle *RuleBundle + FileID *uint `gorm:"index" ref:"file"` + File *File +} diff --git a/migration/v3/model/application.go b/migration/v3/model/application.go index e1aa101bf..9c5db0f16 100644 --- a/migration/v3/model/application.go +++ b/migration/v3/model/application.go @@ -1,5 +1,12 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + type Application struct { Model BucketOwner @@ -16,3 +23,252 @@ type Application struct { BusinessServiceID *uint `gorm:"index"` BusinessService *BusinessService } + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Metadata struct { + Projects []Project `json:"projects"` +} + +type Project struct { + ID string `json:"id"` + Key string `json:"key"` + Name string `json:"name"` + IssueTypes []IssueType `json:"issueTypes"` +} + +type IssueType struct { + ID string `json:"id"` + Name string `json:"name"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Metadata JSON `gorm:"type:json"` + Connected bool + LastUpdated time.Time + Message string + Tickets []Ticket `gorm:"constraint:OnDelete:CASCADE"` +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v3/model/applicationtag.go b/migration/v3/model/applicationtag.go deleted file mode 100644 index d6cb5974d..000000000 --- a/migration/v3/model/applicationtag.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -// -// ApplicationTag represents a row in the join table for the -// many-to-many relationship between Applications and Tags. -type ApplicationTag struct { - ApplicationID uint `gorm:"primaryKey"` - TagID uint `gorm:"primaryKey"` - Source string `gorm:"primaryKey;not null"` - Application Application `gorm:"constraint:OnDelete:CASCADE"` - Tag Tag `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// TableName must return "ApplicationTags" to ensure compatibility -// with the autogenerated join table name. -func (ApplicationTag) TableName() string { - return "ApplicationTags" -} diff --git a/migration/v9/model/review.go b/migration/v3/model/assessment.go similarity index 69% rename from migration/v9/model/review.go rename to migration/v3/model/assessment.go index 6c113f579..e4936d2c6 100644 --- a/migration/v9/model/review.go +++ b/migration/v3/model/assessment.go @@ -7,8 +7,6 @@ type Review struct { ProposedAction string `gorm:"not null"` WorkPriority uint `gorm:"not null"` Comments string - ApplicationID *uint `gorm:"uniqueIndex"` + ApplicationID uint `gorm:"uniqueIndex"` Application *Application - ArchetypeID *uint `gorm:"uniqueIndex"` - Archetype *Archetype } diff --git a/migration/v3/model/bucket.go b/migration/v3/model/bucket.go deleted file mode 100644 index a856729da..000000000 --- a/migration/v3/model/bucket.go +++ /dev/null @@ -1,56 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - liberr "github.com/jortel/go-utils/error" - "gorm.io/gorm" - "os" - "path" - "time" -) - -type Bucket struct { - Model - Path string `gorm:"<-:create;uniqueIndex"` - Expiration *time.Time -} - -func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { - if m.Path == "" { - uid := uuid.New() - m.Path = path.Join( - Settings.Hub.Bucket.Path, - uid.String()) - err = os.MkdirAll(m.Path, 0777) - if err != nil { - err = liberr.Wrap( - err, - "path", - m.Path) - } - } - return -} - -type BucketOwner struct { - BucketID *uint `gorm:"index" ref:"bucket"` - Bucket *Bucket -} - -func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { - if !m.HasBucket() { - b := &Bucket{} - err = db.Create(b).Error - m.SetBucket(&b.ID) - } - return -} - -func (m *BucketOwner) SetBucket(id *uint) { - m.BucketID = id - m.Bucket = nil -} - -func (m *BucketOwner) HasBucket() (b bool) { - return m.BucketID != nil -} diff --git a/migration/v3/model/core.go b/migration/v3/model/core.go new file mode 100644 index 000000000..bd253bb69 --- /dev/null +++ b/migration/v3/model/core.go @@ -0,0 +1,273 @@ +package model + +import ( + "encoding/json" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Error string + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +type TaskReport struct { + Model + Status string + Error string + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} diff --git a/migration/v3/model/fact.go b/migration/v3/model/fact.go deleted file mode 100644 index 77b6cc384..000000000 --- a/migration/v3/model/fact.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type Fact struct { - ApplicationID uint `gorm:"<-:create;primaryKey"` - Key string `gorm:"<-:create;primaryKey"` - Value JSON `gorm:"type:json;not null"` - Application *Application -} diff --git a/migration/v3/model/file.go b/migration/v3/model/file.go deleted file mode 100644 index 97606a8b0..000000000 --- a/migration/v3/model/file.go +++ /dev/null @@ -1,33 +0,0 @@ -package model - -import ( - "github.com/google/uuid" - liberr "github.com/jortel/go-utils/error" - "gorm.io/gorm" - "os" - "path" - "time" -) - -type File struct { - Model - Name string - Path string `gorm:"<-:create;uniqueIndex"` - Expiration *time.Time -} - -func (m *File) BeforeCreate(db *gorm.DB) (err error) { - uid := uuid.New() - m.Path = path.Join( - Settings.Hub.Bucket.Path, - ".file", - uid.String()) - err = os.MkdirAll(path.Dir(m.Path), 0777) - if err != nil { - err = liberr.Wrap( - err, - "path", - m.Path) - } - return -} diff --git a/migration/v3/model/import.go b/migration/v3/model/import.go deleted file mode 100644 index 680f8ad4b..000000000 --- a/migration/v3/model/import.go +++ /dev/null @@ -1,52 +0,0 @@ -package model - -import "fmt" - -type Import struct { - Model - Filename string - ApplicationName string - BusinessService string - Comments string - Dependency string - DependencyDirection string - Description string - ErrorMessage string - IsValid bool - RecordType1 string - ImportSummary ImportSummary - ImportSummaryID uint `gorm:"index"` - Processed bool - ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` - BinaryGroup string - BinaryArtifact string - BinaryVersion string - BinaryPackaging string - RepositoryKind string - RepositoryURL string - RepositoryBranch string - RepositoryPath string -} - -func (r *Import) AsMap() (m map[string]interface{}) { - m = make(map[string]interface{}) - m["filename"] = r.Filename - m["applicationName"] = r.ApplicationName - // "Application Name" is necessary in order for - // the UI to display the error report correctly. - m["Application Name"] = r.ApplicationName - m["businessService"] = r.BusinessService - m["comments"] = r.Comments - m["dependency"] = r.Dependency - m["dependencyDirection"] = r.DependencyDirection - m["description"] = r.Description - m["errorMessage"] = r.ErrorMessage - m["isValid"] = r.IsValid - m["processed"] = r.Processed - m["recordType1"] = r.RecordType1 - for i, tag := range r.ImportTags { - m[fmt.Sprintf("category%v", i+1)] = tag.Category - m[fmt.Sprintf("tag%v", i+1)] = tag.Name - } - return -} diff --git a/migration/v3/model/importsummary.go b/migration/v3/model/importsummary.go deleted file mode 100644 index f635f4de1..000000000 --- a/migration/v3/model/importsummary.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type ImportSummary struct { - Model - Content []byte - Filename string - ImportStatus string - Imports []Import `gorm:"constraint:OnDelete:CASCADE"` - CreateEntities bool -} diff --git a/migration/v3/model/importtag.go b/migration/v3/model/importtag.go deleted file mode 100644 index bf5166e12..000000000 --- a/migration/v3/model/importtag.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type ImportTag struct { - Model - Name string - Category string - ImportID uint `gorm:"index"` - Import *Import -} diff --git a/migration/v3/model/pkg.go b/migration/v3/model/pkg.go index f8bf03300..8a631093e 100644 --- a/migration/v3/model/pkg.go +++ b/migration/v3/model/pkg.go @@ -1,7 +1,6 @@ package model import ( - v2 "github.com/konveyor/tackle2-hub/migration/v2/model" "github.com/konveyor/tackle2-hub/settings" ) @@ -13,25 +12,6 @@ var ( // JSON field (data) type. type JSON = []byte -// -// Unchanged models imported from previous migration. -type Model = v2.Model -type BusinessService = v2.BusinessService -type Dependency = v2.Dependency -type Identity = v2.Identity -type JobFunction = v2.JobFunction -type Proxy = v2.Proxy -type Review = v2.Review -type Setting = v2.Setting -type Stakeholder = v2.Stakeholder -type StakeholderGroup = v2.StakeholderGroup -type TagType = v2.TagType -type TaskReport = v2.TaskReport - -// -// Errors -type DependencyCyclicError = v2.DependencyCyclicError - // // All builds all models. // Models are enumerated such that each are listed after diff --git a/migration/v3/model/ruleset.go b/migration/v3/model/ruleset.go deleted file mode 100644 index da558305d..000000000 --- a/migration/v3/model/ruleset.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -// -// RuleSet - Analysis ruleset. -type RuleSet struct { - Model - Name string `gorm:"uniqueIndex:RuleSetA;not null"` - Description string - Metadata JSON `gorm:"type:json"` - RuleBundleID uint `gorm:"uniqueIndex:RuleSetA;not null"` - RuleBundle *RuleBundle - FileID *uint `gorm:"index" ref:"file"` - File *File -} diff --git a/migration/v3/model/tag.go b/migration/v3/model/tag.go deleted file mode 100644 index 164dc63bb..000000000 --- a/migration/v3/model/tag.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type Tag struct { - Model - Name string `gorm:"uniqueIndex:tagA;not null"` - Username string - CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` - Category TagCategory -} diff --git a/migration/v3/model/tagcategory.go b/migration/v3/model/tagcategory.go deleted file mode 100644 index 10368768b..000000000 --- a/migration/v3/model/tagcategory.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type TagCategory struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Rank uint - Color string - Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v3/model/task.go b/migration/v3/model/task.go deleted file mode 100644 index 56c28c56c..000000000 --- a/migration/v3/model/task.go +++ /dev/null @@ -1,59 +0,0 @@ -package model - -import ( - "gorm.io/gorm" - "time" -) - -type Task struct { - Model - BucketOwner - Name string `gorm:"index"` - Addon string `gorm:"index"` - Locator string `gorm:"index"` - Priority int - Image string - Variant string - Policy string - TTL JSON - Data JSON - Started *time.Time - Terminated *time.Time - State string `gorm:"index"` - Error string - Pod string `gorm:"index"` - Retries int - Canceled bool - Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` - ApplicationID *uint - Application *Application - TaskGroupID *uint `gorm:"<-:create"` - TaskGroup *TaskGroup -} - -func (m *Task) Reset() { - m.Started = nil - m.Terminated = nil - m.Report = nil -} - -func (m *Task) BeforeCreate(db *gorm.DB) (err error) { - err = m.BucketOwner.BeforeCreate(db) - m.Reset() - return -} - -// -// Map alias. -type Map = map[string]interface{} - -// -// TTL time-to-live. -type TTL struct { - Created int `json:"created,omitempty"` - Pending int `json:"pending,omitempty"` - Postponed int `json:"postponed,omitempty"` - Running int `json:"running,omitempty"` - Succeeded int `json:"succeeded,omitempty"` - Failed int `json:"failed,omitempty"` -} diff --git a/migration/v3/model/taskgroup.go b/migration/v3/model/taskgroup.go deleted file mode 100644 index cc61ce221..000000000 --- a/migration/v3/model/taskgroup.go +++ /dev/null @@ -1,91 +0,0 @@ -package model - -import ( - "encoding/json" - liberr "github.com/jortel/go-utils/error" -) - -type TaskGroup struct { - Model - BucketOwner - Name string - Addon string - Data JSON - Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` - List JSON - State string -} - -// -// Propagate group data into the task. -func (m *TaskGroup) Propagate() (err error) { - for i := range m.Tasks { - task := &m.Tasks[i] - task.State = m.State - task.SetBucket(m.BucketID) - if task.Addon == "" { - task.Addon = m.Addon - } - if m.Data == nil { - continue - } - a := Map{} - err = json.Unmarshal(m.Data, &a) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - b := Map{} - err = json.Unmarshal(task.Data, &b) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - task.Data, _ = json.Marshal(m.merge(a, b)) - } - - return -} - -// -// merge maps B into A. -// The B map is the authority. -func (m *TaskGroup) merge(a, b Map) (out Map) { - if a == nil { - a = Map{} - } - if b == nil { - b = Map{} - } - out = Map{} - // - // Merge-in elements found in B and in A. - for k, v := range a { - out[k] = v - if bv, found := b[k]; found { - out[k] = bv - if av, cast := v.(Map); cast { - if bv, cast := bv.(Map); cast { - out[k] = m.merge(av, bv) - } else { - out[k] = bv - } - } - } - } - // - // Add elements found only in B. - for k, v := range b { - if _, found := a[k]; !found { - out[k] = v - } - } - - return -} diff --git a/migration/v3/model/ticket.go b/migration/v3/model/ticket.go deleted file mode 100644 index 4d83c0f63..000000000 --- a/migration/v3/model/ticket.go +++ /dev/null @@ -1,46 +0,0 @@ -package model - -import "time" - -type Ticket struct { - Model - // Kind of ticket in the external tracker. - Kind string `gorm:"not null"` - // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) - Parent string `gorm:"not null"` - // Custom fields to send to the tracker when creating the ticket - Fields JSON `gorm:"type:json"` - // Whether the last attempt to do something with the ticket reported an error - Error bool - // Error message, if any - Message string - // Whether the ticket was created in the external tracker - Created bool - // Reference id in external tracker - Reference string - // URL to ticket in external tracker - Link string - // Status of ticket in external tracker - Status string - LastUpdated time.Time - Application *Application - ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` - Tracker *Tracker - TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` -} - -type Metadata struct { - Projects []Project `json:"projects"` -} - -type Project struct { - ID string `json:"id"` - Key string `json:"key"` - Name string `json:"name"` - IssueTypes []IssueType `json:"issueTypes"` -} - -type IssueType struct { - ID string `json:"id"` - Name string `json:"name"` -} diff --git a/migration/v3/model/tracker.go b/migration/v3/model/tracker.go deleted file mode 100644 index 5b3030e15..000000000 --- a/migration/v3/model/tracker.go +++ /dev/null @@ -1,17 +0,0 @@ -package model - -import "time" - -type Tracker struct { - Model - Name string `gorm:"index;unique;not null"` - URL string - Kind string - Identity *Identity - IdentityID uint - Metadata JSON `gorm:"type:json"` - Connected bool - LastUpdated time.Time - Message string - Tickets []Ticket `gorm:"constraint:OnDelete:CASCADE"` -} diff --git a/migration/v4/model/analysis.go b/migration/v4/model/analysis.go new file mode 100644 index 000000000..48e8dafdb --- /dev/null +++ b/migration/v4/model/analysis.go @@ -0,0 +1,30 @@ +package model + +// +// RuleBundle - Analysis rules. +type RuleBundle struct { + Model + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Custom bool + Repository JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + IdentityID *uint `gorm:"index"` + Identity *Identity + RuleSets []RuleSet `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + Name string `gorm:"uniqueIndex:RuleSetA;not null"` + Description string + Metadata JSON `gorm:"type:json"` + RuleBundleID uint `gorm:"uniqueIndex:RuleSetA;not null"` + RuleBundle *RuleBundle + FileID *uint `gorm:"index" ref:"file"` + File *File +} diff --git a/migration/v4/model/application.go b/migration/v4/model/application.go index 44023729a..071a68440 100644 --- a/migration/v4/model/application.go +++ b/migration/v4/model/application.go @@ -1,5 +1,12 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + type Application struct { Model BucketOwner @@ -21,3 +28,266 @@ type Application struct { MigrationWaveID *uint `gorm:"index"` MigrationWave *MigrationWave } + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string + StartDate time.Time + EndDate time.Time + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Metadata struct { + Projects []Project `json:"projects"` +} + +type Project struct { + ID string `json:"id"` + Key string `json:"key"` + Name string `json:"name"` + IssueTypes []IssueType `json:"issueTypes"` +} + +type IssueType struct { + ID string `json:"id"` + Name string `json:"name"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Metadata JSON `gorm:"type:json"` + Connected bool + LastUpdated time.Time + Message string + Tickets []Ticket `gorm:"constraint:OnDelete:CASCADE"` +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v4/model/applicationtag.go b/migration/v4/model/applicationtag.go deleted file mode 100644 index d6cb5974d..000000000 --- a/migration/v4/model/applicationtag.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -// -// ApplicationTag represents a row in the join table for the -// many-to-many relationship between Applications and Tags. -type ApplicationTag struct { - ApplicationID uint `gorm:"primaryKey"` - TagID uint `gorm:"primaryKey"` - Source string `gorm:"primaryKey;not null"` - Application Application `gorm:"constraint:OnDelete:CASCADE"` - Tag Tag `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// TableName must return "ApplicationTags" to ensure compatibility -// with the autogenerated join table name. -func (ApplicationTag) TableName() string { - return "ApplicationTags" -} diff --git a/migration/v4/model/assessment.go b/migration/v4/model/assessment.go new file mode 100644 index 000000000..e4936d2c6 --- /dev/null +++ b/migration/v4/model/assessment.go @@ -0,0 +1,12 @@ +package model + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID uint `gorm:"uniqueIndex"` + Application *Application +} diff --git a/migration/v4/model/businessservice.go b/migration/v4/model/businessservice.go deleted file mode 100644 index 2eb888546..000000000 --- a/migration/v4/model/businessservice.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type BusinessService struct { - Model - Name string `gorm:"index;unique;not null"` - Description string - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - StakeholderID *uint `gorm:"index"` - Stakeholder *Stakeholder -} diff --git a/migration/v4/model/core.go b/migration/v4/model/core.go new file mode 100644 index 000000000..bd253bb69 --- /dev/null +++ b/migration/v4/model/core.go @@ -0,0 +1,273 @@ +package model + +import ( + "encoding/json" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Error string + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +type TaskReport struct { + Model + Status string + Error string + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} diff --git a/migration/v4/model/jobfunction.go b/migration/v4/model/jobfunction.go deleted file mode 100644 index fc14c08d7..000000000 --- a/migration/v4/model/jobfunction.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type JobFunction struct { - Model - Username string - Name string `gorm:"index;unique;not null"` - Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` -} diff --git a/migration/v4/model/migrationwave.go b/migration/v4/model/migrationwave.go deleted file mode 100644 index 66052cc40..000000000 --- a/migration/v4/model/migrationwave.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -import "time" - -type MigrationWave struct { - Model - Name string - StartDate time.Time - EndDate time.Time - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` - StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v4/model/pkg.go b/migration/v4/model/pkg.go index d03a52fee..f333361bb 100644 --- a/migration/v4/model/pkg.go +++ b/migration/v4/model/pkg.go @@ -1,7 +1,6 @@ package model import ( - v3 "github.com/konveyor/tackle2-hub/migration/v3/model" "github.com/konveyor/tackle2-hub/settings" ) @@ -13,39 +12,6 @@ var ( // JSON field (data) type. type JSON = []byte -// -// Unchanged models imported from previous migration. -type Model = v3.Model -type Bucket = v3.Bucket -type BucketOwner = v3.BucketOwner -type Dependency = v3.Dependency -type Fact = v3.Fact -type File = v3.File -type Identity = v3.Identity -type Import = v3.Import -type ImportSummary = v3.ImportSummary -type ImportTag = v3.ImportTag -type Proxy = v3.Proxy -type Review = v3.Review -type RuleBundle = v3.RuleBundle -type RuleSet = v3.RuleSet -type Setting = v3.Setting -type Tag = v3.Tag -type TagCategory = v3.TagCategory -type Task = v3.Task -type TaskGroup = v3.TaskGroup -type TaskReport = v3.TaskReport -type Ticket = v3.Ticket -type Tracker = v3.Tracker -type TTL = v3.TTL -type Metadata = v3.Metadata -type Project = v3.Project -type IssueType = v3.IssueType - -// -// Errors -type DependencyCyclicError = v3.DependencyCyclicError - // // All builds all models. // Models are enumerated such that each are listed after diff --git a/migration/v4/model/stakeholder.go b/migration/v4/model/stakeholder.go deleted file mode 100644 index 66243f8f7..000000000 --- a/migration/v4/model/stakeholder.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Stakeholder struct { - Model - Name string `gorm:"not null;"` - Email string `gorm:"index;unique;not null"` - Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` - JobFunctionID *uint `gorm:"index"` - JobFunction *JobFunction - Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` - Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v4/model/stakeholdergroup.go b/migration/v4/model/stakeholdergroup.go deleted file mode 100644 index 384373cd0..000000000 --- a/migration/v4/model/stakeholdergroup.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type StakeholderGroup struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Description string - Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v5/model/analysis.go b/migration/v5/model/analysis.go index 12c72ab41..3624852ea 100644 --- a/migration/v5/model/analysis.go +++ b/migration/v5/model/analysis.go @@ -61,3 +61,32 @@ type Link struct { URL string `json:"url"` Title string `json:"title,omitempty"` } + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Custom bool + Repository JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} diff --git a/migration/v5/model/application.go b/migration/v5/model/application.go index fa1f5566b..aae434219 100644 --- a/migration/v5/model/application.go +++ b/migration/v5/model/application.go @@ -1,5 +1,12 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + type Application struct { Model BucketOwner @@ -23,3 +30,251 @@ type Application struct { MigrationWave *MigrationWave Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` } + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v5/model/applicationtag.go b/migration/v5/model/applicationtag.go deleted file mode 100644 index d6cb5974d..000000000 --- a/migration/v5/model/applicationtag.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -// -// ApplicationTag represents a row in the join table for the -// many-to-many relationship between Applications and Tags. -type ApplicationTag struct { - ApplicationID uint `gorm:"primaryKey"` - TagID uint `gorm:"primaryKey"` - Source string `gorm:"primaryKey;not null"` - Application Application `gorm:"constraint:OnDelete:CASCADE"` - Tag Tag `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// TableName must return "ApplicationTags" to ensure compatibility -// with the autogenerated join table name. -func (ApplicationTag) TableName() string { - return "ApplicationTags" -} diff --git a/migration/v5/model/assessment.go b/migration/v5/model/assessment.go new file mode 100644 index 000000000..e4936d2c6 --- /dev/null +++ b/migration/v5/model/assessment.go @@ -0,0 +1,12 @@ +package model + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID uint `gorm:"uniqueIndex"` + Application *Application +} diff --git a/migration/v5/model/businessservice.go b/migration/v5/model/businessservice.go deleted file mode 100644 index 2eb888546..000000000 --- a/migration/v5/model/businessservice.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type BusinessService struct { - Model - Name string `gorm:"index;unique;not null"` - Description string - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - StakeholderID *uint `gorm:"index"` - Stakeholder *Stakeholder -} diff --git a/migration/v5/model/core.go b/migration/v5/model/core.go new file mode 100644 index 000000000..a64b1e5b7 --- /dev/null +++ b/migration/v5/model/core.go @@ -0,0 +1,337 @@ +package model + +import ( + "encoding/json" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Error string + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +type TaskReport struct { + Model + Status string + Error string + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v5/model/fact.go b/migration/v5/model/fact.go deleted file mode 100644 index 71b3dbe9f..000000000 --- a/migration/v5/model/fact.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type Fact struct { - ApplicationID uint `gorm:"<-:create;primaryKey"` - Key string `gorm:"<-:create;primaryKey"` - Source string `gorm:"<-:create;primaryKey;not null"` - Value JSON `gorm:"type:json;not null"` - Application *Application -} diff --git a/migration/v5/model/identity.go b/migration/v5/model/identity.go deleted file mode 100644 index d0134ec86..000000000 --- a/migration/v5/model/identity.go +++ /dev/null @@ -1,83 +0,0 @@ -package model - -import ( - liberr "github.com/jortel/go-utils/error" - "github.com/konveyor/tackle2-hub/encryption" -) - -// Identity represents and identity with a set of credentials. -type Identity struct { - Model - Kind string `gorm:"not null"` - Name string `gorm:"index;unique;not null"` - Description string - User string - Password string - Key string - Settings string - Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` -} - -// Encrypt sensitive fields. -// The ref identity is used to determine when sensitive fields -// have changed and need to be (re)encrypted. -func (r *Identity) Encrypt(ref *Identity) (err error) { - passphrase := Settings.Encryption.Passphrase - aes := encryption.New(passphrase) - if r.Password != ref.Password { - if r.Password != "" { - r.Password, err = aes.Encrypt(r.Password) - if err != nil { - err = liberr.Wrap(err) - return - } - } - } - if r.Key != ref.Key { - if r.Key != "" { - r.Key, err = aes.Encrypt(r.Key) - if err != nil { - err = liberr.Wrap(err) - return - } - } - } - if r.Settings != ref.Settings { - if r.Settings != "" { - r.Settings, err = aes.Encrypt(r.Settings) - if err != nil { - err = liberr.Wrap(err) - return - } - } - } - return -} - -// Decrypt sensitive fields. -func (r *Identity) Decrypt() (err error) { - passphrase := Settings.Encryption.Passphrase - aes := encryption.New(passphrase) - if r.Password != "" { - r.Password, err = aes.Decrypt(r.Password) - if err != nil { - err = liberr.Wrap(err) - return - } - } - if r.Key != "" { - r.Key, err = aes.Decrypt(r.Key) - if err != nil { - err = liberr.Wrap(err) - return - } - } - if r.Settings != "" { - r.Settings, err = aes.Decrypt(r.Settings) - if err != nil { - err = liberr.Wrap(err) - return - } - } - return -} diff --git a/migration/v5/model/jobfunction.go b/migration/v5/model/jobfunction.go deleted file mode 100644 index fc14c08d7..000000000 --- a/migration/v5/model/jobfunction.go +++ /dev/null @@ -1,8 +0,0 @@ -package model - -type JobFunction struct { - Model - Username string - Name string `gorm:"index;unique;not null"` - Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` -} diff --git a/migration/v5/model/migrationwave.go b/migration/v5/model/migrationwave.go deleted file mode 100644 index 8cec17fee..000000000 --- a/migration/v5/model/migrationwave.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -import "time" - -type MigrationWave struct { - Model - Name string `gorm:"uniqueIndex:MigrationWaveA"` - StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` - StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v5/model/pkg.go b/migration/v5/model/pkg.go index 5294d6629..4ce2479de 100644 --- a/migration/v5/model/pkg.go +++ b/migration/v5/model/pkg.go @@ -1,7 +1,6 @@ package model import ( - v4 "github.com/konveyor/tackle2-hub/migration/v4/model" "github.com/konveyor/tackle2-hub/settings" ) @@ -13,30 +12,6 @@ var ( // JSON field (data) type. type JSON = []byte -// -// Unchanged models imported from previous migration. -type Model = v4.Model -type Bucket = v4.Bucket -type BucketOwner = v4.BucketOwner -type Dependency = v4.Dependency -type File = v4.File -type Import = v4.Import -type ImportSummary = v4.ImportSummary -type ImportTag = v4.ImportTag -type Proxy = v4.Proxy -type Review = v4.Review -type Setting = v4.Setting -type Tag = v4.Tag -type TagCategory = v4.TagCategory -type Task = v4.Task -type TaskGroup = v4.TaskGroup -type TaskReport = v4.TaskReport -type TTL = v4.TTL - -// -// Errors -type DependencyCyclicError = v4.DependencyCyclicError - // // All builds all models. // Models are enumerated such that each are listed after diff --git a/migration/v5/model/ruleset.go b/migration/v5/model/ruleset.go deleted file mode 100644 index 92551d428..000000000 --- a/migration/v5/model/ruleset.go +++ /dev/null @@ -1,30 +0,0 @@ -package model - -// -// RuleSet - Analysis ruleset. -type RuleSet struct { - Model - Kind string - Name string `gorm:"uniqueIndex;not null"` - Description string - Custom bool - Repository JSON `gorm:"type:json"` - ImageID uint `gorm:"index" ref:"file"` - Image *File - IdentityID *uint `gorm:"index"` - Identity *Identity - Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// Rule - Analysis rule. -type Rule struct { - Model - Name string - Description string - Labels JSON `gorm:"type:json"` - RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` - RuleSet *RuleSet - FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` - File *File -} diff --git a/migration/v5/model/stakeholder.go b/migration/v5/model/stakeholder.go deleted file mode 100644 index 66243f8f7..000000000 --- a/migration/v5/model/stakeholder.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Stakeholder struct { - Model - Name string `gorm:"not null;"` - Email string `gorm:"index;unique;not null"` - Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` - JobFunctionID *uint `gorm:"index"` - JobFunction *JobFunction - Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` - Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v5/model/stakeholdergroup.go b/migration/v5/model/stakeholdergroup.go deleted file mode 100644 index 384373cd0..000000000 --- a/migration/v5/model/stakeholdergroup.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type StakeholderGroup struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Description string - Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v5/model/ticket.go b/migration/v5/model/ticket.go deleted file mode 100644 index e0c67a049..000000000 --- a/migration/v5/model/ticket.go +++ /dev/null @@ -1,30 +0,0 @@ -package model - -import "time" - -type Ticket struct { - Model - // Kind of ticket in the external tracker. - Kind string `gorm:"not null"` - // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) - Parent string `gorm:"not null"` - // Custom fields to send to the tracker when creating the ticket - Fields JSON `gorm:"type:json"` - // Whether the last attempt to do something with the ticket reported an error - Error bool - // Error message, if any - Message string - // Whether the ticket was created in the external tracker - Created bool - // Reference id in external tracker - Reference string - // URL to ticket in external tracker - Link string - // Status of ticket in external tracker - Status string - LastUpdated time.Time - Application *Application - ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` - Tracker *Tracker - TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` -} diff --git a/migration/v5/model/tracker.go b/migration/v5/model/tracker.go deleted file mode 100644 index 8fe40c225..000000000 --- a/migration/v5/model/tracker.go +++ /dev/null @@ -1,17 +0,0 @@ -package model - -import "time" - -type Tracker struct { - Model - Name string `gorm:"index;unique;not null"` - URL string - Kind string - Identity *Identity - IdentityID uint - Connected bool - LastUpdated time.Time - Message string - Insecure bool - Tickets []Ticket -} diff --git a/migration/v6/model/analysis.go b/migration/v6/model/analysis.go index 0f7d223de..43f3e8e1a 100644 --- a/migration/v6/model/analysis.go +++ b/migration/v6/model/analysis.go @@ -1,5 +1,7 @@ package model +import "gorm.io/gorm" + // // Analysis report. type Analysis struct { @@ -62,3 +64,67 @@ type Link struct { URL string `json:"url"` Title string `json:"title,omitempty"` } + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Custom bool + Repository JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` + DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` +} + +// +// BeforeUpdate hook to avoid cyclic dependencies. +func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { + seen := make(map[uint]bool) + var nextDeps []RuleSet + var nextRuleSetIDs []uint + for _, dep := range r.DependsOn { + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + for len(nextRuleSetIDs) != 0 { + result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) + if result.Error != nil { + err = result.Error + return + } + nextRuleSetIDs = nextRuleSetIDs[:0] + for _, nextDep := range nextDeps { + for _, dep := range nextDep.DependsOn { + if seen[dep.ID] { + continue + } + if dep.ID == r.ID { + err = DependencyCyclicError{} + return + } + seen[dep.ID] = true + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + } + } + + return +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} diff --git a/migration/v6/model/application.go b/migration/v6/model/application.go new file mode 100644 index 000000000..aae434219 --- /dev/null +++ b/migration/v6/model/application.go @@ -0,0 +1,280 @@ +package model + +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + +type Application struct { + Model + BucketOwner + Name string `gorm:"index;unique;not null"` + Description string + Review *Review `gorm:"constraint:OnDelete:CASCADE"` + Repository JSON `gorm:"type:json"` + Binary string + Facts []Fact `gorm:"constraint:OnDelete:CASCADE"` + Comments string + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + Tags []Tag `gorm:"many2many:ApplicationTags"` + Identities []Identity `gorm:"many2many:ApplicationIdentity;constraint:OnDelete:CASCADE"` + BusinessServiceID *uint `gorm:"index"` + BusinessService *BusinessService + OwnerID *uint `gorm:"index"` + Owner *Stakeholder `gorm:"foreignKey:OwnerID"` + Contributors []Stakeholder `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + Analyses []Analysis `gorm:"constraint:OnDelete:CASCADE"` + MigrationWaveID *uint `gorm:"index"` + MigrationWave *MigrationWave + Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` +} + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v6/model/assessment.go b/migration/v6/model/assessment.go new file mode 100644 index 000000000..e4936d2c6 --- /dev/null +++ b/migration/v6/model/assessment.go @@ -0,0 +1,12 @@ +package model + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID uint `gorm:"uniqueIndex"` + Application *Application +} diff --git a/migration/v6/model/core.go b/migration/v6/model/core.go new file mode 100644 index 000000000..6d6557ae6 --- /dev/null +++ b/migration/v6/model/core.go @@ -0,0 +1,356 @@ +package model + +import ( + "encoding/json" + "fmt" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Errors JSON + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil + m.Errors = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Error appends an error. +func (m *Task) Error(severity, description string, x ...interface{}) { + var list []TaskError + description = fmt.Sprintf(description, x...) + te := TaskError{Severity: severity, Description: description} + _ = json.Unmarshal(m.Errors, &list) + list = append(list, te) + m.Errors, _ = json.Marshal(list) +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +// +// TaskError used in Task.Errors. +type TaskError struct { + Severity string `json:"severity"` + Description string `json:"description"` +} + +type TaskReport struct { + Model + Status string + Errors JSON + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v6/model/pkg.go b/migration/v6/model/pkg.go index e58d282a4..33c97725e 100644 --- a/migration/v6/model/pkg.go +++ b/migration/v6/model/pkg.go @@ -1,37 +1,15 @@ package model -import "github.com/konveyor/tackle2-hub/migration/v5/model" +import "github.com/konveyor/tackle2-hub/settings" + +var ( + Settings = &settings.Settings +) // // JSON field (data) type. type JSON = []byte -type Model = model.Model -type Application = model.Application -type Bucket = model.Bucket -type BucketOwner = model.BucketOwner -type BusinessService = model.BusinessService -type Dependency = model.Dependency -type File = model.File -type Fact = model.Fact -type Identity = model.Identity -type Import = model.Import -type ImportSummary = model.ImportSummary -type ImportTag = model.ImportTag -type JobFunction = model.JobFunction -type MigrationWave = model.MigrationWave -type Proxy = model.Proxy -type Review = model.Review -type Setting = model.Setting -type Stakeholder = model.Stakeholder -type StakeholderGroup = model.StakeholderGroup -type Tag = model.Tag -type TagCategory = model.TagCategory -type Ticket = model.Ticket -type Tracker = model.Tracker -type ApplicationTag = model.ApplicationTag -type DependencyCyclicError = model.DependencyCyclicError - // // All builds all models. // Models are enumerated such that each are listed after diff --git a/migration/v6/model/ruleset.go b/migration/v6/model/ruleset.go deleted file mode 100644 index 032818cb9..000000000 --- a/migration/v6/model/ruleset.go +++ /dev/null @@ -1,67 +0,0 @@ -package model - -import "gorm.io/gorm" - -// -// RuleSet - Analysis ruleset. -type RuleSet struct { - Model - Kind string - Name string `gorm:"uniqueIndex;not null"` - Description string - Custom bool - Repository JSON `gorm:"type:json"` - ImageID uint `gorm:"index" ref:"file"` - Image *File - IdentityID *uint `gorm:"index"` - Identity *Identity - Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` - DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` -} - -// -// BeforeUpdate hook to avoid cyclic dependencies. -func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { - seen := make(map[uint]bool) - var nextDeps []RuleSet - var nextRuleSetIDs []uint - for _, dep := range r.DependsOn { - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - for len(nextRuleSetIDs) != 0 { - result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) - if result.Error != nil { - err = result.Error - return - } - nextRuleSetIDs = nextRuleSetIDs[:0] - for _, nextDep := range nextDeps { - for _, dep := range nextDep.DependsOn { - if seen[dep.ID] { - continue - } - if dep.ID == r.ID { - err = DependencyCyclicError{} - return - } - seen[dep.ID] = true - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - } - } - - return -} - -// -// Rule - Analysis rule. -type Rule struct { - Model - Name string - Description string - Labels JSON `gorm:"type:json"` - RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` - RuleSet *RuleSet - FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` - File *File -} diff --git a/migration/v6/model/task.go b/migration/v6/model/task.go deleted file mode 100644 index c74f45db7..000000000 --- a/migration/v6/model/task.go +++ /dev/null @@ -1,92 +0,0 @@ -package model - -import ( - "encoding/json" - "fmt" - "gorm.io/gorm" - "time" -) - -type Task struct { - Model - BucketOwner - Name string `gorm:"index"` - Addon string `gorm:"index"` - Locator string `gorm:"index"` - Priority int - Image string - Variant string - Policy string - TTL JSON - Data JSON - Started *time.Time - Terminated *time.Time - State string `gorm:"index"` - Errors JSON - Pod string `gorm:"index"` - Retries int - Canceled bool - Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` - ApplicationID *uint - Application *Application - TaskGroupID *uint `gorm:"<-:create"` - TaskGroup *TaskGroup -} - -func (m *Task) Reset() { - m.Started = nil - m.Terminated = nil - m.Report = nil - m.Errors = nil -} - -func (m *Task) BeforeCreate(db *gorm.DB) (err error) { - err = m.BucketOwner.BeforeCreate(db) - m.Reset() - return -} - -// -// Error appends an error. -func (m *Task) Error(severity, description string, x ...interface{}) { - var list []TaskError - description = fmt.Sprintf(description, x...) - te := TaskError{Severity: severity, Description: description} - _ = json.Unmarshal(m.Errors, &list) - list = append(list, te) - m.Errors, _ = json.Marshal(list) -} - -// -// Map alias. -type Map = map[string]interface{} - -// -// TTL time-to-live. -type TTL struct { - Created int `json:"created,omitempty"` - Pending int `json:"pending,omitempty"` - Postponed int `json:"postponed,omitempty"` - Running int `json:"running,omitempty"` - Succeeded int `json:"succeeded,omitempty"` - Failed int `json:"failed,omitempty"` -} - -// -// TaskError used in Task.Errors. -type TaskError struct { - Severity string `json:"severity"` - Description string `json:"description"` -} - -type TaskReport struct { - Model - Status string - Errors JSON - Total int - Completed int - Activity JSON `gorm:"type:json"` - Result JSON `gorm:"type:json"` - TaskID uint `gorm:"<-:create;uniqueIndex"` - Task *Task -} diff --git a/migration/v6/model/taskgroup.go b/migration/v6/model/taskgroup.go deleted file mode 100644 index cc61ce221..000000000 --- a/migration/v6/model/taskgroup.go +++ /dev/null @@ -1,91 +0,0 @@ -package model - -import ( - "encoding/json" - liberr "github.com/jortel/go-utils/error" -) - -type TaskGroup struct { - Model - BucketOwner - Name string - Addon string - Data JSON - Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` - List JSON - State string -} - -// -// Propagate group data into the task. -func (m *TaskGroup) Propagate() (err error) { - for i := range m.Tasks { - task := &m.Tasks[i] - task.State = m.State - task.SetBucket(m.BucketID) - if task.Addon == "" { - task.Addon = m.Addon - } - if m.Data == nil { - continue - } - a := Map{} - err = json.Unmarshal(m.Data, &a) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - b := Map{} - err = json.Unmarshal(task.Data, &b) - if err != nil { - err = liberr.Wrap( - err, - "id", - m.ID) - return - } - task.Data, _ = json.Marshal(m.merge(a, b)) - } - - return -} - -// -// merge maps B into A. -// The B map is the authority. -func (m *TaskGroup) merge(a, b Map) (out Map) { - if a == nil { - a = Map{} - } - if b == nil { - b = Map{} - } - out = Map{} - // - // Merge-in elements found in B and in A. - for k, v := range a { - out[k] = v - if bv, found := b[k]; found { - out[k] = bv - if av, cast := v.(Map); cast { - if bv, cast := bv.(Map); cast { - out[k] = m.merge(av, bv) - } else { - out[k] = bv - } - } - } - } - // - // Add elements found only in B. - for k, v := range b { - if _, found := a[k]; !found { - out[k] = v - } - } - - return -} diff --git a/migration/v7/model/analysis.go b/migration/v7/model/analysis.go new file mode 100644 index 000000000..a3f1ea1f2 --- /dev/null +++ b/migration/v7/model/analysis.go @@ -0,0 +1,131 @@ +package model + +import "gorm.io/gorm" + +// +// Analysis report. +type Analysis struct { + Model + Effort int + Issues []Issue `gorm:"constraint:OnDelete:CASCADE"` + Dependencies []TechDependency `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID uint `gorm:"index;not null"` + Application *Application +} + +// +// TechDependency report dependency. +type TechDependency struct { + Model + Provider string `gorm:"uniqueIndex:depA"` + Name string `gorm:"uniqueIndex:depA"` + Version string `gorm:"uniqueIndex:depA"` + SHA string `gorm:"uniqueIndex:depA"` + Indirect bool + Labels JSON `gorm:"type:json"` + AnalysisID uint `gorm:"index;uniqueIndex:depA;not null"` + Analysis *Analysis +} + +// +// Issue report issue (violation). +type Issue struct { + Model + RuleSet string `gorm:"uniqueIndex:issueA;not null"` + Rule string `gorm:"uniqueIndex:issueA;not null"` + Name string `gorm:"index"` + Description string + Category string `gorm:"index;not null"` + Incidents []Incident `gorm:"foreignKey:IssueID;constraint:OnDelete:CASCADE"` + Links JSON `gorm:"type:json"` + Facts JSON `gorm:"type:json"` + Labels JSON `gorm:"type:json"` + Effort int `gorm:"index;not null"` + AnalysisID uint `gorm:"index;uniqueIndex:issueA;not null"` + Analysis *Analysis +} + +// +// Incident report an issue incident. +type Incident struct { + Model + File string `gorm:"index;not null"` + Line int + Message string + CodeSnip string + Facts JSON `gorm:"type:json"` + IssueID uint `gorm:"index;not null"` + Issue *Issue +} + +// +// Link URL link. +type Link struct { + URL string `json:"url"` + Title string `json:"title,omitempty"` +} + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + UUID *string `gorm:"uniqueIndex"` + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Custom bool + Repository JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` + DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` +} + +// +// BeforeUpdate hook to avoid cyclic dependencies. +func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { + seen := make(map[uint]bool) + var nextDeps []RuleSet + var nextRuleSetIDs []uint + for _, dep := range r.DependsOn { + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + for len(nextRuleSetIDs) != 0 { + result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) + if result.Error != nil { + err = result.Error + return + } + nextRuleSetIDs = nextRuleSetIDs[:0] + for _, nextDep := range nextDeps { + for _, dep := range nextDep.DependsOn { + if seen[dep.ID] { + continue + } + if dep.ID == r.ID { + err = DependencyCyclicError{} + return + } + seen[dep.ID] = true + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + } + } + + return +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} diff --git a/migration/v7/model/application.go b/migration/v7/model/application.go index fa1f5566b..f604ccfe0 100644 --- a/migration/v7/model/application.go +++ b/migration/v7/model/application.go @@ -1,5 +1,12 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + type Application struct { Model BucketOwner @@ -23,3 +30,254 @@ type Application struct { MigrationWave *MigrationWave Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` } + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + UUID *string `gorm:"uniqueIndex"` + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v7/model/applicationtag.go b/migration/v7/model/applicationtag.go deleted file mode 100644 index d6cb5974d..000000000 --- a/migration/v7/model/applicationtag.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -// -// ApplicationTag represents a row in the join table for the -// many-to-many relationship between Applications and Tags. -type ApplicationTag struct { - ApplicationID uint `gorm:"primaryKey"` - TagID uint `gorm:"primaryKey"` - Source string `gorm:"primaryKey;not null"` - Application Application `gorm:"constraint:OnDelete:CASCADE"` - Tag Tag `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// TableName must return "ApplicationTags" to ensure compatibility -// with the autogenerated join table name. -func (ApplicationTag) TableName() string { - return "ApplicationTags" -} diff --git a/migration/v7/model/assessment.go b/migration/v7/model/assessment.go new file mode 100644 index 000000000..e4936d2c6 --- /dev/null +++ b/migration/v7/model/assessment.go @@ -0,0 +1,12 @@ +package model + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID uint `gorm:"uniqueIndex"` + Application *Application +} diff --git a/migration/v7/model/businessservice.go b/migration/v7/model/businessservice.go deleted file mode 100644 index 2eb888546..000000000 --- a/migration/v7/model/businessservice.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type BusinessService struct { - Model - Name string `gorm:"index;unique;not null"` - Description string - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - StakeholderID *uint `gorm:"index"` - Stakeholder *Stakeholder -} diff --git a/migration/v7/model/core.go b/migration/v7/model/core.go new file mode 100644 index 000000000..c18e5663e --- /dev/null +++ b/migration/v7/model/core.go @@ -0,0 +1,357 @@ +package model + +import ( + "encoding/json" + "fmt" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Errors JSON + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil + m.Errors = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Error appends an error. +func (m *Task) Error(severity, description string, x ...interface{}) { + var list []TaskError + description = fmt.Sprintf(description, x...) + te := TaskError{Severity: severity, Description: description} + _ = json.Unmarshal(m.Errors, &list) + list = append(list, te) + m.Errors, _ = json.Marshal(list) +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +// +// TaskError used in Task.Errors. +type TaskError struct { + Severity string `json:"severity"` + Description string `json:"description"` +} + +type TaskReport struct { + Model + Status string + Errors JSON + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v7/model/jobfunction.go b/migration/v7/model/jobfunction.go deleted file mode 100644 index d8fc8438c..000000000 --- a/migration/v7/model/jobfunction.go +++ /dev/null @@ -1,9 +0,0 @@ -package model - -type JobFunction struct { - Model - UUID *string `gorm:"uniqueIndex"` - Username string - Name string `gorm:"index;unique;not null"` - Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` -} diff --git a/migration/v7/model/migrationwave.go b/migration/v7/model/migrationwave.go deleted file mode 100644 index 8cec17fee..000000000 --- a/migration/v7/model/migrationwave.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -import "time" - -type MigrationWave struct { - Model - Name string `gorm:"uniqueIndex:MigrationWaveA"` - StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` - StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v7/model/pkg.go b/migration/v7/model/pkg.go index b179224ab..111324a64 100644 --- a/migration/v7/model/pkg.go +++ b/migration/v7/model/pkg.go @@ -1,35 +1,14 @@ package model -import "github.com/konveyor/tackle2-hub/migration/v6/model" +import "github.com/konveyor/tackle2-hub/settings" // // JSON field (data) type. type JSON = []byte -type Model = model.Model -type TechDependency = model.TechDependency -type Incident = model.Incident -type Analysis = model.Analysis -type Issue = model.Issue -type Bucket = model.Bucket -type BucketOwner = model.BucketOwner -type Dependency = model.Dependency -type File = model.File -type Fact = model.Fact -type Identity = model.Identity -type Import = model.Import -type ImportSummary = model.ImportSummary -type ImportTag = model.ImportTag -type Proxy = model.Proxy -type Review = model.Review -type Setting = model.Setting -type Task = model.Task -type TaskGroup = model.TaskGroup -type TaskReport = model.TaskReport -type Ticket = model.Ticket -type Tracker = model.Tracker -type TTL = model.TTL -type DependencyCyclicError = model.DependencyCyclicError +var ( + Settings = &settings.Settings +) // // All builds all models. diff --git a/migration/v7/model/ruleset.go b/migration/v7/model/ruleset.go deleted file mode 100644 index b40d56993..000000000 --- a/migration/v7/model/ruleset.go +++ /dev/null @@ -1,68 +0,0 @@ -package model - -import "gorm.io/gorm" - -// -// RuleSet - Analysis ruleset. -type RuleSet struct { - Model - UUID *string `gorm:"uniqueIndex"` - Kind string - Name string `gorm:"uniqueIndex;not null"` - Description string - Custom bool - Repository JSON `gorm:"type:json"` - ImageID uint `gorm:"index" ref:"file"` - Image *File - IdentityID *uint `gorm:"index"` - Identity *Identity - Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` - DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` -} - -// -// BeforeUpdate hook to avoid cyclic dependencies. -func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { - seen := make(map[uint]bool) - var nextDeps []RuleSet - var nextRuleSetIDs []uint - for _, dep := range r.DependsOn { - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - for len(nextRuleSetIDs) != 0 { - result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) - if result.Error != nil { - err = result.Error - return - } - nextRuleSetIDs = nextRuleSetIDs[:0] - for _, nextDep := range nextDeps { - for _, dep := range nextDep.DependsOn { - if seen[dep.ID] { - continue - } - if dep.ID == r.ID { - err = DependencyCyclicError{} - return - } - seen[dep.ID] = true - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - } - } - - return -} - -// -// Rule - Analysis rule. -type Rule struct { - Model - Name string - Description string - Labels JSON `gorm:"type:json"` - RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` - RuleSet *RuleSet - FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` - File *File -} diff --git a/migration/v7/model/stakeholder.go b/migration/v7/model/stakeholder.go deleted file mode 100644 index 66243f8f7..000000000 --- a/migration/v7/model/stakeholder.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Stakeholder struct { - Model - Name string `gorm:"not null;"` - Email string `gorm:"index;unique;not null"` - Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` - JobFunctionID *uint `gorm:"index"` - JobFunction *JobFunction - Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` - Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v7/model/stakeholdergroup.go b/migration/v7/model/stakeholdergroup.go deleted file mode 100644 index 384373cd0..000000000 --- a/migration/v7/model/stakeholdergroup.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type StakeholderGroup struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Description string - Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v7/model/tag.go b/migration/v7/model/tag.go deleted file mode 100644 index 80c8aa1ba..000000000 --- a/migration/v7/model/tag.go +++ /dev/null @@ -1,10 +0,0 @@ -package model - -type Tag struct { - Model - UUID *string `gorm:"uniqueIndex"` - Name string `gorm:"uniqueIndex:tagA;not null"` - Username string - CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` - Category TagCategory -} diff --git a/migration/v7/model/tagcategory.go b/migration/v7/model/tagcategory.go deleted file mode 100644 index cd9ac559b..000000000 --- a/migration/v7/model/tagcategory.go +++ /dev/null @@ -1,11 +0,0 @@ -package model - -type TagCategory struct { - Model - UUID *string `gorm:"uniqueIndex"` - Name string `gorm:"index;unique;not null"` - Username string - Rank uint - Color string - Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v8/model/analysis.go b/migration/v8/model/analysis.go new file mode 100644 index 000000000..3c9e2e52e --- /dev/null +++ b/migration/v8/model/analysis.go @@ -0,0 +1,151 @@ +package model + +import "gorm.io/gorm" + +// +// Analysis report. +type Analysis struct { + Model + Effort int + Issues []Issue `gorm:"constraint:OnDelete:CASCADE"` + Dependencies []TechDependency `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID uint `gorm:"index;not null"` + Application *Application +} + +// +// TechDependency report dependency. +type TechDependency struct { + Model + Provider string `gorm:"uniqueIndex:depA"` + Name string `gorm:"uniqueIndex:depA"` + Version string `gorm:"uniqueIndex:depA"` + SHA string `gorm:"uniqueIndex:depA"` + Indirect bool + Labels JSON `gorm:"type:json"` + AnalysisID uint `gorm:"index;uniqueIndex:depA;not null"` + Analysis *Analysis +} + +// +// Issue report issue (violation). +type Issue struct { + Model + RuleSet string `gorm:"uniqueIndex:issueA;not null"` + Rule string `gorm:"uniqueIndex:issueA;not null"` + Name string `gorm:"index"` + Description string + Category string `gorm:"index;not null"` + Incidents []Incident `gorm:"foreignKey:IssueID;constraint:OnDelete:CASCADE"` + Links JSON `gorm:"type:json"` + Facts JSON `gorm:"type:json"` + Labels JSON `gorm:"type:json"` + Effort int `gorm:"index;not null"` + AnalysisID uint `gorm:"index;uniqueIndex:issueA;not null"` + Analysis *Analysis +} + +// +// Incident report an issue incident. +type Incident struct { + Model + File string `gorm:"index;not null"` + Line int + Message string + CodeSnip string + Facts JSON `gorm:"type:json"` + IssueID uint `gorm:"index;not null"` + Issue *Issue +} + +// +// Link URL link. +type Link struct { + URL string `json:"url"` + Title string `json:"title,omitempty"` +} + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + UUID *string `gorm:"uniqueIndex"` + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Repository JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` + DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` +} + +func (r *RuleSet) Builtin() bool { + return r.UUID != nil +} + +// +// BeforeUpdate hook to avoid cyclic dependencies. +func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { + seen := make(map[uint]bool) + var nextDeps []RuleSet + var nextRuleSetIDs []uint + for _, dep := range r.DependsOn { + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + for len(nextRuleSetIDs) != 0 { + result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) + if result.Error != nil { + err = result.Error + return + } + nextRuleSetIDs = nextRuleSetIDs[:0] + for _, nextDep := range nextDeps { + for _, dep := range nextDep.DependsOn { + if seen[dep.ID] { + continue + } + if dep.ID == r.ID { + err = DependencyCyclicError{} + return + } + seen[dep.ID] = true + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + } + } + + return +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} + +// +// Target - analysis rule selector. +type Target struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex;not null"` + Description string + Choice bool + Labels JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + RuleSetID *uint `gorm:"index"` + RuleSet *RuleSet +} + +func (r *Target) Builtin() bool { + return r.UUID != nil +} diff --git a/migration/v8/model/application.go b/migration/v8/model/application.go new file mode 100644 index 000000000..f604ccfe0 --- /dev/null +++ b/migration/v8/model/application.go @@ -0,0 +1,283 @@ +package model + +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + +type Application struct { + Model + BucketOwner + Name string `gorm:"index;unique;not null"` + Description string + Review *Review `gorm:"constraint:OnDelete:CASCADE"` + Repository JSON `gorm:"type:json"` + Binary string + Facts []Fact `gorm:"constraint:OnDelete:CASCADE"` + Comments string + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + Tags []Tag `gorm:"many2many:ApplicationTags"` + Identities []Identity `gorm:"many2many:ApplicationIdentity;constraint:OnDelete:CASCADE"` + BusinessServiceID *uint `gorm:"index"` + BusinessService *BusinessService + OwnerID *uint `gorm:"index"` + Owner *Stakeholder `gorm:"foreignKey:OwnerID"` + Contributors []Stakeholder `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + Analyses []Analysis `gorm:"constraint:OnDelete:CASCADE"` + MigrationWaveID *uint `gorm:"index"` + MigrationWave *MigrationWave + Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` +} + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + UUID *string `gorm:"uniqueIndex"` + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v8/model/assessment.go b/migration/v8/model/assessment.go new file mode 100644 index 000000000..e4936d2c6 --- /dev/null +++ b/migration/v8/model/assessment.go @@ -0,0 +1,12 @@ +package model + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID uint `gorm:"uniqueIndex"` + Application *Application +} diff --git a/migration/v8/model/core.go b/migration/v8/model/core.go new file mode 100644 index 000000000..c18e5663e --- /dev/null +++ b/migration/v8/model/core.go @@ -0,0 +1,357 @@ +package model + +import ( + "encoding/json" + "fmt" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Errors JSON + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil + m.Errors = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Error appends an error. +func (m *Task) Error(severity, description string, x ...interface{}) { + var list []TaskError + description = fmt.Sprintf(description, x...) + te := TaskError{Severity: severity, Description: description} + _ = json.Unmarshal(m.Errors, &list) + list = append(list, te) + m.Errors, _ = json.Marshal(list) +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +// +// TaskError used in Task.Errors. +type TaskError struct { + Severity string `json:"severity"` + Description string `json:"description"` +} + +type TaskReport struct { + Model + Status string + Errors JSON + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v8/model/pkg.go b/migration/v8/model/pkg.go index 269614bed..615ee9e66 100644 --- a/migration/v8/model/pkg.go +++ b/migration/v8/model/pkg.go @@ -1,44 +1,14 @@ package model -import "github.com/konveyor/tackle2-hub/migration/v7/model" +import "github.com/konveyor/tackle2-hub/settings" // // JSON field (data) type. type JSON = []byte -type Model = model.Model -type Application = model.Application -type TechDependency = model.TechDependency -type Incident = model.Incident -type Analysis = model.Analysis -type Issue = model.Issue -type Bucket = model.Bucket -type BucketOwner = model.BucketOwner -type BusinessService = model.BusinessService -type Dependency = model.Dependency -type File = model.File -type Fact = model.Fact -type Identity = model.Identity -type Import = model.Import -type ImportSummary = model.ImportSummary -type ImportTag = model.ImportTag -type JobFunction = model.JobFunction -type MigrationWave = model.MigrationWave -type Proxy = model.Proxy -type Review = model.Review -type Setting = model.Setting -type Stakeholder = model.Stakeholder -type StakeholderGroup = model.StakeholderGroup -type Tag = model.Tag -type TagCategory = model.TagCategory -type Task = model.Task -type TaskGroup = model.TaskGroup -type TaskReport = model.TaskReport -type Ticket = model.Ticket -type Tracker = model.Tracker -type TTL = model.TTL -type ApplicationTag = model.ApplicationTag -type DependencyCyclicError = model.DependencyCyclicError +var ( + Settings = &settings.Settings +) // // All builds all models. diff --git a/migration/v8/model/ruleset.go b/migration/v8/model/ruleset.go deleted file mode 100644 index 4edf0c021..000000000 --- a/migration/v8/model/ruleset.go +++ /dev/null @@ -1,69 +0,0 @@ -package model - -import "gorm.io/gorm" - -// -// RuleSet - Analysis ruleset. -type RuleSet struct { - Model - UUID *string `gorm:"uniqueIndex"` - Kind string - Name string `gorm:"uniqueIndex;not null"` - Description string - Repository JSON `gorm:"type:json"` - IdentityID *uint `gorm:"index"` - Identity *Identity - Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` - DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` -} - -func (r *RuleSet) Builtin() bool { - return r.UUID != nil -} - -// -// BeforeUpdate hook to avoid cyclic dependencies. -func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { - seen := make(map[uint]bool) - var nextDeps []RuleSet - var nextRuleSetIDs []uint - for _, dep := range r.DependsOn { - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - for len(nextRuleSetIDs) != 0 { - result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) - if result.Error != nil { - err = result.Error - return - } - nextRuleSetIDs = nextRuleSetIDs[:0] - for _, nextDep := range nextDeps { - for _, dep := range nextDep.DependsOn { - if seen[dep.ID] { - continue - } - if dep.ID == r.ID { - err = DependencyCyclicError{} - return - } - seen[dep.ID] = true - nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) - } - } - } - - return -} - -// -// Rule - Analysis rule. -type Rule struct { - Model - Name string - Description string - Labels JSON `gorm:"type:json"` - RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` - RuleSet *RuleSet - FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` - File *File -} diff --git a/migration/v8/model/target.go b/migration/v8/model/target.go deleted file mode 100644 index f6e0dfe54..000000000 --- a/migration/v8/model/target.go +++ /dev/null @@ -1,20 +0,0 @@ -package model - -// -// Target - analysis rule selector. -type Target struct { - Model - UUID *string `gorm:"uniqueIndex"` - Name string `gorm:"uniqueIndex;not null"` - Description string - Choice bool - Labels JSON `gorm:"type:json"` - ImageID uint `gorm:"index" ref:"file"` - Image *File - RuleSetID *uint `gorm:"index"` - RuleSet *RuleSet -} - -func (r *Target) Builtin() bool { - return r.UUID != nil -} diff --git a/migration/v9/model/analysis.go b/migration/v9/model/analysis.go new file mode 100644 index 000000000..3c9e2e52e --- /dev/null +++ b/migration/v9/model/analysis.go @@ -0,0 +1,151 @@ +package model + +import "gorm.io/gorm" + +// +// Analysis report. +type Analysis struct { + Model + Effort int + Issues []Issue `gorm:"constraint:OnDelete:CASCADE"` + Dependencies []TechDependency `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID uint `gorm:"index;not null"` + Application *Application +} + +// +// TechDependency report dependency. +type TechDependency struct { + Model + Provider string `gorm:"uniqueIndex:depA"` + Name string `gorm:"uniqueIndex:depA"` + Version string `gorm:"uniqueIndex:depA"` + SHA string `gorm:"uniqueIndex:depA"` + Indirect bool + Labels JSON `gorm:"type:json"` + AnalysisID uint `gorm:"index;uniqueIndex:depA;not null"` + Analysis *Analysis +} + +// +// Issue report issue (violation). +type Issue struct { + Model + RuleSet string `gorm:"uniqueIndex:issueA;not null"` + Rule string `gorm:"uniqueIndex:issueA;not null"` + Name string `gorm:"index"` + Description string + Category string `gorm:"index;not null"` + Incidents []Incident `gorm:"foreignKey:IssueID;constraint:OnDelete:CASCADE"` + Links JSON `gorm:"type:json"` + Facts JSON `gorm:"type:json"` + Labels JSON `gorm:"type:json"` + Effort int `gorm:"index;not null"` + AnalysisID uint `gorm:"index;uniqueIndex:issueA;not null"` + Analysis *Analysis +} + +// +// Incident report an issue incident. +type Incident struct { + Model + File string `gorm:"index;not null"` + Line int + Message string + CodeSnip string + Facts JSON `gorm:"type:json"` + IssueID uint `gorm:"index;not null"` + Issue *Issue +} + +// +// Link URL link. +type Link struct { + URL string `json:"url"` + Title string `json:"title,omitempty"` +} + +// +// RuleSet - Analysis ruleset. +type RuleSet struct { + Model + UUID *string `gorm:"uniqueIndex"` + Kind string + Name string `gorm:"uniqueIndex;not null"` + Description string + Repository JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity + Rules []Rule `gorm:"constraint:OnDelete:CASCADE"` + DependsOn []RuleSet `gorm:"many2many:RuleSetDependencies;constraint:OnDelete:CASCADE"` +} + +func (r *RuleSet) Builtin() bool { + return r.UUID != nil +} + +// +// BeforeUpdate hook to avoid cyclic dependencies. +func (r *RuleSet) BeforeUpdate(db *gorm.DB) (err error) { + seen := make(map[uint]bool) + var nextDeps []RuleSet + var nextRuleSetIDs []uint + for _, dep := range r.DependsOn { + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + for len(nextRuleSetIDs) != 0 { + result := db.Preload("DependsOn").Where("ID IN ?", nextRuleSetIDs).Find(&nextDeps) + if result.Error != nil { + err = result.Error + return + } + nextRuleSetIDs = nextRuleSetIDs[:0] + for _, nextDep := range nextDeps { + for _, dep := range nextDep.DependsOn { + if seen[dep.ID] { + continue + } + if dep.ID == r.ID { + err = DependencyCyclicError{} + return + } + seen[dep.ID] = true + nextRuleSetIDs = append(nextRuleSetIDs, dep.ID) + } + } + } + + return +} + +// +// Rule - Analysis rule. +type Rule struct { + Model + Name string + Description string + Labels JSON `gorm:"type:json"` + RuleSetID uint `gorm:"uniqueIndex:RuleA;not null"` + RuleSet *RuleSet + FileID *uint `gorm:"uniqueIndex:RuleA" ref:"file"` + File *File +} + +// +// Target - analysis rule selector. +type Target struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex;not null"` + Description string + Choice bool + Labels JSON `gorm:"type:json"` + ImageID uint `gorm:"index" ref:"file"` + Image *File + RuleSetID *uint `gorm:"index"` + RuleSet *RuleSet +} + +func (r *Target) Builtin() bool { + return r.UUID != nil +} diff --git a/migration/v9/model/application.go b/migration/v9/model/application.go index b9673835f..64e1e52a2 100644 --- a/migration/v9/model/application.go +++ b/migration/v9/model/application.go @@ -1,5 +1,12 @@ package model +import ( + "fmt" + "gorm.io/gorm" + "sync" + "time" +) + type Application struct { Model BucketOwner @@ -24,3 +31,271 @@ type Application struct { Ticket *Ticket `gorm:"constraint:OnDelete:CASCADE"` Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` } + +type Fact struct { + ApplicationID uint `gorm:"<-:create;primaryKey"` + Key string `gorm:"<-:create;primaryKey"` + Source string `gorm:"<-:create;primaryKey;not null"` + Value JSON `gorm:"type:json;not null"` + Application *Application +} + +// +// ApplicationTag represents a row in the join table for the +// many-to-many relationship between Applications and Tags. +type ApplicationTag struct { + ApplicationID uint `gorm:"primaryKey"` + TagID uint `gorm:"primaryKey"` + Source string `gorm:"primaryKey;not null"` + Application Application `gorm:"constraint:OnDelete:CASCADE"` + Tag Tag `gorm:"constraint:OnDelete:CASCADE"` +} + +// +// TableName must return "ApplicationTags" to ensure compatibility +// with the autogenerated join table name. +func (ApplicationTag) TableName() string { + return "ApplicationTags" +} + +// +// depMutex ensures Dependency.Create() is not executed concurrently. +var depMutex sync.Mutex + +type Dependency struct { + Model + ToID uint `gorm:"index"` + To *Application `gorm:"foreignKey:ToID;constraint:OnDelete:CASCADE"` + FromID uint `gorm:"index"` + From *Application `gorm:"foreignKey:FromID;constraint:OnDelete:CASCADE"` +} + +// +// Create a dependency synchronized using a mutex. +func (r *Dependency) Create(db *gorm.DB) (err error) { + depMutex.Lock() + defer depMutex.Unlock() + err = db.Create(r).Error + return +} + +// +// Validation Hook to avoid cyclic dependencies. +func (r *Dependency) BeforeCreate(db *gorm.DB) (err error) { + var nextDeps []*Dependency + var nextAppsIDs []uint + nextAppsIDs = append(nextAppsIDs, r.FromID) + for len(nextAppsIDs) != 0 { + db.Where("ToID IN ?", nextAppsIDs).Find(&nextDeps) + nextAppsIDs = nextAppsIDs[:0] // empty array, but keep capacity + for _, nextDep := range nextDeps { + if nextDep.FromID == r.ToID { + err = DependencyCyclicError{} + return + } + nextAppsIDs = append(nextAppsIDs, nextDep.FromID) + } + } + + return +} + +// +// Custom error type to allow API recognize Cyclic Dependency error and assign proper status code. +type DependencyCyclicError struct{} + +func (err DependencyCyclicError) Error() string { + return "cyclic dependencies are not allowed" +} + +type BusinessService struct { + Model + Name string `gorm:"index;unique;not null"` + Description string + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + StakeholderID *uint `gorm:"index"` + Stakeholder *Stakeholder +} + +type JobFunction struct { + Model + UUID *string `gorm:"uniqueIndex"` + Username string + Name string `gorm:"index;unique;not null"` + Stakeholders []Stakeholder `gorm:"constraint:OnDelete:SET NULL"` +} + +type Stakeholder struct { + Model + Name string `gorm:"not null;"` + Email string `gorm:"index;unique;not null"` + Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` + JobFunctionID *uint `gorm:"index"` + JobFunction *JobFunction + Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` + Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"many2many:AssessmentStakeholders;constraint:OnDelete:CASCADE"` + Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` +} + +type StakeholderGroup struct { + Model + Name string `gorm:"index;unique;not null"` + Username string + Description string + Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` + MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"many2many:AssessmentStakeholderGroups;constraint:OnDelete:CASCADE"` + Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type MigrationWave struct { + Model + Name string `gorm:"uniqueIndex:MigrationWaveA"` + StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` + Applications []Application `gorm:"constraint:OnDelete:SET NULL"` + Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Archetype struct { + Model + Name string + Description string + Comments string + Review *Review `gorm:"constraint:OnDelete:CASCADE"` + Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` + CriteriaTags []Tag `gorm:"many2many:ArchetypeCriteriaTags;constraint:OnDelete:CASCADE"` + Tags []Tag `gorm:"many2many:ArchetypeTags;constraint:OnDelete:CASCADE"` + Stakeholders []Stakeholder `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` + StakeholderGroups []StakeholderGroup `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` +} + +type Tag struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"uniqueIndex:tagA;not null"` + Username string + CategoryID uint `gorm:"uniqueIndex:tagA;index;not null"` + Category TagCategory +} + +type TagCategory struct { + Model + UUID *string `gorm:"uniqueIndex"` + Name string `gorm:"index;unique;not null"` + Username string + Rank uint + Color string + Tags []Tag `gorm:"foreignKey:CategoryID;constraint:OnDelete:CASCADE"` +} + +type Ticket struct { + Model + // Kind of ticket in the external tracker. + Kind string `gorm:"not null"` + // Parent resource that this ticket should belong to in the tracker. (e.g. Jira project) + Parent string `gorm:"not null"` + // Custom fields to send to the tracker when creating the ticket + Fields JSON `gorm:"type:json"` + // Whether the last attempt to do something with the ticket reported an error + Error bool + // Error message, if any + Message string + // Whether the ticket was created in the external tracker + Created bool + // Reference id in external tracker + Reference string + // URL to ticket in external tracker + Link string + // Status of ticket in external tracker + Status string + LastUpdated time.Time + Application *Application + ApplicationID uint `gorm:"uniqueIndex:ticketA;not null"` + Tracker *Tracker + TrackerID uint `gorm:"uniqueIndex:ticketA;not null"` +} + +type Tracker struct { + Model + Name string `gorm:"index;unique;not null"` + URL string + Kind string + Identity *Identity + IdentityID uint + Connected bool + LastUpdated time.Time + Message string + Insecure bool + Tickets []Ticket +} + +type Import struct { + Model + Filename string + ApplicationName string + BusinessService string + Comments string + Dependency string + DependencyDirection string + Description string + ErrorMessage string + IsValid bool + RecordType1 string + ImportSummary ImportSummary + ImportSummaryID uint `gorm:"index"` + Processed bool + ImportTags []ImportTag `gorm:"constraint:OnDelete:CASCADE"` + BinaryGroup string + BinaryArtifact string + BinaryVersion string + BinaryPackaging string + RepositoryKind string + RepositoryURL string + RepositoryBranch string + RepositoryPath string +} + +func (r *Import) AsMap() (m map[string]interface{}) { + m = make(map[string]interface{}) + m["filename"] = r.Filename + m["applicationName"] = r.ApplicationName + // "Application Name" is necessary in order for + // the UI to display the error report correctly. + m["Application Name"] = r.ApplicationName + m["businessService"] = r.BusinessService + m["comments"] = r.Comments + m["dependency"] = r.Dependency + m["dependencyDirection"] = r.DependencyDirection + m["description"] = r.Description + m["errorMessage"] = r.ErrorMessage + m["isValid"] = r.IsValid + m["processed"] = r.Processed + m["recordType1"] = r.RecordType1 + for i, tag := range r.ImportTags { + m[fmt.Sprintf("category%v", i+1)] = tag.Category + m[fmt.Sprintf("tag%v", i+1)] = tag.Name + } + return +} + +type ImportSummary struct { + Model + Content []byte + Filename string + ImportStatus string + Imports []Import `gorm:"constraint:OnDelete:CASCADE"` + CreateEntities bool +} + +type ImportTag struct { + Model + Name string + Category string + ImportID uint `gorm:"index"` + Import *Import +} diff --git a/migration/v9/model/applicationtag.go b/migration/v9/model/applicationtag.go deleted file mode 100644 index d6cb5974d..000000000 --- a/migration/v9/model/applicationtag.go +++ /dev/null @@ -1,19 +0,0 @@ -package model - -// -// ApplicationTag represents a row in the join table for the -// many-to-many relationship between Applications and Tags. -type ApplicationTag struct { - ApplicationID uint `gorm:"primaryKey"` - TagID uint `gorm:"primaryKey"` - Source string `gorm:"primaryKey;not null"` - Application Application `gorm:"constraint:OnDelete:CASCADE"` - Tag Tag `gorm:"constraint:OnDelete:CASCADE"` -} - -// -// TableName must return "ApplicationTags" to ensure compatibility -// with the autogenerated join table name. -func (ApplicationTag) TableName() string { - return "ApplicationTags" -} diff --git a/migration/v9/model/archetype.go b/migration/v9/model/archetype.go deleted file mode 100644 index 795732479..000000000 --- a/migration/v9/model/archetype.go +++ /dev/null @@ -1,14 +0,0 @@ -package model - -type Archetype struct { - Model - Name string - Description string - Comments string - Review *Review `gorm:"constraint:OnDelete:CASCADE"` - Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` - CriteriaTags []Tag `gorm:"many2many:ArchetypeCriteriaTags;constraint:OnDelete:CASCADE"` - Tags []Tag `gorm:"many2many:ArchetypeTags;constraint:OnDelete:CASCADE"` - Stakeholders []Stakeholder `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` - StakeholderGroups []StakeholderGroup `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v9/model/assessment.go b/migration/v9/model/assessment.go index 54bf99977..f3eeddfa0 100644 --- a/migration/v9/model/assessment.go +++ b/migration/v9/model/assessment.go @@ -26,3 +26,16 @@ type Assessment struct { Stakeholders []Stakeholder `gorm:"many2many:AssessmentStakeholders;constraint:OnDelete:CASCADE"` StakeholderGroups []StakeholderGroup `gorm:"many2many:AssessmentStakeholderGroups;constraint:OnDelete:CASCADE"` } + +type Review struct { + Model + BusinessCriticality uint `gorm:"not null"` + EffortEstimate string `gorm:"not null"` + ProposedAction string `gorm:"not null"` + WorkPriority uint `gorm:"not null"` + Comments string + ApplicationID *uint `gorm:"uniqueIndex"` + Application *Application + ArchetypeID *uint `gorm:"uniqueIndex"` + Archetype *Archetype +} diff --git a/migration/v9/model/core.go b/migration/v9/model/core.go new file mode 100644 index 000000000..c18e5663e --- /dev/null +++ b/migration/v9/model/core.go @@ -0,0 +1,357 @@ +package model + +import ( + "encoding/json" + "fmt" + "github.com/google/uuid" + liberr "github.com/jortel/go-utils/error" + "github.com/konveyor/tackle2-hub/encryption" + "gorm.io/gorm" + "os" + "path" + "time" +) + +// +// Model Base model. +type Model struct { + ID uint `gorm:"<-:create;primaryKey"` + CreateTime time.Time `gorm:"<-:create;autoCreateTime"` + CreateUser string `gorm:"<-:create"` + UpdateUser string +} + +type Setting struct { + Model + Key string `gorm:"<-:create;uniqueIndex"` + Value JSON `gorm:"type:json"` +} + +type Bucket struct { + Model + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *Bucket) BeforeCreate(db *gorm.DB) (err error) { + if m.Path == "" { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + uid.String()) + err = os.MkdirAll(m.Path, 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + } + return +} + +type BucketOwner struct { + BucketID *uint `gorm:"index" ref:"bucket"` + Bucket *Bucket +} + +func (m *BucketOwner) BeforeCreate(db *gorm.DB) (err error) { + if !m.HasBucket() { + b := &Bucket{} + err = db.Create(b).Error + m.SetBucket(&b.ID) + } + return +} + +func (m *BucketOwner) SetBucket(id *uint) { + m.BucketID = id + m.Bucket = nil +} + +func (m *BucketOwner) HasBucket() (b bool) { + return m.BucketID != nil +} + +type File struct { + Model + Name string + Path string `gorm:"<-:create;uniqueIndex"` + Expiration *time.Time +} + +func (m *File) BeforeCreate(db *gorm.DB) (err error) { + uid := uuid.New() + m.Path = path.Join( + Settings.Hub.Bucket.Path, + ".file", + uid.String()) + err = os.MkdirAll(path.Dir(m.Path), 0777) + if err != nil { + err = liberr.Wrap( + err, + "path", + m.Path) + } + return +} + +type Task struct { + Model + BucketOwner + Name string `gorm:"index"` + Addon string `gorm:"index"` + Locator string `gorm:"index"` + Priority int + Image string + Variant string + Policy string + TTL JSON + Data JSON + Started *time.Time + Terminated *time.Time + State string `gorm:"index"` + Errors JSON + Pod string `gorm:"index"` + Retries int + Canceled bool + Report *TaskReport `gorm:"constraint:OnDelete:CASCADE"` + ApplicationID *uint + Application *Application + TaskGroupID *uint `gorm:"<-:create"` + TaskGroup *TaskGroup +} + +func (m *Task) Reset() { + m.Started = nil + m.Terminated = nil + m.Report = nil + m.Errors = nil +} + +func (m *Task) BeforeCreate(db *gorm.DB) (err error) { + err = m.BucketOwner.BeforeCreate(db) + m.Reset() + return +} + +// +// Error appends an error. +func (m *Task) Error(severity, description string, x ...interface{}) { + var list []TaskError + description = fmt.Sprintf(description, x...) + te := TaskError{Severity: severity, Description: description} + _ = json.Unmarshal(m.Errors, &list) + list = append(list, te) + m.Errors, _ = json.Marshal(list) +} + +// +// Map alias. +type Map = map[string]interface{} + +// +// TTL time-to-live. +type TTL struct { + Created int `json:"created,omitempty"` + Pending int `json:"pending,omitempty"` + Postponed int `json:"postponed,omitempty"` + Running int `json:"running,omitempty"` + Succeeded int `json:"succeeded,omitempty"` + Failed int `json:"failed,omitempty"` +} + +// +// TaskError used in Task.Errors. +type TaskError struct { + Severity string `json:"severity"` + Description string `json:"description"` +} + +type TaskReport struct { + Model + Status string + Errors JSON + Total int + Completed int + Activity JSON `gorm:"type:json"` + Result JSON `gorm:"type:json"` + TaskID uint `gorm:"<-:create;uniqueIndex"` + Task *Task +} + +type TaskGroup struct { + Model + BucketOwner + Name string + Addon string + Data JSON + Tasks []Task `gorm:"constraint:OnDelete:CASCADE"` + List JSON + State string +} + +// +// Propagate group data into the task. +func (m *TaskGroup) Propagate() (err error) { + for i := range m.Tasks { + task := &m.Tasks[i] + task.State = m.State + task.SetBucket(m.BucketID) + if task.Addon == "" { + task.Addon = m.Addon + } + if m.Data == nil { + continue + } + a := Map{} + err = json.Unmarshal(m.Data, &a) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + b := Map{} + err = json.Unmarshal(task.Data, &b) + if err != nil { + err = liberr.Wrap( + err, + "id", + m.ID) + return + } + task.Data, _ = json.Marshal(m.merge(a, b)) + } + + return +} + +// +// merge maps B into A. +// The B map is the authority. +func (m *TaskGroup) merge(a, b Map) (out Map) { + if a == nil { + a = Map{} + } + if b == nil { + b = Map{} + } + out = Map{} + // + // Merge-in elements found in B and in A. + for k, v := range a { + out[k] = v + if bv, found := b[k]; found { + out[k] = bv + if av, cast := v.(Map); cast { + if bv, cast := bv.(Map); cast { + out[k] = m.merge(av, bv) + } else { + out[k] = bv + } + } + } + } + // + // Add elements found only in B. + for k, v := range b { + if _, found := a[k]; !found { + out[k] = v + } + } + + return +} + +// +// Proxy configuration. +// kind = (http|https) +type Proxy struct { + Model + Enabled bool + Kind string `gorm:"uniqueIndex"` + Host string `gorm:"not null"` + Port int + Excluded JSON `gorm:"type:json"` + IdentityID *uint `gorm:"index"` + Identity *Identity +} + +// Identity represents and identity with a set of credentials. +type Identity struct { + Model + Kind string `gorm:"not null"` + Name string `gorm:"index;unique;not null"` + Description string + User string + Password string + Key string + Settings string + Proxies []Proxy `gorm:"constraint:OnDelete:SET NULL"` +} + +// Encrypt sensitive fields. +// The ref identity is used to determine when sensitive fields +// have changed and need to be (re)encrypted. +func (r *Identity) Encrypt(ref *Identity) (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != ref.Password { + if r.Password != "" { + r.Password, err = aes.Encrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Key != ref.Key { + if r.Key != "" { + r.Key, err = aes.Encrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + if r.Settings != ref.Settings { + if r.Settings != "" { + r.Settings, err = aes.Encrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + } + return +} + +// Decrypt sensitive fields. +func (r *Identity) Decrypt() (err error) { + passphrase := Settings.Encryption.Passphrase + aes := encryption.New(passphrase) + if r.Password != "" { + r.Password, err = aes.Decrypt(r.Password) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Key != "" { + r.Key, err = aes.Decrypt(r.Key) + if err != nil { + err = liberr.Wrap(err) + return + } + } + if r.Settings != "" { + r.Settings, err = aes.Decrypt(r.Settings) + if err != nil { + err = liberr.Wrap(err) + return + } + } + return +} diff --git a/migration/v9/model/migrationwave.go b/migration/v9/model/migrationwave.go deleted file mode 100644 index 8cec17fee..000000000 --- a/migration/v9/model/migrationwave.go +++ /dev/null @@ -1,13 +0,0 @@ -package model - -import "time" - -type MigrationWave struct { - Model - Name string `gorm:"uniqueIndex:MigrationWaveA"` - StartDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - EndDate time.Time `gorm:"uniqueIndex:MigrationWaveA"` - Applications []Application `gorm:"constraint:OnDelete:SET NULL"` - Stakeholders []Stakeholder `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` - StakeholderGroups []StakeholderGroup `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v9/model/pkg.go b/migration/v9/model/pkg.go index fb1767a70..5bc918d1c 100644 --- a/migration/v9/model/pkg.go +++ b/migration/v9/model/pkg.go @@ -1,41 +1,14 @@ package model -import "github.com/konveyor/tackle2-hub/migration/v8/model" +import "github.com/konveyor/tackle2-hub/settings" // // JSON field (data) type. type JSON = []byte -type Model = model.Model -type TechDependency = model.TechDependency -type Incident = model.Incident -type Analysis = model.Analysis -type Issue = model.Issue -type Bucket = model.Bucket -type BucketOwner = model.BucketOwner -type BusinessService = model.BusinessService -type Dependency = model.Dependency -type File = model.File -type Fact = model.Fact -type Identity = model.Identity -type Import = model.Import -type ImportSummary = model.ImportSummary -type ImportTag = model.ImportTag -type JobFunction = model.JobFunction -type Proxy = model.Proxy -type Setting = model.Setting -type RuleSet = model.RuleSet -type Rule = model.Rule -type Tag = model.Tag -type TagCategory = model.TagCategory -type Target = model.Target -type Task = model.Task -type TaskGroup = model.TaskGroup -type TaskReport = model.TaskReport -type Ticket = model.Ticket -type Tracker = model.Tracker -type TTL = model.TTL -type DependencyCyclicError = model.DependencyCyclicError +var ( + Settings = &settings.Settings +) // // All builds all models. diff --git a/migration/v9/model/stakeholder.go b/migration/v9/model/stakeholder.go deleted file mode 100644 index ad347ba4b..000000000 --- a/migration/v9/model/stakeholder.go +++ /dev/null @@ -1,16 +0,0 @@ -package model - -type Stakeholder struct { - Model - Name string `gorm:"not null;"` - Email string `gorm:"index;unique;not null"` - Groups []StakeholderGroup `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - BusinessServices []BusinessService `gorm:"constraint:OnDelete:SET NULL"` - JobFunctionID *uint `gorm:"index"` - JobFunction *JobFunction - Owns []Application `gorm:"foreignKey:OwnerID;constraint:OnDelete:SET NULL"` - Contributes []Application `gorm:"many2many:ApplicationContributors;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholders;constraint:OnDelete:CASCADE"` - Assessments []Assessment `gorm:"many2many:AssessmentStakeholders;constraint:OnDelete:CASCADE"` - Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholders;constraint:OnDelete:CASCADE"` -} diff --git a/migration/v9/model/stakeholdergroup.go b/migration/v9/model/stakeholdergroup.go deleted file mode 100644 index 085bf4aac..000000000 --- a/migration/v9/model/stakeholdergroup.go +++ /dev/null @@ -1,12 +0,0 @@ -package model - -type StakeholderGroup struct { - Model - Name string `gorm:"index;unique;not null"` - Username string - Description string - Stakeholders []Stakeholder `gorm:"many2many:StakeholderGroupStakeholder;constraint:OnDelete:CASCADE"` - MigrationWaves []MigrationWave `gorm:"many2many:MigrationWaveStakeholderGroups;constraint:OnDelete:CASCADE"` - Assessments []Assessment `gorm:"many2many:AssessmentStakeholderGroups;constraint:OnDelete:CASCADE"` - Archetypes []Archetype `gorm:"many2many:ArchetypeStakeholderGroups;constraint:OnDelete:CASCADE"` -} From ff4b6755371919b7cab5f194751c5e2722f03267 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Wed, 4 Oct 2023 17:04:36 -0400 Subject: [PATCH 04/56] :sparkles: Surface assessment tags on Archetype resource (#502) * Use TagRefs on the Archetype resource * Add virtual tags inherited from assessments to the Tags field on the Archetype resource * Fixed a bug where an application would be denied membership in an archetype that wasn't a strict subset of another archetype. --------- Signed-off-by: Sam Lucidi --- api/archetype.go | 71 ++++++++++++++++++++++++++----------- api/base.go | 4 +-- assessment/archetype.go | 38 ++++++++++++++++++++ assessment/membership.go | 4 +-- assessment/questionnaire.go | 2 +- assessment/set.go | 15 +++++--- assessment/set_test.go | 46 ++++++++++++++++++++++++ 7 files changed, 150 insertions(+), 30 deletions(-) create mode 100644 assessment/archetype.go create mode 100644 assessment/set_test.go diff --git a/api/archetype.go b/api/archetype.go index 5218ebc6e..2388e0572 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -64,16 +64,24 @@ func (h ArchetypeHandler) Get(ctx *gin.Context) { return } - resolver, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) + questionnaires, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) if err != nil { _ = ctx.Error(err) return } + tags, err := assessment.NewTagResolver(h.DB(ctx)) + if err != nil { + _ = ctx.Error(err) + } + + resolver := assessment.NewArchetypeResolver(m, tags) + r := Archetype{} r.With(m) r.WithApplications(applications) - r.Assessed = resolver.Assessed(m.Assessments) + r.WithAssessmentTags(resolver.AssessmentTags()) + r.Assessed = questionnaires.Assessed(m.Assessments) h.Respond(ctx, http.StatusOK, r) } @@ -93,11 +101,15 @@ func (h ArchetypeHandler) List(ctx *gin.Context) { return } - resolver, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) + questionnaires, err := assessment.NewQuestionnaireResolver(h.DB(ctx)) if err != nil { _ = ctx.Error(err) return } + tags, err := assessment.NewTagResolver(h.DB(ctx)) + if err != nil { + _ = ctx.Error(err) + } membership := assessment.NewMembershipResolver(h.DB(ctx)) resources := []Archetype{} @@ -109,9 +121,11 @@ func (h ArchetypeHandler) List(ctx *gin.Context) { _ = ctx.Error(err) return } + resolver := assessment.NewArchetypeResolver(m, tags) r.With(m) r.WithApplications(applications) - r.Assessed = resolver.Assessed(m.Assessments) + r.WithAssessmentTags(resolver.AssessmentTags()) + r.Assessed = questionnaires.Assessed(m.Assessments) resources = append(resources, r) } @@ -326,17 +340,17 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) { // Archetype REST resource. type Archetype struct { Resource - Name string `json:"name" yaml:"name"` - Description string `json:"description" yaml:"description"` - Comments string `json:"comments" yaml:"comments"` - Tags []Ref `json:"tags" yaml:"tags"` - CriteriaTags []Ref `json:"criteriaTags" yaml:"criteriaTags"` - Stakeholders []Ref `json:"stakeholders" yaml:"stakeholders"` - StakeholderGroups []Ref `json:"stakeholderGroups" yaml:"stakeholderGroups"` - Applications []Ref `json:"applications" yaml:"applications"` - Assessments []Ref `json:"assessments" yaml:"assessments"` - Assessed bool `json:"assessed"` - Review *Ref `json:"review"` + Name string `json:"name" yaml:"name"` + Description string `json:"description" yaml:"description"` + Comments string `json:"comments" yaml:"comments"` + Tags []TagRef `json:"tags" yaml:"tags"` + Criteria []TagRef `json:"criteria" yaml:"criteria"` + Stakeholders []Ref `json:"stakeholders" yaml:"stakeholders"` + StakeholderGroups []Ref `json:"stakeholderGroups" yaml:"stakeholderGroups"` + Applications []Ref `json:"applications" yaml:"applications"` + Assessments []Ref `json:"assessments" yaml:"assessments"` + Assessed bool `json:"assessed"` + Review *Ref `json:"review"` } // @@ -346,13 +360,17 @@ func (r *Archetype) With(m *model.Archetype) { r.Name = m.Name r.Description = m.Description r.Comments = m.Comments - r.Tags = []Ref{} + r.Tags = []TagRef{} for _, t := range m.Tags { - r.Tags = append(r.Tags, r.ref(t.ID, &t)) + ref := TagRef{} + ref.With(t.ID, t.Name, "", false) + r.Tags = append(r.Tags, ref) } - r.CriteriaTags = []Ref{} + r.Criteria = []TagRef{} for _, t := range m.CriteriaTags { - r.CriteriaTags = append(r.CriteriaTags, r.ref(t.ID, &t)) + ref := TagRef{} + ref.With(t.ID, t.Name, "", false) + r.Criteria = append(r.Criteria, ref) } r.Stakeholders = []Ref{} for _, s := range m.Stakeholders { @@ -383,6 +401,16 @@ func (r *Archetype) WithApplications(apps []model.Application) { } } +// +// WithAssessmentTags updates the Archetype resource with tags inherited from assessments. +func (r *Archetype) WithAssessmentTags(tags []model.Tag) { + for _, t := range tags { + ref := TagRef{} + ref.With(t.ID, t.Name, SourceAssessment, true) + r.Tags = append(r.Tags, ref) + } +} + // // Model builds a model from the resource. func (r *Archetype) Model() (m *model.Archetype) { @@ -393,6 +421,9 @@ func (r *Archetype) Model() (m *model.Archetype) { } m.ID = r.ID for _, ref := range r.Tags { + if ref.Virtual { + continue + } m.Tags = append( m.Tags, model.Tag{ @@ -401,7 +432,7 @@ func (r *Archetype) Model() (m *model.Archetype) { }, }) } - for _, ref := range r.CriteriaTags { + for _, ref := range r.Criteria { m.CriteriaTags = append( m.CriteriaTags, model.Tag{ diff --git a/api/base.go b/api/base.go index 260836f8b..5e0c9607e 100644 --- a/api/base.go +++ b/api/base.go @@ -372,8 +372,8 @@ func (r *Ref) With(id uint, name string) { type TagRef struct { ID uint `json:"id" binding:"required"` Name string `json:"name"` - Source string `json:"source"` - Virtual bool `json:"virtual,omitempty"` + Source string `json:"source,omitempty" yaml:"source,omitempty"` + Virtual bool `json:"virtual,omitempty" yaml:"virtual,omitempty"` } // diff --git a/assessment/archetype.go b/assessment/archetype.go new file mode 100644 index 000000000..550330d25 --- /dev/null +++ b/assessment/archetype.go @@ -0,0 +1,38 @@ +package assessment + +import "github.com/konveyor/tackle2-hub/model" + +// +// NewArchetypeResolver creates a new ArchetypeResolver. +func NewArchetypeResolver(archetype *model.Archetype, tags *TagResolver) (a *ArchetypeResolver) { + a = &ArchetypeResolver{ + archetype: archetype, + tagResolver: tags, + } + return +} + +// +// ArchetypeResolver wraps an Archetype model +// with assessment-related functionality. +type ArchetypeResolver struct { + archetype *model.Archetype + tagResolver *TagResolver +} + +// +// AssessmentTags returns the list of tags that the archetype should +// inherit from the answers given to its assessments. +func (r *ArchetypeResolver) AssessmentTags() (tags []model.Tag) { + seenTags := make(map[uint]bool) + for _, assessment := range r.archetype.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 +} diff --git a/assessment/membership.go b/assessment/membership.go index e6eeee83a..2119e0011 100644 --- a/assessment/membership.go +++ b/assessment/membership.go @@ -54,7 +54,7 @@ func (r *MembershipResolver) Archetypes(m *model.Application) (archetypes []mode matches := []model.Archetype{} for _, a := range r.archetypes { - if appTags.Superset(r.tagSets[a.ID]) { + if appTags.Superset(r.tagSets[a.ID], false) { matches = append(matches, a) } } @@ -69,7 +69,7 @@ loop: } a1tags := r.tagSets[a1.ID] a2tags := r.tagSets[a2.ID] - if a1tags.Subset(a2tags) { + if a1tags.Subset(a2tags, true) { continue loop } } diff --git a/assessment/questionnaire.go b/assessment/questionnaire.go index d1fa86d01..c1e1a3a49 100644 --- a/assessment/questionnaire.go +++ b/assessment/questionnaire.go @@ -60,7 +60,7 @@ loop: answered.Add(a.QuestionnaireID) } } - assessed = answered.Superset(r.requiredQuestionnaires) + assessed = answered.Superset(r.requiredQuestionnaires, false) return } diff --git a/assessment/set.go b/assessment/set.go index c71006248..5a49ee930 100644 --- a/assessment/set.go +++ b/assessment/set.go @@ -23,8 +23,10 @@ func (r Set) Size() int { // // Add a member to the set. -func (r Set) Add(member uint) { - r.members[member] = true +func (r Set) Add(members ...uint) { + for _, member := range members { + r.members[member] = true + } } // @@ -35,7 +37,10 @@ func (r Set) Contains(element uint) bool { // // Superset tests whether every element of other is in the set. -func (r Set) Superset(other Set) bool { +func (r Set) Superset(other Set, strict bool) bool { + if strict && r.Size() <= other.Size() { + return false + } for m := range other.members { if !r.Contains(m) { return false @@ -46,8 +51,8 @@ func (r Set) Superset(other Set) bool { // // Subset tests whether every element of this set is in the other. -func (r Set) Subset(other Set) bool { - return other.Superset(r) +func (r Set) Subset(other Set, strict bool) bool { + return other.Superset(r, strict) } // diff --git a/assessment/set_test.go b/assessment/set_test.go new file mode 100644 index 000000000..b87df2ac2 --- /dev/null +++ b/assessment/set_test.go @@ -0,0 +1,46 @@ +package assessment + +import ( + "github.com/onsi/gomega" + "testing" +) + +func TestSet_Superset(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + a := NewSet() + b := NewSet() + a.Add(1, 2, 3, 4) + b.Add(1, 2, 3, 4) + + g.Expect(a.Superset(b, false)).To(gomega.BeTrue()) + g.Expect(b.Superset(a, false)).To(gomega.BeTrue()) + g.Expect(a.Superset(b, true)).To(gomega.BeFalse()) + g.Expect(b.Superset(a, true)).To(gomega.BeFalse()) + + a.Add(5) + g.Expect(a.Superset(b, false)).To(gomega.BeTrue()) + g.Expect(a.Superset(b, true)).To(gomega.BeTrue()) + g.Expect(b.Superset(a, false)).To(gomega.BeFalse()) + g.Expect(b.Superset(a, true)).To(gomega.BeFalse()) +} + +func TestSet_Subset(t *testing.T) { + g := gomega.NewGomegaWithT(t) + + a := NewSet() + b := NewSet() + a.Add(1, 2, 3, 4) + b.Add(1, 2, 3, 4) + + g.Expect(a.Subset(b, false)).To(gomega.BeTrue()) + g.Expect(b.Subset(a, false)).To(gomega.BeTrue()) + g.Expect(a.Subset(b, true)).To(gomega.BeFalse()) + g.Expect(b.Subset(a, true)).To(gomega.BeFalse()) + + b.Add(5) + g.Expect(a.Subset(b, false)).To(gomega.BeTrue()) + g.Expect(a.Subset(b, true)).To(gomega.BeTrue()) + g.Expect(b.Subset(a, false)).To(gomega.BeFalse()) + g.Expect(b.Subset(a, true)).To(gomega.BeFalse()) +} From 7f49d714fde45b79548730466c0b23572cb156e6 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Thu, 5 Oct 2023 08:54:43 -0500 Subject: [PATCH 05/56] :bug: Fix latest analayis report. (#504) The `/applications/:id/analysis` and `/applications/:id/analysis/report` returned the report for: analysis.ID=:id (application ID) instead of the Last analysis for the application.ID = :id. Potentially related to: https://issues.redhat.com/browse/MTA-1344 Signed-off-by: Jeff Ortel --- api/analysis.go | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/api/analysis.go b/api/analysis.go index 251fafefb..d04d7c6e0 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -130,7 +130,7 @@ func (h AnalysisHandler) AppLatest(ctx *gin.Context) { return } writer := AnalysisWriter{ctx: ctx} - path, err := writer.Create(id) + path, err := writer.Create(m.ID) if err != nil { _ = ctx.Error(err) return @@ -152,8 +152,16 @@ func (h AnalysisHandler) AppLatest(ctx *gin.Context) { // @param id path string true "Application ID" func (h AnalysisHandler) AppLatestReport(ctx *gin.Context) { id := h.pk(ctx) + m := &model.Analysis{} + db := h.DB(ctx) + db = db.Where("ApplicationID", id) + err := db.Last(&m).Error + if err != nil { + _ = ctx.Error(err) + return + } reportWriter := ReportWriter{ctx: ctx} - reportWriter.Write(id) + reportWriter.Write(m.ID) } // AppList godoc @@ -2315,6 +2323,7 @@ func (r *ReportWriter) buildOutput(id uint) (path string, err error) { r.begin() r.field("id").write(strconv.Itoa(int(m.Application.ID))) r.field("name").writeStr(m.Application.Name) + r.field("analysis").writeStr(strconv.Itoa(int(m.ID))) aWriter := AnalysisWriter{ctx: r.ctx} aWriter.encoder = r.encoder err = aWriter.addIssues(m) From e44f340c8b4a5e166d02553fb23c07c06b93e7a9 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Thu, 5 Oct 2023 10:48:17 -0500 Subject: [PATCH 06/56] :ghost: Support seed build args. (#503) Better support for test run analysis with seed PRs using `--build-arg SEED_PROJECT ` `--build-arg SEED_BRANCH ` Example: ``` $ docker build . -t quay.io/jortel/tackle2-hub:latest \ --build-arg 'SEED_PROJECT=jortel/tackle2-seed' \ --build-arg 'SEED_BRANCH=add-targets' \ && docker push quay.io/jortel/tackle2-hub:latest ``` Signed-off-by: Jeff Ortel --- Dockerfile | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index a29319844..2aa1e3695 100644 --- a/Dockerfile +++ b/Dockerfile @@ -2,7 +2,9 @@ FROM registry.access.redhat.com/ubi9/go-toolset:latest as builder ENV GOPATH=$APP_ROOT COPY --chown=1001:0 . . RUN make docker -RUN git clone https://github.com/konveyor/tackle2-seed +ARG SEED_PROJECT=konveyor/tackle2-seed +ARG SEED_BRANCH=main +RUN git clone --branch ${SEED_BRANCH} https://github.com/${SEED_PROJECT} FROM quay.io/konveyor/static-report as report From e30dbbcb95fa45fd05599281c0b9300a4ce9afad Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Thu, 5 Oct 2023 16:25:03 -0400 Subject: [PATCH 07/56] :bug: Only marshal assessment sections if not empty (#506) Marshalling the Assessment resource's `Sections` field unconditionally results in populating the model's `Sections` with the byte string `null`, which breaks the test for empty sections, making it always look like the assessment is being imported with sections "as-is". To fix this, only marshal the sections in the Assessment's `Model()` method if they are not empty. Additionally, replace the `if m.Sections == nil` test with a test for length, which works on nil as well as empty slices. Signed-off-by: Sam Lucidi --- api/application.go | 4 ++-- api/archetype.go | 4 ++-- api/assessment.go | 4 +++- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/api/application.go b/api/application.go index 2e048bfa4..c0e982347 100644 --- a/api/application.go +++ b/api/application.go @@ -1072,9 +1072,9 @@ func (h ApplicationHandler) AssessmentCreate(ctx *gin.Context) { m.Thresholds = q.Thresholds m.RiskMessages = q.RiskMessages m.CreateUser = h.CurrentUser(ctx) - // if sections aren't nil that indicates that this assessment is being + // if sections aren't empty that indicates that this assessment is being // created "as-is" and should not have its sections populated or autofilled. - if m.Sections == nil { + if len(m.Sections) == 0 { m.Sections = q.Sections resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) if rErr != nil { diff --git a/api/archetype.go b/api/archetype.go index 2388e0572..bb605a545 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -315,9 +315,9 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) { m.Thresholds = q.Thresholds m.RiskMessages = q.RiskMessages m.CreateUser = h.CurrentUser(ctx) - // if sections aren't nil that indicates that this assessment is being + // if sections aren't empty that indicates that this assessment is being // created "as-is" and should not have its sections populated or autofilled. - if m.Sections == nil { + if len(m.Sections) == 0 { m.Sections = q.Sections resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) if rErr != nil { diff --git a/api/assessment.go b/api/assessment.go index 5eb56f92f..b6bbc326a 100644 --- a/api/assessment.go +++ b/api/assessment.go @@ -220,7 +220,9 @@ func (r *Assessment) With(m *model.Assessment) { func (r *Assessment) Model() (m *model.Assessment) { m = &model.Assessment{} m.ID = r.ID - m.Sections, _ = json.Marshal(r.Sections) + if r.Sections != nil { + m.Sections, _ = json.Marshal(r.Sections) + } m.QuestionnaireID = r.Questionnaire.ID if r.Archetype != nil { m.ArchetypeID = &r.Archetype.ID From 47a3daab56efe3682de1879e5e2391e3d96c7b72 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Fri, 6 Oct 2023 11:19:41 -0400 Subject: [PATCH 08/56] :bug: PrepareForArchetype should use criteria and tags (#508) Previously PrepareForArchetype was using only the membership criteria to autofill assessments, but the enhancement specifies that it should use the archetype tags as well as the criteria tags. Fixes https://issues.redhat.com/browse/MTA-1396 Signed-off-by: Sam Lucidi --- assessment/pkg.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/assessment/pkg.go b/assessment/pkg.go index c1c70238d..6476314bd 100644 --- a/assessment/pkg.go +++ b/assessment/pkg.go @@ -103,6 +103,9 @@ func PrepareForArchetype(tagResolver *TagResolver, archetype *model.Archetype, a for _, t := range archetype.CriteriaTags { tagSet.Add(t.ID) } + for _, t := range archetype.Tags { + tagSet.Add(t.ID) + } assessment.Sections, _ = json.Marshal(prepareSections(tagResolver, tagSet, sections)) From 8168a59bd44c8562a51e6c2ff92fdc40ab1f7091 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 10 Oct 2023 11:02:59 -0400 Subject: [PATCH 09/56] :bug: Increment assessment counter when a new one is created (#511) Fixes https://github.com/konveyor/tackle2-hub/issues/510 Signed-off-by: Sam Lucidi --- api/application.go | 6 ++++++ api/archetype.go | 6 ++++++ 2 files changed, 12 insertions(+) diff --git a/api/application.go b/api/application.go index c0e982347..2ef87ef0a 100644 --- a/api/application.go +++ b/api/application.go @@ -4,6 +4,7 @@ import ( "encoding/json" "github.com/gin-gonic/gin" "github.com/konveyor/tackle2-hub/assessment" + "github.com/konveyor/tackle2-hub/metrics" "github.com/konveyor/tackle2-hub/model" "gorm.io/gorm/clause" "net/http" @@ -1074,6 +1075,7 @@ func (h ApplicationHandler) AssessmentCreate(ctx *gin.Context) { m.CreateUser = h.CurrentUser(ctx) // if sections aren't empty that indicates that this assessment is being // created "as-is" and should not have its sections populated or autofilled. + newAssessment := false if len(m.Sections) == 0 { m.Sections = q.Sections resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) @@ -1082,12 +1084,16 @@ func (h ApplicationHandler) AssessmentCreate(ctx *gin.Context) { return } assessment.PrepareForApplication(resolver, application, m) + newAssessment = true } result = h.DB(ctx).Create(m) if result.Error != nil { _ = ctx.Error(result.Error) return } + if newAssessment { + metrics.AssessmentsInitiated.Inc() + } r.With(m) h.Respond(ctx, http.StatusCreated, r) diff --git a/api/archetype.go b/api/archetype.go index bb605a545..f15a7b68b 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -3,6 +3,7 @@ package api import ( "github.com/gin-gonic/gin" "github.com/konveyor/tackle2-hub/assessment" + "github.com/konveyor/tackle2-hub/metrics" "github.com/konveyor/tackle2-hub/model" "gorm.io/gorm/clause" "net/http" @@ -317,6 +318,7 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) { m.CreateUser = h.CurrentUser(ctx) // if sections aren't empty that indicates that this assessment is being // created "as-is" and should not have its sections populated or autofilled. + newAssessment := false if len(m.Sections) == 0 { m.Sections = q.Sections resolver, rErr := assessment.NewTagResolver(h.DB(ctx)) @@ -325,12 +327,16 @@ func (h ArchetypeHandler) AssessmentCreate(ctx *gin.Context) { return } assessment.PrepareForArchetype(resolver, archetype, m) + newAssessment = true } result = h.DB(ctx).Create(m) if result.Error != nil { _ = ctx.Error(result.Error) return } + if newAssessment { + metrics.AssessmentsInitiated.Inc() + } r.With(m) h.Respond(ctx, http.StatusCreated, r) From 27a44eac24dd5a1691a8acaf53fb17efc6044447 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 10 Oct 2023 12:27:32 -0400 Subject: [PATCH 10/56] :bug: Protect builtin questionnaires from update/delete (#512) Only changing the `required` field is permitted for builtin questionnaires, all other changes and deletion are disallowed. --------- Signed-off-by: Sam Lucidi --- api/questionnaire.go | 38 ++++++++++++++++++++++++++----- migration/v10/model/assessment.go | 6 +++++ 2 files changed, 38 insertions(+), 6 deletions(-) diff --git a/api/questionnaire.go b/api/questionnaire.go index 890ffb2d2..cc7d3699e 100644 --- a/api/questionnaire.go +++ b/api/questionnaire.go @@ -123,6 +123,10 @@ func (h QuestionnaireHandler) Delete(ctx *gin.Context) { _ = ctx.Error(result.Error) return } + if m.Builtin() { + h.Status(ctx, http.StatusForbidden) + return + } result = h.DB(ctx).Delete(m) if result.Error != nil { _ = ctx.Error(result.Error) @@ -134,7 +138,9 @@ func (h QuestionnaireHandler) Delete(ctx *gin.Context) { // Update godoc // @summary Update a questionnaire. -// @description Update a questionnaire. +// @description Update a questionnaire. If the Questionnaire +// @description is builtin, only its "required" field can be changed +// @description and all other fields will be ignored. // @tags questionnaires // @accept json // @success 204 @@ -149,12 +155,30 @@ func (h QuestionnaireHandler) Update(ctx *gin.Context) { _ = ctx.Error(err) return } - m := r.Model() - m.ID = id - m.UpdateUser = h.CurrentUser(ctx) - db := h.DB(ctx).Model(m) + m := &model.Questionnaire{} + db := h.DB(ctx) + result := db.First(m, id) + if result.Error != nil { + _ = ctx.Error(result.Error) + return + } + + updated := r.Model() + updated.ID = id + updated.UpdateUser = h.CurrentUser(ctx) + var fields map[string]interface{} + if m.Builtin() { + fields = map[string]interface{}{ + "updateUser": updated.UpdateUser, + "required": updated.Required, + } + } else { + fields = h.fields(updated) + } + + db = h.DB(ctx).Model(m) db = db.Omit(clause.Associations) - result := db.Updates(h.fields(m)) + result = db.Updates(fields) if result.Error != nil { _ = ctx.Error(result.Error) return @@ -171,6 +195,7 @@ type Questionnaire struct { Sections []assessment.Section `json:"sections" yaml:"sections" binding:"required"` Thresholds assessment.Thresholds `json:"thresholds" yaml:"thresholds" binding:"required"` RiskMessages assessment.RiskMessages `json:"riskMessages" yaml:"riskMessages" binding:"required"` + Builtin bool `json:"builtin,omitempty" yaml:"builtin,omitempty"` } // With updates the resource with the model. @@ -179,6 +204,7 @@ func (r *Questionnaire) With(m *model.Questionnaire) { r.Name = m.Name r.Description = m.Description r.Required = m.Required + r.Builtin = m.Builtin() _ = json.Unmarshal(m.Sections, &r.Sections) _ = json.Unmarshal(m.Thresholds, &r.Thresholds) _ = json.Unmarshal(m.RiskMessages, &r.RiskMessages) diff --git a/migration/v10/model/assessment.go b/migration/v10/model/assessment.go index f3eeddfa0..a8cc0b6fe 100644 --- a/migration/v10/model/assessment.go +++ b/migration/v10/model/assessment.go @@ -12,6 +12,12 @@ type Questionnaire struct { Assessments []Assessment `gorm:"constraint:OnDelete:CASCADE"` } +// +// Builtin returns true if this is a Konveyor-provided questionnaire. +func (r *Questionnaire) Builtin() bool { + return r.UUID != nil +} + type Assessment struct { Model ApplicationID *uint `gorm:"uniqueIndex:AssessmentA"` From 54849ba24bb531afc3ccc674031ddba7e85e0222 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Wed, 11 Oct 2023 09:22:05 -0500 Subject: [PATCH 11/56] :bug: Fix HTML analysis report. (#513) The HTML report (tarball) is composed/streamed by the hub in steps: 1. Add the static report directory (template). 2. Add the composed `output.js` file which contains the analysis data. Using this method, the ReportWriter was adding the `output.js` (entry) twice in the tar. First from the static report (template) and the second generated by the hub. The tar command line seems to deal with this by overwriting the file. However the _extract_ functionality used by browsers ignores the 2nd occurrence. The fix is to filter out the 1st output.js when using tar.Writer.AddDir(). The `Filter` in the `tar` package only supported _include_ filtering. This PR updates the `tar.Filter` to support both _included_ and _excluded_ patterns. Refitted and tested the /bucket. --------- Signed-off-by: Jeff Ortel --- api/analysis.go | 4 ++ api/bucket.go | 6 +-- tar/filter.go | 97 ++++++++++++++++++++++++++++++++++++++++++++----- 3 files changed, 93 insertions(+), 14 deletions(-) diff --git a/api/analysis.go b/api/analysis.go index d04d7c6e0..459581996 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -2270,6 +2270,7 @@ func (r *ReportWriter) db() (db *gorm.DB) { // // Write builds and streams the analysis report. func (r *ReportWriter) Write(id uint) { + reportDir := Settings.Analysis.ReportPath path, err := r.buildOutput(id) if err != nil { _ = r.ctx.Error(err) @@ -2282,6 +2283,9 @@ func (r *ReportWriter) Write(id uint) { defer func() { tarWriter.Close() }() + filter := tar.NewFilter(reportDir) + filter.Exclude("output.js") + tarWriter.Filter = filter err = tarWriter.AssertDir(Settings.Analysis.ReportPath) if err != nil { _ = r.ctx.Error(err) diff --git a/api/bucket.go b/api/bucket.go index 2ca45908f..42d4c0934 100644 --- a/api/bucket.go +++ b/api/bucket.go @@ -231,10 +231,8 @@ func (h *BucketOwner) bucketGet(ctx *gin.Context, id uint) { return } if st.IsDir() { - filter := tar.Filter{ - Pattern: ctx.Query(Filter), - Root: path, - } + filter := tar.NewFilter(path) + filter.Include(ctx.Query(Filter)) if h.Accepted(ctx, binding.MIMEHTML) { h.getFile(ctx, m) } else { diff --git a/tar/filter.go b/tar/filter.go index 36b683fe3..63fdd5a1c 100644 --- a/tar/filter.go +++ b/tar/filter.go @@ -5,28 +5,105 @@ import ( "path/filepath" ) +// +// NewFilter returns a filter. +func NewFilter(root string) (f Filter) { + f = Filter{Root: root} + return +} + // // Filter supports glob-style filtering. type Filter struct { - Root string - Pattern string - cache map[string]bool + included FilterSet + excluded FilterSet + Root string } // // Match determines if path matches the filter. func (r *Filter) Match(path string) (b bool) { - if r.Pattern == "" { - b = true + r.included.root = r.Root + r.excluded.root = r.Root + if r.included.Len() > 0 { + included := r.included.Match(path) + if !included { + return + } + } + b = true + if r.excluded.Len() > 0 { + excluded := r.excluded.Match(path) + if excluded { + b = false + return + } + } + return +} + +// +// Include adds included patterns. +// Empty ("") patterns are ignored. +func (r *Filter) Include(patterns ...string) { + r.included.Add(patterns...) +} + +// +// Exclude adds excluded patterns. +// Empty ("") patterns are ignored. +func (r *Filter) Exclude(patterns ...string) { + r.excluded.Add(patterns...) +} + +// +// FilterSet is a collection of filter patterns. +type FilterSet struct { + root string + patterns []string + cache map[string]bool +} + +// +// Match returns true when the path matches. +func (r *FilterSet) Match(path string) (match bool) { + r.build() + _, match = r.cache[path] + return +} + +// +// Add pattern. +// Empty ("") patterns are ignored. +func (r *FilterSet) Add(patterns ...string) { + for _, p := range patterns { + if p == "" { + continue + } + r.cache = nil + r.patterns = append( + r.patterns, + p) + } +} + +// +// Len returns number of patterns. +func (r *FilterSet) Len() (n int) { + return len(r.patterns) +} + +// +// build populates the cache as needed. +func (r *FilterSet) build() { + if r.cache != nil { return } - if r.cache == nil { - r.cache = map[string]bool{} - matches, _ := filepath.Glob(pathlib.Join(r.Root, r.Pattern)) + r.cache = make(map[string]bool) + for i := range r.patterns { + matches, _ := filepath.Glob(pathlib.Join(r.root, r.patterns[i])) for _, p := range matches { r.cache[p] = true } } - _, b = r.cache[path] - return } From 68c73a7cc1da6a66e400d2ebdbdb021dd352dffc Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Wed, 11 Oct 2023 11:19:49 -0500 Subject: [PATCH 12/56] :bug: Fix business service filter of issues. (#515) https://issues.redhat.com/browse/MTA-1298 Signed-off-by: Jeff Ortel --- api/analysis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/analysis.go b/api/analysis.go index 459581996..680b73a69 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -1652,7 +1652,7 @@ func (h *AnalysisHandler) appIDs(ctx *gin.Context, f qf.Filter) (q *gorm.DB) { iq = iq.Model(&model.BusinessService{}) iq = iq.Select("ID") iq = bsFilter.Where(iq) - q = q.Where("ID IN (?)", iq) + q = q.Where("BusinessServiceID IN (?)", iq) return } return From 3ba496fe1633321518bea85ef0f953a0aab85e70 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Wed, 11 Oct 2023 15:22:23 -0400 Subject: [PATCH 13/56] :sparkles: Add `comment` string field to Section (#516) This was missing from the Assessment/Questionnaire sections and is necessary to completely implement the enhancement. Signed-off-by: Sam Lucidi --- assessment/section.go | 1 + 1 file changed, 1 insertion(+) diff --git a/assessment/section.go b/assessment/section.go index ce3db2af6..9cbea46b8 100644 --- a/assessment/section.go +++ b/assessment/section.go @@ -6,6 +6,7 @@ type Section struct { Order uint `json:"order" yaml:"order" binding:"required"` Name string `json:"name" yaml:"name"` Questions []Question `json:"questions" yaml:"questions"` + Comment string `json:"comment,omitempty" yaml:"comment,omitempty"` } // From ae995140a1e7000f29d2d2b052334fd06c5152c7 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Wed, 11 Oct 2023 15:24:01 -0500 Subject: [PATCH 14/56] :bug: Static report app id needs to be a string. (#518) The static report JS needs the app ID to be a string. Signed-off-by: Jeff Ortel --- api/analysis.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/analysis.go b/api/analysis.go index 680b73a69..1bcdecec8 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -2325,7 +2325,7 @@ func (r *ReportWriter) buildOutput(id uint) (path string, err error) { r.encoder = &jsonEncoder{output: file} r.write("window[\"apps\"]=[") r.begin() - r.field("id").write(strconv.Itoa(int(m.Application.ID))) + r.field("id").writeStr(strconv.Itoa(int(m.Application.ID))) r.field("name").writeStr(m.Application.Name) r.field("analysis").writeStr(strconv.Itoa(int(m.ID))) aWriter := AnalysisWriter{ctx: r.ctx} From 47eee2d3fcf11e7fbecfba2605327ec57e06d799 Mon Sep 17 00:00:00 2001 From: Marek Aufart Date: Thu, 12 Oct 2023 06:47:04 +0200 Subject: [PATCH 15/56] :seedling: Fix Identity API test Maven sample (#514) Updating Maven Identity sample to use (currently) correct "maven" kind instead of "mvn" to make it working with addon https://github.com/konveyor/tackle2-addon-analyzer/blob/61027b29f36ffa5b884ceac81c61d74341bdd762/cmd/mode.go#L151-L153 Signed-off-by: Marek Aufart --- test/api/identity/samples.go | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/test/api/identity/samples.go b/test/api/identity/samples.go index a7aededfa..89e588ac3 100644 --- a/test/api/identity/samples.go +++ b/test/api/identity/samples.go @@ -35,8 +35,8 @@ var ( `, } Mvn = api.Identity{ - Kind: "mvn", - Name: "mvn-settings", + Kind: "maven", + Name: "maven-settings", Settings: ` - tackle-testapp + tackle-testapp-public GITHUB_USER GITHUB_TOKEN @@ -70,8 +70,8 @@ var ( https://repo1.maven.org/maven2 - tackle-testapp - https://maven.pkg.github.com/konveyor/tackle-testapp + tackle-testapp-public + https://maven.pkg.github.com/konveyor/tackle-testapp-public true From aae707c97e60308ae1b299d3ad071e377d3b5544 Mon Sep 17 00:00:00 2001 From: Yash Khare Date: Thu, 12 Oct 2023 12:29:29 +0530 Subject: [PATCH 16/56] :seedling: add ticket API test (#477) Add the ticket API Test --------- Signed-off-by: Yash Khare --- binding/richclient.go | 4 + binding/ticket.go | 42 ++++++++++ docs/test-api-matrix.md | 2 +- test/api/ticket/api_test.go | 152 ++++++++++++++++++++++++++++++++++++ test/api/ticket/pkg.go | 31 ++++++++ test/api/ticket/samples.go | 21 +++++ 6 files changed, 251 insertions(+), 1 deletion(-) create mode 100644 binding/ticket.go create mode 100644 test/api/ticket/api_test.go create mode 100644 test/api/ticket/pkg.go create mode 100644 test/api/ticket/samples.go diff --git a/binding/richclient.go b/binding/richclient.go index 6302ed07a..ccca92cbe 100644 --- a/binding/richclient.go +++ b/binding/richclient.go @@ -40,6 +40,7 @@ type RichClient struct { TagCategory TagCategory Target Target Task Task + Ticket Ticket Tracker Tracker // A REST client. @@ -112,6 +113,9 @@ func New(baseUrl string) (r *RichClient) { Task: Task{ client: client, }, + Ticket: Ticket{ + client: client, + }, Tracker: Tracker{ client: client, }, diff --git a/binding/ticket.go b/binding/ticket.go new file mode 100644 index 000000000..60c294dd1 --- /dev/null +++ b/binding/ticket.go @@ -0,0 +1,42 @@ +package binding + +import ( + "github.com/konveyor/tackle2-hub/api" +) + +// +// Ticket API. +type Ticket struct { + client *Client +} + +// +// Create a Ticket. +func (h *Ticket) Create(r *api.Ticket) (err error) { + err = h.client.Post(api.TicketsRoot, &r) + return +} + +// +// Get a Ticket by ID. +func (h *Ticket) Get(id uint) (r *api.Ticket, err error) { + r = &api.Ticket{} + path := Path(api.TicketRoot).Inject(Params{api.ID: id}) + err = h.client.Get(path, r) + return +} + +// +// List Tickets.. +func (h *Ticket) List() (list []api.Ticket, err error) { + list = []api.Ticket{} + err = h.client.Get(api.TicketsRoot, &list) + return +} + +// +// Delete a Ticket. +func (h *Ticket) Delete(id uint) (err error) { + err = h.client.Delete(Path(api.TicketRoot).Inject(Params{api.ID: id})) + return +} diff --git a/docs/test-api-matrix.md b/docs/test-api-matrix.md index 1c4a1e635..774be208c 100644 --- a/docs/test-api-matrix.md +++ b/docs/test-api-matrix.md @@ -25,7 +25,7 @@ ruleset|:heavy_check_mark:|:heavy_check_mark:|| **Migrationwaves and Jira**|||| batch|||| migrationwave|:heavy_check_mark:|:heavy_check_mark:|| -ticket|||| +ticket|:heavy_check_mark:|:heavy_check_mark:|| tracker|:heavy_check_mark:|:heavy_check_mark:|| **Assessments**|||| archetype|||| diff --git a/test/api/ticket/api_test.go b/test/api/ticket/api_test.go new file mode 100644 index 000000000..af6f277c1 --- /dev/null +++ b/test/api/ticket/api_test.go @@ -0,0 +1,152 @@ +package ticket + +import ( + "testing" + + "github.com/konveyor/tackle2-hub/api" + TrackerSamples "github.com/konveyor/tackle2-hub/test/api/tracker" + "github.com/konveyor/tackle2-hub/test/assert" +) + +func TestTicketCRUD(t *testing.T) { + for _, r := range Samples { + t.Run("Ticket "+r.Kind+" CRUD", func(t *testing.T) { + + // Create a sample Application for the ticket. + app := api.Application{ + Name: r.Application.Name, + } + assert.Must(t, Application.Create(&app)) + + createdIdentities := []api.Identity{} + createdTrackers := []api.Tracker{} + for _, tracker := range TrackerSamples.Samples { + // Create a sample identity for the tracker + identity := api.Identity{ + Name: tracker.Identity.Name, + Kind: tracker.Kind, + } + assert.Must(t, Identity.Create(&identity)) + createdIdentities = append(createdIdentities, identity) + assert.Must(t, Tracker.Create(&tracker)) + createdTrackers = append(createdTrackers, tracker) + } + + // Create a sample ticket + assert.Must(t, Ticket.Create(&r)) + + // Get. + got, err := Ticket.Get(r.ID) + if err != nil { + t.Errorf(err.Error()) + } + + // Compare got values with expected values. + AssertEqualTickets(t, got, r) + + // Delete ticket and its related resources. + assert.Must(t, Ticket.Delete(r.ID)) + for _, tracker := range createdTrackers { + assert.Must(t, Tracker.Delete(tracker.ID)) + } + for _, identity := range createdIdentities { + assert.Must(t, Identity.Delete(identity.ID)) + } + assert.Must(t, Application.Delete(app.ID)) + + // Check if the Ticket is present even after deletion or not. + _, err = Ticket.Get(r.ID) + if err == nil { + t.Errorf("Resource exits, but should be deleted: %v", r) + } + }) + } +} + +func TestTicketList(t *testing.T) { + for _, r := range Samples { + + createdTickets := []api.Ticket{} + // Create a sample Application for the ticket. + app := api.Application{ + Name: r.Application.Name, + } + assert.Must(t, Application.Create(&app)) + + createdIdentities := []api.Identity{} + createdTrackers := []api.Tracker{} + for _, tracker := range TrackerSamples.Samples { + // Create a sample identity for the tracker + identity := api.Identity{ + Name: tracker.Identity.Name, + Kind: tracker.Kind, + } + assert.Must(t, Identity.Create(&identity)) + createdIdentities = append(createdIdentities, identity) + assert.Must(t, Tracker.Create(&tracker)) + createdTrackers = append(createdTrackers, tracker) + } + + // Create a sample ticket + assert.Must(t, Ticket.Create(&r)) + createdTickets = append(createdTickets, r) + + // List Tickets. + got, err := Ticket.List() + if err != nil { + t.Errorf(err.Error()) + } + + for _, createdTicket := range createdTickets { + found := false + for _, retrievedTicket := range got { + if assert.FlatEqual(createdTicket.ID, retrievedTicket.ID) { + found = true + break + } + } + if !found { + t.Errorf("Expected ticket not found in the list: %v", createdTicket) + } + } + + // Delete tickets and related resources. + for _, ticket := range createdTickets { + assert.Must(t, Ticket.Delete(ticket.ID)) + assert.Must(t, Application.Delete(ticket.ID)) + } + for _, tracker := range createdTrackers { + assert.Must(t, Tracker.Delete(tracker.ID)) + } + for _, identity := range createdIdentities { + assert.Must(t, Identity.Delete(identity.ID)) + } + } +} + +func AssertEqualTickets(t *testing.T, got *api.Ticket, expected api.Ticket) { + if got.Kind != expected.Kind { + t.Errorf("Different Kind Got %v, expected %v", got.Kind, expected.Kind) + } + if got.Reference != expected.Reference { + t.Errorf("Different Tracker Reference Got %v, expected %v", got.Reference, expected.Reference) + } + if got.Link != expected.Link { + t.Errorf("Different Url Got %v, expected %v", got.Link, expected.Link) + } + if got.Parent != expected.Parent { + t.Errorf("Different Parent Got %v, expected %v", got.Parent, expected.Parent) + } + if got.Message != expected.Message { + t.Errorf("Different Message Got %v, expected %v", got.Message, expected.Message) + } + if got.Status != expected.Status { + t.Errorf("Different Status Got %v, expected %v", got.Status, expected.Status) + } + if got.Application.Name != expected.Application.Name { + t.Errorf("Different Application's Name Got %v, expected %v", got.Application.Name, expected.Application.Name) + } + if got.Tracker.Name != expected.Tracker.Name { + t.Errorf("Different Tracker's Name Got %v, expected %v", got.Tracker.Name, expected.Tracker.Name) + } +} diff --git a/test/api/ticket/pkg.go b/test/api/ticket/pkg.go new file mode 100644 index 000000000..f6f5aab7f --- /dev/null +++ b/test/api/ticket/pkg.go @@ -0,0 +1,31 @@ +package ticket + +import ( + "github.com/konveyor/tackle2-hub/binding" + "github.com/konveyor/tackle2-hub/test/api/client" +) + +var ( + RichClient *binding.RichClient + Ticket binding.Ticket + Tracker binding.Tracker + Identity binding.Identity + Application binding.Application +) + +func init() { + // Prepare RichClient and login to Hub API (configured from env variables). + RichClient = client.PrepareRichClient() + + // Shortcut for Ticket-related RichClient methods. + Ticket = RichClient.Ticket + + // Shortcut for Tracker-related RichClient methods. + Tracker = RichClient.Tracker + + // Shortcut for Identity-related RichClient methods. + Identity = RichClient.Identity + + // Shortcut for Application-related RichClient methods. + Application = RichClient.Application +} diff --git a/test/api/ticket/samples.go b/test/api/ticket/samples.go new file mode 100644 index 000000000..5a74246ad --- /dev/null +++ b/test/api/ticket/samples.go @@ -0,0 +1,21 @@ +package ticket + +import ( + "github.com/konveyor/tackle2-hub/api" + TrackerSamples "github.com/konveyor/tackle2-hub/test/api/tracker" +) + +var Samples = []api.Ticket{ + { + Kind: "10001", + Parent: "10000", + Application: api.Ref{ + ID: 1, + Name: "Sample Application1", + }, + Tracker: api.Ref{ + ID: 1, + Name: TrackerSamples.Samples[0].Name, + }, + }, +} From 49e509b499bb56f6d76e6e0f143ea209695f3396 Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Thu, 12 Oct 2023 10:46:56 -0400 Subject: [PATCH 17/56] :bug: Deduplicate tags on imported apps (#517) Signed-off-by: Sam Lucidi --- importer/manager.go | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/importer/manager.go b/importer/manager.go index 3b1487539..96bc78732 100644 --- a/importer/manager.go +++ b/importer/manager.go @@ -200,6 +200,7 @@ func (m *Manager) createApplication(imp *model.Import) (ok bool) { db := m.DB.Preload("Category") db.Find(&allTags) + seenTags := make(map[uint]bool) appTags := []model.ApplicationTag{} for _, impTag := range imp.ImportTags { // Prepare normalized names for importTag @@ -270,8 +271,10 @@ func (m *Manager) createApplication(imp *model.Import) (ok bool) { return } } - - appTags = append(appTags, model.ApplicationTag{TagID: tag.ID, Source: ""}) + if !seenTags[tag.ID] { + seenTags[tag.ID] = true + appTags = append(appTags, model.ApplicationTag{TagID: tag.ID, Source: ""}) + } } result := m.DB.Create(app) From d971779d3a4bfc9672e5f38e16dd79dd61efac37 Mon Sep 17 00:00:00 2001 From: Dylan Murray Date: Mon, 16 Oct 2023 14:18:11 -0400 Subject: [PATCH 18/56] :bug: Bump x/net to 0.17.0 (#519) Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=2242803. CVE which impacts http/2 and rapid reset DDOS attacks. Signed-off-by: Dylan Murray --- go.mod | 10 +++++----- go.sum | 20 ++++++++++---------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/go.mod b/go.mod index de8b5f734..fc631351c 100644 --- a/go.mod +++ b/go.mod @@ -16,7 +16,7 @@ require ( github.com/onsi/gomega v1.27.6 github.com/prometheus/client_golang v1.15.0 github.com/swaggo/swag v1.16.1 - golang.org/x/sys v0.7.0 + 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 @@ -84,11 +84,11 @@ require ( github.com/ugorji/go/codec v1.2.9 // indirect go.uber.org/zap v1.24.0 // indirect golang.org/x/arch v0.0.0-20210923205945-b76863e36670 // indirect - golang.org/x/crypto v0.7.0 // indirect - golang.org/x/net v0.8.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 - golang.org/x/term v0.6.0 // indirect - golang.org/x/text v0.8.0 // indirect + golang.org/x/term v0.13.0 // indirect + golang.org/x/text v0.13.0 // indirect golang.org/x/time v0.3.0 // indirect golang.org/x/tools v0.7.0 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect diff --git a/go.sum b/go.sum index 30856dc6a..4d94c6145 100644 --- a/go.sum +++ b/go.sum @@ -237,8 +237,8 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk 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= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= -golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= +golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= +golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE= golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU= @@ -259,8 +259,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM= golang.org/x/net v0.0.0-20210928044308-7d9f5e0b762b/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= -golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= +golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= +golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.5.0 h1:HuArIo48skDwlrvM3sEdHXElYslAMsf3KwRkkW4MC4s= golang.org/x/oauth2 v0.5.0/go.mod h1:9/XBHVqLaWO3/BRHs5jbpYCnOZVjj5V0ndyaAM7KB4I= @@ -283,19 +283,19 @@ golang.org/x/sys v0.0.0-20220330033206-e17cdc41300f/go.mod h1:oPkhp1MJrh7nUepCBc 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.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU= -golang.org/x/sys v0.7.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= golang.org/x/term v0.0.0-20210220032956-6a3ed077a48d/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= -golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= +golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= +golang.org/x/term v0.13.0/go.mod h1:LTmsnFJwVN6bCy1rVCoS+qHT1HhALEFxKncY3WNNh4U= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= -golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= -golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= +golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= +golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= From e8dbcc1e0047bd41bbeedbdfdabfe15f3a6b7a63 Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Mon, 16 Oct 2023 16:50:12 -0500 Subject: [PATCH 19/56] :sparkles: Better pod OOM reporting. (#521) Using the container status `Reason` for more accurate reporting. ``` state: Failed image: quay.io/jortel/tackle2-addon-analyzer:debug pod: konveyor-tackle/task-13-gcmjs retries: 1 started: 2023-10-16T10:36:30.221282042-07:00 terminated: 2023-10-16T10:36:40.301254088-07:00 bucket: id: 17 name: "" errors: - severity: Error description: 'Pod failed: OOMKilled' ``` Also, the RWX should be disabled by default. --------- Signed-off-by: Jeff Ortel --- settings/hub.go | 2 -- task/manager.go | 5 ++++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/settings/hub.go b/settings/hub.go index d7d984e87..deaf0c00f 100644 --- a/settings/hub.go +++ b/settings/hub.go @@ -106,8 +106,6 @@ func (r *Hub) Load() (err error) { if found { b, _ := strconv.ParseBool(s) r.Cache.RWX = b - } else { - r.Cache.RWX = true } r.Cache.PVC, found = os.LookupEnv(EnvCachePvc) if !found { diff --git a/task/manager.go b/task/manager.go index 524923d27..172fc0f8b 100644 --- a/task/manager.go +++ b/task/manager.go @@ -356,7 +356,10 @@ func (r *Task) Reflect(client k8s.Client) (err error) { r.State = Succeeded r.Terminated = &mark case core.PodFailed: - r.Error("Error", "Pod failed: %s", pod.Status.Message) + r.Error( + "Error", + "Pod failed: %s", + pod.Status.ContainerStatuses[0].State.Terminated.Reason) switch pod.Status.ContainerStatuses[0].State.Terminated.ExitCode { case 137: // Killed. if r.Retries < Settings.Hub.Task.Retries { From cd09f8bb7c2de8d1f2876d530e22d7a4eafbd2ec Mon Sep 17 00:00:00 2001 From: Jeff Ortel Date: Tue, 17 Oct 2023 10:23:38 -0500 Subject: [PATCH 20/56] :ghost: Update 0.1.2 for License. (#522) Fixes FOSSA complaint. Signed-off-by: Jeff Ortel --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index fc631351c..311679f40 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,7 @@ require ( github.com/go-playground/validator/v10 v10.13.0 github.com/golang-jwt/jwt/v4 v4.5.0 github.com/google/uuid v1.3.0 - github.com/jortel/go-utils v0.1.1 + github.com/jortel/go-utils v0.1.2 github.com/konveyor/tackle2-seed v0.0.0-20230928184719-4a383c5aa887 github.com/mattn/go-sqlite3 v1.14.17 github.com/onsi/gomega v1.27.6 diff --git a/go.sum b/go.sum index 4d94c6145..0ac63456a 100644 --- a/go.sum +++ b/go.sum @@ -129,8 +129,8 @@ github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkr 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.1 h1:zkAAA+i5Z+151zUG7lkjILGxSo3pQ4bkLTRcPTCy3hs= -github.com/jortel/go-utils v0.1.1/go.mod h1:sl6vav63ODI0sUfSz8e0pImNmCVFnVsuOFhZmwe9GDk= +github.com/jortel/go-utils v0.1.2 h1:R0TcGRCcwoL793CymcKC5AF9idWXT2cR6eQ2xpBUsoI= +github.com/jortel/go-utils v0.1.2/go.mod h1:sl6vav63ODI0sUfSz8e0pImNmCVFnVsuOFhZmwe9GDk= github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= From b9593afae94e9d53bf3a2d944224530b73207e5a Mon Sep 17 00:00:00 2001 From: Samuel Lucidi Date: Tue, 17 Oct 2023 16:06:01 -0400 Subject: [PATCH 21/56] :book: Update OpenAPI spec w/ Assessment changes (#520) `ArchivedIssue` in the API package being an alias to another type confuses the swag tool. To mitigate this, I had to overwrite the swagger type of that field on the Analysis resource with `object`. This means that the api documentation for that field will be unhelpfully vague, but it allows the documentation to build. Signed-off-by: Sam Lucidi --- api/analysis.go | 2 +- api/archetype.go | 2 +- docs/docs.go | 1026 +++++++++++++++++++++++++++++++++++++++++---- docs/index.html | 410 +++++++++++------- docs/swagger.json | 1021 ++++++++++++++++++++++++++++++++++++++++---- docs/swagger.yaml | 610 ++++++++++++++++++++++++++- 6 files changed, 2761 insertions(+), 310 deletions(-) diff --git a/api/analysis.go b/api/analysis.go index 1bcdecec8..35d977ec6 100644 --- a/api/analysis.go +++ b/api/analysis.go @@ -1811,7 +1811,7 @@ type Analysis struct { Archived bool `json:"archived,omitempty" yaml:",omitempty"` Issues []Issue `json:"issues,omitempty" yaml:",omitempty"` Dependencies []TechDependency `json:"dependencies,omitempty" yaml:",omitempty"` - Summary []ArchivedIssue `json:"summary,omitempty" yaml:",omitempty"` + Summary []ArchivedIssue `json:"summary,omitempty" yaml:",omitempty" swaggertype:"object"` } // diff --git a/api/archetype.go b/api/archetype.go index f15a7b68b..06f0c9358 100644 --- a/api/archetype.go +++ b/api/archetype.go @@ -45,7 +45,7 @@ func (h ArchetypeHandler) AddRoutes(e *gin.Engine) { // @description Get an archetype by ID. // @tags archetypes // @produce json -// @success 200 {object} api.Archetypes +// @success 200 {object} api.Archetype // @router /archetypes/{id} [get] // @param id path string true "Archetype ID" func (h ArchetypeHandler) Get(ctx *gin.Context) { diff --git a/docs/docs.go b/docs/docs.go index d7fa02cf5..3ffbf7bef 100644 --- a/docs/docs.go +++ b/docs/docs.go @@ -1,5 +1,4 @@ -// Package docs GENERATED BY SWAG; DO NOT EDIT -// This file was generated by swaggo/swag +// Package docs Code generated by swaggo/swag. DO NOT EDIT package docs import "github.com/swaggo/swag" @@ -314,7 +313,7 @@ const docTemplate = `{ "get": { "description": "Get an analysis (report) by ID.", "produces": [ - "application/json" + "application/octet-stream" ], "tags": [ "analyses" @@ -612,7 +611,7 @@ const docTemplate = `{ "get": { "description": "Get the latest analysis for an application.", "produces": [ - "application/json" + "application/octet-stream" ], "tags": [ "analyses" @@ -637,6 +636,93 @@ const docTemplate = `{ } } }, + "/applications/{id}/analysis/report": { + "get": { + "description": "Get the latest analysis (static) report.", + "produces": [ + "application/octet-stream" + ], + "tags": [ + "analyses" + ], + "summary": "Get the latest analysis (static) report.", + "parameters": [ + { + "type": "string", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK" + } + } + } + }, + "/applications/{id}/assessments": { + "get": { + "description": "List the assessments of an Application and any it inherits from its archetypes.", + "tags": [ + "applications" + ], + "summary": "List the assessments of an Application and any it inherits from its archetypes.", + "parameters": [ + { + "type": "integer", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Assessment" + } + } + } + } + }, + "post": { + "description": "Create an application assessment.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "applications" + ], + "summary": "Create an application assessment.", + "parameters": [ + { + "description": "Assessment data", + "name": "assessment", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + } + } + }, "/applications/{id}/bucket/{wildcard}": { "get": { "description": "Get bucket content by ID and path.\nReturns index.html for directories when Accept=text/html else a tarball.\n?filter=glob supports directory content filtering.", @@ -968,6 +1054,36 @@ const docTemplate = `{ } }, "/applications/{id}/tags": { + "get": { + "description": "List tag references.", + "produces": [ + "application/json" + ], + "tags": [ + "applications" + ], + "summary": "List tag references.", + "parameters": [ + { + "type": "string", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + } + } + } + }, "post": { "description": "Ensure tag is associated with the application.", "consumes": [ @@ -1043,20 +1159,185 @@ const docTemplate = `{ } } }, - "/applications/{id}/tags/id": { + "/applications/{id}/tags/{sid}": { + "delete": { + "description": "Ensure tag is not associated with the application.", + "tags": [ + "applications" + ], + "summary": "Delete tag association.", + "parameters": [ + { + "type": "string", + "description": "Application ID", + "name": "id", + "in": "path", + "required": true + }, + { + "type": "string", + "description": "Tag ID", + "name": "sid", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/archetypes": { "get": { - "description": "List tag references.", + "description": "List all archetypes.", "produces": [ "application/json" ], "tags": [ - "applications" + "archetypes" ], - "summary": "List tag references.", + "summary": "List all archetypes.", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Archetype" + } + } + } + } + }, + "post": { + "description": "Create an archetype.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "archetypes" + ], + "summary": "Create an archetype.", + "parameters": [ + { + "description": "Archetype data", + "name": "archetype", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Archetype" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.Archetype" + } + } + } + } + }, + "/archetypes/{id}": { + "get": { + "description": "Get an archetype by ID.", + "produces": [ + "application/json" + ], + "tags": [ + "archetypes" + ], + "summary": "Get an archetype by ID.", "parameters": [ { "type": "string", - "description": "Application ID", + "description": "Archetype ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.Archetype" + } + } + } + }, + "put": { + "description": "Update an archetype.", + "consumes": [ + "application/json" + ], + "tags": [ + "archetypes" + ], + "summary": "Update an archetype.", + "parameters": [ + { + "type": "string", + "description": "Archetype ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Archetype data", + "name": "archetype", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Archetype" + } + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "Delete an archetype.", + "tags": [ + "archetypes" + ], + "summary": "Delete an archetype.", + "parameters": [ + { + "type": "string", + "description": "Archetype ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, + "/archetypes/{id}/assessments": { + "get": { + "description": "List the assessments of an archetype.", + "tags": [ + "archetypes" + ], + "summary": "List the assessments of an archetype.", + "parameters": [ + { + "type": "integer", + "description": "Archetype ID", "name": "id", "in": "path", "required": true @@ -1068,32 +1349,140 @@ const docTemplate = `{ "schema": { "type": "array", "items": { - "$ref": "#/definitions/api.Ref" + "$ref": "#/definitions/api.Assessment" } } } } + }, + "post": { + "description": "Create an archetype assessment.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "archetypes" + ], + "summary": "Create an archetype assessment.", + "parameters": [ + { + "description": "Assessment data", + "name": "assessment", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + ], + "responses": { + "201": { + "description": "Created", + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + } } }, - "/applications/{id}/tags/{sid}": { - "delete": { - "description": "Ensure tag is not associated with the application.", + "/assessments": { + "get": { + "description": "List all assessments.", + "produces": [ + "application/json" + ], "tags": [ - "applications" + "assessments" + ], + "summary": "List all assessments.", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Assessment" + } + } + } + } + } + }, + "/assessments/{id}": { + "get": { + "description": "Get an assessment by ID.", + "produces": [ + "application/json" + ], + "tags": [ + "questionnaires" + ], + "summary": "Get an assessment by ID.", + "parameters": [ + { + "type": "string", + "description": "Assessment ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + } + }, + "put": { + "description": "Update an assessment.", + "consumes": [ + "application/json" + ], + "tags": [ + "assessments" ], - "summary": "Delete tag association.", + "summary": "Update an assessment.", "parameters": [ { "type": "string", - "description": "Application ID", + "description": "Assessment ID", "name": "id", "in": "path", "required": true }, + { + "description": "Assessment data", + "name": "assessment", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Assessment" + } + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "Delete an assessment.", + "tags": [ + "assessments" + ], + "summary": "Delete an assessment.", + "parameters": [ { "type": "string", - "description": "Tag ID", - "name": "sid", + "description": "Assessment ID", + "name": "id", "in": "path", "required": true } @@ -2560,6 +2949,144 @@ const docTemplate = `{ } } }, + "/questionnaires": { + "get": { + "description": "List all questionnaires.", + "produces": [ + "application/json" + ], + "tags": [ + "questionnaires" + ], + "summary": "List all questionnaires.", + "responses": { + "200": { + "description": "OK", + "schema": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Questionnaire" + } + } + } + } + }, + "post": { + "description": "Create a questionnaire.", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "tags": [ + "questionnaires" + ], + "summary": "Create a questionnaire.", + "parameters": [ + { + "description": "Questionnaire data", + "name": "questionnaire", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Questionnaire" + } + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.Questionnaire" + } + } + } + } + }, + "/questionnaires/{id}": { + "get": { + "description": "Get a questionnaire by ID.", + "produces": [ + "application/json" + ], + "tags": [ + "questionnaires" + ], + "summary": "Get a questionnaire by ID.", + "parameters": [ + { + "type": "string", + "description": "Questionnaire ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "OK", + "schema": { + "$ref": "#/definitions/api.Questionnaire" + } + } + } + }, + "put": { + "description": "Update a questionnaire. If the Questionnaire\nis builtin, only its \"required\" field can be changed\nand all other fields will be ignored.", + "consumes": [ + "application/json" + ], + "tags": [ + "questionnaires" + ], + "summary": "Update a questionnaire.", + "parameters": [ + { + "type": "string", + "description": "Questionnaire ID", + "name": "id", + "in": "path", + "required": true + }, + { + "description": "Questionnaire data", + "name": "questionnaire", + "in": "body", + "required": true, + "schema": { + "$ref": "#/definitions/api.Questionnaire" + } + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + }, + "delete": { + "description": "Delete a questionnaire.", + "tags": [ + "questionnaires" + ], + "summary": "Delete a questionnaire.", + "parameters": [ + { + "type": "string", + "description": "Questionnaire ID", + "name": "id", + "in": "path", + "required": true + } + ], + "responses": { + "204": { + "description": "No Content" + } + } + } + }, "/reviews": { "get": { "description": "List all reviews.", @@ -2728,7 +3255,7 @@ const docTemplate = `{ }, "/rulesets": { "get": { - "description": "List all bindings.", + "description": "List all bindings.\nfilters:\n- name\n- labels", "produces": [ "application/json" ], @@ -4759,47 +5286,204 @@ const docTemplate = `{ } } } - } - } - } - }, - "definitions": { - "api.Addon": { - "type": "object", - "properties": { - "image": { - "type": "string" + } + } + } + }, + "definitions": { + "api.Addon": { + "type": "object", + "properties": { + "image": { + "type": "string" + }, + "name": { + "type": "string" + } + } + }, + "api.Analysis": { + "type": "object", + "properties": { + "archived": { + "type": "boolean" + }, + "createTime": { + "type": "string" + }, + "createUser": { + "type": "string" + }, + "dependencies": { + "type": "array", + "items": { + "$ref": "#/definitions/api.TechDependency" + } + }, + "effort": { + "type": "integer" + }, + "id": { + "type": "integer" + }, + "issues": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Issue" + } + }, + "summary": { + "type": "object" + }, + "updateUser": { + "type": "string" + } + } + }, + "api.Application": { + "type": "object", + "required": [ + "name" + ], + "properties": { + "archetypes": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "assessed": { + "type": "boolean" + }, + "assessments": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "binary": { + "type": "string" + }, + "bucket": { + "$ref": "#/definitions/api.Ref" + }, + "businessService": { + "$ref": "#/definitions/api.Ref" + }, + "comments": { + "type": "string" + }, + "contributors": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "createTime": { + "type": "string" + }, + "createUser": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "identities": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "migrationWave": { + "$ref": "#/definitions/api.Ref" + }, + "name": { + "type": "string" + }, + "owner": { + "$ref": "#/definitions/api.Ref" + }, + "repository": { + "$ref": "#/definitions/api.Repository" + }, + "review": { + "$ref": "#/definitions/api.Ref" + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/api.TagRef" + } }, - "name": { + "updateUser": { "type": "string" } } }, - "api.Analysis": { + "api.Archetype": { "type": "object", "properties": { + "applications": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "assessed": { + "type": "boolean" + }, + "assessments": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "comments": { + "type": "string" + }, "createTime": { "type": "string" }, "createUser": { "type": "string" }, - "dependencies": { + "criteria": { "type": "array", "items": { - "$ref": "#/definitions/api.TechDependency" + "$ref": "#/definitions/api.TagRef" } }, - "effort": { - "type": "integer" + "description": { + "type": "string" }, "id": { "type": "integer" }, - "issues": { + "name": { + "type": "string" + }, + "review": { + "$ref": "#/definitions/api.Ref" + }, + "stakeholderGroups": { "type": "array", "items": { - "$ref": "#/definitions/api.Issue" + "$ref": "#/definitions/api.Ref" + } + }, + "stakeholders": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } + }, + "tags": { + "type": "array", + "items": { + "$ref": "#/definitions/api.TagRef" } }, "updateUser": { @@ -4807,29 +5491,20 @@ const docTemplate = `{ } } }, - "api.Application": { + "api.Assessment": { "type": "object", "required": [ - "name" + "questionnaire" ], "properties": { - "binary": { - "type": "string" - }, - "bucket": { + "application": { "$ref": "#/definitions/api.Ref" }, - "businessService": { + "archetype": { "$ref": "#/definitions/api.Ref" }, - "comments": { - "type": "string" - }, - "contributors": { - "type": "array", - "items": { - "$ref": "#/definitions/api.Ref" - } + "confidence": { + "type": "integer" }, "createTime": { "type": "string" @@ -4837,39 +5512,43 @@ const docTemplate = `{ "createUser": { "type": "string" }, - "description": { - "type": "string" - }, "id": { "type": "integer" }, - "identities": { - "type": "array", - "items": { - "$ref": "#/definitions/api.Ref" - } - }, - "migrationWave": { + "questionnaire": { "$ref": "#/definitions/api.Ref" }, - "name": { + "risk": { + "description": "read only", "type": "string" }, - "owner": { - "$ref": "#/definitions/api.Ref" + "riskMessages": { + "$ref": "#/definitions/assessment.RiskMessages" }, - "repository": { - "$ref": "#/definitions/api.Repository" + "sections": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.Section" + } }, - "review": { - "$ref": "#/definitions/api.Ref" + "stakeholderGroups": { + "type": "array", + "items": { + "$ref": "#/definitions/api.Ref" + } }, - "tags": { + "stakeholders": { "type": "array", "items": { - "$ref": "#/definitions/api.TagRef" + "$ref": "#/definitions/api.Ref" } }, + "status": { + "type": "string" + }, + "thresholds": { + "$ref": "#/definitions/assessment.Thresholds" + }, "updateUser": { "type": "string" } @@ -5538,6 +6217,53 @@ const docTemplate = `{ } } }, + "api.Questionnaire": { + "type": "object", + "required": [ + "name", + "riskMessages", + "sections", + "thresholds" + ], + "properties": { + "builtin": { + "type": "boolean" + }, + "createTime": { + "type": "string" + }, + "createUser": { + "type": "string" + }, + "description": { + "type": "string" + }, + "id": { + "type": "integer" + }, + "name": { + "type": "string" + }, + "required": { + "type": "boolean" + }, + "riskMessages": { + "$ref": "#/definitions/assessment.RiskMessages" + }, + "sections": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.Section" + } + }, + "thresholds": { + "$ref": "#/definitions/assessment.Thresholds" + }, + "updateUser": { + "type": "string" + } + } + }, "api.Ref": { "type": "object", "required": [ @@ -5574,13 +6300,13 @@ const docTemplate = `{ }, "api.Review": { "type": "object", - "required": [ - "application" - ], "properties": { "application": { "$ref": "#/definitions/api.Ref" }, + "archetype": { + "$ref": "#/definitions/api.Ref" + }, "businessCriticality": { "type": "integer" }, @@ -5695,6 +6421,9 @@ const docTemplate = `{ "$ref": "#/definitions/api.Ref" } }, + "description": { + "type": "string" + }, "id": { "type": "integer" }, @@ -5958,6 +6687,9 @@ const docTemplate = `{ }, "source": { "type": "string" + }, + "virtual": { + "type": "boolean" } } }, @@ -6332,6 +7064,150 @@ const docTemplate = `{ "type": "string" } } + }, + "assessment.Answer": { + "type": "object", + "required": [ + "order" + ], + "properties": { + "applyTags": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.CategorizedTag" + } + }, + "autoAnswerFor": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.CategorizedTag" + } + }, + "autoAnswered": { + "type": "boolean" + }, + "mitigation": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "rationale": { + "type": "string" + }, + "risk": { + "type": "string", + "enum": [ + "red" + ] + }, + "selected": { + "type": "boolean" + }, + "text": { + "type": "string" + } + } + }, + "assessment.CategorizedTag": { + "type": "object", + "properties": { + "category": { + "type": "string" + }, + "tag": { + "type": "string" + } + } + }, + "assessment.Question": { + "type": "object", + "required": [ + "order" + ], + "properties": { + "answers": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.Answer" + } + }, + "excludeFor": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.CategorizedTag" + } + }, + "explanation": { + "type": "string" + }, + "includeFor": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.CategorizedTag" + } + }, + "order": { + "type": "integer" + }, + "text": { + "type": "string" + } + } + }, + "assessment.RiskMessages": { + "type": "object", + "properties": { + "green": { + "type": "string" + }, + "red": { + "type": "string" + }, + "unknown": { + "type": "string" + }, + "yellow": { + "type": "string" + } + } + }, + "assessment.Section": { + "type": "object", + "required": [ + "order" + ], + "properties": { + "comment": { + "type": "string" + }, + "name": { + "type": "string" + }, + "order": { + "type": "integer" + }, + "questions": { + "type": "array", + "items": { + "$ref": "#/definitions/assessment.Question" + } + } + } + }, + "assessment.Thresholds": { + "type": "object", + "properties": { + "red": { + "type": "integer" + }, + "unknown": { + "type": "integer" + }, + "yellow": { + "type": "integer" + } + } } } }` @@ -6346,6 +7222,8 @@ var SwaggerInfo = &swag.Spec{ Description: "", InfoInstanceName: "swagger", SwaggerTemplate: docTemplate, + LeftDelim: "{{", + RightDelim: "}}", } func init() { diff --git a/docs/index.html b/docs/index.html index 8a264074c..bea91c0c5 100644 --- a/docs/index.html +++ b/docs/index.html @@ -2098,7 +2098,7 @@ -

Response samples

Content type
application/json
{ }

analyses

List analyses.

List analyses for an application. Resources do not include relations.

Responses

Response samples

Content type
application/json
[
  • {
    }
]

Get an analysis (report) by ID.

Get an analysis (report) by ID.

+

Response samples

Content type
application/json
[
  • {
    }
]

Get an analysis (report) by ID.

Get an analysis (report) by ID.

path Parameters
id
required
string

Analysis ID

Responses

Response samples

Content type
application/json
{
  • "createTime": "string",
  • "createUser": "string",
  • "dependencies": [
    ],
  • "effort": 0,
  • "id": 0,
  • "issues": [
    ],
  • "updateUser": "string"
}

Delete an analysis by ID.

Delete an analysis by ID.

+

Delete an analysis by ID.

Delete an analysis by ID.

path Parameters
id
required
string

Analysis ID

Responses

Create an analysis.

Create an analysis. @@ -2141,12 +2141,16 @@

  • dependencies: file that multiple api.TechDependency resources.
  • Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependencies": [
      ],
    • "effort": 0,
    • "id": 0,
    • "issues": [
      ],
    • "updateUser": "string"
    }

    Get the latest analysis.

    Get the latest analysis for an application.

    +

    Response samples

    Content type
    application/json
    {
    • "archived": true,
    • "createTime": "string",
    • "createUser": "string",
    • "dependencies": [
      ],
    • "effort": 0,
    • "id": 0,
    • "issues": [
      ],
    • "summary": { },
    • "updateUser": "string"
    }

    Get the latest analysis.

    Get the latest analysis for an application.

    path Parameters
    id
    required
    string

    Application ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependencies": [
      ],
    • "effort": 0,
    • "id": 0,
    • "issues": [
      ],
    • "updateUser": "string"
    }

    dependencies

    List dependency reports.

    Each report collates dependencies by name and SHA. +

    Get the latest analysis (static) report.

    Get the latest analysis (static) report.

    +
    path Parameters
    id
    required
    string

    Application ID

    +

    Responses

    dependencies

    List dependency reports.

    Each report collates dependencies by name and SHA. filters:

      +
    • provider
    • name
    • version
    • sha
    • @@ -2154,14 +2158,17 @@
    • labels
    • application.id
    • application.name
    • +
    • businessService.id
    • +
    • businessService.name
    • tag.id sort:
    • +
    • provider
    • name
    • version
    • sha

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application dependencies.

    List application dependencies. +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application dependencies.

    List application dependencies. filters:

    • name
    • @@ -2172,15 +2179,15 @@
    path Parameters
    id
    required
    string

    Application ID

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all dependencies.

    List all dependencies.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all dependencies.

    List all dependencies.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a dependency.

    Create a dependency.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a dependency.

    Create a dependency.

    Request Body schema: application/json

    Dependency data

    createTime
    string
    createUser
    string
    object (api.Ref)
    id
    integer
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Get a dependency by ID.

    Get a dependency by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Get a dependency by ID.

    Get a dependency by ID.

    path Parameters
    id
    required
    string

    Dependency ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Delete a dependency.

    Delete a dependency.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Delete a dependency.

    Delete a dependency.

    path Parameters
    id
    required
    string

    Dependency id

    Responses

    issues

    List all issues.

    List all issues. @@ -2197,7 +2204,7 @@

  • tag.id
  • Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application issues.

    List application issues. +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application issues.

    List application issues. filters:

    • ruleset
    • @@ -2209,45 +2216,65 @@
    path Parameters
    id
    required
    string

    Application ID

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issue

    Get an issue.

    Get an issue.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issue

    Get an issue.

    Get an issue.

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "facts": { },
    • "id": 0,
    • "incidents": [
      ],
    • "labels": [
      ],
    • "links": [
      ],
    • "name": "string",
    • "rule": "string",
    • "ruleset": "string",
    • "updateUser": "string"
    }

    incidents

    List incidents for an issue.

    List incidents for an issue. +

    Response samples

    Content type
    application/json
    {
    • "category": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "facts": { },
    • "id": 0,
    • "incidents": [
      ],
    • "labels": [
      ],
    • "links": [
      ],
    • "name": "string",
    • "rule": "string",
    • "ruleset": "string",
    • "updateUser": "string"
    }

    incidents

    List incidents for an issue.

    List incidents for an issue. filters:

    • file

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    appreports

    List application reports.

    List application reports. +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    depappreports

    List application reports.

    List application reports. filters:

    • id
    • name
    • description
    • businessService
    • -
    • effort
    • -
    • incidents
    • -
    • files
    • -
    • issue.id
    • -
    • issue.name
    • -
    • issue.ruleset
    • -
    • issue.rule
    • -
    • issue.category
    • -
    • issue.effort
    • -
    • issue.labels
    • +
    • provider
    • +
    • name
    • +
    • version
    • +
    • sha
    • +
    • indirect
    • +
    • dep.provider
    • +
    • dep.name
    • +
    • dep.version
    • +
    • dep.sha
    • +
    • dep.indirect
    • +
    • dep.labels
    • application.id
    • application.name
    • +
    • businessService.id
    • businessService.name sort:
    • -
    • id
    • name
    • description
    • businessService
    • +
    • provider
    • +
    • name
    • +
    • version
    • +
    • sha
    • +
    • indirect
    • +
    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issuereport

    List application issue reports.

    Each report collates issues by ruleset/rule. +filters:

    +
      +
    • ruleset
    • +
    • rule
    • +
    • category
    • +
    • effort
    • +
    • labels +sort:
    • +
    • ruleset
    • +
    • rule
    • +
    • category
    • effort
    • -
    • incidents
    • files
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    filereports

    List incident file reports.

    Each report collates incidents by file. +

    path Parameters
    id
    required
    string

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    filereports

    List incident file reports.

    Each report collates incidents by file. filters:

    • file
    • @@ -2259,7 +2286,7 @@
    • incidents

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    rulereports

    List rule reports.

    Each report collates issues by ruleset/rule. +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    rulereports

    List rule reports.

    Each report collates issues by ruleset/rule. filters:

    • ruleset
    • @@ -2270,6 +2297,8 @@
    • applications
    • application.id
    • application.name
    • +
    • businessService.id
    • +
    • businessService.name
    • tag.id sort:
    • ruleset
    • @@ -2279,25 +2308,32 @@
    • applications

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    applications

    List all applications.

    List all applications.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    applications

    List all applications.

    List all applications.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application.

    Create an application.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application.

    Create an application.

    Request Body schema: application/json

    Application data

    -
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete a applications.

    Delete applications.

    +
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete a applications.

    Delete applications.

    Request Body schema: application/json

    List of id

    Array
    integer

    Responses

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Get an application by ID.

    Get an application by ID.

    +

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Get an application by ID.

    Get an application by ID.

    path Parameters
    id
    required
    integer

    Application ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an application.

    Update an application.

    +

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an application.

    Update an application.

    path Parameters
    id
    required
    integer

    Application id

    Request Body schema: application/json

    Application data

    -
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an application.

    Delete an application.

    +
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an application.

    Delete an application.

    path Parameters
    id
    required
    integer

    Application id

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. +

    List the assessments of an Application and any it inherits from its archetypes.

    List the assessments of an Application and any it inherits from its archetypes.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Create an application assessment.

    Create an application assessment.

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get bucket content by ID and path.

    Get bucket content by ID and path. Returns index.html for directories when Accept=text/html else a tarball. ?filter=glob supports directory content filtering.

    path Parameters
    id
    required
    string

    Application ID

    @@ -2313,18 +2349,18 @@
    path Parameters
    id
    required
    string

    Application ID

    Request Body schema: application/json

    Fact data

    key
    string
    source
    string
    value
    any

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "source": "string",
    • "value": null
    }

    Get fact by name.

    Get fact by name. +

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "source": "string",
    • "value": null
    }

    Get fact by name.

    Get fact by name. see api.FactKey for details on key parameter format.

    path Parameters
    id
    required
    string

    Application ID

    key
    required
    string

    Fact key

    Responses

    Response samples

    Content type
    application/json
    { }

    Update (or create) a fact.

    Update (or create) a fact. +

    Response samples

    Content type
    application/json
    { }

    Update (or create) a fact.

    Update (or create) a fact. see api.FactKey for details on key parameter format.

    path Parameters
    id
    required
    string

    Application ID

    key
    required
    string

    Fact key

    Request Body schema: application/json

    Fact value

    object

    Responses

    Request samples

    Content type
    application/json
    { }

    Delete a fact.

    Delete a fact. +

    Request samples

    Content type
    application/json
    { }

    Delete a fact.

    Delete a fact. see api.FactKey for details on key parameter format.

    path Parameters
    id
    required
    string

    Application ID

    key
    required
    string

    Fact key

    @@ -2334,79 +2370,131 @@
    path Parameters
    id
    required
    string

    Application ID

    source
    required
    string

    Source key

    Responses

    Response samples

    Content type
    application/json
    { }

    Replace all facts from a source.

    Replace all facts from a source. +

    Response samples

    Content type
    application/json
    { }

    Replace all facts from a source.

    Replace all facts from a source. see api.FactKey for details on key parameter format.

    path Parameters
    id
    required
    string

    Application ID

    source
    required
    string

    Fact key

    Request Body schema: application/json

    Fact map

    property name*
    any

    Responses

    Request samples

    Content type
    application/json
    { }

    Update the owner and contributors of an Application.

    Update the owner and contributors of an Application.

    +

    Request samples

    Content type
    application/json
    { }

    Update the owner and contributors of an Application.

    Update the owner and contributors of an Application.

    path Parameters
    id
    required
    integer

    Application ID

    Request Body schema: application/json

    Application stakeholders

    Array of objects (api.Ref) [ items ]
    object (api.Ref)

    Responses

    Request samples

    Content type
    application/json
    {
    • "contributors": [
      ],
    • "owner": {
      }
    }

    Add tag association.

    Ensure tag is associated with the application.

    +

    Request samples

    Content type
    application/json
    {
    • "contributors": [
      ],
    • "owner": {
      }
    }

    List tag references.

    List tag references.

    +
    path Parameters
    id
    required
    string

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Add tag association.

    Ensure tag is associated with the application.

    Request Body schema: application/json

    Tag data

    id
    required
    integer
    name
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Replace tag associations.

    Replace tag associations.

    +

    Request samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Replace tag associations.

    Replace tag associations.

    path Parameters
    id
    required
    string

    Application ID

    query Parameters
    source
    string

    Source

    Request Body schema: application/json

    Tag references

    -
    Array
    id
    required
    integer
    name
    string
    source
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    List tag references.

    List tag references.

    -
    path Parameters
    id
    required
    string

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Delete tag association.

    Ensure tag is not associated with the application.

    +
    Array
    id
    required
    integer
    name
    string
    source
    string
    virtual
    boolean

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Delete tag association.

    Ensure tag is not associated with the application.

    path Parameters
    id
    required
    string

    Application ID

    sid
    required
    string

    Tag ID

    Responses

    auth

    Login and obtain a bearer token.

    Login and obtain a bearer token.

    +

    archetypes

    List all archetypes.

    List all archetypes.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an archetype.

    Create an archetype.

    +
    Request Body schema: application/json

    Archetype data

    +
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    comments
    string
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef) [ items ]
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Get an archetype by ID.

    Get an archetype by ID.

    +
    path Parameters
    id
    required
    string

    Archetype ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an archetype.

    Update an archetype.

    +
    path Parameters
    id
    required
    string

    Archetype ID

    +
    Request Body schema: application/json

    Archetype data

    +
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    comments
    string
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef) [ items ]
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an archetype.

    Delete an archetype.

    +
    path Parameters
    id
    required
    string

    Archetype ID

    +

    Responses

    List the assessments of an archetype.

    List the assessments of an archetype.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +

    Responses

    Create an archetype assessment.

    Create an archetype assessment.

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    assessments

    List all assessments.

    List all assessments.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Update an assessment.

    Update an assessment.

    +
    path Parameters
    id
    required
    string

    Assessment ID

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete an assessment.

    Delete an assessment.

    +
    path Parameters
    id
    required
    string

    Assessment ID

    +

    Responses

    questionnaires

    Get an assessment by ID.

    Get an assessment by ID.

    +
    path Parameters
    id
    required
    string

    Assessment ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    List all questionnaires.

    List all questionnaires.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a questionnaire.

    Create a questionnaire.

    +
    Request Body schema: application/json

    Questionnaire data

    +
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section) [ items ]
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get a questionnaire by ID.

    Get a questionnaire by ID.

    +
    path Parameters
    id
    required
    string

    Questionnaire ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Update a questionnaire.

    Update a questionnaire. If the Questionnaire +is builtin, only its "required" field can be changed +and all other fields will be ignored.

    +
    path Parameters
    id
    required
    string

    Questionnaire ID

    +
    Request Body schema: application/json

    Questionnaire data

    +
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section) [ items ]
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete a questionnaire.

    Delete a questionnaire.

    +
    path Parameters
    id
    required
    string

    Questionnaire ID

    +

    Responses

    auth

    Login and obtain a bearer token.

    Login and obtain a bearer token.

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    Refresh bearer token.

    Refresh bearer token.

    +

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    Refresh bearer token.

    Refresh bearer token.

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    batch

    Batch-create Tags.

    Batch-create Tags.

    +

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    batch

    Batch-create Tags.

    Batch-create Tags.

    Request Body schema: application/json

    Tags data

    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Batch-create Tickets.

    Batch-create Tickets.

    +

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Batch-create Tickets.

    Batch-create Tickets.

    Request Body schema: application/json

    Tickets data

    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    tags

    Batch-create Tags.

    Batch-create Tags.

    +

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    tags

    Batch-create Tags.

    Batch-create Tags.

    Request Body schema: application/json

    Tags data

    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tags.

    List all tags.

    +

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tags.

    List all tags.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag.

    Create a tag.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag.

    Create a tag.

    Request Body schema: application/json

    Tag data

    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Get a tag by ID.

    Get a tag by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Get a tag by ID.

    Get a tag by ID.

    path Parameters
    id
    required
    string

    Tag ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Update a tag.

    Update a tag.

    +

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Update a tag.

    Update a tag.

    path Parameters
    id
    required
    string

    Tag ID

    Request Body schema: application/json

    Tag data

    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Delete a tag.

    Delete a tag.

    +

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Delete a tag.

    Delete a tag.

    path Parameters
    id
    required
    string

    Tag ID

    Responses

    tickets

    Batch-create Tickets.

    Batch-create Tickets.

    Request Body schema: application/json

    Tickets data

    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tickets.

    List all tickets.

    +

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tickets.

    List all tickets.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ticket.

    Create a ticket.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ticket.

    Create a ticket.

    Request Body schema: application/json

    Ticket data

    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Get a ticket by ID.

    Get a ticket by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Get a ticket by ID.

    Get a ticket by ID.

    path Parameters
    id
    required
    string

    Ticket ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Delete a ticket.

    Delete a ticket.

    +

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Delete a ticket.

    Delete a ticket.

    path Parameters
    id
    required
    integer

    Ticket id

    Responses

    buckets

    List all buckets.

    List all buckets.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a bucket.

    Create a bucket.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a bucket.

    Create a bucket.

    path Parameters
    name
    required
    string

    Bucket name

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "path": "string",
    • "updateUser": "string"
    }

    Get a bucket by ID.

    Get a bucket by ID. +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "path": "string",
    • "updateUser": "string"
    }

    Get a bucket by ID.

    Get a bucket by ID. Returns api.Bucket when Accept=application/json. Else returns index.html when Accept=text/html. Else returns tarball.

    @@ -2431,17 +2519,17 @@

    Responses

    businessservices

    List all business services.

    List all business services.

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Create a business service.

    Create a business service.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Create a business service.

    Create a business service.

    Request Body schema: application/json

    Business service data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Get a business service by ID.

    Get a business service by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Get a business service by ID.

    Get a business service by ID.

    path Parameters
    id
    required
    string

    Business Service ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Update a business service.

    Update a business service.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Update a business service.

    Update a business service.

    path Parameters
    id
    required
    string

    Business service ID

    Request Body schema: application/json

    Business service data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Delete a business service.

    Delete a business service.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Delete a business service.

    Delete a business service.

    path Parameters
    id
    required
    string

    Business service ID

    Responses

    cache

    Delete a directory within the cache.

    Delete a directory within the cache.

    @@ -2449,12 +2537,12 @@

    Get the cache.

    Get the cache.

    path Parameters
    name
    required
    string

    Cache DIR

    Responses

    Response samples

    Content type
    application/json
    {
    • "capacity": "string",
    • "exists": true,
    • "path": "string",
    • "used": "string"
    }

    file

    List all files.

    List all files.

    +

    Response samples

    Content type
    application/json
    {
    • "capacity": "string",
    • "exists": true,
    • "path": "string",
    • "used": "string"
    }

    file

    List all files.

    List all files.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a file.

    Create a file.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a file.

    Create a file.

    path Parameters
    name
    required
    string

    File name

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "name": "string",
    • "path": "string",
    • "updateUser": "string"
    }

    Get a file by ID.

    Get a file by ID. Returns api.File when Accept=application/json else the file content.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "name": "string",
    • "path": "string",
    • "updateUser": "string"
    }

    Get a file by ID.

    Get a file by ID. Returns api.File when Accept=application/json else the file content.

    path Parameters
    id
    required
    string

    File ID

    Responses

    Delete a file.

    Delete a file.

    @@ -2462,53 +2550,53 @@

    Responses

    identities

    List all identities.

    List all identities.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an identity.

    Create an identity.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an identity.

    Create an identity.

    Request Body schema: application/json

    Identity data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Get an identity by ID.

    Get an identity by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Get an identity by ID.

    Get an identity by ID.

    path Parameters
    id
    required
    string

    Identity ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Update an identity.

    Update an identity.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Update an identity.

    Update an identity.

    path Parameters
    id
    required
    string

    Identity ID

    Request Body schema: application/json

    Identity data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Delete an identity.

    Delete an identity.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Delete an identity.

    Delete an identity.

    path Parameters
    id
    required
    string

    Identity ID

    Responses

    imports

    List imports.

    List imports.

    Responses

    Response samples

    Content type
    application/json
    [
    • { }
    ]

    Get an import by ID.

    Get an import by ID.

    +

    Response samples

    Content type
    application/json
    [
    • { }
    ]

    Get an import by ID.

    Get an import by ID.

    path Parameters
    id
    required
    string

    Import ID

    Responses

    Response samples

    Content type
    application/json
    { }

    Delete an import.

    Delete an import. This leaves any created application or dependency.

    +

    Response samples

    Content type
    application/json
    { }

    Delete an import.

    Delete an import. This leaves any created application or dependency.

    path Parameters
    id
    required
    string

    Import ID

    Responses

    List import summaries.

    List import summaries.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Export the source CSV for a particular import summary.

    Export the source CSV for a particular import summary.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Export the source CSV for a particular import summary.

    Export the source CSV for a particular import summary.

    query Parameters
    importSummary.id
    required
    string

    ImportSummary ID

    Responses

    Upload a CSV containing applications and dependencies to import.

    Upload a CSV containing applications and dependencies to import.

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Get an import summary by ID.

    Get an import by ID.

    +

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Get an import summary by ID.

    Get an import by ID.

    path Parameters
    id
    required
    string

    ImportSummary ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Delete an import summary and associated import records.

    Delete an import summary and associated import records.

    +

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Delete an import summary and associated import records.

    Delete an import summary and associated import records.

    path Parameters
    id
    required
    string

    ImportSummary ID

    Responses

    jobfunctions

    List all job functions.

    List all job functions.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a job function.

    Create a job function.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a job function.

    Create a job function.

    Request Body schema: application/json

    Job Function data

    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a job function by ID.

    Get a job function by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a job function by ID.

    Get a job function by ID.

    path Parameters
    id
    required
    string

    Job Function ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a job function.

    Update a job function.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a job function.

    Update a job function.

    path Parameters
    id
    required
    string

    Job Function ID

    Request Body schema: application/json

    Job Function data

    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a job function.

    Delete a job function.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a job function.

    Delete a job function.

    path Parameters
    id
    required
    string

    Job Function ID

    Responses

    metrics

    Get Prometheus metrics.

    Get Prometheus metrics. @@ -2517,149 +2605,169 @@

    Responses

    migrationwaves

    List all migration waves.

    List all migration waves.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a migration wave.

    Create a migration wave.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a migration wave.

    Create a migration wave.

    Request Body schema: application/json

    Migration Wave data

    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Get a migration wave by ID.

    Get a migration wave by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Get a migration wave by ID.

    Get a migration wave by ID.

    path Parameters
    id
    required
    integer

    Migration Wave ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Update a migration wave.

    Update a migration wave.

    +

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Update a migration wave.

    Update a migration wave.

    path Parameters
    id
    required
    integer

    MigrationWave id

    Request Body schema: application/json

    MigrationWave data

    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Delete a migration wave.

    Delete a migration wave.

    +

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Delete a migration wave.

    Delete a migration wave.

    path Parameters
    id
    required
    integer

    MigrationWave id

    Responses

    proxies

    List all proxies.

    List all proxies.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an proxy.

    Create an proxy.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an proxy.

    Create an proxy.

    Request Body schema: application/json

    Proxy data

    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Get an proxy by ID.

    Get an proxy by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Get an proxy by ID.

    Get an proxy by ID.

    path Parameters
    id
    required
    string

    Proxy ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Update an proxy.

    Update an proxy.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Update an proxy.

    Update an proxy.

    path Parameters
    id
    required
    string

    Proxy ID

    Request Body schema: application/json

    Proxy data

    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Delete an proxy.

    Delete an proxy.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Delete an proxy.

    Delete an proxy.

    path Parameters
    id
    required
    string

    Proxy ID

    Responses

    reviews

    List all reviews.

    List all reviews.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a review.

    Create a review.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a review.

    Create a review.

    Request Body schema: application/json

    Review data

    -
    required
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Copy a review from one application to others.

    Copy a review from one application to others.

    +
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Copy a review from one application to others.

    Copy a review from one application to others.

    Request Body schema: application/json

    Review copy request data

    sourceReview
    required
    integer
    targetApplications
    required
    Array of integers[ items ]

    Responses

    Request samples

    Content type
    application/json
    {
    • "sourceReview": 0,
    • "targetApplications": [
      ]
    }

    Get a review by ID.

    Get a review by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "sourceReview": 0,
    • "targetApplications": [
      ]
    }

    Get a review by ID.

    Get a review by ID.

    path Parameters
    id
    required
    string

    Review ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Update a review.

    Update a review.

    +

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Update a review.

    Update a review.

    path Parameters
    id
    required
    string

    Review ID

    Request Body schema: application/json

    Review data

    -
    required
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Delete a review.

    Delete a review.

    +
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Delete a review.

    Delete a review.

    path Parameters
    id
    required
    string

    Review ID

    Responses

    rulesets

    List all bindings.

    List all bindings.

    +

    rulesets

    List all bindings.

    List all bindings. +filters:

    +
      +
    • name
    • +
    • labels
    • +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ruleset.

    Create a ruleset.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ruleset.

    Create a ruleset.

    Request Body schema: application/json

    RuleSet data

    -
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "image": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "image": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Get a RuleSet by ID.

    Get a RuleSet by ID.

    +
    createTime
    string
    createUser
    string
    Array of objects (api.Ref) [ items ]
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Get a RuleSet by ID.

    Get a RuleSet by ID.

    path Parameters
    id
    required
    string

    RuleSet ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "image": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Update a ruleset.

    Update a ruleset.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Update a ruleset.

    Update a ruleset.

    path Parameters
    id
    required
    string

    RuleSet ID

    Request Body schema: application/json

    RuleSet data

    -
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "image": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Delete a ruleset.

    Delete a ruleset.

    +
    createTime
    string
    createUser
    string
    Array of objects (api.Ref) [ items ]
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Delete a ruleset.

    Delete a ruleset.

    path Parameters
    id
    required
    string

    RuleSet ID

    Responses

    schema

    Get the API schema.

    Get the API schema.

    Responses

    Response samples

    Content type
    application/json
    {
    • "paths": [
      ],
    • "version": "string"
    }

    settings

    List all settings.

    List all settings.

    +

    Response samples

    Content type
    application/json
    {
    • "paths": [
      ],
    • "version": "string"
    }

    settings

    List all settings.

    List all settings.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a setting.

    Create a setting.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a setting.

    Create a setting.

    Request Body schema: application/json

    Setting data

    key
    string
    value
    any

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Get a setting by its key.

    Get a setting by its key.

    +

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Get a setting by its key.

    Get a setting by its key.

    path Parameters
    key
    required
    string

    Key

    Responses

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Update a setting.

    Update a setting.

    +

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Update a setting.

    Update a setting.

    path Parameters
    key
    required
    string

    Key

    Responses

    Create a setting.

    Create a setting.

    Request Body schema: application/json

    Setting value

    key
    string
    value
    any

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Delete a setting.

    Delete a setting.

    +

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": null
    }

    Delete a setting.

    Delete a setting.

    path Parameters
    key
    required
    string

    Key

    Responses

    stakeholdergroups

    List all stakeholder groups.

    List all stakeholder groups.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder group.

    Create a stakeholder group.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder group.

    Create a stakeholder group.

    Request Body schema: application/json

    Stakeholder Group data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder group by ID.

    Get a stakeholder group by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder group by ID.

    Get a stakeholder group by ID.

    path Parameters
    id
    required
    string

    Stakeholder Group ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder group.

    Update a stakeholder group.

    +

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder group.

    Update a stakeholder group.

    path Parameters
    id
    required
    string

    Stakeholder Group ID

    Request Body schema: application/json

    Stakeholder Group data

    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder group.

    Delete a stakeholder group.

    +

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder group.

    Delete a stakeholder group.

    path Parameters
    id
    required
    string

    Stakeholder Group ID

    Responses

    stakeholders

    List all stakeholders.

    List all stakeholders.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder.

    Create a stakeholder.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder.

    Create a stakeholder.

    Request Body schema: application/json

    Stakeholder data

    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder by ID.

    Get a stakeholder by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder by ID.

    Get a stakeholder by ID.

    path Parameters
    id
    required
    string

    Stakeholder ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder.

    Update a stakeholder.

    +

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder.

    Update a stakeholder.

    path Parameters
    id
    required
    string

    Stakeholder ID

    Request Body schema: application/json

    Stakeholder data

    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder.

    Delete a stakeholder.

    +

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder.

    Delete a stakeholder.

    path Parameters
    id
    required
    string

    Stakeholder ID

    Responses

    tagcategories

    List all tag categories.

    List all tag categories.

    query Parameters
    name
    string

    Optional category name filter

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag category.

    Create a tag category.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag category.

    Create a tag category.

    Request Body schema: application/json

    Tag Category data

    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref) [ items ]
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Get a tag category by ID.

    Get a tag category by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Get a tag category by ID.

    Get a tag category by ID.

    path Parameters
    id
    required
    string

    Tag Category ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Update a tag category.

    Update a tag category.

    +

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Update a tag category.

    Update a tag category.

    path Parameters
    id
    required
    string

    Tag Category ID

    Request Body schema: application/json

    Tag Category data

    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref) [ items ]
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Delete a tag category.

    Delete a tag category.

    +

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Delete a tag category.

    Delete a tag category.

    path Parameters
    id
    required
    string

    Tag Category ID

    Responses

    List the tags in the tag category.

    List the tags in the tag category.

    path Parameters
    id
    required
    string

    Tag Category ID

    query Parameters
    name
    string

    Optional tag name filter

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    taskgroups

    List all task groups.

    List all task groups.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    targets

    List all targets.

    List all targets.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a target.

    Create a target.

    +
    Request Body schema: application/json

    Target data

    +
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label) [ items ]
    name
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Get a Target by ID.

    Get a Target by ID.

    +
    path Parameters
    id
    required
    string

    Target ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Update a target.

    Update a target.

    +
    path Parameters
    id
    required
    string

    Target ID

    +
    Request Body schema: application/json

    Target data

    +
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label) [ items ]
    name
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Delete a target.

    Delete a target.

    +
    path Parameters
    id
    required
    string

    Target ID

    +

    Responses

    taskgroups

    List all task groups.

    List all task groups.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task group.

    Create a task group.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task group.

    Create a task group.

    Request Body schema: application/json

    TaskGroup data

    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Get a task group by ID.

    Get a task group by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Get a task group by ID.

    Get a task group by ID.

    path Parameters
    id
    required
    string

    TaskGroup ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Update a task group.

    Update a task group.

    +

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Update a task group.

    Update a task group.

    path Parameters
    id
    required
    string

    Task ID

    Request Body schema: application/json

    Task data

    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Delete a task group.

    Delete a task group.

    +

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Delete a task group.

    Delete a task group.

    path Parameters
    id
    required
    string

    TaskGroup ID

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. @@ -2678,19 +2786,19 @@

    path Parameters
    id
    required
    string

    TaskGroup ID

    Request Body schema: application/json

    TaskGroup data (optional)

    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    tasks

    List all tasks.

    List all tasks.

    +

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    tasks

    List all tasks.

    List all tasks.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task.

    Create a task.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task.

    Create a task.

    Request Body schema: application/json

    Task data

    -
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    error
    string
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    object (api.TaskReport)
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "error": "string",
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "report": {
      },
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "error": "string",
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "report": {
      },
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Get a task by ID.

    Get a task by ID.

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Get a task by ID.

    Get a task by ID.

    path Parameters
    id
    required
    string

    Task ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "error": "string",
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "report": {
      },
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Update a task.

    Update a task.

    +

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Update a task.

    Update a task.

    path Parameters
    id
    required
    string

    Task ID

    Request Body schema: application/json

    Task data

    -
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    error
    string
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    object (api.TaskReport)
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "error": "string",
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "report": {
      },
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Delete a task.

    Delete a task.

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Delete a task.

    Delete a task.

    path Parameters
    id
    required
    string

    Task ID

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. @@ -2711,47 +2819,47 @@

    Update a task report.

    Update a task report.

    path Parameters
    id
    required
    string

    Task ID

    Request Body schema: application/json

    TaskReport data

    -
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    error
    string
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "error": "string",
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "error": "string",
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Create a task report.

    Update a task report.

    +
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError) [ items ]
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Create a task report.

    Update a task report.

    path Parameters
    id
    required
    string

    Task ID

    Request Body schema: application/json

    TaskReport data

    -
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    error
    string
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "error": "string",
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "error": "string",
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Delete a task report.

    Delete a task report.

    +
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError) [ items ]
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Delete a task report.

    Delete a task report.

    path Parameters
    id
    required
    string

    Task ID

    Responses

    Submit a task.

    Submit a task.

    path Parameters
    id
    required
    string

    Task ID

    Request Body schema: application/json

    Task data (optional)

    -
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    error
    string
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    object (api.TaskReport)
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "error": "string",
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "report": {
      },
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    trackers

    List all trackers.

    List all trackers.

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    trackers

    List all trackers.

    List all trackers.

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tracker.

    Create a tracker.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tracker.

    Create a tracker.

    Request Body schema: application/json

    Tracker data

    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Get a tracker by ID.

    Get a tracker by ID.

    +

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Get a tracker by ID.

    Get a tracker by ID.

    path Parameters
    id
    required
    string

    Tracker ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Update a tracker.

    Update a tracker.

    +

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Update a tracker.

    Update a tracker.

    path Parameters
    id
    required
    integer

    Tracker id

    Request Body schema: application/json

    Tracker data

    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Delete a tracker.

    Delete a tracker.

    +

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Delete a tracker.

    Delete a tracker.

    path Parameters
    id
    required
    integer

    Tracker id

    Responses

    List a tracker's projects.

    List a tracker's projects.

    path Parameters
    id
    required
    string

    Tracker ID

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get a tracker project by ID.

    Get a tracker project by ID.

    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get a tracker project by ID.

    Get a tracker project by ID.

    path Parameters
    id
    required
    string

    Tracker ID

    id2
    required
    string

    Project ID

    Responses

    Response samples

    Content type
    application/json
    {
    • "id": "string",
    • "name": "string"
    }

    List a tracker project's issue types.

    List a tracker project's issue types.

    +

    Response samples

    Content type
    application/json
    {
    • "id": "string",
    • "name": "string"
    }

    List a tracker project's issue types.

    List a tracker project's issue types.

    path Parameters
    id
    required
    string

    Tracker ID

    id2
    required
    string

    Project ID

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]
    +

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]
    -

    Konveyor Hub API (0.3.z)

    Download OpenAPI specification:Download

    License: Apache 2.0

    addons

    List all addons.

    List all addons.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get an addon by name.

    Get an addon by name.

    -
    path Parameters
    name
    required
    string

    Addon name

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "image": "string",
    • "name": "string"
    }

    adoptionplans

    Generate an application dependency graph arranged in topological order.

    Graph generates an application dependency graph arranged in topological order.

    -
    Request Body schema: application/json

    List of requested App IDs

    -
    Array
    integer

    Responses

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    analyses

    List analyses.

    List analyses for an application. + " fill="currentColor">

    Konveyor Hub API (0.3.z)

    Download OpenAPI specification:Download

    License: Apache 2.0

    addons

    List all addons.

    List all addons.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get an addon by name.

    Get an addon by name.

    +
    path Parameters
    name
    required
    string

    Addon name

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "image": "string",
    • "name": "string"
    }

    adoptionplans

    Generate an application dependency graph arranged in topological order.

    Graph generates an application dependency graph arranged in topological order.

    +
    Request Body schema: application/json

    List of requested App IDs

    +
    Array
    integer

    Responses

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    analyses

    List analyses.

    List analyses for an application. Resources do not include relations.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get an analysis (report) by ID.

    Get an analysis (report) by ID.

    -
    path Parameters
    id
    required
    integer

    Analysis ID

    -

    Responses

    Delete an analysis by ID.

    Delete an analysis by ID.

    -
    path Parameters
    id
    required
    integer

    Analysis ID

    -

    Responses

    Create an analysis.

    Create an analysis. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get an analysis (report) by ID.

    Get an analysis (report) by ID.

    +
    path Parameters
    id
    required
    integer

    Analysis ID

    +

    Responses

    Delete an analysis by ID.

    Delete an analysis by ID.

    +
    path Parameters
    id
    required
    integer

    Analysis ID

    +

    Responses

    Create an analysis.

    Create an analysis. Form fields:

    • file: file that contains the api.Analysis resource.
    • issues: file that multiple api.Issue resources.
    • dependencies: file that multiple api.TechDependency resources.
    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "archived": true,
    • "createTime": "string",
    • "createUser": "string",
    • "dependencies": [
      ],
    • "effort": 0,
    • "id": 0,
    • "issues": [
      ],
    • "summary": { },
    • "updateUser": "string"
    }

    Get the latest analysis.

    Get the latest analysis for an application.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Get the latest analysis (static) report.

    Get the latest analysis (static) report.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    dependencies

    List dependency reports.

    Each report collates dependencies by name and SHA. +

    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "archived": true,
    • "createTime": "string",
    • "createUser": "string",
    • "dependencies": [
      ],
    • "effort": 0,
    • "id": 0,
    • "issues": [
      ],
    • "summary": { },
    • "updateUser": "string"
    }

    Get the latest analysis.

    Get the latest analysis for an application.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Get the latest analysis (static) report.

    Get the latest analysis (static) report.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    dependencies

    List dependency reports.

    Each report collates dependencies by name and SHA. filters:

    • provider
    • @@ -2166,11 +2244,10 @@ sort:
    • provider
    • name
    • -
    • version
    • -
    • sha
    • +
    • labels
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application dependencies.

    List application dependencies. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application dependencies.

    List application dependencies. filters:

    • name
    • @@ -2179,20 +2256,20 @@
    • indirect
    • labels
    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all dependencies.

    List all dependencies.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a dependency.

    Create a dependency.

    -
    Request Body schema: application/json

    Dependency data

    -
    createTime
    string
    createUser
    string
    object (api.Ref)
    id
    integer
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Get a dependency by ID.

    Get a dependency by ID.

    -
    path Parameters
    id
    required
    integer

    Dependency ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Delete a dependency.

    Delete a dependency.

    -
    path Parameters
    id
    required
    integer

    Dependency id

    -

    Responses

    issues

    List all issues.

    List all issues. +

    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all dependencies.

    List all dependencies.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a dependency.

    Create a dependency.

    +
    Request Body schema: application/json

    Dependency data

    +
    createTime
    string
    createUser
    string
    object (api.Ref)
    id
    integer
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Get a dependency by ID.

    Get a dependency by ID.

    +
    path Parameters
    id
    required
    integer

    Dependency ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "from": {
      },
    • "id": 0,
    • "to": {
      },
    • "updateUser": "string"
    }

    Delete a dependency.

    Delete a dependency.

    +
    path Parameters
    id
    required
    integer

    Dependency id

    +

    Responses

    issues

    List all issues.

    List all issues. filters:

    • ruleset
    • @@ -2205,8 +2282,8 @@
    • application.name
    • tag.id
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application issues.

    List application issues. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List application issues.

    List application issues. filters:

    • ruleset
    • @@ -2216,19 +2293,19 @@
    • effort
    • labels
    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issue

    Get an issue.

    Get an issue.

    -
    path Parameters
    id
    required
    integer

    Issue ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "facts": { },
    • "id": 0,
    • "incidents": [
      ],
    • "labels": [
      ],
    • "links": [
      ],
    • "name": "string",
    • "rule": "string",
    • "ruleset": "string",
    • "updateUser": "string"
    }

    incidents

    List incidents for an issue.

    List incidents for an issue. +

    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issue

    Get an issue.

    Get an issue.

    +
    path Parameters
    id
    required
    integer

    Issue ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "facts": { },
    • "id": 0,
    • "incidents": [
      ],
    • "labels": [
      ],
    • "links": [
      ],
    • "name": "string",
    • "rule": "string",
    • "ruleset": "string",
    • "updateUser": "string"
    }

    incidents

    List incidents for an issue.

    List incidents for an issue. filters:

    • file
    -
    path Parameters
    id
    required
    integer

    Issue ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    depappreports

    List application reports.

    List application reports. +

    path Parameters
    id
    required
    integer

    Issue ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    depappreports

    List application reports.

    List application reports. filters:

    • id
    • @@ -2260,8 +2337,8 @@
    • sha
    • indirect
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issuereport

    List application issue reports.

    Each report collates issues by ruleset/rule. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    issuereport

    List application issue reports.

    Each report collates issues by ruleset/rule. filters:

    • ruleset
    • @@ -2276,9 +2353,9 @@
    • effort
    • files
    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    filereports

    List incident file reports.

    Each report collates incidents by file. +

    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    filereports

    List incident file reports.

    Each report collates incidents by file. filters:

    • file
    • @@ -2289,9 +2366,9 @@
    • effort
    • incidents
    -
    path Parameters
    id
    required
    integer

    Issue ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    rulereports

    List rule reports.

    Each report collates issues by ruleset/rule. +

    path Parameters
    id
    required
    integer

    Issue ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    rulereports

    List rule reports.

    Each report collates issues by ruleset/rule. filters:

    • ruleset
    • @@ -2312,575 +2389,575 @@
    • effort
    • applications
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    applications

    List all applications.

    List all applications.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application.

    Create an application.

    -
    Request Body schema: application/json

    Application data

    -
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    confidence
    integer
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    effort
    integer
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    risk
    string
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete a applications.

    Delete applications.

    -
    Request Body schema: application/json

    List of id

    -
    Array
    integer

    Responses

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Get an application by ID.

    Get an application by ID.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an application.

    Update an application.

    -
    path Parameters
    id
    required
    integer

    Application id

    -
    Request Body schema: application/json

    Application data

    -
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    confidence
    integer
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    description
    string
    effort
    integer
    id
    integer
    Array of objects (api.Ref) [ items ]
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    risk
    string
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an application.

    Delete an application.

    -
    path Parameters
    id
    required
    integer

    Application id

    -

    Responses

    List the assessments of an Application and any it inherits from its archetypes.

    List the assessments of an Application and any it inherits from its archetypes.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application assessment.

    Create an application assessment.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    Request Body schema: application/json

    Assessment data

    -
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    -
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get bucket content by ID and path.

    Get bucket content by ID and path. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    applications

    List all applications.

    List all applications.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application.

    Create an application.

    +
    Request Body schema: application/json

    Application data

    +
    Array of objects (api.Ref)
    assessed
    boolean
    Array of objects (api.Ref)
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    confidence
    integer
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    description
    string
    effort
    integer
    id
    integer
    Array of objects (api.Ref)
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    risk
    string
    Array of objects (api.TagRef)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete a applications.

    Delete applications.

    +
    Request Body schema: application/json

    List of id

    +
    Array
    integer

    Responses

    Request samples

    Content type
    application/json
    [
    • 0
    ]

    Get an application by ID.

    Get an application by ID.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an application.

    Update an application.

    +
    path Parameters
    id
    required
    integer

    Application id

    +
    Request Body schema: application/json

    Application data

    +
    Array of objects (api.Ref)
    assessed
    boolean
    Array of objects (api.Ref)
    binary
    string
    object (api.Ref)
    object (api.Ref)
    comments
    string
    confidence
    integer
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    description
    string
    effort
    integer
    id
    integer
    Array of objects (api.Ref)
    object (api.Ref)
    name
    required
    string
    object (api.Ref)
    object (api.Repository)
    object (api.Ref)
    risk
    string
    Array of objects (api.TagRef)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "archetypes": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "binary": "string",
    • "bucket": {
      },
    • "businessService": {
      },
    • "comments": "string",
    • "confidence": 0,
    • "contributors": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "effort": 0,
    • "id": 0,
    • "identities": [
      ],
    • "migrationWave": {
      },
    • "name": "string",
    • "owner": {
      },
    • "repository": {
      },
    • "review": {
      },
    • "risk": "string",
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an application.

    Delete an application.

    +
    path Parameters
    id
    required
    integer

    Application id

    +

    Responses

    List the assessments of an Application and any it inherits from its archetypes.

    List the assessments of an Application and any it inherits from its archetypes.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an application assessment.

    Create an application assessment.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section)
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get bucket content by ID and path.

    Get bucket content by ID and path. Returns index.html for directories when Accept=text/html else a tarball. ?filter=glob supports directory content filtering.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    wildcard
    required
    string

    Content path

    -
    query Parameters
    filter
    string

    Filter

    -

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Create a fact.

    Create a fact.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    Request Body schema: application/json

    Fact data

    -
    key
    string
    source
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "source": "string",
    • "value": { }
    }

    Get fact by name.

    Get fact by name. +

    path Parameters
    id
    required
    integer

    Application ID

    +
    wildcard
    required
    string

    Content path

    +
    query Parameters
    filter
    string

    Filter

    +

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Create a fact.

    Create a fact.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    Request Body schema: application/json

    Fact data

    +
    key
    string
    source
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "source": "string",
    • "value": { }
    }

    Get fact by name.

    Get fact by name. see api.FactKey for details on key parameter format.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    key
    required
    string

    Fact key

    -

    Responses

    Response samples

    Content type
    application/json
    { }

    Update (or create) a fact.

    Update (or create) a fact. +

    path Parameters
    id
    required
    integer

    Application ID

    +
    key
    required
    string

    Fact key

    +

    Responses

    Response samples

    Content type
    application/json
    { }

    Update (or create) a fact.

    Update (or create) a fact. see api.FactKey for details on key parameter format.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    key
    required
    string

    Fact key

    -
    Request Body schema: application/json

    Fact value

    -
    object

    Responses

    Request samples

    Content type
    application/json
    { }

    Delete a fact.

    Delete a fact. +

    path Parameters
    id
    required
    integer

    Application ID

    +
    key
    required
    string

    Fact key

    +
    Request Body schema: application/json

    Fact value

    +
    object

    Responses

    Request samples

    Content type
    application/json
    { }

    Delete a fact.

    Delete a fact. see api.FactKey for details on key parameter format.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    key
    required
    string

    Fact key

    -

    Responses

    List facts.

    List facts by source. +

    path Parameters
    id
    required
    integer

    Application ID

    +
    key
    required
    string

    Fact key

    +

    Responses

    List facts.

    List facts by source. see api.FactKey for details on key parameter format.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    source
    required
    string

    Source key

    -

    Responses

    Response samples

    Content type
    application/json
    { }

    Replace all facts from a source.

    Replace all facts from a source. +

    path Parameters
    id
    required
    integer

    Application ID

    +
    source
    required
    string

    Source key

    +

    Responses

    Response samples

    Content type
    application/json
    { }

    Replace all facts from a source.

    Replace all facts from a source. see api.FactKey for details on key parameter format.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    source
    required
    string

    Fact key

    -
    Request Body schema: application/json

    Fact map

    -
    object (api.FactMap)

    Responses

    Request samples

    Content type
    application/json
    { }

    Update the owner and contributors of an Application.

    Update the owner and contributors of an Application.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    Request Body schema: application/json

    Application stakeholders

    -
    Array of objects (api.Ref) [ items ]
    object (api.Ref)

    Responses

    Request samples

    Content type
    application/json
    {
    • "contributors": [
      ],
    • "owner": {
      }
    }

    List tag references.

    List tag references.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Add tag association.

    Ensure tag is associated with the application.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    Request Body schema: application/json

    Tag data

    -
    id
    required
    integer
    name
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Replace tag associations.

    Replace tag associations.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    query Parameters
    source
    string

    Source

    -
    Request Body schema: application/json

    Tag references

    -
    Array
    id
    required
    integer
    name
    string
    source
    string
    virtual
    boolean

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Delete tag association.

    Ensure tag is not associated with the application.

    -
    path Parameters
    id
    required
    integer

    Application ID

    -
    sid
    required
    string

    Tag ID

    -

    Responses

    archetypes

    List all archetypes.

    List all archetypes.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an archetype.

    Create an archetype.

    -
    Request Body schema: application/json

    Archetype data

    -
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    comments
    string
    confidence
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef) [ items ]
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    risk
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Get an archetype by ID.

    Get an archetype by ID.

    -
    path Parameters
    id
    required
    integer

    Archetype ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an archetype.

    Update an archetype.

    -
    path Parameters
    id
    required
    integer

    Archetype ID

    -
    Request Body schema: application/json

    Archetype data

    -
    Array of objects (api.Ref) [ items ]
    assessed
    boolean
    Array of objects (api.Ref) [ items ]
    comments
    string
    confidence
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef) [ items ]
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    risk
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.TagRef) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an archetype.

    Delete an archetype.

    -
    path Parameters
    id
    required
    integer

    Archetype ID

    -

    Responses

    List the assessments of an archetype.

    List the assessments of an archetype.

    -
    path Parameters
    id
    required
    integer

    Archetype ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an archetype assessment.

    Create an archetype assessment.

    -
    path Parameters
    id
    required
    integer

    Archetype ID

    -
    Request Body schema: application/json

    Assessment data

    -
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    -
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    assessments

    List all assessments.

    List all assessments.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Update an assessment.

    Update an assessment.

    -
    path Parameters
    id
    required
    integer

    Assessment ID

    -
    Request Body schema: application/json

    Assessment data

    -
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    -
    object (assessment.RiskMessages)
    Array of objects (assessment.Section) [ items ]
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete an assessment.

    Delete an assessment.

    -
    path Parameters
    id
    required
    integer

    Assessment ID

    -

    Responses

    questionnaires

    Get an assessment by ID.

    Get an assessment by ID.

    -
    path Parameters
    id
    required
    integer

    Assessment ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    List all questionnaires.

    List all questionnaires.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a questionnaire.

    Create a questionnaire.

    -
    Request Body schema: application/json

    Questionnaire data

    -
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section) [ items ]
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get a questionnaire by ID.

    Get a questionnaire by ID.

    -
    path Parameters
    id
    required
    integer

    Questionnaire ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Update a questionnaire.

    Update a questionnaire. If the Questionnaire +

    path Parameters
    id
    required
    integer

    Application ID

    +
    source
    required
    string

    Fact key

    +
    Request Body schema: application/json

    Fact map

    +
    property name*
    additional property
    any

    Responses

    Request samples

    Content type
    application/json
    { }

    Update the owner and contributors of an Application.

    Update the owner and contributors of an Application.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    Request Body schema: application/json

    Application stakeholders

    +
    Array of objects (api.Ref)
    object (api.Ref)

    Responses

    Request samples

    Content type
    application/json
    {
    • "contributors": [
      ],
    • "owner": {
      }
    }

    List tag references.

    List tag references.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Add tag association.

    Ensure tag is associated with the application.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    Request Body schema: application/json

    Tag data

    +
    id
    required
    integer
    name
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "id": 0,
    • "name": "string"
    }

    Replace tag associations.

    Replace tag associations.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    query Parameters
    source
    string

    Source

    +
    Request Body schema: application/json

    Tag references

    +
    Array
    id
    required
    integer
    name
    string
    source
    string
    virtual
    boolean

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Delete tag association.

    Ensure tag is not associated with the application.

    +
    path Parameters
    id
    required
    integer

    Application ID

    +
    sid
    required
    string

    Tag ID

    +

    Responses

    archetypes

    List all archetypes.

    List all archetypes.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an archetype.

    Create an archetype.

    +
    Request Body schema: application/json

    Archetype data

    +
    Array of objects (api.Ref)
    assessed
    boolean
    Array of objects (api.Ref)
    comments
    string
    confidence
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef)
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    risk
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    Array of objects (api.TagRef)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Get an archetype by ID.

    Get an archetype by ID.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Update an archetype.

    Update an archetype.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +
    Request Body schema: application/json

    Archetype data

    +
    Array of objects (api.Ref)
    assessed
    boolean
    Array of objects (api.Ref)
    comments
    string
    confidence
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TagRef)
    description
    string
    id
    integer
    name
    string
    object (api.Ref)
    risk
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    Array of objects (api.TagRef)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "assessed": true,
    • "assessments": [
      ],
    • "comments": "string",
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "criteria": [
      ],
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "review": {
      },
    • "risk": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "tags": [
      ],
    • "updateUser": "string"
    }

    Delete an archetype.

    Delete an archetype.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +

    Responses

    List the assessments of an archetype.

    List the assessments of an archetype.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an archetype assessment.

    Create an archetype assessment.

    +
    path Parameters
    id
    required
    integer

    Archetype ID

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section)
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    assessments

    List all assessments.

    List all assessments.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Update an assessment.

    Update an assessment.

    +
    path Parameters
    id
    required
    integer

    Assessment ID

    +
    Request Body schema: application/json

    Assessment data

    +
    object (api.Ref)
    object (api.Ref)
    confidence
    integer
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    risk
    string

    read only

    +
    object (assessment.RiskMessages)
    Array of objects (assessment.Section)
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    status
    string
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete an assessment.

    Delete an assessment.

    +
    path Parameters
    id
    required
    integer

    Assessment ID

    +

    Responses

    questionnaires

    Get an assessment by ID.

    Get an assessment by ID.

    +
    path Parameters
    id
    required
    integer

    Assessment ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "confidence": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "questionnaire": {
      },
    • "risk": "string",
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "status": "string",
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    List all questionnaires.

    List all questionnaires.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a questionnaire.

    Create a questionnaire.

    +
    Request Body schema: application/json

    Questionnaire data

    +
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section)
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Get a questionnaire by ID.

    Get a questionnaire by ID.

    +
    path Parameters
    id
    required
    integer

    Questionnaire ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Update a questionnaire.

    Update a questionnaire. If the Questionnaire is builtin, only its "required" field can be changed and all other fields will be ignored.

    -
    path Parameters
    id
    required
    integer

    Questionnaire ID

    -
    Request Body schema: application/json

    Questionnaire data

    -
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section) [ items ]
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete a questionnaire.

    Delete a questionnaire.

    -
    path Parameters
    id
    required
    integer

    Questionnaire ID

    -

    Responses

    auth

    Login and obtain a bearer token.

    Login and obtain a bearer token.

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    Refresh bearer token.

    Refresh bearer token.

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    batch

    Batch-create Tags.

    Batch-create Tags.

    -
    Request Body schema: application/json

    Tags data

    -
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Batch-create Tickets.

    Batch-create Tickets.

    -
    Request Body schema: application/json

    Tickets data

    -
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    fields
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    tags

    Batch-create Tags.

    Batch-create Tags.

    -
    Request Body schema: application/json

    Tags data

    -
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tags.

    List all tags.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag.

    Create a tag.

    -
    Request Body schema: application/json

    Tag data

    -
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Get a tag by ID.

    Get a tag by ID.

    -
    path Parameters
    id
    required
    integer

    Tag ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Update a tag.

    Update a tag.

    -
    path Parameters
    id
    required
    integer

    Tag ID

    -
    Request Body schema: application/json

    Tag data

    -
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Delete a tag.

    Delete a tag.

    -
    path Parameters
    id
    required
    integer

    Tag ID

    -

    Responses

    tickets

    Batch-create Tickets.

    Batch-create Tickets.

    -
    Request Body schema: application/json

    Tickets data

    -
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    fields
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tickets.

    List all tickets.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ticket.

    Create a ticket.

    -
    Request Body schema: application/json

    Ticket data

    -
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    fields
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Get a ticket by ID.

    Get a ticket by ID.

    -
    path Parameters
    id
    required
    integer

    Ticket ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Delete a ticket.

    Delete a ticket.

    -
    path Parameters
    id
    required
    integer

    Ticket id

    -

    Responses

    buckets

    List all buckets.

    List all buckets.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a bucket.

    Create a bucket.

    -
    path Parameters
    name
    required
    string

    Bucket name

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "path": "string",
    • "updateUser": "string"
    }

    Get a bucket by ID.

    Get a bucket by ID. +

    path Parameters
    id
    required
    integer

    Questionnaire ID

    +
    Request Body schema: application/json

    Questionnaire data

    +
    builtin
    boolean
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    required
    boolean
    required
    object (assessment.RiskMessages)
    required
    Array of objects (assessment.Section)
    required
    object (assessment.Thresholds)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "builtin": true,
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "required": true,
    • "riskMessages": {
      },
    • "sections": [
      ],
    • "thresholds": {
      },
    • "updateUser": "string"
    }

    Delete a questionnaire.

    Delete a questionnaire.

    +
    path Parameters
    id
    required
    integer

    Questionnaire ID

    +

    Responses

    auth

    Login and obtain a bearer token.

    Login and obtain a bearer token.

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    Refresh bearer token.

    Refresh bearer token.

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "expiry": 0,
    • "password": "string",
    • "refresh": "string",
    • "token": "string",
    • "user": "string"
    }

    batch

    Batch-create Tags.

    Batch-create Tags.

    +
    Request Body schema: application/json

    Tags data

    +
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Batch-create Tickets.

    Batch-create Tickets.

    +
    Request Body schema: application/json

    Tickets data

    +
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    tags

    Batch-create Tags.

    Batch-create Tags.

    +
    Request Body schema: application/json

    Tags data

    +
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tags.

    List all tags.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag.

    Create a tag.

    +
    Request Body schema: application/json

    Tag data

    +
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Get a tag by ID.

    Get a tag by ID.

    +
    path Parameters
    id
    required
    integer

    Tag ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Update a tag.

    Update a tag.

    +
    path Parameters
    id
    required
    integer

    Tag ID

    +
    Request Body schema: application/json

    Tag data

    +
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "category": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "updateUser": "string"
    }

    Delete a tag.

    Delete a tag.

    +
    path Parameters
    id
    required
    integer

    Tag ID

    +

    Responses

    tickets

    Batch-create Tickets.

    Batch-create Tickets.

    +
    Request Body schema: application/json

    Tickets data

    +
    Array
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    [
    • {
      }
    ]

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    List all tickets.

    List all tickets.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ticket.

    Create a ticket.

    +
    Request Body schema: application/json

    Ticket data

    +
    required
    object (api.Ref)
    createTime
    string
    createUser
    string
    error
    boolean
    object (api.Fields)
    id
    integer
    kind
    required
    string
    lastUpdated
    string
    link
    string
    message
    string
    parent
    required
    string
    reference
    string
    status
    string
    required
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Get a ticket by ID.

    Get a ticket by ID.

    +
    path Parameters
    id
    required
    integer

    Ticket ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "error": true,
    • "fields": { },
    • "id": 0,
    • "kind": "string",
    • "lastUpdated": "string",
    • "link": "string",
    • "message": "string",
    • "parent": "string",
    • "reference": "string",
    • "status": "string",
    • "tracker": {
      },
    • "updateUser": "string"
    }

    Delete a ticket.

    Delete a ticket.

    +
    path Parameters
    id
    required
    integer

    Ticket id

    +

    Responses

    buckets

    List all buckets.

    List all buckets.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a bucket.

    Create a bucket.

    +
    path Parameters
    name
    required
    string

    Bucket name

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "path": "string",
    • "updateUser": "string"
    }

    Get a bucket by ID.

    Get a bucket by ID. Returns api.Bucket when Accept=application/json. Else returns index.html when Accept=text/html. Else returns tarball.

    -
    path Parameters
    id
    required
    integer

    Bucket ID

    -

    Responses

    Delete a bucket.

    Delete a bucket.

    -
    path Parameters
    id
    required
    integer

    Bucket ID

    -

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. +

    path Parameters
    id
    required
    integer

    Bucket ID

    +

    Responses

    Delete a bucket.

    Delete a bucket.

    +
    path Parameters
    id
    required
    integer

    Bucket ID

    +

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. When path is FILE, returns file content. When path is DIRECTORY and Accept=text/html returns index.html. ?filter=glob supports directory content filtering. Else returns a tarball.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    wildcard
    required
    string

    Content path

    -
    query Parameters
    filter
    string

    Filter

    -

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    -
    path Parameters
    id
    required
    integer

    Bucket ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    -
    path Parameters
    id
    required
    integer

    Bucket ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    businessservices

    List all business services.

    List all business services.

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Create a business service.

    Create a business service.

    -
    Request Body schema: application/json

    Business service data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Get a business service by ID.

    Get a business service by ID.

    -
    path Parameters
    id
    required
    integer

    Business Service ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Update a business service.

    Update a business service.

    -
    path Parameters
    id
    required
    integer

    Business service ID

    -
    Request Body schema: application/json

    Business service data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Delete a business service.

    Delete a business service.

    -
    path Parameters
    id
    required
    integer

    Business service ID

    -

    Responses

    cache

    Delete a directory within the cache.

    Delete a directory within the cache.

    -

    Responses

    Get the cache.

    Get the cache.

    -
    path Parameters
    wildcard
    required
    string

    Cache DIR

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "capacity": "string",
    • "exists": true,
    • "path": "string",
    • "used": "string"
    }

    file

    List all files.

    List all files.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a file.

    Create a file.

    -
    path Parameters
    name
    required
    string

    File name

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "name": "string",
    • "path": "string",
    • "updateUser": "string"
    }

    Get a file by ID.

    Get a file by ID. Returns api.File when Accept=application/json else the file content.

    -
    path Parameters
    id
    required
    integer

    File ID

    -

    Responses

    Delete a file.

    Delete a file.

    -
    path Parameters
    id
    required
    integer

    File ID

    -

    Responses

    identities

    List all identities.

    List all identities.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an identity.

    Create an identity.

    -
    Request Body schema: application/json

    Identity data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Get an identity by ID.

    Get an identity by ID.

    -
    path Parameters
    id
    required
    integer

    Identity ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Update an identity.

    Update an identity.

    -
    path Parameters
    id
    required
    integer

    Identity ID

    -
    Request Body schema: application/json

    Identity data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Delete an identity.

    Delete an identity.

    -
    path Parameters
    id
    required
    integer

    Identity ID

    -

    Responses

    imports

    List imports.

    List imports.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • { }
    ]

    Get an import by ID.

    Get an import by ID.

    -
    path Parameters
    id
    required
    integer

    Import ID

    -

    Responses

    Response samples

    Content type
    application/json
    { }

    Delete an import.

    Delete an import. This leaves any created application or dependency.

    -
    path Parameters
    id
    required
    integer

    Import ID

    -

    Responses

    List import summaries.

    List import summaries.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Export the source CSV for a particular import summary.

    Export the source CSV for a particular import summary.

    -
    query Parameters
    importSummary.id
    required
    string

    ImportSummary ID

    -

    Responses

    Upload a CSV containing applications and dependencies to import.

    Upload a CSV containing applications and dependencies to import.

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Get an import summary by ID.

    Get an import by ID.

    -
    path Parameters
    id
    required
    integer

    ImportSummary ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Delete an import summary and associated import records.

    Delete an import summary and associated import records.

    -
    path Parameters
    id
    required
    integer

    ImportSummary ID

    -

    Responses

    jobfunctions

    List all job functions.

    List all job functions.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a job function.

    Create a job function.

    -
    Request Body schema: application/json

    Job Function data

    -
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a job function by ID.

    Get a job function by ID.

    -
    path Parameters
    id
    required
    integer

    Job Function ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a job function.

    Update a job function.

    -
    path Parameters
    id
    required
    integer

    Job Function ID

    -
    Request Body schema: application/json

    Job Function data

    -
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a job function.

    Delete a job function.

    -
    path Parameters
    id
    required
    integer

    Job Function ID

    -

    Responses

    metrics

    Get Prometheus metrics.

    Get Prometheus metrics. +

    path Parameters
    id
    required
    integer

    Task ID

    +
    wildcard
    required
    string

    Content path

    +
    query Parameters
    filter
    string

    Filter

    +

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    +
    path Parameters
    id
    required
    integer

    Bucket ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    +
    path Parameters
    id
    required
    integer

    Bucket ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    businessservices

    List all business services.

    List all business services.

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Create a business service.

    Create a business service.

    +
    Request Body schema: application/json

    Business service data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Get a business service by ID.

    Get a business service by ID.

    +
    path Parameters
    id
    required
    integer

    Business Service ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Update a business service.

    Update a business service.

    +
    path Parameters
    id
    required
    integer

    Business service ID

    +
    Request Body schema: application/json

    Business service data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    name
    required
    string
    object (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "name": "string",
    • "owner": {
      },
    • "updateUser": "string"
    }

    Delete a business service.

    Delete a business service.

    +
    path Parameters
    id
    required
    integer

    Business service ID

    +

    Responses

    cache

    Delete a directory within the cache.

    Delete a directory within the cache.

    +

    Responses

    Get the cache.

    Get the cache.

    +
    path Parameters
    wildcard
    required
    string

    Cache DIR

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "capacity": "string",
    • "exists": true,
    • "path": "string",
    • "used": "string"
    }

    file

    List all files.

    List all files.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a file.

    Create a file.

    +
    path Parameters
    name
    required
    string

    File name

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "expiration": "string",
    • "id": 0,
    • "name": "string",
    • "path": "string",
    • "updateUser": "string"
    }

    Get a file by ID.

    Get a file by ID. Returns api.File when Accept=application/json else the file content.

    +
    path Parameters
    id
    required
    integer

    File ID

    +

    Responses

    Delete a file.

    Delete a file.

    +
    path Parameters
    id
    required
    integer

    File ID

    +

    Responses

    identities

    List all identities.

    List all identities.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an identity.

    Create an identity.

    +
    Request Body schema: application/json

    Identity data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Get an identity by ID.

    Get an identity by ID.

    +
    path Parameters
    id
    required
    integer

    Identity ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Update an identity.

    Update an identity.

    +
    path Parameters
    id
    required
    integer

    Identity ID

    +
    Request Body schema: application/json

    Identity data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    key
    string
    kind
    required
    string
    name
    required
    string
    password
    string
    settings
    string
    updateUser
    string
    user
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "key": "string",
    • "kind": "string",
    • "name": "string",
    • "password": "string",
    • "settings": "string",
    • "updateUser": "string",
    • "user": "string"
    }

    Delete an identity.

    Delete an identity.

    +
    path Parameters
    id
    required
    integer

    Identity ID

    +

    Responses

    imports

    List imports.

    List imports.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • { }
    ]

    Get an import by ID.

    Get an import by ID.

    +
    path Parameters
    id
    required
    integer

    Import ID

    +

    Responses

    Response samples

    Content type
    application/json
    { }

    Delete an import.

    Delete an import. This leaves any created application or dependency.

    +
    path Parameters
    id
    required
    integer

    Import ID

    +

    Responses

    List import summaries.

    List import summaries.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Export the source CSV for a particular import summary.

    Export the source CSV for a particular import summary.

    +
    query Parameters
    importSummary.id
    required
    string

    ImportSummary ID

    +

    Responses

    Upload a CSV containing applications and dependencies to import.

    Upload a CSV containing applications and dependencies to import.

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Get an import summary by ID.

    Get an import by ID.

    +
    path Parameters
    id
    required
    integer

    ImportSummary ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createEntities": true,
    • "createTime": "string",
    • "createUser": "string",
    • "filename": "string",
    • "id": 0,
    • "importStatus": "string",
    • "importTime": "string",
    • "invalidCount": 0,
    • "updateUser": "string",
    • "validCount": 0
    }

    Delete an import summary and associated import records.

    Delete an import summary and associated import records.

    +
    path Parameters
    id
    required
    integer

    ImportSummary ID

    +

    Responses

    jobfunctions

    List all job functions.

    List all job functions.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a job function.

    Create a job function.

    +
    Request Body schema: application/json

    Job Function data

    +
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a job function by ID.

    Get a job function by ID.

    +
    path Parameters
    id
    required
    integer

    Job Function ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a job function.

    Update a job function.

    +
    path Parameters
    id
    required
    integer

    Job Function ID

    +
    Request Body schema: application/json

    Job Function data

    +
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a job function.

    Delete a job function.

    +
    path Parameters
    id
    required
    integer

    Job Function ID

    +

    Responses

    metrics

    Get Prometheus metrics.

    Get Prometheus metrics. Wrapper for Prometheus-supplied handler. Served on port defined by METRICS_PORT environment variable.

    -

    Responses

    migrationwaves

    List all migration waves.

    List all migration waves.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a migration wave.

    Create a migration wave.

    -
    Request Body schema: application/json

    Migration Wave data

    -
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Get a migration wave by ID.

    Get a migration wave by ID.

    -
    path Parameters
    id
    required
    integer

    Migration Wave ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Update a migration wave.

    Update a migration wave.

    -
    path Parameters
    id
    required
    integer

    MigrationWave id

    -
    Request Body schema: application/json

    MigrationWave data

    -
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Delete a migration wave.

    Delete a migration wave.

    -
    path Parameters
    id
    required
    integer

    MigrationWave id

    -

    Responses

    proxies

    List all proxies.

    List all proxies.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an proxy.

    Create an proxy.

    -
    Request Body schema: application/json

    Proxy data

    -
    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Get an proxy by ID.

    Get an proxy by ID.

    -
    path Parameters
    id
    required
    integer

    Proxy ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Update an proxy.

    Update an proxy.

    -
    path Parameters
    id
    required
    integer

    Proxy ID

    -
    Request Body schema: application/json

    Proxy data

    -
    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Delete an proxy.

    Delete an proxy.

    -
    path Parameters
    id
    required
    integer

    Proxy ID

    -

    Responses

    reviews

    List all reviews.

    List all reviews.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a review.

    Create a review.

    -
    Request Body schema: application/json

    Review data

    -
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Copy a review from one application to others.

    Copy a review from one application to others.

    -
    Request Body schema: application/json

    Review copy request data

    -
    sourceReview
    required
    integer
    targetApplications
    required
    Array of integers[ items ]

    Responses

    Request samples

    Content type
    application/json
    {
    • "sourceReview": 0,
    • "targetApplications": [
      ]
    }

    Get a review by ID.

    Get a review by ID.

    -
    path Parameters
    id
    required
    integer

    Review ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Update a review.

    Update a review.

    -
    path Parameters
    id
    required
    integer

    Review ID

    -
    Request Body schema: application/json

    Review data

    -
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Delete a review.

    Delete a review.

    -
    path Parameters
    id
    required
    integer

    Review ID

    -

    Responses

    rulesets

    List all bindings.

    List all bindings. +

    Responses

    migrationwaves

    List all migration waves.

    List all migration waves.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a migration wave.

    Create a migration wave.

    +
    Request Body schema: application/json

    Migration Wave data

    +
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Get a migration wave by ID.

    Get a migration wave by ID.

    +
    path Parameters
    id
    required
    integer

    Migration Wave ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Update a migration wave.

    Update a migration wave.

    +
    path Parameters
    id
    required
    integer

    MigrationWave id

    +
    Request Body schema: application/json

    MigrationWave data

    +
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    endDate
    string
    id
    integer
    name
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    startDate
    string
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "applications": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "endDate": "string",
    • "id": 0,
    • "name": "string",
    • "stakeholderGroups": [
      ],
    • "stakeholders": [
      ],
    • "startDate": "string",
    • "updateUser": "string"
    }

    Delete a migration wave.

    Delete a migration wave.

    +
    path Parameters
    id
    required
    integer

    MigrationWave id

    +

    Responses

    proxies

    List all proxies.

    List all proxies.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create an proxy.

    Create an proxy.

    +
    Request Body schema: application/json

    Proxy data

    +
    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Get an proxy by ID.

    Get an proxy by ID.

    +
    path Parameters
    id
    required
    integer

    Proxy ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Update an proxy.

    Update an proxy.

    +
    path Parameters
    id
    required
    integer

    Proxy ID

    +
    Request Body schema: application/json

    Proxy data

    +
    createTime
    string
    createUser
    string
    enabled
    boolean
    excluded
    Array of strings
    host
    string
    id
    integer
    object (api.Ref)
    kind
    string
    Enum: "http" "https"
    port
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "enabled": true,
    • "excluded": [
      ],
    • "host": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "http",
    • "port": 0,
    • "updateUser": "string"
    }

    Delete an proxy.

    Delete an proxy.

    +
    path Parameters
    id
    required
    integer

    Proxy ID

    +

    Responses

    reviews

    List all reviews.

    List all reviews.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a review.

    Create a review.

    +
    Request Body schema: application/json

    Review data

    +
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Copy a review from one application to others.

    Copy a review from one application to others.

    +
    Request Body schema: application/json

    Review copy request data

    +
    sourceReview
    required
    integer
    targetApplications
    required
    Array of integers

    Responses

    Request samples

    Content type
    application/json
    {
    • "sourceReview": 0,
    • "targetApplications": [
      ]
    }

    Get a review by ID.

    Get a review by ID.

    +
    path Parameters
    id
    required
    integer

    Review ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Update a review.

    Update a review.

    +
    path Parameters
    id
    required
    integer

    Review ID

    +
    Request Body schema: application/json

    Review data

    +
    object (api.Ref)
    object (api.Ref)
    businessCriticality
    integer
    comments
    string
    createTime
    string
    createUser
    string
    effortEstimate
    string
    id
    integer
    proposedAction
    string
    updateUser
    string
    workPriority
    integer

    Responses

    Request samples

    Content type
    application/json
    {
    • "application": {
      },
    • "archetype": {
      },
    • "businessCriticality": 0,
    • "comments": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "effortEstimate": "string",
    • "id": 0,
    • "proposedAction": "string",
    • "updateUser": "string",
    • "workPriority": 0
    }

    Delete a review.

    Delete a review.

    +
    path Parameters
    id
    required
    integer

    Review ID

    +

    Responses

    rulesets

    List all bindings.

    List all bindings. filters:

    • name
    • labels
    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ruleset.

    Create a ruleset.

    -
    Request Body schema: application/json

    RuleSet data

    -
    createTime
    string
    createUser
    string
    Array of objects (api.Ref) [ items ]
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Get a RuleSet by ID.

    Get a RuleSet by ID.

    -
    path Parameters
    id
    required
    integer

    RuleSet ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Update a ruleset.

    Update a ruleset.

    -
    path Parameters
    id
    required
    integer

    RuleSet ID

    -
    Request Body schema: application/json

    RuleSet data

    -
    createTime
    string
    createUser
    string
    Array of objects (api.Ref) [ items ]
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Delete a ruleset.

    Delete a ruleset.

    -
    path Parameters
    id
    required
    integer

    RuleSet ID

    -

    Responses

    schema

    Get the API schema.

    Get the API schema.

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "paths": [
      ],
    • "version": "string"
    }

    settings

    List all settings.

    List all settings.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a setting.

    Create a setting.

    -
    Request Body schema: application/json

    Setting data

    -
    key
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Get a setting by its key.

    Get a setting by its key.

    -
    path Parameters
    key
    required
    string

    Key

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Update a setting.

    Update a setting.

    -
    path Parameters
    key
    required
    string

    Key

    -

    Responses

    Create a setting.

    Create a setting.

    -
    path Parameters
    key
    required
    string

    Key

    -
    Request Body schema: application/json

    Setting value

    -
    key
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Delete a setting.

    Delete a setting.

    -
    path Parameters
    key
    required
    string

    Key

    -

    Responses

    stakeholdergroups

    List all stakeholder groups.

    List all stakeholder groups.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder group.

    Create a stakeholder group.

    -
    Request Body schema: application/json

    Stakeholder Group data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder group by ID.

    Get a stakeholder group by ID.

    -
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder group.

    Update a stakeholder group.

    -
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    -
    Request Body schema: application/json

    Stakeholder Group data

    -
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder group.

    Delete a stakeholder group.

    -
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    -

    Responses

    stakeholders

    List all stakeholders.

    List all stakeholders.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder.

    Create a stakeholder.

    -
    Request Body schema: application/json

    Stakeholder data

    -
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder by ID.

    Get a stakeholder by ID.

    -
    path Parameters
    id
    required
    integer

    Stakeholder ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder.

    Update a stakeholder.

    -
    path Parameters
    id
    required
    integer

    Stakeholder ID

    -
    Request Body schema: application/json

    Stakeholder data

    -
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref) [ items ]
    name
    required
    string
    Array of objects (api.Ref) [ items ]
    Array of objects (api.Ref) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder.

    Delete a stakeholder.

    -
    path Parameters
    id
    required
    integer

    Stakeholder ID

    -

    Responses

    tagcategories

    List all tag categories.

    List all tag categories.

    -
    query Parameters
    name
    string

    Optional category name filter

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag category.

    Create a tag category.

    -
    Request Body schema: application/json

    Tag Category data

    -
    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref) [ items ]
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Get a tag category by ID.

    Get a tag category by ID.

    -
    path Parameters
    id
    required
    integer

    Tag Category ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Update a tag category.

    Update a tag category.

    -
    path Parameters
    id
    required
    integer

    Tag Category ID

    -
    Request Body schema: application/json

    Tag Category data

    -
    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref) [ items ]
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Delete a tag category.

    Delete a tag category.

    -
    path Parameters
    id
    required
    integer

    Tag Category ID

    -

    Responses

    List the tags in the tag category.

    List the tags in the tag category.

    -
    path Parameters
    id
    required
    integer

    Tag Category ID

    -
    query Parameters
    name
    string

    Optional tag name filter

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    targets

    List all targets.

    List all targets.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a target.

    Create a target.

    -
    Request Body schema: application/json

    Target data

    -
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label) [ items ]
    name
    string
    provider
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Get a Target by ID.

    Get a Target by ID.

    -
    path Parameters
    id
    required
    integer

    Target ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Update a target.

    Update a target.

    -
    path Parameters
    id
    required
    integer

    Target ID

    -
    Request Body schema: application/json

    Target data

    -
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label) [ items ]
    name
    string
    provider
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Delete a target.

    Delete a target.

    -
    path Parameters
    id
    required
    integer

    Target ID

    -

    Responses

    taskgroups

    List all task groups.

    List all task groups.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task group.

    Create a task group.

    -
    Request Body schema: application/json

    TaskGroup data

    -
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Get a task group by ID.

    Get a task group by ID.

    -
    path Parameters
    id
    required
    integer

    TaskGroup ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Update a task group.

    Update a task group.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    Request Body schema: application/json

    Task data

    -
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Delete a task group.

    Delete a task group.

    -
    path Parameters
    id
    required
    integer

    TaskGroup ID

    -

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a ruleset.

    Create a ruleset.

    +
    Request Body schema: application/json

    RuleSet data

    +
    createTime
    string
    createUser
    string
    Array of objects (api.Ref)
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Get a RuleSet by ID.

    Get a RuleSet by ID.

    +
    path Parameters
    id
    required
    integer

    RuleSet ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Update a ruleset.

    Update a ruleset.

    +
    path Parameters
    id
    required
    integer

    RuleSet ID

    +
    Request Body schema: application/json

    RuleSet data

    +
    createTime
    string
    createUser
    string
    Array of objects (api.Ref)
    description
    string
    id
    integer
    object (api.Ref)
    kind
    string
    name
    string
    object (api.Repository)
    Array of objects (api.Rule)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "dependsOn": [
      ],
    • "description": "string",
    • "id": 0,
    • "identity": {
      },
    • "kind": "string",
    • "name": "string",
    • "repository": {
      },
    • "rules": [
      ],
    • "updateUser": "string"
    }

    Delete a ruleset.

    Delete a ruleset.

    +
    path Parameters
    id
    required
    integer

    RuleSet ID

    +

    Responses

    schema

    Get the API schema.

    Get the API schema.

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "paths": [
      ],
    • "version": "string"
    }

    settings

    List all settings.

    List all settings.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a setting.

    Create a setting.

    +
    Request Body schema: application/json

    Setting data

    +
    key
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Get a setting by its key.

    Get a setting by its key.

    +
    path Parameters
    key
    required
    string

    Key

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Update a setting.

    Update a setting.

    +
    path Parameters
    key
    required
    string

    Key

    +

    Responses

    Create a setting.

    Create a setting.

    +
    path Parameters
    key
    required
    string

    Key

    +
    Request Body schema: application/json

    Setting value

    +
    key
    string
    value
    object

    Responses

    Request samples

    Content type
    application/json
    {
    • "key": "string",
    • "value": { }
    }

    Delete a setting.

    Delete a setting.

    +
    path Parameters
    key
    required
    string

    Key

    +

    Responses

    stakeholdergroups

    List all stakeholder groups.

    List all stakeholder groups.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder group.

    Create a stakeholder group.

    +
    Request Body schema: application/json

    Stakeholder Group data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref)
    name
    required
    string
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder group by ID.

    Get a stakeholder group by ID.

    +
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder group.

    Update a stakeholder group.

    +
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    +
    Request Body schema: application/json

    Stakeholder Group data

    +
    createTime
    string
    createUser
    string
    description
    string
    id
    integer
    Array of objects (api.Ref)
    name
    required
    string
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "createTime": "string",
    • "createUser": "string",
    • "description": "string",
    • "id": 0,
    • "migrationWaves": [
      ],
    • "name": "string",
    • "stakeholders": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder group.

    Delete a stakeholder group.

    +
    path Parameters
    id
    required
    integer

    Stakeholder Group ID

    +

    Responses

    stakeholders

    List all stakeholders.

    List all stakeholders.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a stakeholder.

    Create a stakeholder.

    +
    Request Body schema: application/json

    Stakeholder data

    +
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref)
    name
    required
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Get a stakeholder by ID.

    Get a stakeholder by ID.

    +
    path Parameters
    id
    required
    integer

    Stakeholder ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Update a stakeholder.

    Update a stakeholder.

    +
    path Parameters
    id
    required
    integer

    Stakeholder ID

    +
    Request Body schema: application/json

    Stakeholder data

    +
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    createTime
    string
    createUser
    string
    email
    required
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Ref)
    name
    required
    string
    Array of objects (api.Ref)
    Array of objects (api.Ref)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "businessServices": [
      ],
    • "contributes": [
      ],
    • "createTime": "string",
    • "createUser": "string",
    • "email": "string",
    • "id": 0,
    • "jobFunction": {
      },
    • "migrationWaves": [
      ],
    • "name": "string",
    • "owns": [
      ],
    • "stakeholderGroups": [
      ],
    • "updateUser": "string"
    }

    Delete a stakeholder.

    Delete a stakeholder.

    +
    path Parameters
    id
    required
    integer

    Stakeholder ID

    +

    Responses

    tagcategories

    List all tag categories.

    List all tag categories.

    +
    query Parameters
    name
    string

    Optional category name filter

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tag category.

    Create a tag category.

    +
    Request Body schema: application/json

    Tag Category data

    +
    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref)
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Get a tag category by ID.

    Get a tag category by ID.

    +
    path Parameters
    id
    required
    integer

    Tag Category ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Update a tag category.

    Update a tag category.

    +
    path Parameters
    id
    required
    integer

    Tag Category ID

    +
    Request Body schema: application/json

    Tag Category data

    +
    colour
    string
    createTime
    string
    createUser
    string
    id
    integer
    name
    required
    string
    rank
    integer
    Array of objects (api.Ref)
    updateUser
    string
    username
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "colour": "string",
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "name": "string",
    • "rank": 0,
    • "tags": [
      ],
    • "updateUser": "string",
    • "username": "string"
    }

    Delete a tag category.

    Delete a tag category.

    +
    path Parameters
    id
    required
    integer

    Tag Category ID

    +

    Responses

    List the tags in the tag category.

    List the tags in the tag category.

    +
    path Parameters
    id
    required
    integer

    Tag Category ID

    +
    query Parameters
    name
    string

    Optional tag name filter

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    targets

    List all targets.

    List all targets.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a target.

    Create a target.

    +
    Request Body schema: application/json

    Target data

    +
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label)
    name
    string
    provider
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Get a Target by ID.

    Get a Target by ID.

    +
    path Parameters
    id
    required
    integer

    Target ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Update a target.

    Update a target.

    +
    path Parameters
    id
    required
    integer

    Target ID

    +
    Request Body schema: application/json

    Target data

    +
    choice
    boolean
    createTime
    string
    createUser
    string
    custom
    boolean
    description
    string
    id
    integer
    object (api.Ref)
    Array of objects (api.Label)
    name
    string
    provider
    string
    object (api.RuleSet)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "choice": true,
    • "createTime": "string",
    • "createUser": "string",
    • "custom": true,
    • "description": "string",
    • "id": 0,
    • "image": {
      },
    • "labels": [
      ],
    • "name": "string",
    • "provider": "string",
    • "ruleset": {
      },
    • "updateUser": "string"
    }

    Delete a target.

    Delete a target.

    +
    path Parameters
    id
    required
    integer

    Target ID

    +

    Responses

    taskgroups

    List all task groups.

    List all task groups.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task group.

    Create a task group.

    +
    Request Body schema: application/json

    TaskGroup data

    +
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Get a task group by ID.

    Get a task group by ID.

    +
    path Parameters
    id
    required
    integer

    TaskGroup ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Update a task group.

    Update a task group.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    Request Body schema: application/json

    Task data

    +
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    Delete a task group.

    Delete a task group.

    +
    path Parameters
    id
    required
    integer

    TaskGroup ID

    +

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. Returns index.html for directories when Accept=text/html else a tarball. ?filter=glob supports directory content filtering.

    -
    path Parameters
    id
    required
    integer

    TaskGroup ID

    -
    wildcard
    required
    string

    Content path

    -
    query Parameters
    filter
    string

    Filter

    -

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    -
    path Parameters
    id
    required
    integer

    TaskGroup ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Submit a task group.

    Submit a task group.

    -
    path Parameters
    id
    required
    integer

    TaskGroup ID

    -
    Request Body schema: application/json

    TaskGroup data (optional)

    -
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task) [ items ]
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    tasks

    List all tasks.

    List all tasks.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task.

    Create a task.

    -
    Request Body schema: application/json

    Task data

    -
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Get a task by ID.

    Get a task by ID.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Update a task.

    Update a task.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    Request Body schema: application/json

    Task data

    -
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Delete a task.

    Delete a task.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. +

    path Parameters
    id
    required
    integer

    TaskGroup ID

    +
    wildcard
    required
    string

    Content path

    +
    query Parameters
    filter
    string

    Filter

    +

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    +
    path Parameters
    id
    required
    integer

    TaskGroup ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Submit a task group.

    Submit a task group.

    +
    path Parameters
    id
    required
    integer

    TaskGroup ID

    +
    Request Body schema: application/json

    TaskGroup data (optional)

    +
    addon
    string
    object (api.Ref)
    createTime
    string
    createUser
    string
    data
    required
    object
    id
    integer
    name
    string
    state
    string
    Array of objects (api.Task)
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "addon": "string",
    • "bucket": {
      },
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "id": 0,
    • "name": "string",
    • "state": "string",
    • "tasks": [
      ],
    • "updateUser": "string"
    }

    tasks

    List all tasks.

    List all tasks.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a task.

    Create a task.

    +
    Request Body schema: application/json

    Task data

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError)
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Get a task by ID.

    Get a task by ID.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Update a task.

    Update a task.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    Request Body schema: application/json

    Task data

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError)
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    Delete a task.

    Delete a task.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +

    Responses

    Get bucket content by ID and path.

    Get bucket content by ID and path. Returns index.html for directories when Accept=text/html else a tarball. ?filter=glob supports directory content filtering.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    wildcard
    required
    string

    Content path

    -
    query Parameters
    filter
    string

    Filter

    -

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    wildcard
    required
    string

    Content path

    -

    Responses

    Cancel a task.

    Cancel a task.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -

    Responses

    Update a task report.

    Update a task report.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    Request Body schema: application/json

    TaskReport data

    -
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError) [ items ]
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Create a task report.

    Update a task report.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    Request Body schema: application/json

    TaskReport data

    -
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError) [ items ]
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Delete a task report.

    Delete a task report.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -

    Responses

    Submit a task.

    Submit a task.

    -
    path Parameters
    id
    required
    integer

    Task ID

    -
    Request Body schema: application/json

    Task data (optional)

    -
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError) [ items ]
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    trackers

    List all trackers.

    List all trackers.

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tracker.

    Create a tracker.

    -
    Request Body schema: application/json

    Tracker data

    -
    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Get a tracker by ID.

    Get a tracker by ID.

    -
    path Parameters
    id
    required
    integer

    Tracker ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Update a tracker.

    Update a tracker.

    -
    path Parameters
    id
    required
    integer

    Tracker id

    -
    Request Body schema: application/json

    Tracker data

    -
    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Delete a tracker.

    Delete a tracker.

    -
    path Parameters
    id
    required
    integer

    Tracker id

    -

    Responses

    List a tracker's projects.

    List a tracker's projects.

    -
    path Parameters
    id
    required
    integer

    Tracker ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get a tracker project by ID.

    Get a tracker project by ID.

    -
    path Parameters
    id
    required
    integer

    Tracker ID

    -
    id2
    required
    string

    Project ID

    -

    Responses

    Response samples

    Content type
    application/json
    {
    • "id": "string",
    • "name": "string"
    }

    List a tracker project's issue types.

    List a tracker project's issue types.

    -
    path Parameters
    id
    required
    integer

    Tracker ID

    -
    id2
    required
    string

    Project ID

    -

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]
    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    wildcard
    required
    string

    Content path

    +
    query Parameters
    filter
    string

    Filter

    +

    Responses

    Upload bucket content by ID and path.

    Upload bucket content by ID and path (handles both [post] and [put] requests).

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Delete bucket content by ID and path.

    Delete bucket content by ID and path.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    wildcard
    required
    string

    Content path

    +

    Responses

    Cancel a task.

    Cancel a task.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +

    Responses

    Update a task report.

    Update a task report.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    Request Body schema: application/json

    TaskReport data

    +
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError)
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Create a task report.

    Update a task report.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    Request Body schema: application/json

    TaskReport data

    +
    activity
    Array of strings
    completed
    integer
    createTime
    string
    createUser
    string
    Array of objects (api.TaskError)
    id
    integer
    result
    object
    status
    string
    task
    integer
    total
    integer
    updateUser
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "completed": 0,
    • "createTime": "string",
    • "createUser": "string",
    • "errors": [
      ],
    • "id": 0,
    • "result": { },
    • "status": "string",
    • "task": 0,
    • "total": 0,
    • "updateUser": "string"
    }

    Delete a task report.

    Delete a task report.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +

    Responses

    Submit a task.

    Submit a task.

    +
    path Parameters
    id
    required
    integer

    Task ID

    +
    Request Body schema: application/json

    Task data (optional)

    +
    activity
    Array of strings
    addon
    required
    string
    object (api.Ref)
    object (api.Ref)
    canceled
    boolean
    createTime
    string
    createUser
    string
    data
    required
    object
    Array of objects (api.TaskError)
    id
    integer
    image
    string
    locator
    string
    name
    string
    pod
    string
    policy
    string
    priority
    integer
    purged
    boolean
    retries
    integer
    started
    string
    state
    string
    terminated
    string
    object (api.TTL)
    updateUser
    string
    variant
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "activity": [
      ],
    • "addon": "string",
    • "application": {
      },
    • "bucket": {
      },
    • "canceled": true,
    • "createTime": "string",
    • "createUser": "string",
    • "data": { },
    • "errors": [
      ],
    • "id": 0,
    • "image": "string",
    • "locator": "string",
    • "name": "string",
    • "pod": "string",
    • "policy": "string",
    • "priority": 0,
    • "purged": true,
    • "retries": 0,
    • "started": "string",
    • "state": "string",
    • "terminated": "string",
    • "ttl": {
      },
    • "updateUser": "string",
    • "variant": "string"
    }

    trackers

    List all trackers.

    List all trackers.

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Create a tracker.

    Create a tracker.

    +
    Request Body schema: application/json

    Tracker data

    +
    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Get a tracker by ID.

    Get a tracker by ID.

    +
    path Parameters
    id
    required
    integer

    Tracker ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Update a tracker.

    Update a tracker.

    +
    path Parameters
    id
    required
    integer

    Tracker id

    +
    Request Body schema: application/json

    Tracker data

    +
    connected
    boolean
    createTime
    string
    createUser
    string
    id
    integer
    required
    object (api.Ref)
    insecure
    boolean
    kind
    required
    string
    Enum: "jira-cloud" "jira-onprem"
    lastUpdated
    string
    message
    string
    name
    required
    string
    updateUser
    string
    url
    required
    string

    Responses

    Request samples

    Content type
    application/json
    {
    • "connected": true,
    • "createTime": "string",
    • "createUser": "string",
    • "id": 0,
    • "identity": {
      },
    • "insecure": true,
    • "kind": "jira-cloud",
    • "lastUpdated": "string",
    • "message": "string",
    • "name": "string",
    • "updateUser": "string",
    • "url": "string"
    }

    Delete a tracker.

    Delete a tracker.

    +
    path Parameters
    id
    required
    integer

    Tracker id

    +

    Responses

    List a tracker's projects.

    List a tracker's projects.

    +
    path Parameters
    id
    required
    integer

    Tracker ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]

    Get a tracker project by ID.

    Get a tracker project by ID.

    +
    path Parameters
    id
    required
    integer

    Tracker ID

    +
    id2
    required
    string

    Project ID

    +

    Responses

    Response samples

    Content type
    application/json
    {
    • "id": "string",
    • "name": "string"
    }

    List a tracker project's issue types.

    List a tracker project's issue types.

    +
    path Parameters
    id
    required
    integer

    Tracker ID

    +
    id2
    required
    string

    Project ID

    +

    Responses

    Response samples

    Content type
    application/json
    [
    • {
      }
    ]