Skip to content

Commit

Permalink
feat: artifactory generic feed
Browse files Browse the repository at this point in the history
  • Loading branch information
benPearce1 committed Nov 29, 2023
1 parent fd21a66 commit 7dacbf9
Show file tree
Hide file tree
Showing 10 changed files with 313 additions and 7 deletions.
4 changes: 3 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -54,4 +54,6 @@ terraform/**/terrform.tfstate
terraform/**/.terraform/*

# Ignore the test results file
results.xml
results.xml

.DS_Store
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ HOSTNAME=octopus.com
NAMESPACE=com
NAME=octopusdeploy
BINARY=terraform-provider-${NAME}
VERSION=0.7.82
VERSION=0.7.95

ifeq ($(OS), Windows_NT)
OS_ARCH?=windows_386
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
terraform import [options] octopusdeploy_artifactory_generic_feed.<name> <feed-id>
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
resource "octopusdeploy_artifactory_generic_feed" "example" {
feed_uri = "https://example.jfrog.io/"
password = "test-password"
name = "Test Artifactory Generic Feed (OK to Delete)"
username = "test-username"
repository = "repo"
layout_regex = "this is regex"
}
4 changes: 4 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@ module github.com/OctopusDeploy/terraform-provider-octopusdeploy

go 1.20

replace (
github.com/OctopusDeploy/go-octopusdeploy/v2 => ../go-octopusdeploy
)

require (
github.com/OctopusDeploy/go-octopusdeploy/v2 v2.33.3
github.com/OctopusSolutionsEngineering/OctopusTerraformTestFramework v0.0.0-20230705105638-f5ef7c07973b
Expand Down
1 change: 1 addition & 0 deletions octopusdeploy/provider.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ func Provider() *schema.Provider {
"octopusdeploy_listening_tentacle_deployment_target": resourceListeningTentacleDeploymentTarget(),
"octopusdeploy_machine_policy": resourceMachinePolicy(),
"octopusdeploy_maven_feed": resourceMavenFeed(),
"octopusdeploy_artifactory_generic_feed": resourceArtifactoryGenericFeed(),
"octopusdeploy_nuget_feed": resourceNuGetFeed(),
"octopusdeploy_offline_package_drop_deployment_target": resourceOfflinePackageDropDeploymentTarget(),
"octopusdeploy_polling_tentacle_deployment_target": resourcePollingTentacleDeploymentTarget(),
Expand Down
108 changes: 108 additions & 0 deletions octopusdeploy/resource_artifactory_generic_feed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
package octopusdeploy

import (
"context"
"fmt"

"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds"
"github.com/OctopusDeploy/terraform-provider-octopusdeploy/internal/errors"
"github.com/hashicorp/terraform-plugin-log/tflog"
"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
)

func resourceArtifactoryGenericFeed() *schema.Resource {
return &schema.Resource{
CreateContext: resourceArtifactoryGenericFeedCreate,
DeleteContext: resourceArtifactoryGenericFeedDelete,
Description: "This resource manages a Artifactory Generic feed in Octopus Deploy.",
Importer: getImporter(),
ReadContext: resourceArtifactoryGenericFeedRead,
Schema: getArtifactoryGenericFeedSchema(),
UpdateContext: resourceArtifactoryGenericFeedUpdate,
}
}

func resourceArtifactoryGenericFeedCreate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
artifactoryGenericFeed, err := expandArtifactoryGenericFeed(d)
if err != nil {
return diag.FromErr(err)
}

tflog.Info(ctx, fmt.Sprintf("creating Artifactory Generic feed: %s", artifactoryGenericFeed.GetName()))

client := m.(*client.Client)
createdFeed, err := feeds.Add(client, artifactoryGenericFeed)
if err != nil {
return diag.FromErr(err)
}

if err := setArtifactoryGenericFeed(ctx, d, createdFeed.(*feeds.ArtifactoryGenericFeed)); err != nil {
return diag.FromErr(err)
}

d.SetId(createdFeed.GetID())

tflog.Info(ctx, fmt.Sprintf("Artifactory Generic feed created (%s)", d.Id()))
return nil
}

func resourceArtifactoryGenericFeedDelete(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
tflog.Info(ctx, fmt.Sprintf("deleting Artifactory Generic feed (%s)", d.Id()))

client := m.(*client.Client)
err := feeds.DeleteByID(client, d.Get("space_id").(string), d.Id())
if err != nil {
return diag.FromErr(err)
}

d.SetId("")

tflog.Info(ctx, "Artifactory Generic feed deleted")
return nil
}

func resourceArtifactoryGenericFeedRead(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
tflog.Info(ctx, fmt.Sprintf("reading Artifactory Generic feed (%s)", d.Id()))

client := m.(*client.Client)
feed, err := feeds.GetByID(client, d.Get("space_id").(string), d.Id())

if err != nil {
return errors.ProcessApiError(ctx, d, err, "Artifactory Generic feed")
}

if err := setArtifactoryGenericFeed(ctx, d, feed.(*feeds.ArtifactoryGenericFeed)); err != nil {
return diag.FromErr(err)
}

tflog.Info(ctx, fmt.Sprintf("Artifactory Generic feed read (%s)", feed.GetID()))
return nil
}

func resourceArtifactoryGenericFeedUpdate(ctx context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
feed, err := expandArtifactoryGenericFeed(d)

tflog.Debug(ctx, fmt.Sprintf("layout_regex from schema: %s", d.Get("layout_regex").(string)))

tflog.Debug(ctx, fmt.Sprintf("layout regex from feed model: %s", feed.LayoutRegex))
if err != nil {
return diag.FromErr(err)
}

tflog.Info(ctx, fmt.Sprintf("updating Artifactory Generic feed (%s)", feed.GetID()))

client := m.(*client.Client)
updatedFeed, err := feeds.Update(client, feed)
if err != nil {
return diag.FromErr(err)
}

if err := setArtifactoryGenericFeed(ctx, d, updatedFeed.(*feeds.ArtifactoryGenericFeed)); err != nil {
return diag.FromErr(err)
}

tflog.Info(ctx, fmt.Sprintf("Artifactory Generic feed updated (%s)", d.Id()))
return nil
}
82 changes: 82 additions & 0 deletions octopusdeploy/resource_artifactory_generic_feed_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
package octopusdeploy

import (
"fmt"
"testing"

"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/client"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/acctest"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/resource"
"github.com/hashicorp/terraform-plugin-sdk/v2/terraform"
)

func TestAccOctopusDeployArtifactoryGenericFeed(t *testing.T) {
localName := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)
prefix := "octopusdeploy_artifactory_generic_feed." + localName

feedURI := "https://example.jfrog.io"
name := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)
password := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)
username := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)
repository := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)
layoutRegex := acctest.RandStringFromCharSet(20, acctest.CharSetAlpha)

resource.Test(t, resource.TestCase{
CheckDestroy: testArtifactoryGenericFeedCheckDestroy,
PreCheck: func() { testAccPreCheck(t) },
Providers: testAccProviders,
Steps: []resource.TestStep{
{
Check: resource.ComposeTestCheckFunc(
testArtifactoryGenericFeedExists(prefix),
resource.TestCheckResourceAttr(prefix, "feed_uri", feedURI),
resource.TestCheckResourceAttr(prefix, "name", name),
resource.TestCheckResourceAttr(prefix, "password", password),
resource.TestCheckResourceAttr(prefix, "username", username),
resource.TestCheckResourceAttr(prefix, "repository", repository),
resource.TestCheckResourceAttr(prefix, "layout_regex", layoutRegex),
),
Config: testArtifactoryGenericFeedBasic(localName, feedURI, name, username, password, repository, layoutRegex),
},
},
})
}

func testArtifactoryGenericFeedBasic(localName string, feedURI string, name string, username string, password string, repository string, layoutRegex string) string {
return fmt.Sprintf(`resource "octopusdeploy_artifactory_generic_feed" "%s" {
feed_uri = "%s"
name = "%s"
password = "%s"
username = "%s"
repository = "%s"
layout_regex = "%s"
}`, localName, feedURI, name, password, username, repository, layoutRegex)
}

func testArtifactoryGenericFeedExists(prefix string) resource.TestCheckFunc {
return func(s *terraform.State) error {
client := testAccProvider.Meta().(*client.Client)
feedID := s.RootModule().Resources[prefix].Primary.ID
if _, err := client.Feeds.GetByID(feedID); err != nil {
return err
}

return nil
}
}

func testArtifactoryGenericFeedCheckDestroy(s *terraform.State) error {
for _, rs := range s.RootModule().Resources {
if rs.Type != "octopusdeploy_artifactory_generic_feed" {
continue
}

client := testAccProvider.Meta().(*client.Client)
feed, err := client.Feeds.GetByID(rs.Primary.ID)
if err == nil && feed != nil {
return fmt.Errorf("Artifactory Generic feed (%s) still exists", rs.Primary.ID)
}
}

return nil
}
104 changes: 104 additions & 0 deletions octopusdeploy/schema_artifactory_generic_feed.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package octopusdeploy

import (
"context"
"fmt"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/core"
"github.com/OctopusDeploy/go-octopusdeploy/v2/pkg/feeds"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/validation"
)

func expandArtifactoryGenericFeed(d *schema.ResourceData) (*feeds.ArtifactoryGenericFeed, error) {
name := d.Get("name").(string)

feed, err := feeds.NewArtifactoryGenericFeed(name)
if err != nil {
return nil, err
}

feed.ID = d.Id()

if v, ok := d.GetOk("feed_uri"); ok {
feed.FeedURI = v.(string)
}

if v, ok := d.GetOk("package_acquisition_location_options"); ok {
feed.PackageAcquisitionLocationOptions = getSliceFromTerraformTypeList(v)
}

if v, ok := d.GetOk("password"); ok {
feed.Password = core.NewSensitiveValue(v.(string))
}

if v, ok := d.GetOk("space_id"); ok {
feed.SpaceID = v.(string)
}

if v, ok := d.GetOk("username"); ok {
feed.Username = v.(string)
}

if v, ok := d.GetOk("layout_regex"); ok {
feed.LayoutRegex = v.(string)
}

if v, ok := d.GetOk("repository"); ok {
feed.Repository = v.(string)
}

return feed, nil
}

func getArtifactoryGenericFeedSchema() map[string]*schema.Schema {
return map[string]*schema.Schema{
"feed_uri": {
Required: true,
Type: schema.TypeString,
},
"id": getIDSchema(),
"name": {
Description: "A short, memorable, unique name for this feed. Example: ACME Builds.",
Required: true,
Type: schema.TypeString,
ValidateDiagFunc: validation.ToDiagFunc(validation.StringIsNotEmpty),
},
"package_acquisition_location_options": {
Computed: true,
Elem: &schema.Schema{Type: schema.TypeString},
Optional: true,
Type: schema.TypeList,
},
"password": getPasswordSchema(false),
"space_id": getSpaceIDSchema(),
"username": getUsernameSchema(false),
"repository": {
Computed: false,
Required: true,
Type: schema.TypeString,
},
"layout_regex": {
Computed: false,
Required: false,
Optional: true,
Type: schema.TypeString,
},
}
}

func setArtifactoryGenericFeed(ctx context.Context, d *schema.ResourceData, feed *feeds.ArtifactoryGenericFeed) error {
d.Set("feed_uri", feed.FeedURI)
d.Set("name", feed.Name)
d.Set("space_id", feed.SpaceID)
d.Set("username", feed.Username)
d.Set("repository", feed.Repository)
d.Set("layout_regex", feed.LayoutRegex)

if err := d.Set("package_acquisition_location_options", feed.PackageAcquisitionLocationOptions); err != nil {
return fmt.Errorf("error setting package_acquisition_location_options: %s", err)
}

d.SetId(feed.GetID())

return nil
}
6 changes: 1 addition & 5 deletions octopusdeploy/schema_docker_container_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -44,10 +44,6 @@ func expandDockerContainerRegistry(d *schema.ResourceData) (*feeds.DockerContain
feed.Password = core.NewSensitiveValue(v.(string))
}

if v, ok := d.GetOk("space_id"); ok {
feed.SpaceID = v.(string)
}

if v, ok := d.GetOk("username"); ok {
feed.Username = v.(string)
}
Expand All @@ -62,7 +58,7 @@ func getDockerContainerRegistrySchema() map[string]*schema.Schema {
Type: schema.TypeString,
},
"feed_uri": {
Description: "The URL to a Maven repository. This URL is the same value defined in the `repositories`/`repository`/`url` element of a Maven `settings.xml` file.",
Description: "The URL to a Docker repository.",
Required: true,
Type: schema.TypeString,
ValidateDiagFunc: validation.ToDiagFunc(validation.IsURLWithHTTPorHTTPS),
Expand Down

0 comments on commit 7dacbf9

Please sign in to comment.