diff --git a/DESCRIPTION b/DESCRIPTION index e33574f..8a0767e 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -16,4 +16,5 @@ Imports: openssl, xml2, AzureRMR +Roxygen: list(markdown=TRUE) RoxygenNote: 6.0.1 diff --git a/NAMESPACE b/NAMESPACE index 16453bc..9debb56 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -1,8 +1,20 @@ # Generated by roxygen2: do not edit by hand +S3method(blob_container,blob_endpoint) +S3method(blob_container,character) +S3method(create_blob_container,blob_endpoint) +S3method(create_blob_container,character) +S3method(delete_blob_container,blob_endpoint) +S3method(delete_blob_container,character) +S3method(file_share,character) +S3method(file_share,file_endpoint) S3method(get_storage_properties,blob_container) S3method(get_storage_properties,file_share) S3method(get_storage_properties,storage_endpoint) +S3method(list_blob_containers,blob_endpoint) +S3method(list_blob_containers,character) +S3method(list_file_shares,character) +S3method(list_file_shares,file_share) export(acquire_lease) export(az_storage) export(blob_container) @@ -11,11 +23,13 @@ export(change_lease) export(create_azure_dir) export(create_blob_container) export(create_file_share) +export(create_file_share.character) export(delete_azure_dir) export(delete_azure_file) export(delete_blob) export(delete_blob_container) export(delete_file_share) +export(delete_file_share.character) export(download_azure_file) export(download_blob) export(download_from_url) diff --git a/R/add_methods.R b/R/add_methods.R index 8db4efe..8ee6410 100644 --- a/R/add_methods.R +++ b/R/add_methods.R @@ -1,17 +1,150 @@ -## extend resource group methods -AzureRMR::az_resource_group$set("public", "create_storage", function(name, location, ...) +# documentation is separate from implementation because roxygen still doesn't know how to handle R6 + +#' Create Azure storage account +#' +#' Method for the [AzureRMR::az_resource_group] class. +#' +#' @rdname create_storage_account +#' @name create_storage_account +#' @usage +#' create_storage_account(name, location, kind="Storage", sku=list(name="Standard_LRS", tier="Standard"), ...) +#' +#' @param name The name of the storage account. +#' @param location The location/region in which to create the account. +#' @param kind The type of account, either `"Storage"` or `"BlobStorage"`. +#' @param sku The SKU. This is a named list specifying various configuration options for the account. +#' @param ... Other named arguments to pass to the [az_storage] initialization function. +#' +#' @details +#' This method deploys a new storage account resource, with parameters given by the arguments. A storage account can host multiple types of storage: +#' - blob storage +#' - file storage +#' - table storage +#' - queue storage +#' +#' Accounts created with `kind = "BlobStorage"` can only host blob and table storage, while those with `kind = "Storage"` can host all four. +#' +#' @return +#' An object of class `az_storage` representing the created storage account. +#' +#' @seealso +#' [get_storage_account], [delete_storage_account], [az_storage], +#' [Azure Storage Provider API reference](https://docs.microsoft.com/en-us/rest/api/storagerp/) +NULL + + +#' Get existing Azure storage account(s) +#' +#' Methods for the [AzureRMR::az_resource_group] and [AzureRMR::az_subscription] classes. +#' +#' @rdname get_storage_account +#' @name get_storage_account +#' @aliases list_storage_accounts +#' +#' @usage +#' get_storage_account(name) +#' list_storage_accounts() +#' +#' @param name For `get_storage_account()`, the name of the storage account. +#' +#' @details +#' The `AzureRMR::az_resource_group` class has both `get_storage_account()` and `list_storage_accounts()` methods, while the `AzureRMR::az_subscription` class only has the latter. +#' +#' @return +#' For `get_storage_account()`, an object of class `az_storage` representing the storage account. +#' +#' For `list_storage_accounts()`, a list of such objects. +#' +#' @seealso +#' [create_storage_account], [delete_storage_account], [az_storage], +#' [Azure Storage Provider API reference](https://docs.microsoft.com/en-us/rest/api/storagerp/) +NULL + + +#' Delete an Azure storage account +#' +#' Method for the [AzureRMR::az_resource_group] class. +#' +#' @rdname delete_storage_account +#' @name delete_storage_account +#' +#' @usage +#' delete_storage_account(name, confirm=TRUE, wait=FALSE) +#' +#' @param name The name of the storage account. +#' @param confirm Whether to ask for confirmation before deleting. +#' @param wait Whether to wait until the deletion is complete. +#' +#' @return +#' NULL on successful deletion. +#' +#' @seealso +#' [create_storage_account], [get_storage_account], [az_storage], +#' [Azure Storage Provider API reference](https://docs.microsoft.com/en-us/rest/api/storagerp/) +NULL + + +AzureRMR::az_resource_group$set("public", "create_storage_account", function(name, location, ...) { az_storage$new(self$token, self$subscription, self$name, name, location=location, ...) }) -AzureRMR::az_resource_group$set("public", "get_storage", function(name) +AzureRMR::az_resource_group$set("public", "get_storage_account", function(name) { az_storage$new(self$token, self$subscription, self$name, name) }) -AzureRMR::az_resource_group$set("public", "delete_storage", function(name, confirm=TRUE, wait=FALSE) +AzureRMR::az_resource_group$set("public", "delete_storage_account", function(name, confirm=TRUE, wait=FALSE) { - self$get_storage(name)$delete(confirm=confirm, wait=wait) + self$get_storage_account(name)$delete(confirm=confirm, wait=wait) +}) + + +AzureRMR::az_resource_group$set("public", "list_storage_accounts", function(name) +{ + provider <- "Microsoft.Storage" + path <- "storageAccounts" + api_version <- az_subscription$ + new(self$token, self$subscription)$ + get_provider_api_version(provider, path) + + op <- file.path("resourceGroups", self$name, "providers", provider, path) + + cont <- call_azure_rm(self$token, self$subscription, op, api_version=api_version) + lst <- lapply(cont$value, + function(parms) az_storage$new(self$token, self$subscription, deployed_properties=parms)) + + # keep going until paging is complete + while(!is_empty(cont$nextLink)) + { + cont <- call_azure_url(self$token, cont$nextLink) + lst <- lapply(cont$value, + function(parms) az_storage$new(self$token, self$subscription, deployed_properties=parms)) + } + named_list(lst) +}) + + +AzureRMR::az_subscription$set("public", "list_storage_accounts", function(name) +{ + provider <- "Microsoft.Storage" + path <- "storageAccounts" + api_version <- self$get_provider_api_version(provider, path) + + op <- file.path("providers", provider, path) + + cont <- call_azure_rm(self$token, self$subscription, op, api_version=api_version) + lst <- lapply(cont$value, + function(parms) az_storage$new(self$token, self$subscription, deployed_properties=parms)) + + # keep going until paging is complete + while(!is_empty(cont$nextLink)) + { + cont <- call_azure_url(self$token, cont$nextLink) + lst <- lapply(cont$value, + function(parms) az_storage$new(self$token, self$subscription, deployed_properties=parms)) + } + named_list(lst) }) diff --git a/R/blob_client_funcs.R b/R/blob_client_funcs.R index e0111a7..5af8cbf 100644 --- a/R/blob_client_funcs.R +++ b/R/blob_client_funcs.R @@ -1,7 +1,72 @@ +#' Operations on a blob endpoint +#' +#' Get, list, create, or delete blob containers. +#' +#' @param endpoint Either a blob endpoint object as created by [storage_endpoint], or a character string giving the URL of the endpoint. +#' @param key, sas If an endpoint object is not supplied, authentication details. If neither an access key nor a SAS are provided, only public (anonymous) access to the share is possible. +#' @param api_version If an endpoint object is not supplied, the storage API version to use when interacting with the host. Currently defaults to `"2017-07-29"`. +#' @param name The name of the blob container to get, create, or delete. +#' @param confirm For deleting a container, whether to ask for confirmation. +#' @param lease For deleting a leased container, the lease ID. +#' @param public_access For creating a container, the level of public access to allow. +#' @param ... Further arguments passed to lower-level functions. +#' +#' @details +#' You can call these functions in a couple of ways: by passing the full URL of the share, or by passing the endpoint object and the name of the container as a string. +#' +#' @return +#' For `blob_container` and `create_blob_container`, an S3 object representing an existing or created container respectively. +#' +#' For `list_blob_containers`, a list of such objects. +#' +#' For `delete_blob_container`, NULL on successful deletion. +#' +#' @seealso [storage_endpoint], [az_storage] +#' +#' @rdname blob_endpoint #' @export -list_blob_containers <- function(endpoint) +blob_container <- function(endpoint, ...) +{ + UseMethod("blob_container") +} + +#' @rdname blob_endpoint +#' @export +blob_container.character <- function(endpoint, key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version")) +{ + do.call(blob_container, generate_endpoint_container(endpoint, key, sas, api_version)) +} + +#' @rdname blob_endpoint +#' @export +blob_container.blob_endpoint <- function(endpoint, name) +{ + obj <- list(name=name, endpoint=endpoint) + class(obj) <- "blob_container" + obj +} + + + +#' @rdname blob_endpoint +#' @export +list_blob_containers <- function(endpoint, ...) +{ + UseMethod("list_blob_containers") +} + +#' @rdname blob_endpoint +#' @export +list_blob_containers.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version")) +{ + do.call(list_blob_containers, generate_endpoint_container(endpoint, key, sas, api_version)) +} + +#' @rdname blob_endpoint +#' @export +list_blob_containers.blob_endpoint <- function(endpoint, ...) { - stopifnot(inherits(endpoint, "blob_endpoint")) lst <- do_storage_call(endpoint$url, "/", options=list(comp="list"), key=endpoint$key, sas=endpoint$sas, api_version=endpoint$api_version) @@ -10,35 +75,28 @@ list_blob_containers <- function(endpoint) } -#' @export -blob_container <- function(endpoint, name, key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version")) -{ - if(missing(name) && is_url(endpoint)) - { - stor_path <- parse_storage_url(endpoint) - endpoint <- storage_endpoint(stor_path[1], key, sas, api_version) - name <- stor_path[2] - } - obj <- list(name=name, endpoint=endpoint) - class(obj) <- "blob_container" - obj +#' @rdname blob_endpoint +#' @export +create_blob_container <- function(endpoint, ...) +{ + UseMethod("create_blob_container") } - +#' @rdname blob_endpoint #' @export -create_blob_container <- function(endpoint, name, key=NULL, sas=NULL, - api_version=getOption("azure_storage_api_version"), - public_access=c("none", "blob", "container"), - ...) +create_blob_container.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version"), + ...) { - if(missing(name) && is_url(endpoint)) - { - stor_path <- parse_storage_url(endpoint) - name <- stor_path[2] - endpoint <- storage_endpoint(stor_path[1], key, sas, api_version) - } + endp <- generate_endpoint_container(endpoint, key, sas, api_version) + create_blob_container(endp$endpoint, endp$name, ...) +} +#' @rdname blob_endpoint +#' @export +create_blob_container.blob_endpoint <- function(endpoint, public_access=c("none", "blob", "container"), ...) +{ public_access <- match.arg(public_access) headers <- if(public_access != "none") modifyList(list(...), list("x-ms-blob-public-access"=public_access)) @@ -50,13 +108,31 @@ create_blob_container <- function(endpoint, name, key=NULL, sas=NULL, } + +#' @rdname blob_endpoint #' @export -delete_blob_container <- function(container, confirm=TRUE, lease=NULL) +delete_blob_container <- function(endpoint, ...) +{ + UseMethod("delete_blob_container") +} + +#' @rdname blob_endpoint +#' @export +delete_blob_container.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version"), + ...) +{ + endp <- generate_endpoint_container(endpoint, key, sas, api_version) + delete_blob_container(endp$endpoint, endp$name, ...) +} + +#' @rdname blob_endpoint +#' @export +delete_blob_container.blob_endpoint <- function(endpoint, name, confirm=TRUE, lease=NULL) { if(confirm && interactive()) { - endp <- container$endpoint - path <- paste0(endp$url, endp$name, "/") + path <- paste0(endpoint$url, name, "/") yn <- readline(paste0("Are you sure you really want to delete the container '", path, "'? (y/N) ")) if(tolower(substr(yn, 1, 1)) != "y") return(invisible(NULL)) @@ -64,10 +140,28 @@ delete_blob_container <- function(container, confirm=TRUE, lease=NULL) headers <- if(!is_empty(lease)) list("x-ms-lease-id"=lease) else list() - do_container_op(container, options=list(restype="container"), headers=headers, http_verb="DELETE") + + obj <- blob_container(endpoint, name) + do_container_op(obj, options=list(restype="container"), headers=headers, http_verb="DELETE") } +#' Operations on a blob container +#' +#' Upload, download, or delete a blob; list blobs in a container. +#' +#' @param container A blob container object. +#' @param blob A string naming a blob. +#' @param src, dest The source and destination filenames for uploading and downloading. Paths are allowed. +#' @param confirm Whether to ask for confirmation on deleting a blob. +#' +#' @return +#' For `list_blobs`, a vector of blob names in the container. For the other functions, NULL on successful completion. +#' +#' @seealso +#' [blob_container], [az_storage] +#' +#' @rdname blob_container #' @export list_blobs <- function(container) { @@ -75,7 +169,7 @@ list_blobs <- function(container) unname(vapply(lst$Blobs, function(b) b$Name[[1]], FUN.VALUE=character(1))) } - +#' @rdname blob_container #' @export upload_blob <- function(container, src, dest, type="BlockBlob") { @@ -92,14 +186,14 @@ upload_blob <- function(container, src, dest, type="BlockBlob") http_verb="PUT") } - +#' @rdname blob_container #' @export download_blob <- function(container, src, dest, overwrite=FALSE) { do_container_op(container, src, config=httr::write_disk(dest, overwrite)) } - +#' @rdname blob_container #' @export delete_blob <- function(container, blob, confirm=TRUE) { diff --git a/R/client.R b/R/client.R index 4b31828..a79ef24 100644 --- a/R/client.R +++ b/R/client.R @@ -1,27 +1,54 @@ +#' Create a storage endpoint object +#' +#' @param endpoint The URL (hostname) for the endpoint. This must be of the form `http[s]://{account-name}.{type}.{core-host-name}`, where `type` is one of `"blob"`, `"file"`, `"queue"` or `"table"`. On the public Azure cloud, endpoints will be of the form `https://{account-name}.{type}.core.windows.net`. +#' @param key The access key for the storage account. +#' @param sas A shared access signature for the account. If neither `key` nor `sas` are provided, only public (anonymous) access to the endpoint is possible. +#' @param api_version The storage API version to use when interacting with the host. Currently defaults to `"2017-07-29"`. +#' +#' @details +#' This is the starting point for the client-side storage interface in AzureRMR. +#' +#' @return +#' An object of S3 class `"blob_endpoint"`, `"file_endpoint"`, `"queue_endpoint"` or `"table_endpoint"` depending on the type of endpoint. All of these also inherit from class `"storage_endpoint"`. +#' +#' @seealso +#' [az_storage], [file_share], [create_file_share], [blob_container], [create_blob_container] +#' +#' @aliases endpoint blob_endpoint file_endpoint queue_endpoint table_endpoint #' @export -storage_endpoint <- function(endpoint, - key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version"), - type=c("blob", "file", "queue", "table")) +storage_endpoint <- function(endpoint, key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version")) { - if(missing(type)) # determine type of endpoint from url - { - type <- sapply(type, function(x) is_endpoint_url(endpoint, x)) - if(!any(type)) - stop("Unknown endpoint type", call.=FALSE) - type <- names(type)[type] - } - else - { - type <- match.arg(type) - if(!is_endpoint_url(endpoint, type)) - stop("Unknown endpoint type", call.=FALSE) - } + if(is_empty(endpoint)) + stop("Invalid endpoint type", call.=FALSE) + + type <- sapply(c("blob", "file", "queue", "table"), + function(x) is_endpoint_url(endpoint, x)) + if(!any(type)) + stop("Unknown endpoint type", call.=FALSE) + type <- names(type)[type] + obj <- list(url=endpoint, key=key, sas=sas, api_version=api_version) class(obj) <- c(paste0(type, "_endpoint"), "storage_endpoint") obj } +#' Generic upload and download +#' +#' @param src, dest The source and destination files/URLs. Paths are allowed. +#' @param ... Further arguments to pass to lower-level functions. In particular, use `key` and/or `sas` to supply an access key or SAS. Without a key or SAS, only unauthenticated (anonymous) access is possible. +#' @param overwrite For downloading, whether to overwrite any destination files that exist. +#' +#' @details +#' These functions allow you to transfer files to and from a storage account, given the URL of the destination (for uploading) or source (for downloading). They dispatch to [upload_azure_file]/[download_azure_file] for a file storage URL and [upload_blob]/[download_blob] for a blob storage URL respectively. +#' +#' @return +#' NULL on successful completion. +#' +#' @seealso +#' [download_azure_file], [download_blob]. [az_storage] +#' +#' @rdname file_transfer #' @export download_from_url <- function(src, dest, ..., overwrite=FALSE) { @@ -42,6 +69,7 @@ download_from_url <- function(src, dest, ..., overwrite=FALSE) } +#' @rdname file_transfer #' @export upload_to_url <- function(src, dest, ...) { diff --git a/R/file_client_funcs.R b/R/file_client_funcs.R index ad6dabb..f1c09ab 100644 --- a/R/file_client_funcs.R +++ b/R/file_client_funcs.R @@ -1,7 +1,70 @@ +#' Operations on a file endpoint +#' +#' Get, list, create, or delete file shares. +#' +#' @param endpoint Either a file endpoint object as created by [storage_endpoint], or a character string giving the URL of the endpoint. +#' @param key, sas If an endpoint object is not supplied, authentication details. If neither an access key nor a SAS are provided, only public (anonymous) access to the share is possible. +#' @param api_version If an endpoint object is not supplied, the storage API version to use when interacting with the host. Currently defaults to `"2017-07-29"`. +#' @param name The name of the file share to get, create, or delete. +#' @param confirm For deleting a share, whether to ask for confirmation. +#' @param ... Further arguments passed to lower-level functions. +#' +#' @details +#' You can call these functions in a couple of ways: by passing the full URL of the share, or by passing the endpoint object and the name of the share as a string. +#' +#' @return +#' For `file_share` and `create_file_share`, an S3 object representing an existing or created share respectively. +#' +#' For `list_file_shares`, a list of such objects. +#' +#' For `delete_file_share`, NULL on successful deletion. +#' +#' @seealso [storage_endpoint], [az_storage] +#' +#' @rdname file_endpoint #' @export -list_file_shares <- function(endpoint) +file_share <- function(endpoint, ...) +{ + UseMethod("file_share") +} + +#' @rdname file_endpoint +#' @export +file_share.character <- function(endpoint, key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version")) +{ + do.call(file_share, generate_endpoint_container(endpoint, key, sas, api_version)) +} + +#' @rdname file_endpoint +#' @export +file_share.file_endpoint <- function(endpoint, name) +{ + obj <- list(name=name, endpoint=endpoint) + class(obj) <- "file_share" + obj +} + + + +#' @rdname file_endpoint +#' @export +list_file_shares <- function(endpoint, ...) +{ + UseMethod("list_file_shares") +} + +#' @rdname file_endpoint +#' @export +list_file_shares.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version")) +{ + do.call(list_file_shares, generate_endpoint_container(endpoint, key, sas, api_version)) +} + +#' @rdname file_endpoint +#' @export +list_file_shares.file_share <- function(endpoint, ...) { - stopifnot(inherits(endpoint, "file_endpoint")) lst <- do_storage_call(endpoint$url, "/", options=list(comp="list"), key=endpoint$key, sas=endpoint$sas, api_version=endpoint$api_version) @@ -10,55 +73,88 @@ list_file_shares <- function(endpoint) } -#' @export -file_share <- function(endpoint, name, key=NULL, sas=NULL, api_version=getOption("azure_storage_api_version")) -{ - if(missing(name) && is_url(endpoint)) - { - stor_path <- parse_storage_url(endpoint) - endpoint <- storage_endpoint(stor_path[1], key, sas, api_version) - name <- stor_path[2] - } - obj <- list(name=name, endpoint=endpoint) - class(obj) <- "file_share" - obj +#' @rdname file_endpoint +#' @export +create_file_share <- function(endpoint, ...) +{ + UseMethod("create_file_share") } - +#' @rdname file_endpoint #' @export -create_file_share <- function(endpoint, name, key=NULL, sas=NULL, - api_version=getOption("azure_storage_api_version"), - ...) +create_file_share.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version"), + ...) { - if(missing(name) && is_url(endpoint)) - { - stor_path <- parse_storage_url(endpoint) - name <- stor_path[2] - endpoint <- storage_endpoint(stor_path[1], key, sas, api_version) - } + endp <- generate_endpoint_container(endpoint, key, sas, api_version) + create_file_share(endp$endpoint, endp$name, ...) +} +#' @rdname file_endpoint +#' @export +create_file_share <- function(endpoint, name, ...) +{ obj <- file_share(endpoint, name) do_container_op(obj, options=list(restype="share"), headers=list(...), http_verb="PUT") obj } + +#' @rdname file_endpoint #' @export -delete_file_share <- function(share, confirm=TRUE) +delete_file_share <- function(endpoint, ...) +{ + UseMethod("delete_file_share") +} + +#' @rdname file_endpoint +#' @export +delete_file_share.character <- function(endpoint, key=NULL, sas=NULL, + api_version=getOption("azure_storage_api_version"), + ...) +{ + endp <- generate_endpoint_container(endpoint, key, sas, api_version) + delete_file_share(endp$endpoint, endp$name, ...) +} + +#' @rdname file_endpoint +#' @export +delete_file_share <- function(endpoint, name, confirm=TRUE) { if(confirm && interactive()) { - endp <- share$endpoint - path <- paste0(endp$url, endp$name, "/") + path <- paste0(endpoint$url, name, "/") yn <- readline(paste0("Are you sure you really want to delete the share '", path, "'? (y/N) ")) if(tolower(substr(yn, 1, 1)) != "y") return(invisible(NULL)) } - do_container_op(share, options=list(restype="share"), http_verb="DELETE") + + obj <- file_share(endpoint, name) + do_container_op(obj, options=list(restype="share"), http_verb="DELETE") } +#' Operations on a file share +#' +#' Upload, download, or delete a file; list files in a directory; create or delete directories. +#' +#' @param share A file share object. +#' @param dir, file A string naming a directory or file respectively. +#' @param all_info Whether to return names only, or all information in a directory listing. +#' @param src, dest The source and destination filenames for uploading and downloading. Paths are allowed. +#' @param confirm Whether to ask for confirmation on deleting a file or directory. +#' +#' @return +#' For `list_azure_files`, if `all_info=FALSE`, a vector of file/directory names. If `all_info=TRUE`, a data frame giving the file size and whether each object is a file or directory. +#' +#' For the other functions, NULL on successful completion. +#' +#' @seealso +#' [file_share], [az_storage] +#' +#' @rdname file_share #' @export list_azure_files <- function(share, dir, all_info=TRUE) { @@ -76,7 +172,7 @@ list_azure_files <- function(share, dir, all_info=TRUE) data.frame(name=name, type=type, size=as.numeric(size), stringsAsFactors=FALSE) } - +#' @rdname file_share #' @export upload_azure_file <- function(share, src, dest) { @@ -100,14 +196,14 @@ upload_azure_file <- function(share, src, dest) do_container_op(share, dest, options=options, headers=headers, body=body, http_verb="PUT") } - +#' @rdname file_share #' @export download_azure_file <- function(share, src, dest, overwrite=FALSE) { do_container_op(share, src, config=httr::write_disk(dest, overwrite)) } - +#' @rdname file_share #' @export delete_azure_file <- function(share, file, confirm=TRUE) { @@ -122,14 +218,14 @@ delete_azure_file <- function(share, file, confirm=TRUE) do_container_op(share, file, http_verb="DELETE") } - +#' @rdname file_share #' @export create_azure_dir <- function(share, dir) { do_container_op(share, dir, options=list(restype="directory"), http_verb="PUT") } - +#' @rdname file_share #' @export delete_azure_dir <- function(share, dir, confirm=TRUE) { diff --git a/R/storage.R b/R/storage.R index 9f415a4..62e76dd 100644 --- a/R/storage.R +++ b/R/storage.R @@ -1,3 +1,48 @@ +#' Storage account resource class +#' +#' Class representing a storage account, exposing methods for working with it. +#' +#' @docType class +#' @section Methods: +#' The following methods are available, in addition to those provided by the [AzureRMR::az_resource] class: +#' - `new(...)`: Initialize a new storage object. See 'Initialization'. +#' - `list_keys`: Return the access keys for this account. +#' - `get_account_sas(...)`: Return an account shared access signature (SAS). See 'Shared access signatures' for more details. +#' - `get_blob_endpoint(key, sas)`: Return the account's blob storage endpoint, along with an access key and/or a SAS. See 'Endpoints' for more details +#' - `get_file_endpoint(key, sas)`: Return the account's file storage endpoint. +#' - `get_queue_endpoint(key, sas)`: Return the account's queue storage endpoint. +#' - `get_table_endpoint(key, sas)`: Return the account's table storage endpoint. +#' +#' @section Initialization: +#' Initializing a new object of this class can either retrieve an existing storage account, or create a account on the host. Generally, the best way to initialize an object is via the `get_storage_account`, `create_storage_account` or `list_storage_accounts` methods of the [az_resource_group] class, which handle the details automatically. +#' +#' @section Shared access signatures: +#' The simplest way for a user to access files and data in a storage account is to give them the account's access key. This gives them full control of the account, and so may be a security risk. An alternative is to provide the user with a _shared access signature_ (SAS), which limits access to specific resources and only for a set length of time. +#' +#' To create an account SAS, call the `get_account_sas()` method with the following arguments: +#' - `start`: The starting access date/time, as a `Date` or `POSIXct` value. Defaults to the current time. +#' - `expiry`: The ending access date/time, as a `Date` or `POSIXct` value. Defaults to 8 hours after the start time. +#' - `services`: Which services to allow access to. A string containing a combination of the letters `b`, `f`, `q`, `t` for blob, file, queue and table access. Defaults to `bfqt`. +#' - `permissions`: Which permissions to grant. A string containing a combination of the letters `r` (read), `w` (write), `d` (delete), `l` (list), `a` (add), `c` (create), `u` (update) , `p` (process). Defaults to `r`. +#' - `resource_types`: Which levels of the resource type hierarchy to allow access to. A string containing a combination of the letters `s` (service), `c` (container), `o` (object). Defaults to `sco`. +#' - ip: An IP address or range to grant access to. +#' - `protocol`: Which protocol to allow, either `"http"`, `"http,https"` or `"https"`. Defaults to NULL, which is the same as `"http,https"`. +#' - `key`: the access key used to sign (authorise) the SAS. +#' +#' @section Endpoints: +#' The client-side interaction with a storage account is via an _endpoint_. A storage account can have several endpoints, one for each type of storage supported: blob, file, queue and table. +#' +#' The client-side interface in AzureStor is implemented using S3 classes. This is for consistency with other data access packages in R, which mostly use S3. It also emphasises the distinction between Resource Manager (which is for interacting with the storage account itself) and the client (which is for accessing files and data stored in the account). +#' +#' To create a storage endpoint independently of Resource Manager (for example if you are a user without admin or owner access to the account), use the [storage_endpoint] function. This is called under the hood by the `get_xxxx_endpoint` methods. +#' +#' If a storage endpoint is created without an access key and SAS, only public (anonymous) access is possible. +#' +#' @seealso +#' [storage_endpoint], +#' [create_storage_account], [get_storage_account], [delete_storage_account], +#' [Azure Storage Provider API reference](https://docs.microsoft.com/en-us/rest/api/storagerp/), +#' [Azure Storage Services API reference](https://docs.microsoft.com/en-us/rest/api/storageservices/) #' @export az_storage <- R6::R6Class("az_storage", inherit=AzureRMR::az_resource, @@ -29,16 +74,17 @@ public=list( self$do_operation("POST", "listAccountSas", body=parms, encode="json")$accountSasToken }, - get_service_sas=function(start=NULL, expiry=NULL, path=NULL, service=NULL, permissions="r", - ip=NULL, protocol=NULL, key=NULL) - { - dates <- private$set_sas_dates(start, expiry) - parms <- list(keyToSign=key, canonicalizedResource=path, - signedExpiry=dates$expiry, signedIp=ip, signedPermission=permissions, signedProtocol=protocol, - signedResource=service, signedStart=dates$start) + # hide for now + #get_service_sas=function(start=NULL, expiry=NULL, path=NULL, service=NULL, permissions="r", + #ip=NULL, protocol=NULL, key=NULL) + #{ + #dates <- private$set_sas_dates(start, expiry) + #parms <- list(keyToSign=key, canonicalizedResource=path, + #signedExpiry=dates$expiry, signedIp=ip, signedPermission=permissions, signedProtocol=protocol, + #signedResource=service, signedStart=dates$start) - self$do_operation("POST", "listServiceSas", body=parms, encode="json")$serviceSasToken - }, + #self$do_operation("POST", "listServiceSas", body=parms, encode="json")$serviceSasToken + #}, get_blob_endpoint=function(key=self$list_keys()[1]) { @@ -62,11 +108,11 @@ private=list( if(inherits(start, c("POSIXt", "Date"))) start <- strftime(start, "%Y-%m-%dT%H:%M:%SZ", tz="UTC") - if(is.null(expiry)) # by default, 1 year after start + if(is.null(expiry)) # by default, 8 hours after start { - expiry <- as.POSIXlt(start, tz="UTC") - expiry$year <- expiry$year + 1 - expiry <- as.POSIXct(expiry, tz="UTC") + expiry <- as.POSIXlt(start) + expiry$hour <- expiry$hour + 8 + expiry <- as.POSIXct(expiry) } else if(is.numeric(expiry)) expiry <- as.POSIXct(expiry, origin="1970-01-01") diff --git a/R/storage_utils.R b/R/storage_utils.R index 3e52de9..d19c81c 100644 --- a/R/storage_utils.R +++ b/R/storage_utils.R @@ -144,8 +144,17 @@ parse_storage_url <- function(url) is_endpoint_url <- function(url, type) { - type <- sprintf("://[a-z0-9]+\\.%s\\.", type) + # endpoint URL must be of the form {scheme}://{acctname}.{type}.{etc} + type <- sprintf("^https?://[a-z0-9]+\\.%s\\.", type) grepl(type, url) } +generate_endpoint_container <- function(url, key, sas, api_version) +{ + stor_path <- parse_storage_url(url) + endpoint <- storage_endpoint(stor_path[1], key, sas, api_version) + name <- stor_path[2] + list(endpoint=endpoint, name=name) +} + diff --git a/man/az_storage.Rd b/man/az_storage.Rd new file mode 100644 index 0000000..533747b --- /dev/null +++ b/man/az_storage.Rd @@ -0,0 +1,67 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/storage.R +\docType{class} +\name{az_storage} +\alias{az_storage} +\title{Storage account resource class} +\format{An object of class \code{R6ClassGenerator} of length 24.} +\usage{ +az_storage +} +\description{ +Class representing a storage account, exposing methods for working with it. +} +\section{Methods}{ + +The following methods are available, in addition to those provided by the \link[AzureRMR:az_resource]{AzureRMR::az_resource} class: +\itemize{ +\item \code{new(...)}: Initialize a new storage object. See 'Initialization'. +\item \code{list_keys}: Return the access keys for this account. +\item \code{get_account_sas(...)}: Return an account shared access signature (SAS). See 'Shared access signatures' for more details. +\item \code{get_blob_endpoint(key, sas)}: Return the account's blob storage endpoint, along with an access key and/or a SAS. See 'Endpoints' for more details +\item \code{get_file_endpoint(key, sas)}: Return the account's file storage endpoint. +\item \code{get_queue_endpoint(key, sas)}: Return the account's queue storage endpoint. +\item \code{get_table_endpoint(key, sas)}: Return the account's table storage endpoint. +} +} + +\section{Initialization}{ + +Initializing a new object of this class can either retrieve an existing storage account, or create a account on the host. Generally, the best way to initialize an object is via the \code{get_storage_account}, \code{create_storage_account} or \code{list_storage_accounts} methods of the \link{az_resource_group} class, which handle the details automatically. +} + +\section{Shared access signatures}{ + +The simplest way for a user to access files and data in a storage account is to give them the account's access key. This gives them full control of the account, and so may be a security risk. An alternative is to provide the user with a \emph{shared access signature} (SAS), which limits access to specific resources and only for a set length of time. + +To create an account SAS, call the \code{get_account_sas()} method with the following arguments: +\itemize{ +\item \code{start}: The starting access date/time, as a \code{Date} or \code{POSIXct} value. Defaults to the current time. +\item \code{expiry}: The ending access date/time, as a \code{Date} or \code{POSIXct} value. Defaults to 8 hours after the start time. +\item \code{services}: Which services to allow access to. A string containing a combination of the letters \code{b}, \code{f}, \code{q}, \code{t} for blob, file, queue and table access. Defaults to \code{bfqt}. +\item \code{permissions}: Which permissions to grant. A string containing a combination of the letters \code{r} (read), \code{w} (write), \code{d} (delete), \code{l} (list), \code{a} (add), \code{c} (create), \code{u} (update) , \code{p} (process). Defaults to \code{r}. +\item \code{resource_types}: Which levels of the resource type hierarchy to allow access to. A string containing a combination of the letters \code{s} (service), \code{c} (container), \code{o} (object). Defaults to \code{sco}. +\item ip: An IP address or range to grant access to. +\item \code{protocol}: Which protocol to allow, either \code{"http"}, \code{"http,https"} or \code{"https"}. Defaults to NULL, which is the same as \code{"http,https"}. +\item \code{key}: the access key used to sign (authorise) the SAS. +} +} + +\section{Endpoints}{ + +The client-side interaction with a storage account is via an \emph{endpoint}. A storage account can have several endpoints, one for each type of storage supported: blob, file, queue and table. + +The client-side interface in AzureStor is implemented using S3 classes. This is for consistency with other data access packages in R, which mostly use S3. It also emphasises the distinction between Resource Manager (which is for interacting with the storage account itself) and the client (which is for accessing files and data stored in the account). + +To create a storage endpoint independently of Resource Manager (for example if you are a user without admin or owner access to the account), use the \link{storage_endpoint} function. This is called under the hood by the \code{get_xxxx_endpoint} methods. + +If a storage endpoint is created without an access key and SAS, only public (anonymous) access is possible. +} + +\seealso{ +\link{storage_endpoint}, +\link{create_storage_account}, \link{get_storage_account}, \link{delete_storage_account}, +\href{https://docs.microsoft.com/en-us/rest/api/storagerp/}{Azure Storage Provider API reference}, +\href{https://docs.microsoft.com/en-us/rest/api/storageservices/}{Azure Storage Services API reference} +} +\keyword{datasets} diff --git a/man/blob_container.Rd b/man/blob_container.Rd new file mode 100644 index 0000000..b39fe53 --- /dev/null +++ b/man/blob_container.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/blob_client_funcs.R +\name{list_blobs} +\alias{list_blobs} +\alias{upload_blob} +\alias{download_blob} +\alias{delete_blob} +\title{Operations on a blob container} +\usage{ +list_blobs(container) + +upload_blob(container, src, dest, type = "BlockBlob") + +download_blob(container, src, dest, overwrite = FALSE) + +delete_blob(container, blob, confirm = TRUE) +} +\arguments{ +\item{container}{A blob container object.} + +\item{src, }{dest The source and destination filenames for uploading and downloading. Paths are allowed.} + +\item{blob}{A string naming a blob.} + +\item{confirm}{Whether to ask for confirmation on deleting a blob.} +} +\value{ +For \code{list_blobs}, a vector of blob names in the container. For the other functions, NULL on successful completion. +} +\description{ +Upload, download, or delete a blob; list blobs in a container. +} +\seealso{ +\link{blob_container}, \link{az_storage} +} diff --git a/man/blob_endpoint.Rd b/man/blob_endpoint.Rd new file mode 100644 index 0000000..b3944b0 --- /dev/null +++ b/man/blob_endpoint.Rd @@ -0,0 +1,80 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/blob_client_funcs.R +\name{blob_container} +\alias{blob_container} +\alias{blob_container.character} +\alias{blob_container.blob_endpoint} +\alias{list_blob_containers} +\alias{list_blob_containers.character} +\alias{list_blob_containers.blob_endpoint} +\alias{create_blob_container} +\alias{create_blob_container.character} +\alias{create_blob_container.blob_endpoint} +\alias{delete_blob_container} +\alias{delete_blob_container.character} +\alias{delete_blob_container.blob_endpoint} +\title{Operations on a blob endpoint} +\usage{ +blob_container(endpoint, ...) + +\method{blob_container}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version")) + +\method{blob_container}{blob_endpoint}(endpoint, name) + +list_blob_containers(endpoint, ...) + +\method{list_blob_containers}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version")) + +\method{list_blob_containers}{blob_endpoint}(endpoint, ...) + +create_blob_container(endpoint, ...) + +\method{create_blob_container}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version"), ...) + +\method{create_blob_container}{blob_endpoint}(endpoint, + public_access = c("none", "blob", "container"), ...) + +delete_blob_container(endpoint, ...) + +\method{delete_blob_container}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version"), ...) + +\method{delete_blob_container}{blob_endpoint}(endpoint, name, confirm = TRUE, + lease = NULL) +} +\arguments{ +\item{endpoint}{Either a blob endpoint object as created by \link{storage_endpoint}, or a character string giving the URL of the endpoint.} + +\item{...}{Further arguments passed to lower-level functions.} + +\item{key, }{sas If an endpoint object is not supplied, authentication details. If neither an access key nor a SAS are provided, only public (anonymous) access to the share is possible.} + +\item{api_version}{If an endpoint object is not supplied, the storage API version to use when interacting with the host. Currently defaults to \code{"2017-07-29"}.} + +\item{name}{The name of the blob container to get, create, or delete.} + +\item{public_access}{For creating a container, the level of public access to allow.} + +\item{confirm}{For deleting a container, whether to ask for confirmation.} + +\item{lease}{For deleting a leased container, the lease ID.} +} +\value{ +For \code{blob_container} and \code{create_blob_container}, an S3 object representing an existing or created container respectively. + +For \code{list_blob_containers}, a list of such objects. + +For \code{delete_blob_container}, NULL on successful deletion. +} +\description{ +Get, list, create, or delete blob containers. +} +\details{ +You can call these functions in a couple of ways: by passing the full URL of the share, or by passing the endpoint object and the name of the container as a string. +} +\seealso{ +\link{storage_endpoint}, \link{az_storage} +} diff --git a/man/create_storage_account.Rd b/man/create_storage_account.Rd new file mode 100644 index 0000000..a1fe727 --- /dev/null +++ b/man/create_storage_account.Rd @@ -0,0 +1,40 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_methods.R +\name{create_storage_account} +\alias{create_storage_account} +\title{Create Azure storage account} +\usage{ +create_storage_account(name, location, kind="Storage", sku=list(name="Standard_LRS", tier="Standard"), ...) +} +\arguments{ +\item{name}{The name of the storage account.} + +\item{location}{The location/region in which to create the account.} + +\item{kind}{The type of account, either \code{"Storage"} or \code{"BlobStorage"}.} + +\item{sku}{The SKU. This is a named list specifying various configuration options for the account.} + +\item{...}{Other named arguments to pass to the \link{az_storage} initialization function.} +} +\value{ +An object of class \code{az_storage} representing the created storage account. +} +\description{ +Method for the \link[AzureRMR:az_resource_group]{AzureRMR::az_resource_group} class. +} +\details{ +This method deploys a new storage account resource, with parameters given by the arguments. A storage account can host multiple types of storage: +\itemize{ +\item blob storage +\item file storage +\item table storage +\item queue storage +} + +Accounts created with \code{kind = "BlobStorage"} can only host blob and table storage, while those with \code{kind = "Storage"} can host all four. +} +\seealso{ +\link{get_storage_account}, \link{delete_storage_account}, \link{az_storage}, +\href{https://docs.microsoft.com/en-us/rest/api/storagerp/}{Azure Storage Provider API reference} +} diff --git a/man/delete_storage_account.Rd b/man/delete_storage_account.Rd new file mode 100644 index 0000000..bdb540a --- /dev/null +++ b/man/delete_storage_account.Rd @@ -0,0 +1,25 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_methods.R +\name{delete_storage_account} +\alias{delete_storage_account} +\title{Delete an Azure storage account} +\usage{ +delete_storage_account(name, confirm=TRUE, wait=FALSE) +} +\arguments{ +\item{name}{The name of the storage account.} + +\item{confirm}{Whether to ask for confirmation before deleting.} + +\item{wait}{Whether to wait until the deletion is complete.} +} +\value{ +NULL on successful deletion. +} +\description{ +Method for the \link[AzureRMR:az_resource_group]{AzureRMR::az_resource_group} class. +} +\seealso{ +\link{create_storage_account}, \link{get_storage_account}, \link{az_storage}, +\href{https://docs.microsoft.com/en-us/rest/api/storagerp/}{Azure Storage Provider API reference} +} diff --git a/man/file_endpoint.Rd b/man/file_endpoint.Rd new file mode 100644 index 0000000..539fde6 --- /dev/null +++ b/man/file_endpoint.Rd @@ -0,0 +1,74 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/file_client_funcs.R +\name{file_share} +\alias{file_share} +\alias{file_share.character} +\alias{file_share.file_endpoint} +\alias{list_file_shares} +\alias{list_file_shares.character} +\alias{list_file_shares.file_share} +\alias{create_file_share} +\alias{create_file_share.character} +\alias{create_file_share} +\alias{delete_file_share} +\alias{delete_file_share.character} +\alias{delete_file_share} +\title{Operations on a file endpoint} +\usage{ +file_share(endpoint, ...) + +\method{file_share}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version")) + +\method{file_share}{file_endpoint}(endpoint, name) + +list_file_shares(endpoint, ...) + +\method{list_file_shares}{character}(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version")) + +\method{list_file_shares}{file_share}(endpoint, ...) + +create_file_share(endpoint, name, ...) + +create_file_share.character(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version"), ...) + +create_file_share(endpoint, name, ...) + +delete_file_share(endpoint, name, confirm = TRUE) + +delete_file_share.character(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version"), ...) + +delete_file_share(endpoint, name, confirm = TRUE) +} +\arguments{ +\item{endpoint}{Either a file endpoint object as created by \link{storage_endpoint}, or a character string giving the URL of the endpoint.} + +\item{...}{Further arguments passed to lower-level functions.} + +\item{key, }{sas If an endpoint object is not supplied, authentication details. If neither an access key nor a SAS are provided, only public (anonymous) access to the share is possible.} + +\item{api_version}{If an endpoint object is not supplied, the storage API version to use when interacting with the host. Currently defaults to \code{"2017-07-29"}.} + +\item{name}{The name of the file share to get, create, or delete.} + +\item{confirm}{For deleting a share, whether to ask for confirmation.} +} +\value{ +For \code{file_share} and \code{create_file_share}, an S3 object representing an existing or created share respectively. + +For \code{list_file_shares}, a list of such objects. + +For \code{delete_file_share}, NULL on successful deletion. +} +\description{ +Get, list, create, or delete file shares. +} +\details{ +You can call these functions in a couple of ways: by passing the full URL of the share, or by passing the endpoint object and the name of the share as a string. +} +\seealso{ +\link{storage_endpoint}, \link{az_storage} +} diff --git a/man/file_share.Rd b/man/file_share.Rd new file mode 100644 index 0000000..ff90875 --- /dev/null +++ b/man/file_share.Rd @@ -0,0 +1,45 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/file_client_funcs.R +\name{list_azure_files} +\alias{list_azure_files} +\alias{upload_azure_file} +\alias{download_azure_file} +\alias{delete_azure_file} +\alias{create_azure_dir} +\alias{delete_azure_dir} +\title{Operations on a file share} +\usage{ +list_azure_files(share, dir, all_info = TRUE) + +upload_azure_file(share, src, dest) + +download_azure_file(share, src, dest, overwrite = FALSE) + +delete_azure_file(share, file, confirm = TRUE) + +create_azure_dir(share, dir) + +delete_azure_dir(share, dir, confirm = TRUE) +} +\arguments{ +\item{share}{A file share object.} + +\item{dir, }{file A string naming a directory or file respectively.} + +\item{all_info}{Whether to return names only, or all information in a directory listing.} + +\item{src, }{dest The source and destination filenames for uploading and downloading. Paths are allowed.} + +\item{confirm}{Whether to ask for confirmation on deleting a file or directory.} +} +\value{ +For \code{list_azure_files}, if \code{all_info=FALSE}, a vector of file/directory names. If \code{all_info=TRUE}, a data frame giving the file size and whether each object is a file or directory. + +For the other functions, NULL on successful completion. +} +\description{ +Upload, download, or delete a file; list files in a directory; create or delete directories. +} +\seealso{ +\link{file_share}, \link{az_storage} +} diff --git a/man/file_transfer.Rd b/man/file_transfer.Rd new file mode 100644 index 0000000..56c2f18 --- /dev/null +++ b/man/file_transfer.Rd @@ -0,0 +1,30 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/client.R +\name{download_from_url} +\alias{download_from_url} +\alias{upload_to_url} +\title{Generic upload and download} +\usage{ +download_from_url(src, dest, ..., overwrite = FALSE) + +upload_to_url(src, dest, ...) +} +\arguments{ +\item{src, }{dest The source and destination files/URLs. Paths are allowed.} + +\item{...}{Further arguments to pass to lower-level functions. In particular, use \code{key} and/or \code{sas} to supply an access key or SAS. Without a key or SAS, only unauthenticated (anonymous) access is possible.} + +\item{overwrite}{For downloading, whether to overwrite any destination files that exist.} +} +\value{ +NULL on successful completion. +} +\description{ +Generic upload and download +} +\details{ +These functions allow you to transfer files to and from a storage account, given the URL of the destination (for uploading) or source (for downloading). They dispatch to \link{upload_azure_file}/\link{download_azure_file} for a file storage URL and \link{upload_blob}/\link{download_blob} for a blob storage URL respectively. +} +\seealso{ +\link{download_azure_file}, \link{download_blob}. \link{az_storage} +} diff --git a/man/get_storage_account.Rd b/man/get_storage_account.Rd new file mode 100644 index 0000000..cc62888 --- /dev/null +++ b/man/get_storage_account.Rd @@ -0,0 +1,28 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/add_methods.R +\name{get_storage_account} +\alias{get_storage_account} +\alias{list_storage_accounts} +\title{Get existing Azure storage account(s)} +\usage{ +get_storage_account(name) +list_storage_accounts() +} +\arguments{ +\item{name}{For \code{get_storage_account()}, the name of the storage account.} +} +\value{ +For \code{get_storage_account()}, an object of class \code{az_storage} representing the storage account. + +For \code{list_storage_accounts()}, a list of such objects. +} +\description{ +Methods for the \link[AzureRMR:az_resource_group]{AzureRMR::az_resource_group} and \link[AzureRMR:az_subscription]{AzureRMR::az_subscription} classes. +} +\details{ +The \code{AzureRMR::az_resource_group} class has both \code{get_storage_account()} and \code{list_storage_accounts()} methods, while the \code{AzureRMR::az_subscription} class only has the latter. +} +\seealso{ +\link{create_storage_account}, \link{delete_storage_account}, \link{az_storage}, +\href{https://docs.microsoft.com/en-us/rest/api/storagerp/}{Azure Storage Provider API reference} +} diff --git a/man/storage_endpoint.Rd b/man/storage_endpoint.Rd new file mode 100644 index 0000000..dbb1a6f --- /dev/null +++ b/man/storage_endpoint.Rd @@ -0,0 +1,35 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/client.R +\name{storage_endpoint} +\alias{storage_endpoint} +\alias{endpoint} +\alias{blob_endpoint} +\alias{file_endpoint} +\alias{queue_endpoint} +\alias{table_endpoint} +\title{Create a storage endpoint object} +\usage{ +storage_endpoint(endpoint, key = NULL, sas = NULL, + api_version = getOption("azure_storage_api_version")) +} +\arguments{ +\item{endpoint}{The URL (hostname) for the endpoint. This must be of the form \code{http[s]://{account-name}.{type}.{core-host-name}}, where \code{type} is one of \code{"blob"}, \code{"file"}, \code{"queue"} or \code{"table"}. On the public Azure cloud, endpoints will be of the form \code{https://{account-name}.{type}.core.windows.net}.} + +\item{key}{The access key for the storage account.} + +\item{sas}{A shared access signature for the account. If neither \code{key} nor \code{sas} are provided, only public (anonymous) access to the endpoint is possible.} + +\item{api_version}{The storage API version to use when interacting with the host. Currently defaults to \code{"2017-07-29"}.} +} +\value{ +An object of S3 class \code{"blob_endpoint"}, \code{"file_endpoint"}, \code{"queue_endpoint"} or \code{"table_endpoint"} depending on the type of endpoint. All of these also inherit from class \code{"storage_endpoint"}. +} +\description{ +Create a storage endpoint object +} +\details{ +This is the starting point for the client-side storage interface in AzureRMR. +} +\seealso{ +\link{az_storage}, \link{file_share}, \link{create_file_share}, \link{blob_container}, \link{create_blob_container} +}