Skip to content

Commit 201fbec

Browse files
feat(lh-89397): add optional software_version and asdm_version params to cdo_asa_device (#154)
* feat(lh-89397): add optional software_version and asdm_version params to cdo_asa_device * fix(lh-89397): fail with sensible error if the software version or ASDM version is updated Support will be added to update software version and ASDM version as part of https://jira-eng-rtp3.cisco.com/jira/browse/LH-89398 * docs(lh-89397): fix docs * test(lh-89397): revert this: make sure everything is fine by running acceptance tests against branch * fix(lh-89937): fix broken acceptance test * ci(lh-89397): fix IP address * fix(lh-89397): fix again * ci(lh-89397): do not run acceptance tests on branch
1 parent 4364675 commit 201fbec

File tree

12 files changed

+192
-49
lines changed

12 files changed

+192
-49
lines changed

client/client.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (c *Client) ReadDeviceByName(ctx context.Context, inp device.ReadByNameAndT
7373
return device.ReadByNameAndType(ctx, c.client, inp)
7474
}
7575

76-
func (c *Client) CreateAsa(ctx context.Context, inp asa.CreateInput) (*asa.CreateOutput, *asa.CreateError) {
76+
func (c *Client) CreateAsa(ctx context.Context, inp asa.CreateInput) (*asa.ReadOutput, *asa.ReadSpecificOutput, *asa.CreateError) {
7777
return asa.Create(ctx, c.client, inp)
7878
}
7979

client/device/asa/asafixture_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ func configureDeviceReadToRespondWithError(deviceUid string) {
129129
)
130130
}
131131

132-
func configureDeviceReadSpecificToRespondSuccessfully(deviceUid string, readOutput device.ReadSpecificOutput) {
132+
func configureDeviceReadSpecificToRespondSuccessfully(deviceUid string, readOutput asa.ReadSpecificOutput) {
133133
httpmock.RegisterResponder(
134134
http.MethodGet,
135135
buildDeviceReadSpecificPath(deviceUid),

client/device/asa/create.go

Lines changed: 52 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@ package asa
22

33
import (
44
"context"
5+
"errors"
6+
"fmt"
7+
"strings"
58

69
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/connector"
710
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
@@ -21,10 +24,10 @@ type CreateInput struct {
2124
Password string
2225

2326
IgnoreCertificate bool
27+
SoftwareVersion string
28+
AsdmVersion string
2429
}
2530

26-
type CreateOutput = ReadOutput
27-
2831
type Metadata struct {
2932
IsNewPolicyObjectModel string `json:"isNewPolicyObjectModel"` // yes it is a string, but it should be either "true" or "false" :/
3033
}
@@ -49,7 +52,7 @@ func (r *CreateError) Error() string {
4952
return r.Err.Error()
5053
}
5154

52-
func NewCreateRequestInput(name, connectorUid, connectorType, socketAddress, username, password string, ignoreCertificate bool, labels publicapilabels.Type) *CreateInput {
55+
func NewCreateRequestInput(name, connectorUid, connectorType, socketAddress, username, password string, ignoreCertificate bool, labels publicapilabels.Type, softwareVersion string, asdmVersion string) *CreateInput {
5356
return &CreateInput{
5457
Name: name,
5558
ConnectorUid: connectorUid,
@@ -59,20 +62,22 @@ func NewCreateRequestInput(name, connectorUid, connectorType, socketAddress, use
5962
Password: password,
6063
IgnoreCertificate: ignoreCertificate,
6164
Labels: labels,
65+
SoftwareVersion: softwareVersion,
66+
AsdmVersion: asdmVersion,
6267
}
6368
}
6469

65-
func Create(ctx context.Context, client http.Client, createInp CreateInput) (*CreateOutput, *CreateError) {
70+
func Create(ctx context.Context, client http.Client, createInp CreateInput) (*ReadOutput, *ReadSpecificOutput, *CreateError) {
6671

67-
client.Logger.Println("creating asa")
72+
client.Logger.Println("creating asa device")
6873

6974
createUrl := url.CreateAsa(client.BaseUrl())
7075

7176
var connectorName string
7277
if createInp.ConnectorType == "SDC" {
7378
conn, err := connector.ReadByUid(ctx, client, connector.ReadByUidInput{ConnectorUid: createInp.ConnectorUid})
7479
if err != nil {
75-
return nil, &CreateError{
80+
return nil, nil, &CreateError{
7681
Err: err,
7782
CreatedResourceId: nil,
7883
}
@@ -96,7 +101,7 @@ func Create(ctx context.Context, client http.Client, createInp CreateInput) (*Cr
96101
},
97102
)
98103
if err != nil {
99-
return nil, &CreateError{
104+
return nil, nil, &CreateError{
100105
Err: err,
101106
CreatedResourceId: &transaction.EntityUid,
102107
}
@@ -108,19 +113,53 @@ func Create(ctx context.Context, client http.Client, createInp CreateInput) (*Cr
108113
"Waiting for Asa to onboard...",
109114
)
110115
if err != nil {
111-
return nil, &CreateError{
116+
return nil, nil, &CreateError{
112117
Err: err,
113118
CreatedResourceId: &transaction.EntityUid,
114119
}
115120
}
116121

117122
readOut, err := Read(ctx, client, ReadInput{Uid: transaction.EntityUid})
118123
if err == nil {
119-
return readOut, nil
120-
} else {
121-
return readOut, &CreateError{
122-
Err: err,
123-
CreatedResourceId: &transaction.EntityUid,
124+
if err = validateSoftwareVersion(readOut, createInp.SoftwareVersion); err != nil {
125+
client.Logger.Println("Version validation failed...")
126+
return nil, nil, &CreateError{
127+
Err: err,
128+
CreatedResourceId: &transaction.EntityUid,
129+
}
124130
}
131+
132+
readSpecificOut, err := ReadSpecific(ctx, client, ReadSpecificInput{Uid: transaction.EntityUid})
133+
if err == nil {
134+
if err = validateAsdmVersion(readSpecificOut, createInp.AsdmVersion); err != nil {
135+
client.Logger.Println("ASDM version validation failed...")
136+
return nil, nil, &CreateError{
137+
Err: err,
138+
CreatedResourceId: &transaction.EntityUid,
139+
}
140+
}
141+
return readOut, readSpecificOut, nil
142+
}
143+
}
144+
145+
return nil, nil, &CreateError{
146+
Err: err,
147+
CreatedResourceId: &transaction.EntityUid,
125148
}
126149
}
150+
151+
func validateSoftwareVersion(readOut *ReadOutput, softwareVersion string) error {
152+
if strings.TrimSpace(softwareVersion) != "" && readOut.SoftwareVersion != softwareVersion {
153+
return errors.New(fmt.Sprintf("ASA Software version mismatch. Specified software version %s does not match actual software version %s on ASA device", softwareVersion, readOut.SoftwareVersion))
154+
}
155+
156+
return nil
157+
}
158+
159+
func validateAsdmVersion(readOut *ReadSpecificOutput, asdmVersion string) error {
160+
if strings.TrimSpace(asdmVersion) != "" && readOut.Metadata.AsdmVersion != asdmVersion {
161+
return errors.New(fmt.Sprintf("ASDM version mismatch. Specified ASDM version %s does not match actual ASDM version %s on ASA device", asdmVersion, readOut.Metadata.AsdmVersion))
162+
}
163+
164+
return nil
165+
}

client/device/asa/create_test.go

Lines changed: 49 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -24,14 +24,19 @@ func TestAsaCreate(t *testing.T) {
2424
cdgReadOutput := testModel.CdgReadOutput()
2525
createInput := testModel.AsaCreateInput()
2626
readOutput := testModel.AsaReadOutput()
27+
readSpecificOutput := testModel.AsaReadSpecificDeviceOutput()
28+
createInputWithIncorrectSoftwareVersion := createInput
29+
createInputWithIncorrectSoftwareVersion.SoftwareVersion = readOutput.SoftwareVersion + "_different"
30+
createInputWithIncorrectAsdmVersion := createInput
31+
createInputWithIncorrectAsdmVersion.AsdmVersion = readOutput.AsdmVersion + "_different"
2732
doneTransaction := testModel.CreateDoneTransaction(readOutput.Uid, transactiontype.ONBOARD_ASA)
2833
errorTransaction := testModel.CreateErrorTransaction(readOutput.Uid, transactiontype.ONBOARD_ASA)
2934

3035
testCases := []struct {
3136
testName string
3237
input asa.CreateInput
3338
setupFunc func(input asa.CreateInput)
34-
assertFunc func(output *asa.CreateOutput, err *asa.CreateError, t *testing.T)
39+
assertFunc func(output *asa.ReadOutput, specificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T)
3540
}{
3641
{
3742
testName: "successfully onboards ASA",
@@ -41,16 +46,50 @@ func TestAsaCreate(t *testing.T) {
4146
internalTesting.MockGetOk(url.ReadConnectorByUid(testModel.BaseUrl, cdgReadOutput.Uid), cdgReadOutput)
4247
internalTesting.MockPostAccepted(url.CreateAsa(testModel.BaseUrl), doneTransaction)
4348
internalTesting.MockGetOk(url.ReadDevice(testModel.BaseUrl, readOutput.Uid), readOutput)
49+
internalTesting.MockGetOk(url.ReadSpecificDevice(testModel.BaseUrl, readOutput.Uid), readSpecificOutput)
4450
},
4551

46-
assertFunc: func(actualOutput *asa.CreateOutput, err *asa.CreateError, t *testing.T) {
52+
assertFunc: func(actualOutput *asa.ReadOutput, actualSpecificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T) {
4753
assert.Nil(t, err)
4854
assert.NotNil(t, actualOutput)
55+
assert.NotNil(t, actualSpecificDeviceOutput)
4956
assert.Equal(t, readOutput, *actualOutput)
5057
},
5158
},
5259
{
53-
testName: "fails onboards Duo Admin Panel if transaction fails",
60+
testName: "fails to onboard ASA due to specified software version mismatch",
61+
input: createInputWithIncorrectSoftwareVersion,
62+
setupFunc: func(input asa.CreateInput) {
63+
internalTesting.MockGetOk(url.ReadConnectorByUid(testModel.BaseUrl, cdgReadOutput.Uid), cdgReadOutput)
64+
internalTesting.MockPostAccepted(url.CreateAsa(testModel.BaseUrl), doneTransaction)
65+
internalTesting.MockGetOk(url.ReadDevice(testModel.BaseUrl, readOutput.Uid), readOutput)
66+
internalTesting.MockGetOk(url.ReadSpecificDevice(testModel.BaseUrl, readOutput.Uid), readSpecificOutput)
67+
},
68+
assertFunc: func(actualOutput *asa.ReadOutput, actualSpecificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T) {
69+
assert.Nil(t, actualOutput)
70+
assert.Nil(t, actualSpecificDeviceOutput)
71+
assert.NotNil(t, err)
72+
assert.ErrorContains(t, err, "ASA Software version mismatch.")
73+
},
74+
},
75+
{
76+
testName: "fails to onboard ASA due to specified ASDM version mismatch",
77+
input: createInputWithIncorrectAsdmVersion,
78+
setupFunc: func(input asa.CreateInput) {
79+
internalTesting.MockGetOk(url.ReadConnectorByUid(testModel.BaseUrl, cdgReadOutput.Uid), cdgReadOutput)
80+
internalTesting.MockPostAccepted(url.CreateAsa(testModel.BaseUrl), doneTransaction)
81+
internalTesting.MockGetOk(url.ReadDevice(testModel.BaseUrl, readOutput.Uid), readOutput)
82+
internalTesting.MockGetOk(url.ReadSpecificDevice(testModel.BaseUrl, readOutput.Uid), readSpecificOutput)
83+
},
84+
assertFunc: func(actualOutput *asa.ReadOutput, actualSpecificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T) {
85+
assert.Nil(t, actualOutput)
86+
assert.Nil(t, actualSpecificDeviceOutput)
87+
assert.NotNil(t, err)
88+
assert.ErrorContains(t, err, "ASDM version mismatch.")
89+
},
90+
},
91+
{
92+
testName: "fails onboards ASA if transaction fails",
5493
input: createInput,
5594

5695
setupFunc: func(input asa.CreateInput) {
@@ -59,23 +98,25 @@ func TestAsaCreate(t *testing.T) {
5998
internalTesting.MockGetOk(url.ReadDevice(testModel.BaseUrl, readOutput.Uid), readOutput)
6099
},
61100

62-
assertFunc: func(actualOutput *asa.CreateOutput, err *asa.CreateError, t *testing.T) {
101+
assertFunc: func(actualOutput *asa.ReadOutput, actualSpecificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T) {
63102
assert.Nil(t, actualOutput)
103+
assert.Nil(t, actualSpecificDeviceOutput)
64104
assert.NotNil(t, err)
65105
assert.ErrorContains(t, err, errorTransaction.ErrorMessage)
66106
},
67107
},
68108
{
69-
testName: "fails onboards Duo Admin Panel if trigger transaction fails",
109+
testName: "fails onboards ASA if trigger transaction fails",
70110
input: createInput,
71111

72112
setupFunc: func(input asa.CreateInput) {
73113
internalTesting.MockPostError(url.CreateAsa(testModel.BaseUrl), "post error")
74114
internalTesting.MockGetOk(url.ReadDevice(testModel.BaseUrl, readOutput.Uid), readOutput)
75115
},
76116

77-
assertFunc: func(actualOutput *asa.CreateOutput, err *asa.CreateError, t *testing.T) {
117+
assertFunc: func(actualOutput *asa.ReadOutput, actualSpecificDeviceOutput *asa.ReadSpecificOutput, err *asa.CreateError, t *testing.T) {
78118
assert.Nil(t, actualOutput)
119+
assert.Nil(t, actualSpecificDeviceOutput)
79120
assert.NotNil(t, err)
80121
assert.ErrorContains(t, err, "post error")
81122
},
@@ -88,13 +129,13 @@ func TestAsaCreate(t *testing.T) {
88129

89130
testCase.setupFunc(testCase.input)
90131

91-
output, err := asa.Create(
132+
output, specificDeviceOuput, err := asa.Create(
92133
context.Background(),
93134
*http.MustNewWithConfig(testModel.BaseUrl, "a_valid_token", 0, 0, time.Minute),
94135
testCase.input,
95136
)
96137

97-
testCase.assertFunc(output, err, t)
138+
testCase.assertFunc(output, specificDeviceOuput, err, t)
98139
})
99140
}
100141
}

client/device/asa/read.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@ package asa
22

33
import (
44
"context"
5-
65
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/device/tags"
76
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/devicetype"
87
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/model/statemachine"
@@ -26,6 +25,8 @@ type ReadOutput struct {
2625
Port string `json:"port"`
2726
Host string `json:"host"`
2827
Tags tags.Type `json:"tags"`
28+
SoftwareVersion string `json:"softwareVersion"`
29+
AsdmVersion string `json:"asdmVersion,omitempty"`
2930

3031
IgnoreCertificate bool `json:"ignoreCertificate"`
3132
ConnectivityState int `json:"connectivityState,omitempty"`

client/device/asa/readspecific.go

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,15 @@ type ReadSpecificInput struct {
1313
}
1414

1515
type ReadSpecificOutput struct {
16-
SpecificUid string `json:"uid"`
17-
State state.Type `json:"state"`
18-
Namespace string `json:"namespace"`
19-
Type string `json:"type"`
16+
SpecificUid string `json:"uid"`
17+
State state.Type `json:"state"`
18+
Namespace string `json:"namespace"`
19+
Type string `json:"type"`
20+
Metadata SpecificDeviceMetadata `json:"metadata"`
21+
}
22+
23+
type SpecificDeviceMetadata struct {
24+
AsdmVersion string `json:"deviceManager"`
2025
}
2126

2227
func NewReadSpecificInput(uid string) *ReadSpecificInput {

client/device/asa/readspecific_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ import (
66
"testing"
77
"time"
88

9-
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/device"
109
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/device/asa"
1110
"github.com/CiscoDevnet/terraform-provider-cdo/go-client/internal/http"
1211
"github.com/jarcoal/httpmock"
@@ -35,7 +34,7 @@ func TestAsaReadSpecific(t *testing.T) {
3534
},
3635

3736
setupFunc: func() {
38-
configureDeviceReadSpecificToRespondSuccessfully(deviceUid, device.ReadSpecificOutput(specificDevice))
37+
configureDeviceReadSpecificToRespondSuccessfully(deviceUid, asa.ReadSpecificOutput(specificDevice))
3938
},
4039

4140
assertFunc: func(output *asa.ReadSpecificOutput, err error, t *testing.T) {

client/device/asa/update_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ func TestAsaUpdate(t *testing.T) {
8787
},
8888

8989
setupFunc: func(input asa.UpdateInput) {
90-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
90+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
9191
configureDeviceReadToRespondSuccessfully(asaDevice)
9292
configureAsaConfigUpdateToRespondSuccessfully(asaConfig.SpecificUid, asaconfig.UpdateOutput{Uid: asaConfig.SpecificUid})
9393
configureAsaConfigReadToRespondSuccessfully(asaConfig.SpecificUid, asaconfig.ReadOutput{Uid: asaConfig.SpecificUid, State: state.DONE})
@@ -111,7 +111,7 @@ func TestAsaUpdate(t *testing.T) {
111111
},
112112

113113
setupFunc: func(input asa.UpdateInput) {
114-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
114+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
115115
configureDeviceReadToRespondSuccessfully(asaDeviceOnboardedByOnPremConnector)
116116

117117
configureConnectorReadToRespondSuccessfully(onPremConnector)
@@ -141,7 +141,7 @@ func TestAsaUpdate(t *testing.T) {
141141
updatedDevice.Host = "10.10.5.4"
142142
updatedDevice.Port = "443"
143143

144-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
144+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
145145
configureDeviceReadToRespondSuccessfully(asaDevice)
146146
configureAsaConfigUpdateToRespondSuccessfully(asaConfig.SpecificUid, asaconfig.UpdateOutput{Uid: asaConfig.SpecificUid})
147147
configureAsaConfigReadToRespondSuccessfully(asaConfig.SpecificUid, asaconfig.ReadOutput{Uid: asaConfig.SpecificUid, State: state.DONE})
@@ -193,7 +193,7 @@ func TestAsaUpdate(t *testing.T) {
193193
},
194194

195195
setupFunc: func(input asa.UpdateInput) {
196-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
196+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
197197
configureDeviceReadToRespondWithError(asaDeviceOnboardedByOnPremConnector.Uid)
198198

199199
configureConnectorReadToRespondSuccessfully(onPremConnector)
@@ -217,7 +217,7 @@ func TestAsaUpdate(t *testing.T) {
217217
},
218218

219219
setupFunc: func(input asa.UpdateInput) {
220-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
220+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
221221
configureDeviceReadToRespondSuccessfully(asaDeviceOnboardedByOnPremConnector)
222222

223223
configureConnectorReadToRespondWithError(onPremConnector.Uid)
@@ -241,7 +241,7 @@ func TestAsaUpdate(t *testing.T) {
241241
},
242242

243243
setupFunc: func(input asa.UpdateInput) {
244-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
244+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
245245
configureDeviceReadToRespondSuccessfully(asaDeviceOnboardedByOnPremConnector)
246246

247247
configureConnectorReadToRespondSuccessfully(onPremConnector)
@@ -265,7 +265,7 @@ func TestAsaUpdate(t *testing.T) {
265265
},
266266

267267
setupFunc: func(input asa.UpdateInput) {
268-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
268+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
269269
configureDeviceReadToRespondSuccessfully(asaDeviceOnboardedByOnPremConnector)
270270

271271
configureConnectorReadToRespondSuccessfully(onPremConnector)
@@ -293,7 +293,7 @@ func TestAsaUpdate(t *testing.T) {
293293
updatedDevice.Host = "10.10.5.4"
294294
updatedDevice.Port = "443"
295295

296-
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, device.ReadSpecificOutput(asaConfig))
296+
configureDeviceReadSpecificToRespondSuccessfully(input.Uid, asaConfig)
297297
configureDeviceReadToRespondSuccessfully(asaDevice)
298298
configureAsaConfigUpdateToRespondSuccessfully(asaConfig.SpecificUid, asaconfig.UpdateOutput{Uid: asaConfig.SpecificUid})
299299
configureAsaConfigReadToRespondWithError(asaConfig.SpecificUid)

0 commit comments

Comments
 (0)