зеркало из https://github.com/Azure/AzureRMR.git
2.3.6.9000 update (#17)
* resource methods
* add tests
* document
* update news
* add example
* slight adjustment
* change org
* move util fns to AzureGraph
* update news
* require latest AzureGraph
* use aad v2.0, switch back to AzureR
* Revert "use aad v2.0, switch back to AzureR"
This reverts commit 53fa77465f
.
* really revert to Azure
* better repo check
* update news
* switch to aad v2
* bump version no
* use dev version no for now
* fix bug in obtaining graph token
* update news
* AzureGraph changes merged
This commit is contained in:
Родитель
68c2115041
Коммит
4771f109c4
|
@ -6,7 +6,7 @@ name: R-CMD-check
|
|||
|
||||
jobs:
|
||||
R-CMD-check:
|
||||
if: github.repository_owner == 'Azure'
|
||||
if: github.repository_owner != 'cloudyr'
|
||||
runs-on: ${{ matrix.config.os }}
|
||||
|
||||
name: ${{ matrix.config.os }} (${{ matrix.config.r }})
|
||||
|
@ -29,7 +29,7 @@ jobs:
|
|||
fetch-depth: 0 # required for mirroring, see https://stackoverflow.com/a/64272409/474349
|
||||
|
||||
- name: Copy to Cloudyr
|
||||
if: runner.os == 'Linux' && github.ref == 'refs/heads/master'
|
||||
if: runner.os == 'Linux' && github.ref == 'refs/heads/master' && github.repository_owner == 'Azure'
|
||||
env:
|
||||
token: "${{ secrets.ghPat }}"
|
||||
# git config hack required, see https://stackoverflow.com/q/64270867/474349
|
||||
|
@ -91,7 +91,7 @@ jobs:
|
|||
path: check
|
||||
|
||||
- name: Update Cloudyr drat
|
||||
if: success() && runner.os == 'Linux' && github.ref == 'refs/heads/master'
|
||||
if: success() && runner.os == 'Linux' && github.ref == 'refs/heads/master' && github.repository_owner == 'Azure'
|
||||
env:
|
||||
token: "${{ secrets.ghPat }}"
|
||||
run: |
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
Package: AzureRMR
|
||||
Title: Interface to 'Azure Resource Manager'
|
||||
Version: 2.3.6
|
||||
Version: 2.3.6.9000
|
||||
Authors@R: c(
|
||||
person("Hong", "Ooi", , "hongooi73@gmail.com", role = c("aut", "cre")),
|
||||
person("Microsoft", role="cph")
|
||||
|
@ -13,7 +13,7 @@ VignetteBuilder: knitr
|
|||
Depends:
|
||||
R (>= 3.3)
|
||||
Imports:
|
||||
AzureGraph (>= 1.0.4),
|
||||
AzureGraph (>= 1.1.2.9000),
|
||||
AzureAuth (>= 1.2.1),
|
||||
utils,
|
||||
parallel,
|
||||
|
@ -29,3 +29,5 @@ Suggests:
|
|||
AzureStor
|
||||
Roxygen: list(markdown=TRUE, r6=FALSE, old_usage=TRUE)
|
||||
RoxygenNote: 7.1.1
|
||||
Remotes:
|
||||
Azure/AzureGraph
|
||||
|
|
2
LICENSE
2
LICENSE
|
@ -1,2 +1,2 @@
|
|||
YEAR: 2018
|
||||
YEAR: 2018-2021
|
||||
COPYRIGHT HOLDER: Microsoft
|
||||
|
|
|
@ -49,4 +49,5 @@ export(pool_map)
|
|||
export(pool_sapply)
|
||||
export(pool_size)
|
||||
import(AzureAuth)
|
||||
import(AzureGraph)
|
||||
importFrom(utils,modifyList)
|
||||
|
|
7
NEWS.md
7
NEWS.md
|
@ -1,3 +1,10 @@
|
|||
# AzureRMR 2.3.6.9000
|
||||
|
||||
- Some utility functions moved to AzureGraph package. These are imported and then reexported by AzureRMR so that existing code should work unchanged.
|
||||
- Add methods to get, create and delete sub-resources of a resource, eg `res$get_subresource(type="subrestype", name="subresname")`. See `az_resource` for more information.
|
||||
- Fix a bug in obtaining the Microsoft Graph login when using AAD v2.0.
|
||||
- Switch to AAD v2.0 as the default for authenticating.
|
||||
|
||||
# AzureRMR 2.3.6
|
||||
|
||||
- Add ability to specify user-defined functions in `build_template_definition`. Also allow changing the schema, content version and api profile.
|
||||
|
|
13
R/AzureRMR.R
13
R/AzureRMR.R
|
@ -1,7 +1,20 @@
|
|||
#' @import AzureAuth
|
||||
#' @import AzureGraph
|
||||
#' @importFrom utils modifyList
|
||||
NULL
|
||||
|
||||
#' @export
|
||||
AzureGraph::named_list
|
||||
|
||||
#' @export
|
||||
AzureGraph::is_empty
|
||||
|
||||
#' @export
|
||||
AzureGraph::format_public_fields
|
||||
|
||||
#' @export
|
||||
AzureGraph::format_public_methods
|
||||
|
||||
utils::globalVariables(c("self", "private", "pool"))
|
||||
|
||||
.onLoad <- function(libname, pkgname)
|
||||
|
|
16
R/az_login.R
16
R/az_login.R
|
@ -8,6 +8,8 @@
|
|||
#' @param auth_type The OAuth authentication method to use, one of "client_credentials", "authorization_code", "device_code" or "resource_owner". If `NULL`, this is chosen based on the presence of the `username` and `password` arguments.
|
||||
#' @param host Your ARM host. Defaults to `https://management.azure.com/`. Change this if you are using a government or private cloud.
|
||||
#' @param aad_host Azure Active Directory host for authentication. Defaults to `https://login.microsoftonline.com/`. Change this if you are using a government or private cloud.
|
||||
#' @param version The Azure Active Directory version to use for authenticating.
|
||||
#' @param scopes The Azure Service Management scopes (permissions) to obtain for this login. Only for `version=2`.
|
||||
#' @param config_file Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI `az ad sp create-for-rbac` command.
|
||||
#' @param token Optionally, an OAuth 2.0 token, of class [AzureToken]. This allows you to reuse the authentication details for an existing session. If supplied, the other arguments above to `create_azure_login` will be ignored.
|
||||
#' @param graph_host The Microsoft Graph endpoint. See 'Microsoft Graph integration' below.
|
||||
|
@ -66,9 +68,10 @@
|
|||
#' @rdname azure_login
|
||||
#' @export
|
||||
create_azure_login <- function(tenant="common", app=.az_cli_app_id,
|
||||
password=NULL, username=NULL, certificate=NULL, auth_type=NULL,
|
||||
password=NULL, username=NULL, certificate=NULL, auth_type=NULL, version=2,
|
||||
host="https://management.azure.com/", aad_host="https://login.microsoftonline.com/",
|
||||
config_file=NULL, token=NULL, graph_host="https://graph.microsoft.com/", ...)
|
||||
scopes=".default", config_file=NULL, token=NULL,
|
||||
graph_host="https://graph.microsoft.com/", ...)
|
||||
{
|
||||
if(!is_azure_token(token))
|
||||
{
|
||||
|
@ -84,7 +87,11 @@ create_azure_login <- function(tenant="common", app=.az_cli_app_id,
|
|||
tenant <- normalize_tenant(tenant)
|
||||
app <- normalize_guid(app)
|
||||
|
||||
token_args <- list(resource=host,
|
||||
newhost <- if(version == 2)
|
||||
c(paste0(host, scopes), "openid", "offline_access")
|
||||
else host
|
||||
|
||||
token_args <- list(resource=newhost,
|
||||
tenant=tenant,
|
||||
app=app,
|
||||
password=password,
|
||||
|
@ -92,6 +99,7 @@ create_azure_login <- function(tenant="common", app=.az_cli_app_id,
|
|||
certificate=certificate,
|
||||
auth_type=auth_type,
|
||||
aad_host=aad_host,
|
||||
version=version,
|
||||
...)
|
||||
|
||||
hash <- do.call(token_hash, token_args)
|
||||
|
@ -114,7 +122,7 @@ create_azure_login <- function(tenant="common", app=.az_cli_app_id,
|
|||
arm_logins[[tenant]] <- sort(unique(c(arm_logins[[tenant]], client$token$hash())))
|
||||
save_arm_logins(arm_logins)
|
||||
|
||||
make_graph_login_from_token(token, aad_host, graph_host)
|
||||
make_graph_login_from_token(token, host, graph_host)
|
||||
|
||||
client
|
||||
}
|
||||
|
|
|
@ -10,6 +10,9 @@
|
|||
#' - `sync_fields()`: Synchronise the R object with the resource it represents in Azure. Returns the `properties$provisioningState` field, so you can query this programmatically to check if a resource has finished provisioning. Not all resource types require explicit provisioning, in which case this method will return NULL.
|
||||
#' - `set_api_version(api_version, stable_only=TRUE)`: Set the API version to use when interacting with the host. If `api_version` is not supplied, use the latest version available, either the latest stable version (if `stable_only=TRUE`) or the latest preview version (if `stable_only=FALSE`).
|
||||
#' - `get_api_version()`: Get the current API version.
|
||||
#' - `get_subresource(type, name)`: Get a sub-resource of this resource. See 'Sub-resources' below.
|
||||
#' - `create_subresource(type, name, ...)`: Create a sub-resource of this resource.
|
||||
#' - `delete_subresource(type, name, confirm=TRUE)`: Delete a sub-resource of this resource.
|
||||
#' - `do_operation(...)`: Carry out an operation. See 'Operations' for more details.
|
||||
#' - `set_tags(..., keep_existing=TRUE)`: Set the tags on this resource. The tags can be either names or name-value pairs. To delete a tag, set it to `NULL`.
|
||||
#' - `get_tags()`: Get the tags on this resource.
|
||||
|
@ -54,6 +57,17 @@
|
|||
#'
|
||||
#' Consult the Azure documentation for your resource to find out what operations are supported.
|
||||
#'
|
||||
#' @section Sub-resources:
|
||||
#' Some resource types can have sub-resources: objects exposed by Resource Manager that make up a part of their parent's functionality. For example, a storage account (type `Microsoft.Storage/storageAccounts`) provides the blob storage service, which can be accessed via Resource Manager as a sub-resource of type `Microsoft.Storage/storageAccounts/blobServices/default`.
|
||||
#'
|
||||
#' To retrieve an existing sub-resource, use the `get_subresource()` method. You do not need to include the parent resource's type and name. For example, if `res` is a resource for a storage account, and you want to retrieve the sub-resource for the blob container "myblobs", call
|
||||
#'
|
||||
#' ```
|
||||
#' res$get_subresource(type="blobServices/default/containers", name="myblobs")
|
||||
#' ```
|
||||
#'
|
||||
#' Notice that the storage account's resource type and name are omitted from the `get_subresource` arguments. Similarly, to create a new subresource, call the `create_subresource()` method with the same naming convention, passing any required fields as named arguments; and to delete it, call `delete_subresource()`.
|
||||
#'
|
||||
#' @section Role-based access control:
|
||||
#' AzureRMR implements a subset of the full RBAC functionality within Azure Active Directory. You can retrieve role definitions and add and remove role assignments, at the subscription, resource group and resource levels. See [rbac] for more information.
|
||||
#'
|
||||
|
@ -106,7 +120,12 @@
|
|||
#' # sync with Azure: useful to track resource creation/update status
|
||||
#' vm$sync_fields()
|
||||
#'
|
||||
#' # delete a resource
|
||||
#' ## subresource: create a public blob container
|
||||
#' stor$create_subresource(type="blobservices/default/containers", name="mycontainer",
|
||||
#' properties=list(publicAccess="container"))
|
||||
#'
|
||||
#' ## delete a subresource and resource
|
||||
#' stor$delete_subresource(type="blobservices/default/containers", name="mycontainer")
|
||||
#' stor$delete()
|
||||
#'
|
||||
#' }
|
||||
|
@ -234,6 +253,33 @@ public=list(
|
|||
invisible(NULL)
|
||||
},
|
||||
|
||||
get_subresource=function(type, name, id, api_version=NULL)
|
||||
{
|
||||
name <- file.path(self$name, type, name)
|
||||
az_resource$new(self$token, self$subscription,
|
||||
resource_group=self$resource_group, type=self$type, name=name, id=id,
|
||||
api_version=api_version)
|
||||
},
|
||||
|
||||
create_subresource=function(type, name, id, location=self$location, ...)
|
||||
{
|
||||
name <- file.path(self$name, type, name)
|
||||
az_resource$new(self$token, self$subscription,
|
||||
resource_group=self$resource_group, type=self$type, name=name, id=id,
|
||||
location=location, ...)
|
||||
},
|
||||
|
||||
delete_subresource=function(type, name, id, api_version=NULL, confirm=TRUE, wait=FALSE)
|
||||
{
|
||||
name <- file.path(self$name, type, name)
|
||||
# supply deployed_properties arg to prevent querying host for resource info
|
||||
az_resource$
|
||||
new(self$token, self$subscription, self$resource_group,
|
||||
type=self$type, name=name, id=id,
|
||||
deployed_properties=list(NULL), api_version=api_version)$
|
||||
delete(confirm=confirm, wait=wait)
|
||||
},
|
||||
|
||||
do_operation=function(..., options=list(), http_verb="GET")
|
||||
{
|
||||
private$res_op(..., options=options, http_verb=http_verb)
|
||||
|
|
12
R/az_rm.R
12
R/az_rm.R
|
@ -22,9 +22,11 @@
|
|||
#' - `username`: if `auth_type == "resource_owner"`, your username.
|
||||
#' - `certificate`: If `auth_type == "client_credentials", a certificate to authenticate with. This is a more secure alternative to using an app secret.
|
||||
#' - `auth_type`: The OAuth authentication method to use, one of "client_credentials", "authorization_code", "device_code" or "resource_owner". See [get_azure_token] for how the default method is chosen, along with some caveats.
|
||||
#' - `version`: The Azure Active Directory version to use for authenticating.
|
||||
#' - `host`: your ARM host. Defaults to `https://management.azure.com/`. Change this if you are using a government or private cloud.
|
||||
#' - `aad_host`: Azure Active Directory host for authentication. Defaults to `https://login.microsoftonline.com/`. Change this if you are using a government or private cloud.
|
||||
#' - `...`: Further arguments to pass to `get_azure_token`.
|
||||
#' - `scopes`: The Azure Service Management scopes (permissions) to obtain for this login. Only for `version=2`.
|
||||
#' - `token`: Optionally, an OAuth 2.0 token, of class [AzureToken]. This allows you to reuse the authentication details for an existing session. If supplied, all other arguments will be ignored.
|
||||
#'
|
||||
#' @section Operations:
|
||||
|
@ -72,9 +74,9 @@ public=list(
|
|||
|
||||
# authenticate and get subscriptions
|
||||
initialize=function(tenant="common", app=.az_cli_app_id,
|
||||
password=NULL, username=NULL, certificate=NULL, auth_type=NULL,
|
||||
password=NULL, username=NULL, certificate=NULL, auth_type=NULL, version=2,
|
||||
host="https://management.azure.com/", aad_host="https://login.microsoftonline.com/",
|
||||
token=NULL, ...)
|
||||
scopes=".default", token=NULL, ...)
|
||||
{
|
||||
if(is_azure_token(token))
|
||||
{
|
||||
|
@ -88,7 +90,10 @@ public=list(
|
|||
self$tenant <- normalize_tenant(tenant)
|
||||
app <- normalize_guid(app)
|
||||
|
||||
token_args <- list(resource=self$host,
|
||||
if(version == 2)
|
||||
host <- c(paste0(host, scopes), "openid", "offline_access")
|
||||
|
||||
token_args <- list(resource=host,
|
||||
tenant=self$tenant,
|
||||
app=app,
|
||||
password=password,
|
||||
|
@ -96,6 +101,7 @@ public=list(
|
|||
certificate=certificate,
|
||||
auth_type=auth_type,
|
||||
aad_host=aad_host,
|
||||
version=version,
|
||||
...)
|
||||
|
||||
self$token <- do.call(get_azure_token, token_args)
|
||||
|
|
65
R/format.R
65
R/format.R
|
@ -1,65 +0,0 @@
|
|||
#' Format an Azure object
|
||||
#'
|
||||
#' Miscellaneous functions for printing Azure R6 objects
|
||||
#'
|
||||
#' @param env An R6 object's environment for printing.
|
||||
#' @param exclude Objects in `env` to exclude from the printout.
|
||||
#'
|
||||
#' @details
|
||||
#' These functions are utilities to aid in printing Azure R6 objects. They are not meant to be called by the user.
|
||||
#'
|
||||
#' @rdname format
|
||||
#' @export
|
||||
format_public_fields <- function(env, exclude=character(0))
|
||||
{
|
||||
objnames <- ls(env)
|
||||
std_fields <- "token"
|
||||
objnames <- setdiff(objnames, c(exclude, std_fields))
|
||||
|
||||
maxwidth <- as.integer(0.8 * getOption("width"))
|
||||
|
||||
objconts <- sapply(objnames, function(n)
|
||||
{
|
||||
x <- get(n, env)
|
||||
deparsed <- if(is_empty(x) || is.function(x)) # don't print empty fields
|
||||
return(NULL)
|
||||
else if(is.list(x))
|
||||
paste0("list(", paste(names(x), collapse=", "), ")")
|
||||
else if(is.vector(x))
|
||||
{
|
||||
x <- paste0(x, collapse=", ")
|
||||
if(nchar(x) > maxwidth - nchar(n) - 10)
|
||||
x <- paste0(substr(x, 1, maxwidth - nchar(n) - 10), " ...")
|
||||
x
|
||||
}
|
||||
else deparse(x)[[1]]
|
||||
|
||||
paste0(strwrap(paste0(n, ": ", deparsed), width=maxwidth, indent=2, exdent=4),
|
||||
collapse="\n")
|
||||
}, simplify=FALSE)
|
||||
|
||||
empty <- sapply(objconts, is.null)
|
||||
objconts <- objconts[!empty]
|
||||
|
||||
# print etag at the bottom, not the top
|
||||
if("etag" %in% names(objconts))
|
||||
objconts <- c(objconts[-which(names(objconts) == "etag")], objconts["etag"])
|
||||
|
||||
paste0(paste0(objconts, collapse="\n"), "\n---\n")
|
||||
}
|
||||
|
||||
|
||||
#' @rdname format
|
||||
#' @export
|
||||
format_public_methods <- function(env)
|
||||
{
|
||||
objnames <- ls(env)
|
||||
std_methods <- c("clone", "print", "initialize")
|
||||
objnames <- setdiff(objnames, std_methods)
|
||||
is_method <- sapply(objnames, function(obj) is.function(.subset2(env, obj)))
|
||||
|
||||
maxwidth <- as.integer(0.8 * getOption("width"))
|
||||
|
||||
objnames <- strwrap(paste(objnames[is_method], collapse=", "), width=maxwidth, indent=4, exdent=4)
|
||||
paste0(" Methods:\n", paste0(objnames, collapse="\n"), "\n")
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
make_graph_login_from_token <- function(token, aad_host, graph_host)
|
||||
make_graph_login_from_token <- function(token, azure_host, graph_host)
|
||||
{
|
||||
if(is_empty(graph_host))
|
||||
return()
|
||||
|
@ -7,7 +7,7 @@ make_graph_login_from_token <- function(token, aad_host, graph_host)
|
|||
newtoken <- token$clone()
|
||||
if(is_azure_v1_token(newtoken))
|
||||
newtoken$resource <- graph_host
|
||||
else newtoken$scope <- sub(aad_host, graph_host, newtoken$scope, fixed=TRUE)
|
||||
else newtoken$scope <- c(paste0(graph_host, ".default"), "openid", "offline_access")
|
||||
|
||||
newtoken$refresh()
|
||||
|
||||
|
|
43
R/utils.R
43
R/utils.R
|
@ -1,51 +1,21 @@
|
|||
#' Miscellaneous utility functions
|
||||
#'
|
||||
#' @param lst A named list of objects.
|
||||
#' @param name_fields The components of the objects in `lst`, to be used as names.
|
||||
#' @param x For `is_url` and `is_empty`, An R object.
|
||||
#' @param x For `is_url`, An R object.
|
||||
#' @param https_only For `is_url`, whether to allow only HTTPS URLs.
|
||||
#' @param token For `get_paged_list`, an Azure OAuth token, of class [AzureToken].
|
||||
#' @param next_link_name,value_name For `get_paged_list`, the names of the next link and value components in the `lst` argument. The default values are correct for Resource Manager.
|
||||
#'
|
||||
#' @details
|
||||
#' `named_list` extracts from each object in `lst`, the components named by `name_fields`. It then constructs names for `lst` from these components, separated by a `"/"`.
|
||||
#'
|
||||
#' `get_paged_list` reconstructs a complete list of objects from a paged response. Many Resource Manager list operations will return _paged_ output, that is, the response contains a subset of all items, along with a URL to query to retrieve the next subset. `get_paged_list` retrieves each subset and returns all items in a single list.
|
||||
#'
|
||||
#' @return
|
||||
#' For `named_list`, the list that was passed in but with names. An empty input results in a _named list_ output: a list of length 0, with a `names` attribute.
|
||||
#'
|
||||
#' For `get_paged_list`, a list.
|
||||
#'
|
||||
#' For `is_url`, whether the object appears to be a URL (is character of length 1, and starts with the string `"http"`). Optionally, restricts the check to HTTPS URLs only. For `is_empty`, whether the length of the object is zero (this includes the special case of `NULL`).
|
||||
#' For `is_url`, whether the object appears to be a URL (is character of length 1, and starts with the string `"http"`). Optionally, restricts the check to HTTPS URLs only.
|
||||
#'
|
||||
#' @rdname utils
|
||||
#' @export
|
||||
named_list <- function(lst=NULL, name_fields="name")
|
||||
{
|
||||
if(is_empty(lst))
|
||||
return(structure(list(), names=character(0)))
|
||||
|
||||
lst_names <- sapply(name_fields, function(n) sapply(lst, `[[`, n))
|
||||
if(length(name_fields) > 1)
|
||||
{
|
||||
dim(lst_names) <- c(length(lst_names) / length(name_fields), length(name_fields))
|
||||
lst_names <- apply(lst_names, 1, function(nn) paste(nn, collapse="/"))
|
||||
}
|
||||
names(lst) <- lst_names
|
||||
dups <- duplicated(tolower(names(lst)))
|
||||
if(any(dups))
|
||||
{
|
||||
duped_names <- names(lst)[dups]
|
||||
warning("Some names are duplicated: ", paste(unique(duped_names), collapse=" "), call.=FALSE)
|
||||
}
|
||||
lst
|
||||
}
|
||||
|
||||
|
||||
# check if a string appears to be a http/https URL, optionally only https allowed
|
||||
#' @rdname utils
|
||||
#' @export
|
||||
is_url <- function(x, https_only=FALSE)
|
||||
{
|
||||
pat <- if(https_only) "^https://" else "^https?://"
|
||||
|
@ -53,15 +23,6 @@ is_url <- function(x, https_only=FALSE)
|
|||
}
|
||||
|
||||
|
||||
# TRUE for NULL and length-0 objects
|
||||
#' @rdname utils
|
||||
#' @export
|
||||
is_empty <- function(x)
|
||||
{
|
||||
length(x) == 0
|
||||
}
|
||||
|
||||
|
||||
# combine several pages of objects into a single list
|
||||
#' @rdname utils
|
||||
#' @export
|
||||
|
|
|
@ -19,6 +19,9 @@ Class representing a generic Azure resource.
|
|||
\item \code{sync_fields()}: Synchronise the R object with the resource it represents in Azure. Returns the \code{properties$provisioningState} field, so you can query this programmatically to check if a resource has finished provisioning. Not all resource types require explicit provisioning, in which case this method will return NULL.
|
||||
\item \code{set_api_version(api_version, stable_only=TRUE)}: Set the API version to use when interacting with the host. If \code{api_version} is not supplied, use the latest version available, either the latest stable version (if \code{stable_only=TRUE}) or the latest preview version (if \code{stable_only=FALSE}).
|
||||
\item \code{get_api_version()}: Get the current API version.
|
||||
\item \code{get_subresource(type, name)}: Get a sub-resource of this resource. See 'Sub-resources' below.
|
||||
\item \code{create_subresource(type, name, ...)}: Create a sub-resource of this resource.
|
||||
\item \code{delete_subresource(type, name, confirm=TRUE)}: Delete a sub-resource of this resource.
|
||||
\item \code{do_operation(...)}: Carry out an operation. See 'Operations' for more details.
|
||||
\item \code{set_tags(..., keep_existing=TRUE)}: Set the tags on this resource. The tags can be either names or name-value pairs. To delete a tag, set it to \code{NULL}.
|
||||
\item \code{get_tags()}: Get the tags on this resource.
|
||||
|
@ -75,6 +78,16 @@ The \code{do_operation()} method allows you to carry out arbitrary operations on
|
|||
Consult the Azure documentation for your resource to find out what operations are supported.
|
||||
}
|
||||
|
||||
\section{Sub-resources}{
|
||||
|
||||
Some resource types can have sub-resources: objects exposed by Resource Manager that make up a part of their parent's functionality. For example, a storage account (type \code{Microsoft.Storage/storageAccounts}) provides the blob storage service, which can be accessed via Resource Manager as a sub-resource of type \code{Microsoft.Storage/storageAccounts/blobServices/default}.
|
||||
|
||||
To retrieve an existing sub-resource, use the \code{get_subresource()} method. You do not need to include the parent resource's type and name. For example, if \code{res} is a resource for a storage account, and you want to retrieve the sub-resource for the blob container "myblobs", call\preformatted{res$get_subresource(type="blobServices/default/containers", name="myblobs")
|
||||
}
|
||||
|
||||
Notice that the storage account's resource type and name are omitted from the \code{get_subresource} arguments. Similarly, to create a new subresource, call the \code{create_subresource()} method with the same naming convention, passing any required fields as named arguments; and to delete it, call \code{delete_subresource()}.
|
||||
}
|
||||
|
||||
\section{Role-based access control}{
|
||||
|
||||
AzureRMR implements a subset of the full RBAC functionality within Azure Active Directory. You can retrieve role definitions and add and remove role assignments, at the subscription, resource group and resource levels. See \link{rbac} for more information.
|
||||
|
@ -121,7 +134,12 @@ vm$do_operation(http_verb="PATCH",
|
|||
# sync with Azure: useful to track resource creation/update status
|
||||
vm$sync_fields()
|
||||
|
||||
# delete a resource
|
||||
## subresource: create a public blob container
|
||||
stor$create_subresource(type="blobservices/default/containers", name="mycontainer",
|
||||
properties=list(publicAccess="container"))
|
||||
|
||||
## delete a subresource and resource
|
||||
stor$delete_subresource(type="blobservices/default/containers", name="mycontainer")
|
||||
stor$delete()
|
||||
|
||||
}
|
||||
|
|
|
@ -33,9 +33,11 @@ To authenticate with the \code{az_rm} class directly, provide the following argu
|
|||
\item \code{username}: if \code{auth_type == "resource_owner"}, your username.
|
||||
\item \code{certificate}: If `auth_type == "client_credentials", a certificate to authenticate with. This is a more secure alternative to using an app secret.
|
||||
\item \code{auth_type}: The OAuth authentication method to use, one of "client_credentials", "authorization_code", "device_code" or "resource_owner". See \link{get_azure_token} for how the default method is chosen, along with some caveats.
|
||||
\item \code{version}: The Azure Active Directory version to use for authenticating.
|
||||
\item \code{host}: your ARM host. Defaults to \verb{https://management.azure.com/}. Change this if you are using a government or private cloud.
|
||||
\item \code{aad_host}: Azure Active Directory host for authentication. Defaults to \verb{https://login.microsoftonline.com/}. Change this if you are using a government or private cloud.
|
||||
\item \code{...}: Further arguments to pass to \code{get_azure_token}.
|
||||
\item \code{scopes}: The Azure Service Management scopes (permissions) to obtain for this login. Only for \code{version=2}.
|
||||
\item \code{token}: Optionally, an OAuth 2.0 token, of class \link{AzureToken}. This allows you to reuse the authentication details for an existing session. If supplied, all other arguments will be ignored.
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,9 +9,10 @@
|
|||
\usage{
|
||||
create_azure_login(tenant = "common", app = .az_cli_app_id,
|
||||
password = NULL, username = NULL, certificate = NULL,
|
||||
auth_type = NULL, host = "https://management.azure.com/",
|
||||
aad_host = "https://login.microsoftonline.com/", config_file = NULL,
|
||||
token = NULL, graph_host = "https://graph.microsoft.com/", ...)
|
||||
auth_type = NULL, version = 2, host = "https://management.azure.com/",
|
||||
aad_host = "https://login.microsoftonline.com/", scopes = ".default",
|
||||
config_file = NULL, token = NULL,
|
||||
graph_host = "https://graph.microsoft.com/", ...)
|
||||
|
||||
get_azure_login(tenant = "common", selection = NULL, refresh = TRUE)
|
||||
|
||||
|
@ -32,10 +33,14 @@ list_azure_logins()
|
|||
|
||||
\item{auth_type}{The OAuth authentication method to use, one of "client_credentials", "authorization_code", "device_code" or "resource_owner". If \code{NULL}, this is chosen based on the presence of the \code{username} and \code{password} arguments.}
|
||||
|
||||
\item{version}{The Azure Active Directory version to use for authenticating.}
|
||||
|
||||
\item{host}{Your ARM host. Defaults to \verb{https://management.azure.com/}. Change this if you are using a government or private cloud.}
|
||||
|
||||
\item{aad_host}{Azure Active Directory host for authentication. Defaults to \verb{https://login.microsoftonline.com/}. Change this if you are using a government or private cloud.}
|
||||
|
||||
\item{scopes}{The Azure Service Management scopes (permissions) to obtain for this login. Only for \code{version=2}.}
|
||||
|
||||
\item{config_file}{Optionally, a JSON file containing any of the arguments listed above. Arguments supplied in this file take priority over those supplied on the command line. You can also use the output from the Azure CLI \verb{az ad sp create-for-rbac} command.}
|
||||
|
||||
\item{token}{Optionally, an OAuth 2.0 token, of class \link{AzureToken}. This allows you to reuse the authentication details for an existing session. If supplied, the other arguments above to \code{create_azure_login} will be ignored.}
|
||||
|
|
|
@ -1,22 +0,0 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/format.R
|
||||
\name{format_public_fields}
|
||||
\alias{format_public_fields}
|
||||
\alias{format_public_methods}
|
||||
\title{Format an Azure object}
|
||||
\usage{
|
||||
format_public_fields(env, exclude = character(0))
|
||||
|
||||
format_public_methods(env)
|
||||
}
|
||||
\arguments{
|
||||
\item{env}{An R6 object's environment for printing.}
|
||||
|
||||
\item{exclude}{Objects in \code{env} to exclude from the printout.}
|
||||
}
|
||||
\description{
|
||||
Miscellaneous functions for printing Azure R6 objects
|
||||
}
|
||||
\details{
|
||||
These functions are utilities to aid in printing Azure R6 objects. They are not meant to be called by the user.
|
||||
}
|
|
@ -1,8 +1,12 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/reexport_AzureAuth.R
|
||||
% Please edit documentation in R/AzureRMR.R, R/reexport_AzureAuth.R
|
||||
\docType{import}
|
||||
\name{reexports}
|
||||
\alias{reexports}
|
||||
\alias{named_list}
|
||||
\alias{is_empty}
|
||||
\alias{format_public_fields}
|
||||
\alias{format_public_methods}
|
||||
\alias{clean_token_directory}
|
||||
\alias{delete_azure_token}
|
||||
\alias{get_azure_token}
|
||||
|
@ -19,5 +23,7 @@ below to see their documentation.
|
|||
|
||||
\describe{
|
||||
\item{AzureAuth}{\code{\link[AzureAuth]{AzureR_dir}}, \code{\link[AzureAuth:get_azure_token]{clean_token_directory}}, \code{\link[AzureAuth:get_azure_token]{delete_azure_token}}, \code{\link[AzureAuth]{get_azure_token}}, \code{\link[AzureAuth:get_azure_token]{is_azure_token}}, \code{\link[AzureAuth:get_azure_token]{is_azure_v1_token}}, \code{\link[AzureAuth:get_azure_token]{is_azure_v1_token}}, \code{\link[AzureAuth:guid]{is_guid}}, \code{\link[AzureAuth:get_azure_token]{list_azure_tokens}}}
|
||||
|
||||
\item{AzureGraph}{\code{\link[AzureGraph:format]{format_public_fields}}, \code{\link[AzureGraph:format]{format_public_methods}}, \code{\link[AzureGraph:utils]{is_empty}}, \code{\link[AzureGraph:utils]{named_list}}}
|
||||
}}
|
||||
|
||||
|
|
22
man/utils.Rd
22
man/utils.Rd
|
@ -1,45 +1,33 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/utils.R
|
||||
\name{named_list}
|
||||
\alias{named_list}
|
||||
\name{is_url}
|
||||
\alias{is_url}
|
||||
\alias{is_empty}
|
||||
\alias{get_paged_list}
|
||||
\title{Miscellaneous utility functions}
|
||||
\usage{
|
||||
named_list(lst = NULL, name_fields = "name")
|
||||
|
||||
is_url(x, https_only = FALSE)
|
||||
|
||||
is_empty(x)
|
||||
|
||||
get_paged_list(lst, token, next_link_name = "nextLink", value_name = "value")
|
||||
}
|
||||
\arguments{
|
||||
\item{lst}{A named list of objects.}
|
||||
|
||||
\item{name_fields}{The components of the objects in \code{lst}, to be used as names.}
|
||||
|
||||
\item{x}{For \code{is_url} and \code{is_empty}, An R object.}
|
||||
\item{x}{For \code{is_url}, An R object.}
|
||||
|
||||
\item{https_only}{For \code{is_url}, whether to allow only HTTPS URLs.}
|
||||
|
||||
\item{lst}{A named list of objects.}
|
||||
|
||||
\item{token}{For \code{get_paged_list}, an Azure OAuth token, of class \link{AzureToken}.}
|
||||
|
||||
\item{next_link_name, value_name}{For \code{get_paged_list}, the names of the next link and value components in the \code{lst} argument. The default values are correct for Resource Manager.}
|
||||
}
|
||||
\value{
|
||||
For \code{named_list}, the list that was passed in but with names. An empty input results in a \emph{named list} output: a list of length 0, with a \code{names} attribute.
|
||||
|
||||
For \code{get_paged_list}, a list.
|
||||
|
||||
For \code{is_url}, whether the object appears to be a URL (is character of length 1, and starts with the string \code{"http"}). Optionally, restricts the check to HTTPS URLs only. For \code{is_empty}, whether the length of the object is zero (this includes the special case of \code{NULL}).
|
||||
For \code{is_url}, whether the object appears to be a URL (is character of length 1, and starts with the string \code{"http"}). Optionally, restricts the check to HTTPS URLs only.
|
||||
}
|
||||
\description{
|
||||
Miscellaneous utility functions
|
||||
}
|
||||
\details{
|
||||
\code{named_list} extracts from each object in \code{lst}, the components named by \code{name_fields}. It then constructs names for \code{lst} from these components, separated by a \code{"/"}.
|
||||
|
||||
\code{get_paged_list} reconstructs a complete list of objects from a paged response. Many Resource Manager list operations will return \emph{paged} output, that is, the response contains a subset of all items, along with a URL to query to retrieve the next subset. \code{get_paged_list} retrieves each subset and returns all items in a single list.
|
||||
}
|
||||
|
|
|
@ -9,15 +9,18 @@ if(tenant == "" || app == "" || password == "" || subscription == "")
|
|||
skip("Authentication tests skipped: ARM credentials not set")
|
||||
|
||||
|
||||
clean_token_directory(confirm=FALSE)
|
||||
suppressWarnings(file.remove(file.path(AzureR_dir(), "arm_logins.json")))
|
||||
|
||||
scopes <- c("https://management.azure.com/.default", "openid", "offline_access")
|
||||
|
||||
test_that("ARM authentication works",
|
||||
{
|
||||
az <- az_rm$new(tenant=tenant, app=app, password=password)
|
||||
expect_is(az, "az_rm")
|
||||
expect_true(is_azure_token(az$token))
|
||||
|
||||
tok <- get_azure_token("https://management.azure.com/", tenant, app, password)
|
||||
tok <- get_azure_token(scopes, tenant, app, password, version=2)
|
||||
az2 <- az_rm$new(token=tok)
|
||||
expect_is(az2, "az_rm")
|
||||
})
|
||||
|
@ -40,7 +43,7 @@ test_that("Login interface works",
|
|||
az5 <- get_azure_login(tenant)
|
||||
expect_is(az5, "az_rm")
|
||||
|
||||
tok <- get_azure_token("https://management.azure.com/", tenant, app, password)
|
||||
tok <- get_azure_token(scopes, tenant, app, password, version=2)
|
||||
az6 <- create_azure_login(token=tok, graph_host=NULL)
|
||||
expect_is(az6, "az_rm")
|
||||
})
|
||||
|
@ -58,6 +61,10 @@ test_that("Graph interop works",
|
|||
|
||||
gr <- AzureGraph::get_graph_login(tenant)
|
||||
expect_is(gr, "ms_graph")
|
||||
expect_true(
|
||||
(!is.null(gr$token$resource) && grepl("graph\\.microsoft\\.com", gr$token$resource)) ||
|
||||
(!is.null(gr$token$scope) && any(grepl("graph\\.microsoft\\.com", gr$token$scope)))
|
||||
)
|
||||
})
|
||||
|
||||
test_that("Top-level do_operation works",
|
||||
|
|
|
@ -67,10 +67,10 @@ test_that("List filters work",
|
|||
function(r) is_resource(r) && r$type == "Microsoft.Storage/storageAccounts" && !is_empty(r$ext$createdTime))))
|
||||
})
|
||||
|
||||
test_that("Subscription methods work with AAD v2.0",
|
||||
test_that("Subscription methods work with AAD v1.0",
|
||||
{
|
||||
token <- get_azure_token(c("https://management.azure.com/.default", "offline_access"),
|
||||
tenant=tenant, app=app, password=password, version=2)
|
||||
token <- get_azure_token("https://management.azure.com/",
|
||||
tenant=tenant, app=app, password=password, version=1)
|
||||
az <- az_rm$new(token=token)
|
||||
|
||||
subs <- az$list_subscriptions()
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
context("Sub-resources")
|
||||
|
||||
tenant <- Sys.getenv("AZ_TEST_TENANT_ID")
|
||||
app <- Sys.getenv("AZ_TEST_APP_ID")
|
||||
password <- Sys.getenv("AZ_TEST_PASSWORD")
|
||||
subscription <- Sys.getenv("AZ_TEST_SUBSCRIPTION")
|
||||
|
||||
if(tenant == "" || app == "" || password == "" || subscription == "")
|
||||
skip("Resource group method tests skipped: ARM credentials not set")
|
||||
|
||||
rgname <- paste(sample(letters, 20, replace=TRUE), collapse="")
|
||||
rg <- az_rm$
|
||||
new(tenant=tenant, app=app, password=password)$
|
||||
get_subscription(subscription)$
|
||||
create_resource_group(rgname, location="australiaeast")
|
||||
|
||||
|
||||
test_that("Resource methods work",
|
||||
{
|
||||
resname <- paste0(sample(letters, 20), collapse="")
|
||||
# resource with sub-resources
|
||||
res <- rg$create_resource(type="Microsoft.Storage/storageAccounts", name=resname,
|
||||
kind="StorageV2",
|
||||
sku=list(name="Standard_LRS"),
|
||||
wait=TRUE)
|
||||
expect_true(is_resource(res))
|
||||
|
||||
subresname <- paste0(sample(letters, 20), collapse="")
|
||||
subres <- res$create_subresource(type="blobservices/default/containers", name=subresname)
|
||||
expect_true(is_resource(subres))
|
||||
|
||||
expect_true(is_resource(res$get_subresource(type="blobservices/default/containers", name=subresname)))
|
||||
|
||||
expect_message(res$delete_subresource(type="blobservices/default/containers", name=subresname, confirm=FALSE))
|
||||
})
|
||||
|
||||
rg$delete(confirm=FALSE)
|
||||
|
||||
|
Загрузка…
Ссылка в новой задаче