Skip to content

Commit 8eee8f1

Browse files
author
Jean-Marc van Leerdam
committed
WIP - adding azure CLI logic to create prerequisite resource group and storage account
1 parent 60c1da7 commit 8eee8f1

File tree

7 files changed

+264
-128
lines changed

7 files changed

+264
-128
lines changed
Lines changed: 25 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,29 @@
11
package sbtazurefunctions
22

3-
import nl.codestar.azurefunctions.FunctionConfigGenerator
4-
import org.reflections.util.ClasspathHelper
5-
import sbt.Keys.{baseDirectory, target}
63
import sbt._
7-
import sbt.io.Path.allSubpaths
8-
import sbtassembly.AssemblyKeys.assembly
9-
10-
import scala.collection.JavaConverters.collectionAsScalaIterableConverter
114

125
object AzureFunctionsKeys {
13-
val azfunTargetFolder = settingKey[File](
14-
"Target folder that receives the Azure function definitions"
15-
)
166
val azfunHostJsonFile =
177
settingKey[File]("Location of the host.json file")
188
val azfunJarName =
199
settingKey[String]("Name of the jar that holds the function definitions (default: AzureFunction.jar)")
2010
val azfunLocalSettingsFile =
2111
settingKey[File]("Location of the local.settings.json")
12+
val azfunTargetFolder = settingKey[File](
13+
"Target folder that receives the Azure function definitions"
14+
)
2215
val azfunZipName =
2316
settingKey[String]("Name of the zip file that will contain the results (default: AzureFunction.zip)")
2417

18+
// settings for Azure resources
19+
val azfunAppInsightsName =
20+
settingKey[String]("Azure Application Insights instance (defaults to azfunFunctionAppName)")
21+
val azfunFunctionAppName = settingKey[String]("Function App Name for the Azure Function")
22+
val azfunLocation = settingKey[String]("Azure Location for the Azure Function")
23+
val azfunResourceGroup = settingKey[String]("Resource group that will hold the Azure Function")
24+
val azfunSKU = settingKey[String]("The Stock Keeping Unit (SKU) for the storage account (defaults to Standard_LRS)")
25+
val azfunStorageAccount = settingKey[String]("Storage Account for the Azure Function")
26+
2527
val azfunCreateZipFile = taskKey[File](
2628
"Generate the zip file containing the complete Azure Function definition"
2729
)
@@ -38,128 +40,24 @@ object AzureFunctions extends AutoPlugin {
3840
override def requires = sbt.plugins.JvmPlugin
3941

4042
object autoImport {
41-
val AzureFunctionsKeys = sbtazurefunctions.AzureFunctionsKeys
43+
// settings available to users
4244
val azfunJarName = sbtazurefunctions.AzureFunctionsKeys.azfunJarName
4345
val azfunZipName = sbtazurefunctions.AzureFunctionsKeys.azfunZipName
44-
val azfunCreateZipFile = sbtazurefunctions.AzureFunctionsKeys.azfunCreateZipFile
45-
}
46-
47-
import AzureFunctionsKeys._
48-
49-
override lazy val projectSettings: Seq[Setting[_]] = Seq(
50-
azfunHostJsonFile := (baseDirectory in Compile).value / "host.json",
51-
azfunLocalSettingsFile := (baseDirectory in Compile).value / "local.settings.json",
52-
azfunTargetFolder := (target in Compile).value / stripExtension(azfunZipName.value),
53-
azfunZipName := "AzureFunction.zip",
54-
azfunJarName := "AzureFunction.jar",
55-
azfunCopyHostJson := {
56-
val log = sbt.Keys.streams.value.log
57-
val folder = azfunTargetFolder.value
58-
log.info(s"Placing host.json in $folder ...")
59-
60-
val src = azfunHostJsonFile.value
61-
val tgt = azfunTargetFolder.value / "host.json"
62-
63-
IO.copy(
64-
Seq((src, tgt)),
65-
CopyOptions.apply(
66-
overwrite = true,
67-
preserveLastModified = true,
68-
preserveExecutable = false
69-
)
70-
)
71-
tgt
72-
},
73-
azfunCopyLocalSettingsJson := {
74-
val log = sbt.Keys.streams.value.log
75-
val folder = azfunTargetFolder.value
76-
log.info(s"Placing local.settings.json in $folder ...")
77-
78-
val src = azfunLocalSettingsFile.value
79-
val tgt = azfunTargetFolder.value / "local.settings.json"
46+
val azfunTargetFolder = sbtazurefunctions.AzureFunctionsKeys.azfunTargetFolder
8047

81-
IO.copy(
82-
Seq((src, tgt)),
83-
CopyOptions.apply(
84-
overwrite = true,
85-
preserveLastModified = true,
86-
preserveExecutable = false
87-
)
88-
)
89-
tgt
90-
},
91-
azfunCreateZipFile := {
92-
// depend on the steps that provide the contents of the zip
93-
val _ = {
94-
azfunCopyHostJson.value
95-
azfunCopyLocalSettingsJson.value
96-
azfunGenerateFunctionJsons.value
97-
}
48+
val azfunAppInsightsName = sbtazurefunctions.AzureFunctionsKeys.azfunAppInsightsName
49+
val azfunFunctionAppName = sbtazurefunctions.AzureFunctionsKeys.azfunFunctionAppName
50+
val azfunLocation = sbtazurefunctions.AzureFunctionsKeys.azfunLocation
51+
val azfunResourceGroup = sbtazurefunctions.AzureFunctionsKeys.azfunResourceGroup
52+
val azfunStorageAccount = sbtazurefunctions.AzureFunctionsKeys.azfunStorageAccount
53+
val azfunSKU = sbtazurefunctions.AzureFunctionsKeys.azfunSKU
9854

99-
val log = sbt.Keys.streams.value.log
100-
101-
val tgtFolder = (target in Compile).value
102-
103-
log.info("Running azfunCreateZipFile task...")
104-
log.info(
105-
s"Creating Azure Function zip file in target folder ($tgtFolder) ..."
106-
)
107-
108-
val src = azfunTargetFolder.value
109-
val tgt = tgtFolder / ensureExtension(azfunZipName.value, "zip")
110-
IO.zip(allSubpaths(src), tgt)
111-
tgt
112-
},
113-
azfunDeploy := {
114-
// depend on having the zip available
115-
val _ = azfunCreateZipFile.value
116-
//val artefact = azfunCreateZipFile.value
117-
118-
val log = sbt.Keys.streams.value.log
119-
log.info("Running azfunDeploy task...")
120-
121-
import scala.sys.process._
122-
import scala.language.postfixOps
123-
"echo 'hello world'" !
124-
},
125-
azfunGenerateFunctionJsons := {
126-
// depend on assembly step
127-
val assemblyJar = assembly.value
128-
val log = sbt.Keys.streams.value.log
129-
130-
val folder = azfunTargetFolder.value
131-
132-
log.info("Running azureFunctions task...")
133-
log.info(s"Generating function.json files to $folder ...")
134-
135-
val fatJarFile = folder / azfunJarName.value
136-
137-
// copy the assembly jar into the folder that will be zipped eventually
138-
IO.copy(
139-
Seq((assemblyJar, fatJarFile))
140-
)
141-
val urls = ClasspathHelper.forManifest(fatJarFile.toURI.toURL).asScala.toList
142-
val configs = FunctionConfigGenerator.getConfigs(urls)
143-
144-
val baseFolder = azfunTargetFolder.value
145-
FunctionConfigGenerator.generateFunctionJsons(azfunJarName.value, baseFolder.toPath, configs)
146-
azfunTargetFolder.value
147-
}
148-
)
149-
150-
private def ensureExtension(input: String, extension: String): String = {
151-
input.lastIndexOf('.') match {
152-
case 0 => s"${input}.${extension}"
153-
case n if (n == input.size - 1) => s"${input}${extension}"
154-
case _ => input
155-
}
55+
// tasks available to users
56+
val azfunCreateZipFile = sbtazurefunctions.AzureFunctionsKeys.azfunCreateZipFile
57+
val azfunDeploy = sbtazurefunctions.AzureFunctionsKeys.azfunDeploy
15658
}
15759

158-
private def stripExtension(input: String): String = {
159-
input.lastIndexOf('.') match {
160-
case 0 => input
161-
case n => input.take(n)
162-
}
163-
}
60+
override lazy val projectSettings: Seq[Setting[_]] =
61+
DefaultSettings.settings ++ CopyTask.settings ++ CreateZipFileTask.settings ++ DeployTask.settings ++ GenerateFunctionsJsonTask.settings
16462

16563
}
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package sbtazurefunctions
2+
3+
import sbt._
4+
import sbt.{CopyOptions, IO, Setting}
5+
import sbtazurefunctions.AzureFunctionsKeys.{
6+
azfunCopyHostJson,
7+
azfunCopyLocalSettingsJson,
8+
azfunHostJsonFile,
9+
azfunLocalSettingsFile,
10+
azfunTargetFolder
11+
}
12+
13+
object CopyTask {
14+
def settings: Seq[Setting[_]] =
15+
Seq(
16+
azfunCopyHostJson := {
17+
val log = sbt.Keys.streams.value.log
18+
val folder = azfunTargetFolder.value
19+
log.info(s"Placing host.json in $folder ...")
20+
21+
val src = azfunHostJsonFile.value
22+
val tgt = azfunTargetFolder.value / "host.json"
23+
24+
IO.copy(
25+
Seq((src, tgt)),
26+
CopyOptions.apply(
27+
overwrite = true,
28+
preserveLastModified = true,
29+
preserveExecutable = false
30+
)
31+
)
32+
tgt
33+
},
34+
azfunCopyLocalSettingsJson := {
35+
val log = sbt.Keys.streams.value.log
36+
val folder = azfunTargetFolder.value
37+
log.info(s"Placing local.settings.json in $folder ...")
38+
39+
val src = azfunLocalSettingsFile.value
40+
val tgt = azfunTargetFolder.value / "local.settings.json"
41+
42+
IO.copy(
43+
Seq((src, tgt)),
44+
CopyOptions.apply(
45+
overwrite = true,
46+
preserveLastModified = true,
47+
preserveExecutable = false
48+
)
49+
)
50+
tgt
51+
}
52+
)
53+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
package sbtazurefunctions
2+
3+
import sbt._
4+
import sbt.Keys.target
5+
import sbt.io.Path.allSubpaths
6+
import sbt.{IO, Setting}
7+
import sbtazurefunctions.AzureFunctionsKeys._
8+
9+
object CreateZipFileTask {
10+
def settings: Seq[Setting[_]] =
11+
Seq(
12+
azfunCreateZipFile := {
13+
// depend on the steps that provide the contents of the zip
14+
val _ = {
15+
azfunCopyHostJson.value
16+
azfunCopyLocalSettingsJson.value
17+
azfunGenerateFunctionJsons.value
18+
}
19+
20+
val log = sbt.Keys.streams.value.log
21+
22+
val tgtFolder = (target in Compile).value
23+
24+
log.info("Running azfunCreateZipFile task...")
25+
log.info(
26+
s"Creating Azure Function zip file in target folder ($tgtFolder) ..."
27+
)
28+
29+
val src = azfunTargetFolder.value
30+
val tgt = tgtFolder / ensureExtension(azfunZipName.value, "zip")
31+
IO.zip(allSubpaths(src), tgt)
32+
tgt
33+
}
34+
)
35+
36+
private def ensureExtension(input: String, extension: String): String = {
37+
input.lastIndexOf('.') match {
38+
case 0 => s"${input}.${extension}"
39+
case n if (n == input.size - 1) => s"${input}${extension}"
40+
case _ => input
41+
}
42+
}
43+
}
Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package sbtazurefunctions
2+
3+
import sbt._
4+
import sbt.Keys.{baseDirectory, target}
5+
import sbt.Setting
6+
import sbtazurefunctions.AzureFunctionsKeys.{
7+
azfunAppInsightsName,
8+
azfunFunctionAppName,
9+
azfunHostJsonFile,
10+
azfunJarName,
11+
azfunLocalSettingsFile,
12+
azfunSKU,
13+
azfunTargetFolder,
14+
azfunZipName
15+
}
16+
17+
object DefaultSettings {
18+
def settings: Seq[Setting[_]] =
19+
Seq(
20+
azfunAppInsightsName := azfunFunctionAppName.value,
21+
azfunHostJsonFile := (baseDirectory in Compile).value / "host.json",
22+
azfunJarName := "AzureFunction.jar",
23+
azfunLocalSettingsFile := (baseDirectory in Compile).value / "local.settings.json",
24+
azfunSKU := "Standard_LRS",
25+
azfunTargetFolder := (target in Compile).value / stripExtension(azfunZipName.value),
26+
azfunZipName := "AzureFunction.zip"
27+
)
28+
29+
private def stripExtension(input: String): String = {
30+
input.lastIndexOf('.') match {
31+
case 0 => input
32+
case n => input.take(n)
33+
}
34+
}
35+
36+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
package sbtazurefunctions
2+
3+
import sbt.Setting
4+
import sbtazurefunctions.AzureFunctionsKeys.{
5+
azfunCreateZipFile,
6+
azfunDeploy,
7+
azfunLocation,
8+
azfunResourceGroup,
9+
azfunSKU,
10+
azfunStorageAccount
11+
}
12+
13+
object DeployTask {
14+
def settings: Seq[Setting[_]] =
15+
Seq(
16+
azfunDeploy := {
17+
// depend on having the zip available
18+
val _ = azfunCreateZipFile.value
19+
//val artefact = azfunCreateZipFile.value
20+
21+
val log = sbt.Keys.streams.value.log
22+
log.info("Running azfunDeploy task")
23+
24+
import scala.language.postfixOps
25+
import scala.sys.process._
26+
27+
val resourceGroup = azfunResourceGroup.value
28+
log.info(s"Checking if group ${resourceGroup} exists...")
29+
val output = (s"az group exists -n ${resourceGroup}" !!)
30+
val groupExists = output.startsWith("true")
31+
if (!groupExists) {
32+
log.info(s"Group ${resourceGroup} does not yet exist, creating it")
33+
val result = (s"az group create -n ${resourceGroup} -l ${azfunLocation.value}" !)
34+
if (result != 0) {
35+
log.error("Failed to create resource group")
36+
} else {
37+
log.info("Resource group created")
38+
}
39+
} else {
40+
log.info(s"Group ${resourceGroup} is present")
41+
}
42+
43+
val storageAccount = azfunStorageAccount.value
44+
log.info(s"Checking if storage account ${storageAccount} exists...")
45+
val output2 = (s"az storage account check-name -n ${storageAccount} --query nameAvailable" !!)
46+
val saExists = output2.startsWith("false")
47+
if (!saExists) {
48+
log.info(s"Storage Account ${storageAccount} does not yet exist, creating it")
49+
val result =
50+
s"az storage account create -n ${storageAccount} -l ${azfunLocation.value} -g ${resourceGroup} --sku ${azfunSKU.value}" !
51+
52+
if (result != 0) {
53+
log.error("Failed to create storage account")
54+
} else {
55+
log.info("Storage account created")
56+
}
57+
} else {
58+
log.info(s"Storage account ${storageAccount} is present")
59+
}
60+
61+
}
62+
)
63+
}

0 commit comments

Comments
 (0)