How Do You Invoke a class in a Groovy Program?

Problem scenario
You have a Groovy with these lines of code:

class Contint {
   static void main(String[] args) {
      def apple = {println "This is a basic test."};
      apple.call();
   }
}
println "This is the second print statement in the code."

The "Contint" class is never invoked.  What should you do?

Solution
Overview

You need to use the "new" reserved word.  This will instantiate the class.  The object that is created can invoke this "main" method with the .main() syntax.  

Procedures
1.  Add these two lines under the last line of the program:

test = new Contint()
test.main()

2.  After the program has been saved, run the program again.

3.  You are done.  How Do You Create a Class for Objects with Many Data Members and Access One Specific Data Member in Groovy?
shows two ways of instantiating a class.  It uses the above method with the "new" keyword as well as a way that does not use the "new" keyword.

How Do You Connect to a Windows VM in Azure?

Problem scenario
You created a Windows VM.  But you cannot ping it or connect to it with RDP.  What do you do?

Solution
1.  In the Azure portal web UI, click on the NSG (Network Security Group) protecting the VM. 
2.  Add a rule. 
3.  Click the "Advanced" button so you are able to add an IP address source for the rule. 
4.  From your workstation, go to www.ipchicken.com
5.  Use this IP address as the source in the Azure rule. 
6.  Save the rule in Azure.  Wait two minutes.

How Do You Create a Logic App without Using the Azure Portal Web UI?

Problem scenario
You want to create a Logic App without using the Azure Portal web UI.  What should you do?

Possible Solution #1
To get an overview of using an ARM template for a Logic App, you should read this article.

Possible Solution #2
If you have Visual Studio, you can use the Azure Logic Apps Tool for Visual Studio.  To learn more, see this site.

Possible Solution #3
Use this PowerShell creator.

How Do You Troubleshoot This Message “ImportError: No module named ‘google.cloud’?

Problem scenario
You run a Python program or from the Python command prompt you receive this message:

Traceback (most recent call last):
  File "main.py", line 21, in <module>
    from google.cloud import pubsub_v1
 ImportError: No module named 'google.cloud'
...

ModuleNotFoundError: No module named 'google'

What should you do to eliminate this problem?

Possible Solution #1
Try to run the program as sudo:

sudo python nameOfProg.py

Possible Solution #2
Try this with or without sudo (depending on whether or not you are using "sudo" to run the Python program):

sudo pip install google-cloud-bigquery

# You may or may not want to omit the "sudo" in the above command.

Possible Solution #3
Prerequisite

This assumes that pip has been installed.  If you need assistance see this posting.

sudo pip uninstall google-cloud-bigquery
sudo pip install google-cloud-bigquery

How Do You Troubleshoot Azure Template Files?

Problem scenario
You are having problems with your ARM templates (the .json files).  You want to learn more techniques at troubleshoot ARM templates. What should you do?

Possible Solution #1   Follow these directions on Microsoft's website.
(You will need to download a .psm1 file and use the import-module command in PowerShell.)

Possible Solution #2
Clone this Git repo and use it to validate your ARM templates:  https://github.com/Azure/azure-arm-validator

Possible Solution #3
Substitute any very sensitive data from the JSON with dummy (fake or random) data.  (Although you can probably trust jsonlint.com.)  Copy what remains and validate the JSON itself with this site.

Possible Solution #4
Try this part of Azure: https://resources.azure.com/

Possible Solution #5
Are you using the latest version of the Azure CLI?  You may want to upgrade it.

Possible Solution #6
This page on Microsoft's website has a list of common errors and information to help you fix the problem.

Possible Solution #7
To learn about the formatting fundamentals you can read this Microsoft web page.

How Do You Troubleshoot the kubectl Error “Access denied status code: 403”

Problem scenario
You run a kubectl command but you get this error:

"could not get token: AccessDenied: Access denied
        status code: 403, request id:
Unable to connect to the server: getting credentials: exec: exit status 1"

What should you do?

Solution
The root cause is likely that your .kube directory has an incorrect configuration file. 

Possible Solution #1
If you are not using Amazon EKS, see this posting.

