From 31c7ed1be6e13bf1e75d9aa117d84554f327ef26 Mon Sep 17 00:00:00 2001 From: Christian Nunciato Date: Mon, 17 Oct 2022 16:18:47 -0700 Subject: [PATCH] Return JSON in all apps, add comments --- container-azure-csharp/Program.cs | 11 +- container-azure-csharp/app/Dockerfile | 7 +- container-azure-csharp/app/Program.cs | 8 +- container-azure-go/app/Dockerfile | 3 +- container-azure-go/app/main.go | 17 ++- container-azure-go/main.go | 13 ++- container-azure-python/__main__.py | 135 ++++++++++++++---------- container-azure-python/app/Dockerfile | 1 + container-azure-python/app/app.py | 2 +- container-azure-typescript/app/index.js | 8 +- container-azure-typescript/index.ts | 10 +- 11 files changed, 140 insertions(+), 75 deletions(-) diff --git a/container-azure-csharp/Program.cs b/container-azure-csharp/Program.cs index d4694101a..b9cac4b7c 100644 --- a/container-azure-csharp/Program.cs +++ b/container-azure-csharp/Program.cs @@ -7,6 +7,7 @@ return await Pulumi.Deployment.RunAsync(() => { + // Import the program's configuration settings. var config = new Config(); var appPath = config.Get("appPath") ?? "./app"; var imageName = config.Get("imageName") ?? "my-app"; @@ -14,8 +15,10 @@ var cpu = Math.Max(config.GetObject("cpu"), 1.0); var memory = Math.Max(config.GetObject("memory"), 1.5); + // Create a resource group for the container registry. var resourceGroup = new AzureNative.Resources.ResourceGroup("resource-group"); + // Create a container registry. var registry = new AzureNative.ContainerRegistry.Registry("registry", new() { ResourceGroupName = resourceGroup.Name, @@ -25,15 +28,16 @@ }, }); + // Fetch login credentials for the registry. var credentials = AzureNative.ContainerRegistry.ListRegistryCredentials.Invoke(new() { ResourceGroupName = resourceGroup.Name, RegistryName = registry.Name, }); - var registryUsername = credentials.Apply(result => result.Username!); var registryPassword = credentials.Apply(result => result.Passwords[0]!.Value!); + // Create a container image for the service. var image = new Docker.Image("image", new() { ImageName = Pulumi.Output.Format($"{registry.LoginServer}/{imageName}"), @@ -47,12 +51,14 @@ }, }); + // Use a random string to give the service a unique DNS name. var dnsName = new Random.RandomString("dns-name", new() { Length = 8, Special = false, }).Result.Apply(result => $"{imageName}-{result.ToLower()}"); + // Create a container group for the service that makes it publicly accessible. var containerGroup = new AzureNative.ContainerInstance.ContainerGroup("container-group", new() { ResourceGroupName = resourceGroup.Name, @@ -103,10 +109,11 @@ } }); + // Export the service's IP address, hostname, and fully-qualified URL. return new Dictionary { - ["ipAddress"] = containerGroup.IpAddress.Apply(addr => addr!.Ip), ["hostname"] = containerGroup.IpAddress.Apply(addr => addr!.Fqdn), + ["ip"] = containerGroup.IpAddress.Apply(addr => addr!.Ip), ["url"] = containerGroup.IpAddress.Apply(addr => $"http://{addr!.Fqdn}:{containerPort}"), }; }); diff --git a/container-azure-csharp/app/Dockerfile b/container-azure-csharp/app/Dockerfile index fa18e125c..a2f435fc4 100644 --- a/container-azure-csharp/app/Dockerfile +++ b/container-azure-csharp/app/Dockerfile @@ -1,13 +1,14 @@ FROM mcr.microsoft.com/dotnet/sdk:6.0 AS build -WORKDIR /app +WORKDIR /app COPY *.csproj ./ RUN dotnet restore - -COPY . ./ +COPY . . RUN dotnet publish -c Release -o out FROM mcr.microsoft.com/dotnet/aspnet:6.0 as base + WORKDIR /app COPY --from=build /app/out . + ENTRYPOINT ["dotnet", "App.dll"] diff --git a/container-azure-csharp/app/Program.cs b/container-azure-csharp/app/Program.cs index 04ce7f50d..3936e7bec 100644 --- a/container-azure-csharp/app/Program.cs +++ b/container-azure-csharp/app/Program.cs @@ -1,6 +1,12 @@ var builder = WebApplication.CreateBuilder(args); var app = builder.Build(); -app.MapGet("/", () => "Hello, world! 👋"); +app.MapGet("/", async (context) => +{ + await context.Response.WriteAsJsonAsync(new + { + message = "Hello, world! 👋" + }); +}); app.Run(); diff --git a/container-azure-go/app/Dockerfile b/container-azure-go/app/Dockerfile index 9369b67c4..c8b62cdca 100644 --- a/container-azure-go/app/Dockerfile +++ b/container-azure-go/app/Dockerfile @@ -4,8 +4,7 @@ WORKDIR /usr/src/app COPY go.* ./ RUN go mod download - COPY . . RUN go build -o /app -ENTRYPOINT /app +ENTRYPOINT ["/app"] diff --git a/container-azure-go/app/main.go b/container-azure-go/app/main.go index 710b0f0d1..1426cab70 100644 --- a/container-azure-go/app/main.go +++ b/container-azure-go/app/main.go @@ -1,16 +1,31 @@ package main import ( + "encoding/json" "fmt" "log" "net/http" "os" ) +type AppResponse struct { + Message string `json:"message"` +} + func main() { http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { - fmt.Fprintf(w, "Hello, world! 👋") + response := AppResponse{ + Message: "Hello, world! 👋", + } + + s, err := json.Marshal(response) + if err != nil { + http.Error(w, "Internal Server Error", http.StatusInternalServerError) + } + + w.Header().Set("Content-Type", "application/json") + fmt.Fprintf(w, string(s)) }) if err := http.ListenAndServe(fmt.Sprintf(":%s", os.Getenv("PORT")), nil); err != nil { diff --git a/container-azure-go/main.go b/container-azure-go/main.go index 04c9e4e21..1ea3148c0 100644 --- a/container-azure-go/main.go +++ b/container-azure-go/main.go @@ -16,6 +16,7 @@ import ( func main() { pulumi.Run(func(ctx *pulumi.Context) error { + // Import the program's configuration settings. cfg := config.New(ctx, "") imageName := "my-app" if param := cfg.Get("imageName"); param != "" { @@ -33,16 +34,18 @@ func main() { if param := cfg.GetFloat64("cpu"); param != 0 { cpu = param } - memory := 1.0 + memory := 1.5 if param := cfg.GetFloat64("memory"); param != 0 { memory = param } + // Create a resource group for the container registry. resourceGroup, err := resources.NewResourceGroup(ctx, "resource-group", nil) if err != nil { return err } + // Create a container registry. registry, err := containerregistry.NewRegistry(ctx, "registry", &containerregistry.RegistryArgs{ ResourceGroupName: resourceGroup.Name, AdminUserEnabled: pulumi.Bool(true), @@ -54,6 +57,7 @@ func main() { return err } + // Fetch login credentials for the registry. credentials := containerregistry.ListRegistryCredentialsOutput(ctx, containerregistry.ListRegistryCredentialsOutputArgs{ ResourceGroupName: resourceGroup.Name, RegistryName: registry.Name, @@ -61,6 +65,7 @@ func main() { registryUsername := credentials.Username().Elem() registryPassword := credentials.Passwords().Index(pulumi.Int(0)).Value().Elem() + // Create a container image for the service. image, err := docker.NewImage(ctx, "image", &docker.ImageArgs{ ImageName: pulumi.Sprintf("%s/%s", registry.LoginServer, imageName), Build: docker.DockerBuildArgs{ @@ -76,6 +81,7 @@ func main() { return err } + // Use a random string to give the service a unique DNS name. dnsNameSuffix, err := random.NewRandomString(ctx, "dns-name-suffix", &random.RandomStringArgs{ Length: pulumi.Int(8), Special: pulumi.Bool(false), @@ -83,11 +89,11 @@ func main() { if err != nil { return err } - dnsName := dnsNameSuffix.Result.ApplyT(func(result string) string { return fmt.Sprintf("%s-%s", imageName, strings.ToLower(result)) }).(pulumi.StringOutput) + // Create a container group for the service that makes it publicly accessible. containerGroup, err := containerinstance.NewContainerGroup(ctx, "container-group", &containerinstance.ContainerGroupArgs{ ResourceGroupName: resourceGroup.Name, OsType: pulumi.String("linux"), @@ -135,7 +141,8 @@ func main() { }, }) - ctx.Export("ipAddress", containerGroup.IpAddress.Elem().Ip()) + // Export the service's IP address, hostname, and fully-qualified URL. + ctx.Export("ip", containerGroup.IpAddress.Elem().Ip()) ctx.Export("hostname", containerGroup.IpAddress.Elem().Fqdn()) ctx.Export("url", pulumi.Sprintf("http://%s:%d", containerGroup.IpAddress.Elem().Fqdn(), containerPort)) diff --git a/container-azure-python/__main__.py b/container-azure-python/__main__.py index 543d74518..b0c17e447 100644 --- a/container-azure-python/__main__.py +++ b/container-azure-python/__main__.py @@ -3,6 +3,7 @@ import pulumi_random as random from pulumi_azure_native import resources, containerregistry, containerinstance +# Import the program's configuration settings. config = pulumi.Config() image_name = config.get("imageName", "my-app") app_path = config.get("appPath", "./app") @@ -10,16 +11,22 @@ cpu = config.get_float("cpu", 1.0) memory = config.get_float("memory", 1.5) +# Create a resource group for the container registry. resource_group = resources.ResourceGroup("resource-group") -registry = containerregistry.Registry("registry", containerregistry.RegistryArgs( - resource_group_name=resource_group.name, - admin_user_enabled=True, - sku=containerregistry.SkuArgs( - name=containerregistry.SkuName.BASIC, +# Create a container registry. +registry = containerregistry.Registry( + "registry", + containerregistry.RegistryArgs( + resource_group_name=resource_group.name, + admin_user_enabled=True, + sku=containerregistry.SkuArgs( + name=containerregistry.SkuName.BASIC, + ), ), -)) +) +# Fetch login credentials for the registry. credentials = containerregistry.list_registry_credentials_output( resource_group_name=resource_group.name, registry_name=registry.name, @@ -28,7 +35,9 @@ registry_username = credentials.apply(lambda creds: creds.username) registry_password = credentials.apply(lambda creds: creds.passwords[0].value) -image = docker.Image("image", +# Create a container image for the service. +image = docker.Image( + "image", image_name=pulumi.Output.concat(registry.login_server, "/", image_name), build=docker.DockerBuild( context=app_path, @@ -40,62 +49,76 @@ ), ) -dns_name = random.RandomString("dns-name", random.RandomStringArgs( - length=8, - special=False, -)).result.apply(lambda result: f"{image_name}-{result.lower()}") +# Use a random string to give the service a unique DNS name. +dns_name = random.RandomString( + "dns-name", + random.RandomStringArgs( + length=8, + special=False, + ), +).result.apply(lambda result: f"{image_name}-{result.lower()}") -container_group = containerinstance.ContainerGroup("container-group", containerinstance.ContainerGroupArgs( - resource_group_name=resource_group.name, - os_type="linux", - restart_policy="always", - image_registry_credentials=[ - containerinstance.ImageRegistryCredentialArgs( - server=registry.login_server, - username=registry_username, - password=registry_password, - ), - ], - containers=[ - containerinstance.ContainerArgs( - name=image_name, - image=image.image_name, +# Create a container group for the service that makes it publicly accessible. +container_group = containerinstance.ContainerGroup( + "container-group", + containerinstance.ContainerGroupArgs( + resource_group_name=resource_group.name, + os_type="linux", + restart_policy="always", + image_registry_credentials=[ + containerinstance.ImageRegistryCredentialArgs( + server=registry.login_server, + username=registry_username, + password=registry_password, + ), + ], + containers=[ + containerinstance.ContainerArgs( + name=image_name, + image=image.image_name, + ports=[ + containerinstance.ContainerPortArgs( + port=container_port, + protocol="tcp", + ), + ], + environment_variables=[ + containerinstance.EnvironmentVariableArgs( + name="FLASK_RUN_PORT", + value=str(container_port), + ), + containerinstance.EnvironmentVariableArgs( + name="FLASK_RUN_HOST", + value="0.0.0.0", + ), + ], + resources=containerinstance.ResourceRequirementsArgs( + requests=containerinstance.ResourceRequestsArgs( + cpu=cpu, + memory_in_gb=memory, + ), + ), + ), + ], + ip_address=containerinstance.IpAddressArgs( + type=containerinstance.ContainerGroupIpAddressType.PUBLIC, + dns_name_label=dns_name, ports=[ - containerinstance.ContainerPortArgs( + containerinstance.PortArgs( port=container_port, protocol="tcp", ), ], - environment_variables=[ - containerinstance.EnvironmentVariableArgs( - name="FLASK_RUN_PORT", - value=str(container_port), - ), - containerinstance.EnvironmentVariableArgs( - name="FLASK_RUN_HOST", - value="0.0.0.0", - ), - ], - resources=containerinstance.ResourceRequirementsArgs( - requests=containerinstance.ResourceRequestsArgs( - cpu=cpu, - memory_in_gb=memory, - ), - ), ), - ], - ip_address=containerinstance.IpAddressArgs( - type=containerinstance.ContainerGroupIpAddressType.PUBLIC, - dns_name_label=dns_name, - ports=[ - containerinstance.PortArgs( - port=container_port, - protocol="tcp", - ), - ], ), -)) +) -pulumi.export("ipAddress", container_group.ip_address.apply(lambda addr: addr.ip)) +# Export the service's IP address, hostname, and fully-qualified URL. pulumi.export("hostname", container_group.ip_address.apply(lambda addr: addr.fqdn)) -pulumi.export("url", container_group.ip_address.apply(lambda addr: f"http://{addr.fqdn}:{container_port}")) +pulumi.export("ip", container_group.ip_address.apply(lambda addr: addr.ip)) +pulumi.export( + "url", + container_group.ip_address.apply( + lambda addr: f"http://{addr.fqdn}:{container_port}" + ), +) diff --git a/container-azure-python/app/Dockerfile b/container-azure-python/app/Dockerfile index 1e2f05ac2..2e6ab7b30 100644 --- a/container-azure-python/app/Dockerfile +++ b/container-azure-python/app/Dockerfile @@ -1,4 +1,5 @@ FROM python:3.10-alpine + WORKDIR /usr/src/app COPY requirements.txt requirements.txt diff --git a/container-azure-python/app/app.py b/container-azure-python/app/app.py index 161faf4d7..aec19bd2d 100644 --- a/container-azure-python/app/app.py +++ b/container-azure-python/app/app.py @@ -4,4 +4,4 @@ @app.route("/") def index(): - return "Hello, world! 👋" + return { "message": "Hello, world! 👋" } diff --git a/container-azure-typescript/app/index.js b/container-azure-typescript/app/index.js index 1778c60f3..389b064c1 100644 --- a/container-azure-typescript/app/index.js +++ b/container-azure-typescript/app/index.js @@ -4,12 +4,10 @@ const express = require("express"); const app = express(); app.get("/", (req, res) => { - res.send("Hello, world! 👋"); + res.json({ message: "Hello, world! 👋" }); }); -const host = "0.0.0.0"; const port = process.env.PORT; - -app.listen(port, host, () => { - console.log(`Running on http://${host}:${port}`); +app.listen(port, () => { + console.log(`Listening on port ${port}`); }); diff --git a/container-azure-typescript/index.ts b/container-azure-typescript/index.ts index 4f910a8da..84d5407bb 100644 --- a/container-azure-typescript/index.ts +++ b/container-azure-typescript/index.ts @@ -5,13 +5,16 @@ import * as containerinstance from "@pulumi/azure-native/containerinstance"; import * as random from "@pulumi/random"; import * as docker from "@pulumi/docker"; +// Import the program's configuration settings. const config = new pulumi.Config(); const imageName = config.get("imageName") || "my-app"; const appPath = config.get("appPath") || "./app"; const containerPort = config.getNumber("containerPort") || 80; +// Create a resource group for the container registry. const resourceGroup = new resources.ResourceGroup("resource-group"); +// Create a container registry. const registry = new containerregistry.Registry("registry", { resourceGroupName: resourceGroup.name, adminUserEnabled: true, @@ -20,6 +23,7 @@ const registry = new containerregistry.Registry("registry", { }, }); +// Fetch login credentials for the registry. const credentials = containerregistry.listRegistryCredentialsOutput({ resourceGroupName: resourceGroup.name, registryName: registry.name, @@ -30,6 +34,7 @@ const credentials = containerregistry.listRegistryCredentialsOutput({ }; }); +// Create a container image for the service. const image = new docker.Image("image", { imageName: pulumi.interpolate`${registry.loginServer}/${imageName}`, build: { @@ -42,11 +47,13 @@ const image = new docker.Image("image", { }, }); +// Use a random string to give the service a unique DNS name. const dnsName = new random.RandomString("dns-name", { length: 8, special: false, }).result.apply(result => `${imageName}-${result.toLowerCase()}`); +// Create a container group for the service that makes it publicly accessible. const containerGroup = new containerinstance.ContainerGroup("container-group", { resourceGroupName: resourceGroup.name, osType: "linux", @@ -94,6 +101,7 @@ const containerGroup = new containerinstance.ContainerGroup("container-group", { }, }); -export const ipAddress = containerGroup.ipAddress.apply(addr => addr!.ip!); +// Export the service's IP address, hostname, and fully-qualified URL. export const hostname = containerGroup.ipAddress.apply(addr => addr!.fqdn!); +export const ip = containerGroup.ipAddress.apply(addr => addr!.ip!); export const url = containerGroup.ipAddress.apply(addr => `http://${addr!.fqdn!}:${containerPort}`);