ADLS - Address TODOs and bug fixes
This commit is contained in:
Родитель
f367c20f55
Коммит
35d0edff58
|
@ -79,6 +79,7 @@ export(dumpAzureContext)
|
|||
export(is.azureActiveContext)
|
||||
export(read.AzureSMR.config)
|
||||
export(setAzureContext)
|
||||
export(showDeviceCodeMessageToUser)
|
||||
importFrom(DT,dataTableOutput)
|
||||
importFrom(DT,renderDataTable)
|
||||
importFrom(XML,htmlParse)
|
||||
|
|
|
@ -33,19 +33,19 @@ azureAuthenticateOnAuthType <- function(azureActiveContext, authType, resource,
|
|||
assert_that(is.azureActiveContext(azureActiveContext))
|
||||
|
||||
if (missing(authType)) authType <- azureActiveContext$authType
|
||||
if (is.null(authType) || nchar(authType) == 0)
|
||||
stop("Unspecified Auth Type. Please specify a valid authType.")
|
||||
|
||||
if (missing(resource)) resource <- azureActiveContext$resource
|
||||
if (is.null(resource) || nchar(resource) == 0)
|
||||
stop("Unspecified Resource. Please specify a valid resource.")
|
||||
|
||||
# before using the preferred auth type, check if access token can be fetched with a valid refresh token
|
||||
refreshToken <- azureActiveContext$RefreshToken
|
||||
if (!is.null(refreshToken) && nchar(refreshToken) > 0) {
|
||||
|
||||
assert_that(is_authType(authType))
|
||||
assert_that(is_resource(resource))
|
||||
|
||||
# Before using the preferred auth type, check if access token
|
||||
# can be fetched with a valid refresh token
|
||||
if (is_refreshToken(refreshToken)) {
|
||||
authType <- "RefreshToken"
|
||||
}
|
||||
|
||||
print(paste("Fetch azure active directory access token using authType = ", authType))
|
||||
result <- switch(
|
||||
authType,
|
||||
RefreshToken = azureGetTokenRefreshToken(azureActiveContext),
|
||||
|
@ -55,7 +55,7 @@ azureAuthenticateOnAuthType <- function(azureActiveContext, authType, resource,
|
|||
)
|
||||
|
||||
# persist valid auth type in the context
|
||||
if (result) {
|
||||
if (result && is.null(azureActiveContext$authType)) {
|
||||
azureActiveContext$authType <- authType
|
||||
}
|
||||
|
||||
|
@ -86,7 +86,7 @@ azureGetTokenClientCredential <- function(azureActiveContext, tenantID, clientID
|
|||
assert_that(is_tenant_id(tenantID))
|
||||
assert_that(is_client_id(clientID))
|
||||
assert_that(is_authKey(authKey))
|
||||
# TODO: check resource?
|
||||
assert_that(is_resource(resource))
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
|
@ -124,7 +124,7 @@ azureGetTokenClientCredential <- function(azureActiveContext, tenantID, clientID
|
|||
#' @param verbose Print Tracing information (Default False)
|
||||
#'
|
||||
#' @note See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
|
||||
#' @references \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
|
||||
#' @references \url{https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-deviceprofile/}
|
||||
#'
|
||||
#' @return If successful, returns TRUE
|
||||
#' @family Azure resource functions
|
||||
|
@ -139,6 +139,7 @@ azureGetTokenDeviceCode <- function(azureActiveContext, tenantID, clientID, reso
|
|||
|
||||
assert_that(is_tenant_id(tenantID))
|
||||
assert_that(is_client_id(clientID))
|
||||
assert_that(is_resource(resource))
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
|
@ -172,6 +173,7 @@ azureGetTokenDeviceCode <- function(azureActiveContext, tenantID, clientID, reso
|
|||
expiresIn <- j1$expires_in
|
||||
pollingInterval <- j1$interval
|
||||
|
||||
# Wait till user manually approves the user_code in the device code portal
|
||||
iteration <- 0
|
||||
waiting <- TRUE
|
||||
while (iteration < 50 && waiting) {
|
||||
|
@ -185,8 +187,17 @@ azureGetTokenDeviceCode <- function(azureActiveContext, tenantID, clientID, reso
|
|||
return(TRUE)
|
||||
}
|
||||
|
||||
#' Display device code flow message to user.
|
||||
#'
|
||||
#' @param jsonResponseObject JSON object that contains the message to be displayed.
|
||||
#'
|
||||
#' @return If successful, returns TRUE
|
||||
#' @family Azure resource functions
|
||||
#'
|
||||
#' @export
|
||||
showDeviceCodeMessageToUser <- function(jsonResponseObject) {
|
||||
print(jsonResponseObject$message)
|
||||
return(TRUE)
|
||||
}
|
||||
|
||||
#' Get Azure token using device_code
|
||||
|
@ -196,7 +207,7 @@ showDeviceCodeMessageToUser <- function(jsonResponseObject) {
|
|||
#' @param verbose Print Tracing information (Default False)
|
||||
#'
|
||||
#' @note See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
|
||||
#' @references \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
|
||||
#' @references \url{https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-deviceprofile/}
|
||||
#'
|
||||
#' @return If successful, returns TRUE
|
||||
#' @family Azure resource functions
|
||||
|
@ -212,7 +223,7 @@ azureGetTokenDeviceCodeFetch <- function(azureActiveContext, tenantID, clientID,
|
|||
|
||||
assert_that(is_tenant_id(tenantID))
|
||||
assert_that(is_client_id(clientID))
|
||||
# TODO: check device code?
|
||||
assert_that(is_deviceCode(deviceCode))
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
|
@ -228,7 +239,7 @@ azureGetTokenDeviceCodeFetch <- function(azureActiveContext, tenantID, clientID,
|
|||
`Content-type` = "application/x-www-form-urlencoded")),
|
||||
body = bodyGT,
|
||||
verbosity)
|
||||
# handle special error case
|
||||
# handle special error - HTTP400 - authorization_pending
|
||||
if(status_code(r) == 400) {
|
||||
rr <- content(r)
|
||||
if (rr$error == "authorization_pending") {
|
||||
|
@ -273,18 +284,19 @@ azureGetTokenRefreshToken <- function(azureActiveContext, tenantID, refreshToken
|
|||
|
||||
assert_that(is_tenant_id(tenantID))
|
||||
assert_that(is_client_id(clientID))
|
||||
# TODO: need another validate function
|
||||
#assert_that(is_authKey(refreshToken))
|
||||
assert_that(is_refreshToken(refreshToken))
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
URLGT <- paste0("https://login.microsoftonline.com/", tenantID, "/oauth2/token?api-version=1.0")
|
||||
refreshTokenEncoded <- URLencode(refreshToken, reserved = TRUE)
|
||||
# NOTE: Providing the optional client ID fails the request!
|
||||
bodyGT <- paste0("grant_type=refresh_token&refresh_token=", refreshTokenEncoded)
|
||||
|
||||
r <- httr::POST(URLGT,
|
||||
add_headers(
|
||||
.headers = c(`Content-type` = "application/x-www-form-urlencoded")),
|
||||
.headers = c(`Cache-Control` = "no-cache",
|
||||
`Content-type` = "application/x-www-form-urlencoded")),
|
||||
body = bodyGT,
|
||||
verbosity)
|
||||
stopWithAzureError(r)
|
||||
|
|
|
@ -199,17 +199,17 @@ azureDataLakeMkdirs <- function(azureActiveContext, azureDataLakeAccount, relati
|
|||
#' @family Azure Data Lake Store functions
|
||||
#' @export
|
||||
azureDataLakeCreate <- function(azureActiveContext, azureDataLakeAccount, relativePath, overwrite = FALSE, permission = NULL, contents = "", verbose = FALSE) {
|
||||
|
||||
|
||||
if (!missing(azureActiveContext) && !is.null(azureActiveContext)) {
|
||||
assert_that(is.azureActiveContext(azureActiveContext))
|
||||
azureCheckToken(azureActiveContext)
|
||||
}
|
||||
assert_that(is_storage_account(azureDataLakeAccount))
|
||||
if (!missing(permission) && !is.null(permission)) assert_that(is_permission(permission))
|
||||
# TODO: Need a check for contents ?
|
||||
#assert_that(is_content(contents))
|
||||
assert_that(is_content(contents))
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
|
||||
URL <- paste0(
|
||||
"https://", azureDataLakeAccount, ".azuredatalakestore.net/webhdfs/v1/",
|
||||
relativePath,
|
||||
|
@ -218,7 +218,7 @@ azureDataLakeCreate <- function(azureActiveContext, azureDataLakeAccount, relati
|
|||
)
|
||||
if (!missing(overwrite) && !is.null(overwrite)) URL <- paste0(URL, "&overwrite=", overwrite)
|
||||
if (!missing(permission) && !is.null(permission)) URL <- paste0(URL, "&permission=", permission)
|
||||
|
||||
|
||||
resHttp <- callAzureDataLakeApi(URL, verb = "PUT",
|
||||
azureActiveContext = azureActiveContext,
|
||||
content = contents, contenttype = "text/plain; charset=UTF-8",
|
||||
|
@ -251,8 +251,12 @@ azureDataLakeAppend <- function(azureActiveContext, azureDataLakeAccount, relati
|
|||
azureCheckToken(azureActiveContext)
|
||||
}
|
||||
assert_that(is_storage_account(azureDataLakeAccount))
|
||||
# TODO: Need a check for contents ?
|
||||
#assert_that(is_content(contents))
|
||||
assert_that(is_content(contents))
|
||||
|
||||
if (nchar(contents) == 0) {
|
||||
return()
|
||||
}
|
||||
|
||||
verbosity <- set_verbosity(verbose)
|
||||
|
||||
URL <- paste0(
|
||||
|
|
70
R/methods.R
70
R/methods.R
|
@ -102,6 +102,26 @@ on_failure(is_authKey) <- function(call, env) {
|
|||
"Provide a valid autkKeyID argument, or set using createAzureContext()"
|
||||
}
|
||||
|
||||
# --- refreshToken
|
||||
|
||||
is_refreshToken <- function(x) {
|
||||
is.character(x) && length(x) == 1 && nchar(x) > 0
|
||||
}
|
||||
|
||||
on_failure(is_refreshToken) <- function(call, env) {
|
||||
"Provide a valid refreshToken argument"
|
||||
}
|
||||
|
||||
# --- deviceToken
|
||||
|
||||
is_deviceCode <- function(x) {
|
||||
is.character(x) && length(x) == 1 && nchar(x) > 0
|
||||
}
|
||||
|
||||
on_failure(is_deviceCode) <- function(call, env) {
|
||||
"Provide a valid deviceCode argument"
|
||||
}
|
||||
|
||||
# --- vm_name
|
||||
|
||||
is_vm_name <- function(x) {
|
||||
|
@ -285,3 +305,53 @@ on_failure(is_valid_permission) <- function(call, env) {
|
|||
"and use numbers between 0 to 7 only.",
|
||||
sep = "\n")
|
||||
}
|
||||
|
||||
# --- auth type
|
||||
|
||||
is_authType <- function(x) {
|
||||
is.character(x) && length(x) == 1 && nchar(x) > 0 && assert_that(is_valid_authType(x))
|
||||
}
|
||||
|
||||
on_failure(is_authType) <- function(call, env) {
|
||||
"Provide a valid authType string"
|
||||
}
|
||||
|
||||
is_valid_authType <- function(x) {
|
||||
x == "ClientCredential" || x == "DeviceCode" || x == "RefreshToken"
|
||||
}
|
||||
|
||||
on_failure(is_valid_authType) <- function(call, env) {
|
||||
paste("authType string must be a string",
|
||||
"and should be one of \"ClientCredential\", \"DeviceCode\" or \"RefreshToken\".",
|
||||
sep = "\n")
|
||||
}
|
||||
|
||||
# --- resource
|
||||
|
||||
is_resource <- function(x) {
|
||||
is.character(x) && length(x) == 1 && nchar(x) > 0 && assert_that(is_valid_resource(x))
|
||||
}
|
||||
|
||||
on_failure(is_resource) <- function(call, env) {
|
||||
"Provide a valid resource string"
|
||||
}
|
||||
|
||||
is_valid_resource <- function(x) {
|
||||
grepl("^(https?:\\/\\/)?([\\da-z\\.-]+)\\.([a-z\\.]{2,6})([\\/\\w \\.-]*)*\\/?$", x)
|
||||
}
|
||||
|
||||
on_failure(is_valid_resource) <- function(call, env) {
|
||||
paste("resource must be a string",
|
||||
"and should be in a valid URL format.",
|
||||
sep = "\n")
|
||||
}
|
||||
|
||||
# --- content
|
||||
|
||||
is_content <- function(x) {
|
||||
is.character(x) && length(x) == 1 && nchar(x) >= 0
|
||||
}
|
||||
|
||||
on_failure(is_content) <- function(call, env) {
|
||||
"Provide a valid non-null content with 0 or more length"
|
||||
}
|
||||
|
|
|
@ -41,5 +41,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -28,5 +28,6 @@ Other Azure resource functions: \code{\link{azureAuthenticate}},
|
|||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -18,5 +18,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -38,5 +38,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureCheckToken}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ Get Azure token using DeviceCode.
|
|||
See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
|
||||
}
|
||||
\references{
|
||||
\url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
|
||||
\url{https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-deviceprofile/}
|
||||
}
|
||||
\seealso{
|
||||
Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
||||
|
@ -36,5 +36,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureCheckToken}},
|
||||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -28,7 +28,7 @@ Get Azure token using device_code
|
|||
See \url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/} for instructions to set up an Active Directory application
|
||||
}
|
||||
\references{
|
||||
\url{https://azure.microsoft.com/en-us/documentation/articles/resource-group-create-service-principal-portal/}
|
||||
\url{https://azure.microsoft.com/en-us/resources/samples/active-directory-dotnet-deviceprofile/}
|
||||
}
|
||||
\seealso{
|
||||
Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
||||
|
@ -36,5 +36,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureCheckToken}},
|
||||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
\code{\link{azureGetTokenRefreshToken}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -34,5 +34,6 @@ Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
|||
\code{\link{azureCheckToken}},
|
||||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}}
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{showDeviceCodeMessageToUser}}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,26 @@
|
|||
% Generated by roxygen2: do not edit by hand
|
||||
% Please edit documentation in R/AzureAuthenticate.R
|
||||
\name{showDeviceCodeMessageToUser}
|
||||
\alias{showDeviceCodeMessageToUser}
|
||||
\title{Display device code flow message to user.}
|
||||
\usage{
|
||||
showDeviceCodeMessageToUser(jsonResponseObject)
|
||||
}
|
||||
\arguments{
|
||||
\item{jsonResponseObject}{JSON object that contains the message to be displayed.}
|
||||
}
|
||||
\value{
|
||||
If successful, returns TRUE
|
||||
}
|
||||
\description{
|
||||
Display device code flow message to user.
|
||||
}
|
||||
\seealso{
|
||||
Other Azure resource functions: \code{\link{azureAuthenticateOnAuthType}},
|
||||
\code{\link{azureAuthenticate}},
|
||||
\code{\link{azureCheckToken}},
|
||||
\code{\link{azureGetTokenClientCredential}},
|
||||
\code{\link{azureGetTokenDeviceCodeFetch}},
|
||||
\code{\link{azureGetTokenDeviceCode}},
|
||||
\code{\link{azureGetTokenRefreshToken}}
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
#' ------------------------------------------------------------------------
|
||||
#'
|
||||
#' {
|
||||
#' "authType": "ClientCredential",
|
||||
#' "resource": "https://datalake.azure.net/",
|
||||
#' "tenantID": "72f988bf-blah-41af-blah-2d7cd011blah",
|
||||
#' "clientID": "1d604733-blah-4b37-blah-98fca981blah",
|
||||
#' "authKey": "zTw5blah+IN+yIblahrKv2K8dM2/BLah4FogBLAH/ME=",
|
||||
|
@ -24,9 +26,9 @@ context("Data Lake Store")
|
|||
|
||||
asc <- createAzureContext()
|
||||
with(config,
|
||||
setAzureContext(asc, tenantID = tenantID, clientID = clientID, authKey = authKey)
|
||||
setAzureContext(asc, tenantID = tenantID, clientID = clientID, authKey = authKey, authType = authType, resource = resource)
|
||||
)
|
||||
azureAuthenticate(asc)
|
||||
azureAuthenticateOnAuthType(asc)
|
||||
|
||||
# NOTE: make sure to provide the azureDataLakeAccount name in the config file.
|
||||
azureDataLakeAccount <- config$azureDataLakeAccount
|
||||
|
|
Загрузка…
Ссылка в новой задаче