R/build_json.R

Defines functions build_resource_fields.list build_resource_fields add_template_resources add_template_variables.NULL add_template_variables.az_resource add_template_variables.character add_template_variables add_template_parameters build_template_parameters.vmss_config build_template_parameters.vm_config build_template_definition.vmss_config build_template_definition.vm_config

Documented in build_template_definition.vm_config build_template_definition.vmss_config build_template_parameters.vm_config build_template_parameters.vmss_config

#' Build template definition and parameters
#'
#' @param config An object of class `vm_config` or `vmss_config` representing a virtual machine or scaleset deployment.
#' @param name The VM or scaleset name. Will also be used for the domain name label, if a public IP address is included in the deployment.
#' @param login_user An object of class `user_config` representing the login details for the admin user account on the VM.
#' @param size The VM (instance) size.
#' @param ... Unused.
#'
#' @details
#' These are methods for the generics defined in the AzureRMR package.
#'
#' @return
#' Objects of class `json`, which are JSON character strings representing the deployment template and its parameters.
#'
#' @seealso
#' [create_vm], [vm_config], [vmss_config]
#'
#' @examples
#'
#' vm <- ubuntu_18.04()
#' build_template_definition(vm)
#' build_template_parameters(vm, "myubuntuvm",
#'     user_config("username", "~/.ssh/id_rsa.pub"), "Standard_DS3_v2")
#'
#' @rdname build_template
#' @aliases build_template
#' @export
build_template_definition.vm_config <- function(config, ...)
{
    tpl <- list(
        `$schema`="http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        contentVersion="1.0.0.0",
        parameters=add_template_parameters(config),
        variables=add_template_variables(config),
        resources=add_template_resources(config),
        outputs=tpl_outputs_default
    )

    jsonlite::prettify(jsonlite::toJSON(tpl, auto_unbox=TRUE, null="null"))
}


#' @rdname build_template
#' @export
build_template_definition.vmss_config <- function(config, ...)
{
    tpl <- list(
        `$schema`="http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
        contentVersion="1.0.0.0",
        parameters=add_template_parameters(config),
        variables=add_template_variables(config),
        resources=add_template_resources(config),
        outputs=tpl_outputs_default
    )

    jsonlite::prettify(jsonlite::toJSON(tpl, auto_unbox=TRUE, null="null"))
}


#' @rdname build_template
#' @export
build_template_parameters.vm_config <- function(config, name, login_user, size, ...)
{
    add_parameters <- function(...)
    {
        new_params <- lapply(list(...), function(obj) list(value=obj))
        params <<- c(params, new_params)
    }

    stopifnot(inherits(login_user, "user_config"))

    params <- list()
    add_parameters(vmName=name, vmSize=size, adminUsername=login_user$user)

    if(config$keylogin && !is_empty(login_user$key))
        add_parameters(sshKeyData=login_user$key)
    else add_parameters(adminPassword=login_user$pwd)

    if(inherits(config$image, "image_marketplace"))
        add_parameters(
            imagePublisher=config$image$publisher,
            imageOffer=config$image$offer,
            imageSku=config$image$sku,
            imageVersion=config$image$version
        )
    else add_parameters(imageId=config$image$id)

    # add datadisks to params
    if(!is_empty(config$datadisks))
    {
        # fixup datadisk LUNs and names
        for(i in seq_along(config$datadisks))
        {
            config$datadisks[[i]]$vm_spec$lun <- i - 1
            diskname <- config$datadisks[[i]]$vm_spec$name
            if(!is.null(diskname))
            {
                newdiskname <- paste(name, diskname, i, sep="_")
                config$datadisks[[i]]$res_spec$name <- newdiskname
                config$datadisks[[i]]$vm_spec$name <- newdiskname
            }
        }

        disk_res_spec <- lapply(config$datadisks, `[[`, "res_spec")
        null <- sapply(disk_res_spec, is.null)

        add_parameters(
            dataDisks=lapply(config$datadisks, `[[`, "vm_spec"),
            dataDiskResources=disk_res_spec[!null]
        )
    }

    jsonlite::prettify(jsonlite::toJSON(params, auto_unbox=TRUE, null="null"))
}


