ADLS - Address TODOs and bug fixes

This commit is contained in:
omkarksa 2017-09-26 15:02:15 +05:30
Родитель f367c20f55
Коммит 35d0edff58
13 изменённых файлов: 157 добавлений и 35 удалений

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

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

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

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