github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/docs/MIGRATING.md (about)

     1  # Migration guide
     2  
     3  Gophercloud follows [semver](https://semver.org/) and each major release brings
     4  a number of changes breaking backward compatibility. This guide details those
     5  changes and explains how to migrate from one major version of Gophercloud to
     6  another.
     7  
     8  ## From v1 to v2
     9  
    10  ### Change import path
    11  
    12  The module is now named `github.com/vnpaycloud-console/gophercloud/v2`. Consequently,
    13  you need to update all your imports:
    14  
    15  ```diff
    16  import (
    17  -	"github.com/gophercloud/gophercloud"
    18  -	"github.com/gophercloud/gophercloud/pagination"
    19  +	"github.com/vnpaycloud-console/gophercloud/v2"
    20  +	"github.com/vnpaycloud-console/gophercloud/v2/pagination"
    21  )
    22  ```
    23  
    24  If using [gophercloud/utils](https://github.com/gophercloud/utils), you will
    25  also need to update those imports:
    26  
    27  ```diff
    28  import (
    29  -	"github.com/gophercloud/gophercloud"
    30  -	serverutils "github.com/gophercloud/utils/openstack/compute/v2/servers"
    31  +	"github.com/vnpaycloud-console/gophercloud/v2"
    32  +	serverutils "github.com/gophercloud/utils/v2/openstack/compute/v2/servers"
    33  )
    34  ```
    35  
    36  ### Go version
    37  
    38  The minimum go version for Gophercloud v2 is now v1.22.
    39  
    40  ### Context-awareness
    41  
    42  Gophercloud is now context aware, for tracing and cancellation. All function
    43  signatures triggering an HTTP call now take a `context.Context` as their first
    44  argument.
    45  
    46  While you previously called:
    47  
    48  ```go
    49  myServer, err := servers.Get(client, server.ID)
    50  ```
    51  
    52  You now need to pass it a context, for example:
    53  
    54  ```go
    55  ctx := context.TODO()
    56  myServer, err := servers.Get(ctx, client, server.ID)
    57  ```
    58  
    59  Now that every method accept a context, it is no longer possible to attach
    60  a context to the Provider client. Use per-call context instead.
    61  
    62  The `WaitFor` functions now take a context as well, and we've dropped the
    63  timeout argument. This means that the following code:
    64  
    65  ```go
    66  err = attachments.WaitForStatus(client, attachment.ID, "attached", 60)
    67  ```
    68  
    69  Must be changed to use a context with timeout. For example:
    70  
    71  ```go
    72  ctx, cancel := context.WithTimeout(context.TODO(), 60*time.Second)
    73  defer cancel()
    74  
    75  err = attachments.WaitForStatus(ctx, client, attachment.ID, "attached")
    76  ```
    77  
    78  ### Error handling
    79  
    80  The error types for specific response codes (`ErrDefault400`, `ErrDefault401`, etc.) have been removed.
    81  All unexpected response codes will now return `ErrUnexpectedResponseCode` instead.
    82  For quickly checking whether a request resulted in a specific response code, use the new `ResponseCodeIs` function:
    83  
    84  ```go
    85  server, err := servers.Get(ctx, client, serverID).Extract()
    86  
    87  // before
    88  if _, ok := err.(gophercloud.ErrDefault404); ok {
    89  	handleServerNotFound()
    90  }
    91  
    92  // after
    93  if gophercloud.ResponseCodeIs(err, http.StatusNotFound) {
    94  	handleServerNotFound()
    95  }
    96  ```
    97  
    98  Furthermore, the error messages returned by ErrUnexpectedResponseCode now include less newlines than before.
    99  If you match on error messages using regexes, please double-check your regexes.
   100  
   101  #### With gophercloud/utils
   102  
   103  If using the `utils` library, note that the `IDFromName` functions return
   104  `ErrResourceNotFound` rather than `ErrUnexpectedResponseCode`. In that
   105  scenario, type assertions for a "not found" error are still necessary:
   106  
   107  ```Go
   108  func IsNotFound(err error) bool {
   109  	if _, ok := err.(gophercloud.ErrResourceNotFound); ok { // <-- this
   110  		return true
   111  	}
   112  
   113  	return gophercloud.ResponseCodeIs(err, http.StatusNotFound)
   114  }
   115  ```
   116  
   117  ### Removal of `extensions` modules
   118  
   119  A number of services previously supported API extensions but have long since
   120  switched to using microversions to allow API changes. This is now reflected
   121  in Gophercloud v2 and the contents of the follow modules have been largely
   122  migrated:
   123  
   124  - `openstack/blockstorage/extensions`
   125  - `openstack/compute/v2/extensions`
   126  - `openstack/identity/v2/extensions`
   127  - `openstack/identity/v3/extensions`
   128  
   129  The replacement for these depends on the type of the former extension. For
   130  extensions that added wholly new APIs, these APIs have been moved into the
   131  main module for the corresponding service. These are:
   132  
   133  - `openstack/blockstorage/extensions/availabilityzones`
   134  
   135    Moved to `openstack/blockstorage/v2/availabilityzones` and
   136    `openstack/blockstorage/v3/availabilityzones`.
   137  
   138  - `openstack/blockstorage/extensions/backups`
   139  
   140    Moved to `openstack/blockstorage/v2/backups` and
   141    `openstack/blockstorage/v3/backups`.
   142  
   143  - `openstack/blockstorage/extensions/limits`
   144  
   145    Moved to `openstack/blockstorage/v2/limits` and
   146    `openstack/blockstorage/v3/limits`.
   147  
   148  - `openstack/blockstorage/extensions/quotasets`
   149  
   150    Moved to `openstack/blockstorage/v2/quotasets` and
   151    `openstack/blockstorage/v3/quotasets`.
   152  
   153  - `openstack/blockstorage/extensions/schedulerstats`
   154  
   155    Moved to `openstack/blockstorage/v2/schedulerstats` and
   156    `openstack/blockstorage/v3/schedulerstats`.
   157  
   158  - `openstack/blockstorage/extensions/services`
   159  
   160    Moved to `openstack/blockstorage/v2/services` and
   161    `openstack/blockstorage/v3/services`.
   162  
   163  - `openstack/blockstorage/extensions/volumetransfers`
   164  
   165    Moved to `openstack/blockstorage/v2/transfers` and
   166    `openstack/blockstorage/v3/transfers`.
   167  
   168  - `openstack/compute/v2/extensions/aggregates`
   169  
   170    Moved to `openstack/compute/v2/aggregates`.
   171  
   172  - `openstack/compute/v2/extensions/attachinterfaces`
   173  
   174    Moved to `openstack/compute/v2/attachinterfaces`.
   175  
   176  - `openstack/compute/v2/extensions/diagnostics`
   177  
   178    Moved to `openstack/compute/v2/diagnostics`.
   179  
   180  - `openstack/compute/v2/extensions/hypervisors`
   181  
   182    Moved to `openstack/compute/v2/hypervisors`.
   183  
   184  - `openstack/compute/v2/extensions/instanceactions`
   185  
   186    Moved to `openstack/compute/v2/instanceactions`.
   187  
   188  - `openstack/compute/v2/extensions/keypairs`
   189  
   190    Moved to `openstack/compute/v2/keypairs`.
   191  
   192  - `openstack/compute/v2/extensions/limits`
   193  
   194    Moved to `openstack/compute/v2/limits`.
   195  
   196  - `openstack/compute/v2/extensions/quotasets`
   197  
   198    Moved to `openstack/compute/v2/quotasets`.
   199  
   200  - `openstack/compute/v2/extensions/remoteconsoles`
   201  
   202    Moved to `openstack/compute/v2/remoteconsoles`.
   203  
   204  - `openstack/compute/v2/extensions/secgroups`
   205  
   206    Moved to `openstack/compute/v2/secgroups`.
   207  
   208  - `openstack/compute/v2/extensions/servergroups`
   209  
   210    Moved to `openstack/compute/v2/servergroups`.
   211  
   212  - `openstack/compute/v2/extensions/services`
   213  
   214    Moved to `openstack/compute/v2/services`.
   215  
   216  - `openstack/compute/v2/extensions/tags`
   217  
   218    Moved to `openstack/compute/v2/tags`.
   219  
   220  - `openstack/compute/v2/extensions/usage`
   221  
   222    Moved to `openstack/compute/v2/usage`.
   223  
   224  - `openstack/compute/v2/extensions/volumeattach`
   225  
   226    Moved to `openstack/compute/v2/volumeattach`.
   227  
   228  - `openstack/identity/v2/extensions/admin/roles`
   229  
   230    Moved to `openstack/identity/v2/roles`.
   231  
   232  - `openstack/identity/v3/extensions/ec2credentials`
   233  
   234    Moved to `openstack/identity/v3/ec2credentials`.
   235  
   236  - `openstack/identity/v3/extensions/ec2tokens`
   237  
   238    Moved to `openstack/identity/v3/ec2tokens`.
   239  
   240  - `openstack/identity/v3/extensions/federation`
   241  
   242    Moved to `openstack/identity/v3/federation`
   243  
   244  - `openstack/identity/v3/extensions/oauth1`.
   245  
   246    Moved to `openstack/identity/v3/oauth1`
   247  
   248  - `openstack/identity/v3/extensions/projectendpoints`
   249  
   250    Moved to `openstack/identity/v3/projectendpoints`.
   251  
   252  For extensions that modified existing APIs, these modifications have been
   253  folded into the modified APIs. These are:
   254  
   255  - `openstack/blockstorage/extensions/schedulerhints`
   256  
   257    `SchedulerHints` has been renamed to `SchedulerHintOpts` and moved to
   258    `openstack/blockstorage/v2/volumes` and `openstack/blockstorage/v3/volumes`.
   259    This is now a required argument of `volumes.Create` for both modules.
   260  
   261  - `openstack/blockstorage/extensions/volumeactions`
   262  
   263    All functions and supporting structs and interfaces have been moved to
   264    `openstack/blockstorage/v2/volumes` and `openstack/blockstorage/v3/volumes`.
   265  
   266  - `openstack/blockstorage/extensions/volumehost`
   267  
   268    The `VolumeHostExt` struct has been removed and a `Host` field added to the
   269    `Volume` struct in `openstack/blockstorage/v2/volumes` and
   270    `openstack/blockstorage/v3/volumes`.
   271  
   272  - `openstack/blockstorage/extensions/volumetenants`
   273  
   274    The `VolumeTenantExt` struct has been removed and a `TenantID` field added to
   275    the `Volume` struct in `openstack/blockstorage/v2/volumes` and
   276    `openstack/blockstorage/v3/volumes`.
   277  
   278  - `openstack/compute/v2/extensions/bootfromvolume`
   279  
   280    The `CreateOptsExt` struct has been removed and a `BlockDevice` field added
   281    to the `CreateOpts` struct in `openstack/compute/v2/servers`.
   282  
   283  - `openstack/compute/v2/extensions/diskconfig`
   284  
   285    The `CreateOptsExt` struct has been removed and a `DiskConfig` field added to
   286    the `CreateOpts` struct in `openstack/compute/v2/servers`.
   287  
   288  - `openstack/compute/v2/extensions/evacuate`
   289  
   290    All functions and supporting structs and interfaces have been moved to
   291    `openstack/compute/v2/servers`.
   292  
   293  - `openstack/compute/v2/extensions/extendedserverattributes`
   294  
   295    The `ServerAttributesExt` struct has been removed and all fields added to the
   296    `Server` struct in `openstack/compute/v2/servers`.
   297  
   298  - `openstack/compute/v2/extensions/extendedstatus`
   299  
   300    The `ServerExtendedStatusExt` struct has been removed and all fields added to
   301    the `Server` struct in `openstack/compute/v2/servers`.
   302  
   303  - `openstack/compute/v2/extensions/injectnetworkinfo`
   304  
   305    All functions and supporting structs and interfaces have been moved to
   306    `openstack/compute/v2/servers`.
   307  
   308  - `openstack/compute/v2/extensions/lockunlock`
   309  
   310    All functions and supporting structs and interfaces have been moved to
   311    `openstack/compute/v2/servers`.
   312  
   313  - `openstack/compute/v2/extensions/migrate`
   314  
   315    All functions and supporting structs and interfaces have been moved to
   316    `openstack/compute/v2/servers`.
   317  
   318  - `openstack/compute/v2/extensions/pauseunpause`
   319  
   320    All functions and supporting structs and interfaces have been moved to
   321    `openstack/compute/v2/servers`.
   322  
   323  - `openstack/compute/v2/extensions/rescueunrescue`
   324  
   325    All functions and supporting structs and interfaces have been moved to
   326    `openstack/compute/v2/servers`.
   327  
   328  - `openstack/compute/v2/extensions/resetnetwork`
   329  
   330    All functions and supporting structs and interfaces have been moved to
   331    `openstack/compute/v2/servers`.
   332  
   333  - `openstack/compute/v2/extensions/resetstate`
   334  
   335    All functions and supporting structs and interfaces have been moved to
   336    `openstack/compute/v2/servers`.
   337  
   338  - `openstack/compute/v2/extensions/schedulerhints`
   339  
   340    `SchedulerHints` has been moved to `openstack/compute/v2/servers` and
   341    renamed to `SchedulerHintOpts`. This is now a required argument of
   342    `servers.Create`.
   343  
   344  - `openstack/compute/v2/extensions/serverusage`
   345  
   346    The `serverusage` struct has been removed and all fields added to the
   347    `Server` struct in `openstack/compute/v2/servers`.
   348  
   349  - `openstack/compute/v2/extensions/shelveunshelve`
   350  
   351    All functions and supporting structs and interfaces have been moved to
   352    `openstack/compute/v2/servers`.
   353  
   354  - `openstack/compute/v2/extensions/startstop`
   355  
   356    All functions and supporting structs and interfaces have been moved to
   357    `openstack/compute/v2/servers`.
   358  
   359  - `openstack/compute/v2/extensions/suspendresume`
   360  
   361    All functions and supporting structs and interfaces have been moved to
   362    `openstack/compute/v2/servers`.
   363  
   364  For extensions that added new APIs *and* modified existing APIs, the new APIs
   365  are moved into the main module of the corresponding service while the
   366  modifications are folded into the modified APIs. These are:
   367  
   368  - `openstack/compute/v2/extensions/availabilityzones`
   369  
   370    The `ServerAvailabilityZoneExt` struct has been removed and a
   371    `AvailabilityZone` field added to the `Server` struct in
   372    `openstack/compute/v2/servers`. Everything else is moved moved to
   373    `openstack/compute/v2/availabilityzones`.
   374  
   375  - `openstack/identity/v3/extensions/trusts`
   376  
   377    The `AuthOptsExt` struct has been removed and a `TrustID` field added to the
   378    `Scope` struct in `openstack/identity/v3/tokens`. Everything else is moved
   379    moved to `openstack/identity/v3/trusts`.
   380  
   381  Finally, for extensions that are deprecated and have been removed in a
   382  microversion, the APIs were removed entirely. These are:
   383  
   384  - `openstack/compute/v2/extensions/defsecrules`
   385  
   386    This was a proxy for the Networking service, Neutron. Use
   387    `openstack/networking/v2/extensions/security/groups` instead.
   388  
   389  - `openstack/compute/v2/extensions/floatingips`
   390  
   391    This was a proxy for the Networking service, Neutron. Use
   392    `openstack/networking/v2/extensions/layer3/floatingips` instead.
   393  
   394  - `openstack/compute/v2/extensions/images`
   395  
   396    This was a proxy for the Image service, Glance. Use
   397    `openstack/image/v2/images` instead.
   398  
   399  - `openstack/compute/v2/extensions/networks`
   400  
   401    This was a proxy for the Networking service, Neutron. Use
   402    `openstack/networking/v2/networks` instead.
   403  
   404  - `openstack/compute/v2/extensions/tenantnetworks`
   405  
   406    This was a proxy for the Networking service, Neutron. Use
   407    `openstack/networking/v2/networks` instead.
   408  
   409  ### Type changes
   410  
   411  `loadbalancer/v2/pools/CreateOpts.Members` is now a slice of `CreateMemberOpts`
   412  rather than a slice of `BatchUpdateMemberOpts`.
   413  
   414  `blockstorage/v3/volumes/CreateOpts.Multiattach` is removed. Use a volume type
   415  with `multiattach` capability instead.
   416  
   417  The following structs are no longer comparable due to the addition of a non-comparable field:
   418  
   419  - `compute/v2/flavors/Flavor`
   420  - `loadbalancer/v2/l7policies/CreateRuleOpts`
   421  - `loadbalancer/v2/l7policies/UpdateOpts`
   422  - `loadbalancer/v2/l7policies/UpdateRuleOpts`
   423  - `loadbalancer/v2/listeners/ListOpts`
   424  - `loadbalancer/v2/monitors/ListOpts`
   425  - `loadbalancer/v2/monitors/CreateOpts`
   426  - `loadbalancer/v2/monitors/UpdateOpts`
   427  - `loadbalancer/v2/pools/ListOpts`
   428  
   429  This means that you were previously able to use `==` to compare these objects,
   430  this is no longer the case with Gophercloud v2.
   431  
   432  ### Image
   433  
   434  The `imageservice` service is renamed to simply `image` to conform with the other services.
   435  
   436  If you previously imported from
   437  `github.com/vnpaycloud-console/gophercloud/v2/openstack/imageservice/`, you now need
   438  to import from `github.com/vnpaycloud-console/gophercloud/v2/openstack/image/`.
   439  
   440  Additionally, `NewImageServiceV2()` is renamed `NewImageV2()`.
   441  
   442  ### Baremetal inventory
   443  
   444  The Baremetal inventory types moved from
   445  `baremetalintrospection/v1/introspection` to `baremetal/inventory`. This
   446  includes `BootInfoType`, `CPUType`, `LLDPTLVType`, `InterfaceType`,
   447  `InventoryType`, `MemoryType`, `RootDiskType`, `SystemFirmwareType`,
   448  `SystemVendorType`, `ExtraHardwareDataType`, `ExtraHardwareData`,
   449  `ExtraHardwareDataSection`, `NUMATopology`, `NUMACPU`, `NUMANIC`, and
   450  `NUMARAM`.
   451  
   452  Additionally, a few of these types were renamed in the process:
   453  
   454  - `ExtraHardwareDataType` became `ExtraDataType`
   455  - `ExtraHardwareData` became `ExtraDataItem`
   456  - `ExtraHardwareDataSection` became `ExtraHardwareDataSection`
   457  
   458  ### Object storage
   459  
   460  Gophercloud now escapes container and object names in all `objects` and
   461  `containers` functions. If you were previously escaping names (with, for
   462  example, `url.PathEscape` or `url.QueryEscape`), then you should REMOVE that
   463  and pass the intended names to Gophercloud directly.
   464  
   465  The `objectstorage/v1/containers.ListOpts#Full` and
   466  `objectstorage/v1/objects.ListOpts#Full` properties are removed from the
   467  Gophercloud API. Plaintext listing is unfixably wrong and won't handle special
   468  characters reliably (i.e. `\n`). Object listing and container listing now
   469  always behave like “Full” did.
   470  
   471  Empty container names, container names containing a slash (`/`), and empty
   472  object names are now rejected in Gophercloud before any call to Swift.
   473  
   474  The `ErrInvalidContainerName` error has been moved from
   475  `objectstorage/v1/containers` to `objectstorage/v1`. In addition, two new name
   476  validation errors have been added: `objectstorage.v1.ErrEmptyContainerName` and
   477  `objectstorage.v1.ErrEmptyObjectName`.
   478  
   479  The `objectstorage/v1/objects.Copy#Destination` field must be in the form
   480  `/container/object`. The function will reject a destination path if it doesn't
   481  start with a slash (`/`).
   482  
   483  ### Removed services and extensions
   484  
   485  Support for services that are no longer supported upstream has been removed.
   486  Users that still rely on theses old services should continue using Gophercloud v1.
   487  
   488  - Cinder (Blockstorage) v1 (`openstack/blockstorage/v1`)
   489  - Neutron (Networking) LBaaS and LBaaS v2 extensions
   490    (`openstack/networking/v2/extensions/lbaas`,
   491    `openstack/networking/v2/extensions/lbaas_v2`)
   492  - Neutron (Networking) FWaaS extension
   493    (`openstack/networking/v2/extensions/fwaas`)
   494  - Poppy (CDNaaS) service (`openstack/cdn`)
   495  - Senlin (Clustering) service (`openstack/clustering`)
   496  
   497  ### Script-assisted migration
   498  
   499  #### Expected outcome
   500  
   501  After running the script, your code may not compile. The idea is that at this point, you're only left with a few changes that can't reasonably be automated.
   502  
   503  #### What it does
   504  
   505  * Add `/v2` to all Gophercloud imports, except to the packages that have been removed without replacement
   506  * Adjust the import path of moved packages
   507  * Adjust the package identifier in the code where possible
   508  * Add `context.TODO()` where required
   509  
   510  #### Limitations
   511  
   512  * it doesn't fix the use of removed extensions. For example, if you used `openstack/blockstorage/extensions/availabilityzones`, you will have to manually put that back into e.g. `servers.CreateOpts`
   513  * it will just put `context.TODO()` where a context is required to satisfy the function signature. It's up to you to actually replace that with a variable and provide proper cancellation
   514  * it will add `context.TODO()` to `blockstorage/v1` calls, even though that package only exists in Gophercloud v1
   515  
   516  ```bash
   517  # Adjust the blockstorage version appropriately
   518  blockstorageversion=v3
   519  
   520  openstack='github.com/gophercloud/gophercloud/openstack'
   521  openstack_utils='github.com/gophercloud/utils/openstack'
   522  find . -type f -name '*.go' -not -path "*/vendor/*" -exec sed -i '
   523      /^import ($/,/^)$/ {
   524  
   525          # 1: These packages have been removed and their functionality moved into the main module for the corresponding service.
   526          /\(\/openstack\/blockstorage\/v1\|\/openstack\/networking\/v2\/extensions\/lbaas\|\/openstack\/networking\/v2\/extensions\/lbaas_v2\|\/openstack\/networking\/v2\/extensions\/fwaas\|\/openstack\/cdn\|\/openstack\/clustering\)/! {
   527              /\/openstack\/blockstorage\/extensions\/volumehost/d
   528              /\/openstack\/blockstorage\/extensions\/volumetenants/d
   529              /\/openstack\/compute\/v2\/extensions\/bootfromvolume/d
   530              /\/openstack\/compute\/v2\/extensions\/diskconfig/d
   531              /\/openstack\/compute\/v2\/extensions\/extendedserverattributes/d
   532              /\/openstack\/compute\/v2\/extensions\/extendedstatus/d
   533              /\/openstack\/compute\/v2\/extensions\/schedulerhints/d
   534              /\/openstack\/compute\/v2\/extensions\/serverusage/d
   535              /\/openstack\/compute\/v2\/extensions\/availabilityzones/d
   536              /\/openstack\/identity\/v3\/extensions\/trusts/d
   537          }
   538  
   539          '"
   540          # 2: Functions and supporting structs and interfaces of these packages have been moved to an existing package
   541          s|${openstack}/blockstorage/extensions/schedulerhints|${openstack}/blockstorage/${blockstorageversion}/volumes|g
   542          s|${openstack}/blockstorage/extensions/volumeactions|${openstack}/blockstorage/${blockstorageversion}/volumes|g
   543          s|${openstack}/compute/v2/extensions/evacuate|${openstack}/compute/v2/servers|g
   544          s|${openstack}/compute/v2/extensions/injectnetworkinfo|${openstack}/compute/v2/servers|g
   545          s|${openstack}/compute/v2/extensions/lockunlock|${openstack}/compute/v2/servers|g
   546          s|${openstack}/compute/v2/extensions/migrate|${openstack}/compute/v2/servers|g
   547          s|${openstack}/compute/v2/extensions/pauseunpause|${openstack}/compute/v2/servers|g
   548          s|${openstack}/compute/v2/extensions/rescueunrescue|${openstack}/compute/v2/servers|g
   549          s|${openstack}/compute/v2/extensions/resetnetwork|${openstack}/compute/v2/servers|g
   550          s|${openstack}/compute/v2/extensions/resetstate|${openstack}/compute/v2/servers|g
   551          s|${openstack}/compute/v2/extensions/shelveunshelve|${openstack}/compute/v2/servers|g
   552          s|${openstack}/compute/v2/extensions/startstop|${openstack}/compute/v2/servers|g
   553          s|${openstack}/compute/v2/extensions/suspendresume|${openstack}/compute/v2/servers|g
   554  
   555          # 3: These packages have been renamed
   556          s|${openstack}/imageservice|${openstack}/image|g
   557          s|${openstack_utils}/imageservice|${openstack_utils}/image|g
   558          s|${openstack}/blockstorage/extensions/availabilityzones|${openstack}/blockstorage/${blockstorageversion}/availabilityzones|g
   559          s|${openstack}/blockstorage/extensions/backups|${openstack}/blockstorage/${blockstorageversion}/backups|g
   560          s|${openstack}/blockstorage/extensions/limits|${openstack}/blockstorage/${blockstorageversion}/limits|g
   561          s|${openstack}/blockstorage/extensions/quotasets|${openstack}/blockstorage/${blockstorageversion}/quotasets|g
   562          s|${openstack}/blockstorage/extensions/schedulerstats|${openstack}/blockstorage/${blockstorageversion}/schedulerstats|g
   563          s|${openstack}/blockstorage/extensions/services|${openstack}/blockstorage/${blockstorageversion}/services|g
   564          s|${openstack}/blockstorage/extensions/volumetransfers|${openstack}/blockstorage/${blockstorageversion}/transfers|g
   565          s|${openstack}/compute/v2/extensions/aggregates|${openstack}/compute/v2/aggregates|g
   566          s|${openstack}/compute/v2/extensions/attachinterfaces|${openstack}/compute/v2/attachinterfaces|g
   567          s|${openstack}/compute/v2/extensions/diagnostics|${openstack}/compute/v2/diagnostics|g
   568          s|${openstack}/compute/v2/extensions/hypervisors|${openstack}/compute/v2/hypervisors|g
   569          s|${openstack}/compute/v2/extensions/instanceactions|${openstack}/compute/v2/instanceactions|g
   570          s|${openstack}/compute/v2/extensions/keypairs|${openstack}/compute/v2/keypairs|g
   571          s|${openstack}/compute/v2/extensions/limits|${openstack}/compute/v2/limits|g
   572          s|${openstack}/compute/v2/extensions/quotasets|${openstack}/compute/v2/quotasets|g
   573          s|${openstack}/compute/v2/extensions/remoteconsoles|${openstack}/compute/v2/remoteconsoles|g
   574          s|${openstack}/compute/v2/extensions/secgroups|${openstack}/compute/v2/secgroups|g
   575          s|${openstack}/compute/v2/extensions/servergroups|${openstack}/compute/v2/servergroups|g
   576          s|${openstack}/compute/v2/extensions/services|${openstack}/compute/v2/services|g
   577          s|${openstack}/compute/v2/extensions/tags|${openstack}/compute/v2/tags|g
   578          s|${openstack}/compute/v2/extensions/usage|${openstack}/compute/v2/usage|g
   579          s|${openstack}/compute/v2/extensions/volumeattach|${openstack}/compute/v2/volumeattach|g
   580          s|${openstack}/identity/v2/extensions/admin/roles|${openstack}/identity/v2/roles|g
   581          s|${openstack}/identity/v3/extensions/ec2credentials|${openstack}/identity/v3/ec2credentials|g
   582          s|${openstack}/identity/v3/extensions/ec2tokens|${openstack}/identity/v3/ec2tokens|g
   583          s|${openstack}/identity/v3/extensions/federation|${openstack}/identity/v3/federation|g
   584          s|${openstack}/identity/v3/extensions/oauth1|${openstack}/identity/v3/oauth1|g
   585          s|${openstack}/identity/v3/extensions/projectendpoints|${openstack}/identity/v3/projectendpoints|g
   586  
   587          # 4: These removed packages existed as proxies of others
   588          s|${openstack}/compute/v2/extensions/defsecrules|${openstack}/networking/v2/extensions/security/groups|g
   589          s|${openstack}/compute/v2/extensions/floatingips|${openstack}/networking/v2/extensions/layer3/floatingips|g
   590          s|${openstack}/compute/v2/extensions/images|${openstack}/image/v2/images|g
   591          s|${openstack}/compute/v2/extensions/networks|${openstack}/networking/v2/networks|g
   592          s|${openstack}/compute/v2/extensions/tenantnetworks|${openstack}/networking/v2/networks|g
   593          "'
   594  
   595          # 5: Update to v2, except for packages that were removed without replacement
   596          s|github.com/gophercloud/utils|github.com/gophercloud/utils/v2|g
   597          /\(\/openstack\/blockstorage\/v1\|\/openstack\/networking\/v2\/extensions\/lbaas\|\/openstack\/networking\/v2\/extensions\/lbaas_v2\|\/openstack\/networking\/v2\/extensions\/fwaas\|\/openstack\/cdn\|\/openstack\/clustering\)/! s|github.com/gophercloud/gophercloud|github.com/vnpaycloud-console/gophercloud/v2|g
   598      }
   599  
   600      /^)$/,$ {
   601  
   602          # 6: Rename identifiers of items of step 2 above
   603          s#\(schedulerhints\|volumeactions\)\.\([A-Z][A-Z_a-z_0-9]*\)#volumes.\2#g
   604          s#\(evacuate\|injectnetworkinfo\|lockunlock\|migrate\|pauseunpause\|rescueunrescue\|resetnetwork\|resetstate\|shelveunshelve\|startstop\|suspendresume\)\.\([A-Z][A-Z_a-z_0-9]*\)#servers.\2#g
   605  
   606          # 7: Add context.TODO()
   607          s#\(accept\.Create\|accept\.Get\|accounts\.Get\|accounts\.Update\|acls\.DeleteContainerACL\|acls\.DeleteSecretACL\|acls\.GetContainerACL\|acls\.GetSecretACL\|acls\.SetContainerACL\|acls\.SetSecretACL\|acls\.UpdateContainerACL\|acls\.UpdateSecretACL\|addressscopes\.Create\|addressscopes\.Delete\|addressscopes\.Get\|addressscopes\.Update\|agents\.Delete\|agents\.Get\|agents\.ListDHCPNetworks\|agents\.ListL3Routers\|agents\.RemoveBGPSpeaker\|agents\.RemoveDHCPNetwork\|agents\.RemoveL3Router\|agents\.ScheduleBGPSpeaker\|agents\.ScheduleDHCPNetwork\|agents\.ScheduleL3Router\|agents\.Update\|aggregates\.AddHost\|aggregates\.Create\|aggregates\.Delete\|aggregates\.Get\|aggregates\.RemoveHost\|aggregates\.SetMetadata\|aggregates\.Update\|allocations\.Create\|allocations\.Delete\|allocations\.Get\|amphorae\.Failover\|amphorae\.Get\|apiversions\.Get\|apiversions\.List\|applicationcredentials\.Create\|applicationcredentials\.Delete\|applicationcredentials\.DeleteAccessRule\|applicationcredentials\.Get\|applicationcredentials\.GetAccessRule\|attachinterfaces\.Create\|attachinterfaces\.Delete\|attachinterfaces\.Get\|attachments\.Complete\|attachments\.Create\|attachments\.Delete\|attachments\.Get\|attachments\.Update\|attachments\.WaitForStatus\|backups\.Create\|backups\.Delete\|backups\.Export\|backups\.ForceDelete\|backups\.Get\|backups\.Import\|backups\.ResetStatus\|backups\.RestoreFromBackup\|backups\.Update\|bgpvpns\.Create\|bgpvpns\.CreateNetworkAssociation\|bgpvpns\.CreatePortAssociation\|bgpvpns\.CreateRouterAssociation\|bgpvpns\.Delete\|bgpvpns\.DeleteNetworkAssociation\|bgpvpns\.DeletePortAssociation\|bgpvpns\.DeleteRouterAssociation\|bgpvpns\.Get\|bgpvpns\.GetNetworkAssociation\|bgpvpns\.GetPortAssociation\|bgpvpns\.GetRouterAssociation\|bgpvpns\.Update\|bgpvpns\.UpdatePortAssociation\|bgpvpns\.UpdateRouterAssociation\|buildinfo\.Get\|capsules\.Create\|capsules\.Delete\|capsules\.Get\|certificates\.Create\|certificates\.Get\|certificates\.Update\|claims\.Create\|claims\.Delete\|claims\.Get\|claims\.Update\|clusters\.Create\|clusters\.Delete\|clusters\.Get\|clusters\.Resize\|clusters\.Update\|clusters\.Upgrade\|clustertemplates\.Create\|clustertemplates\.Delete\|clustertemplates\.Get\|clustertemplates\.Update\|conductors\.Get\|config\.NewProviderClient\|configurations\.Create\|configurations\.Delete\|configurations\.Get\|configurations\.GetDatastoreParam\|configurations\.GetGlobalParam\|configurations\.Replace\|configurations\.Update\|containers\.BulkDelete\|containers\.Create\|containers\.CreateConsumer\|containers\.CreateSecretRef\|containers\.Delete\|containers\.DeleteConsumer\|containers\.DeleteSecretRef\|containers\.Get\|containers\.Update\|credentials\.Create\|credentials\.Delete\|credentials\.Get\|credentials\.Update\|crontriggers\.Create\|crontriggers\.Delete\|crontriggers\.Get\|databases\.Create\|databases\.Delete\|datastores\.Get\|datastores\.GetVersion\|diagnostics\.Get\|domains\.Create\|domains\.Delete\|domains\.Get\|domains\.Update\|drivers\.GetDriverDetails\|drivers\.GetDriverDiskProperties\|drivers\.GetDriverProperties\|ec2credentials\.Create\|ec2credentials\.Delete\|ec2credentials\.Get\|ec2tokens\.Create\|ec2tokens\.ValidateS3Token\|endpointgroups\.Create\|endpointgroups\.Delete\|endpointgroups\.Get\|endpointgroups\.Update\|endpoints\.Create\|endpoints\.Delete\|endpoints\.Update\|executions\.Create\|executions\.Delete\|executions\.Get\|extensions\.Get\|extraroutes\.Add\|extraroutes\.Remove\|federation\.CreateMapping\|federation\.DeleteMapping\|federation\.GetMapping\|federation\.UpdateMapping\|flavorprofiles\.Create\|flavorprofiles\.Delete\|flavorprofiles\.Get\|flavorprofiles\.Update\|flavors\.AddAccess\|flavors\.Create\|flavors\.CreateExtraSpecs\|flavors\.Delete\|flavors\.DeleteExtraSpec\|flavors\.Get\|flavors\.GetExtraSpec\|flavors\.ListExtraSpecs\|flavors\.RemoveAccess\|flavors\.Update\|flavors\.UpdateExtraSpec\|floatingips\.Create\|floatingips\.Delete\|floatingips\.Get\|floatingips\.Update\|gophercloud\.WaitFor\|groups\.Create\|groups\.Delete\|groups\.Get\|groups\.RemoveEgressPolicy\|groups\.RemoveIngressPolicy\|groups\.Update\|hypervisors\.Get\|hypervisors\.GetStatistics\|hypervisors\.GetUptime\|ikepolicies\.Create\|ikepolicies\.Delete\|ikepolicies\.Get\|ikepolicies\.Update\|imagedata\.Download\|imagedata\.Stage\|imagedata\.Upload\|imageimport\.Create\|imageimport\.Get\|images\.Create\|images\.Delete\|images\.Get\|images\.Update\|instanceactions\.Get\|instances\.AttachConfigurationGroup\|instances\.Create\|instances\.Delete\|instances\.DetachConfigurationGroup\|instances\.EnableRootUser\|instances\.Get\|instances\.IsRootEnabled\|instances\.Resize\|instances\.ResizeVolume\|instances\.Restart\|introspection\.AbortIntrospection\|introspection\.GetIntrospectionData\|introspection\.GetIntrospectionStatus\|introspection\.ReApplyIntrospection\|introspection\.StartIntrospection\|ipsecpolicies\.Create\|ipsecpolicies\.Delete\|ipsecpolicies\.Get\|ipsecpolicies\.Update\|keypairs\.Create\|keypairs\.Delete\|keypairs\.Get\|l7policies\.Create\|l7policies\.CreateRule\|l7policies\.Delete\|l7policies\.DeleteRule\|l7policies\.Get\|l7policies\.GetRule\|l7policies\.Update\|l7policies\.UpdateRule\|limits\.BatchCreate\|limits\.Delete\|limits\.Get\|limits\.GetEnforcementModel\|limits\.Update\|listeners\.Create\|listeners\.Delete\|listeners\.Get\|listeners\.GetStats\|listeners\.Update\|loadbalancers\.Create\|loadbalancers\.Delete\|loadbalancers\.Failover\|loadbalancers\.Get\|loadbalancers\.GetStats\|loadbalancers\.GetStatuses\|loadbalancers\.Update\|members\.Create\|members\.Delete\|members\.Get\|members\.Update\|messages\.Create\|messages\.Delete\|messages\.DeleteMessages\|messages\.Get\|messages\.GetMessages\|messages\.PopMessages\|monitors\.Create\|monitors\.Delete\|monitors\.Get\|monitors\.Update\|networkipavailabilities\.Get\|networks\.Create\|networks\.Delete\|networks\.Get\|networks\.Update\|nodegroups\.Create\|nodegroups\.Delete\|nodegroups\.Get\|nodegroups\.Update\|nodes\.AttachVirtualMedia\|nodes\.ChangePowerState\|nodes\.ChangeProvisionState\|nodes\.Create\|nodes\.CreateSubscription\|nodes\.Delete\|nodes\.DeleteSubscription\|nodes\.DetachVirtualMedia\|nodes\.Get\|nodes\.GetAllSubscriptions\|nodes\.GetBIOSSetting\|nodes\.GetBootDevice\|nodes\.GetInventory\|nodes\.GetSubscription\|nodes\.GetSupportedBootDevices\|nodes\.GetVendorPassthruMethods\|nodes\.InjectNMI\|nodes\.ListBIOSSettings\|nodes\.ListFirmware\|nodes\.SetBootDevice\|nodes\.SetMaintenance\|nodes\.SetRAIDConfig\|nodes\.UnsetMaintenance\|nodes\.Update\|nodes\.Validate\|nodes\.WaitForProvisionState\|oauth1\.AuthorizeToken\|oauth1\.Create\|oauth1\.CreateAccessToken\|oauth1\.CreateConsumer\|oauth1\.DeleteConsumer\|oauth1\.GetAccessToken\|oauth1\.GetAccessTokenRole\|oauth1\.GetConsumer\|oauth1\.RequestToken\|oauth1\.RevokeAccessToken\|oauth1\.UpdateConsumer\|objects\.BulkDelete\|objects\.Copy\|objects\.Create\|objects\.CreateTempURL\|objects\.Delete\|objects\.Download\|objects\.Get\|objects\.Update\|openstack\.Authenticate\|openstack\.AuthenticatedClient\|openstack\.AuthenticateV2\|openstack\.AuthenticateV3\|orders\.Create\|orders\.Delete\|orders\.Get\|osinherit\.Assign\|osinherit\.Unassign\|osinherit\.Validate\|pagination\.Request\|peers\.Create\|peers\.Delete\|peers\.Get\|peers\.Update\|policies\.Create\|policies\.Delete\|policies\.Get\|policies\.InsertRule\|policies\.RemoveRule\|policies\.Update\|pools\.BatchUpdateMembers\|pools\.Create\|pools\.CreateMember\|pools\.Delete\|pools\.DeleteMember\|pools\.Get\|pools\.GetMember\|pools\.Update\|pools\.UpdateMember\|portforwarding\.Create\|portforwarding\.Delete\|portforwarding\.Get\|portforwarding\.Update\|ports\.Create\|ports\.Delete\|ports\.Get\|ports\.Update\|projectendpoints\.Create\|projectendpoints\.Delete\|projects\.Create\|projects\.Delete\|projects\.DeleteTags\|projects\.Get\|projects\.ListTags\|projects\.ModifyTags\|projects\.Update\|qos\.Associate\|qos\.Create\|qos\.Delete\|qos\.DeleteKeys\|qos\.Disassociate\|qos\.DisassociateAll\|qos\.Get\|qos\.Update\|queues\.Create\|queues\.Delete\|queues\.Get\|queues\.GetStats\|queues\.Purge\|queues\.Share\|queues\.Update\|quotas\.Create\|quotasets\.Delete\|quotasets\.Get\|quotasets\.GetDefaults\|quotasets\.GetDetail\|quotasets\.GetUsage\|quotasets\.Update\|quotas\.Get\|quotas\.GetDetail\|quotas\.Update\|rbacpolicies\.Create\|rbacpolicies\.Delete\|rbacpolicies\.Get\|rbacpolicies\.Update\|recordsets\.Create\|recordsets\.Delete\|recordsets\.Get\|recordsets\.Update\|regions\.Create\|regions\.Delete\|regions\.Get\|regions\.Update\|registeredlimits\.BatchCreate\|registeredlimits\.Delete\|registeredlimits\.Get\|registeredlimits\.Update\|remoteconsoles\.Create\|replicas\.Create\|replicas\.Delete\|replicas\.ForceDelete\|replicas\.Get\|replicas\.GetExportLocation\|replicas\.ListExportLocations\|replicas\.Promote\|replicas\.ResetState\|replicas\.ResetStatus\|replicas\.Resync\|request\.Create\|request\.Delete\|request\.Get\|request\.Update\|resourceproviders\.Create\|resourceproviders\.Delete\|resourceproviders\.Get\|resourceproviders\.GetAllocations\|resourceproviders\.GetInventories\|resourceproviders\.GetTraits\|resourceproviders\.GetUsages\|resourceproviders\.Update\|resourcetypes\.GenerateTemplate\|resourcetypes\.GetSchema\|resourcetypes\.List\|roles\.AddUser\|roles\.Assign\|roles\.Create\|roles\.CreateRoleInferenceRule\|roles\.Delete\|roles\.DeleteRoleInferenceRule\|roles\.DeleteUser\|roles\.Get\|roles\.GetRoleInferenceRule\|roles\.ListRoleInferenceRules\|roles\.Unassign\|roles\.Update\|routers\.AddInterface\|routers\.Create\|routers\.Delete\|routers\.Get\|routers\.RemoveInterface\|routers\.Update\|rules\.Create\|rules\.CreateBandwidthLimitRule\|rules\.CreateDSCPMarkingRule\|rules\.CreateMinimumBandwidthRule\|rules\.Delete\|rules\.DeleteBandwidthLimitRule\|rules\.DeleteDSCPMarkingRule\|rules\.DeleteMinimumBandwidthRule\|rules\.Get\|rules\.GetBandwidthLimitRule\|rules\.GetDSCPMarkingRule\|rules\.GetMinimumBandwidthRule\|rules\.Update\|rules\.UpdateBandwidthLimitRule\|rules\.UpdateDSCPMarkingRule\|rules\.UpdateMinimumBandwidthRule\|ruletypes\.GetRuleType\|secgroups\.AddServer\|secgroups\.Create\|secgroups\.CreateRule\|secgroups\.Delete\|secgroups\.DeleteRule\|secgroups\.Get\|secgroups\.RemoveServer\|secgroups\.Update\|secrets\.Create\|secrets\.CreateMetadata\|secrets\.CreateMetadatum\|secrets\.Delete\|secrets\.DeleteMetadatum\|secrets\.Get\|secrets\.GetMetadata\|secrets\.GetMetadatum\|secrets\.GetPayload\|secrets\.Update\|secrets\.UpdateMetadatum\|securityservices\.Create\|securityservices\.Delete\|securityservices\.Get\|securityservices\.Update\|servergroups\.Create\|servergroups\.Delete\|servergroups\.Get\|servers\.ChangeAdminPassword\|servers\.ConfirmResize\|servers\.Create\|servers\.CreateImage\|servers\.CreateMetadatum\|servers\.Delete\|servers\.DeleteMetadatum\|servers\.Evacuate\|servers\.ForceDelete\|servers\.Get\|servers\.GetPassword\|servers\.InjectNetworkInfo\|servers\.LiveMigrate\|servers\.Lock\|servers\.Metadata\|servers\.Metadatum\|servers\.Migrate\|servers\.Pause\|servers\.Reboot\|servers\.Rebuild\|servers\.Rescue\|servers\.ResetMetadata\|servers\.ResetNetwork\|servers\.ResetState\|servers\.Resize\|servers\.Resume\|servers\.RevertResize\|servers\.Shelve\|servers\.ShelveOffload\|servers\.ShowConsoleOutput\|servers\.Start\|servers\.Stop\|servers\.Suspend\|servers\.Unlock\|servers\.Unpause\|servers\.Unrescue\|servers\.Unshelve\|servers\.Update\|servers\.UpdateMetadata\|servers\.WaitForStatus\|services\.Create\|services\.Delete\|services\.Get\|services\.Update\|shareaccessrules\.Get\|shareaccessrules\.List\|sharenetworks\.AddSecurityService\|sharenetworks\.Create\|sharenetworks\.Delete\|sharenetworks\.Get\|sharenetworks\.RemoveSecurityService\|sharenetworks\.Update\|shares\.Create\|shares\.Delete\|shares\.DeleteMetadatum\|shares\.Extend\|shares\.ForceDelete\|shares\.Get\|shares\.GetExportLocation\|shares\.GetMetadata\|shares\.GetMetadatum\|shares\.GrantAccess\|shares\.ListAccessRights\|shares\.ListExportLocations\|shares\.ResetStatus\|shares\.Revert\|shares\.RevokeAccess\|shares\.SetMetadata\|shares\.Shrink\|shares\.Unmanage\|shares\.Update\|shares\.UpdateMetadata\|sharetransfers\.Accept\|sharetransfers\.Create\|sharetransfers\.Delete\|sharetransfers\.Get\|sharetypes\.AddAccess\|sharetypes\.Create\|sharetypes\.Delete\|sharetypes\.GetDefault\|sharetypes\.GetExtraSpecs\|sharetypes\.RemoveAccess\|sharetypes\.SetExtraSpecs\|sharetypes\.ShowAccess\|sharetypes\.UnsetExtraSpecs\|siteconnections\.Create\|siteconnections\.Delete\|siteconnections\.Get\|siteconnections\.Update\|snapshots\.Create\|snapshots\.Delete\|snapshots\.ForceDelete\|snapshots\.Get\|snapshots\.ResetStatus\|snapshots\.Update\|snapshots\.UpdateMetadata\|snapshots\.UpdateStatus\|snapshots\.WaitForStatus\|speakers\.AddBGPPeer\|speakers\.AddGatewayNetwork\|speakers\.Create\|speakers\.Delete\|speakers\.Get\|speakers\.RemoveBGPPeer\|speakers\.RemoveGatewayNetwork\|speakers\.Update\|stackevents\.Find\|stackevents\.Get\|stackresources\.Find\|stackresources\.Get\|stackresources\.MarkUnhealthy\|stackresources\.Metadata\|stackresources\.Schema\|stackresources\.Template\|stacks\.Abandon\|stacks\.Adopt\|stacks\.Create\|stacks\.Delete\|stacks\.Find\|stacks\.Get\|stacks\.Preview\|stacks\.Update\|stacks\.UpdatePatch\|stacktemplates\.Get\|stacktemplates\.Validate\|subnetpools\.Create\|subnetpools\.Delete\|subnetpools\.Get\|subnetpools\.Update\|subnets\.Create\|subnets\.Delete\|subnets\.Get\|subnets\.Update\|swauth\.Auth\|swauth\.NewObjectStorageV1\|tags\.Add\|tags\.Check\|tags\.Delete\|tags\.DeleteAll\|tags\.List\|tags\.ReplaceAll\|tasks\.Create\|tasks\.Get\|tenants\.Create\|tenants\.Delete\|tenants\.Get\|tenants\.Update\|tokens\.Create\|tokens\.Get\|tokens\.Revoke\|tokens\.Validate\|transfers\.Accept\|transfers\.Create\|transfers\.Delete\|transfers\.Get\|trunks\.AddSubports\|trunks\.Create\|trunks\.Delete\|trunks\.Get\|trunks\.GetSubports\|trunks\.RemoveSubports\|trunks\.Update\|trusts\.CheckRole\|trusts\.Create\|trusts\.Delete\|trusts\.Get\|trusts\.GetRole\|users\.AddToGroup\|users\.ChangePassword\|users\.Create\|users\.Delete\|users\.Get\|users\.IsMemberOfGroup\|users\.RemoveFromGroup\|users\.Update\|utils\.ChooseVersion\|utils\.GetSupportedMicroversions\|utils\.RequireMicroversion\|volumeattach\.Create\|volumeattach\.Delete\|volumeattach\.Get\|volumes\.Attach\|volumes\.BeginDetaching\|volumes\.ChangeType\|volumes\.Create\|volumes\.Delete\|volumes\.Detach\|volumes\.ExtendSize\|volumes\.ForceDelete\|volumes\.Get\|volumes\.InitializeConnection\|volumes\.ReImage\|volumes\.Reserve\|volumes\.ResetStatus\|volumes\.SetBootable\|volumes\.SetImageMetadata\|volumes\.TerminateConnection\|volumes\.Unreserve\|volumes\.Update\|volumes\.UploadImage\|volumes\.WaitForStatus\|volumetypes\.AddAccess\|volumetypes\.Create\|volumetypes\.CreateEncryption\|volumetypes\.CreateExtraSpecs\|volumetypes\.Delete\|volumetypes\.DeleteEncryption\|volumetypes\.DeleteExtraSpec\|volumetypes\.Get\|volumetypes\.GetEncryption\|volumetypes\.GetEncryptionSpec\|volumetypes\.GetExtraSpec\|volumetypes\.ListExtraSpecs\|volumetypes\.RemoveAccess\|volumetypes\.Update\|volumetypes\.UpdateEncryption\|volumetypes\.UpdateExtraSpec\|workflows\.Create\|workflows\.Delete\|workflows\.Get\|zones\.Create\|zones\.Delete\|zones\.Get\|zones\.Update\)(#\1(context.TODO(), #g
   608          s#\(\.AllPages(\)#\1context.TODO(), #g
   609          s#\(\.EachPage(\)\(func(\)#\1context.TODO(), \2ctx context.Context, #g
   610  
   611          # 8: Rename identifiers that were changed in v2
   612          s#\(\(volumes\|servers\)\.SchedulerHint\)s#\2.SchedulerHintOpts#g
   613  
   614          # 9: Tentatively replace error handling
   615          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault400); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusBadRequest) {#g
   616          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault401); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusUnauthorized) {#g
   617          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault403); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusForbidden) {#g
   618          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault404); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusNotFound) {#g
   619          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault405); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusMethodNotAllowed) {#g
   620          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault408); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusRequestTimeout) {#g
   621          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault409); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusConflict) {#g
   622          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault429); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusTooManyRequests) {#g
   623          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault500); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusInternalServerError) {#g
   624          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault502); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusBadGateway) {#g
   625          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault503); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusServiceUnavailable) {#g
   626          s#\(\t\+\)if _, ok := err.(gophercloud.ErrDefault504); \(!\?\)ok {#\1if \2gophercloud.ResponseCodeIs(err, http.StatusGatewayTimeout) {#g
   627      }
   628      ' {} \;
   629  
   630  grep -r -l 'context\.TODO' | xargs -r sed -i '
   631      /^import ($/ a  "context"
   632      '
   633  
   634  grep -r -l 'http\.Status' | xargs -r sed -i '
   635      /^import ($/ a  "net/http"
   636      '
   637  
   638  goimports -format-only -w .
   639  go mod tidy
   640  ```