Skip to content

Commit

Permalink
PLT-1440: Latest version will set for data source pack
Browse files Browse the repository at this point in the history
  • Loading branch information
SivaanandM committed Jan 15, 2025
1 parent 82e3056 commit ead670c
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 7 deletions.
2 changes: 1 addition & 1 deletion docs/data-sources/pack.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ data "spectrocloud_pack" "cni" {
- `name` (String) The name of the pack to search for.
- `registry_uid` (String) The unique identifier (UID) of the registry where the pack is located. Specify `registry_uid` to search within a specific registry.
- `type` (String) The type of pack to search for. Supported values are `helm`, `manifest`, `container`, `operator-instance`.
- `version` (String) The version of the pack to search for.
- `version` (String) Specifies the version of the pack to search for. If not set, the latest available version from the specified registry will be used.

### Read-Only

Expand Down
2 changes: 1 addition & 1 deletion go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ module github.com/spectrocloud/terraform-provider-spectrocloud
go 1.22.5

require (
github.com/Masterminds/semver/v3 v3.1.1
github.com/go-openapi/strfmt v0.23.0
github.com/google/go-cmp v0.6.0
github.com/gorilla/mux v1.8.0
Expand All @@ -23,7 +24,6 @@ require (

require (
github.com/Masterminds/goutils v1.1.1 // indirect
github.com/Masterminds/semver/v3 v3.1.1 // indirect
github.com/Masterminds/sprig/v3 v3.2.2 // indirect
github.com/ProtonMail/go-crypto v0.0.0-20230828082145-3c4c8a2d2371 // indirect
github.com/agext/levenshtein v1.2.2 // indirect
Expand Down
69 changes: 64 additions & 5 deletions spectrocloud/data_source_pack.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,11 @@ package spectrocloud
import (
"context"
"fmt"
"github.com/Masterminds/semver/v3"
"github.com/spectrocloud/gomi/pkg/ptr"
"github.com/spectrocloud/palette-sdk-go/api/models"
"github.com/spectrocloud/palette-sdk-go/client"
"sort"
"strings"

"github.com/hashicorp/terraform-plugin-sdk/v2/diag"
Expand Down Expand Up @@ -46,7 +51,7 @@ func dataSourcePack() *schema.Resource {
},
"version": {
Type: schema.TypeString,
Description: "The version of the pack to search for.",
Description: "Specifies the version of the pack to search for. If not set, the latest available version from the specified registry will be used.",
Computed: true,
Optional: true,
},
Expand All @@ -73,6 +78,7 @@ func dataSourcePack() *schema.Resource {

func dataSourcePackRead(_ context.Context, d *schema.ResourceData, m interface{}) diag.Diagnostics {
c := getV1ClientWithResourceContext(m, "")
var packName = ""

// Warning or errors can be collected in a slice type
var diags diag.Diagnostics
Expand Down Expand Up @@ -115,17 +121,24 @@ func dataSourcePackRead(_ context.Context, d *schema.ResourceData, m interface{}
and first part would be any random name to make overall pack name unique and 2nd part is actual pack name.
Thus, splitting pack name with '--' to get the correct pack name to find pack uuid
*/

if strings.Contains(v.(string), "--") {
v = strings.Split(v.(string), "--")[1]
}
packName = v.(string)
filters = append(filters, fmt.Sprintf("spec.name=%s", v.(string)))
}
if v, ok := d.GetOk("version"); ok {
filters = append(filters, fmt.Sprintf("spec.version=%s", v.(string)))
}
if v, ok := d.GetOk("registry_uid"); ok {
registryUID = v.(string)
}
if v, ok := d.GetOk("version"); ok {
filters = append(filters, fmt.Sprintf("spec.version=%s", v.(string)))
} else {
latestVersion := setLatestPackVersionToFilters(packName, registryUID, c)
if latestVersion != "" {
filters = append(filters, fmt.Sprintf("spec.version=%s", latestVersion))
}
}
if v, ok := d.GetOk("cloud"); ok {
clouds := expandStringList(v.(*schema.Set).List())
if !stringContains(clouds, "all") {
Expand All @@ -140,7 +153,7 @@ func dataSourcePackRead(_ context.Context, d *schema.ResourceData, m interface{}
return diag.FromErr(err)
}

packName := "unknown"
packName = "unknown"
if v, ok := d.GetOk("name"); ok {
packName = v.(string)
}
Expand Down Expand Up @@ -196,3 +209,49 @@ func dataSourcePackRead(_ context.Context, d *schema.ResourceData, m interface{}

return diags
}

func setLatestPackVersionToFilters(packName string, registryUID string, c *client.V1Client) string {
var packLayers = []models.V1PackLayer{"addon", "csi", "cni", "os", "kernel"}
var packTypes = []models.V1PackType{"spectro", "helm", "manifest", "oci"}
var packAddOnTypes = []string{"load balancer", "ingress", "logging", "monitoring", "security", "authentication",
"servicemesh", "system app", "app services", "registry", "csi", "cni", "integration", ""}

newFilter := &models.V1PackFilterSpec{
Name: &models.V1FilterString{
Eq: ptr.StringPtr(packName),
},
Type: packTypes,
Layer: packLayers,
Environment: []string{"all"},
AddOnType: packAddOnTypes,
}
if registryUID != "" {
newFilter.RegistryUID = []string{registryUID}
}
var newSort []*models.V1PackSortSpec
latestVersion := ""
packsResults, _ := c.SearchPacks(newFilter, newSort)
if len(packsResults) == 1 {
latestVersion, _ = getLatestVersion(packsResults[0].Spec.Registries)
return latestVersion
}
return ""
}

// getLatestVersion returns the latest version from a list of version strings.
func getLatestVersion(versions []*models.V1RegistryPackMetadata) (string, error) {
if len(versions) == 0 {
return "", fmt.Errorf("no versions provided")
}
semverVersions := make([]*semver.Version, len(versions))
for i, v := range versions {
ver, err := semver.NewVersion(v.LatestVersion)
if err != nil {
return "", fmt.Errorf("invalid version %q: %w", v, err)
}
semverVersions[i] = ver
}
sort.Sort(semver.Collection(semverVersions))

return semverVersions[len(semverVersions)-1].String(), nil
}
59 changes: 59 additions & 0 deletions spectrocloud/data_source_pack_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package spectrocloud
import (
"context"
"github.com/hashicorp/terraform-plugin-sdk/v2/helper/schema"
"github.com/spectrocloud/palette-sdk-go/api/models"
"github.com/stretchr/testify/assert"
"testing"
)
Expand Down Expand Up @@ -48,3 +49,61 @@ func TestDataSourcePacksReadHelmMultiPacks(t *testing.T) {
assertFirstDiagMessage(t, diags, "Multiple packs returned")

}

func TestGetLatestVersion(t *testing.T) {
t.Run("valid versions", func(t *testing.T) {
versions := []*models.V1RegistryPackMetadata{
{LatestVersion: "v1.0.0"},
{LatestVersion: "v1.2.0"},
{LatestVersion: "v1.1.0"},
}
latest, err := getLatestVersion(versions)

assert.NoError(t, err, "Expected no error")
assert.Equal(t, "1.2.0", latest, "The latest version should be returned")
})

t.Run("empty versions list", func(t *testing.T) {
versions := []*models.V1RegistryPackMetadata{}
latest, err := getLatestVersion(versions)

assert.Error(t, err, "Expected an error for empty versions list")
assert.Equal(t, "", latest, "No version should be returned")
assert.Equal(t, "no versions provided", err.Error(), "Expected specific error message")
})

t.Run("invalid version string", func(t *testing.T) {
versions := []*models.V1RegistryPackMetadata{
{LatestVersion: "1.0.0"},
{LatestVersion: "invalid-version"},
{LatestVersion: "1.1.0"},
}
latest, err := getLatestVersion(versions)

assert.Error(t, err, "Expected an error for invalid version string")
assert.Equal(t, "", latest, "No version should be returned for invalid input")
assert.Contains(t, err.Error(), "invalid version", "Error message should indicate invalid version")
})

t.Run("single version", func(t *testing.T) {
versions := []*models.V1RegistryPackMetadata{
{LatestVersion: "2.0.0"},
}
latest, err := getLatestVersion(versions)

assert.NoError(t, err, "Expected no error")
assert.Equal(t, "2.0.0", latest, "The single version should be returned")
})

t.Run("pre-release versions", func(t *testing.T) {
versions := []*models.V1RegistryPackMetadata{
{LatestVersion: "1.0.0-alpha"},
{LatestVersion: "1.0.0-beta"},
{LatestVersion: "1.0.0"},
}
latest, err := getLatestVersion(versions)

assert.NoError(t, err, "Expected no error")
assert.Equal(t, "1.0.0", latest, "The stable version should be returned as the latest")
})
}

0 comments on commit ead670c

Please sign in to comment.