Possible Solution #2
Alternatively you may want to run these commands to see what you get:

kubectl config view
aws-iam-authenticator token -i foobar # but replace "foobar" with the name of your cluster
aws sts get-caller-identity 

You may want to back up your config-foobar file in your .kube directory.   This way you can experiment with different syntax and values.  You may want to read this external page.

Possible Solution #3
If you are using Amazon EKS (a Kubernetes PaaS), run this command to generate the correct configuration file (replace "contint" with the name of the Kubernetes cluster):
aws eks update-kubeconfig --name contint

How Do You Create the PowerShell Script, the Template.json and the Parameters.json Necessary to Utilize ARM?

Problem scenario
To use ARM templates you know know you should have three text files: 1) a PowerShell script 2) a template.json file and 3) a parameters.json file.

How do you create these for a given resource (e.g., a storage account, VM, or Function App)?

Solution
1.  In the Azure Portal web UI, start the process of creating a resource.  Right before you click "Create", and there may be a few intermediate steps before you get there, click on the nearby hyperlink that says "Download a template for automation" (or for a Function App it may say "Automation options").

2.  You can click on "Template" near the top.  The JSON should be copied into a file called template.json.

3.  You can click on "Parameters" near the top.  The JSON should be copied into a file called parameters.json.

4.  Click on "PowerShell" near the top.  This is the PowerShell you should use.  You should modify two PowerShell stanzas to have explicit paths to the template.json and parameters.json files:

 $templateFilePath = "C:\path\to\template.json",
 $parametersFilePath = "C:\path\to\parameters.json"

5.  Now you can run the PowerShell script to use ARM templates for the resource you were about to create.  Infastructure as a code is great for simplifying your standards and keeping a record of the configuration deployed.

How Do You Use an ARM Template to Create an Azure Serverless Function App?

Problem scenario
As a proof-of-concept you want to use an ARM template to create an Azure Function that uses Azure storage.  You want the template to create the Azure storage account as it is a dependency of the Azure Serverless Function (also known as an App Service).  How do you do this?

Overview
This will create an Azure Function also known as an App Service.  The name of it will be entered interactively when the PowerShell script is run (when you are prompted for a "nameFromTemplate").

Prerequisites
1.  If you are using Windows 7, you have installed Azure PowerShell; if you need assistance, see this posting.  If you are using Windows 10, you have installed the modules for Azure and the storage resource; if you need assistance with this, see this posting.

2.  You know your subscription ID.  If you need assistance, see this posting.

Procedures
1.  Create a template.json file with the following content (and remember its location for step #3):

{
    "resources": [
        {
            "apiVersion": "2016-03-01",
            "name": "[parameters('name')]",
            "type": "Microsoft.Web/sites",
            "properties": {
                "name": "[parameters('name')]",
                "siteConfig": {
                    "appSettings": [
                        {
                            "name": "FUNCTIONS_WORKER_RUNTIME",
                            "value": "node"
                        },
                        {
                            "name": "AzureWebJobsStorage",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2015-05-01-preview').key1)]"
                        },
                        {
                            "name": "FUNCTIONS_EXTENSION_VERSION",
                            "value": "~2"
                        },
                        {
                            "name": "WEBSITE_CONTENTAZUREFILECONNECTIONSTRING",
                            "value": "[concat('DefaultEndpointsProtocol=https;AccountName=',parameters('storageName'),';AccountKey=',listKeys(resourceId('Microsoft.Storage/storageAccounts', parameters('storageName')), '2015-05-01-preview').key1)]"
                        },
                        {
                            "name": "WEBSITE_CONTENTSHARE",
                            "value": "[concat(toLower(parameters('name')), 'ba80')]"
                        },
                        {
                            "name": "WEBSITE_NODE_DEFAULT_VERSION",
                            "value": "8.11.1"
                        }
                    ]
                },
                "clientAffinityEnabled": false,
                "reserved": false
            },
            "dependsOn": [
                "[resourceId('Microsoft.Storage/storageAccounts', parameters('storageName'))]"
            ],
            "location": "North Central US",
            "kind": "functionapp"
        },
        {
            "apiVersion": "2015-05-01-preview",
            "type": "Microsoft.Storage/storageAccounts",
            "name": "[parameters('storageName')]",
            "location": "[parameters('location')]",
            "properties": {
                "accountType": "Standard_LRS"
            }
        }
    ],
    "parameters": {
        "name": {
            "type": "string"
        },
        "storageName": {
            "type": "string"
        },
        "location": {
            "type": "string"
        },
        "subscriptionId": {
            "type": "string"
        }
    },
    "$schema": "http://schema.management.azure.com/schemas/2014-04-01-preview/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0"
}

2.  Create a parameters.json file, start with the "{" as the first line as a draft with the following content (and remember its location for step #3).  Replace 1234-abcd-5678-efgh with your subscription ID, replace zzzxxxyyywww with what you want your storage account name to be:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "name": {
            "value": "ne3c8dnmq40328"
        },
        "storageName": {
            "value": "zzzxxxyyywww"
        },
        "location": {
            "value": "North Central US"
        },
        "subscriptionId": {
            "value": "1234-abcd-5678-efgh"
        }
    }
}

