diff --git a/.github/no-response.yml b/.github/no-response.yml new file mode 100644 index 000000000000..bacbe1631ef1 --- /dev/null +++ b/.github/no-response.yml @@ -0,0 +1,13 @@ +# Configuration for probot-no-response - https://github.com/probot/no-response + +# Number of days of inactivity before an Issue is closed for lack of response +daysUntilClose: 14 +# Label requiring a response +responseRequiredLabel: customer-response-expected +# Comment to post when closing an Issue for lack of response. Set to `false` to disable +closeComment: > + This issue has been automatically closed because there has been no response + to our request for more information from the original author. With only the + information that is currently in the issue, we don't have enough information + to take action. Please reach out if you have or find the answers we need so + that we can investigate further. \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index 3746de322502..e77bf1ad3f3f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,792 +1,1320 @@ # CHANGELOG -## `v14.3.0` +## `v38.2.0` -### Changes +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| attestation | 2018-09-01-preview | +| eventgrid | 2020-04-01-preview | +| storagesync | 2019-06-01 | -- Add exports for max file range and sizes for files in storage. -- Updated README regarding blob storage support. -- Add godoc indexer tool. -- Add apidiff tool. +## `v38.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| frontdoor | 2019-10-01
2019-11-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| storage | 2019-06-01 | + +## `v38.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| containerregistry | 2019-12-01-preview | +| databoxedge | 2019-08-01 | +| machinelearningservices | 2020-01-01 | +| netapp | 2019-10-01 | +| windowsesu | 2019-09-16-preview | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| anomalydetector | v1.0 | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | +| insights | 2015-05-01 | +| media | 2018-07-01 | +| personalizer | v1.0 | +| resourcehealth | 2017-07-01 | +| servicebus | 2018-01-01-preview | +| siterecovery | 2018-07-10 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| authorization | 2015-07-01
2017-10-01-preview | +| blueprint | 2018-11-01-preview | +| compute | 2018-10-01
2019-03-01
2019-07-01 | +| containerservice | 2019-11-01 | +| customerlockbox | 2018-02-28-preview | +| databricks | 2018-04-01 | +| datafactory | 2018-06-01 | +| features | 2019-07-01 | +| managedservices | 2018-06-01
2019-04-01 | +| resources | 2015-11-01
2016-02-01
2016-07-01
2016-09-01
2017-05-10
2018-02-01
2018-05-01
2019-03-01
2019-05-01 | +| security | v1.0
v2.0
v3.0 | +| servicefabric | 2017-07-01-preview
2018-02-01
2019-03-01
2019-03-01-preview | +| sql | v3.0 | +| textanalytics | v2.1 | + +## `v37.2.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| containerservice | 2019-11-01 | +| deploymentmanager | 2019-11-01-preview | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| containerservice | 2017-07-01
2017-08-31
2017-09-30
2018-03-31 | +| machinelearningservices | 2019-11-01 | + +## `v37.1.0` + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| iotcentral | 2018-09-01 | + +## `v37.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| azuredata | 2017-03-01-preview | +| backup | 2019-05-13 | +| customerlockbox | 2018-02-28-preview | +| managedapplications | 2019-07-01 | +| servicefabric | 7.0 | +| siterecovery | 2018-07-10 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| azurestack | 2017-06-01 | +| compute | 2018-04-01
2018-06-01
2018-10-01
2019-03-01 | +| containerregistry | 2019-06-01-preview | +| containerservice | 2019-10-01 | +| datashare | 2018-11-01-preview
2019-11-01 | +| hanaonazure | 2017-11-03-preview | +| mysql | 2017-12-01
2017-12-01-preview | +| network | 2019-09-01 | +| policyinsights | 2019-10-01 | +| postgresql | 2017-12-01-preview | +| qnamaker | v4.0 | +| securityinsight | 2017-08-01-preview | +| sql | 2015-05-01-preview
2018-06-01-preview | +| sqlvirtualmachine | 2017-03-01-preview | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| appplatform | 2019-05-01-preview | +| backup | 2017-07-01 | +| cdn | 2019-06-15-preview | +| compute | 2019-07-01 | +| datafactory | 2018-06-01 | +| documentdb | 2019-08-01
2019-08-01-preview | +| network | 2019-08-01 | +| resourcegraph | 2018-09-01 | +| security | v1.0
v2.0
v3.0 | +| sql | 2017-03-01-preview
v3.0 | +| storage | 2019-06-01 | +| virtualmachineimagebuilder | 2019-05-01-preview | + +## `v36.2.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| media | 2019-05-01-preview | +| netapp | 2019-08-01 | +| sql | v3.0 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| containerservice | 2019-06-01 | + +## `v36.1.0` + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| eventgrid | 2020-01-01-preview | + +## `v36.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| documentdb | 2019-08-01-preview | +| machinelearningservices | 2019-11-01 | +| managementgroups | 2019-11-01 | +| policy | 2019-09-01 | +| workspaces | 2019-10-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| datafactory | 2018-06-01 | +| hanaonazure | 2017-11-03-preview | +| securityinsight | 2017-08-01-preview | +| storage | 2019-06-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| authoring | luis | +| network | 2019-04-01
2019-06-01
2019-07-01
2019-08-01
2019-09-01 | +| serialconsole | 2018-05-01 | +| signalr | 2018-10-01 | +| sql | 2018-06-01-preview | +| timeseriesinsights | 2018-08-15-preview | + +### Removed Packages + +| Package Name | API Version | +| -----------: | :---------: | +| documentdb | 2019-08-01-preview | + +## `v35.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| documentdb | 2019-08-01
2019-08-01-preview | + +## `v35.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| appconfiguration | 2019-10-01 | +| authoring | luis | +| containerservice | 2019-09-30-preview
2019-10-01 | +| costmanagement | 2019-10-01
2019-10-01 | +| datashare | 2019-11-01 | +| hybridcompute | 2019-03-18-preview | +| peering | 2019-09-01-preview | +| policyinsights | 2019-10-01 | +| storagecache | 2019-11-01 | +| training | customvision | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| advisor | 2017-03-31
2017-04-19 | +| apimanagement | 2019-01-01 | +| compute | 2018-10-01 | +| containerservice | 2019-08-01 | +| datafactory | 2017-09-01-preview | +| eventgrid | 2018-01-01 | +| eventhub | 2018-01-01-preview | +| maps | 2017-01-01-preview | +| mysql | 2017-12-01-preview | +| postgresql | 2017-12-01-preview | +| qnamakerruntime | v4.0 | +| sqlvirtualmachine | 2017-03-01-preview | +| web | 2018-02-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| aad | 2017-01-01
2017-06-01 | +| appplatform | 2019-05-01-preview | +| backup | 2016-12-01
2017-07-01 | +| cdn | 2019-04-15 | +| cognitiveservices | 2017-04-18 | +| compute | 2019-03-01
2019-07-01 | +| containerregistry | 2017-10-01
2018-02-01
2018-09-01 | +| datafactory | 2018-06-01 | +| datashare | 2018-11-01-preview | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | +| operationalinsights | 2015-03-20 | +| reservations | 2019-04-01 | +| security | v3.0 | +| servicebus | 2017-04-01 | +| sql | 2014-04-01 | +| storage | 2019-04-01 | +| vmwarecloudsimple | 2019-04-01 | +| web | 2019-08-01 | + +### Removed Packages + +| Package Name | API Version | +| -----------: | :---------: | +| sql | 2018-06-15-preview | + +## `v34.4.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| eventgrid | 2020-01-01-preview | +| sql | 2018-06-15-preview | + +## `v34.3.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| network | 2019-09-01 | +| runtime | luis | +| storage | 2019-06-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| datamigration | 2018-07-15-preview | + +### Removed Packages + +| Package Name | API Version | +| -----------: | :---------: | +| runtime | luis | + +## `v34.2.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| appplatform | 2019-05-01-preview | +| web | 2019-08-01 | + +## `v34.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| features | 2019-07-01 | +| network | 2019-08-01 | +| affinitygroup | management | +| auth | keyvault | +| hostedservice | management | +| location | management | +| mongodb | cosmos-db | +| networksecuritygroup | management | +| osimage | management | +| programmatic | luis | +| sql | management | +| storageservice | management | +| testutils | management | +| virtualmachine | management | +| virtualmachinedisk | management | +| virtualmachineimage | management | +| virtualnetwork | management | +| vmutils | management | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| compute | 2019-03-01
2019-07-01 | + +Revert deletion of packages in `classic\management` and `keyvault\auth` + +## `v34.0.0` + +### New Packages +| Package Name | API Version | +| -----------: | :---------: | +| databox | 2019-09-01 | +| databoxedge | 2019-03-01
2019-07-01 | +| frontdoor | 2019-04-01
2019-05-01 | +| healthcareapis | 2019-09-16 | +| kusto | 2019-09-07 | +| logic | 2019-05-01 | +| maintenance | 2018-06-01-preview | +| storagedatalake | 2019-10-31 | +| subscriptions | 2019-06-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| appconfiguration | 2019-02-01-preview | +| datashare | 2018-11-01-preview | +| eventgrid | 2018-01-01 | +| eventhub | 2017-04-01 | +| kusto | 2019-05-15 | +| network | 2018-07-01
2018-08-01
2018-10-01
2018-11-01
2018-12-01
2019-02-01 | +| servicebus | 2017-04-01 | +| sql | 2015-05-01-preview
2017-03-01-preview | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2019-01-01 | +| compute | 2016-03-30
2017-03-30
2017-12-01
2018-04-01
2018-06-01
2018-10-01
2019-03-01
2019-07-01 | +| containerregistry | 2019-05-01-preview
2019-06-01-preview | +| containerservice | 2019-06-01
2019-08-01 | +| datafactory | 2018-06-01 | +| datamigration | 2018-03-31-preview
2018-04-19
2018-07-15-preview | +| documentdb | 2015-04-08 | +| frontdoor | 2018-08-01-preview | +| machinelearningservices | 2019-06-01 | +| managednetwork | 2019-06-01-preview | +| network | 2019-04-01 | +| reservations | 2019-04-01 | +| security | v1.0
v2.0
v3.0 | +| securityinsight | 2017-08-01-preview | +| storage | 2019-04-01 | + +### Removed Packages + +| Package Name | API Version | +| -----------: | :---------: | +| affinitygroup | management | +| anomalyfinder | v2.0 | +| auth | keyvault | +| batch | 2015-12-01.2.2
2016-02-01.3.0
2016-07-01.3.1
2017-01-01.4.0
2017-06-01.5.1
2017-09-01.6.0 | +| computervision | v1.0 | +| devspaces | 2018-06-01-preview
2019-01-01-preview | +| edgegateway | 2019-03-01 | +| frontdoor | preview/2019-04-01
preview/2019-05-01 | +| hostedservice | management | +| insights | v1 | +| location | management | +| mobileengagement | 2014-12-01 | +| mongodb | cosmos-db | +| networksecuritygroup | management | +| osimage | management | +| peering | 2019-03-01-preview | +| portal | 2015-11-01-preview | +| programmatic | luis | +| servicefabric | 2019-03-01 | +| services | 2018-03-01-preview | +| sql | management | +| storageservice | management | +| testutils | management | +| virtualmachine | management | +| virtualmachinedisk | management | +| virtualmachineimage | management | +| virtualnetwork | management | +| vmutils | management | + +## `v33.4.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| netapp | 2019-07-01 | + +## `v33.3.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| network | 2019-07-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| network | 2019-06-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| sql | 2017-10-01-preview
2018-06-01-preview | + +## `v33.2.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| sql | 2018-06-01-preview | + +## `v33.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| storagecache | 2019-08-01-preview | + +## `v33.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| batch | 2019-08-01
2019-08-01.10.0 | +| computervision | v2.1 | +| containerregistry | 2019-07 | +| containerservice | 2019-08-01 | +| frontdoor | 2019-05-01 | +| machinelearningservices | 2019-06-01 | +| managednetwork | 2019-06-01-preview | +| peering | 2019-08-01-preview | +| policy | 2019-06-01 | +| portal | 2018-10-01-preview | +| servicefabric | 2019-03-01-preview | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| backup | 2016-12-01
2017-07-01 | +| frontdoor | 2019-04-01 | +| logic | 2016-06-01
2018-07-01-preview | +| network | 2018-07-01
2018-08-01
2018-10-01
2018-11-01
2018-12-01 | +| resources | 2015-11-01
2016-02-01
2016-07-01
2016-09-01
2017-05-10
2018-02-01
2018-05-01
2019-03-01
2019-05-01 | +| security | v2.0 | +| sql | 2015-05-01-preview
2017-03-01-preview
2017-10-01-preview | +| storage | 2019-04-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| billing | 2018-11-01-preview | +| compute | 2019-03-01
2019-07-01 | +| datafactory | 2018-06-01 | +| datamigration | 2017-11-15-preview
2018-03-31-preview
2018-04-19
2018-07-15-preview | +| hanaonazure | 2017-11-03-preview | +| healthcareapis | 2018-08-20-preview | +| inkrecognizer | v1.0 | +| insights | 2015-05-01 | +| kusto | 2019-01-21 | +| network | 2019-02-01
2019-04-01
2019-06-01 | +| qnamaker | v4.0 | +| reservations | 2019-04-01 | +| security | v3.0 | +| securityinsight | 2017-08-01-preview | +| servicefabric | 2019-03-01 | -## `v14.2.0` +## `v32.6.0` -### Changes +### New Packages -- For blob storage, added GetProperties() method to Container. -- Added PublicAccess field to ContainerProperties struct. +| Package Name | API Version | +| -----------: | :---------: | +| kusto | 2019-05-15 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| datalake | 2018-06-17 | -## `v14.1.1` +## `v32.5.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| servicebus | 2018-01-01-preview | -- Fixing timestamp marshalling bug in the `storage` package. -- Updating `profileBuilder` to clear-output folders when it is run by `go generate`. -- Tweaking Swagger -> SDK config to use "latest" instead of "nightly" and be tied to a particular version of autorest.go. +## `v32.4.0` + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| datamigration | 2018-07-15-preview | + +## `v32.3.0` + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| subscription | 2018-03-01-preview | + +## `v32.2.0` + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | + +## `v32.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| qnamakerruntime | v4.0 | + +### Fixed a bug with the table query continuation token in the ./storage package. + +## `v32.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| aad | 2017-04-01 | +| compute | 2019-07-01 | +| datashare | 2018-11-01-preview | +| devops | 2019-07-01-preview | +| enterpriseknowledgegraphservice | 2018-12-03 | +| managedservices | 2019-06-01 | +| migrate | 2018-09-01-preview | +| mysql | 2017-12-01-preview | +| network | 2019-06-01 | +| policy | 2019-01-01 | +| portal | 2015-08-01-preview
2019-01-01-preview | +| postgresql | 2017-12-01-preview | +| windowsiot | 2019-06-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| alertsmanagement | 2019-05-05 | +| authoring | luis | +| cdn | 2019-04-15 | +| datafactory | 2017-09-01-preview | +| datamigration | 2018-07-15-preview | +| devices | 2019-03-22-preview | +| hanaonazure | 2017-11-03-preview | +| signalr | 2018-10-01 | +| subscriptions | 2018-06-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| compute | 2019-03-01 | +| contentmoderator | v1.0 | +| datafactory | 2018-06-01 | +| documentdb | 2015-04-08 | +| dtl | 2018-09-15 | +| healthcareapis | 2018-08-20-preview | +| insights | 2018-03-01
2018-09-01
2018-11-01-preview
2019-03-01
2019-06-01 | +| machinelearningservices | 2019-05-01 | +| managedservices | 2018-06-01 | +| network | 2019-04-01 | +| reservations | 2019-04-01 | +| security | v1.0
v2.0
v3.0 | +| securityinsight | 2017-08-01-preview | +| storage | 2019-04-01 | + +## `v31.2.0` + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2019-01-01 | + +## `v31.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| alertsmanagement | 2019-03-01 | +| authorization | 2018-07-01-preview | +| batch | 2019-04-01 | +| containerregistry | 2019-06-01-preview | +| netapp | 2019-06-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| alertsmanagement | 2018-05-05-preview | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | +| sqlvirtualmachine | 2017-03-01-preview | + +## `v31.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| alertsmanagement | 2019-05-05 | +| appconfiguration | 2019-02-01-preview | +| cdn | 2019-06-15-preview | +| containerservice | 2019-06-01 | +| insights | 2019-06-01 | +| machinelearningservices | 2018-03-01-preview
2018-11-19
2019-05-01 | +| network | 2019-04-01 | +| resources | 2019-05-01 | +| servicefabric | 6.5 | +| softwareplan | 2019-06-01-preview | +| vmwarecloudsimple | 2019-04-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| cognitiveservices | 2017-04-18 | +| compute | 2019-03-01 | +| containerregistry | 2019-04-01
2019-05-01 | +| hanaonazure | 2017-11-03-preview | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | +| insights | 2017-05-01-preview
2018-03-01
2018-09-01
2018-11-01-preview
2019-03-01 | +| managementgroups | 2018-03-01-preview | +| media | 2018-07-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| alertsmanagement | 2018-05-05 | +| authorization | 2015-07-01 | +| billing | 2018-11-01-preview | +| blueprint | 2018-11-01-preview | +| computervision | v2.0 | +| datafactory | 2017-09-01-preview
2018-06-01 | +| eventgrid | 2018-01-01 | +| eventhub | 2015-08-01
2018-01-01-preview | +| face | v1.0 | +| netapp | 2019-05-01 | +| network | 2015-06-15
2016-09-01
2016-12-01
2017-03-01
2017-06-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2018-01-01
2018-02-01
2018-04-01
2018-06-01
2018-07-01
2018-08-01
2018-10-01
2018-11-01
2018-12-01
2019-02-01 | +| reservations | 2019-04-01 | +| resourcegraph | 2019-04-01 | +| securityinsight | 2017-08-01-preview | +| sql | 2015-05-01-preview
2017-03-01-preview | +| storage | 2019-04-01 | + +## `v30.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| batch | 2019-06-01.9.0 | +| managedservices | 2019-04-01 | +| personalizer | v1.0 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| authorization | 2017-10-01-preview
2018-01-01-preview
2018-09-01-preview | +| automation | 2015-10-31
2017-05-15-preview
2018-01-15-preview
2018-06-30-preview | +| datafactory | 2018-06-01 | +| datamigration | 2018-07-15-preview | +| documentdb | 2015-04-08 | +| formrecognizer | v1.0 | +| hanaonazure | 2017-11-03-preview | +| hdinsight | 2018-06-01-preview | +| postgresql | 2017-12-01 | +| qnamaker | v4.0 | +| signalr | 2018-10-01 | + +## `v30.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| blockchain | 2018-06-01-preview | +| containerregistry | 2019-05-01
2019-05-01-preview | +| costmanagement | 2019-03-01 | +| devices | 2019-03-22-preview | +| devspaces | 2019-04-01 | +| dns | 2018-05-01 | +| eventgrid | 2019-06-01 | +| security | v3.0 | +| servicefabric | 2019-03-01
2019-03-01 | + +### Updated Packages + +| account | 2016-11-01 | +| advisor | 2017-04-19 | +| billing | 2018-11-01-preview | +| cdn | 2019-04-15 | +| cognitiveservices | 2017-04-18 | +| customproviders | 2018-09-01-preview | +| datafactory | 2018-06-01 | +| devices | 2018-12-01-preview | +| eventgrid | 2018-01-01 | +| hanaonazure | 2017-11-03-preview | +| kusto | 2019-01-21 | +| managementpartner | 2018-02-01 | +| mariadb | 2018-06-01 | +| mysql | 2017-12-01 | +| network | 2019-02-01 | +| operationsmanagement | 2015-11-01-preview | +| postgresql | 2017-12-01 | +| servicefabric | 2016-09-01 | +| web | 2018-02-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| analysisservices | 2017-08-01 | +| authoring | luis | +| automation | 2018-01-15-preview
2018-06-30-preview | +| blueprint | 2018-11-01-preview | +| compute | 2017-12-01 | +| computervision | v2.0 | +| contentmoderator | v1.0 | +| documentdb | 2015-04-08 | +| insights | 2015-05-01 | +| netapp | 2019-05-01 | +| resources | 2018-05-01 | +| security | v1.0
v2.0 | +| servicefabric | 2017-07-01-preview
2018-02-01 | +| spellcheck | v1.0 | +| subscriptions | 2016-06-01 | + +## `v29.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| cdn | 2019-04-15 | +| customproviders | 2018-09-01-preview | +| formrecognizer | v1.0 | +| inkrecognizer | v1.0 | +| portal | 2015-11-01-preview | +| runtime | luis | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| insights | 2018-03-01
2018-09-01
2018-11-01-preview
2019-03-01 | +| locks | 2016-09-01 | +| sql | 2014-04-01
2017-10-01-preview | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2019-01-01 | +| containerservice | 2019-04-30 | +| graphrbac | 1.6 | +| sql | 2015-05-01-preview
2017-03-01-preview | +| storage | 2019-04-01 | + +## `v28.1.0` + +Fixed build issue in legacy storage package affecting some consumers. + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| resourcegraph | 2018-09-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| eventhub | 2018-01-01-preview | + +## `v28.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| containerregistry | 2019-04-01 | +| containerservice | 2019-04-30 | +| hybriddata | 2016-06-01 | +| netapp | 2019-05-01 | +| network | 2019-02-01 | +| resources | 2019-03-01 | +| serialconsole | 2018-05-01 | +| storage | 2019-04-01 | +| subscriptions | 2018-06-01 | +| virtualmachineimagebuilder | 2019-05-01-preview | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| cognitiveservices | 2017-04-18 | +| consumption | 2019-01-01 | +| costmanagement | 2019-01-01 | +| datafactory | 2018-06-01 | +| eventgrid | 2018-01-01 | +| iotcentral | 2018-09-01 | +| qnamaker | v4.0 | +| sql | 2017-10-01-preview | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2018-06-01-preview
2019-01-01 | +| billing | 2018-11-01-preview | +| compute | 2019-03-01 | +| cosmos-db | 2015-04-08 | +| documentdb | 2015-04-08 | +| hanaonazure | 2017-11-03-preview | +| insights | 2018-03-01
2018-09-01
2018-11-01-preview
2019-03-01 | +| mysql | 2017-12-01 | +| network | 2017-06-01
2017-08-01
2017-09-01
2017-10-01
2017-11-01
2018-01-01
2018-02-01
2018-04-01
2018-06-01
2018-07-01
2018-08-01
2018-10-01
2018-11-01
2018-12-01 | +| operationalinsights | 2015-11-01-preview | +| policyinsights | 2018-07-01-preview | +| postgresql | 2017-12-01 | +| resources | 2018-05-01 | +| runtime | luis | +| sql | 2015-05-01-preview
2017-03-01-preview | +| storagedatalake | 2018-11-09 | +| subscriptions | 2016-06-01 | +| virtualmachineimagebuilder | 2019-02-01-preview | +| web | 2018-02-01 | + +### Removed Packages (duplicates) + +| Package Name | API Version | +| -----------: | :---------: | +| automation | 2017-05-15-preview | +| compute | 2017-06-01-preview | +| devices | 2018-12-01-preview | +| fabric | 2016-05-01 | +| infrastructureinsights | 2016-05-01 | +| mariadb | 2018-06-01-preview | +| postgresql | 2017-04-30-preview
2017-12-01-preview | +| reservations | 2018-06-01 | +| storagesync | 2018-10-01 | + +## `v27.3.0` + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| anomalydetector | v1.0 | + +### Breaking Changes - Preview Only + +| Package Name | API Version | +| -----------: | :---------: | +| hanaonazure | 2017-11-03-preview | + +## `v27.2.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2019-01-01 | +| reservations | 2019-04-01 | + +## `v27.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| compute | 2019-03-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| cdn | 2017-10-12 | +| compute | 2018-10-01 | +| containerservice | 2018-08-01-preview
2018-09-30-preview
2019-02-01 | +| datafactory | 2018-06-01 | +| hdinsight | 2018-06-01-preview | +| postgresql | 2017-12-01 | +| recoveryservices | 2016-06-01 | +| security | v1.0
v2.0 | +| securityinsight | 2017-08-01-preview | +| storage | 2018-02-01
2018-03-01-preview
2018-07-01
2018-11-01 | + +### Breaking Changes - Preview Only + +| Package Name | API Version | +| -----------: | :---------: | +| hdinsight | 2015-03-01-preview | + +## `v27.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| billing | 2018-11-01-preview | +| frontdoor | 2019-04-01 | +| healthcareapis | 2018-08-20-preview | +| managedservices | 2018-06-01 | +| peering | 2019-03-01-preview | +| resourcegraph | 2019-04-01 | +| storagesync | 2019-02-01 | +| virtualmachineimagebuilder | 2018-02-01-preview
2019-02-01-preview | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| adhybridhealthservice | 2014-01-01 | +| catalog | 2016-11-01-preview | +| containerregistry | 2017-10-01
2018-02-01
2018-09-01 | +| eventgrid | 2018-01-01 | +| eventhub | 2017-04-01 | +| hanaonazure | 2017-11-03-preview | +| mysql | 2017-12-01 | +| postgresql | 2017-12-01 | +| security | v1.0
v2.0 | +| servicebus | 2017-04-01 | +| signalr | 2018-10-01 | +| sql | 2017-03-01-preview | +| storage | 2018-11-01 | -## `v14.1.0` +### BreakingChanges -### Changes +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2018-06-01-preview | +| authoring | luis | +| blueprint | 2018-11-01-preview | +| cdn | 2017-10-12 | +| compute | 2018-10-01 | +| computervision | v2.0 | +| datafactory | 2017-09-01-preview
2018-06-01 | +| devices | 2018-12-01-preview | +| edgegateway | 2019-03-01 | +| face | v1.0 | +| graphrbac | 1.6 | +| insights | 2018-03-01 | +| postgresqlapi | postgresql | +| search | 2015-08-19 | +| web | 2018-02-01 | +| webservices | 2017-01-01 | -- Update README with details on new authentication helpers. -- Update `latest` profile to point to latest stable API versions. -- Add new API version for Azure Monitoring service and for Batch Data plane service. +## `v26.7.0` -## `v14.0.2` +| Package Name | API Version | +| -----------: | :---------: | +| training | v3.0 | -### Changes +## `v26.6.0` -- Updating `profileBuilder list` to accept an `input` flag instead of reading from `stdin`. -- Simplifying CI to have less chatter, be faster, and have no special cases. +## New Packages -## `v14.0.1` +| Package Name | API Version | +| -----------: | :---------: | +| prediction | v3.0 | -### Changes +### Updated Packages -- Removed the ./services/search/2016-09-01/search package, it was never intended to be included and doesn't work. +| Package Name | API Version | +| -----------: | :---------: | +| marketplaceordering | 2015-06-01 | +| media | 2018-07-01 | -## `v14.0.0` +### Breaking Changes - Preview -### Breaking Changes +| Package Name | API Version | +| -----------: | :---------: | +| netapp | 2017-08-15 | -- Removed the ./arm, ./datalake-store and ./dataplane directories. You can find the same packages under ./services -- The management package was moved to ./services/classic/management -- Renamed package ./services/redis/mgmt/2017-10-01/cache to ./services/redis/mgmt/2017-10-01/redis +## `v26.5.0` + +### New Packages -### Changes +| Package Name | API Version | +| -----------: | :---------: | +| anomalydetector | v1.0 | +| containerservice | 2019-02-01 | +| storage | 2018-11-01 | -- Removed the "-beta" suffix. -- Added various new services. -- Added ./version package for centralized SDK versioning. +### Updated Packages -## `v12.5.0-beta` +| Package Name | API Version | +| -----------: | :---------: | +| network | 2018-12-01 | + +## `v26.4.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| insights | 2019-03-01 | + +## `v26.3.1` + +Remove committed vendored content. + +## `v26.3.0` + +| Package Name | API Version | +| -----------: | :---------: | +| eventgrid | 2019-02-01-preview | -### Changes +### Updated Packages -- Added Container Instance API Versions 2017-10-01-preview, 2017-12-01-preview, and 2018-02-01-preview. +| Package Name | API Version | +| -----------: | :---------: | +| marketplaceordering | 2015-06-01 | -## `v12.4.0-beta` +## `v26.2.0` -### Changes +### New Packages -- Added API version 2017-12-01 for the compute package. +| Package Name | API Version | +| -----------: | :---------: | +| mariadb | 2018-06-01 | +| netapp | 2017-08-15 | +| security | v2.0 | +| translatortext | v3.0 | -## `v12.3.0-beta` +### Updated Packages -### Changes +| Package Name | API Version | +| -----------: | :---------: | +| sql | 2015-05-01-preview
2017-03-01-preview | -- Updated event grid dataplane with latest swagger changes. -- Added latest event grid management plane API version. +### Moved Packages -## `v12.2.0-beta` +| Package Name | API Version | +| -----------: | :---------: | +| security | 2017-08-01-preview -> v1.0 | -### Changes +## `v26.1.0` -#### Storage +### New Packages -- Add support for creating a SAS client from an endpoint and SAS token. -- Fixed bug that wasn't appending SAS token to URI query parameters in all cases. +| Package Name | API Version | +| -----------: | :---------: | +| mixedreality | 2019-02-28 | +| trafficmanager | 2018-04-01 | -## `v12.1.1-beta` +### Updated Packages -### Changes +| Package Name | API Version | +| -----------: | :---------: | +| mysql | 2017-12-01 | +| postgresql | 2017-12-01 | +| search | 2015-08-19 | -- Removing (at least temporarily) calls to `uuid.NewV1()` due to breaking changes (see https://github.com/Azure/azure-sdk-for-go/issues/947 for more info). -- Deleted glide files as we are now using dep. +## `v26.0.0` -## `v12.1.0-beta` +### New Packages -### New Services +| Package Name | API Version | +| -----------: | :---------: | +| anomalyfinder | v2.0 | +| blueprint | 2018-11-01-preview | +| costmanagement | 2019-01-01 | +| devspaces | 2019-01-01-preview | +| edgegateway | 2019-03-01 | +| network | 2018-12-01 | +| privatedns | 2018-09-01 | -#### Data plane -- Cognitive Services Computer Vision -- Cognitive Services Content Moderator -- Cognitive Services LUIS +### Updated Packages -## `v12.0.0-beta` - -### Changes -- Long Running Operations now return a `Future` type. Go routines and return via channel features have been removed. -- Added support for services that make use of polymorphic types. -- Operations now make use of the [Context Pattern](https://blog.golang.org/context). -- Container Services has been moved out of Compute folder in its own folder. -- Azure Go SDK is now using [dep](https://github.com/golang/dep) for vendoring. -- The *arm* and *dataplane* folders have been deprecated. Use the *profiles* and the *services* folders instead. -- Group clients have been renamed to a a service specific name. - -### New Services - -#### Management Plane -- Azure Container Service for Kubernetes (AKS) -- Azure MSI Service - -#### Data plane -- Cognitive Services Custom Search -- Cognitive Services Entity Search -- Cognitive Services Image Search -- Cognitive Services News Search -- Cognitive Services Video Search -- Cognitive Services Web Search -- Cognitive Services Spell Check -- MongoDb for CosmosDb - - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: 515f358fe1e521441aec5d63d62b5f0affcc8ea9 -- [AutoRest Go Generator](https://github.com/Azure/autorest.go) commit: c759908a0d8726eb755afd93353c58e072c345af - -## `v11.3.0-beta` - -### ARM - -- Added storage API version 2017-10-01. - -## `v11.2.2-beta` - -### Bug Fixes - - Regenerating `latest` and `preview` profiles after deleting falsely included apimanagement. - -## `v11.2.1-beta` - -### Bug Fixes - - Commenting out ignore rule that false-positived on the graphrbac package. - -## `v11.2.0-beta` - -### Repository Structure - - Adding support for Multi-API Version paradigm in `services` directory. - - Adding support for Azure Profile in `profiles` directory. - -### Storage - - Added operations for getting and setting container metadata. - - Fixed unmarshaling bug on list containers operation.' - -### Generated code notes - -- Services directory generated from [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: 274c99f7bd93d8b98048e31b74a34333cecded74 -- [AutoRest Go Generator](https://github.com/Azure/autorest.go) version: 2.0.41 - -## `v11.1.1-beta` - -### ARM - -- Registers resource providers if necessary. -- Requires go-autorest v9.1.0 - -### Generated code notes - -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commits: - - All services except trafficmanager and containerregistry: 0c2a12b50d8598f68d6715b507f7dd53e163407e - - trafficmanager and containerregistry: c97a18ed775029207715b09c80761334724740b9 -- [AutoRest Go Generator](https://github.com/Azure/autorest.go) version: 2.0.36 - -### Storage - -- Fixed bug in which blob types were unmarshaed incorrectly. - -## `v11.1.0-beta` - -### ARM - -- trafficmanager and containerregistry SDKs now reflect the services faithfully -- trafficmanager also has a new operation group: user metrics. - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: c97a18ed775029207715b09c80761334724740b9 -- [AutoRest Go Generator](https://github.com/Azure/autorest.go) commit: 5d984152f2e9cff6878ea5060bed7e8d8a2ae1cc - -## `v11.0.0-beta` - -### ARM - -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| arm/analysisservices | 2017-08-01-beta | update | -| arm/batch | 2017-05-01 | update | -| arm/cdn | 2017-04-02 | update | -| arm/cognitiveservices | 2017-04-18 | update | -| arm/compute | multiple | update | -| arm/containerregistry | 2017-10-01 | update | -| arm/customerinsights | 2017-04-26 | update | -| arm/eventgrid | 2017-09-15-preview | update | -| arm/eventhub | 2017-04-01 | update | -| arm/graphrbac | 1.6 | update | -| arm/iothub | 2017-07-01 | update | -| arm/keyvault | 2016-10-01 | update | -| arm/marketplaceordering | 2015-06-01 | new | -| arm/opertionalinsights | multiple | update | -| arm/operationsmanagement | 2015-11-01-preview | new | -| arm/recoveryservices | multiple | update | -| arm/recoveryservicesbackup | multiple | update | -| arm/redis | 2017-02-01 | update | -| arm/relay | 2017-04-01 | update | -| arm/resourcehealth | 017-07-01 | update | -| arm/resources/resources | 2017-05-10 | update | -| arm/servicebus | 2017-04-01 | update | -| arm/storage | 2017-06-01 | update | -| arm/streamanalytics | 2016-03-01 | update | -| arm/trafficmanager | 2017-09-01-preview | update | -| arm/visualstudio | 2014-04-01-preview | update | - -### Data plane - -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| dataplane/cognitiveservices/face | 1.0 | new | -| dataplane/cognitiveservices/textanalytics | v2.0 | new | - -### Storage - -- Support for queue SAS. -- Refactored GetSASURI blob operation to be more complete. -- Added a SAS client for some operations (`container.Exists()`, and `container.ListBlobs()`) - -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: 0c2a12b50d8598f68d6715b507f7dd53e163407e -- [AutoRest Go Generator](https://github.com/Azure/autorest.go) commit: 678110f012c7cde6528a1e61d125bdc7ea636b7f - -## `v10.3.1-beta` -- Added Apache notice file. - -### ARM -- Fixed package name on some `version.go` files. - -### Storage -- Fixed bug related to SAS URI generation and storage emulator support. - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: ad55af74f3f0e2b390a4306532528168ba742fef -- [AutoRest Go extension](https://github.com/Azure/autorest.go) commit: 28a531c59c82cf67bc90c87095c1d34a936461b4 - -## `v10.3.0-beta` -### ARM - -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| arm/containerinstance | 2017-08-01-preview | new | -| arm/eventgrid | 2017-06-15-preview | new | - -### ASM -- Marked as in mainteinance mode. -- Added Go 1.7 build tags. - -### Storage -- Support for Go 1.7 and Go 1.6 (except table batch operation tests). - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: ad55af74f3f0e2b390a4306532528168ba742fef -- [AutoRest](https://github.com/Azure/autorest) commit: cfb296f153f948f85afab637f7212fcfdc4a8bbb - -## `v10.2.1-beta` -- Fixes polymorphic structs in `mysql` and `postgresql` packages. - -## `v10.2.0-beta` -### ARM - -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| arm/cosmos-db | 2015-04-08 | new | -| arm/mysql | 2017-04-30-preview | new | -| arm/postgresql | 2017-04-30-preview | new | - -### Storage -- Bug fixes. - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: 485ded7560c6309efb2f795ec6e46b7436dc6fdb -- [AutoRest](https://github.com/Azure/autorest) commit: c180952b850e677a8624655abeaded307d95cae3 - -## `v10.1.0-beta` -### ARM - -| arm/recoveryservicessiterecovery | 2016-08-10 | new | -| arm/managedapplications | 2016-09-01-preview | new | -| arm/storsimple8000series | 2017-06-01 | new | -| arm/streamanalytics | multiple | new | - -### Storage -- Bug fixes. - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: a2cdf005407b81edb161c1f7b5c49b5ce8e7f041 -- [AutoRest](https://github.com/Azure/autorest) commit: 8e9c2d3704a04913a175ab76972b7d9597c77687 - ------ -## `v10.0.0-beta` -### ARM -In addition to the tabulated changes below, each package had the following updates: -- Long running operations now run inside a goroutine and return channels for the response and the errors. -- Some functions changed from returning `autorest.Response` to return the already unmarshaled struct. -- Uses go-autorest v8.0.0. - -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| arm/advisor | 2017-04-19 | new | -| arm/analysisservices | 2016-05-16 | refactor | -| arm/apimanagement | 2016-10-10 | update to latest swagger & refactor | -| arm/appinsights | 2015-05-01 | new | -| arm/automation | 2015-10-31 | new | -| arm/billing | 2017-04-24-preview | update to latest swagger & refactor | -| arm/cdn | 2016-10-02 | refactor | -| arm/commerce | 2015-06-01-preview | refactor | -| arm/compute | 2016-04-30-preview | refactor | -| arm/consumption | 2017-04-24-preview | new | -| arm/containerregistry | 2017-03-01 | update to latest swagger & refactor | -| arm/containerservice | 2017-01-31 | update to latest swagger & refactor | -| arm/customer-insights | 2017-01-01 | refactor | -| arm/datalake-analytics/account | 2016-11-01 | refactor | -| arm/datalake-store/account | 2016-11-01 | refactor | -| arm/devtestlabs | 2016-05-15 | refactor | -| arm/disk | 2016-04-30-preview | refactor | -| arm/dns | 2016-04-01 | refactor | -| arm/documentdb | 2015-04-08 | refactor | -| arm/eventhub | 2015-08-01 | refactor | -| arm/graphrbac | 1.6 | refactor | -| arm/hdinsight | 2015-03-01-preview | new | -| arm/insights | multiple | new | -| arm/intune | 2015-01-14-preview | refactor | -| arm/iothub | 2016-02-03 | refactor | -| arm/machinelearning/commitmentplans | 2016-05-01-preview | refactor | -| arm/machinelearning/webservices | 2017-01-01 | update to latest swagger & refactor | -| arm/monitor | multiple | new | -| arm/network | 2017-03-01 | update to latest swagger & refactor | -| arm/notificationhubs | 2017-04-01 | update to latest swagger & refactor | -| arm/operationalinsights | 2015-11-01-preview | update to latest swagger & refactor | -| arm/powerbiembedded | 2016-01-29 | refactor | -| arm/recoveryservices | 2016-12-01 | refactor | -| arm/recoveryservicesbackup | 2016-12-01 | new | -| arm/redis | 2016-04-01 | refactor | -| arm/relay | 2016-07-01 | new | -| arm/resourcehealth | 2015-01-01 | new | -| arm/resources/features | 2015-12-01 | refactor | -| arm/resources/links | 2016-09-01 | refactor | -| arm/resources/resources | 2016-09-01 | refactor | -| arm/resources/subscriptions | 2016-06-01 | refactor | -| arm/scheduler | 2016-03-01 | refactor | -| arm/servermanagement | 2016-07-01-preview | refactor | -| arm/servicebus | 2015-08-01 | refactor | -| arm/servicefabric | 2016-09-01 | new | -| arm/service-map | 2015-11-01-preview | refactor | -| arm/sql | multiple | update to latest swagger & refactor | -| arm/storage | 2016-12-01 | update to latest swagger & refactor | -| arm/storageimportexport | 2016-11-01 | refactor | -| arm/web | multiple | refactor | - -### Data plane -| api | version | note | -|:------------------------------------|:-------------------|:------------------------------------| -| dataplane/keyvault | 2016-10-01 | refactor | - -### Storage -Storage has returned to this repo. -It has also been refactored: -- Blobs, containers, tables, etc are now method receivers. These structs are the ones being - updated with each operation. -- When creating a client, the SDK checks if the storage account provided is valid. -- Added retry logic. It provides the flexibility for user to provide their own retry logic. -- Added operations: - - Get table - - Get entity - - Get and set queue ACL - - Table batch - - Page blob incremental copy -- All operations that previously had `extraHeaders` as parameter now recieve a struct with well - defined possible headers and other options. Some functions are easier to use. -- Storage tests now use HTTP recordings. - -### Generated code notes -- [Azure REST API specs](https://github.com/Azure/azure-rest-api-specs) commit: 519980465d9c195622d466dc4601b1999a448ed5 -- [AutoRest](https://github.com/Azure/autorest) commit: ced950d64e39735b84d41876a56b54b27c227dc7 - -## `v9.0.0-beta` -### ARM -In addition to the tabulated changes below, each package had the following updates: - - API Version is now associated with individual methods, instead of the client. This was done to - support composite swaggers, which logically may contain more than one API Version. - - Version numbers are now calculated in the generator instead of at runtime. This keeps us from - adding new allocations, while removing the race-conditions that were added. - -| api | version | note | -|:------------------------------------|:-------------------|:-----------------------------------| -| arm/analysisservices | 2016-05-16 | update to latest swagger | -| arm/authorization | 2015-07-01 | refactoring | -| arm/batch | 2017-01-01 | update to latest swagger &refactor | -| arm/cdn | 2016-10-02 | update to latest swagger | -| arm/compute | 2016-04-30-preview | update to latest swagger | -| arm/dns | 2016-04-01 | update to latest swagger &refactor | -| arm/eventhub | 2015-08-01 | refactoring | -| arm/logic | 2016-06-01 | update to latest swagger &refactor | -| arm/notificationshub | 2016-03-01 | update to latest swagger &refactor | -| arm/redis | 2016-04-01 | update to latest swagger &refactor | -| arm/resources/resources | 2016-09-01 | update to latest swagger | -| arm/servicebus | 2015-08-01 | update to latest swagger | -| arm/sql | 2014-04-01 | update to latest swagger | -| arm/web | multiple | generating from composite | -| datalake-analytics/account | 2016-11-01 | update to latest swagger | -| datalake-store/filesystem | 2016-11-01 | update to latest swagger | - -### Storage -Storage has been moved to its own repository which can be found here: -https://github.com/Azure/azure-storage-go - -For backwards compatibility, a submodule has been added to this repo. However, consuming storage -via this repository is deprecated and may be deleted in future versions. - -## `v8.1.0-beta` -### ARM -| api | version | note | -|:------------------------------------|:-------------------|:-----------------------------------| -| arm/apimanagement | 2016-07-07 | new | -| arm/apideployment | 2016-07-07 | new | -| arm/billing | 2017-02-27-preview | new | -| arm/compute | 2016-04-30-preview | update to latest swagger | -| arm/containerservice | 2017-01-31 | update to latest swagger | -| arm/customer-insights | 2017-01-01 | new | -| arm/graphrbac | 1.6 | new | -| arm/networkwatcher | 2016-12-01 | new | -| arm/operationalinsights | 2015-11-01-preview | new | -| arm/service-map | 2015-11-01-preview | new | -| arm/storageimportexport | 2016-11-01 | new | - -### Data plane -| api | version | note | -|:------------------------------------|:-------------------|:-----------------------------------| -| dataplane/keyvault | 2016-10-01 | new | - -- Uses go-autorest v7.3.0 - - -## `v8.0.0-beta` -### ARM -- In addition to the tablulated changes below, all updated packages received performance - improvements to their Version() method. -- Some validation that was taking place in the runtime was erroneously blocking calls. - all packages have been updated to take that bug fix. - -| api | version | note | -|:------------------------------------|:-------------------|:-----------------------------------| -| arm/analysisservices | 2016-05-16 | update to latest swagger | -| arm/cdn | 2016-10-02 | update to latest swagger | -| arm/cognitiveservices | 2016-02-01-preview | update to latest swagger | -| arm/compute | 2016-03-30 | update to latest swagger, refactor | -| arm/containerregistry | 2016-06-27-preview | update to latest swagger | -| arm/containerservice | 2016-09-30 | update to latest swagger | -| arm/datalake-analytics | 2016-11-01 | update to latest swagger | -| arm/datalake-store | 2016-11-01 | update to latest swagger | -| arm/disk | 2016-04-30-preview | new | -| arm/documentdb | 2015-04-08 | update to latest swagger | -| arm/iothub | 2016-02-03 | update to latest swagger | -| arm/keyvault | 2015-06-01 | update to latest swagger | -| arm/logic | 2016-06-01 | update to latest swagger | -| arm/machinelearning | 2016-05-01-preview | update to latest swagger | -| arm/mobileengagement | 2014-12-01 | update to latest swagger, refactor | -| arm/redis | 2016-04-01 | update to latest swagger | -| arm/resources/locks | 2016-09-01 | refactor | -| arm/resources/policy | 2016-12-01 | previous version was deleted | -| arm/resources/resources | 2016-09-01 | update to latest swagger, refactor | -| arm/scheduler | 2016-03-01 | refactor | -| arm/search | 2015-08-19 | refactor | -| arm/web | 2015-08-01 | refactor | - -## `v7.0.0-beta` - -| api | version | note | -|:------------------------------------|:-------------------|:-----------------------------------| -| arm/analysisservices | 2016-05-16 | new | -| arm/cdn | 2016-10-02 | update to latest swagger | -| arm/commerce | 2015-06-01-preview | new | -| arm/containerservice | 2016-09-30 | update to latest swagger | -| arm/containerregistry | 2016-06-27-preview | new | -| arm/datalake-analytics/account | 2016-11-01 | update to latest swagger | -| arm/datalake-store/account | 2016-11-01 | update to latest swagger | -| arm/datalake-store/filesystem | 2016-11-01 | update to latest swagger | -| arm/documentdb | 2015-04-08 | new | -| arm/machinelearning/commitmentplans | 2016-05-01-preview | new | -| arm/recoveryservices | 2016-06-01 | new | -| arm/resources/subscriptions | 2016-06-01 | new | -| arm/search | 2015-08-19 | update to latest swagger | -| arm/sql | 2014-04-01 | previous version was deleted | - -### Storage -- Can now update messages in storage queues. -- Added support for blob snapshots and aborting blob copy operations. -- Added support for getting and setting ACLs on containers. -- Added various APIs for file and directory manipulation. - -### Support for the following swagger extensions was added to the Go generator which affected codegen. -- x-ms-client-flatten -- x-ms-paramater-location - -## `v6.0.0-beta` - -| api | version | note | -|:-------------------------------|:-------------------|:-----------------------------------| -| arm/authorization | no change | code refactoring | -| arm/batch | no change | code refactoring | -| arm/compute | no change | code refactoring | -| arm/containerservice | 2016-03-30 | return | -| arm/datalake-analytics/account | 2015-10-01-preview | new | -| arm/datalake-store/filesystem | no change | moved to datalake-store/filesystem | -| arm/eventhub | no change | code refactoring | -| arm/intune | no change | code refactoring | -| arm/iothub | no change | code refactoring | -| arm/keyvault | no change | code refactoring | -| arm/mediaservices | no change | code refactoring | -| arm/network | no change | code refactoring | -| arm/notificationhubs | no change | code refactoring | -| arm/redis | no change | code refactoring | -| arm/resources/resources | no change | code refactoring | -| arm/resources/links | 2016-09-01 | new | -| arm/resources/locks | 2016-09-01 | updated | -| arm/resources/policy | no change | code refactoring | -| arm/resources/resources | 2016-09-01 | updated | -| arm/servermanagement | 2016-07-01-preview | updated | -| arm/web | no change | code refactoring | - -- storage: Added blob lease functionality and tests - -## `v5.0.0-beta` - -| api | version | note | -|:------------------------------|:--------------------|:-----------------| -| arm/network | 2016-09-01 | updated | -| arm/servermanagement | 2015-07-01-preview | new | -| arm/eventhub | 2015-08-01 | new | -| arm/containerservice | -- | removed | -| arm/resources/subscriptions | no change | code refactoring | -| arm/resources/features | no change | code refactoring | -| arm/resources/resources | no change | code refactoring | -| arm/datalake-store/accounts | no change | code refactoring | -| arm/datalake-store/filesystem | no change | code refactoring | -| arm/notificationhubs | no change | code refactoring | -| arm/redis | no change | code refactoring | - -- storage: Add more file storage share operations. -- azure-rest-api-specs/commit/b8cdc2c50a0872fc0039f20c2b6b33aa0c2af4bf -- Uses go-autorest v7.2.1 - -## `v4.0.0-beta` - -- arm/logic: breaking change in package logic. -- arm: parameter validation code added in all arm packages. -- Uses go-autorest v7.2.0. - - -## `v3.2.0-beta` - -| api | version | note | -|:----------------------------|:--------------------|:----------| -| arm/mediaservices | 2015-10-01 | new | -| arm/keyvault | 2015-06-01 | new | -| arm/iothub | 2016-02-03 | new | -| arm/datalake-store | 2015-12-01 | new | -| arm/network | 2016-06-01 | updated | -| arm/resources/resources | 2016-07-01 | updated | -| arm/resources/policy | 2016-04-01 | updated | -| arm/servicebus | 2015-08-01 | updated | - -- arm: uses go-autorest version v7.1.0. -- storage: fix for operating on blobs names containing special characters. -- storage: add SetBlobProperties(), update BlobProperties response fields. -- storage: make storage client work correctly with read-only secondary account. -- storage: add Azure Storage Emulator support. - - -## `v3.1.0-beta` - -- Added a new arm/compute/containerservice (2016-03-30) package -- Reintroduced NewxxClientWithBaseURI method. -- Uses go-autorest version - v7.0.7. - - -## `v3.0.0-beta` - -This release brings the Go SDK ARM packages up-to-date with Azure ARM Swagger files for most -services. Since the underlying [Swagger files](https://github.com/Azure/azure-rest-api-specs) -continue to change substantially, the ARM packages are still in *beta* status. - -The ARM packages now align with the following API versions (*highlighted* packages are new or -updated in this release): - -| api | version | note | -|:----------------------------|:--------------------|:----------| -| arm/authorization | 2015-07-01 | no change | -| arm/intune | 2015-01-14-preview | no change | -| arm/notificationhubs | 2014-09-01 | no change | -| arm/resources/features | 2015-12-01 | no change | -| arm/resources/subscriptions | 2015-11-01 | no change | -| arm/web | 2015-08-01 | no change | -| arm/cdn | 2016-04-02 | updated | -| arm/compute | 2016-03-30 | updated | -| arm/dns | 2016-04-01 | updated | -| arm/logic | 2015-08-01-preview | updated | -| arm/network | 2016-03-30 | updated | -| arm/redis | 2016-04-01 | updated | -| arm/resources/resources | 2016-02-01 | updated | -| arm/resources/policy | 2015-10-01-preview | updated | -| arm/resources/locks | 2015-01-01 | updated (resources/authorization earlier)| -| arm/scheduler | 2016-03-01 | updated | -| arm/storage | 2016-01-01 | updated | -| arm/search | 2015-02-28 | updated | -| arm/batch | 2015-12-01 | new | -| arm/cognitiveservices | 2016-02-01-preview | new | -| arm/devtestlabs | 2016-05-15 | new | -| arm/machinelearning | 2016-05-01-preview | new | -| arm/powerbiembedded | 2016-01-29 | new | -| arm/mobileengagement | 2014-12-01 | new | -| arm/servicebus | 2014-09-01 | new | -| arm/sql | 2015-05-01 | new | -| arm/trafficmanager | 2015-11-01 | new | - - -Below are some design changes. -- Removed Api version from method arguments. -- Removed New...ClientWithBaseURI() method in all clients. BaseURI value is set in client.go. -- Uses go-autorest version v7.0.6. - - -## `v2.2.0-beta` - -- Uses go-autorest version v7.0.5. -- Update version of pacakges "jwt-go" and "crypto" in glide.lock. - - -## `v2.1.1-beta` - -- arm: Better error messages for long running operation failures (Uses go-autorest version v7.0.4). - - -## `v2.1.0-beta` - -- arm: Uses go-autorest v7.0.3 (polling related updates). -- arm: Cancel channel argument added in long-running calls. -- storage: Allow caller to provide headers for DeleteBlob methods. -- storage: Enables connection sharing with http keepalive. -- storage: Add BlobPrefixes and Delimiter to BlobListResponse - - -## `v2.0.0-beta` - -- Uses go-autorest v6.0.0 (Polling and Asynchronous requests related changes). - - -## `v0.5.0-beta` - -Updated following packages to new API versions: -- arm/resources/features 2015-12-01 -- arm/resources/resources 2015-11-01 -- arm/resources/subscriptions 2015-11-01 - - -### Changes - - - SDK now uses go-autorest v3.0.0. - - - -## `v0.4.0-beta` - -This release brings the Go SDK ARM packages up-to-date with Azure ARM Swagger files for most -services. Since the underlying [Swagger files](https://github.com/Azure/azure-rest-api-specs) -continue to change substantially, the ARM packages are still in *beta* status. - -The ARM packages now align with the following API versions (*highlighted* packages are new or -updated in this release): - -- *arm/authorization 2015-07-01* -- *arm/cdn 2015-06-01* -- arm/compute 2015-06-15 -- arm/dns 2015-05-04-preview -- *arm/intune 2015-01-14-preview* -- arm/logic 2015-02-01-preview -- *arm/network 2015-06-15* -- *arm/notificationhubs 2014-09-01* -- arm/redis 2015-08-01 -- *arm/resources/authorization 2015-01-01* -- *arm/resources/features 2014-08-01-preview* -- *arm/resources/resources 2014-04-01-preview* -- *arm/resources/subscriptions 2014-04-01-preview* -- *arm/scheduler 2016-01-01* -- arm/storage 2015-06-15 -- arm/web 2015-08-01 - -### Changes - -- Moved the arm/authorization, arm/features, arm/resources, and arm/subscriptions packages under a new, resources, package (to reflect the corresponding Swagger structure) -- Added a new arm/authoriation (2015-07-01) package -- Added a new arm/cdn (2015-06-01) package -- Added a new arm/intune (2015-01-14-preview) package -- Udated arm/network (2015-06-01) -- Added a new arm/notificationhubs (2014-09-01) package -- Updated arm/scheduler (2016-01-01) package - - ------ - -## `v0.3.0-beta` - -- Corrected unintentional struct field renaming and client renaming in v0.2.0-beta - ------ - -## `v0.2.0-beta` - -- Added support for DNS, Redis, and Web site services -- Updated Storage service to API version 2015-06-15 -- Updated Network to include routing table support -- Address https://github.com/Azure/azure-sdk-for-go/issues/232 -- Address https://github.com/Azure/azure-sdk-for-go/issues/231 -- Address https://github.com/Azure/azure-sdk-for-go/issues/230 -- Address https://github.com/Azure/azure-sdk-for-go/issues/224 -- Address https://github.com/Azure/azure-sdk-for-go/issues/184 -- Address https://github.com/Azure/azure-sdk-for-go/issues/183 - ------- - -## `v0.1.1-beta` - -- Improves the UserAgent string to disambiguate arm packages from others in the SDK -- Improves setting the http.Response into generated results (reduces likelihood of a nil reference) -- Adds gofmt, golint, and govet to Travis CI for the arm packages - -##### Fixed Issues - -- https://github.com/Azure/azure-sdk-for-go/issues/196 -- https://github.com/Azure/azure-sdk-for-go/issues/213 - ------- - -## v0.1.0-beta - -This release addresses the issues raised against the alpha release and adds more features. Most -notably, to address the challenges of encoding JSON -(see the [comments](https://github.com/Azure/go-autorest#handling-empty-values) in the -[go-autorest](https://github.com/Azure/go-autorest) package) by using pointers for *all* structure -fields (with the exception of enumerations). The -[go-autorest/autorest/to](https://github.com/Azure/go-autorest/tree/master/autorest/to) package -provides helpers to convert to / from pointers. The examples demonstrate their usage. - -Additionally, the packages now align with Go coding standards and pass both `golint` and `govet`. -Accomplishing this required renaming various fields and parameters (such as changing Url to URL). - -##### Changes - -- Changed request / response structures to use pointer fields. -- Changed methods to return `error` instead of `autorest.Error`. -- Re-divided methods to ease asynchronous requests. -- Added paged results support. -- Added a UserAgent string. -- Added changes necessary to pass golint and govet. -- Updated README.md with details on asynchronous requests and paging. -- Saved package dependencies through Godep (for the entire SDK). - -##### Fixed Issues: - -- https://github.com/Azure/azure-sdk-for-go/issues/205 -- https://github.com/Azure/azure-sdk-for-go/issues/206 -- https://github.com/Azure/azure-sdk-for-go/issues/211 -- https://github.com/Azure/azure-sdk-for-go/issues/212 - ------ - -## v0.1.0-alpha - -This release introduces the Azure Resource Manager packages generated from the corresponding -[Swagger API](http://swagger.io) [definitions](https://github.com/Azure/azure-rest-api-specs). \ No newline at end of file +| Package Name | API Version | +| commitmentplans | 2016-05-01-preview | +| computervision | v2.0 | +| consumption | 2018-10-01 | +| hanaonazure | 2017-11-03-preview | +| operationalinsights | 2015-03-20 | +| webapi | web | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| containerservice | 2018-03-31
2018-08-01-preview
2018-09-30-preview | +| costmanagement | 2018-08-01-preview | +| datafactory | 2018-06-01 | +| eventgrid | 2018-01-01 | +| face | v1.0 | +| kusto | 2019-01-21 | +| policyinsights | 2018-07-01-preview | +| security | 2017-08-01-preview | +| securityinsight | 2017-08-01-preview | +| sql | 2015-05-01-preview
2017-03-01-preview | +| storagedatalake | 2018-11-09 | +| textanalytics | v2.1 | +| web | 2018-02-01 | + +### Removed Packages + +| Package Name | API Version | +| -----------: | :---------: | +| blueprint | 2017-11-11-preview | +| edgegateway | 2018-07-01 | + +## `v25.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| consumption | 2019-01-01 | +| kusto | 2019-01-21 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| authorization | 2015-07-01 | +| backup | 2017-07-01 | +| compute | 2018-10-01 | +| eventgrid | 2018-01-01 | +| eventhub | 2017-04-01 | +| sql | 2017-03-01-preview | + +## `v25.0.0` + +NOTE: Go 1.8 has been removed from CI due to a transitive dependency no longer supporting it. + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| devices | 2018-12-01-preview | +| insights | 2018-11-01-preview | +| securityinsight | 2017-08-01-preview | +| storagedatalake | 2018-11-09 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| cognitiveservices | 2017-04-18 | +| containerregistry | 2018-09-01 | +| eventgrid | 2018-01-01 | +| hdinsight | 2015-03-01-preview
2018-06-01-preview | +| network | 2018-11-01 | +| runtime | luis | +| sql | 2015-05-01-preview
2017-03-01-preview
2017-10-01-preview | +| web | 2018-02-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| adhybridhealthservice | 2014-01-01 | +| backup | 2016-12-01
2017-07-01 | +| blueprint | 2017-11-11-preview | +| containerservice | 2018-03-31
2018-08-01-preview
2018-09-30-preview | +| datafactory | 2017-09-01-preview
2018-06-01 | +| face | v1.0 | +| hanaonazure | 2017-11-03-preview | +| insights | 2017-05-01-preview | +| logic | 2018-07-01-preview | +| security | 2017-08-01-preview | +| storage | 2015-05-01-preview
2015-06-15
2016-01-01
2016-05-01
2016-12-01
2017-06-01
2017-10-01
2018-02-01
2018-03-01-preview
2018-07-01 | +| virtualmachine | management | + +### Removed Packages + +NOTE: Some removed packages are preview packages that were incorrectly placed in the stable location. The copies under `preview` still exist. + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2018-01-01 | +| datafactory | 2017-09-01-preview | +| dns | 2018-03-01-preview | +| insights | 2017-09-01 | +| iothub | 2017-08-21-preview | +| managedapplications | 2016-09-01-preview | +| managementpartner | 2018-02-01 | +| policy | 2015-10-01-preview
2017-06-01-preview | +| servicefabric | 1.0.0
5.6
6.0
6.1 | +| storagedatalake | 2018-06-17
2018-11-09 | + +## `v24.1.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| edgegateway | 2018-07-01 | +| network | 2018-11-01 | +| storagesync | 2018-10-01 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2018-06-01-preview | +| automation | 2017-05-15-preview
2018-01-15-preview
2018-06-30-preview | +| classic | management | +| containerservice | 2018-03-31
2018-08-01-preview
2018-09-30-preview | +| hanaonazure | 2017-11-03-preview | +| maps | 2018-05-01 | + +## `v24.0.0` + +### New Packages + +| Package Name | API Version | +| -----------: | :---------: | +| batch | 2018-12-01
2018-12-01.8.0 | +| devices | 2018-12-01-preview | +| eventgrid | 2019-01-01 | +| storagedatalake | 2018-06-17
2018-11-09 | + +### Updated Packages + +| Package Name | API Version | +| -----------: | :---------: | +| apimanagement | 2018-01-01
2018-06-01-preview | +| containerinstance | 2018-10-01 | +| containerregistry | 2017-10-01
2018-02-01
2018-09-01 | +| containerservice | 2018-08-01-preview
2018-09-30-preview | +| costmanagement | 2018-08-01-preview | +| datafactory | 2018-06-01 | +| eventhub | 2018-01-01-preview | +| hanaonazure | 2017-11-03-preview | +| hdinsight | 2018-11-01-preview | +| network | 2018-10-01 | +| resourcehealth | 2015-01-01
2017-07-01 | +| sql | 2017-03-01-preview | +| storagesync | 2018-10-01 | + +### BreakingChanges + +| Package Name | API Version | +| -----------: | :---------: | +| authoring | luis | +| cognitiveservices | 2017-04-18 | +| computervision | v2.0 | +| datamigration | 2018-04-19
2018-07-15-preview | +| labservices | 2018-10-15 | +| logic | 2018-07-01-preview | +| media | 2018-07-01 | +| siterecovery | 2018-01-10 | +| sqlvirtualmachine | 2017-03-01-preview | +| workloadmonitor | 2018-08-31-preview | diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 000000000000..0ec91828f850 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,12 @@ +/documentation/ @joshgav +/profiles/ @jhendrixMSFT @vladbarosan +/services/ @jhendrixMSFT @vladbarosan +/storage/ @jhendrixMSFT @vladbarosan +/tools/apidiff/ @jhendrixMSFT @vladbarosan +/tools/generator/ @jhendrixMSFT @vladbarosan +/tools/indexer/ @jhendrixMSFT @vladbarosan +/tools/profileBuilder/ @jhendrixMSFT @vladbarosan +/version/ @jhendrixMSFT @vladbarosan +.travis.yml @jhendrixMSFT @vladbarosan +doc.go @joshgav +findTestedPackages.sh @jhendrixMSFT @vladbarosan diff --git a/azure-pipelines.yml b/azure-pipelines.yml index 9dc7b82e01ab..a07f78593af6 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -1,3 +1,13 @@ +trigger: + paths: + exclude: + - sdk/ + +pr: + paths: + exclude: + - sdk/ + jobs: - job: Build_Test strategy: @@ -18,6 +28,7 @@ jobs: GOPATH: '$(system.defaultWorkingDirectory)/work' sdkPath: '$(GOPATH)/src/github.com/$(build.repository.name)' IGNORE_BREAKING_CHANGES: true + go.list.filter: '| grep -v vendor' steps: - script: | @@ -37,13 +48,13 @@ jobs: go get -u golang.org/x/lint/golint workingDirectory: '$(sdkPath)' displayName: 'Install Dependencies' - - script: go vet $(go list ./... | grep -v vendor) + - script: go vet -v $(go list ./... $(go.list.filter)) workingDirectory: '$(sdkPath)' displayName: 'Vet' - - script: go build -v $(go list ./... | grep -v vendor) + - script: go build -v $(go list ./... $(go.list.filter)) workingDirectory: '$(sdkPath)' displayName: 'Build' - - script: go test $(dirname $(find . -path ./vendor -prune -o -name '*_test.go' -print) | sort -u) + - script: go test $(dirname $(find . -path ./vendor -prune -o -path ./sdk -prune -o -name '*_test.go' -print) | sort -u) workingDirectory: '$(sdkPath)' displayName: 'Run Tests' - script: go run ./tools/apidiff/main.go packages ./services FETCH_HEAD~1 FETCH_HEAD --copyrepo --breakingchanges || $IGNORE_BREAKING_CHANGES diff --git a/doc.go b/doc.go new file mode 100644 index 000000000000..af79e21481b3 --- /dev/null +++ b/doc.go @@ -0,0 +1,26 @@ +/* +Package sdk provides Go packages for managing and using Azure services. + +GitHub repo: https://github.com/Azure/azure-sdk-for-go + +Official documentation: https://docs.microsoft.com/azure/go + +API reference: https://godoc.org/github.com/Azure/azure-sdk-for-go + +Samples: https://github.com/Azure-Samples/azure-sdk-for-go-samples +*/ +package sdk + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. diff --git a/eng/common/README.md b/eng/common/README.md new file mode 100644 index 000000000000..7e9e197fc466 --- /dev/null +++ b/eng/common/README.md @@ -0,0 +1,12 @@ +# Common Engineering System + +The `eng/common` directory contains engineering files that are common across the various azure-sdk language repos. +It should remain relatively small and only contain textual based files like scripts, configs, or templates. It +should not contain binary files as they don't play well with git. + +# Updating + +Any updates to files in the `eng/common` directory should be made in the [azure-sdk-tools](https://github.com/azure/azure-sdk-tools) repo. +All changes made will cause a PR to created in all subscribed azure-sdk language repos which will blindly replace all contents of +the `eng/common` directory in that repo. For that reason do **NOT** make changes to files in this directory in the individual azure-sdk +languages repos as they will be overwritten the next time an update is taken from the common azure-sdk-tools repo. \ No newline at end of file diff --git a/sdk/azcore/core.go b/sdk/azcore/core.go new file mode 100644 index 000000000000..de01623ffe3b --- /dev/null +++ b/sdk/azcore/core.go @@ -0,0 +1,114 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "errors" + "io" + "net/http" +) + +// Policy represents an extensibility point for the Pipeline that can mutate the specified +// Request and react to the received Response. +type Policy interface { + // Do applies the policy to the specified Request. When implementing a Policy, mutate the + // request before calling req.Do() to move on to the next policy, and respond to the result + // before returning to the caller. + Do(ctx context.Context, req *Request) (*Response, error) +} + +// PolicyFunc is a type that implements the Policy interface. +// Use this type when implementing a stateless policy as a first-class function. +type PolicyFunc func(context.Context, *Request) (*Response, error) + +// Do implements the Policy interface on PolicyFunc. +func (pf PolicyFunc) Do(ctx context.Context, req *Request) (*Response, error) { + return pf(ctx, req) +} + +// Transport represents an HTTP pipeline transport used to send HTTP requests and receive responses. +type Transport interface { + // Do sends the HTTP request and returns the HTTP response or error. + Do(ctx context.Context, req *http.Request) (*http.Response, error) +} + +// transportFunc is a type that implements the Transport interface. +// Use this type when implementing a stateless transport as a first-class function. +type transportFunc func(context.Context, *http.Request) (*http.Response, error) + +// Do implements the Transport interface on transportFunc. +func (tf transportFunc) Do(ctx context.Context, req *http.Request) (*http.Response, error) { + return tf(ctx, req) +} + +// used to adapt a TransportPolicy to a Policy +type transportPolicy struct { + trans Transport +} + +func (tp transportPolicy) Do(ctx context.Context, req *Request) (*Response, error) { + resp, err := tp.trans.Do(ctx, req.Request) + if err != nil { + return nil, err + } + return &Response{Response: resp}, nil +} + +// Pipeline represents a primitive for sending HTTP requests and receiving responses. +// Its behavior can be extended by specifying policies during construction. +type Pipeline struct { + policies []Policy +} + +// NewPipeline creates a new goroutine-safe Pipeline object from the specified Policies. +// If no transport is provided then the default HTTP transport will be used. +func NewPipeline(transport Transport, policies ...Policy) Pipeline { + if transport == nil { + transport = DefaultHTTPClientTransport() + } + // transport policy must always be the last in the slice + policies = append(policies, newBodyDownloadPolicy(), transportPolicy{trans: transport}) + return Pipeline{ + policies: policies, + } +} + +// Do is called for each and every HTTP request. It passes the Context and request through +// all the Policy objects (which can transform the Request's URL/query parameters/headers) +// and ultimately sends the transformed HTTP request over the network. +func (p Pipeline) Do(ctx context.Context, req *Request) (*Response, error) { + req.policies = p.policies + return req.Next(ctx) +} + +// ReadSeekCloser is the interface that groups the io.ReadCloser and io.Seeker interfaces. +type ReadSeekCloser interface { + io.ReadCloser + io.Seeker +} + +type nopCloser struct { + io.ReadSeeker +} + +func (n nopCloser) Close() error { + return nil +} + +// NopCloser returns a ReadSeekCloser with a no-op close method wrapping the provided io.ReadSeeker. +func NopCloser(rs io.ReadSeeker) ReadSeekCloser { + return nopCloser{rs} +} + +// IterationDone is returned by an iterator's Next method when iteration is complete. +var IterationDone = errors.New("no more items in iterator") + +// Retrier provides methods describing if an error should be considered as transient. +type Retrier interface { + // IsNotRetriable returns true for error types that are not retriable. + IsNotRetriable() bool +} diff --git a/sdk/azcore/credential.go b/sdk/azcore/credential.go new file mode 100644 index 000000000000..997872203925 --- /dev/null +++ b/sdk/azcore/credential.go @@ -0,0 +1,52 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "time" +) + +// AuthenticationPolicyOptions contains various options used to create a credential policy. +type AuthenticationPolicyOptions struct { + // Options contains the TokenRequestOptions that includes a scopes field which contains + // the list of OAuth2 authentication scopes used when requesting a token. + // This field is ignored for other forms of authentication (e.g. shared key). + Options TokenRequestOptions +} + +// Credential represents any credential type. +type Credential interface { + // AuthenticationPolicy returns a policy that requests the credential and applies it to the HTTP request. + AuthenticationPolicy(options AuthenticationPolicyOptions) Policy +} + +// credentialFunc is a type that implements the Credential interface. +// Use this type when implementing a stateless credential as a first-class function. +type credentialFunc func(options AuthenticationPolicyOptions) Policy + +// AuthenticationPolicy implements the Credential interface on credentialFunc. +func (cf credentialFunc) AuthenticationPolicy(options AuthenticationPolicyOptions) Policy { + return cf(options) +} + +// TokenCredential represents a credential capable of providing an OAuth token. +type TokenCredential interface { + Credential + // GetToken requests an access token for the specified set of scopes. + GetToken(ctx context.Context, options TokenRequestOptions) (*AccessToken, error) +} + +// AccessToken represents an Azure service bearer access token with expiry information. +type AccessToken struct { + Token string + ExpiresOn time.Time +} + +// TokenRequestOptions contain specific parameter that may be used by credentials types when attempting to get a token +type TokenRequestOptions struct { + Scopes []string +} diff --git a/sdk/azcore/doc.go b/sdk/azcore/doc.go new file mode 100644 index 000000000000..6546445bc796 --- /dev/null +++ b/sdk/azcore/doc.go @@ -0,0 +1,164 @@ +// +build go1.13 + +// Copyright 2017 Microsoft Corporation. All rights reserved. +// Use of this source code is governed by an MIT +// license that can be found in the LICENSE file. + +/* +Package azcore implements an HTTP request/response middleware pipeline whose +policy objects mutate an HTTP request's URL, query parameters, and/or headers before +the request is sent over the wire. + +Not all policy objects mutate an HTTP request; some policy objects simply impact the +flow of requests/responses by performing operations such as logging, retry policies, +timeouts, failure injection, and deserialization of response payloads. + +Implementing the Policy Interface + +To implement a policy, define a struct that implements the pipeline.Policy interface's Do method. Your Do +method is called when an HTTP request wants to be sent over the network. Your Do method can perform any +operation(s) it desires. For example, it can log the outgoing request, mutate the URL, headers, and/or query +parameters, inject a failure, etc. Your Do method must then forward the HTTP request to next Policy object +in a linked-list ensuring that the remaining Policy objects perform their work. Ultimately, the last Policy +object sends the HTTP request over the network (by calling the HTTPSender's Do method). + +When an HTTP response comes back, each Policy object in the linked-list gets a chance to process the response +(in reverse order). The Policy object can log the response, retry the operation if due to a transient failure +or timeout, deserialize the response body, etc. Ultimately, the last Policy object returns the HTTP response +to the code that initiated the original HTTP request. + +Here is a template for how to define a pipeline.Policy object: + + type myPolicy struct { + node PolicyNode + // TODO: Add configuration/setting fields here (if desired)... + } + + func (p *myPolicy) Do(ctx context.Context, request pipeline.Request) (pipeline.Response, error) { + // TODO: Mutate/process the HTTP request here... + response, err := p.node.Do(ctx, request) // Forward HTTP request to next Policy & get HTTP response + // TODO: Mutate/process the HTTP response here... + return response, err // Return response/error to previous Policy + } + +Implementing the Factory Interface + +Each Policy struct definition requires a factory struct definition that implements the pipeline.Factory interface's New +method. The New method is called when application code wants to initiate a new HTTP request. Factory's New method is +passed a pipeline.PolicyNode object which contains a reference to the owning pipeline.Pipeline object (discussed later) and +a reference to the next Policy object in the linked list. The New method should create its corresponding Policy object +passing it the PolicyNode and any other configuration/settings fields appropriate for the specific Policy object. + +Here is a template for how to define a pipeline.Policy object: + + // NOTE: Once created & initialized, Factory objects should be goroutine-safe (ex: immutable); + // this allows reuse (efficient use of memory) and makes these objects usable by multiple goroutines concurrently. + type myPolicyFactory struct { + // TODO: Add any configuration/setting fields if desired... + } + + func (f *myPolicyFactory) New(node pipeline.PolicyNode) Policy { + return &myPolicy{node: node} // TODO: Also initialize any configuration/setting fields here (if desired)... + } + +Using your Factory and Policy objects via a Pipeline + +To use the Factory and Policy objects, an application constructs a slice of Factory objects and passes +this slice to the pipeline.NewPipeline function. + + func NewPipeline(factories []pipeline.Factory, sender pipeline.HTTPSender) Pipeline + +This function also requires an object implementing the HTTPSender interface. For simple scenarios, +passing nil for HTTPSender causes a standard Go http.Client object to be created and used to actually +send the HTTP response over the network. For more advanced scenarios, you can pass your own HTTPSender +object in. This allows sharing of http.Client objects or the use of custom-configured http.Client objects +or other objects that can simulate the network requests for testing purposes. + +Now that you have a pipeline.Pipeline object, you can create a pipeline.Request object (which is a simple +wrapper around Go's standard http.Request object) and pass it to Pipeline's Do method along with passing a +context.Context for cancelling the HTTP request (if desired). + + type Pipeline interface { + Do(ctx context.Context, methodFactory pipeline.Factory, request pipeline.Request) (pipeline.Response, error) + } + +Do iterates over the slice of Factory objects and tells each one to create its corresponding +Policy object. After the linked-list of Policy objects have been created, Do calls the first +Policy object passing it the Context & HTTP request parameters. These parameters now flow through +all the Policy objects giving each object a chance to look at and/or mutate the HTTP request. +The last Policy object sends the message over the network. + +When the network operation completes, the HTTP response and error return values pass +back through the same Policy objects in reverse order. Most Policy objects ignore the +response/error but some log the result, retry the operation (depending on the exact +reason the operation failed), or deserialize the response's body. Your own Policy +objects can do whatever they like when processing outgoing requests or incoming responses. + +Note that after an I/O request runs to completion, the Policy objects for that request +are garbage collected. However, Pipeline object (like Factory objects) are goroutine-safe allowing +them to be created once and reused over many I/O operations. This allows for efficient use of +memory and also makes them safely usable by multiple goroutines concurrently. + +Inserting a Method-Specific Factory into the Linked-List of Policy Objects + +While Pipeline and Factory objects can be reused over many different operations, it is +common to have special behavior for a specific operation/method. For example, a method +may need to deserialize the response's body to an instance of a specific data type. +To accommodate this, the Pipeline's Do method takes an additional method-specific +Factory object. The Do method tells this Factory to create a Policy object and +injects this method-specific Policy object into the linked-list of Policy objects. + +When creating a Pipeline object, the slice of Factory objects passed must have 1 +(and only 1) entry marking where the method-specific Factory should be injected. +The Factory marker is obtained by calling the pipeline.MethodFactoryMarker() function: + + func MethodFactoryMarker() pipeline.Factory + +Creating an HTTP Request Object + +The HTTP request object passed to Pipeline's Do method is not Go's http.Request struct. +Instead, it is a pipeline.Request struct which is a simple wrapper around Go's standard +http.Request. You create a pipeline.Request object by calling the pipeline.NewRequest function: + + func NewRequest(method string, url url.URL, options pipeline.RequestOptions) (request pipeline.Request, err error) + +To this function, you must pass a pipeline.RequestOptions that looks like this: + + type RequestOptions struct { + // The readable and seekable stream to be sent to the server as the request's body. + Body io.ReadSeeker + + // The callback method (if not nil) to be invoked to report progress as the stream is uploaded in the HTTP request. + Progress ProgressReceiver + } + +The method and struct ensure that the request's body stream is a read/seekable stream. +A seekable stream is required so that upon retry, the final Policy object can seek +the stream back to the beginning before retrying the network request and re-uploading the +body. In addition, you can associate a ProgressReceiver callback function which will be +invoked periodically to report progress while bytes are being read from the body stream +and sent over the network. + +Processing the HTTP Response + +When an HTTP response comes in from the network, a reference to Go's http.Response struct is +embedded in a struct that implements the pipeline.Response interface: + + type Response interface { + Response() *http.Response + } + +This interface is returned through all the Policy objects. Each Policy object can call the Response +interface's Response method to examine (or mutate) the embedded http.Response object. + +A Policy object can internally define another struct (implementing the pipeline.Response interface) +that embeds an http.Response and adds additional fields and return this structure to other Policy +objects. This allows a Policy object to deserialize the body to some other struct and return the +original http.Response and the additional struct back through the Policy chain. Other Policy objects +can see the Response but cannot see the additional struct with the deserialized body. After all the +Policy objects have returned, the pipeline.Response interface is returned by Pipeline's Do method. +The caller of this method can perform a type assertion attempting to get back to the struct type +really returned by the Policy object. If the type assertion is successful, the caller now has +access to both the http.Response and the deserialized struct object. +*/ +package azcore diff --git a/sdk/azcore/error.go b/sdk/azcore/error.go new file mode 100644 index 000000000000..93d6957e206f --- /dev/null +++ b/sdk/azcore/error.go @@ -0,0 +1,53 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "errors" + "fmt" +) + +var ( + // ErrNoMorePolicies is returned from Request.Next() if there are no more policies in the pipeline. + ErrNoMorePolicies = errors.New("no more policies") +) + +// TODO: capture frame info for marshal, unmarshal, and parsing errors +// built in frame in xerror? %w +type frameInfo struct { + file string + line int +} + +func (f frameInfo) String() string { + if f.zero() { + return "" + } + return fmt.Sprintf("file: %s, line: %d", f.file, f.line) +} + +func (f frameInfo) zero() bool { + return f.file == "" && f.line == 0 +} + +// RequestError is returned when the service returns an unsuccessful resopnse code (4xx, 5xx). +type RequestError struct { + msg string + resp *Response +} + +func newRequestError(message string, response *Response) error { + return RequestError{msg: message, resp: response} +} + +func (re RequestError) Error() string { + return re.msg +} + +// Response returns the underlying response. +func (re RequestError) Response() *Response { + return re.resp +} diff --git a/sdk/azcore/go.mod b/sdk/azcore/go.mod new file mode 100644 index 000000000000..637312064cb5 --- /dev/null +++ b/sdk/azcore/go.mod @@ -0,0 +1,5 @@ +module github.com/Azure/azure-sdk-for-go/sdk/azcore + +require github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 + +go 1.13 diff --git a/sdk/azcore/go.sum b/sdk/azcore/go.sum new file mode 100644 index 000000000000..6306f1577dcd --- /dev/null +++ b/sdk/azcore/go.sum @@ -0,0 +1,2 @@ +github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0 h1:sgOdyT1ZAW3nErwCuvlGrkeP03pTtbRBW5MGCXWGZws= +github.com/Azure/azure-sdk-for-go/sdk/internal v0.1.0/go.mod h1:Q+TCQnSr+clUU0JU+xrHZ3slYCxw17AOFdvWFpQXjAY= diff --git a/sdk/azcore/headers.go b/sdk/azcore/headers.go new file mode 100644 index 000000000000..0daa2908ee04 --- /dev/null +++ b/sdk/azcore/headers.go @@ -0,0 +1,29 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +// Constants ensuring that header names are correctly spelled and consistently cased. +const ( + HeaderAuthorization = "Authorization" + HeaderCacheControl = "Cache-Control" + HeaderContentEncoding = "Content-Encoding" + HeaderContentDisposition = "Content-Disposition" + HeaderContentLanguage = "Content-Language" + HeaderContentLength = "Content-Length" + HeaderContentMD5 = "Content-MD5" + HeaderContentType = "Content-Type" + HeaderDate = "Date" + HeaderIfMatch = "If-Match" + HeaderIfModifiedSince = "If-Modified-Since" + HeaderIfNoneMatch = "If-None-Match" + HeaderIfUnmodifiedSince = "If-Unmodified-Since" + HeaderMetadata = "Metadata" + HeaderRange = "Range" + HeaderURLEncoded = "application/x-www-form-urlencoded" + HeaderUserAgent = "User-Agent" + HeaderXmsDate = "x-ms-date" + HeaderXmsVersion = "x-ms-version" +) diff --git a/sdk/azcore/log.go b/sdk/azcore/log.go new file mode 100644 index 000000000000..211cdd99d622 --- /dev/null +++ b/sdk/azcore/log.go @@ -0,0 +1,86 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +// LogClassification is used to group entries. Each group can be toggled on or off. +type LogClassification string + +const ( + // LogError entries contain detailed error information. + // This includes the error message and stack trace. + LogError LogClassification = "Error" + + // LogRequest entries contain information about HTTP requests. + // This includes information like the URL, query parameters, and headers. + LogRequest LogClassification = "Request" + + // LogResponse entries contain information about HTTP responses. + // This includes information like the HTTP status code, headers, and request URL. + LogResponse LogClassification = "Response" + + // LogRetryPolicy entries contain information specific to the retry policy in use. + LogRetryPolicy LogClassification = "RetryPolicy" + + // LogSlowResponse entries contain information for responses that take longer than the specified threshold. + LogSlowResponse LogClassification = "SlowResponse" +) + +// Listener is the function signature invoked when writing log entries. +// A Listener is required to perform its own synchronization if it's +// expected to be called from multiple Go routines. +type Listener func(LogClassification, string) + +// Logger controls which classifications to log and writing to the underlying log. +type Logger struct { + cls []LogClassification + lst Listener +} + +// SetClassifications is used to control which classifications are written to +// the log. By default all log classifications are written. +func (l *Logger) SetClassifications(cls ...LogClassification) { + l.cls = cls +} + +// SetListener will set the Logger to write to the specified Listener. +func (l *Logger) SetListener(lst Listener) { + l.lst = lst +} + +// Should returns true if the specified log classification should be written to the log. +// TODO: explain why you would want to call this +func (l *Logger) Should(cls LogClassification) bool { + if l.cls == nil || len(l.cls) == 0 { + return true + } + for _, c := range l.cls { + if c == cls { + return true + } + } + return false +} + +// Write invokes the underlying Listener with the specified classification and message. +// If the classification shouldn't be logged or there is no listener then Write does nothing. +func (l *Logger) Write(cls LogClassification, message string) { + if l.lst == nil || !l.Should(cls) { + return + } + l.lst(cls, message) +} + +// for testing purposes +func (l *Logger) resetClassifications() { + l.cls = nil +} + +var log Logger + +// Log returns the process-wide logger. +func Log() *Logger { + return &log +} diff --git a/sdk/azcore/log_test.go b/sdk/azcore/log_test.go new file mode 100644 index 000000000000..f9eadbe2c5f8 --- /dev/null +++ b/sdk/azcore/log_test.go @@ -0,0 +1,50 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import "testing" + +func TestLoggingDefault(t *testing.T) { + // ensure logging with nil listener doesn't fail + Log().SetListener(nil) + Log().Write(LogError, "this should work just fine") + + log := map[LogClassification]string{} + Log().SetListener(func(cls LogClassification, msg string) { + log[cls] = msg + }) + const req = "this is a request" + Log().Write(LogRequest, req) + const resp = "this is a response" + Log().Write(LogResponse, resp) + if l := len(log); l != 2 { + t.Fatalf("unexpected log entry count: %d", l) + } + if log[LogRequest] != req { + t.Fatalf("unexpected log request: %s", log[LogRequest]) + } + if log[LogResponse] != resp { + t.Fatalf("unexpected log response: %s", log[LogResponse]) + } +} + +func TestLoggingClassification(t *testing.T) { + log := map[LogClassification]string{} + Log().SetListener(func(cls LogClassification, msg string) { + log[cls] = msg + }) + Log().SetClassifications(LogError) + defer Log().resetClassifications() + Log().Write(LogSlowResponse, "this shouldn't be in the log") + if s, ok := log[LogSlowResponse]; ok { + t.Fatalf("unexpected log entry %s", s) + } + const err = "this is an error" + Log().Write(LogError, err) + if log[LogError] != err { + t.Fatalf("unexpected log entry: %s", log[LogError]) + } +} diff --git a/sdk/azcore/policy_anonymous_credential.go b/sdk/azcore/policy_anonymous_credential.go new file mode 100644 index 000000000000..6d5977ccd9f6 --- /dev/null +++ b/sdk/azcore/policy_anonymous_credential.go @@ -0,0 +1,18 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import "context" + +// AnonymousCredential is for use with HTTP(S) requests that read public resource +// or for use with Shared Access Signatures (SAS). +func AnonymousCredential() Credential { + return credentialFunc(func(AuthenticationPolicyOptions) Policy { + return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) { + return req.Next(ctx) + }) + }) +} diff --git a/sdk/azcore/policy_anonymous_credential_test.go b/sdk/azcore/policy_anonymous_credential_test.go new file mode 100644 index 000000000000..d860a843f704 --- /dev/null +++ b/sdk/azcore/policy_anonymous_credential_test.go @@ -0,0 +1,30 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "net/http" + "reflect" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestAnonymousCredential(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithStatusCode(http.StatusOK)) + pl := NewPipeline(srv, AnonymousCredential().AuthenticationPolicy(AuthenticationPolicyOptions{})) + req := NewRequest(http.MethodGet, srv.URL()) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !reflect.DeepEqual(req.Header, resp.Request.Header) { + t.Fatal("unexpected modification to request headers") + } +} diff --git a/sdk/azcore/policy_body_download.go b/sdk/azcore/policy_body_download.go new file mode 100644 index 000000000000..22f5a1b9b415 --- /dev/null +++ b/sdk/azcore/policy_body_download.go @@ -0,0 +1,73 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "fmt" + "io" + "io/ioutil" +) + +// newBodyDownloadPolicy creates a policy object that downloads the response's body to a []byte. +func newBodyDownloadPolicy() Policy { + return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) { + resp, err := req.Next(ctx) + if err != nil { + return resp, err + } + var opValues bodyDownloadPolicyOpValues + if req.OperationValue(&opValues); !opValues.skip && resp.Body != nil { + // Either bodyDownloadPolicyOpValues was not specified (so skip is false) + // or it was specified and skip is false: don't skip downloading the body + b, err := ioutil.ReadAll(resp.Body) + resp.Body.Close() + if err != nil { + err = fmt.Errorf("body download policy: %w", err) + } + resp.Body = &nopClosingBytesReader{s: b} + } + return resp, err + }) +} + +// bodyDownloadPolicyOpValues is the struct containing the per-operation values +type bodyDownloadPolicyOpValues struct { + skip bool +} + +// nopClosingBytesReader is an io.ReadCloser around a byte slice. +// It also provides direct access to the byte slice. +type nopClosingBytesReader struct { + s []byte + i int64 +} + +// Bytes returns the underlying byte slice. +func (r *nopClosingBytesReader) Bytes() []byte { + return r.s +} + +// Close implements the io.Closer interface. +func (*nopClosingBytesReader) Close() error { + return nil +} + +// Read implements the io.Reader interface. +func (r *nopClosingBytesReader) Read(b []byte) (n int, err error) { + if r.i >= int64(len(r.s)) { + return 0, io.EOF + } + n = copy(b, r.s[r.i:]) + r.i += int64(n) + return +} + +// Set replaces the existing byte slice with the specified byte slice and resets the reader. +func (r *nopClosingBytesReader) Set(b []byte) { + r.s = b + r.i = 0 +} diff --git a/sdk/azcore/policy_body_download_test.go b/sdk/azcore/policy_body_download_test.go new file mode 100644 index 000000000000..a46f4dcfd502 --- /dev/null +++ b/sdk/azcore/policy_body_download_test.go @@ -0,0 +1,51 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestDownloadBody(t *testing.T) { + const message = "downloaded" + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody([]byte(message))) + // download policy is automatically added during pipeline construction + pl := NewPipeline(srv) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(resp.payload()) == 0 { + t.Fatal("missing payload") + } + if string(resp.payload()) != message { + t.Fatalf("unexpected response: %s", string(resp.payload())) + } +} + +func TestSkipBodyDownload(t *testing.T) { + const message = "not downloaded" + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody([]byte(message))) + // download policy is automatically added during pipeline construction + pl := NewPipeline(srv) + req := NewRequest(http.MethodGet, srv.URL()) + req.SkipBodyDownload() + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if len(resp.payload()) > 0 { + t.Fatalf("unexpected download: %s", string(resp.payload())) + } +} diff --git a/sdk/azcore/policy_logging.go b/sdk/azcore/policy_logging.go new file mode 100644 index 000000000000..5900e64f9c04 --- /dev/null +++ b/sdk/azcore/policy_logging.go @@ -0,0 +1,160 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "bytes" + "context" + "fmt" + "net/http" + "net/url" + "runtime" + "strings" + "time" +) + +// RequestLogOptions configures the retry policy's behavior. +type RequestLogOptions struct { + // LogWarningIfTryOverThreshold logs a warning if a tried operation takes longer than the specified + // duration (-1=no logging; 0=default threshold). + LogWarningIfTryOverThreshold time.Duration +} + +func (o RequestLogOptions) defaults() RequestLogOptions { + if o.LogWarningIfTryOverThreshold == 0 { + // It would be good to relate this to https://azure.microsoft.com/en-us/support/legal/sla/storage/v1_2/ + // But this monitors the time to get the HTTP response; NOT the time to download the response body. + o.LogWarningIfTryOverThreshold = 3 * time.Second // Default to 3 seconds + } + return o +} + +type requestLogPolicy struct { + options RequestLogOptions +} + +// NewRequestLogPolicy creates a RequestLogPolicy object configured using the specified options. +func NewRequestLogPolicy(o RequestLogOptions) Policy { + o = o.defaults() // Force defaults to be calculated + return &requestLogPolicy{options: o} +} + +// logPolicyOpValues is the struct containing the per-operation values +type logPolicyOpValues struct { + try int32 + start time.Time +} + +func (p *requestLogPolicy) Do(ctx context.Context, req *Request) (*Response, error) { + // Get the per-operation values. These are saved in the Message's map so that they persist across each retry calling into this policy object. + var opValues logPolicyOpValues + if req.OperationValue(&opValues); opValues.start.IsZero() { + opValues.start = time.Now() // If this is the 1st try, record this operation's start time + } + opValues.try++ // The first try is #1 (not #0) + req.SetOperationValue(opValues) + + // Log the outgoing request as informational + if Log().Should(LogRequest) { + b := &bytes.Buffer{} + fmt.Fprintf(b, "==> OUTGOING REQUEST (Try=%d)\n", opValues.try) + WriteRequestWithResponse(b, prepareRequestForLogging(req), nil, nil) + Log().Write(LogRequest, b.String()) + } + + // Set the time for this particular retry operation and then Do the operation. + tryStart := time.Now() + response, err := req.Next(ctx) // Make the request + tryEnd := time.Now() + tryDuration := tryEnd.Sub(tryStart) + opDuration := tryEnd.Sub(opValues.start) + + logClass := LogResponse // Default logging information + + // If the response took too long, we'll upgrade to warning. + if p.options.LogWarningIfTryOverThreshold > 0 && tryDuration > p.options.LogWarningIfTryOverThreshold { + // Log a warning if the try duration exceeded the specified threshold + logClass = LogSlowResponse + } + + if err == nil { // We got a response from the service + sc := response.StatusCode + if ((sc >= 400 && sc <= 499) && sc != http.StatusNotFound && sc != http.StatusConflict && sc != http.StatusPreconditionFailed && sc != http.StatusRequestedRangeNotSatisfiable) || (sc >= 500 && sc <= 599) { + logClass = LogError // Promote to Error any 4xx (except those listed is an error) or any 5xx + } else { + // For other status codes, we leave the level as is. + } + } else { // This error did not get an HTTP response from the service; upgrade the severity to Error + logClass = LogError + } + + if Log().Should(logClass) { + // We're going to log this; build the string to log + b := &bytes.Buffer{} + slow := "" + if p.options.LogWarningIfTryOverThreshold > 0 && tryDuration > p.options.LogWarningIfTryOverThreshold { + slow = fmt.Sprintf("[SLOW >%v]", p.options.LogWarningIfTryOverThreshold) + } + fmt.Fprintf(b, "==> REQUEST/RESPONSE (Try=%d/%v%s, OpTime=%v) -- ", opValues.try, tryDuration, slow, opDuration) + if err != nil { // This HTTP request did not get a response from the service + fmt.Fprint(b, "REQUEST ERROR\n") + } else { + if logClass == LogError { + fmt.Fprint(b, "RESPONSE STATUS CODE ERROR\n") + } else { + fmt.Fprint(b, "RESPONSE SUCCESSFULLY RECEIVED\n") + } + } + + WriteRequestWithResponse(b, prepareRequestForLogging(req), response, err) + if logClass == LogError { + b.Write(stack()) // For errors (or lower levels), we append the stack trace (an expensive operation) + } + Log().Write(logClass, b.String()) + } + return response, err +} + +// RedactSigQueryParam redacts the 'sig' query parameter in URL's raw query to protect secret. +func RedactSigQueryParam(rawQuery string) (bool, string) { + rawQuery = strings.ToLower(rawQuery) // lowercase the string so we can look for ?sig= and &sig= + sigFound := strings.Contains(rawQuery, "?sig=") + if !sigFound { + sigFound = strings.Contains(rawQuery, "&sig=") + if !sigFound { + return sigFound, rawQuery // [?|&]sig= not found; return same rawQuery passed in (no memory allocation) + } + } + // [?|&]sig= found, redact its value + values, _ := url.ParseQuery(rawQuery) + for name := range values { + if strings.EqualFold(name, "sig") { + values[name] = []string{"REDACTED"} + } + } + return sigFound, values.Encode() +} + +func prepareRequestForLogging(req *Request) *Request { + request := req + if sigFound, rawQuery := RedactSigQueryParam(request.URL.RawQuery); sigFound { + // Make copy so we don't destroy the query parameters we actually need to send in the request + request = req.copy() + request.URL.RawQuery = rawQuery + } + return request +} + +func stack() []byte { + buf := make([]byte, 1024) + for { + n := runtime.Stack(buf, false) + if n < len(buf) { + return buf[:n] + } + buf = make([]byte, 2*len(buf)) + } +} diff --git a/sdk/azcore/policy_logging_test.go b/sdk/azcore/policy_logging_test.go new file mode 100644 index 000000000000..046a6a448262 --- /dev/null +++ b/sdk/azcore/policy_logging_test.go @@ -0,0 +1,116 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "errors" + "net/http" + "strings" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestPolicyLoggingSuccess(t *testing.T) { + log := map[LogClassification]string{} + Log().SetListener(func(cls LogClassification, s string) { + log[cls] = s + }) + srv, close := mock.NewServer() + defer close() + srv.SetResponse() + pl := NewPipeline(srv, NewRequestLogPolicy(RequestLogOptions{})) + req := NewRequest(http.MethodGet, srv.URL()) + req.SetQueryParam("one", "fish") + req.SetQueryParam("sig", "redact") + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if logReq, ok := log[LogRequest]; ok { + // Request ==> OUTGOING REQUEST (Try=1) + // GET http://127.0.0.1:49475?one=fish&sig=REDACTED + // (no headers) + if !strings.Contains(logReq, "sig=REDACTED") { + t.Fatal("missing redacted sig query param") + } + if !strings.Contains(logReq, "(no headers)") { + t.Fatal("missing (no headers)") + } + } else { + t.Fatal("missing LogRequest") + } + if logResp, ok := log[LogResponse]; ok { + // Response ==> REQUEST/RESPONSE (Try=1/1.0034ms, OpTime=1.0034ms) -- RESPONSE SUCCESSFULLY RECEIVED + // GET http://127.0.0.1:49475?one=fish&sig=REDACTED + // (no headers) + // -------------------------------------------------------------------------------- + // RESPONSE Status: 200 OK + // Content-Length: [0] + // Date: [Fri, 22 Nov 2019 23:48:02 GMT] + if !strings.Contains(logResp, "RESPONSE Status: 200 OK") { + t.Fatal("missing response status") + } + } else { + t.Fatal("missing LogResponse") + } +} + +func TestPolicyLoggingError(t *testing.T) { + log := map[LogClassification]string{} + Log().SetListener(func(cls LogClassification, s string) { + log[cls] = s + }) + srv, close := mock.NewServer() + defer close() + srv.SetError(errors.New("bogus error")) + pl := NewPipeline(srv, NewRequestLogPolicy(RequestLogOptions{})) + req := NewRequest(http.MethodGet, srv.URL()) + req.Header.Add("header", "one") + req.Header.Add("Authorization", "redact") + resp, err := pl.Do(context.Background(), req) + if err == nil { + t.Fatal("unexpected nil error") + } + if resp != nil { + t.Fatal("unexpected respose") + } + if logReq, ok := log[LogRequest]; ok { + // Request ==> OUTGOING REQUEST (Try=1) + // GET http://127.0.0.1:50057 + // Authorization: REDACTED + // Header: [one] + if !strings.Contains(logReq, "Authorization: REDACTED") { + t.Fatal("missing redacted authorization header") + } + } else { + t.Fatal("missing LogRequest") + } + if logError, ok := log[LogError]; ok { + // Error ==> REQUEST/RESPONSE (Try=1/0s, OpTime=0s) -- REQUEST ERROR + // GET http://127.0.0.1:50057 + // Authorization: REDACTED + // Header: [one] + // -------------------------------------------------------------------------------- + // ERROR: + // bogus error + // ...stack track... + if !strings.Contains(logError, "Authorization: REDACTED") { + t.Fatal("missing redacted authorization header") + } + if !strings.Contains(logError, "bogus error") { + t.Fatal("missing error message") + } + } else { + t.Fatal("missing LogError") + } +} + +// TODO: add test for slow response diff --git a/sdk/azcore/policy_retry.go b/sdk/azcore/policy_retry.go new file mode 100644 index 000000000000..7d48f98a42b4 --- /dev/null +++ b/sdk/azcore/policy_retry.go @@ -0,0 +1,208 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "fmt" + "io" + "math/rand" + "net/http" + "time" +) + +const ( + defaultMaxTries = 4 +) + +// RetryOptions configures the retry policy's behavior. +type RetryOptions struct { + // MaxTries specifies the maximum number of attempts an operation will be tried before producing an error (0=default). + // A value of zero means that you accept our default policy. A value of 1 means 1 try and no retries. + MaxTries int32 + + // TryTimeout indicates the maximum time allowed for any single try of an HTTP request. + // A value of zero means that you accept our default timeout. NOTE: When transferring large amounts + // of data, the default TryTimeout will probably not be sufficient. You should override this value + // based on the bandwidth available to the host machine and proximity to the service. A good + // starting point may be something like (60 seconds per MB of anticipated-payload-size). + TryTimeout time.Duration + + // RetryDelay specifies the amount of delay to use before retrying an operation (0=default). + // The delay increases exponentially with each retry up to a maximum specified by MaxRetryDelay. + // If you specify 0, then you must also specify 0 for MaxRetryDelay. + // If you specify RetryDelay, then you must also specify MaxRetryDelay, and MaxRetryDelay should be + // equal to or greater than RetryDelay. + RetryDelay time.Duration + + // MaxRetryDelay specifies the maximum delay allowed before retrying an operation (0=default). + // If you specify 0, then you must also specify 0 for RetryDelay. + MaxRetryDelay time.Duration + + // StatusCodes specifies the HTTP status codes that indicate the operation should be retried. + // If unspecified it will default to the status codes in StatusCodesForRetry. + StatusCodes []int +} + +var ( + // StatusCodesForRetry is the default set of HTTP status code for which the policy will retry. + StatusCodesForRetry = [6]int{ + http.StatusRequestTimeout, // 408 + http.StatusTooManyRequests, // 429 + http.StatusInternalServerError, // 500 + http.StatusBadGateway, // 502 + http.StatusServiceUnavailable, // 503 + http.StatusGatewayTimeout, // 504 + } +) + +// DefaultRetryOptions returns an instance of RetryOptions initialized with default values. +func DefaultRetryOptions() RetryOptions { + return RetryOptions{ + StatusCodes: StatusCodesForRetry[:], + MaxTries: defaultMaxTries, + TryTimeout: 1 * time.Minute, + RetryDelay: 4 * time.Second, + MaxRetryDelay: 120 * time.Second, + } +} + +func (o RetryOptions) calcDelay(try int32) time.Duration { // try is >=1; never 0 + pow := func(number int64, exponent int32) int64 { // pow is nested helper function + var result int64 = 1 + for n := int32(0); n < exponent; n++ { + result *= number + } + return result + } + + delay := time.Duration(pow(2, try)-1) * o.RetryDelay + + // Introduce some jitter: [0.0, 1.0) / 2 = [0.0, 0.5) + 0.8 = [0.8, 1.3) + delay = time.Duration(delay.Seconds() * (rand.Float64()/2 + 0.8) * float64(time.Second)) // NOTE: We want math/rand; not crypto/rand + if delay > o.MaxRetryDelay { + delay = o.MaxRetryDelay + } + return delay +} + +// NewRetryPolicy creates a policy object configured using the specified options. +// Pass nil to accept the default values; this is the same as passing the result +// from a call to DefaultRetryOptions(). +func NewRetryPolicy(o *RetryOptions) Policy { + if o == nil { + def := DefaultRetryOptions() + o = &def + } + return &retryPolicy{options: *o} +} + +type retryPolicy struct { + options RetryOptions +} + +func (p *retryPolicy) Do(ctx context.Context, req *Request) (resp *Response, err error) { + // Exponential retry algorithm: ((2 ^ attempt) - 1) * delay * random(0.8, 1.2) + // When to retry: connection failure or temporary/timeout. + if req.Body != nil { + // wrap the body so we control when it's actually closed + rwbody := &retryableRequestBody{body: req.Body.(ReadSeekCloser)} + req.Body = rwbody + req.Request.GetBody = func() (io.ReadCloser, error) { + _, err := rwbody.Seek(0, io.SeekStart) // Seek back to the beginning of the stream + return rwbody, err + } + defer rwbody.realClose() + } + try := int32(1) + shouldLog := Log().Should(LogRetryPolicy) + for { + resp = nil // reset + if shouldLog { + Log().Write(LogRetryPolicy, fmt.Sprintf("\n=====> Try=%d\n", try)) + } + + // For each try, seek to the beginning of the Body stream. We do this even for the 1st try because + // the stream may not be at offset 0 when we first get it and we want the same behavior for the + // 1st try as for additional tries. + err = req.RewindBody() + if err != nil { + return + } + + // Set the time for this particular retry operation and then Do the operation. + tryCtx, tryCancel := context.WithTimeout(ctx, p.options.TryTimeout) + resp, err = req.Next(tryCtx) // Make the request + tryCancel() + if shouldLog { + Log().Write(LogRetryPolicy, fmt.Sprintf("Err=%v, response=%v\n", err, resp)) + } + + if err == nil && !resp.HasStatusCode(p.options.StatusCodes...) { + // if there is no error and the response code isn't in the list of retry codes then we're done. + return + } else if ctx.Err() != nil { + // don't retry if the parent context has been cancelled or its deadline exceeded + return + } else if retrier, ok := err.(Retrier); ok && retrier.IsNotRetriable() { + // the error says it's not retriable so don't retry + return + } + + // drain before retrying so nothing is leaked + resp.Drain() + + if try == p.options.MaxTries { + // max number of tries has been reached, don't sleep again + return + } + + // use the delay from retry-after if available + delay, ok := resp.RetryAfter() + if !ok { + delay = p.options.calcDelay(try) + } + if shouldLog { + Log().Write(LogRetryPolicy, fmt.Sprintf("Try=%d, Delay=%v\n", try, delay)) + } + select { + case <-time.After(delay): + try++ + case <-ctx.Done(): + err = ctx.Err() + return + } + } +} + +// ********** The following type/methods implement the retryableRequestBody (a ReadSeekCloser) + +// This struct is used when sending a body to the network +type retryableRequestBody struct { + body io.ReadSeeker // Seeking is required to support retries +} + +// Read reads a block of data from an inner stream and reports progress +func (b *retryableRequestBody) Read(p []byte) (n int, err error) { + return b.body.Read(p) +} + +func (b *retryableRequestBody) Seek(offset int64, whence int) (offsetFromStart int64, err error) { + return b.body.Seek(offset, whence) +} + +func (b *retryableRequestBody) Close() error { + // We don't want the underlying transport to close the request body on transient failures so this is a nop. + // The retry policy closes the request body upon success. + return nil +} + +func (b *retryableRequestBody) realClose() error { + if c, ok := b.body.(io.Closer); ok { + return c.Close() + } + return nil +} diff --git a/sdk/azcore/policy_retry_test.go b/sdk/azcore/policy_retry_test.go new file mode 100644 index 000000000000..6a3dc79197cf --- /dev/null +++ b/sdk/azcore/policy_retry_test.go @@ -0,0 +1,251 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "errors" + "io" + "net/http" + "strings" + "testing" + "time" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func testRetryOptions() *RetryOptions { + def := DefaultRetryOptions() + def.RetryDelay = 20 * time.Millisecond + return &def +} + +func TestRetryPolicySuccess(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithStatusCode(http.StatusOK)) + pl := NewPipeline(srv, NewRetryPolicy(nil)) + req := NewRequest(http.MethodGet, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if body.rcount > 0 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +func TestRetryPolicyFailOnStatusCode(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithStatusCode(http.StatusInternalServerError)) + pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions())) + req := NewRequest(http.MethodGet, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.StatusCode != http.StatusInternalServerError { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if r := srv.Requests(); r != defaultMaxTries { + t.Fatalf("wrong retry count, got %d expected %d", r, defaultMaxTries) + } + if body.rcount != defaultMaxTries-1 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +func TestRetryPolicySuccessWithRetry(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout)) + srv.AppendResponse(mock.WithStatusCode(http.StatusInternalServerError)) + srv.AppendResponse() + pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions())) + req := NewRequest(http.MethodGet, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.StatusCode != http.StatusOK { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if r := srv.Requests(); r != 3 { + t.Fatalf("wrong retry count, got %d expected %d", r, 3) + } + if body.rcount != 2 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +func TestRetryPolicyFailOnError(t *testing.T) { + srv, close := mock.NewServer() + defer close() + fakeErr := errors.New("bogus error") + srv.SetError(fakeErr) + pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions())) + req := NewRequest(http.MethodPost, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + resp, err := pl.Do(context.Background(), req) + if !errors.Is(err, fakeErr) { + t.Fatalf("unexpected error: %v", err) + } + if resp != nil { + t.Fatal("unexpected response") + } + if r := srv.Requests(); r != defaultMaxTries { + t.Fatalf("wrong retry count, got %d expected %d", r, defaultMaxTries) + } + if body.rcount != defaultMaxTries-1 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +func TestRetryPolicySuccessWithRetryComplex(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout)) + srv.AppendError(errors.New("bogus error")) + srv.AppendResponse(mock.WithStatusCode(http.StatusInternalServerError)) + srv.AppendResponse(mock.WithStatusCode(http.StatusAccepted)) + pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions())) + req := NewRequest(http.MethodGet, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.StatusCode != http.StatusAccepted { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if r := srv.Requests(); r != defaultMaxTries { + t.Fatalf("wrong retry count, got %d expected %d", r, 3) + } + if body.rcount != defaultMaxTries-1 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +func TestRetryPolicyRequestTimedOut(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetError(errors.New("bogus error")) + pl := NewPipeline(srv, NewRetryPolicy(nil)) + req := NewRequest(http.MethodPost, srv.URL()) + body := newRewindTrackingBody("stuff") + req.SetBody(body) + ctx, cancel := context.WithTimeout(context.Background(), 1*time.Second) + defer cancel() + resp, err := pl.Do(ctx, req) + if !errors.Is(err, context.DeadlineExceeded) { + t.Fatalf("unexpected error: %v", err) + } + if resp != nil { + t.Fatal("unexpected response") + } + if body.rcount > 0 { + t.Fatalf("unexpected rewind count: %d", body.rcount) + } + if !body.closed { + t.Fatal("request body wasn't closed") + } +} + +type fatalError struct { + s string +} + +func (f fatalError) Error() string { + return f.s +} + +func (f fatalError) IsNotRetriable() bool { + return true +} + +func TestRetryPolicyIsNotRetriable(t *testing.T) { + theErr := fatalError{s: "it's dead Jim"} + srv, close := mock.NewServer() + defer close() + srv.AppendResponse(mock.WithStatusCode(http.StatusRequestTimeout)) + srv.AppendError(theErr) + pl := NewPipeline(srv, NewRetryPolicy(testRetryOptions())) + _, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err == nil { + t.Fatal("unexpected nil error") + } + if !errors.Is(err, theErr) { + t.Fatalf("unexpected error type: got %v wanted %v", err, theErr) + } + if r := srv.Requests(); r != 2 { + t.Fatalf("wrong retry count, got %d expected %d", r, 3) + } +} + +// TODO: add test for retry failing to read response body + +// TODO: add test for per-retry timeout failed but e2e succeeded + +func newRewindTrackingBody(s string) *rewindTrackingBody { + // there are two rewinds that happen before rewinding for a retry + // 1. to get the body's size in SetBody() + // 2. the first call to Do() in the retry policy + // to offset this we init rcount with -2 so rcount is only > 0 on a rewind due to a retry + return &rewindTrackingBody{ + body: strings.NewReader(s), + rcount: -2, + } +} + +// used to track the number of times a request body has been rewound +type rewindTrackingBody struct { + body *strings.Reader + closed bool // indicates if the body was closed + rcount int // number of times a rewind happened +} + +func (r *rewindTrackingBody) Close() error { + r.closed = true + return nil +} + +func (r *rewindTrackingBody) Read(b []byte) (int, error) { + return r.body.Read(b) +} + +func (r *rewindTrackingBody) Seek(offset int64, whence int) (int64, error) { + if offset == 0 && whence == io.SeekStart { + r.rcount++ + } + return r.body.Seek(offset, whence) +} diff --git a/sdk/azcore/policy_telemetry.go b/sdk/azcore/policy_telemetry.go new file mode 100644 index 000000000000..10c83fb82f2f --- /dev/null +++ b/sdk/azcore/policy_telemetry.go @@ -0,0 +1,53 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "bytes" + "context" + "fmt" + "os" + "runtime" +) + +// TelemetryOptions configures the telemetry policy's behavior. +type TelemetryOptions struct { + // Value is a string prepended to each request's User-Agent and sent to the service. + // The service records the user-agent in logs for diagnostics and tracking of client requests. + Value string +} + +type telemetryPolicy struct { + telemetryValue string +} + +// NewTelemetryPolicy creates a telemetry policy object that adds telemetry information to outgoing HTTP requests. +func NewTelemetryPolicy(o TelemetryOptions) Policy { + b := &bytes.Buffer{} + b.WriteString(o.Value) + if b.Len() > 0 { + b.WriteRune(' ') + } + b.WriteString(platformInfo) + return &telemetryPolicy{telemetryValue: b.String()} +} + +func (p telemetryPolicy) Do(ctx context.Context, req *Request) (*Response, error) { + req.Request.Header.Set(HeaderUserAgent, p.telemetryValue) + return req.Next(ctx) +} + +// NOTE: the ONLY function that should write to this variable is this func +var platformInfo = func() string { + operatingSystem := runtime.GOOS // Default OS string + switch operatingSystem { + case "windows": + operatingSystem = os.Getenv("OS") // Get more specific OS information + case "linux": // accept default OS info + case "freebsd": // accept default OS info + } + return fmt.Sprintf("(%s; %s)", runtime.Version(), operatingSystem) +}() diff --git a/sdk/azcore/policy_telemetry_test.go b/sdk/azcore/policy_telemetry_test.go new file mode 100644 index 000000000000..2c5dfe3a7f71 --- /dev/null +++ b/sdk/azcore/policy_telemetry_test.go @@ -0,0 +1,44 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "fmt" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestPolicyTelemetryDefault(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse() + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if v := resp.Request.Header.Get(HeaderUserAgent); v != platformInfo { + t.Fatalf("unexpected user agent value: %s", v) + } +} + +func TestPolicyTelemetryWithCustomInfo(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse() + const testValue = "azcore_test" + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{Value: testValue})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if v := resp.Request.Header.Get(HeaderUserAgent); v != fmt.Sprintf("%s %s", testValue, platformInfo) { + t.Fatalf("unexpected user agent value: %s", v) + } +} diff --git a/sdk/azcore/policy_unique_request_id.go b/sdk/azcore/policy_unique_request_id.go new file mode 100644 index 000000000000..c5f9a84f2867 --- /dev/null +++ b/sdk/azcore/policy_unique_request_id.go @@ -0,0 +1,26 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/uuid" +) + +const xMsClientRequestID = "x-ms-client-request-id" + +// NewUniqueRequestIDPolicy creates a policy object that sets the request's x-ms-client-request-id header if it doesn't already exist. +func NewUniqueRequestIDPolicy() Policy { + return PolicyFunc(func(ctx context.Context, req *Request) (*Response, error) { + id := req.Request.Header.Get(xMsClientRequestID) + if id == "" { + // Add a unique request ID if the caller didn't specify one already + req.Request.Header.Set(xMsClientRequestID, uuid.New().String()) + } + return req.Next(ctx) + }) +} diff --git a/sdk/azcore/policy_unique_request_id_test.go b/sdk/azcore/policy_unique_request_id_test.go new file mode 100644 index 000000000000..66c2141063c1 --- /dev/null +++ b/sdk/azcore/policy_unique_request_id_test.go @@ -0,0 +1,45 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestUniqueRequestIDPolicy(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse() + pl := NewPipeline(srv, NewUniqueRequestIDPolicy()) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.Request.Header.Get(xMsClientRequestID) == "" { + t.Fatal("missing request ID header") + } +} + +func TestUniqueRequestIDPolicyUserDefined(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse() + pl := NewPipeline(srv, NewUniqueRequestIDPolicy()) + req := NewRequest(http.MethodGet, srv.URL()) + const customID = "my-custom-id" + req.Header.Set(xMsClientRequestID, customID) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if v := resp.Request.Header.Get(xMsClientRequestID); v != customID { + t.Fatalf("unexpected request ID value: %s", v) + } +} diff --git a/sdk/azcore/progress.go b/sdk/azcore/progress.go new file mode 100644 index 000000000000..8364581b657e --- /dev/null +++ b/sdk/azcore/progress.go @@ -0,0 +1,78 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import "io" + +// ********** The following is common between the request body AND the response body. + +// ProgressReceiver defines the signature of a callback function invoked as progress is reported. +type ProgressReceiver func(bytesTransferred int64) + +// ********** The following are specific to the request body (a ReadSeekCloser) + +// This struct is used when sending a body to the network +type requestBodyProgress struct { + requestBody ReadSeekCloser // Seeking is required to support retries + pr ProgressReceiver +} + +// NewRequestBodyProgress adds progress reporting to an HTTP request's body stream. +func NewRequestBodyProgress(requestBody ReadSeekCloser, pr ProgressReceiver) ReadSeekCloser { + return &requestBodyProgress{requestBody: requestBody, pr: pr} +} + +// Read reads a block of data from an inner stream and reports progress +func (rbp *requestBodyProgress) Read(p []byte) (n int, err error) { + n, err = rbp.requestBody.Read(p) + if err != nil { + return + } + // Invokes the user's callback method to report progress + position, err := rbp.requestBody.Seek(0, io.SeekCurrent) + if err != nil { + return + } + rbp.pr(position) + return +} + +func (rbp *requestBodyProgress) Seek(offset int64, whence int) (offsetFromStart int64, err error) { + return rbp.requestBody.Seek(offset, whence) +} + +// requestBodyProgress supports Close but the underlying stream may not; if it does, Close will close it. +func (rbp *requestBodyProgress) Close() error { + return rbp.requestBody.Close() +} + +// ********** The following are specific to the response body (a ReadCloser) + +// This struct is used when sending a body to the network +type responseBodyProgress struct { + responseBody io.ReadCloser + pr ProgressReceiver + offset int64 +} + +// NewResponseBodyProgress adds progress reporting to an HTTP response's body stream. +func NewResponseBodyProgress(responseBody io.ReadCloser, pr ProgressReceiver) io.ReadCloser { + return &responseBodyProgress{responseBody: responseBody, pr: pr, offset: 0} +} + +// Read reads a block of data from an inner stream and reports progress +func (rbp *responseBodyProgress) Read(p []byte) (n int, err error) { + n, err = rbp.responseBody.Read(p) + rbp.offset += int64(n) + + // Invokes the user's callback method to report progress + rbp.pr(rbp.offset) + return +} + +func (rbp *responseBodyProgress) Close() error { + return rbp.responseBody.Close() +} diff --git a/sdk/azcore/progress_test.go b/sdk/azcore/progress_test.go new file mode 100644 index 000000000000..61c3830175f0 --- /dev/null +++ b/sdk/azcore/progress_test.go @@ -0,0 +1,59 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "bytes" + "context" + "io/ioutil" + "net/http" + "reflect" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestProgressReporting(t *testing.T) { + const contentSize = 4096 + content := make([]byte, contentSize) + for i := 0; i < contentSize; i++ { + content[i] = byte(i % 255) + } + body := bytes.NewReader(content) + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody(content)) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + req := NewRequest(http.MethodGet, srv.URL()) + req.SkipBodyDownload() + var bytesSent int64 + reqRpt := NewRequestBodyProgress(NopCloser(body), func(bytesTransferred int64) { + bytesSent = bytesTransferred + }) + req.SetBody(reqRpt) + resp, err := pl.Do(context.Background(), req) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + var bytesReceived int64 + respRpt := NewResponseBodyProgress(resp.Body, func(bytesTransferred int64) { + bytesReceived = bytesTransferred + }) + defer respRpt.Close() + b, err := ioutil.ReadAll(respRpt) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if bytesSent != contentSize { + t.Fatalf("wrong bytes sent: %d", bytesSent) + } + if bytesReceived != contentSize { + t.Fatalf("wrong bytes received: %d", bytesReceived) + } + if !reflect.DeepEqual(content, b) { + t.Fatal("request and response bodies don't match") + } +} diff --git a/sdk/azcore/request.go b/sdk/azcore/request.go new file mode 100644 index 000000000000..7d87b20baa07 --- /dev/null +++ b/sdk/azcore/request.go @@ -0,0 +1,196 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "bytes" + "context" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "net/http" + "net/url" + "reflect" + "strings" +) + +const ( + contentTypeAppJSON = "application/json" + contentTypeAppXML = "application/xml" +) + +// Request is an abstraction over the creation of an HTTP request as it passes through the pipeline. +type Request struct { + *http.Request + policies []Policy + qp url.Values + values opValues +} + +type opValues map[reflect.Type]interface{} + +// Set adds/changes a value +func (ov opValues) set(value interface{}) { + ov[reflect.TypeOf(value)] = value +} + +// Get looks for a value set by SetValue first +func (ov opValues) get(value interface{}) bool { + v, ok := ov[reflect.ValueOf(value).Elem().Type()] + if ok { + reflect.ValueOf(value).Elem().Set(reflect.ValueOf(v)) + } + return ok +} + +// NewRequest creates a new Request with the specified input. +func NewRequest(httpMethod string, endpoint url.URL) *Request { + // removeEmptyPort strips the empty port in ":port" to "" + // as mandated by RFC 3986 Section 6.2.3. + // adapted from removeEmptyPort() in net/http.go + if strings.LastIndex(endpoint.Host, ":") > strings.LastIndex(endpoint.Host, "]") { + endpoint.Host = strings.TrimSuffix(endpoint.Host, ":") + } + return &Request{ + Request: &http.Request{ + Method: httpMethod, + URL: &endpoint, + Proto: "HTTP/1.1", + ProtoMajor: 1, + ProtoMinor: 1, + Header: http.Header{}, + Host: endpoint.Host, + }, + } +} + +// Next calls the next policy in the pipeline. +// If there are no more policies, nil and ErrNoMorePolicies are returned. +// This method is intended to be called from pipeline policies. +// To send a request through a pipeline call Pipeline.Do(). +func (req *Request) Next(ctx context.Context) (*Response, error) { + if len(req.policies) == 0 { + return nil, ErrNoMorePolicies + } + nextPolicy := req.policies[0] + nextReq := *req + nextReq.policies = nextReq.policies[1:] + // encode any pending query params + if nextReq.qp != nil { + nextReq.Request.URL.RawQuery = nextReq.qp.Encode() + nextReq.qp = nil + } + return nextPolicy.Do(ctx, &nextReq) +} + +// MarshalAsJSON calls json.Marshal() to get the JSON encoding of v then calls SetBody. +// If json.Marshal fails a MarshalError is returned. Any error from SetBody is returned. +func (req *Request) MarshalAsJSON(v interface{}) error { + b, err := json.Marshal(v) + if err != nil { + return fmt.Errorf("error marshalling type %s: %w", reflect.TypeOf(v).Name(), err) + } + req.Header.Set(HeaderContentType, contentTypeAppJSON) + return req.SetBody(NopCloser(bytes.NewReader(b))) +} + +// MarshalAsXML calls xml.Marshal() to get the XML encoding of v then calls SetBody. +// If xml.Marshal fails a MarshalError is returned. Any error from SetBody is returned. +func (req *Request) MarshalAsXML(v interface{}) error { + b, err := xml.Marshal(v) + if err != nil { + return fmt.Errorf("error marshalling type %s: %w", reflect.TypeOf(v).Name(), err) + } + req.Header.Set(HeaderContentType, contentTypeAppXML) + return req.SetBody(NopCloser(bytes.NewReader(b))) +} + +// SetOperationValue adds/changes a mutable key/value associated with a single operation. +func (req *Request) SetOperationValue(value interface{}) { + if req.values == nil { + req.values = opValues{} + } + req.values.set(value) +} + +// OperationValue looks for a value set by SetOperationValue(). +func (req *Request) OperationValue(value interface{}) bool { + if req.values == nil { + return false + } + return req.values.get(value) +} + +// SetQueryParam sets the key to value. +func (req *Request) SetQueryParam(key, value string) { + if req.qp == nil { + req.qp = req.Request.URL.Query() + } + req.qp.Set(key, value) +} + +// SetBody sets the specified ReadSeekCloser as the HTTP request body. +func (req *Request) SetBody(body ReadSeekCloser) error { + // Set the body and content length. + size, err := body.Seek(0, io.SeekEnd) // Seek to the end to get the stream's size + if err != nil { + return err + } + if size == 0 { + body.Close() + return nil + } + _, err = body.Seek(0, io.SeekStart) + if err != nil { + return err + } + req.Request.Body = body + req.Request.ContentLength = size + return nil +} + +// SkipBodyDownload will disable automatic downloading of the response body. +func (req *Request) SkipBodyDownload() { + req.SetOperationValue(bodyDownloadPolicyOpValues{skip: true}) +} + +// RewindBody seeks the request's Body stream back to the beginning so it can be resent when retrying an operation. +func (req *Request) RewindBody() error { + if req.Body != nil { + // Reset the stream back to the beginning + _, err := req.Body.(io.Seeker).Seek(0, io.SeekStart) + return err + } + return nil +} + +// Close closes the request body. +func (req *Request) Close() error { + if req.Body == nil { + return nil + } + return req.Body.Close() +} + +func (req *Request) copy() *Request { + clonedURL := *req.URL + // Copy the values and immutable references + return &Request{ + Request: &http.Request{ + Method: req.Method, + URL: &clonedURL, + Proto: req.Proto, + ProtoMajor: req.ProtoMajor, + ProtoMinor: req.ProtoMinor, + Header: req.Header.Clone(), + Host: req.URL.Host, + Body: req.Body, // shallow copy + ContentLength: req.ContentLength, + GetBody: req.GetBody, + }, + } +} diff --git a/sdk/azcore/request_test.go b/sdk/azcore/request_test.go new file mode 100644 index 000000000000..27576d47ee9e --- /dev/null +++ b/sdk/azcore/request_test.go @@ -0,0 +1,81 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "errors" + "net/http" + "net/url" + "testing" +) + +type testJSON struct { + SomeInt int + SomeString string +} + +type testXML struct { + SomeInt int + SomeString string +} + +func TestRequestMarshalXML(t *testing.T) { + u, err := url.Parse("https://contoso.com") + if err != nil { + panic(err) + } + req := NewRequest(http.MethodPost, *u) + err = req.MarshalAsXML(testXML{SomeInt: 1, SomeString: "s"}) + if err != nil { + t.Fatalf("marshal failure: %v", err) + } + if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppXML { + t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppXML) + } + if req.Body == nil { + t.Fatal("unexpected nil request body") + } + if req.ContentLength == 0 { + t.Fatal("unexpected zero content length") + } +} + +func TestRequestEmptyPipeline(t *testing.T) { + u, err := url.Parse("https://contoso.com") + if err != nil { + panic(err) + } + req := NewRequest(http.MethodPost, *u) + resp, err := req.Next(context.Background()) + if resp != nil { + t.Fatal("expected nil response") + } + if !errors.Is(err, ErrNoMorePolicies) { + t.Fatalf("expected ErrNoMorePolicies, got %v", err) + } +} + +func TestRequestMarshalJSON(t *testing.T) { + u, err := url.Parse("https://contoso.com") + if err != nil { + panic(err) + } + req := NewRequest(http.MethodPost, *u) + err = req.MarshalAsJSON(testJSON{SomeInt: 1, SomeString: "s"}) + if err != nil { + t.Fatalf("marshal failure: %v", err) + } + if ct := req.Header.Get(HeaderContentType); ct != contentTypeAppJSON { + t.Fatalf("unexpected content type, got %s wanted %s", ct, contentTypeAppJSON) + } + if req.Body == nil { + t.Fatal("unexpected nil request body") + } + if req.ContentLength == 0 { + t.Fatal("unexpected zero content length") + } +} diff --git a/sdk/azcore/response.go b/sdk/azcore/response.go new file mode 100644 index 000000000000..edb19ad244e3 --- /dev/null +++ b/sdk/azcore/response.go @@ -0,0 +1,147 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "bytes" + "encoding/json" + "encoding/xml" + "fmt" + "io" + "io/ioutil" + "net/http" + "reflect" + "sort" + "strconv" + "strings" + "time" +) + +// Response represents the response from an HTTP request. +type Response struct { + *http.Response +} + +func (r *Response) payload() []byte { + if r.Body == nil { + return nil + } + // r.Body won't be a nopClosingBytesReader if downloading was skipped + if buf, ok := r.Body.(*nopClosingBytesReader); ok { + return buf.Bytes() + } + return nil +} + +// HasStatusCode returns true if the Response's status code is one of the specified values. +func (r *Response) HasStatusCode(statusCodes ...int) bool { + if r == nil { + return false + } + for _, sc := range statusCodes { + if r.StatusCode == sc { + return true + } + } + return false +} + +// UnmarshalAsJSON calls json.Unmarshal() to unmarshal the received payload into the value pointed to by v. +// If no payload was received a RequestError is returned. If json.Unmarshal fails a UnmarshalError is returned. +func (r *Response) UnmarshalAsJSON(v interface{}) error { + // TODO: verify early exit is correct + if len(r.payload()) == 0 { + return nil + } + r.removeBOM() + err := json.Unmarshal(r.payload(), v) + if err != nil { + err = fmt.Errorf("unmarshalling type %s: %w", reflect.TypeOf(v).Elem().Name(), err) + } + return err +} + +// UnmarshalAsXML calls xml.Unmarshal() to unmarshal the received payload into the value pointed to by v. +// If no payload was received a RequestError is returned. If xml.Unmarshal fails a UnmarshalError is returned. +func (r *Response) UnmarshalAsXML(v interface{}) error { + // TODO: verify early exit is correct + if len(r.payload()) == 0 { + return nil + } + r.removeBOM() + err := xml.Unmarshal(r.payload(), v) + if err != nil { + err = fmt.Errorf("unmarshalling type %s: %w", reflect.TypeOf(v).Elem().Name(), err) + } + return err +} + +// Drain reads the response body to completion then closes it. The bytes read are discarded. +func (r *Response) Drain() { + if r != nil && r.Body != nil { + io.Copy(ioutil.Discard, r.Body) + r.Body.Close() + } +} + +// removeBOM removes any byte-order mark prefix from the payload if present. +func (r *Response) removeBOM() { + // UTF8 + trimmed := bytes.TrimPrefix(r.payload(), []byte("\xef\xbb\xbf")) + if len(trimmed) < len(r.payload()) { + r.Body.(*nopClosingBytesReader).Set(trimmed) + } +} + +// RetryAfter returns (non-zero, true) if the response contains a Retry-After header value +func (r *Response) RetryAfter() (time.Duration, bool) { + if r == nil { + return 0, false + } + if retryAfter, _ := strconv.Atoi(r.Header.Get("Retry-After")); retryAfter > 0 { + return time.Duration(retryAfter) * time.Second, true + } + return 0, false +} + +// WriteRequestWithResponse appends a formatted HTTP request into a Buffer. If request and/or err are +// not nil, then these are also written into the Buffer. +func WriteRequestWithResponse(b *bytes.Buffer, request *Request, response *Response, err error) { + // Write the request into the buffer. + fmt.Fprint(b, " "+request.Method+" "+request.URL.String()+"\n") + writeHeader(b, request.Header) + if response != nil { + fmt.Fprintln(b, " --------------------------------------------------------------------------------") + fmt.Fprint(b, " RESPONSE Status: "+response.Status+"\n") + writeHeader(b, response.Header) + } + if err != nil { + fmt.Fprintln(b, " --------------------------------------------------------------------------------") + fmt.Fprint(b, " ERROR:\n"+err.Error()+"\n") + } +} + +// formatHeaders appends an HTTP request's or response's header into a Buffer. +func writeHeader(b *bytes.Buffer, header http.Header) { + if len(header) == 0 { + b.WriteString(" (no headers)\n") + return + } + keys := make([]string, 0, len(header)) + // Alphabetize the headers + for k := range header { + keys = append(keys, k) + } + sort.Strings(keys) + for _, k := range keys { + // Redact the value of any Authorization header to prevent security information from persisting in logs + value := interface{}("REDACTED") + if !strings.EqualFold(k, "Authorization") { + value = header[k] + } + fmt.Fprintf(b, " %s: %+v\n", k, value) + } +} diff --git a/sdk/azcore/response_test.go b/sdk/azcore/response_test.go new file mode 100644 index 000000000000..263f0c3db674 --- /dev/null +++ b/sdk/azcore/response_test.go @@ -0,0 +1,105 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "net/http" + "testing" + + "github.com/Azure/azure-sdk-for-go/sdk/internal/mock" +) + +func TestResponseUnmarshalXML(t *testing.T) { + srv, close := mock.NewServer() + defer close() + // include UTF8 BOM + srv.SetResponse(mock.WithBody([]byte("\xef\xbb\xbf1s"))) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !resp.HasStatusCode(http.StatusOK) { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + var tx testXML + if err := resp.UnmarshalAsXML(&tx); err != nil { + t.Fatalf("unexpected error unmarshalling: %v", err) + } + if tx.SomeInt != 1 || tx.SomeString != "s" { + t.Fatal("unexpected value") + } +} + +func TestResponseFailureStatusCode(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithStatusCode(http.StatusForbidden)) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if resp.HasStatusCode(http.StatusOK) { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } +} + +func TestResponseUnmarshalJSON(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody([]byte(`{ "someInt": 1, "someString": "s" }`))) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !resp.HasStatusCode(http.StatusOK) { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + var tx testJSON + if err := resp.UnmarshalAsJSON(&tx); err != nil { + t.Fatalf("unexpected error unmarshalling: %v", err) + } + if tx.SomeInt != 1 || tx.SomeString != "s" { + t.Fatal("unexpected value") + } +} + +func TestResponseUnmarshalJSONNoBody(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody([]byte{})) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !resp.HasStatusCode(http.StatusOK) { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if err := resp.UnmarshalAsJSON(nil); err != nil { + t.Fatalf("unexpected error unmarshalling: %v", err) + } +} + +func TestResponseUnmarshalXMLNoBody(t *testing.T) { + srv, close := mock.NewServer() + defer close() + srv.SetResponse(mock.WithBody([]byte{})) + pl := NewPipeline(srv, NewTelemetryPolicy(TelemetryOptions{})) + resp, err := pl.Do(context.Background(), NewRequest(http.MethodGet, srv.URL())) + if err != nil { + t.Fatalf("unexpected error: %v", err) + } + if !resp.HasStatusCode(http.StatusOK) { + t.Fatalf("unexpected status code: %d", resp.StatusCode) + } + if err := resp.UnmarshalAsXML(nil); err != nil { + t.Fatalf("unexpected error unmarshalling: %v", err) + } +} diff --git a/sdk/azcore/transport_default_http_client.go b/sdk/azcore/transport_default_http_client.go new file mode 100644 index 000000000000..487ed9566d26 --- /dev/null +++ b/sdk/azcore/transport_default_http_client.go @@ -0,0 +1,40 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +import ( + "context" + "crypto/tls" + "net/http" +) + +var defaultHTTPClient *http.Client + +func init() { + defaultTransport := http.DefaultTransport.(*http.Transport) + transport := &http.Transport{ + Proxy: defaultTransport.Proxy, + DialContext: defaultTransport.DialContext, + MaxIdleConns: defaultTransport.MaxIdleConns, + IdleConnTimeout: defaultTransport.IdleConnTimeout, + TLSHandshakeTimeout: defaultTransport.TLSHandshakeTimeout, + ExpectContinueTimeout: defaultTransport.ExpectContinueTimeout, + TLSClientConfig: &tls.Config{ + MinVersion: tls.VersionTLS12, + }, + } + // TODO: in track 1 we created a cookiejar, do we need one here? make it an option? user-specified HTTP client policy? + defaultHTTPClient = &http.Client{ + Transport: transport, + } +} + +// DefaultHTTPClientTransport ... +func DefaultHTTPClientTransport() Transport { + return transportFunc(func(ctx context.Context, req *http.Request) (*http.Response, error) { + return defaultHTTPClient.Do(req.WithContext(ctx)) + }) +} diff --git a/sdk/azcore/version.go b/sdk/azcore/version.go new file mode 100644 index 000000000000..8d4493c648c8 --- /dev/null +++ b/sdk/azcore/version.go @@ -0,0 +1,14 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package azcore + +const ( + // UserAgent is the string to be used in the user agent string when making requests. + UserAgent = "azcore/" + Version + + // Version is the semantic version (see http://semver.org) of the pipeline package. + Version = "0.1.0" +) diff --git a/sdk/ci.yml b/sdk/ci.yml new file mode 100644 index 000000000000..dec76b72a543 --- /dev/null +++ b/sdk/ci.yml @@ -0,0 +1,80 @@ +trigger: + paths: + include: + - sdk/ + +pr: + paths: + include: + - sdk/ + +jobs: + - job: Build_Test + strategy: + matrix: + Linux_Go113: + vm.image: 'ubuntu-18.04' + go.version: '1.13' + GOROOT: '/usr/local/go$(go.version)' + + pool: + vmImage: $(vm.image) + + variables: + GOPATH: '$(system.defaultWorkingDirectory)/work' + sdkPath: '$(GOPATH)/src/github.com/$(build.repository.name)' + + steps: + - script: | + set -e + mkdir -p '$(GOPATH)/bin' + mkdir -p '$(sdkPath)' + shopt -s dotglob extglob + mv !(work) '$(sdkPath)' + echo '##vso[task.prependpath]$(GOROOT)/bin' + echo '##vso[task.prependpath]$(GOPATH)/bin' + displayName: 'Create Go Workspace' + - script: | + set -e + go version + go get github.com/jstemmer/go-junit-report + go get github.com/axw/gocov/gocov + go get github.com/AlekSi/gocov-xml + go get -u github.com/matm/gocov-html + workingDirectory: '$(sdkPath)' + displayName: 'Install Dependencies' + - script: go vet $(go list ./sdk/...) + workingDirectory: '$(sdkPath)' + displayName: 'Vet' + - script: go build -v $(go list ./sdk/...) + workingDirectory: '$(sdkPath)' + displayName: 'Build' + - script: | + go test -race -v -coverprofile=coverage.txt -covermode atomic ./sdk/... 2>&1 | go-junit-report > report.xml + gocov convert coverage.txt > coverage.json + gocov-xml < coverage.json > coverage.xml + gocov-html < coverage.json > coverage.html + workingDirectory: '$(sdkPath)' + displayName: 'Run Tests' + - script: grep -L -r --include \*.go -P "Copyright (\d{4}|\(c\)) Microsoft" ./sdk | tee >&2 + workingDirectory: '$(sdkPath)' + displayName: 'Copyright Header Check' + failOnStderr: true + condition: succeededOrFailed() + - script: gofmt -s -l -w $(find ./sdk -name '*.go' -print) >&2 + workingDirectory: '$(sdkPath)' + displayName: 'Format Check' + failOnStderr: true + condition: succeededOrFailed() + + - task: PublishTestResults@2 + inputs: + testRunner: JUnit + testResultsFiles: $(sdkPath)/report.xml + failTaskOnFailedTests: true + + - task: PublishCodeCoverageResults@1 + inputs: + codeCoverageTool: Cobertura + summaryFileLocation: $(sdkPath)/coverage.xml + additionalCodeCoverageFiles: $(sdkPath)/coverage.html diff --git a/sdk/internal/atomic/atomic.go b/sdk/internal/atomic/atomic.go new file mode 100644 index 000000000000..781dbeca94af --- /dev/null +++ b/sdk/internal/atomic/atomic.go @@ -0,0 +1,78 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package atomic + +import ( + "sync/atomic" + "time" +) + +// Int64 is an atomic wrapper around an int64. +type Int64 int64 + +// NewInt64 creates a new Int64. +func NewInt64(i int64) Int64 { + return Int64(i) +} + +// CAS is an atomic compare-and-swap. +func (i *Int64) CAS(old, new int64) bool { + return atomic.CompareAndSwapInt64((*int64)(i), old, new) +} + +// Load atomically loads the value. +func (i *Int64) Load() int64 { + return atomic.LoadInt64((*int64)(i)) +} + +// Store atomically stores the value. +func (i *Int64) Store(v int64) { + atomic.StoreInt64((*int64)(i), v) +} + +// String is an atomic wrapper around a string. +type String struct { + v atomic.Value +} + +// NewString creats a new String. +func NewString(s string) *String { + ss := String{} + ss.v.Store(s) + return &ss +} + +// Load atomically loads the string. +func (s *String) Load() string { + return s.v.Load().(string) +} + +// Store atomically stores the string. +func (s *String) Store(v string) { + s.v.Store(v) +} + +// Time is an atomic wrapper around a time.Time. +type Time struct { + v atomic.Value +} + +// NewTime creates a new Time. +func NewTime(t time.Time) *Time { + tt := Time{} + tt.v.Store(t) + return &tt +} + +// Load atomically loads the time.Time. +func (t *Time) Load() time.Time { + return t.v.Load().(time.Time) +} + +// Store atomically stores the time.Time. +func (t *Time) Store(v time.Time) { + t.v.Store(v) +} diff --git a/sdk/internal/go.mod b/sdk/internal/go.mod new file mode 100644 index 000000000000..1bb024518b8c --- /dev/null +++ b/sdk/internal/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/sdk/internal + +go 1.13 diff --git a/sdk/internal/mock/mock.go b/sdk/internal/mock/mock.go new file mode 100644 index 000000000000..d409860389ca --- /dev/null +++ b/sdk/internal/mock/mock.go @@ -0,0 +1,207 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package mock + +import ( + "context" + "net/http" + "net/http/httptest" + "net/url" +) + +// Server is a wrapper around an httptest.Server. +// The serving of requests is not safe for concurrent use +// which is ok for right now as each test creates is own +// server and doesn't create additional go routines. +type Server struct { + srv *httptest.Server + + // static is the static response, if this is not nil it's always returned. + static *mockResponse + + // resp is the queue of responses. each response is taken from the front. + resp []mockResponse + + // count tracks the number of requests that have been made. + count int +} + +// NewServer creates a new Server object. +// The returned close func must be called when the server is no longer needed. +func NewServer() (*Server, func()) { + s := Server{} + s.srv = httptest.NewServer(http.HandlerFunc(s.serveHTTP)) + return &s, func() { s.srv.Close() } +} + +// NewTLSServer creates a new Server object. +// The returned close func must be called when the server is no longer needed. +func NewTLSServer() (*Server, func()) { + s := Server{} + s.srv = httptest.NewTLSServer(http.HandlerFunc(s.serveHTTP)) + return &s, func() { s.srv.Close() } +} + +// returns true if the next response is an error response +func (s *Server) isErrorResp() bool { + if s.static == nil && len(s.resp) == 0 { + panic("no more responses") + } + // always favor static response + if s.static != nil && s.static.err != nil { + return true + } + if len(s.resp) == 0 { + return false + } + return s.resp[0].err != nil +} + +// returns the static response or the next response in the queue +func (s *Server) getResponse() mockResponse { + if s.static == nil && len(s.resp) == 0 { + panic("no more responses") + } + // always favor static response + if s.static != nil { + return *s.static + } + // pop off first response and return it + resp := s.resp[0] + s.resp = s.resp[1:] + return resp +} + +// URL returns the endpoint of the test server in URL format. +func (s *Server) URL() url.URL { + u, err := url.Parse(s.srv.URL) + if err != nil { + panic(err) + } + return *u +} + +// Do implements the azcore.Transport interface on Server. +// Calling this when the response queue is empty and no static +// response has been set will cause a panic. +func (s *Server) Do(ctx context.Context, req *http.Request) (*http.Response, error) { + s.count++ + // error responses are returned here + if s.isErrorResp() { + resp := s.getResponse() + return nil, resp.err + } + return s.srv.Client().Do(req.WithContext(ctx)) +} + +func (s *Server) serveHTTP(w http.ResponseWriter, req *http.Request) { + s.getResponse().write(w) +} + +// Requests returns the number of times an HTTP request was made. +func (s *Server) Requests() int { + return s.count +} + +// AppendError appends the error to the end of the response queue. +func (s *Server) AppendError(err error) { + s.resp = append(s.resp, mockResponse{err: err}) +} + +// RepeatError appends the error n number of times to the end of the response queue. +func (s *Server) RepeatError(n int, err error) { + for i := 0; i < n; i++ { + s.AppendError(err) + } +} + +// SetError indicates the same error should always be returned. +// Any responses set via other methods will be ignored. +func (s *Server) SetError(err error) { + s.static = &mockResponse{err: err} +} + +// AppendResponse appends the response to the end of the response queue. +// If no options are provided the default response is an http.StatusOK. +func (s *Server) AppendResponse(opts ...ResponseOption) { + mr := mockResponse{code: http.StatusOK} + for _, o := range opts { + o.apply(&mr) + } + s.resp = append(s.resp, mr) +} + +// RepeatResponse appends the response n number of times to the end of the response queue. +// If no options are provided the default response is an http.StatusOK. +func (s *Server) RepeatResponse(n int, opts ...ResponseOption) { + for i := 0; i < n; i++ { + s.AppendResponse(opts...) + } +} + +// SetResponse indicates the same response should always be returned. +// Any responses set via other methods will be ignored. +// If no options are provided the default response is an http.StatusOK. +func (s *Server) SetResponse(opts ...ResponseOption) { + mr := mockResponse{code: http.StatusOK} + for _, o := range opts { + o.apply(&mr) + } + s.static = &mr +} + +// ResponseOption is an abstraction for configuring a mock HTTP response. +type ResponseOption interface { + apply(mr *mockResponse) +} + +type fnRespOpt func(*mockResponse) + +func (fn fnRespOpt) apply(mr *mockResponse) { + fn(mr) +} + +type mockResponse struct { + code int + body []byte + headers http.Header + err error +} + +func (mr mockResponse) write(w http.ResponseWriter) { + w.WriteHeader(mr.code) + if mr.body != nil { + w.Write(mr.body) + } + if len(mr.headers) > 0 { + for k, v := range mr.headers { + for _, vv := range v { + w.Header().Add(k, vv) + } + } + } +} + +// WithStatusCode sets the HTTP response's status code to the specified value. +func WithStatusCode(c int) ResponseOption { + return fnRespOpt(func(mr *mockResponse) { + mr.code = c + }) +} + +// WithBody sets the HTTP response's body to the specified value. +func WithBody(b []byte) ResponseOption { + return fnRespOpt(func(mr *mockResponse) { + mr.body = b + }) +} + +// WithHeader adds the specified header and value to the HTTP response. +func WithHeader(k, v string) ResponseOption { + return fnRespOpt(func(mr *mockResponse) { + mr.headers.Add(k, v) + }) +} diff --git a/sdk/internal/uuid/uuid.go b/sdk/internal/uuid/uuid.go new file mode 100644 index 000000000000..4b288d81fecd --- /dev/null +++ b/sdk/internal/uuid/uuid.go @@ -0,0 +1,89 @@ +// +build go1.13 + +// Copyright (c) Microsoft Corporation. All rights reserved. +// Licensed under the MIT License. + +package uuid + +import ( + "fmt" + "math/rand" + "strconv" + "time" +) + +// The UUID reserved variants. +const ( + reservedNCS byte = 0x80 + reservedRFC4122 byte = 0x40 + reservedMicrosoft byte = 0x20 + reservedFuture byte = 0x00 +) + +func init() { + rand.Seed(time.Now().Unix()) +} + +// A UUID representation compliant with specification in RFC 4122 document. +type UUID [16]byte + +// New returns a new uuid using RFC 4122 algorithm. +func New() UUID { + u := UUID{} + // Set all bits to randomly (or pseudo-randomly) chosen values. + // math/rand.Read() is no-fail so we omit any error checking. + // NOTE: this takes a process-wide lock + rand.Read(u[:]) + u[8] = (u[8] | reservedRFC4122) & 0x7F // u.setVariant(ReservedRFC4122) + + var version byte = 4 + u[6] = (u[6] & 0xF) | (version << 4) // u.setVersion(4) + return u +} + +// String returns an unparsed version of the generated UUID sequence. +func (u UUID) String() string { + return fmt.Sprintf("%x-%x-%x-%x-%x", u[0:4], u[4:6], u[6:8], u[8:10], u[10:]) +} + +// Parse parses a string formatted as "003020100-0504-0706-0809-0a0b0c0d0e0f" +// or "{03020100-0504-0706-0809-0a0b0c0d0e0f}" into a UUID. +func Parse(uuidStr string) UUID { + char := func(hexString string) byte { + i, _ := strconv.ParseUint(hexString, 16, 8) + return byte(i) + } + if uuidStr[0] == '{' { + uuidStr = uuidStr[1:] // Skip over the '{' + } + // 03020100 - 05 04 - 07 06 - 08 09 - 0a 0b 0c 0d 0e 0f + // 1 11 1 11 11 1 12 22 2 22 22 22 33 33 33 + // 01234567 8 90 12 3 45 67 8 90 12 3 45 67 89 01 23 45 + uuidVal := UUID{ + char(uuidStr[0:2]), + char(uuidStr[2:4]), + char(uuidStr[4:6]), + char(uuidStr[6:8]), + + char(uuidStr[9:11]), + char(uuidStr[11:13]), + + char(uuidStr[14:16]), + char(uuidStr[16:18]), + + char(uuidStr[19:21]), + char(uuidStr[21:23]), + + char(uuidStr[24:26]), + char(uuidStr[26:28]), + char(uuidStr[28:30]), + char(uuidStr[30:32]), + char(uuidStr[32:34]), + char(uuidStr[34:36]), + } + return uuidVal +} + +func (u UUID) bytes() []byte { + return u[:] +} diff --git a/services/containerservice/mgmt/2017-07-01/containerservice/containerservices.go b/services/containerservice/mgmt/2017-07-01/containerservice/containerservices.go index bc45c720e45e..eac7c50e45ef 100644 --- a/services/containerservice/mgmt/2017-07-01/containerservice/containerservices.go +++ b/services/containerservice/mgmt/2017-07-01/containerservice/containerservices.go @@ -60,35 +60,34 @@ func (client ContainerServicesClient) CreateOrUpdate(ctx context.Context, resour } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, - }}, - {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Pattern, Rule: `^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$`, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, - }}, - {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - }}}}}); err != nil { + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, + }}, + {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ContainerServicesClient", "CreateOrUpdate", err.Error()) } @@ -120,6 +119,9 @@ func (client ContainerServicesClient) CreateOrUpdatePreparer(ctx context.Context "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2017-07-01/containerservice/models.go b/services/containerservice/mgmt/2017-07-01/containerservice/models.go index 25571b4486b1..5897a21ccf53 100644 --- a/services/containerservice/mgmt/2017-07-01/containerservice/models.go +++ b/services/containerservice/mgmt/2017-07-01/containerservice/models.go @@ -464,11 +464,48 @@ type AgentPoolProfile struct { OsType OSType `json:"osType,omitempty"` } +// Componentsschemascontainerserviceallof1 ... +type Componentsschemascontainerserviceallof1 struct { + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemascontainerserviceallof1. +func (c Componentsschemascontainerserviceallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.Properties != nil { + objectMap["properties"] = c.Properties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemascontainerserviceallof1 struct. +func (c *Componentsschemascontainerserviceallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + c.Properties = &properties + } + } + } + + return nil +} + // ContainerService container service. type ContainerService struct { autorest.Response `json:"-"` - // Properties - Properties of the container service. - *Properties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -479,20 +516,22 @@ type ContainerService struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ContainerService. func (cs ContainerService) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if cs.Properties != nil { - objectMap["properties"] = cs.Properties - } if cs.Location != nil { objectMap["location"] = cs.Location } if cs.Tags != nil { objectMap["tags"] = cs.Tags } + if cs.Properties != nil { + objectMap["properties"] = cs.Properties + } return json.Marshal(objectMap) } @@ -505,15 +544,6 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var properties Properties - err = json.Unmarshal(*v, &properties) - if err != nil { - return err - } - cs.Properties = &properties - } case "id": if v != nil { var ID string @@ -559,6 +589,15 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } cs.Tags = tags } + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + cs.Properties = &properties + } } } diff --git a/services/containerservice/mgmt/2017-08-31/containerservice/client.go b/services/containerservice/mgmt/2017-08-31/containerservice/client.go index 09a36def717c..d27853be33c0 100644 --- a/services/containerservice/mgmt/2017-08-31/containerservice/client.go +++ b/services/containerservice/mgmt/2017-08-31/containerservice/client.go @@ -1,4 +1,4 @@ -// Package containerservice implements the Azure ARM Containerservice service API version . +// Package containerservice implements the Azure ARM Containerservice service API version 2017-07-01. // // The Container Service Client. package containerservice diff --git a/services/containerservice/mgmt/2017-08-31/containerservice/containerservices.go b/services/containerservice/mgmt/2017-08-31/containerservice/containerservices.go index bc45c720e45e..eac7c50e45ef 100644 --- a/services/containerservice/mgmt/2017-08-31/containerservice/containerservices.go +++ b/services/containerservice/mgmt/2017-08-31/containerservice/containerservices.go @@ -60,35 +60,34 @@ func (client ContainerServicesClient) CreateOrUpdate(ctx context.Context, resour } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, - }}, - {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Pattern, Rule: `^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$`, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, - }}, - {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - }}}}}); err != nil { + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, + }}, + {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ContainerServicesClient", "CreateOrUpdate", err.Error()) } @@ -120,6 +119,9 @@ func (client ContainerServicesClient) CreateOrUpdatePreparer(ctx context.Context "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2017-08-31/containerservice/managedclusters.go b/services/containerservice/mgmt/2017-08-31/containerservice/managedclusters.go index 77930638e564..4d0edae44070 100644 --- a/services/containerservice/mgmt/2017-08-31/containerservice/managedclusters.go +++ b/services/containerservice/mgmt/2017-08-31/containerservice/managedclusters.go @@ -60,21 +60,21 @@ func (client ManagedClustersClient) CreateOrUpdate(ctx context.Context, resource } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, }}, - }}}}}); err != nil { + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ManagedClustersClient", "CreateOrUpdate", err.Error()) } @@ -106,6 +106,9 @@ func (client ManagedClustersClient) CreateOrUpdatePreparer(ctx context.Context, "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2017-08-31/containerservice/models.go b/services/containerservice/mgmt/2017-08-31/containerservice/models.go index 93024ca0850d..d447755ac9b9 100644 --- a/services/containerservice/mgmt/2017-08-31/containerservice/models.go +++ b/services/containerservice/mgmt/2017-08-31/containerservice/models.go @@ -470,11 +470,126 @@ type AgentPoolProfile struct { OsType OSType `json:"osType,omitempty"` } +// Componentsschemascontainerserviceallof1 ... +type Componentsschemascontainerserviceallof1 struct { + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemascontainerserviceallof1. +func (c Componentsschemascontainerserviceallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.Properties != nil { + objectMap["properties"] = c.Properties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemascontainerserviceallof1 struct. +func (c *Componentsschemascontainerserviceallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + c.Properties = &properties + } + } + } + + return nil +} + +// Componentsschemasmanagedclusteraccessprofileallof1 ... +type Componentsschemasmanagedclusteraccessprofileallof1 struct { + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusteraccessprofileallof1. +func (c Componentsschemasmanagedclusteraccessprofileallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.AccessProfile != nil { + objectMap["properties"] = c.AccessProfile + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusteraccessprofileallof1 struct. +func (c *Componentsschemasmanagedclusteraccessprofileallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + c.AccessProfile = &accessProfile + } + } + } + + return nil +} + +// Componentsschemasmanagedclusterallof1 ... +type Componentsschemasmanagedclusterallof1 struct { + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusterallof1. +func (c Componentsschemasmanagedclusterallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.ManagedClusterProperties != nil { + objectMap["properties"] = c.ManagedClusterProperties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusterallof1 struct. +func (c *Componentsschemasmanagedclusterallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + c.ManagedClusterProperties = &managedClusterProperties + } + } + } + + return nil +} + // ContainerService container service. type ContainerService struct { autorest.Response `json:"-"` - // Properties - Properties of the container service. - *Properties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -485,20 +600,22 @@ type ContainerService struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ContainerService. func (cs ContainerService) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if cs.Properties != nil { - objectMap["properties"] = cs.Properties - } if cs.Location != nil { objectMap["location"] = cs.Location } if cs.Tags != nil { objectMap["tags"] = cs.Tags } + if cs.Properties != nil { + objectMap["properties"] = cs.Properties + } return json.Marshal(objectMap) } @@ -511,15 +628,6 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var properties Properties - err = json.Unmarshal(*v, &properties) - if err != nil { - return err - } - cs.Properties = &properties - } case "id": if v != nil { var ID string @@ -565,6 +673,15 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } cs.Tags = tags } + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + cs.Properties = &properties + } } } @@ -802,8 +919,6 @@ func NewListResultPage(getNextPage func(context.Context, ListResult) (ListResult // ManagedCluster managed cluster. type ManagedCluster struct { autorest.Response `json:"-"` - // ManagedClusterProperties - Properties of a managed cluster. - *ManagedClusterProperties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -814,20 +929,22 @@ type ManagedCluster struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedCluster. func (mc ManagedCluster) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mc.ManagedClusterProperties != nil { - objectMap["properties"] = mc.ManagedClusterProperties - } if mc.Location != nil { objectMap["location"] = mc.Location } if mc.Tags != nil { objectMap["tags"] = mc.Tags } + if mc.ManagedClusterProperties != nil { + objectMap["properties"] = mc.ManagedClusterProperties + } return json.Marshal(objectMap) } @@ -840,15 +957,6 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var managedClusterProperties ManagedClusterProperties - err = json.Unmarshal(*v, &managedClusterProperties) - if err != nil { - return err - } - mc.ManagedClusterProperties = &managedClusterProperties - } case "id": if v != nil { var ID string @@ -894,6 +1002,15 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } mc.Tags = tags } + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + mc.ManagedClusterProperties = &managedClusterProperties + } } } @@ -903,8 +1020,6 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { // ManagedClusterAccessProfile managed cluster Access Profile. type ManagedClusterAccessProfile struct { autorest.Response `json:"-"` - // AccessProfile - AccessProfile of a managed cluster. - *AccessProfile `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -915,20 +1030,22 @@ type ManagedClusterAccessProfile struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedClusterAccessProfile. func (mcap ManagedClusterAccessProfile) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mcap.AccessProfile != nil { - objectMap["properties"] = mcap.AccessProfile - } if mcap.Location != nil { objectMap["location"] = mcap.Location } if mcap.Tags != nil { objectMap["tags"] = mcap.Tags } + if mcap.AccessProfile != nil { + objectMap["properties"] = mcap.AccessProfile + } return json.Marshal(objectMap) } @@ -941,15 +1058,6 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var accessProfile AccessProfile - err = json.Unmarshal(*v, &accessProfile) - if err != nil { - return err - } - mcap.AccessProfile = &accessProfile - } case "id": if v != nil { var ID string @@ -995,6 +1103,15 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } mcap.Tags = tags } + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + mcap.AccessProfile = &accessProfile + } } } diff --git a/services/containerservice/mgmt/2017-08-31/containerservice/version.go b/services/containerservice/mgmt/2017-08-31/containerservice/version.go index d3bc933a65e4..652b5b209e37 100644 --- a/services/containerservice/mgmt/2017-08-31/containerservice/version.go +++ b/services/containerservice/mgmt/2017-08-31/containerservice/version.go @@ -21,7 +21,7 @@ import "github.com/Azure/azure-sdk-for-go/version" // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return "Azure-SDK-For-Go/" + version.Number + " containerservice/2017-08-31" + return "Azure-SDK-For-Go/" + version.Number + " containerservice/2017-07-01" } // Version returns the semantic version (see http://semver.org) of the client. diff --git a/services/containerservice/mgmt/2017-09-30/containerservice/client.go b/services/containerservice/mgmt/2017-09-30/containerservice/client.go index 09a36def717c..d27853be33c0 100644 --- a/services/containerservice/mgmt/2017-09-30/containerservice/client.go +++ b/services/containerservice/mgmt/2017-09-30/containerservice/client.go @@ -1,4 +1,4 @@ -// Package containerservice implements the Azure ARM Containerservice service API version . +// Package containerservice implements the Azure ARM Containerservice service API version 2017-07-01. // // The Container Service Client. package containerservice diff --git a/services/containerservice/mgmt/2017-09-30/containerservice/containerservices.go b/services/containerservice/mgmt/2017-09-30/containerservice/containerservices.go index c3e6fa6ad1ed..eada8b386a36 100644 --- a/services/containerservice/mgmt/2017-09-30/containerservice/containerservices.go +++ b/services/containerservice/mgmt/2017-09-30/containerservice/containerservices.go @@ -60,35 +60,34 @@ func (client ContainerServicesClient) CreateOrUpdate(ctx context.Context, resour } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, - }}, - {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Pattern, Rule: `^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$`, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, - }}, - {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - }}}}}); err != nil { + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, + }}, + {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ContainerServicesClient", "CreateOrUpdate", err.Error()) } @@ -120,6 +119,9 @@ func (client ContainerServicesClient) CreateOrUpdatePreparer(ctx context.Context "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2017-09-30/containerservice/managedclusters.go b/services/containerservice/mgmt/2017-09-30/containerservice/managedclusters.go index 77930638e564..4d0edae44070 100644 --- a/services/containerservice/mgmt/2017-09-30/containerservice/managedclusters.go +++ b/services/containerservice/mgmt/2017-09-30/containerservice/managedclusters.go @@ -60,21 +60,21 @@ func (client ManagedClustersClient) CreateOrUpdate(ctx context.Context, resource } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, }}, - }}}}}); err != nil { + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ManagedClustersClient", "CreateOrUpdate", err.Error()) } @@ -106,6 +106,9 @@ func (client ManagedClustersClient) CreateOrUpdatePreparer(ctx context.Context, "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2017-09-30/containerservice/models.go b/services/containerservice/mgmt/2017-09-30/containerservice/models.go index 932ce31f0f94..091593ba7e82 100644 --- a/services/containerservice/mgmt/2017-09-30/containerservice/models.go +++ b/services/containerservice/mgmt/2017-09-30/containerservice/models.go @@ -470,11 +470,126 @@ type AgentPoolProfile struct { OsType OSType `json:"osType,omitempty"` } +// Componentsschemascontainerserviceallof1 ... +type Componentsschemascontainerserviceallof1 struct { + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemascontainerserviceallof1. +func (c Componentsschemascontainerserviceallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.Properties != nil { + objectMap["properties"] = c.Properties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemascontainerserviceallof1 struct. +func (c *Componentsschemascontainerserviceallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + c.Properties = &properties + } + } + } + + return nil +} + +// Componentsschemasmanagedclusteraccessprofileallof1 ... +type Componentsschemasmanagedclusteraccessprofileallof1 struct { + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusteraccessprofileallof1. +func (c Componentsschemasmanagedclusteraccessprofileallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.AccessProfile != nil { + objectMap["properties"] = c.AccessProfile + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusteraccessprofileallof1 struct. +func (c *Componentsschemasmanagedclusteraccessprofileallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + c.AccessProfile = &accessProfile + } + } + } + + return nil +} + +// Componentsschemasmanagedclusterallof1 ... +type Componentsschemasmanagedclusterallof1 struct { + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusterallof1. +func (c Componentsschemasmanagedclusterallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.ManagedClusterProperties != nil { + objectMap["properties"] = c.ManagedClusterProperties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusterallof1 struct. +func (c *Componentsschemasmanagedclusterallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + c.ManagedClusterProperties = &managedClusterProperties + } + } + } + + return nil +} + // ContainerService container service. type ContainerService struct { autorest.Response `json:"-"` - // Properties - Properties of the container service. - *Properties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -485,20 +600,22 @@ type ContainerService struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ContainerService. func (cs ContainerService) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if cs.Properties != nil { - objectMap["properties"] = cs.Properties - } if cs.Location != nil { objectMap["location"] = cs.Location } if cs.Tags != nil { objectMap["tags"] = cs.Tags } + if cs.Properties != nil { + objectMap["properties"] = cs.Properties + } return json.Marshal(objectMap) } @@ -511,15 +628,6 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var properties Properties - err = json.Unmarshal(*v, &properties) - if err != nil { - return err - } - cs.Properties = &properties - } case "id": if v != nil { var ID string @@ -565,6 +673,15 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } cs.Tags = tags } + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + cs.Properties = &properties + } } } @@ -802,8 +919,6 @@ func NewListResultPage(getNextPage func(context.Context, ListResult) (ListResult // ManagedCluster managed cluster. type ManagedCluster struct { autorest.Response `json:"-"` - // ManagedClusterProperties - Properties of a managed cluster. - *ManagedClusterProperties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -814,20 +929,22 @@ type ManagedCluster struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedCluster. func (mc ManagedCluster) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mc.ManagedClusterProperties != nil { - objectMap["properties"] = mc.ManagedClusterProperties - } if mc.Location != nil { objectMap["location"] = mc.Location } if mc.Tags != nil { objectMap["tags"] = mc.Tags } + if mc.ManagedClusterProperties != nil { + objectMap["properties"] = mc.ManagedClusterProperties + } return json.Marshal(objectMap) } @@ -840,15 +957,6 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var managedClusterProperties ManagedClusterProperties - err = json.Unmarshal(*v, &managedClusterProperties) - if err != nil { - return err - } - mc.ManagedClusterProperties = &managedClusterProperties - } case "id": if v != nil { var ID string @@ -894,6 +1002,15 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } mc.Tags = tags } + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + mc.ManagedClusterProperties = &managedClusterProperties + } } } @@ -903,8 +1020,6 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { // ManagedClusterAccessProfile managed cluster Access Profile. type ManagedClusterAccessProfile struct { autorest.Response `json:"-"` - // AccessProfile - AccessProfile of a managed cluster. - *AccessProfile `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -915,20 +1030,22 @@ type ManagedClusterAccessProfile struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedClusterAccessProfile. func (mcap ManagedClusterAccessProfile) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mcap.AccessProfile != nil { - objectMap["properties"] = mcap.AccessProfile - } if mcap.Location != nil { objectMap["location"] = mcap.Location } if mcap.Tags != nil { objectMap["tags"] = mcap.Tags } + if mcap.AccessProfile != nil { + objectMap["properties"] = mcap.AccessProfile + } return json.Marshal(objectMap) } @@ -941,15 +1058,6 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var accessProfile AccessProfile - err = json.Unmarshal(*v, &accessProfile) - if err != nil { - return err - } - mcap.AccessProfile = &accessProfile - } case "id": if v != nil { var ID string @@ -995,6 +1103,15 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } mcap.Tags = tags } + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + mcap.AccessProfile = &accessProfile + } } } diff --git a/services/containerservice/mgmt/2017-09-30/containerservice/version.go b/services/containerservice/mgmt/2017-09-30/containerservice/version.go index 550a9a973280..652b5b209e37 100644 --- a/services/containerservice/mgmt/2017-09-30/containerservice/version.go +++ b/services/containerservice/mgmt/2017-09-30/containerservice/version.go @@ -21,7 +21,7 @@ import "github.com/Azure/azure-sdk-for-go/version" // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return "Azure-SDK-For-Go/" + version.Number + " containerservice/2017-09-30" + return "Azure-SDK-For-Go/" + version.Number + " containerservice/2017-07-01" } // Version returns the semantic version (see http://semver.org) of the client. diff --git a/services/containerservice/mgmt/2018-03-31/containerservice/client.go b/services/containerservice/mgmt/2018-03-31/containerservice/client.go index 09a36def717c..d27853be33c0 100644 --- a/services/containerservice/mgmt/2018-03-31/containerservice/client.go +++ b/services/containerservice/mgmt/2018-03-31/containerservice/client.go @@ -1,4 +1,4 @@ -// Package containerservice implements the Azure ARM Containerservice service API version . +// Package containerservice implements the Azure ARM Containerservice service API version 2017-07-01. // // The Container Service Client. package containerservice diff --git a/services/containerservice/mgmt/2018-03-31/containerservice/containerservices.go b/services/containerservice/mgmt/2018-03-31/containerservice/containerservices.go index c3e6fa6ad1ed..eada8b386a36 100644 --- a/services/containerservice/mgmt/2018-03-31/containerservice/containerservices.go +++ b/services/containerservice/mgmt/2018-03-31/containerservice/containerservices.go @@ -60,35 +60,34 @@ func (client ContainerServicesClient) CreateOrUpdate(ctx context.Context, resour } if err := validation.Validate([]validation.Validation{ {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.Properties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, - }}, - }}, - {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Pattern, Rule: `^[a-zA-Z0-9]+([._]?[a-zA-Z0-9]+)*$`, Chain: nil}}}, - {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, - }}, - {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - }}}}}); err != nil { + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.OrchestratorProfile", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.CustomProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.CustomProfile.Orchestrator", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.VaultID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.ServicePrincipalProfile.KeyVaultSecretRef.SecretName", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}, + {Target: "parameters.Properties.MasterProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.MasterProfile.DNSPrefix", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.Properties.WindowsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.WindowsProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.WindowsProfile.AdminPassword", Name: validation.Null, Rule: true, Chain: nil}, + }}, + {Target: "parameters.Properties.LinuxProfile", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.Properties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + {Target: "parameters.Properties.DiagnosticsProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.Properties.DiagnosticsProfile.VMDiagnostics.Enabled", Name: validation.Null, Rule: true, Chain: nil}}}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ContainerServicesClient", "CreateOrUpdate", err.Error()) } @@ -120,6 +119,9 @@ func (client ContainerServicesClient) CreateOrUpdatePreparer(ctx context.Context "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2018-03-31/containerservice/managedclusters.go b/services/containerservice/mgmt/2018-03-31/containerservice/managedclusters.go index de04ca199b84..957f65042304 100644 --- a/services/containerservice/mgmt/2018-03-31/containerservice/managedclusters.go +++ b/services/containerservice/mgmt/2018-03-31/containerservice/managedclusters.go @@ -62,30 +62,20 @@ func (client ManagedClustersClient) CreateOrUpdate(ctx context.Context, resource {TargetValue: resourceGroupName, Constraints: []validation.Constraint{{Target: "resourceGroupName", Name: validation.MinLength, Rule: 1, Chain: nil}}}, {TargetValue: parameters, - Constraints: []validation.Constraint{{Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Pattern, Rule: `^[A-Za-z][-A-Za-z0-9_]*$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, - }}, - {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.NetworkProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.NetworkProfile.PodCidr", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.NetworkProfile.PodCidr", Name: validation.Pattern, Rule: `^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.NetworkProfile.ServiceCidr", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.NetworkProfile.ServiceCidr", Name: validation.Pattern, Rule: `^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.NetworkProfile.DNSServiceIP", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.NetworkProfile.DNSServiceIP", Name: validation.Pattern, Rule: `^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$`, Chain: nil}}}, - {Target: "parameters.ManagedClusterProperties.NetworkProfile.DockerBridgeCidr", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.NetworkProfile.DockerBridgeCidr", Name: validation.Pattern, Rule: `^([0-9]{1,3}\.){3}[0-9]{1,3}(\/([0-9]|[1-2][0-9]|3[0-2]))?$`, Chain: nil}}}, + Constraints: []validation.Constraint{{Target: "parameters.Location", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.AdminUsername", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH", Name: validation.Null, Rule: true, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.LinuxProfile.SSH.PublicKeys", Name: validation.Null, Rule: true, Chain: nil}}}, }}, - {Target: "parameters.ManagedClusterProperties.AadProfile", Name: validation.Null, Rule: false, - Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.AadProfile.ClientAppID", Name: validation.Null, Rule: true, Chain: nil}, - {Target: "parameters.ManagedClusterProperties.AadProfile.ServerAppID", Name: validation.Null, Rule: true, Chain: nil}, - }}, - }}}}}); err != nil { + {Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.ServicePrincipalProfile.ClientID", Name: validation.Null, Rule: true, Chain: nil}}}, + {Target: "parameters.ManagedClusterProperties.AadProfile", Name: validation.Null, Rule: false, + Chain: []validation.Constraint{{Target: "parameters.ManagedClusterProperties.AadProfile.ClientAppID", Name: validation.Null, Rule: true, Chain: nil}, + {Target: "parameters.ManagedClusterProperties.AadProfile.ServerAppID", Name: validation.Null, Rule: true, Chain: nil}, + }}, + }}}}}); err != nil { return result, validation.NewError("containerservice.ManagedClustersClient", "CreateOrUpdate", err.Error()) } @@ -117,6 +107,9 @@ func (client ManagedClustersClient) CreateOrUpdatePreparer(ctx context.Context, "api-version": APIVersion, } + parameters.ID = nil + parameters.Name = nil + parameters.Type = nil preparer := autorest.CreatePreparer( autorest.AsContentType("application/json; charset=utf-8"), autorest.AsPut(), diff --git a/services/containerservice/mgmt/2018-03-31/containerservice/models.go b/services/containerservice/mgmt/2018-03-31/containerservice/models.go index 11e2f34d3c27..812def486f9b 100644 --- a/services/containerservice/mgmt/2018-03-31/containerservice/models.go +++ b/services/containerservice/mgmt/2018-03-31/containerservice/models.go @@ -498,11 +498,126 @@ type AgentPoolProfile struct { OsType OSType `json:"osType,omitempty"` } +// Componentsschemascontainerserviceallof1 ... +type Componentsschemascontainerserviceallof1 struct { + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemascontainerserviceallof1. +func (c Componentsschemascontainerserviceallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.Properties != nil { + objectMap["properties"] = c.Properties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemascontainerserviceallof1 struct. +func (c *Componentsschemascontainerserviceallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + c.Properties = &properties + } + } + } + + return nil +} + +// Componentsschemasmanagedclusteraccessprofileallof1 ... +type Componentsschemasmanagedclusteraccessprofileallof1 struct { + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusteraccessprofileallof1. +func (c Componentsschemasmanagedclusteraccessprofileallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.AccessProfile != nil { + objectMap["properties"] = c.AccessProfile + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusteraccessprofileallof1 struct. +func (c *Componentsschemasmanagedclusteraccessprofileallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + c.AccessProfile = &accessProfile + } + } + } + + return nil +} + +// Componentsschemasmanagedclusterallof1 ... +type Componentsschemasmanagedclusterallof1 struct { + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` +} + +// MarshalJSON is the custom marshaler for Componentsschemasmanagedclusterallof1. +func (c Componentsschemasmanagedclusterallof1) MarshalJSON() ([]byte, error) { + objectMap := make(map[string]interface{}) + if c.ManagedClusterProperties != nil { + objectMap["properties"] = c.ManagedClusterProperties + } + return json.Marshal(objectMap) +} + +// UnmarshalJSON is the custom unmarshaler for Componentsschemasmanagedclusterallof1 struct. +func (c *Componentsschemasmanagedclusterallof1) UnmarshalJSON(body []byte) error { + var m map[string]*json.RawMessage + err := json.Unmarshal(body, &m) + if err != nil { + return err + } + for k, v := range m { + switch k { + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + c.ManagedClusterProperties = &managedClusterProperties + } + } + } + + return nil +} + // ContainerService container service. type ContainerService struct { autorest.Response `json:"-"` - // Properties - Properties of the container service. - *Properties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -513,20 +628,22 @@ type ContainerService struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // Properties - Properties of the container service. + *Properties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ContainerService. func (cs ContainerService) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if cs.Properties != nil { - objectMap["properties"] = cs.Properties - } if cs.Location != nil { objectMap["location"] = cs.Location } if cs.Tags != nil { objectMap["tags"] = cs.Tags } + if cs.Properties != nil { + objectMap["properties"] = cs.Properties + } return json.Marshal(objectMap) } @@ -539,15 +656,6 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var properties Properties - err = json.Unmarshal(*v, &properties) - if err != nil { - return err - } - cs.Properties = &properties - } case "id": if v != nil { var ID string @@ -593,6 +701,15 @@ func (cs *ContainerService) UnmarshalJSON(body []byte) error { } cs.Tags = tags } + case "properties": + if v != nil { + var properties Properties + err = json.Unmarshal(*v, &properties) + if err != nil { + return err + } + cs.Properties = &properties + } } } @@ -845,8 +962,6 @@ func NewListResultPage(getNextPage func(context.Context, ListResult) (ListResult // ManagedCluster managed cluster. type ManagedCluster struct { autorest.Response `json:"-"` - // ManagedClusterProperties - Properties of a managed cluster. - *ManagedClusterProperties `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -857,20 +972,22 @@ type ManagedCluster struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // ManagedClusterProperties - Properties of a managed cluster. + *ManagedClusterProperties `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedCluster. func (mc ManagedCluster) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mc.ManagedClusterProperties != nil { - objectMap["properties"] = mc.ManagedClusterProperties - } if mc.Location != nil { objectMap["location"] = mc.Location } if mc.Tags != nil { objectMap["tags"] = mc.Tags } + if mc.ManagedClusterProperties != nil { + objectMap["properties"] = mc.ManagedClusterProperties + } return json.Marshal(objectMap) } @@ -883,15 +1000,6 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var managedClusterProperties ManagedClusterProperties - err = json.Unmarshal(*v, &managedClusterProperties) - if err != nil { - return err - } - mc.ManagedClusterProperties = &managedClusterProperties - } case "id": if v != nil { var ID string @@ -937,6 +1045,15 @@ func (mc *ManagedCluster) UnmarshalJSON(body []byte) error { } mc.Tags = tags } + case "properties": + if v != nil { + var managedClusterProperties ManagedClusterProperties + err = json.Unmarshal(*v, &managedClusterProperties) + if err != nil { + return err + } + mc.ManagedClusterProperties = &managedClusterProperties + } } } @@ -958,8 +1075,6 @@ type ManagedClusterAADProfile struct { // ManagedClusterAccessProfile managed cluster Access Profile. type ManagedClusterAccessProfile struct { autorest.Response `json:"-"` - // AccessProfile - AccessProfile of a managed cluster. - *AccessProfile `json:"properties,omitempty"` // ID - READ-ONLY; Resource Id ID *string `json:"id,omitempty"` // Name - READ-ONLY; Resource name @@ -970,20 +1085,22 @@ type ManagedClusterAccessProfile struct { Location *string `json:"location,omitempty"` // Tags - Resource tags Tags map[string]*string `json:"tags"` + // AccessProfile - AccessProfile of a managed cluster. + *AccessProfile `json:"properties,omitempty"` } // MarshalJSON is the custom marshaler for ManagedClusterAccessProfile. func (mcap ManagedClusterAccessProfile) MarshalJSON() ([]byte, error) { objectMap := make(map[string]interface{}) - if mcap.AccessProfile != nil { - objectMap["properties"] = mcap.AccessProfile - } if mcap.Location != nil { objectMap["location"] = mcap.Location } if mcap.Tags != nil { objectMap["tags"] = mcap.Tags } + if mcap.AccessProfile != nil { + objectMap["properties"] = mcap.AccessProfile + } return json.Marshal(objectMap) } @@ -996,15 +1113,6 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } for k, v := range m { switch k { - case "properties": - if v != nil { - var accessProfile AccessProfile - err = json.Unmarshal(*v, &accessProfile) - if err != nil { - return err - } - mcap.AccessProfile = &accessProfile - } case "id": if v != nil { var ID string @@ -1050,6 +1158,15 @@ func (mcap *ManagedClusterAccessProfile) UnmarshalJSON(body []byte) error { } mcap.Tags = tags } + case "properties": + if v != nil { + var accessProfile AccessProfile + err = json.Unmarshal(*v, &accessProfile) + if err != nil { + return err + } + mcap.AccessProfile = &accessProfile + } } } diff --git a/services/containerservice/mgmt/2018-03-31/containerservice/version.go b/services/containerservice/mgmt/2018-03-31/containerservice/version.go index c2c4f9aefef8..652b5b209e37 100644 --- a/services/containerservice/mgmt/2018-03-31/containerservice/version.go +++ b/services/containerservice/mgmt/2018-03-31/containerservice/version.go @@ -21,7 +21,7 @@ import "github.com/Azure/azure-sdk-for-go/version" // UserAgent returns the UserAgent string to use when sending http.Requests. func UserAgent() string { - return "Azure-SDK-For-Go/" + version.Number + " containerservice/2018-03-31" + return "Azure-SDK-For-Go/" + version.Number + " containerservice/2017-07-01" } // Version returns the semantic version (see http://semver.org) of the client. diff --git a/tools/indexer/main.go b/tools/indexer/main.go index 2bf57f4b0c61..c4076d561809 100644 --- a/tools/indexer/main.go +++ b/tools/indexer/main.go @@ -26,18 +26,18 @@ import ( // adds any missing SDK packages to godoc.org func main() { - dir := "" + // by default assume we're running from the source dir + // and calculate the relative path to the services directory. + dir := "../../services" if len(os.Args) > 1 { // assume second arg is source dir dir = os.Args[1] - } else { - // if no args specified assume we're running from the source dir - // and calculate the relative path to the services directory. - var err error - dir, err = filepath.Abs("../../services") - if err != nil { - panic(err) - } + } + + var err error + dir, err = filepath.Abs(dir) + if err != nil { + panic(err) } pkgs, err := util.GetPackagesForIndexing(dir) diff --git a/tools/pkgchk/cmd/root.go b/tools/pkgchk/cmd/root.go index e91e1b631a1e..5d74563f35ce 100644 --- a/tools/pkgchk/cmd/root.go +++ b/tools/pkgchk/cmd/root.go @@ -31,7 +31,7 @@ import ( "github.com/spf13/cobra" ) -var excepFileFlag string +var exceptFileFlag string var rootCmd = &cobra.Command{ Use: "pkgchk ", @@ -41,12 +41,7 @@ found under the specified directory. Failures can be baselined and thus ignored copying the failure text verbatim, pasting it into a text file then specifying that file via the optional exceptions flag. `, - Args: func(cmd *cobra.Command, args []string) error { - if err := cobra.ExactArgs(1)(cmd, args); err != nil { - return err - } - return nil - }, + Args: cobra.ExactArgs(1), RunE: func(cmd *cobra.Command, args []string) error { cmd.SilenceUsage = true return theCommand(args) @@ -54,7 +49,7 @@ file via the optional exceptions flag. } func init() { - rootCmd.PersistentFlags().StringVarP(&excepFileFlag, "exceptions", "e", "", "text file containing the list of exceptions") + rootCmd.PersistentFlags().StringVarP(&exceptFileFlag, "exceptions", "e", "", "text file containing the list of exceptions") } // Execute executes the specified command. @@ -65,26 +60,17 @@ func Execute() { } func theCommand(args []string) error { - rootDir := args[0] - if !filepath.IsAbs(rootDir) { - asAbs, err := filepath.Abs(rootDir) - if err != nil { - return errors.Wrap(err, "failed to get absolute path") - } - rootDir = asAbs + rootDir, err := filepath.Abs(args[0]) + if err != nil { + return errors.Wrap(err, "failed to get absolute path") } - pkgs, err := getPkgs(rootDir) if err != nil { return errors.Wrap(err, "failed to get packages") } - - var exceptions []string - if excepFileFlag != "" { - exceptions, err = loadExceptions(excepFileFlag) - if err != nil { - return errors.Wrap(err, "failed to load exceptions") - } + exceptions, err := loadExceptions(exceptFileFlag) + if err != nil { + return errors.Wrap(err, "failed to load exceptions") } verifiers := getVerifiers() count := 0 @@ -96,12 +82,10 @@ func theCommand(args []string) error { } } } - - var res error if count > 0 { - res = fmt.Errorf("found %d errors", count) + return fmt.Errorf("found %d errors", count) } - return res + return nil } func contains(items []string, item string) bool { @@ -116,8 +100,11 @@ func contains(items []string, item string) bool { return false } -func loadExceptions(excepFile string) ([]string, error) { - f, err := os.Open(excepFile) +func loadExceptions(exceptFile string) ([]string, error) { + if exceptFile == "" { + return nil, nil + } + f, err := os.Open(exceptFile) if err != nil { return nil, err } @@ -150,7 +137,7 @@ func (p pkg) isARMPkg() bool { // walks the directory hierarchy from the specified root returning a slice of all the packages found func getPkgs(rootDir string) ([]pkg, error) { - pkgs := []pkg{} + pkgs := make([]pkg, 0) err := filepath.Walk(rootDir, func(path string, info os.FileInfo, err error) error { if err != nil { return err @@ -214,19 +201,30 @@ func getVerifiers() []verifier { return []verifier{ verifyPkgMatchesDir, verifyLowerCase, - verifyDirectorySturcture, + verifyDirectoryStructure, } } // ensures that the leaf directory name matches the package name +// new to modules: if the last leaf is version suffix, find its parent as leaf folder func verifyPkgMatchesDir(p pkg) error { - leaf := p.d[strings.LastIndex(p.d, "/")+1:] - if strings.Compare(leaf, p.p.Name) != 0 { + leaf := findPackageFolderInPath(p.d) + if !strings.EqualFold(leaf, p.p.Name) { return fmt.Errorf("leaf directory of '%s' doesn't match package name '%s'", p.d, p.p.Name) } return nil } +func findPackageFolderInPath(path string) string { + regex := regexp.MustCompile(`/v\d+$`) + if regex.MatchString(path) { + // folder path ends with version suffix + path = path[:strings.LastIndex(path, "/")] + } + result := path[strings.LastIndex(path, "/")+1:] + return result +} + // ensures that there are no upper-case letters in a package's directory func verifyLowerCase(p pkg) error { // walk the package directory looking for upper-case characters @@ -242,12 +240,13 @@ func verifyLowerCase(p pkg) error { } // ensures that the package's directory hierarchy is properly formed -func verifyDirectorySturcture(p pkg) error { +func verifyDirectoryStructure(p pkg) error { // for ARM the package directory structure is highly deterministic: // /redis/mgmt/2015-08-01/redis // /resources/mgmt/2017-06-01-preview/policy // /preview/signalr/mgmt/2018-03-01-preview/signalr // /preview/security/mgmt/v2.0/security (version scheme for composite packages) + // /network/mgmt/2019-10-01/network/v2 (new with modules) if !p.isARMPkg() { return nil } @@ -255,9 +254,10 @@ func verifyDirectorySturcture(p pkg) error { `^(?:/preview)?`, `[a-z0-9\-]+`, `mgmt`, - `(?:\d{4}-\d{2}-\d{2}(?:-preview)?)|(?:v\d{1,2}\.\d{1,2})`, + `((?:\d{4}-\d{2}-\d{2}(?:-preview)?)|(?:v\d{1,2}\.\d{1,2}))`, `[a-z0-9]+`, }, "/") + regexStr = regexStr + `(/v\d+)?$` regex := regexp.MustCompile(regexStr) if !regex.MatchString(p.d) { return fmt.Errorf("bad directory structure '%s'", p.d) diff --git a/tools/pkgchk/cmd/root_test.go b/tools/pkgchk/cmd/root_test.go new file mode 100644 index 000000000000..6dc4eacb5383 --- /dev/null +++ b/tools/pkgchk/cmd/root_test.go @@ -0,0 +1,92 @@ +// Copyright 2018 Microsoft Corporation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package cmd + +import ( + "path/filepath" + "strings" + "testing" +) + +const ( + testRoot = "../../testpkgs" +) + +var ( + expected = map[string]string{ + "/scenrioa/foo": "foo", + "/scenriob/foo": "foo", + "/scenriob/foo/v2": "foo", + "/scenrioc/mgmt/2019-10-11/foo": "foo", + "/scenriod/mgmt/2019-10-11/foo": "foo", + "/scenriod/mgmt/2019-10-11/foo/v2": "foo", + "/scenrioe/mgmt/2019-10-11/foo": "foo", + "/scenrioe/mgmt/2019-10-11/foo/v2": "foo", + "/scenrioe/mgmt/2019-10-11/foo/v3": "foo", + } +) + +func Test_getPkgs(t *testing.T) { + rootDir, err := filepath.Abs(testRoot) + if err != nil { + t.Fatalf("failed to get absolute path: %+v", err) + } + pkgs, err := getPkgs(rootDir) + if err != nil { + t.Fatalf("failed to get packages: %+v", err) + } + if len(pkgs) != len(expected) { + t.Fatalf("expected %d packages, but got %d", len(expected), len(pkgs)) + } + for _, pkg := range pkgs { + if pkgName, ok := expected[pkg.d]; !ok { + t.Fatalf("got pkg path '%s', but not found in expected", pkg.d) + } else if !strings.EqualFold(pkgName, pkg.p.Name) { + t.Fatalf("expected package of '%s' in path '%s', but got '%s'", pkgName, pkg.d, pkg.p.Name) + } + } +} + +func Test_verifyDirectoryStructure(t *testing.T) { + rootDir, err := filepath.Abs(testRoot) + if err != nil { + t.Fatalf("failed to get absolute path: %+v", err) + } + pkgs, err := getPkgs(rootDir) + if err != nil { + t.Fatalf("failed to get packages: %+v", err) + } + for _, pkg := range pkgs { + if err := verifyDirectoryStructure(pkg); err != nil { + t.Fatalf("failed to verify directory structure: %+v", err) + } + } +} + +func Test_verifyPkgMatchesDir(t *testing.T) { + rootDir, err := filepath.Abs(testRoot) + if err != nil { + t.Fatalf("failed to get absolute path: %+v", err) + } + pkgs, err := getPkgs(rootDir) + if err != nil { + t.Fatalf("failed to get packages: %+v", err) + } + for _, pkg := range pkgs { + if err := verifyPkgMatchesDir(pkg); err != nil { + t.Fatalf("failed to verify package directory name: %+v", err) + } + } +} diff --git a/tools/testpkgs/scenrioa/foo/client.go b/tools/testpkgs/scenrioa/foo/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenrioa/foo/fooapi/interfaces.go b/tools/testpkgs/scenrioa/foo/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenrioa/foo/gateways.go b/tools/testpkgs/scenrioa/foo/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenrioa/foo/go.mod b/tools/testpkgs/scenrioa/foo/go.mod new file mode 100644 index 000000000000..cd72ef5610b5 --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo + +go 1.12 diff --git a/tools/testpkgs/scenrioa/foo/model.go b/tools/testpkgs/scenrioa/foo/model.go new file mode 100644 index 000000000000..0cb1eb592bb9 --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *int +} diff --git a/tools/testpkgs/scenrioa/foo/version.go b/tools/testpkgs/scenrioa/foo/version.go new file mode 100644 index 000000000000..a2201e008c96 --- /dev/null +++ b/tools/testpkgs/scenrioa/foo/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/1.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "1.0.0" +} diff --git a/tools/testpkgs/scenriob/foo/client.go b/tools/testpkgs/scenriob/foo/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenriob/foo/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenriob/foo/fooapi/interfaces.go b/tools/testpkgs/scenriob/foo/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenriob/foo/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenriob/foo/gateways.go b/tools/testpkgs/scenriob/foo/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenriob/foo/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenriob/foo/go.mod b/tools/testpkgs/scenriob/foo/go.mod new file mode 100644 index 000000000000..cd72ef5610b5 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo + +go 1.12 diff --git a/tools/testpkgs/scenriob/foo/model.go b/tools/testpkgs/scenriob/foo/model.go new file mode 100644 index 000000000000..0cb1eb592bb9 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *int +} diff --git a/tools/testpkgs/scenriob/foo/v2/client.go b/tools/testpkgs/scenriob/foo/v2/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenriob/foo/v2/fooapi/interfaces.go b/tools/testpkgs/scenriob/foo/v2/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenriob/foo/v2/gateways.go b/tools/testpkgs/scenriob/foo/v2/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenriob/foo/v2/go.mod b/tools/testpkgs/scenriob/foo/v2/go.mod new file mode 100644 index 000000000000..e5bbbac12d18 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo/v2 + +go 1.12 diff --git a/tools/testpkgs/scenriob/foo/v2/model.go b/tools/testpkgs/scenriob/foo/v2/model.go new file mode 100644 index 000000000000..2ce42bea6cd7 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *string +} diff --git a/tools/testpkgs/scenriob/foo/v2/version.go b/tools/testpkgs/scenriob/foo/v2/version.go new file mode 100644 index 000000000000..5fccf0de3cb4 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/v2/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/2.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "2.0.0" +} diff --git a/tools/testpkgs/scenriob/foo/version.go b/tools/testpkgs/scenriob/foo/version.go new file mode 100644 index 000000000000..a2201e008c96 --- /dev/null +++ b/tools/testpkgs/scenriob/foo/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/1.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "1.0.0" +} diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/client.go b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/fooapi/interfaces.go b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/gateways.go b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/go.mod b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/go.mod new file mode 100644 index 000000000000..cd72ef5610b5 --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo + +go 1.12 diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/model.go b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/model.go new file mode 100644 index 000000000000..0cb1eb592bb9 --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *int +} diff --git a/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/version.go b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/version.go new file mode 100644 index 000000000000..a2201e008c96 --- /dev/null +++ b/tools/testpkgs/scenrioc/mgmt/2019-10-11/foo/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/1.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "1.0.0" +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/client.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/fooapi/interfaces.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/gateways.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/go.mod b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/go.mod new file mode 100644 index 000000000000..cd72ef5610b5 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo + +go 1.12 diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/model.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/model.go new file mode 100644 index 000000000000..0cb1eb592bb9 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *int +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/client.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/gateways.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/go.mod b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/go.mod new file mode 100644 index 000000000000..e5bbbac12d18 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo/v2 + +go 1.12 diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/model.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/model.go new file mode 100644 index 000000000000..2ce42bea6cd7 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *string +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/version.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/version.go new file mode 100644 index 000000000000..5fccf0de3cb4 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/v2/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/2.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "2.0.0" +} diff --git a/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/version.go b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/version.go new file mode 100644 index 000000000000..a2201e008c96 --- /dev/null +++ b/tools/testpkgs/scenriod/mgmt/2019-10-11/foo/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/1.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "1.0.0" +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/client.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/fooapi/interfaces.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/gateways.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/go.mod b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/go.mod new file mode 100644 index 000000000000..cd72ef5610b5 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo + +go 1.12 diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/model.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/model.go new file mode 100644 index 000000000000..0cb1eb592bb9 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *int +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/client.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/gateways.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/go.mod b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/go.mod new file mode 100644 index 000000000000..e5bbbac12d18 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo/v2 + +go 1.12 diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/model.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/model.go new file mode 100644 index 000000000000..2ce42bea6cd7 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *string + // Field2 ... + Field2 *string +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/version.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/version.go new file mode 100644 index 000000000000..5fccf0de3cb4 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v2/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/2.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "2.0.0" +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/client.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/client.go new file mode 100644 index 000000000000..3383e4936acd --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/client.go @@ -0,0 +1,29 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +const ( + // DefaultBaseURI is the default URI used for the service Network + DefaultBaseURI = "https://management.azure.com" +) + +// BaseClient is the base client for Network. +type BaseClient struct { + autorest.Client + BaseURI string + SubscriptionID string +} + +// New creates an instance of the BaseClient client. +func New(subscriptionID string) BaseClient { + return NewWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewWithBaseURI creates an instance of the BaseClient client. +func NewWithBaseURI(baseURI string, subscriptionID string) BaseClient { + return BaseClient{ + Client: autorest.NewClientWithUserAgent(UserAgent()), + BaseURI: baseURI, + SubscriptionID: subscriptionID, + } +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/fooapi/interfaces.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/fooapi/interfaces.go new file mode 100644 index 000000000000..979eaa56028c --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/fooapi/interfaces.go @@ -0,0 +1,11 @@ +package fooapi + +import ( + "context" + "github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenrioa/foo" +) + +// GatewaysClientAPI ... +type GatewaysClientAPI interface { + CreateOrUpdate(ctx context.Context, resourceGroupName string, gatewayName string, parameters foo.Gateway) (result foo.Gateway, err error) +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/gateways.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/gateways.go new file mode 100644 index 000000000000..0f4bb465babf --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/gateways.go @@ -0,0 +1,16 @@ +package foo + +// GatewaysClient ... +type GatewaysClient struct { + BaseClient +} + +// NewGatewaysClient ... +func NewGatewaysClient(subscriptionID string) GatewaysClient { + return NewGatewaysClientWithBaseURI(DefaultBaseURI, subscriptionID) +} + +// NewGatewaysClientWithBaseURI ... +func NewGatewaysClientWithBaseURI(baseURI string, subscriptionID string) GatewaysClient { + return GatewaysClient{NewWithBaseURI(baseURI, subscriptionID)} +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/go.mod b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/go.mod new file mode 100644 index 000000000000..45952d6e7ff3 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/go.mod @@ -0,0 +1,3 @@ +module github.com/Azure/azure-sdk-for-go/tools/testpkgs/scenarioa/foo/v3 + +go 1.12 diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/model.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/model.go new file mode 100644 index 000000000000..e760e5fe04ae --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/model.go @@ -0,0 +1,12 @@ +package foo + +import "github.com/Azure/go-autorest/autorest" + +// Gateway ... +type Gateway struct { + autorest.Response `json:"-"` + // Field1 ... + Field1 *int + // Field2 ... + Field2 *string +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/version.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/version.go new file mode 100644 index 000000000000..c4e6e6562f39 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/v3/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/3.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "3.0.0" +} diff --git a/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/version.go b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/version.go new file mode 100644 index 000000000000..a2201e008c96 --- /dev/null +++ b/tools/testpkgs/scenrioe/mgmt/2019-10-11/foo/version.go @@ -0,0 +1,28 @@ +package foo + +// Copyright (c) Microsoft and contributors. All rights reserved. +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// +// See the License for the specific language governing permissions and +// limitations under the License. +// +// Code generated by Microsoft (R) AutoRest Code Generator. +// Changes may cause incorrect behavior and will be lost if the code is regenerated. + +// UserAgent returns the UserAgent string to use when sending http.Requests. +func UserAgent() string { + return "Azure-SDK-For-Go/1.0.0 foo/2019-04-01" +} + +// Version returns the semantic version (see http://semver.org) of the client. +func Version() string { + return "1.0.0" +} diff --git a/version/version.go b/version/version.go index 9b42a2166654..b55e476d349d 100644 --- a/version/version.go +++ b/version/version.go @@ -18,4 +18,4 @@ package version // Changes may cause incorrect behavior and will be lost if the code is regenerated. // Number contains the semantic version of this SDK. -const Number = "latest" +const Number = "v38.2.0"