Skip to content

Commit

Permalink
feat(LH-71074): SDC Onboarding Resource (#69)
Browse files Browse the repository at this point in the history
  • Loading branch information
weilueluo authored Oct 2, 2023
1 parent 951f38e commit 24ea16e
Show file tree
Hide file tree
Showing 14 changed files with 513 additions and 3 deletions.
17 changes: 17 additions & 0 deletions client/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ package client

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector/connectoronboarding"
"net/http"

"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector"
Expand Down Expand Up @@ -202,3 +203,19 @@ func (c *Client) ReadCloudFmcDevice(ctx context.Context) (*device.ReadOutput, er
func (c *Client) ReadCloudFmcSpecificDevice(ctx context.Context, inp cloudfmc.ReadSpecificInput) (*cloudfmc.ReadSpecificOutput, error) {
return cloudfmc.ReadSpecific(ctx, c.client, inp)
}

func (c *Client) CreateConnectorOnboarding(ctx context.Context, inp connectoronboarding.CreateInput) (*connectoronboarding.CreateOutput, error) {
return connectoronboarding.Create(ctx, c.client, inp)
}

func (c *Client) UpdateConnectorOnboarding(ctx context.Context, inp connectoronboarding.UpdateInput) (*connectoronboarding.UpdateOutput, error) {
return connectoronboarding.Update(ctx, c.client, inp)
}

func (c *Client) ReadConnectorOnboarding(ctx context.Context, inp connectoronboarding.ReadInput) (*connectoronboarding.ReadOutput, error) {
return connectoronboarding.Read(ctx, c.client, inp)
}

func (c *Client) DeleteConnectorOnboarding(ctx context.Context, inp connectoronboarding.DeleteInput) (*connectoronboarding.DeleteOutput, error) {
return connectoronboarding.Delete(ctx, c.client, inp)
}
43 changes: 43 additions & 0 deletions client/connector/connectoronboarding/create.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
package connectoronboarding

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/retry"
"time"
)

type CreateInput struct {
Name string
}

func NewCreateInput(name string) CreateInput {
return CreateInput{
Name: name,
}
}

type CreateOutput = connector.ReadOutput

func Create(ctx context.Context, client http.Client, createInp CreateInput) (*CreateOutput, error) {

// wait for connector status to be "Active"
var readOutp connector.ReadOutput
err := retry.Do(
UntilConnectorStatusIsActive(ctx, client, *connector.NewReadByNameInput(createInp.Name), &readOutp),
retry.NewOptionsBuilder().
Timeout(15*time.Minute). // usually takes ~3 minutes
Retries(-1).
Delay(2*time.Second).
Logger(client.Logger).
EarlyExitOnError(false).
Build(),
)

if err != nil {
return nil, err
} else {
return &readOutp, nil
}
}
104 changes: 104 additions & 0 deletions client/connector/connectoronboarding/create_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
package connectoronboarding_test

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector/connectoronboarding"
internalHttp "github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/url"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/device/status"
"github.com/jarcoal/httpmock"
"github.com/stretchr/testify/assert"
"net/http"
"testing"
"time"
)

func TestCreate(t *testing.T) {
httpmock.Activate()
defer httpmock.DeactivateAndReset()

activeConnector := connector.ReadOutput{
Uid: "",
Name: "test-sdc",
DefaultConnector: false,
Cdg: false,
TenantUid: "",
PublicKey: model.PublicKey{},
ConnectorStatus: status.Active,
}

onboardingConnector := connector.ReadOutput{
Uid: "",
Name: "test-sdc",
DefaultConnector: false,
Cdg: false,
TenantUid: "",
PublicKey: model.PublicKey{},
ConnectorStatus: status.Onboarding,
}

baseUrl := "https://unittest.cdo.cisco.com"

testCases := []struct {
testName string
input connectoronboarding.CreateInput
setupFunc func()
assertFunc func(output *connectoronboarding.CreateOutput, err error, t *testing.T)
}{
{
testName: "should finish on connector Active status",
input: connectoronboarding.NewCreateInput(activeConnector.Name),
setupFunc: func() {
httpmock.RegisterResponder(
http.MethodGet,
url.ReadConnectorByName(baseUrl),
httpmock.NewJsonResponderOrPanic(http.StatusOK, []connector.ReadOutput{activeConnector}),
)
},
assertFunc: func(output *connectoronboarding.CreateOutput, err error, t *testing.T) {
assert.NotNil(t, output)
assert.Nil(t, err)
assert.Equal(t, *output, activeConnector)
},
},
{
testName: "should retry until SDC activation status is ACTIVE",
input: connectoronboarding.NewCreateInput(activeConnector.Name),
setupFunc: func() {
httpmock.RegisterResponder(
http.MethodGet,
url.ReadConnectorByName(baseUrl),
httpmock.NewJsonResponderOrPanic(http.StatusOK, []connector.ReadOutput{onboardingConnector}),
)
httpmock.RegisterResponder(
http.MethodGet,
url.ReadConnectorByName(baseUrl),
httpmock.NewJsonResponderOrPanic(http.StatusOK, []connector.ReadOutput{activeConnector}),
)
},
assertFunc: func(output *connectoronboarding.CreateOutput, err error, t *testing.T) {
assert.NotNil(t, output)
assert.Nil(t, err)
assert.Equal(t, *output, activeConnector)
},
},
}

for _, testCase := range testCases {
t.Run(testCase.testName, func(t *testing.T) {
httpmock.Reset()

testCase.setupFunc()

output, err := connectoronboarding.Create(
context.Background(),
*internalHttp.MustNewWithConfig(baseUrl, "a_valid_token", 0, 0, time.Minute),
testCase.input,
)

testCase.assertFunc(output, err, t)
})
}
}
23 changes: 23 additions & 0 deletions client/connector/connectoronboarding/delete.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package connectoronboarding

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
)

