Skip to content

Commit

Permalink
Workload type principal preset (prod and non-prod) (#594)
Browse files Browse the repository at this point in the history
* scaffold

* automation account

* basic logs

* final naming

* automation account params and decorators

* start-stop tested e2e

* ui

* utc

* width

* Better UI - removed ACR

* formatt

* fixing test behaviour

* vnet oopsie

* lb
  • Loading branch information
Gordon Byers authored Jun 15, 2023
1 parent eedff24 commit 52914d7
Show file tree
Hide file tree
Showing 11 changed files with 474 additions and 57 deletions.
17 changes: 17 additions & 0 deletions bicep/automationrunbook/aksRbac.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
param principalId string
param aksName string

resource aks 'Microsoft.ContainerService/managedClusters@2023-03-02-preview' existing = {
name: aksName
}

var aksContributor = subscriptionResourceId('Microsoft.Authorization/roleDefinitions', 'b24988ac-6180-42a0-ab88-20f7382dd24c')
resource aksAutomation 'Microsoft.Authorization/roleAssignments@2022-04-01' = {
scope: aks
name: guid(aks.id, principalId , aksContributor)
properties: {
roleDefinitionId: aksContributor
principalType: 'ServicePrincipal'
principalId: principalId
}
}
188 changes: 188 additions & 0 deletions bicep/automationrunbook/automation.bicep
Original file line number Diff line number Diff line change
@@ -0,0 +1,188 @@
@description('The name of the Automation Account')
param automationAccountName string

@description('Deployment Location')
param location string = resourceGroup().location

@description('Used to reference todays date')
param today string = utcNow('yyyyMMddTHHmmssZ')

@description('The timezone to align schedules to. (Eg. "Europe/London" or "America/Los_Angeles")')
param timezone string = 'Etc/UTC'

@allowed(['Basic', 'Free'])
@description('The Automation Account SKU. See https://learn.microsoft.com/en-us/azure/automation/overview#pricing-for-azure-automation')
param accountSku string = 'Basic'

@description('For Automation job logging')
param loganalyticsWorkspaceId string = ''

@description('Which logging categeories to log')
param diagnosticCategories array = [
'JobLogs'
'JobStreams'
'AuditEvent'
]

type schedule = {
frequency : 'Day' | 'Weekday' | 'Week'

hour : hour
minute : minute
}

@minValue(0)
@maxValue(23)
@description('Seperately declaring as a type allows for min/max validation')
type hour = int

@minValue(0)
@maxValue(59)
@description('Seperately declaring as a type allows for min/max validation')
type minute = int

@description('Automation Schedules to create')
param schedulesToCreate schedule[] = [
{
frequency:'Day'
hour:9
minute:0
}
{
frequency:'Weekday'
hour:9
minute:0
}
{
frequency:'Day'
hour:19
minute:0
}
{
frequency:'Weekday'
hour:19
minute:0
}
{
frequency:'Day'
hour:0
minute:0
}
{
frequency:'Weekday'
hour: 0
minute:0
}
]

type runbookJob = {
scheduleName: string
parameters: object?
}

@description('The Runbook-Schedule Jobs to create with workflow specific parameters')
param runbookJobSchedule runbookJob[]

@description('The name of the runbook to create')
param runbookName string

@allowed([
'GraphPowerShell'
'Script'
])
@description('The type of runbook that is being imported')
param runbookType string = 'Script'

@description('The URI to import the runbook code from')
param runbookUri string = ''

@description('A description of what the runbook does')
param runbookDescription string = ''

var runbookVersion = '1.0.0.0'
var tomorrow = dateTimeAdd(today, 'P1D','yyyy-MM-dd')
var timebase = '1900-01-01'
var scheduleNoExpiry = '9999-12-31T23:59:00+00:00'
var workWeek = {weekDays: [
'Monday'
'Tuesday'
'Wednesday'
'Thursday'
'Friday'
]
}

resource automationAccount 'Microsoft.Automation/automationAccounts@2022-08-08' = {
name: automationAccountName
location: location
identity: {
type: 'SystemAssigned'
}
properties: {
sku: {
name: accountSku
}
}
}

resource automationAccountDiagLogging 'Microsoft.Insights/diagnosticSettings@2021-05-01-preview' = if(!empty(loganalyticsWorkspaceId)) {
name: 'diags'
scope: automationAccount
properties: {
workspaceId: loganalyticsWorkspaceId
logs: [for diagCategory in diagnosticCategories: {
category: diagCategory
enabled: true
}]
}
}

resource schedules 'Microsoft.Automation/automationAccounts/schedules@2022-08-08' = [for schedule in schedulesToCreate : {
parent: automationAccount
name: '${schedule.frequency} - ${dateTimeAdd(timebase,'PT${schedule.hour}H','HH')}:${dateTimeAdd(timebase,'PT${schedule.minute}M','mm')}'
properties: {
startTime: dateTimeAdd(dateTimeAdd(tomorrow,'PT${schedule.hour}H'), 'PT${schedule.minute}M','yyyy-MM-ddTHH:mm:00+00:00')
expiryTime: scheduleNoExpiry
interval: 1
frequency: schedule.frequency == 'Day' ? 'Day' : 'Week'
timeZone: timezone
advancedSchedule: schedule.frequency == 'Weekday' ? workWeek : {}
}
}]

resource runbook 'Microsoft.Automation/automationAccounts/runbooks@2022-08-08' = if(!empty(runbookName)) {
parent: automationAccount
name: !empty(runbookName) ? runbookName : 'armtemplatevalidationissue'
location: location
properties: {
logVerbose: true
logProgress: true
runbookType: runbookType
publishContentLink: {
uri: runbookUri
version: runbookVersion
}
description: runbookDescription
}
}

resource automationJobs 'Microsoft.Automation/automationAccounts/jobSchedules@2022-08-08' = [for job in runbookJobSchedule : if(!empty(runbookName)) {
parent: automationAccount
name: guid(automationAccount.id, runbook.name, job.scheduleName)
properties: {
schedule: {
name: job.scheduleName
}
runbook: {
name: runbook.name
}
parameters: job.parameters
}
dependsOn: [schedules] //All of the possible schedules
}]

@description('The Automation Account resource Id')
output automationAccountId string = automationAccount.id

@description('The Automation Account identity Principal Id')
output automationAccountPrincipalId string = automationAccount.identity.principalId
5 changes: 5 additions & 0 deletions bicep/automationrunbook/bicepconfig.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"experimentalFeaturesEnabled": {
"userDefinedTypes": true
}
}
81 changes: 81 additions & 0 deletions bicep/main.bicep
Original file line number Diff line number Diff line change
Expand Up @@ -1795,4 +1795,85 @@ resource telemetrydeployment 'Microsoft.Resources/deployments@2022-09-01' = if (
}
}