3.  Use the following PowerShell script as a draft.  Change the "path\to" on the lines that assign where the respective template.json and parameters.json files should be (so they match where you created them in the above two steps).

<#
 .SYNOPSIS
    Deploys a template to Azure

 .DESCRIPTION
    Deploys an Azure Resource Manager template

 .PARAMETER subscriptionId
    The subscription id where the template will be deployed.

 .PARAMETER resourceGroupName
    The resource group where the template will be deployed. Can be the name of an existing or a new resource group.

 .PARAMETER resourceGroupLocation
    Optional, a resource group location. If specified, will try to create a new resource group in this location. If not specified, assumes resource group is existing.

 .PARAMETER deploymentName
    The deployment name.

 .PARAMETER templateFilePath
    Optional, path to the template file. Defaults to template.json.

 .PARAMETER parametersFilePath
    Optional, path to the parameters file. Defaults to parameters.json. If file is not found, will prompt for parameter values based on template.
#>

param(
 [Parameter(Mandatory=$True)]
 [string]
 $subscriptionId,

 [Parameter(Mandatory=$True)]
 [string]
 $resourceGroupName,

 [string]
 $resourceGroupLocation,

 [Parameter(Mandatory=$True)]
 [string]
 $deploymentName,

 [string]
 $templateFilePath = "C:\Users\jdoe\Documents\WindowsPowerShell\c\template.json",

 [string]
 $parametersFilePath = "C:\Users\jdoe\Documents\WindowsPowerShell\c\parameters.json"
)

<#
.SYNOPSIS
    Registers RPs
#>
Function RegisterRP {
    Param(
        [string]$ResourceProviderNamespace
    )

    Write-Host "Registering resource provider '$ResourceProviderNamespace'";
    Register-AzureRmResourceProvider -ProviderNamespace $ResourceProviderNamespace;
}

#******************************************************************************
# Script body
# Execution begins here
#******************************************************************************
$ErrorActionPreference = "Stop"

# sign in
Write-Host "Logging in...";
Login-AzureRmAccount;

# select subscription
Write-Host "Selecting subscription '$subscriptionId'";
Select-AzureRmSubscription -SubscriptionID $subscriptionId;

# Register RPs
$resourceProviders = @("microsoft.web","microsoft.storage");
if($resourceProviders.length) {
    Write-Host "Registering resource providers"
    foreach($resourceProvider in $resourceProviders) {
        RegisterRP($resourceProvider);
    }
}

#Create or check for existing resource group
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if(!$resourceGroup)
{
    Write-Host "Resource group '$resourceGroupName' does not exist. To create a new resource group, please enter a location.";
    if(!$resourceGroupLocation) {
        $resourceGroupLocation = Read-Host "resourceGroupLocation";
    }
    Write-Host "Creating resource group '$resourceGroupName' in location '$resourceGroupLocation'";
    New-AzureRmResourceGroup -Name $resourceGroupName -Location $resourceGroupLocation
}
else{
    Write-Host "Using existing resource group '$resourceGroupName'";
}

