mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-05-03 15:51:30 -07:00
New Module to manage AWS direct connect link aggregation groups (#27250)
* Add module_utils/aws/direct_connect.py for frequently used functions * new AWS Direct Connect link aggregation group module with tests and placebo recordings * remove extra argument * Remove use of undefined var * Fix param name for extra exception codes for AWSRetry to use. * Fix undefined var and line length and metadata version number * Fix copyright headers
This commit is contained in:
parent
fe21dd272d
commit
a48e0b5101
26 changed files with 1622 additions and 0 deletions
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"data": {
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bf2372eb-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "216",
|
||||
"date": "Mon, 24 Jul 2017 19:39:02 GMT"
|
||||
},
|
||||
"RequestId": "bf2372eb-70a7-11e7-83ab-ef16f9ac5159"
|
||||
},
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "deleted",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"data": {
|
||||
"lagState": "deleted",
|
||||
"location": "EqSe2",
|
||||
"region": "us-west-2",
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bf437e0e-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "266",
|
||||
"date": "Mon, 24 Jul 2017 19:39:02 GMT"
|
||||
},
|
||||
"RequestId": "bf437e0e-70a7-11e7-83ab-ef16f9ac5159"
|
||||
},
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [],
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"minimumLinks": 0,
|
||||
"ownerAccount": "448830907657",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_1"
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bd224baf-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:59 GMT"
|
||||
},
|
||||
"RequestId": "bd224baf-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bda84490-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:59 GMT"
|
||||
},
|
||||
"RequestId": "bda84490-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "be79c564-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:39:01 GMT"
|
||||
},
|
||||
"RequestId": "be79c564-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"data": {
|
||||
"virtualInterfaces": [],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "be66d9a3-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "24",
|
||||
"date": "Mon, 24 Jul 2017 19:39:00 GMT"
|
||||
},
|
||||
"RequestId": "be66d9a3-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
{
|
||||
"data": {
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bf0c687a-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "218",
|
||||
"date": "Mon, 24 Jul 2017 19:39:01 GMT"
|
||||
},
|
||||
"RequestId": "bf0c687a-70a7-11e7-83ab-ef16f9ac5159"
|
||||
},
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"data": {
|
||||
"lagState": "pending",
|
||||
"location": "EqSe2",
|
||||
"region": "us-west-2",
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bef64869-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "509",
|
||||
"date": "Mon, 24 Jul 2017 19:39:01 GMT"
|
||||
},
|
||||
"RequestId": "bef64869-70a7-11e7-83ab-ef16f9ac5159"
|
||||
},
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"minimumLinks": 0,
|
||||
"ownerAccount": "448830907657",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1"
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bc1aedd9-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:57 GMT"
|
||||
},
|
||||
"RequestId": "bc1aedd9-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bc4902ba-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:57 GMT"
|
||||
},
|
||||
"RequestId": "bc4902ba-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bc7ff13c-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:57 GMT"
|
||||
},
|
||||
"RequestId": "bc7ff13c-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"data": {
|
||||
"virtualInterfaces": [],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bc6dc8cb-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "24",
|
||||
"date": "Mon, 24 Jul 2017 19:38:57 GMT"
|
||||
},
|
||||
"RequestId": "bc6dc8cb-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"data": {
|
||||
"Error": {
|
||||
"Code": "DirectConnectClientException",
|
||||
"Message": "Could not find Lag with ID dxlag-XXXXXXXX"
|
||||
},
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 400,
|
||||
"HTTPHeaders": {
|
||||
"connection": "close",
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "bb67ca78-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "95",
|
||||
"date": "Mon, 24 Jul 2017 19:38:56 GMT"
|
||||
},
|
||||
"RequestId": "bb67ca78-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 400
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b8662323-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:50 GMT"
|
||||
},
|
||||
"RequestId": "b8662323-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b91b4255-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:52 GMT"
|
||||
},
|
||||
"RequestId": "b91b4255-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b5e4a858-70a7-11e7-a69f-95e467ba41d7",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:46 GMT"
|
||||
},
|
||||
"RequestId": "b5e4a858-70a7-11e7-a69f-95e467ba41d7"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,157 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-9uinh2jjnuu9",
|
||||
"connections": [],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "sherteltestlag",
|
||||
"lagId": "dxlag-fgr4lfqt"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-2bii1jufy4y7p",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgytkicv",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgytkicv",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-fgsxammv"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_2",
|
||||
"lagId": "dxlag-fgytkicv"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgee5gk5"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-2bii1jufy4y7p",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_2_update",
|
||||
"lagId": "dxlag-fg0hj0n3"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-ffg1zmo4"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-2oqu43nde4cs1",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_2_update",
|
||||
"lagId": "dxlag-ffzm4jk8"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-ffuid1ql"
|
||||
},
|
||||
{
|
||||
"awsDevice": "EqSe2-2oqu43nde4cs1",
|
||||
"connections": [],
|
||||
"lagState": "deleted",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 0,
|
||||
"lagName": "ansible_lag_2_update",
|
||||
"lagId": "dxlag-ffpq2qa7"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b6a0a55a-70a7-11e7-a69f-95e467ba41d7",
|
||||
"content-length": "2920",
|
||||
"date": "Mon, 24 Jul 2017 19:38:49 GMT"
|
||||
},
|
||||
"RequestId": "b6a0a55a-70a7-11e7-a69f-95e467ba41d7"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-1bwfvazist2k0",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgkk4dja",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgkk4dja",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-ffx41o23"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_1",
|
||||
"lagId": "dxlag-fgkk4dja"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b4aa057e-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:44 GMT"
|
||||
},
|
||||
"RequestId": "b4aa057e-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"data": {
|
||||
"Error": {
|
||||
"Code": "DirectConnectClientException",
|
||||
"Message": "Could not find Lag with ID dxlag-XXXXXXXX"
|
||||
},
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 400,
|
||||
"HTTPHeaders": {
|
||||
"connection": "close",
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b7f55ff2-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "95",
|
||||
"date": "Mon, 24 Jul 2017 19:38:50 GMT"
|
||||
},
|
||||
"RequestId": "b7f55ff2-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 400
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"data": {
|
||||
"Error": {
|
||||
"Code": "DirectConnectClientException",
|
||||
"Message": "Lag ID doesntexist has an invalid format."
|
||||
},
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 400,
|
||||
"HTTPHeaders": {
|
||||
"connection": "close",
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b3c76dc0-70a7-11e7-a2a8-21d8bda1f5ec",
|
||||
"content-length": "95",
|
||||
"date": "Mon, 24 Jul 2017 19:38:42 GMT"
|
||||
},
|
||||
"RequestId": "b3c76dc0-70a7-11e7-a2a8-21d8bda1f5ec"
|
||||
}
|
||||
},
|
||||
"status_code": 400
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-2bii1jufy4y7p",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgytkicv",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgytkicv",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-fgsxammv"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_2",
|
||||
"lagId": "dxlag-fgytkicv"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "b9cc69e9-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "520",
|
||||
"date": "Mon, 24 Jul 2017 19:38:53 GMT"
|
||||
},
|
||||
"RequestId": "b9cc69e9-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
{
|
||||
"data": {
|
||||
"lags": [
|
||||
{
|
||||
"awsDevice": "EqSe2-2bii1jufy4y7p",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgytkicv",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgytkicv",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-fgsxammv"
|
||||
}
|
||||
],
|
||||
"lagState": "pending",
|
||||
"minimumLinks": 0,
|
||||
"location": "EqSe2",
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"ownerAccount": "448830907657",
|
||||
"region": "us-west-2",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_2_update",
|
||||
"lagId": "dxlag-fgytkicv"
|
||||
}
|
||||
],
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "ba91197b-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "527",
|
||||
"date": "Mon, 24 Jul 2017 19:38:54 GMT"
|
||||
},
|
||||
"RequestId": "ba91197b-70a7-11e7-83ab-ef16f9ac5159"
|
||||
}
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
{
|
||||
"data": {
|
||||
"lagState": "pending",
|
||||
"location": "EqSe2",
|
||||
"region": "us-west-2",
|
||||
"ResponseMetadata": {
|
||||
"RetryAttempts": 0,
|
||||
"HTTPStatusCode": 200,
|
||||
"HTTPHeaders": {
|
||||
"content-type": "application/x-amz-json-1.1",
|
||||
"x-amzn-requestid": "ba76658a-70a7-11e7-83ab-ef16f9ac5159",
|
||||
"content-length": "516",
|
||||
"date": "Mon, 24 Jul 2017 19:38:54 GMT"
|
||||
},
|
||||
"RequestId": "ba76658a-70a7-11e7-83ab-ef16f9ac5159"
|
||||
},
|
||||
"lagId": "dxlag-fgytkicv",
|
||||
"awsDevice": "EqSe2-2bii1jufy4y7p",
|
||||
"connections": [
|
||||
{
|
||||
"bandwidth": "1Gbps",
|
||||
"connectionName": "Requested Connection 1 for Lag dxlag-fgytkicv",
|
||||
"location": "EqSe2",
|
||||
"ownerAccount": "448830907657",
|
||||
"lagId": "dxlag-fgytkicv",
|
||||
"region": "us-west-2",
|
||||
"connectionState": "requested",
|
||||
"connectionId": "dxcon-fgsxammv"
|
||||
}
|
||||
],
|
||||
"connectionsBandwidth": "1Gbps",
|
||||
"minimumLinks": 0,
|
||||
"ownerAccount": "448830907657",
|
||||
"numberOfConnections": 1,
|
||||
"lagName": "ansible_lag_2_update"
|
||||
},
|
||||
"status_code": 200
|
||||
}
|
|
@ -0,0 +1,176 @@
|
|||
# (c) 2017 Red Hat Inc.
|
||||
#
|
||||
# This file is part of Ansible
|
||||
#
|
||||
# Ansible is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# Ansible is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import pytest
|
||||
import os
|
||||
import collections
|
||||
from . placebo_fixtures import placeboify, maybe_sleep
|
||||
from ansible.modules.cloud.amazon import aws_direct_connect_link_aggregation_group as lag_module
|
||||
from ansible.module_utils.ec2 import get_aws_connection_info, boto3_conn
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def dependencies():
|
||||
|
||||
# each LAG dict will contain the keys: module, connections, virtual_interfaces
|
||||
Dependencies = collections.namedtuple("Dependencies", ["lag_1", "lag_2"])
|
||||
lag_1 = dict()
|
||||
lag_2 = dict()
|
||||
|
||||
vanilla_params = {"name": "ansible_lag_1",
|
||||
"location": "EqSe2",
|
||||
"num_connections": 1,
|
||||
"min_links": 0,
|
||||
"bandwidth": "1Gbps"}
|
||||
|
||||
for lag in ("ansible_lag_1", "ansible_lag_2"):
|
||||
params = dict(vanilla_params)
|
||||
params["name"] = lag
|
||||
if lag == "ansible_lag_1":
|
||||
lag_1["module"] = FakeModule(**params)
|
||||
else:
|
||||
lag_2["module"] = FakeModule(**params)
|
||||
|
||||
if os.getenv("PLACEBO_RECORD"):
|
||||
region, ec2_url, aws_connect_kwargs = get_aws_connection_info(lag_1["module"], boto3=True)
|
||||
client = boto3_conn(lag_1["module"], conn_type="client", resource="directconnect", region=region, endpoint=ec2_url, **aws_connect_kwargs)
|
||||
# See if link aggregation groups exist
|
||||
for name in ("ansible_lag_1", "ansible_lag_2"):
|
||||
lag_id = lag_module.create_lag(client, num_connections=1, location="EqSe2", bandwidth="1Gbps", name=name, connection_id=None)
|
||||
if name == "ansible_lag_1":
|
||||
lag_1["lag_id"] = lag_id
|
||||
lag_1["name"] = name
|
||||
else:
|
||||
lag_2["lag_id"] = lag_id
|
||||
lag_2["name"] = name
|
||||
yield Dependencies(lag_1=lag_1, lag_2=lag_2)
|
||||
else:
|
||||
lag_1.update(lag_id="dxlag-fgkk4dja", name="ansible_lag_1")
|
||||
lag_2.update(lag_id="dxlag-fgytkicv", name="ansible_lag_2")
|
||||
yield Dependencies(lag_1=lag_1, lag_2=lag_2)
|
||||
|
||||
if os.getenv("PLACEBO_RECORD"):
|
||||
# clean up
|
||||
lag_module.ensure_absent(client, lag_1["lag_id"], lag_1["name"], True, True, True, 120)
|
||||
lag_module.ensure_absent(client, lag_2["lag_id"], lag_2["name"], True, True, True, 120)
|
||||
|
||||
|
||||
class FakeModule(object):
|
||||
def __init__(self, **kwargs):
|
||||
self.params = kwargs
|
||||
|
||||
def fail_json(self, *args, **kwargs):
|
||||
self.exit_args = args
|
||||
self.exit_kwargs = kwargs
|
||||
raise Exception("FAIL")
|
||||
|
||||
def exit_json(self, *args, **kwargs):
|
||||
self.exit_args = args
|
||||
self.exit_kwargs = kwargs
|
||||
|
||||
|
||||
def test_nonexistent_lag_status(placeboify, maybe_sleep):
|
||||
client = placeboify.client("directconnect")
|
||||
exists = lag_module.lag_exists(client=client,
|
||||
lag_id="doesntexist",
|
||||
lag_name="doesntexist",
|
||||
verify=True)
|
||||
assert not exists
|
||||
|
||||
|
||||
def test_lag_status(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
status = lag_module.lag_status(client, lag_id=dependencies.lag_1.get("lag_id"))
|
||||
assert status.get("lagId") == dependencies.lag_1.get("lag_id")
|
||||
assert status.get("lagName") == "ansible_lag_1"
|
||||
|
||||
|
||||
def test_lag_exists(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
exists = lag_module.lag_exists(client=client,
|
||||
lag_id=dependencies.lag_1.get("lag_id"),
|
||||
lag_name=None,
|
||||
verify=True)
|
||||
assert exists
|
||||
|
||||
|
||||
def test_lag_exists_using_name(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
exists = lag_module.lag_exists(client=client,
|
||||
lag_id=None,
|
||||
lag_name=dependencies.lag_1.get("name"),
|
||||
verify=True)
|
||||
assert exists
|
||||
|
||||
|
||||
def test_nonexistent_lag_does_not_exist(placeboify, maybe_sleep):
|
||||
client = placeboify.client("directconnect")
|
||||
exists = lag_module.lag_exists(client=client,
|
||||
lag_id="dxlag-XXXXXXXX",
|
||||
lag_name="doesntexist",
|
||||
verify=True)
|
||||
assert not exists
|
||||
|
||||
|
||||
def test_lag_changed_true(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
status = lag_module.lag_status(client=client, lag_id=dependencies.lag_1.get("lag_id"))
|
||||
assert lag_module.lag_changed(status, "new_name", 1)
|
||||
|
||||
|
||||
def test_lag_changed_true_no(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
status = lag_module.lag_status(client=client, lag_id=dependencies.lag_1.get("lag_id"))
|
||||
assert not lag_module.lag_changed(status, "ansible_lag_1", 0)
|
||||
|
||||
|
||||
def test_update_lag(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
status_before = lag_module.lag_status(client=client, lag_id=dependencies.lag_2.get("lag_id"))
|
||||
lag_module.update_lag(client,
|
||||
lag_id=dependencies.lag_2.get("lag_id"),
|
||||
lag_name="ansible_lag_2_update",
|
||||
min_links=0,
|
||||
wait=False,
|
||||
wait_timeout=0,
|
||||
num_connections=1)
|
||||
status_after = lag_module.lag_status(client=client, lag_id=dependencies.lag_2.get("lag_id"))
|
||||
assert status_before != status_after
|
||||
|
||||
# remove the lag name from the statuses and verify it was the only thing changed
|
||||
del status_before['lagName']
|
||||
del status_after['lagName']
|
||||
assert status_before == status_after
|
||||
|
||||
|
||||
def test_delete_nonexistent_lag(placeboify, maybe_sleep):
|
||||
client = placeboify.client("directconnect")
|
||||
changed = lag_module.ensure_absent(client, "dxlag-XXXXXXXX", "doesntexist", True, True, True, 120)
|
||||
assert not changed
|
||||
|
||||
|
||||
def test_delete_lag_with_connections_without_force_delete(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
with pytest.raises(Exception) as error_message:
|
||||
lag_module.ensure_absent(client, dependencies.lag_1.get("lag_id"), "ansible_lag_1", False, True, True, 120)
|
||||
assert "To force deletion of the LAG use delete_force: True" in error_message
|
||||
|
||||
|
||||
def test_delete_lag_with_connections(placeboify, maybe_sleep, dependencies):
|
||||
client = placeboify.client("directconnect")
|
||||
changed = lag_module.ensure_absent(client, dependencies.lag_1.get("lag_id"), "ansible_lag_1", True, True, True, 120)
|
||||
assert changed
|
Loading…
Add table
Add a link
Reference in a new issue