Skip to content

Commit

Permalink
Add acceptance tests for SSO domain resource (#497)
Browse files Browse the repository at this point in the history
* Add acceptance tests for SSO domain resource

* Fix failing test

* Fix failing test
  • Loading branch information
bobbyiliev authored Mar 14, 2024
1 parent b91246c commit 8e17ed2
Show file tree
Hide file tree
Showing 5 changed files with 373 additions and 144 deletions.
8 changes: 0 additions & 8 deletions pkg/frontegg/sso_config.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,6 @@ type SSOConfig struct {
Domains []Domain
}

// Domain represents the structure for SSO domain.
type Domain struct {
ID string `json:"id"`
Domain string `json:"domain"`
Validated bool `json:"validated"`
SsoConfigId string `json:"ssoConfigId"`
}

type SSOConfigurationsResponse []SSOConfig

// Helper function to flatten the SSO configurations data
Expand Down
133 changes: 133 additions & 0 deletions pkg/frontegg/sso_domain.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,133 @@
package frontegg

import (
"bytes"
"context"
"encoding/json"
"fmt"
"io"
"net/http"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/clients"
)

const (
SSODomainsApiPathV1 = "/frontegg/team/resources/sso/v1/configurations"
)

// Domain represents the structure for SSO domain.
type Domain struct {
ID string `json:"id"`
Domain string `json:"domain"`
Validated bool `json:"validated"`
SsoConfigId string `json:"ssoConfigId"`
}

// FetchSSODomain fetches a specific SSO domain.
func FetchSSODomain(ctx context.Context, client *clients.FronteggClient, configID, domainName string) (*Domain, error) {
endpoint := fmt.Sprintf("%s%s", client.Endpoint, SSODomainsApiPathV1)
req, err := http.NewRequestWithContext(ctx, "GET", endpoint, nil)
if err != nil {
return nil, err
}

req.Header.Add("Authorization", "Bearer "+client.Token)

resp, err := client.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
responseData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("error reading SSO configurations: status %d, response: %s", resp.StatusCode, string(responseData))
}

var configs []SSOConfig
if err := json.NewDecoder(resp.Body).Decode(&configs); err != nil {
return nil, err
}

for _, config := range configs {
if config.Id == configID {
for _, domain := range config.Domains {
if domain.Domain == domainName {
return &domain, nil
}
}
}
}

return nil, fmt.Errorf("domain not found")
}

// CreateDomain creates a new SSO domain.
func CreateSSODomain(ctx context.Context, client *clients.FronteggClient, configID, domainName string) (*Domain, error) {
endpoint := fmt.Sprintf("%s%s/%s/domains", client.Endpoint, SSODomainsApiPathV1, configID)
payload := map[string]string{"domain": domainName}
requestBody, err := json.Marshal(payload)
if err != nil {
return nil, err
}

req, err := http.NewRequestWithContext(ctx, "POST", endpoint, bytes.NewBuffer(requestBody))
if err != nil {
return nil, err
}

req.Header.Add("Authorization", "Bearer "+client.Token)
req.Header.Add("Content-Type", "application/json")

resp, err := client.HTTPClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusCreated {
responseData, err := io.ReadAll(resp.Body)
if err != nil {
return nil, err
}
return nil, fmt.Errorf("error creating SSO domain: status %d, response: %s", resp.StatusCode, string(responseData))
}

var result Domain
if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
return nil, err
}

return &result, nil
}

// DeleteSSODomain deletes a specific SSO domain.
func DeleteSSODomain(ctx context.Context, client *clients.FronteggClient, configID, domainID string) error {
endpoint := fmt.Sprintf("%s%s/%s/domains/%s", client.Endpoint, SSODomainsApiPathV1, configID, domainID)

req, err := http.NewRequestWithContext(ctx, "DELETE", endpoint, nil)
if err != nil {
return err
}

req.Header.Add("Authorization", "Bearer "+client.Token)

resp, err := client.HTTPClient.Do(req)
if err != nil {
return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
responseData, err := io.ReadAll(resp.Body)
if err != nil {
return err
}
return fmt.Errorf("error deleting SSO domain: status %d, response: %s", resp.StatusCode, string(responseData))
}

return nil
}
81 changes: 81 additions & 0 deletions pkg/frontegg/sso_domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
package frontegg

import (
"context"
"net/http"
"net/http/httptest"
"testing"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/clients"
"github.com/stretchr/testify/assert"
)

func TestFetchSSODomainSuccess(t *testing.T) {
assert := assert.New(t)

mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
// Mimic the actual structure with configurations containing domains
w.Write([]byte(`[
{
"id": "config-id",
"domains": [
{"id": "domain-id", "domain": "example.com", "validated": true}
]
}
]`))
}))
defer mockServer.Close()

client := &clients.FronteggClient{
Endpoint: mockServer.URL,
HTTPClient: mockServer.Client(),
}

domain, err := FetchSSODomain(context.Background(), client, "config-id", "example.com")
assert.NoError(err)
assert.NotNil(domain)
assert.Equal("domain-id", domain.ID)
assert.Equal("example.com", domain.Domain)
assert.True(domain.Validated)
}