# Start the deployment
Write-Host "Starting deployment...";
if(Test-Path $parametersFilePath) {
    New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateFilePath -TemplateParameterFile $parametersFilePath;
} else {
    New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateFilePath;
}

echo "If you are prompted for a nameFromTemplate (regarding a new-azurermresourcegroupdeployment), enter any arbitrary string.*"
echo "* The string must not already exist in the Microsoft Azure websites; so it must be unique.  It will be the name of your App Service"
echo "The above two-line FYI is for when you first run this script.  When the script is otherwise complete, ignore it."

In the future we want to re-write these directions to use write-verbose instead of write-host. We want to warn people that write-verbose is recommended instead of write-host (according to this posting).

How Do You Create a PowerShell Script to Create a Storage Account in Azure?

Problem scenario
You want to use an ARM template via a PowerShell script to create a storage account in Azure.  How do you do this?

Solution
Prerequisites

1.  If you are using Windows 7, you have installed Azure PowerShell; if you need assistance with this, see this posting.  If you are using Windows 10, you have installed the modules for Azure and the storage resource; if you need assistance with this, see this posting.

2.  You know your subscription ID.  If you need assistance, see this posting.

Procedures
1.  Create a parameters.json file with the following content, but replace foobar with the name you want this storage account to have:

{
    "$schema": "https://schema.management.azure.com/schemas/2015-01-01/deploymentParameters.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "value": "northcentralus"
        },
        "storageAccountName": {
            "value": "foobar"
        },
        "accountType": {
            "value": "Standard_RAGRS"
        },
        "kind": {
            "value": "StorageV2"
        },
        "accessTier": {
            "value": "Hot"
        },
        "supportsHttpsTrafficOnly": {
            "value": true
        }
    }
}

2.  Create a template.json file with the following content:

{
    "$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
    "contentVersion": "1.0.0.0",
    "parameters": {
        "location": {
            "type": "string"
        },
        "storageAccountName": {
            "type": "string"
        },
        "accountType": {
            "type": "string"
        },
        "kind": {
            "type": "string"
        },
        "accessTier": {
            "type": "string"
        },
        "supportsHttpsTrafficOnly": {
            "type": "bool"
        }
    },
    "variables": {},
    "resources": [
        {
            "name": "[parameters('storageAccountName')]",
            "type": "Microsoft.Storage/storageAccounts",
            "apiVersion": "2018-07-01",
            "location": "[parameters('location')]",
            "properties": {
                "accessTier": "[parameters('accessTier')]",
                "supportsHttpsTrafficOnly": "[parameters('supportsHttpsTrafficOnly')]"
            },
            "dependsOn": [],
            "sku": {
                "name": "[parameters('accountType')]"
            },
            "kind": "[parameters('kind')]"
        }
    ],
    "outputs": {}
}

3.  Use this PowerShell script as a draft: first, modify "path\to" to be the paths of the respective files that are assigned.  Secondly change "foobargroup" to a Resource Group name; if you need assistance with finding an existing Resource Group, see this posting or this posting.

<#
 .SYNOPSIS
    Deploys a template to Azure

 .DESCRIPTION
    Deploys an Azure Resource Manager template

 .PARAMETER subscriptionId
    The subscription id where the template will be deployed.

 .PARAMETER resourceGroupName
    The resource group where the template will be deployed. Can be the name of an existing or a new resource group.

 .PARAMETER resourceGroupLocation
    Optional, a resource group location. If specified, will try to create a new resource group in this location. If not specified, assumes resource group is existing.

 .PARAMETER deploymentName
    The deployment name.

 .PARAMETER templateFilePath
    Optional, path to the template file. Defaults to template.json.

 .PARAMETER parametersFilePath
    Optional, path to the parameters file. Defaults to parameters.json. If file is not found, will prompt for parameter values based on template.
#>

