diff --git a/client/robot_account.go b/client/robot_account.go index 253b185..fc191aa 100644 --- a/client/robot_account.go +++ b/client/robot_account.go @@ -1,19 +1,51 @@ package client import ( + "fmt" + "strings" + "github.com/BESTSELLER/terraform-provider-harbor/models" "github.com/hashicorp/terraform-plugin-sdk/helper/schema" ) -func RobotBody(d *schema.ResourceData, resource string) models.RobotBody { - return models.RobotBody{ +func RobotBody(d *schema.ResourceData, projectid string) models.RobotBody { + resource := strings.Replace(projectid, "s", "", +1) + + body := models.RobotBody{ Name: d.Get("name").(string), Description: d.Get("description").(string), - Access: []models.RobotBodyAccess{ - { - Action: d.Get("action").(string), - Resource: resource, - }, - }, } + _, existingAttributeOk := d.GetOk("action") + _, newAttributeOk := d.GetOk("actions") + + robotAccess := models.RobotBodyAccess{} + + if !existingAttributeOk && !newAttributeOk { + fmt.Errorf("one of action or actions must be configured") + + } else if existingAttributeOk { + robotAccess.Action = d.Get("action").(string) + robotAccess.Resource = resource + "/repository" + body.Access = append(body.Access, robotAccess) + + } else if newAttributeOk { + access := d.Get("actions").([]interface{}) + for _, v := range access { + + switch v.(string) { + case "push", "pull": + robotAccess.Action = v.(string) + robotAccess.Resource = resource + "/repository" + case "read": + robotAccess.Action = v.(string) + robotAccess.Resource = resource + "/helm-chart" + case "create": + robotAccess.Action = v.(string) + robotAccess.Resource = resource + "/helm-chart-version" + } + body.Access = append(body.Access, robotAccess) + } + } + + return body } diff --git a/docs/resources/robot_account.md b/docs/resources/robot_account.md index 5b12eca..db5c31d 100644 --- a/docs/resources/robot_account.md +++ b/docs/resources/robot_account.md @@ -10,7 +10,7 @@ resource "harbor_robot_account" "account" { name = "${harbor_project.main.name}" description = "Robot account used to push images to harbor" project_id = harbor_project.main.id - action = "push" + actions = ["push"] } ``` @@ -23,7 +23,17 @@ The following arguments are supported: * **project_id** - (Required) The project id of the project that the robot account will be associated with. -* **action** - (Optional) The action that the robot account will be able to perform on the project. Can be **"pull"** or **"push"** (Default: **pull**). +* **action** - **Deprecated** The action that the robot account will be able to perform on the project. Can be **"pull"** or **"push"**. + +* **actions** - (Optional) A list of actions that the robot account will be able to perform on the project.  + You to have set `["pull"]` as minimal requirement, if `["push"]` is set you don't need to set pull. Other combinations can be `["push","create","read"]` or `["push","read"]` or `["pull","read"]` + ``` + pull = permission to pull from docker registry + push = permission to push to docker registry + create = permission to created helm charts + read = permision to read helm charts + ``` + ## Attributes Reference In addition to all argument, the folloing attributes are exported: diff --git a/provider/resource_robot_account.go b/provider/resource_robot_account.go index c3c8b8b..bcf7976 100644 --- a/provider/resource_robot_account.go +++ b/provider/resource_robot_account.go @@ -34,8 +34,20 @@ func resourceRobotAccount() *schema.Resource { "action": { Type: schema.TypeString, Optional: true, - Default: "pull", - ForceNew: true, + // Default: "pull", + ForceNew: true, + Deprecated: "Use actions attribute instead. action Will be removed in the next Major version", + ConflictsWith: []string{"actions"}, + }, + "actions": { + Type: schema.TypeList, + Elem: &schema.Schema{ + Type: schema.TypeString, + }, + Optional: true, + // Default: ["pull"], + ForceNew: true, + ConflictsWith: []string{"action"}, }, "token": { Type: schema.TypeString, @@ -71,9 +83,8 @@ func resourceRobotAccountCreate(d *schema.ResourceData, m interface{}) error { projectid := d.Get("project_id").(string) url := projectid + "/robots" - resource := strings.Replace(projectid, "s", "", +1) + "/repository" - body := client.RobotBody(d, resource) + body := client.RobotBody(d, projectid) resp, headers, err := apiClient.SendRequest("POST", url, body, 201) if err != nil { diff --git a/provider/resource_robot_account_test.go b/provider/resource_robot_account_test.go index 9da9b08..ca3ef1f 100644 --- a/provider/resource_robot_account_test.go +++ b/provider/resource_robot_account_test.go @@ -25,8 +25,28 @@ func TestAccRobotBasic(t *testing.T) { testAccCheckResourceExists(harborRobotAccount), resource.TestCheckResourceAttr( harborRobotAccount, "name", "test_robot_account"), + // resource.TestCheckResourceAttr( + // harborRobotAccount, "action", "push"), + ), + }, + }, + }) +} + +func TestAccRobotMultipleAction(t *testing.T) { + resource.Test(t, resource.TestCase{ + PreCheck: func() { testAccPreCheck(t) }, + Providers: testAccProviders, + CheckDestroy: testAccCheckRobotDestroy, + Steps: []resource.TestStep{ + { + Config: testAccCheckRobotMultipleAction(), + Check: resource.ComposeTestCheckFunc( + testAccCheckResourceExists("harbor_project.main"), + + testAccCheckResourceExists(harborRobotAccount), resource.TestCheckResourceAttr( - harborRobotAccount, "action", "push"), + harborRobotAccount, "name", "test_robot_account"), ), }, }, @@ -54,11 +74,29 @@ func testAccCheckRobotDestroy(s *terraform.State) error { func testAccCheckRobotBasic() string { return fmt.Sprintf(` + resource "harbor_robot_account" "main" { + name = "test_robot_account" + description = "Robot account to be used to pull images" + project_id = harbor_project.main.id + actions = ["pull"] + + } + + resource "harbor_project" "main" { + name = "test_basic" + } + + `) +} + +func testAccCheckRobotMultipleAction() string { + return fmt.Sprintf(` + resource "harbor_robot_account" "main" { name = "test_robot_account" description = "Robot account to be used to push images" project_id = harbor_project.main.id - action = "push" + actions = ["push","read","create"] } resource "harbor_project" "main" {