* 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:
Hong Ooi 2021-01-12 05:12:38 +11:00 коммит произвёл GitHub
Родитель 68c2115041
Коммит 4771f109c4
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
21 изменённых файлов: 193 добавлений и 171 удалений

6
.github/workflows/check-standard.yaml поставляемый
Просмотреть файл

@ -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

Просмотреть файл

@ -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)

Просмотреть файл

@ -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.

Просмотреть файл

@ -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)

Просмотреть файл

@ -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)

Просмотреть файл

@ -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)

Просмотреть файл

@ -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()

Просмотреть файл

@ -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}}}
}}

Просмотреть файл

@ -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)