param(
# [Parameter(Mandatory=$True)]
# [string]
# $subscriptionId,

# [Parameter(Mandatory=$True)]
# [string]
# $resourceGroupName = "foobargroup",

 [string]
 $resourceGroupLocation,

 [Parameter(Mandatory=$True)]
 [string]
 $deploymentName,

 [string]
 $templateFilePath = "C:\path\to\template.json",

 [string]
 $parametersFilePath = "C:\path\to\parameters.json"
)

<#
.SYNOPSIS
    Registers RPs
#>

Function RegisterRP {
    Param(
        [string]$ResourceProviderNamespace
    )

    Write-Host "Registering resource provider '$ResourceProviderNamespace'";
    Register-AzureRmResourceProvider -ProviderNamespace $ResourceProviderNamespace;
}

#******************************************************************************
# Script body
# Execution begins here
#******************************************************************************
$ErrorActionPreference = "Stop"

# sign in
Write-Host "Logging in...";
Login-AzureRmAccount;

$subscriptions= Get-AzureRmSubscription
$subscriptionId = $subscriptions.Id

$resourceGroupName = "contintgroup"

# select subscription
#Write-Host "Selecting subscription '$subscriptionId'";
echo "This PowerShell Program assumes you have only one subscription ID.  If you have more than one, you'll need to re-write it around this statement"
echo "and in the parameters section."

Select-AzureRmSubscription -SubscriptionID $subscriptionId;

# Register RPs
$resourceProviders = @("microsoft.storage");
if($resourceProviders.length) {
    Write-Host "Registering resource providers"
    foreach($resourceProvider in $resourceProviders) {
        RegisterRP($resourceProvider);
    }
}

#Create or check for existing resource group
$resourceGroup = Get-AzureRmResourceGroup -Name $resourceGroupName -ErrorAction SilentlyContinue
if(!$resourceGroup)
{
    Write-Host "Resource group '$resourceGroupName' does not exist. To create a new resource group, please enter a location.";
    if(!$resourceGroupLocation) {
        $resourceGroupLocation = Read-Host "resourceGroupLocation";
    }
    Write-Host "Creating resource group '$resourceGroupName' in location '$resourceGroupLocation'";
    New-AzureRmResourceGroup -Name $resourceGroupName -Location $resourceGroupLocation
}
else{
    Write-Host "Using existing resource group '$resourceGroupName'";
}

# Start the deployment
Write-Host "Starting deployment...";
if(Test-Path $parametersFilePath) {
    New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateFilePath -TemplateParameterFile $parametersFilePath;
} else {
    New-AzureRmResourceGroupDeployment -ResourceGroupName $resourceGroupName -TemplateFile $templateFilePath;
}
echo "***********************************************"
echo "The deploymentName can be any arbitrary string.  (this statement is for when the program initially runs and prompts user for a deploymentname; ignore it later)"

In the future we want to re-write these directions to use write-verbose instead of write-host. We want to warn people that write-verbose is recommended instead of write-host (according to this posting).

How Do You Install Azure PowerShell on Windows 10?

Problem scenario
You want to run ARM templates to declaratively create resources such as servers, databases, and subnets in Azure.  You need the PowerShell module for Azure to be installed for certain "reserved" words to work.  How do you install the Azure PowerShell?

Solution
1.  Open PowerShell as administrator.  (PowerShellGet is built into Windows 10 by default.  It may appear uninstalled, but it is natively part of the OS.)
2.  Run this command:  Install-Module Azure
3.  You can choose "Y" to the prompt.*
4.  Run this command:  Install-Module AzureRM.storage
5.  You can choose "Y" to the prompt.*
6.  Run this command: Install-Module AzureRM.resources
7.  You can choose "Y" to the prompt.*
8.  Run this command:  Install-Module AzureRM.Compute
9.  You can choose "Y" to the prompt.*
10.  Run this command:  Install-Module AzureRM.sql
11.  You can choose "Y" to the prompt.*
12.  Run this command:  Install-Module AzureRM.network
13.  You can choose "Y" to the prompt.*

*  If you have been running anti-malware applications on your desktop, and your laptop is reasonably secure, you can choose the "Y" option to the prompt about an untrusted repository and proceeding to install the modules from "PSGallery".