type DeleteInput struct {
}

func NewDeleteInput() DeleteInput {
return DeleteInput{}
}

type DeleteOutput struct {
}

func Delete(ctx context.Context, client http.Client, deleteInp DeleteInput) (*DeleteOutput, error) {

// empty

return nil, nil
}
23 changes: 23 additions & 0 deletions client/connector/connectoronboarding/read.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package connectoronboarding

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
)

type ReadInput struct {
}

func NewReadInput() ReadInput {
return ReadInput{}
}

type ReadOutput struct {
}

func Read(ctx context.Context, client http.Client, readInp ReadInput) (*ReadOutput, error) {

// empty

return nil, nil
}
24 changes: 24 additions & 0 deletions client/connector/connectoronboarding/retry.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package connectoronboarding

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/retry"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/device/status"
)

func UntilConnectorStatusIsActive(ctx context.Context, client http.Client, readInp connector.ReadByNameInput, readOutp *connector.ReadOutput) retry.Func {
return func() (bool, error) {
readRes, err := connector.ReadByName(ctx, client, readInp)
*readOutp = *readRes
if err != nil {
return false, err
}
client.Logger.Printf("connector status: %v\n", readRes.ConnectorStatus)
if readRes.ConnectorStatus == status.Active {
return true, nil
}
return false, nil
}
}
23 changes: 23 additions & 0 deletions client/connector/connectoronboarding/update.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package connectoronboarding

import (
"context"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
)

type UpdateInput struct {
}

func NewUpdateInput() UpdateInput {
return UpdateInput{}
}

type UpdateOutput struct {
}

func Update(ctx context.Context, client http.Client, updateInp UpdateInput) (*UpdateOutput, error) {

// empty

return nil, nil
}
5 changes: 4 additions & 1 deletion client/connector/read.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
"context"
"fmt"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/device/status"

"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/url"
Expand All @@ -24,6 +25,7 @@ type ReadOutput struct {
Cdg bool `json:"cdg"`
TenantUid string `json:"tenantUid"`
PublicKey model.PublicKey `json:"larPublicKey"`
ConnectorStatus status.Type `json:"larStatus"`
}

func NewReadByUidInput(connectorUid string) *ReadByUidInput {
Expand All @@ -49,9 +51,10 @@ func newReadByUidRequest(ctx context.Context, client http.Client, readInp ReadBy

func newReadByNameRequest(ctx context.Context, client http.Client, readInp ReadByNameInput) *http.Request {

url := url.ReadConnectorByName(client.BaseUrl(), readInp.ConnectorName)
url := url.ReadConnectorByName(client.BaseUrl())

req := client.NewGet(ctx, url)
req.QueryParams.Add("q", fmt.Sprintf("name:%s", readInp.ConnectorName))

return req
}
Expand Down
4 changes: 2 additions & 2 deletions client/internal/url/url.go
Original file line number Diff line number Diff line change
Expand Up @@ -50,8 +50,8 @@ func ReadConnectorByUid(baseUrl string, connectorUid string) string {
return fmt.Sprintf("%s/aegis/rest/v1/services/targets/proxies/%s", baseUrl, connectorUid)
}

func ReadConnectorByName(baseUrl string, connectorName string) string {
return fmt.Sprintf("%s/aegis/rest/v1/services/targets/proxies?q=name:%s", baseUrl, connectorName)
func ReadConnectorByName(baseUrl string) string {
return fmt.Sprintf("%s/aegis/rest/v1/services/targets/proxies", baseUrl)
}

func CreateConnector(baseUrl string) string {
Expand Down
14 changes: 14 additions & 0 deletions client/model/device/status/status.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package status

type Type string

// see also: https://github.com/cisco-lockhart/lh-plugin-core/blob/master/lh-target/src/main/java/com/cisco/lockhart/target/data/ServiceActivationState.java
const (
New Type = "NEW"
ReOnboard Type = "REONBOARD"
YoReOnboard Type = "YO_REONBOARD"
Onboarding Type = "ONBOARDING"
Active Type = "ACTIVE"
Inactive Type = "INACTIVE"
Disabled Type = "DISABLE"
)
24 changes: 24 additions & 0 deletions docs/resources/sdc_onboarding.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
---
# generated by https://github.com/hashicorp/terraform-plugin-docs
page_title: "cdo_sdc_onboarding Resource - cdo"
subcategory: ""
description: |-
Use this resource to wait for an SDC to finish onboarding. When an SDC is onboarded, either manually or using the CDO Terraform Modules for AWS https://github.com/CiscoDevNet/terraform-aws-cdo-sdc and vSphere https://github.com/CiscoDevNet/terraform-vsphere-cdo-sdc, it can take a few minutes before the SDC is active and capable of proxying communications between CDO and the device. This resource allows you to wait until this is done.
---

# cdo_sdc_onboarding (Resource)

Use this resource to wait for an SDC to finish onboarding. When an SDC is onboarded, either manually or using the CDO Terraform Modules for [AWS](https://github.com/CiscoDevNet/terraform-aws-cdo-sdc) and [vSphere](https://github.com/CiscoDevNet/terraform-vsphere-cdo-sdc), it can take a few minutes before the SDC is active and capable of proxying communications between CDO and the device. This resource allows you to wait until this is done.



<!-- schema generated by tfplugindocs -->
## Schema

### Required

- `name` (String) Specify the name of the SDC.

### Read-Only

- `id` (String) The unique identifier of this SDC onboarding resource.
Loading

0 comments on commit 24ea16e

Please sign in to comment.