-
Notifications
You must be signed in to change notification settings - Fork 93
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #147 from dweebo/issue-88/add-tag-immutability
Issue 88/add tag immutability support
- Loading branch information
Showing
6 changed files
with
268 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
package client | ||
|
||
import ( | ||
"log" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/BESTSELLER/terraform-provider-harbor/models" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func GetImmutableTagRuleBody(d *schema.ResourceData) *models.ImmutableTagRule { | ||
tagId := 0 | ||
if d.Id() != "" { | ||
lastSlashIndex := strings.LastIndex(d.Id(), "/") | ||
tagId, _ = strconv.Atoi(d.Id()[lastSlashIndex+1:]) | ||
} | ||
|
||
tags := []models.ImmutableTagRuleTagSelectors{} | ||
tag := models.ImmutableTagRuleTagSelectors{ | ||
Kind: "doublestar", | ||
} | ||
|
||
if d.Get("tag_matching").(string) != "" { | ||
tag.Decoration = "matches" | ||
tag.Pattern = d.Get("tag_matching").(string) | ||
d.Set("tag_excluding", nil) | ||
} | ||
if d.Get("tag_excluding").(string) != "" { | ||
tag.Decoration = "excludes" | ||
tag.Pattern = d.Get("tag_excluding").(string) | ||
d.Set("tag_matching", nil) | ||
} | ||
tags = append(tags, tag) | ||
|
||
scopeSelectorsRepository := models.ScopeSelectors{ | ||
Repository: []models.Repository{}, | ||
} | ||
|
||
repo := models.Repository{ | ||
Kind: "doublestar", | ||
} | ||
|
||
if d.Get("repo_matching").(string) != "" { | ||
repo.Decoration = "repoMatches" | ||
repo.Pattern = d.Get("repo_matching").(string) | ||
d.Set("repo_excluding", nil) | ||
} | ||
if d.Get("repo_excluding").(string) != "" { | ||
repo.Decoration = "repoExcludes" | ||
repo.Pattern = d.Get("repo_excluding").(string) | ||
d.Set("repo_matching", nil) | ||
} | ||
scopeSelectorsRepository.Repository = append(scopeSelectorsRepository.Repository, repo) | ||
|
||
body := models.ImmutableTagRule{ | ||
Id: tagId, | ||
Disabled: d.Get("disabled").(bool), | ||
ScopeSelectors: scopeSelectorsRepository, | ||
ImmutableTagRuleTagSelectors: tags, | ||
Action: "immutable", | ||
Template: "immutable_template", | ||
} | ||
|
||
log.Printf("[DEBUG] %+v\n ", body) | ||
|
||
return &body | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
# Resource: harbor_immutable_tag_rule | ||
|
||
## Example Usage | ||
|
||
```hcl | ||
resource "harbor_project" "main" { | ||
name = "acctest" | ||
} | ||
resource "harbor_immutable_tag_rule" "main" { | ||
project_id = harbor_project.main.id | ||
repo_matching = "**" | ||
tag_excluding = "latest" | ||
} | ||
``` | ||
|
||
## Argument Reference | ||
The following arguments are supported: | ||
|
||
* `disabled`- (Optional) Specify if the rule is disable or not. Defaults to `false` | ||
* `repo_matching`- (Optional) For the repositories matching. | ||
* `repo_excluding` - (Optional) For the repositories excuding. | ||
* `tag_matching`- (Optional) For the tag matching. | ||
* `tag_excluding` - (Optional) For the tag excuding. | ||
* `scope` - (Required) The project id of which you would like to apply this policy. | ||
|
||
## Import | ||
Harbor immutable tag rule can be imported using the `project and immutabletagrule ids` eg, | ||
|
||
` | ||
terraform import harbor_immutable_tag_rule.main /projects/4/immutabletagrules/25 | ||
` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
package models | ||
|
||
var PathImmutableTagRules = "/immutabletagrules" | ||
|
||
type ImmutableTagRule struct { | ||
Id int `json:"id,omitempty"` | ||
Disabled bool `json:"disabled"` | ||
ScopeSelectors ScopeSelectors `json:"scope_selectors"` | ||
ImmutableTagRuleTagSelectors []ImmutableTagRuleTagSelectors `json:"tag_selectors"` | ||
Action string `json:"action"` | ||
Template string `json:"template"` | ||
} | ||
|
||
type ImmutableTagRuleTagSelectors struct { | ||
Kind string `json:"kind"` | ||
Decoration string `json:"decoration"` | ||
Pattern string `json:"pattern"` | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,147 @@ | ||
package provider | ||
|
||
import ( | ||
"encoding/json" | ||
"fmt" | ||
"log" | ||
"strconv" | ||
"strings" | ||
|
||
"github.com/BESTSELLER/terraform-provider-harbor/client" | ||
"github.com/BESTSELLER/terraform-provider-harbor/models" | ||
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema" | ||
) | ||
|
||
func resourceImmutableTagRule() *schema.Resource { | ||
return &schema.Resource{ | ||
Schema: map[string]*schema.Schema{ | ||
"project_id": { | ||
Type: schema.TypeString, | ||
Required: true, | ||
ForceNew: true, | ||
}, | ||
"disabled": { | ||
Type: schema.TypeBool, | ||
Optional: true, | ||
Default: false, | ||
}, | ||
"repo_matching": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
// ConflictsWith: []string{".repo_excluding"}, | ||
}, | ||
"repo_excluding": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
// ConflictsWith: []string{".repo_matching"}, | ||
}, | ||
"tag_matching": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
// ConflictsWith: []string{".tag_excluding"}, | ||
}, | ||
"tag_excluding": { | ||
Type: schema.TypeString, | ||
Optional: true, | ||
// ConflictsWith: []string{".tag_matching"}, | ||
}, | ||
}, | ||
Create: resourceImmutableTagRuleCreate, | ||
Read: resourceImmutableTagRuleRead, | ||
Update: resourceImmutableTagRuleUpdate, | ||
Delete: resourceImmutableTagRuleDelete, | ||
Importer: &schema.ResourceImporter{ | ||
StateContext: schema.ImportStatePassthroughContext, | ||
}, | ||
} | ||
} | ||
|
||
func resourceImmutableTagRuleCreate(d *schema.ResourceData, m interface{}) error { | ||
apiClient := m.(*client.Client) | ||
|
||
projectid := checkProjectid(d.Get("project_id").(string)) | ||
path := projectid + models.PathImmutableTagRules | ||
|
||
body := client.GetImmutableTagRuleBody(d) | ||
id := "" | ||
|
||
_, headers, err := apiClient.SendRequest("POST", path, body, 201) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
id, err = client.GetID(headers) | ||
d.SetId(id) | ||
return resourceImmutableTagRuleRead(d, m) | ||
} | ||
|
||
func resourceImmutableTagRuleRead(d *schema.ResourceData, m interface{}) error { | ||
apiClient := m.(*client.Client) | ||
|
||
lastSlashIndex := strings.LastIndex(d.Id(), "/") | ||
projectImmutableTagRulePath := d.Id()[0:lastSlashIndex] | ||
tagId, err := strconv.Atoi(d.Id()[lastSlashIndex+1:]) | ||
if err != nil { | ||
return err | ||
} | ||
log.Printf("[DEBUG] Path to immutable tag rules: %+v\n", projectImmutableTagRulePath) | ||
|
||
resp, _, err := apiClient.SendRequest("GET", projectImmutableTagRulePath, nil, 200) | ||
if err != nil { | ||
return fmt.Errorf("Resource not found %s", projectImmutableTagRulePath) | ||
} | ||
|
||
var immutableTagRuleModels []models.ImmutableTagRule | ||
err = json.Unmarshal([]byte(resp), &immutableTagRuleModels) | ||
if err != nil { | ||
return err | ||
} | ||
for _, rule := range immutableTagRuleModels { | ||
if rule.Id == tagId { | ||
log.Printf("[DEBUG] found tag id %d", tagId) | ||
d.Set("disabled", rule.Disabled) | ||
d.Set("project_id", strings.ReplaceAll(projectImmutableTagRulePath, models.PathImmutableTagRules, "")) | ||
|
||
switch rule.ImmutableTagRuleTagSelectors[0].Decoration { | ||
case "matches": | ||
d.Set("tag_matching", rule.ImmutableTagRuleTagSelectors[0].Pattern) | ||
case "excludes": | ||
d.Set("tag_excluding", rule.ImmutableTagRuleTagSelectors[0].Pattern) | ||
} | ||
|
||
switch rule.ScopeSelectors.Repository[0].Decoration { | ||
case "repoMatches": | ||
d.Set("repo_matching", rule.ScopeSelectors.Repository[0].Pattern) | ||
case "excludes": | ||
d.Set("repo_excluding", rule.ScopeSelectors.Repository[0].Pattern) | ||
} | ||
|
||
return nil | ||
} | ||
} | ||
|
||
return fmt.Errorf("Resource not found %s", d.Id()) | ||
} | ||
|
||
func resourceImmutableTagRuleUpdate(d *schema.ResourceData, m interface{}) error { | ||
apiClient := m.(*client.Client) | ||
body := client.GetImmutableTagRuleBody(d) | ||
id := d.Id() | ||
log.Printf("[DEBUG] Update Id: %+v\n", id) | ||
_, _, err := apiClient.SendRequest("PUT", id, body, 200) | ||
if err != nil { | ||
return err | ||
} | ||
|
||
return resourceImmutableTagRuleRead(d, m) | ||
} | ||
|
||
func resourceImmutableTagRuleDelete(d *schema.ResourceData, m interface{}) error { | ||
apiClient := m.(*client.Client) | ||
|
||
_, _, err := apiClient.SendRequest("DELETE", d.Id(), nil, 200) | ||
if err != nil { | ||
return err | ||
} | ||
return nil | ||
} |