func TestCreateSSODomainSuccess(t *testing.T) {
assert := assert.New(t)

mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusCreated)
w.Write([]byte(`{"id":"new-domain-id","domain":"new-example.com","validated":false,"ssoConfigId":"config-id"}`))
}))
defer mockServer.Close()

client := &clients.FronteggClient{
Endpoint: mockServer.URL,
HTTPClient: mockServer.Client(),
}

domain, err := CreateSSODomain(context.Background(), client, "config-id", "new-example.com")
assert.NoError(err)
assert.NotNil(domain)
assert.Equal("new-domain-id", domain.ID)
assert.Equal("new-example.com", domain.Domain)
assert.False(domain.Validated)
assert.Equal("config-id", domain.SsoConfigId)
}

func TestDeleteSSODomainSuccess(t *testing.T) {
assert := assert.New(t)

mockServer := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusOK)
}))
defer mockServer.Close()

client := &clients.FronteggClient{
Endpoint: mockServer.URL,
HTTPClient: mockServer.Client(),
}

err := DeleteSSODomain(context.Background(), client, "config-id", "domain-id")
assert.NoError(err)
}
145 changes: 145 additions & 0 deletions pkg/provider/acceptance_sso_domain_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
package provider

import (
"context"
"fmt"
"testing"

"github.com/MaterializeInc/terraform-provider-materialize/pkg/frontegg"
"github.com/MaterializeInc/terraform-provider-materialize/pkg/utils"
"github.com/hashicorp/terraform-plugin-testing/helper/resource"
"github.com/hashicorp/terraform-plugin-testing/terraform"
)

func TestAccSSODomain_basic(t *testing.T) {
resourceName := "materialize_sso_domain.example"
resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSSODomainConfig("example.com"),
Check: resource.ComposeTestCheckFunc(
testAccCheckSSODomainExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "domain", "example.com"),
resource.TestCheckResourceAttr(resourceName, "validated", "false"),
resource.TestCheckResourceAttrSet(resourceName, "id"),
),
},
},
})
}

func TestAccSSODomain_update(t *testing.T) {
resourceName := "materialize_sso_domain.example"
initialDomain := "example.com"
updatedDomain := "updated-example.com"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSSODomainConfig(initialDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckSSODomainExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "domain", initialDomain),
resource.TestCheckResourceAttr(resourceName, "validated", "false"),
),
},
{
Config: testAccSSODomainConfig(updatedDomain),
Check: resource.ComposeTestCheckFunc(
testAccCheckSSODomainExists(resourceName),
resource.TestCheckResourceAttr(resourceName, "domain", updatedDomain),
resource.TestCheckResourceAttr(resourceName, "validated", "false"),
),
},
},
})
}

func TestAccSSODomain_disappears(t *testing.T) {
resourceName := "materialize_sso_domain.example"

resource.Test(t, resource.TestCase{
PreCheck: func() { testAccPreCheck(t) },
ProviderFactories: testAccProviderFactories,
Steps: []resource.TestStep{
{
Config: testAccSSODomainConfig("example.com"),
Check: resource.ComposeTestCheckFunc(
testAccCheckSSODomainExists(resourceName),
testAccCheckSSODomainDisappears(resourceName),
),
PlanOnly: true,
ExpectNonEmptyPlan: true,
},
},
})
}

func testAccSSODomainConfig(domain string) string {
return fmt.Sprintf(`
resource "materialize_sso_config" "example" {
enabled = false
sign_request = false
sso_endpoint = "https://example.com/sso"
public_certificate = "test-certificate"
type = "saml"
}
resource "materialize_sso_domain" "example" {
sso_config_id = materialize_sso_config.example.id
domain = "%s"
depends_on = [materialize_sso_config.example]
}
`, domain)
}

func testAccCheckSSODomainExists(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}

if rs.Primary.ID == "" {
return fmt.Errorf("No SSO Domain ID is set")
}

meta := testAccProvider.Meta()
providerMeta, _ := utils.GetProviderMeta(meta)
client := providerMeta.Frontegg

domain, err := frontegg.FetchSSODomain(context.Background(), client, rs.Primary.Attributes["sso_config_id"], rs.Primary.Attributes["domain"])
if err != nil {
return err
}

if domain == nil || domain.ID != rs.Primary.ID {
return fmt.Errorf("SSO Domain not found")
}

return nil
}
}

func testAccCheckSSODomainDisappears(resourceName string) resource.TestCheckFunc {
return func(s *terraform.State) error {
rs, ok := s.RootModule().Resources[resourceName]
if !ok {
return fmt.Errorf("Not found: %s", resourceName)
}

meta := testAccProvider.Meta()
providerMeta, _ := utils.GetProviderMeta(meta)
client := providerMeta.Frontegg

err := frontegg.DeleteSSODomain(context.Background(), client, rs.Primary.Attributes["sso_config_id"], rs.Primary.ID)
if err != nil {
return fmt.Errorf("Error deleting SSO domain: %s", err)
}

return nil
}
}
Loading

0 comments on commit 8e17ed2

Please sign in to comment.