diff --git a/go.mod b/go.mod index 9b5e698..5c4661a 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.19 require ( github.com/hashicorp/terraform v0.12.2 github.com/robfig/cron v1.2.0 - github.com/yext/go-teamcity v0.5.4 + github.com/yext/go-teamcity v0.5.5 ) require ( diff --git a/go.sum b/go.sum index 86d8496..8369af0 100644 --- a/go.sum +++ b/go.sum @@ -344,8 +344,8 @@ github.com/vmihailenco/msgpack v4.0.4+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6Ac github.com/xanzy/ssh-agent v0.2.1/go.mod h1:mLlQY/MoOhWBj+gOGMQkOeiEvkx+8pJSI+0Bx9h2kr4= github.com/xiang90/probing v0.0.0-20160813154853-07dd2e8dfe18/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xlab/treeprint v0.0.0-20161029104018-1d6e34225557/go.mod h1:ce1O1j6UtZfjr22oyGxGLbauSBp2YVXpARAosm7dHBg= -github.com/yext/go-teamcity v0.5.4 h1:KKA1wsNF2DGnq1tkCK5iTu4zzKvBYLcquU9DcYPPpo4= -github.com/yext/go-teamcity v0.5.4/go.mod h1:GC2xvLY4y27DU/01mveI8LsSBerjpCEtHk6eQ7ym8oc= +github.com/yext/go-teamcity v0.5.5 h1:3YiCouF6FUqHZku3rSHR9SN3tA1CN+idrMqllydj1yA= +github.com/yext/go-teamcity v0.5.5/go.mod h1:GC2xvLY4y27DU/01mveI8LsSBerjpCEtHk6eQ7ym8oc= github.com/zclconf/go-cty v0.0.0-20181129180422-88fbe721e0f8/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v0.0.0-20190426224007-b18a157db9e2/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= github.com/zclconf/go-cty v0.0.0-20190516203816-4fecf87372ec/go.mod h1:xnAOWiHeOqg2nWS62VtQ7pbOu17FtxJNW8RLEih+O3s= diff --git a/teamcity/resource_build_config.go b/teamcity/resource_build_config.go index 8ab11ba..94f979f 100644 --- a/teamcity/resource_build_config.go +++ b/teamcity/resource_build_config.go @@ -297,7 +297,7 @@ func resourceBuildConfigCreate(d *schema.ResourceData, meta interface{}) error { func resourceBuildConfigUpdate(d *schema.ResourceData, meta interface{}) error { client := meta.(*api.Client) - dt, err := getBuildConfiguration(client, d.Id()) + dt, err := client.BuildTypes.GetByID(d.Id()) if err != nil { return err } @@ -450,14 +450,41 @@ func resourceBuildConfigArchive(d *schema.ResourceData, meta interface{}) error } } - name := d.Get("name") - return client.BuildTypes.Rename(d.Id(), fmt.Sprintf("%s (Archived)", name.(string))) + parent, err := client.Projects.GetByID(d.Get("project_id").(string)) + if err != nil { + return err + } + + existingNames := map[string]struct{}{} + for _, child := range parent.BuildTypes.Items { + existingNames[child.Name] = struct{}{} + } + + var ( + oldName = d.Get("name") + newName = fmt.Sprintf("%s (Archived)", oldName) + ) + + /* + If "... (Archived)" is already taken, check if "... (Archive 2) to + "... (Archive 98)" are taken, using the first that is not. + If all were taken, try using "... (Archive 99)" without checking, + to get TeamCity to return a suitable error if it is also taken. + */ + for i := 2; i <= 99; i++ { + if _, exists := existingNames[newName]; !exists { + break + } + newName = fmt.Sprintf("%s (Archive %d)", oldName, i) + } + + return client.BuildTypes.Rename(d.Id(), newName) } func resourceBuildConfigRead(d *schema.ResourceData, meta interface{}) error { client := meta.(*api.Client) - dt, err := getBuildConfiguration(client, d.Id()) + dt, err := client.BuildTypes.GetByID(d.Id()) if err != nil { return err } @@ -527,15 +554,6 @@ func resourceBuildConfigRead(d *schema.ResourceData, meta interface{}) error { return nil } -func getBuildConfiguration(c *api.Client, id string) (*api.BuildType, error) { - dt, err := c.BuildTypes.GetByID(id) - if err != nil { - return nil, err - } - - return dt, nil -} - var stepTypeMap = map[string]string{ api.StepTypePowershell: "powershell", api.StepTypeCommandLine: "cmd_line", diff --git a/teamcity/resource_project.go b/teamcity/resource_project.go index ef8e205..b943121 100644 --- a/teamcity/resource_project.go +++ b/teamcity/resource_project.go @@ -210,8 +210,40 @@ func resourceProjectArchive(d *schema.ResourceData, meta interface{}) error { return err } - name := d.Get("name") - return client.Projects.Rename(d.Id(), fmt.Sprintf("%s (Archived)", name.(string))) + parentID, hasParent := d.GetOk("parent_id") + if !hasParent { + parentID = "_Root" + } + + parent, err := client.Projects.GetByID(parentID.(string)) + if err != nil { + return err + } + + existingNames := map[string]struct{}{} + for _, subproject := range parent.Projects.Items { + existingNames[subproject.Name] = struct{}{} + } + + var ( + oldName = d.Get("name") + newName = fmt.Sprintf("%s (Archived)", oldName) + ) + + /* + If "... (Archived)" is already taken, check if "... (Archive 2) to + "... (Archive 98)" are taken, using the first that is not. + If all were taken, try using "... (Archived 99)" without checking, + to get TeamCity to return a suitable error if it is also taken. + */ + for i := 2; i <= 99; i++ { + if _, exists := existingNames[newName]; !exists { + break + } + newName = fmt.Sprintf("%s (Archive %d)", oldName, i) + } + + return client.Projects.Rename(d.Id(), newName) } func resourceProjectImport(d *schema.ResourceData, meta interface{}) ([]*schema.ResourceData, error) {