/* ___ __ __ .___________. ______ .___ ___. ___ .___________. __ ______ .__ __.
/ \ | | | | | | / __ \ | \/ | / \ | || | / __ \ | \ | |
/ ^ \ | | | | `---| |----`| | | | | \ / | / ^ \ `---| |----`| | | | | | | \| |
/ /_\ \ | | | | | | | | | | | |\/| | / /_\ \ | | | | | | | | | . ` |
/ _____ \ | `--' | | | | `--' | | | | | / _____ \ | | | | | `--' | | |\ |
/__/ \__\ \______/ |__| \______/ |__| |__| /__/ \__\ |__| |__| \______/ |__| \__| */

@allowed(['', 'Weekday', 'Day'])
@description('Creates an Azure Automation Account to provide scheduled start and stop of the cluster')
@metadata({category: 'Automation'})
param automationAccountScheduledStartStop string = ''

@description('The IANA time zone of the automation account')
@metadata({category: 'Automation'})
param automationTimeZone string = 'Etc/UTC'

@minValue(0)
@maxValue(23)
@description('When to start the cluster')
@metadata({category: 'Automation'})
param automationStartHour int = 8

@minValue(0)
@maxValue(23)
@description('When to stop the cluster')
@metadata({category: 'Automation'})
param automationStopHour int = 19

var automationFrequency = automationAccountScheduledStartStop == 'Day' ? 'Day' : 'Weekday'

module AksStartStop 'automationrunbook/automation.bicep' = if (!empty(automationAccountScheduledStartStop)) {
name: '${deployment().name}-Automation'
params: {
location: location
automationAccountName: 'aa-${resourceName}'
runbookName: 'aks-cluster-changestate'
runbookUri: 'https://raw.githubusercontent.com/finoops/aks-cluster-changestate/main/aks-cluster-changestate.ps1'
runbookType: 'Script'
timezone: automationTimeZone
schedulesToCreate : [
{
frequency: automationFrequency
hour: automationStartHour
minute: 0
}
{
frequency: automationFrequency
hour: automationStopHour
minute:0
}
]
runbookJobSchedule: [
{
scheduleName: '${automationFrequency} - ${padLeft(automationStartHour, 2, '0')}:00'
parameters: {
ResourceGroupName : resourceGroup().name
AksClusterName : aks.name
Operation: 'start'
}
}
{
scheduleName: '${automationFrequency} - ${padLeft(automationStopHour, 2, '0')}:00'
parameters: {
ResourceGroupName : resourceGroup().name
AksClusterName : aks.name
Operation: 'stop'
}
}
]
}
}

@description('Gives the Automation Account permission to stop/start the AKS cluster')
module aksAutomationRbac 'automationrunbook/aksRbac.bicep' = if (!empty(automationAccountScheduledStartStop)) {
name: '${deployment().name}-AutomationRbac'
params: {
aksName: aks.name
principalId: AksStartStop.outputs.automationAccountPrincipalId
}
}

//ACSCII Art link : https://textkool.com/en/ascii-art-generator?hl=default&vl=default&font=Star%20Wars&text=changeme
10 changes: 4 additions & 6 deletions helper/.playwrighttests/helper-test-managednatgw.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const { matchers } = require('playwright-expect');
// add custom matchers
expect.extend(matchers);

test('managed-natgw-option-is-not-the-default', async ({ page }) => {
test('managed-natgw-option-is-now-the-prod-default', async ({ page }) => {

await page.goto('http://localhost:3000/AKS-Construction');

Expand All @@ -14,17 +14,15 @@ test('managed-natgw-option-is-not-the-default', async ({ page }) => {
//Check default value
const dropdown = await page.waitForSelector('[data-testid="net-aksEgressType"]')
await expect(dropdown).toBeVisible()
await expect(dropdown).toMatchText('Load Balancer')
await expect(dropdown).toMatchText('Assigned NAT Gateway')

// Click the 1st Tab in the portal Navigation Pivot (network)
await page.click('[data-testid="portalnav-Pivot"] > button:nth-child(1)');

// //Check parameter is absent
// //Check parameter is there
await page.waitForSelector('[data-testid="deploy-deploycmd"]')
const clitextbox = await page.$('[data-testid="deploy-deploycmd"]')
await expect(clitextbox).toBeVisible()
await expect(clitextbox).not.toContainText('aksOutboundTrafficType')
await expect(clitextbox).toContainText('aksOutboundTrafficType=userAssignedNATGateway')

});

//TODO: Change value and check (this is a real pain with the DropDown control)
Loading

0 comments on commit 52914d7

Please sign in to comment.