#' @param instances For `vmss_config`, the number of (initial) instances in the VM scaleset.
#' @rdname build_template
#' @export
build_template_parameters.vmss_config <- function(config, name, login_user, size, instances, ...)
{
    add_parameters <- function(...)
    {
        new_params <- lapply(list(...), function(obj) list(value=obj))
        params <<- c(params, new_params)
    }

    stopifnot(inherits(login_user, "user_config"))

    params <- list()
    add_parameters(vmName=name, vmSize=size, instanceCount=instances, adminUsername=login_user$user)

    if(config$options$keylogin && !is_empty(login_user$key))
        add_parameters(sshKeyData=login_user$key)
    else add_parameters(adminPassword=login_user$pwd)

    if(inherits(config$image, "image_marketplace"))
        add_parameters(
            imagePublisher=config$image$publisher,
            imageOffer=config$image$offer,
            imageSku=config$image$sku,
            imageVersion=config$image$version
        )
    else add_parameters(imageId=config$image$id)

    do.call(add_parameters, config$options$params)

    # add datadisks to params
    if(!is_empty(config$datadisks))
    {
        # fixup datadisk for scaleset
        for(i in seq_along(config$datadisks))
        {
            config$datadisks[[i]]$vm_spec$lun <- i - 1
            if(config$datadisks[[i]]$vm_spec$createOption == "attach")
            {
                config$datadisks[[i]]$vm_spec$createOption <- "empty"
                config$datadisks[[i]]$vm_spec$diskSizeGB <- config$datadisks[[i]]$res_spec$diskSizeGB
                config$datadisks[[i]]$vm_spec$storageAccountType <- config$datadisks[[i]]$res_spec$sku
            }
            diskname <- config$datadisks[[i]]$vm_spec$name
            if(!is.null(diskname))
            {
                newdiskname <- paste(name, diskname, i, sep="_")
                config$datadisks[[i]]$res_spec$name <- newdiskname
                config$datadisks[[i]]$vm_spec$name <- newdiskname
            }
        }

        disk_res_spec <- lapply(config$datadisks, `[[`, "res_spec")
        null <- sapply(disk_res_spec, is.null)

        add_parameters(
            dataDisks=lapply(config$datadisks, `[[`, "vm_spec"),
            dataDiskResources=disk_res_spec[!null]
        )
    }

    jsonlite::prettify(jsonlite::toJSON(params, auto_unbox=TRUE, null="null"))
}


add_template_parameters <- function(config, ...)
{
    UseMethod("add_template_parameters")
}


add_template_variables <- function(config, ...)
{
    UseMethod("add_template_variables")
}


add_template_variables.character <- function(config, type, ...)
{
    # assume this is a resource ID
    resname <- basename(config)
    varnames <- paste0(type, c("Name", "Id"))
    structure(list(resname, config), names=varnames)
}


add_template_variables.az_resource <- function(config, type, ...)
{
    varnames <- paste0(type, c("Name", "Id"))
    vars <- list(config$name, config$id)

    # a bit hackish, should fully objectify
    if(type == "vnet") # if we have a vnet, extract the 1st subnet name
    {
        subnet <- config$properties$subnets[[1]]$name
        subnet_id <- "[concat(variables('vnetId'), '/subnets/', variables('subnet'))]"
        varnames <- c(varnames, "subnet", "subnetId")
        structure(c(vars, subnet, subnet_id), names=varnames)
    }
    else if(type == "lb") # if we have a load balancer, extract component names
    {
        frontend <- config$properties$frontendIPConfigurations[[1]]$name
        backend <- config$properties$backendAddressPools[[1]]$name
        frontend_id <- "[concat(variables('lbId'), '/frontendIPConfigurations/', variables('lbFrontendName'))]"
        backend_id <- "[concat(variables('lbId'), '/backendAddressPools/', variables('lbBackendName'))]"
        varnames <- c(varnames, "lbFrontendName", "lbBackendName", "lbFrontendId", "lbBackendId")
        structure(c(vars, frontend, backend, frontend_id, backend_id), names=varnames)
    }
    else structure(vars, names=varnames)
}


add_template_variables.NULL <- function(config, ...)
{
    NULL
}


add_template_resources <- function(config, ...)
{
    UseMethod("add_template_resources")
}


build_resource_fields <- function(config)
{
    UseMethod("build_resource_fields")
}


build_resource_fields.list <- function(config, ...)
{
    unclass(config)
}
Hong-Revo/AzureVM documentation built on Jan. 21, 2021, 2:02 p.m.