...

Text file src/github.com/Azure/azure-sdk-for-go/documentation/MIGRATION_GUIDE.md

Documentation: github.com/Azure/azure-sdk-for-go/documentation

     1## Guide for migrating to `sdk/resourcemanager/**/arm**` from `services/**/mgmt/**`
     2
     3This document is intended for users that are familiar with the previous version of the Azure SDK For Go for management modules (`services/**/mgmt/**`) and wish to migrate their application to the next version of Azure resource management libraries (`sdk/resourcemanager/**/arm**`)
     4
     5**For users new to the Azure SDK For Go for resource management modules, please see the [README for 'sdk/azcore`](https://github.com/Azure/azure-sdk-for-go/tree/main/sdk/azcore) and the README for every individual package.**
     6
     7## Table of contents
     8
     9* [Prerequisites](#prerequisites)
    10* [General Changes](#general-changes)
    11* [Breaking Changes](#breaking-changes)
    12    * [Authentication](#authentication)
    13    * [Error Handling](#error-handling)
    14    * [Long Running Operations](#long-running-operations)
    15    * [Pagination](#pagination)
    16    * [Customized Policy](#customized-policy)
    17    * [Custom HTTP Client](#custom-http-client)
    18
    19## Prerequisites
    20
    21- Go 1.18
    22- Latest version of resource management modules
    23
    24## General Changes
    25
    26The latest Azure SDK For Go for management modules is using the [Go Modules](https://github.com/golang/go/wiki/Modules) to manage the dependencies. We ship every RP as an individual module to create a more flexible user experience. Unlike previous version, the latest SDK only provides one API version in one module for each RP. The SDK stable version will always use the service's stable API version. You can search in [pkg.go.dev](https://pkg.go.dev/github.com/Azure/azure-sdk-for-go) to find the preview version and specify version num when using `go get` to retrive it (e.g., `go get github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/keyvault/armkeyvault@v1.1.0-beta.1`).
    27
    28## Breaking Changes
    29
    30### Authentication
    31
    32In the previous version (`services/**/mgmt/**`), `autorest.Authorizer` is used in authentication process.
    33
    34In the latest version (`sdk/resourcemanager/**/arm**`), in order to provide a unified authentication based on Azure Identity for all Azure Go SDKs, the authentication mechanism has been re-designed and improved to offer a simpler interface.
    35
    36To the show the code snippets for the change:
    37
    38**Previous version (`services/**/mgmt/**`)**
    39
    40```go
    41import "github.com/Azure/go-autorest/autorest/adal"
    42import "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources"
    43```
    44
    45```go
    46authorizer, err := adal.NewServicePrincipalToken(oAuthToken, "<ClientId>", "<ClientSecret>", endpoint)
    47client := resources.NewGroupsClient("<SubscriptionId>")
    48client.Authorizer = authorizer
    49```
    50
    51**Latest version (`sdk/resourcemanager/**/arm**`)**
    52
    53```go
    54import "github.com/Azure/azure-sdk-for-go/sdk/azidentity"
    55import "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
    56```
    57
    58```go
    59credential, err := azidentity.NewClientSecretCredential("<TenantId>", "<ClientId>", "<ClientSecret>", nil)
    60client, err := armresources.NewResourceGroupsClient("<SubscriptionId>", credential, nil)
    61```
    62
    63For detailed information on the benefits of using the new authentication types, please refer to [this page](https://github.com/Azure/azure-sdk-for-go/blob/main/sdk/azidentity/README.md)
    64
    65### Error Handling
    66
    67There are some minor changes in the error handling.
    68
    69- When there is an error in the SDK request, in the previous version (`services/**/mgmt/**`), the return value will all be non-nil, and you can get the raw HTTP response from the response value. In the latest version (`sdk/resourcemanager/**/arm**`), the first return value will be empty and you need to convert the error to the `azcore.ResponseError` interface to get the raw HTTP response.
    70- In the latest version (`sdk/resourcemanager/**/arm**`), you can always get the raw HTTP response from request context regardless of request result.
    71
    72**Previous version (`services/**/mgmt/**`)**
    73
    74```go
    75resp, err := resourceGroupsClient.CreateOrUpdate(context.TODO(), resourceGroupName, resourceGroupParameters)
    76if err != nil {
    77    log.Fatalf("Status code: %d", resp.Response().StatusCode)
    78}
    79```
    80
    81**Latest version (`sdk/resourcemanager/**/arm**`)**
    82
    83```go
    84import "github.com/Azure/azure-sdk-for-go/sdk/azcore"
    85import "github.com/Azure/azure-sdk-for-go/sdk/azcore/runtime"
    86```
    87
    88```go
    89var rawResponse *http.Response
    90ctx := context.TODO() // your context
    91ctxWithResp := runtime.WithCaptureResponse(ctx, &rawResponse)
    92resp, err := resourceGroupsClient.CreateOrUpdate(ctxWithResp, resourceGroupName, resourceGroupParameters, nil)
    93if err != nil {
    94    // with error, you can get RawResponse from context
    95    log.Printf("Status code: %d", rawResponse.StatusCode)
    96    var respErr *azcore.ResponseError
    97    if errors.As(err, &respErr) {
    98        // with error, you can also get RawResponse from error
    99        log.Fatalf("Status code: %d", respErr.RawResponse.StatusCode)
   100    } else {
   101        log.Fatalf("Other error: %+v", err)
   102    }
   103}
   104// without error, you can get RawResponse from context
   105log.Printf("Status code: %d", rawResponse.StatusCode)
   106```
   107
   108### Long Running Operations
   109
   110In the previous version, if a request is a long-running operation, a struct `**Future` will be returned, which is an extension of the interface `azure.FutureAPI`. You need to invoke the `future.WaitForCompletionRef` to wait until it finishes.
   111
   112In the latest version, if a request is a long-running operation, the function name will start with `Begin` to indicate this function will return a poller type which contains the polling methods.
   113
   114**Previous version (`services/**/mgmt/**`)**
   115
   116```go
   117ctx := context.TODO() // your context
   118future, err := virtualMachinesClient.CreateOrUpdate(ctx, "<resource group name>", "<virtual machine name>", param)
   119if err != nil {
   120    log.Fatal(err)
   121}
   122if err := future.WaitForCompletionRef(ctx, virtualMachinesClient.Client); err != nil {
   123    log.Fatal(err)
   124}
   125vm, err := future.Result(virtualMachinesClient)
   126if err != nil {
   127    log.Fatal(err)
   128}
   129log.Printf("virtual machine ID: %v", *vm.ID)
   130```
   131
   132**Latest version (`sdk/resourcemanager/**/arm**`)**
   133
   134```go
   135poller, err := client.BeginCreateOrUpdate(context.TODO(), "<resource group name>", "<virtual machine name>", param, nil)
   136if err != nil {
   137    log.Fatal(err)
   138}
   139resp, err := poller.PollUntilDone(context.TODO(), nil)
   140if err != nil {
   141    log.Fatal(err)
   142}
   143log.Printf("virtual machine ID: %v", *resp.VirtualMachine.ID)
   144```
   145
   146### Pagination
   147
   148In the previous version, if a request is a paginated operation, a struct `**ResultPage` will be returned, which is a struct with some paging methods but no interfaces are defined regarding that.
   149
   150In the latest version, if a request is a paginated operation, a struct `**Pager` will be returned that contains the paging methods.
   151
   152**Previous version (`services/**/mgmt/**`)**
   153
   154```go
   155pager, err := resourceGroupsClient.List(context.TODO(), "", nil)
   156if err != nil {
   157    log.Fatal(err)
   158}
   159for p.NotDone() {
   160    for _, v := range pager.Values() {
   161        log.Printf("resource group ID: %s\n", *rg.ID)
   162    }
   163    if err := pager.NextWithContext(context.TODO()); err != nil   {
   164        log.Fatal(err)
   165    }
   166}
   167```
   168
   169**Latest version (`sdk/resourcemanager/**/arm**`)**
   170
   171```go
   172ctx := context.TODO() // your context
   173pager := resourceGroupsClient.NewListPager(nil)
   174for pager.More() {
   175    nextResult, err := pager.NextPage(ctx)
   176    if err != nil {
   177        log.Fatalf("failed to advance page: %v", err)
   178    }
   179    for _, rg := range nextResult.Value {
   180        log.Printf("resource group ID: %s\n", *rg.ID)
   181    }
   182}
   183```
   184
   185### Customized Policy
   186
   187Because of adopting Azure Core which is a shared library across all Azure SDKs, there is also a minor change regarding how customized policy in configured.
   188
   189In the previous version (`services/**/mgmt/**`), we use the `(autorest.Client).Sender`, `(autorest.Client).RequestInspector` and `(autorest.Client).ResponseInspector` properties in `github.com/Azure/go-autorest/autorest` module to provide customized interceptor for the HTTP traffic.
   190
   191In latest version (`sdk/resourcemanager/**/arm**`), we use `arm.ClientOptions.PerCallPolicies` and `arm.ClientOptions.PerRetryPolicies` in `github.com/Azure/azure-sdk-for-go/sdk/azcore/arm` package instead to inject customized policy to the pipeline.
   192
   193### Custom HTTP Client
   194
   195Similar to the customized policy, there are changes regarding how the custom HTTP client is configured as well. You can now use the `arm.ClientOptions.Transport` option in `github.com/Azure/azure-sdk-for-go/sdk/azcore/arm` package to use your own implementation of HTTP client and plug in what they need into the configuration.  The HTTP client must implement the `policy.Transporter` interface.
   196
   197**Previous version (`services/**/mgmt/**`)**
   198
   199```go
   200import "github.com/Azure/azure-sdk-for-go/services/resources/mgmt/2020-10-01/resources"
   201```
   202
   203```go
   204httpClient := NewYourOwnHTTPClient{}
   205client := resources.NewGroupsClient("<SubscriptionId>")
   206client.Sender = &httpClient
   207```
   208
   209**Latest version (`sdk/resourcemanager/**/arm**`)**
   210
   211```go
   212import "github.com/Azure/azure-sdk-for-go/sdk/azcore/arm"
   213import "github.com/Azure/azure-sdk-for-go/sdk/azcore/policy"
   214import "github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/resources/armresources"
   215```
   216
   217```go
   218httpClient := NewYourOwnHTTPClient{}
   219options := &arm.ClientOptions{
   220    ClientOptions: policy.ClientOptions{
   221        Transport: &httpClient,
   222    },
   223}
   224client, err := armresources.NewResourceGroupsClient("<SubscriptionId>", credential, options)
   225```
   226
   227## Need help?
   228
   229If you have encountered an issue during migration, please file an issue via [Github Issues](https://github.com/Azure/azure-sdk-for-go/issues) and make sure you add the "Preview" label to the issue

View as plain text