From 45e5f8a96e05b13513d280db20046868c91b98e4 Mon Sep 17 00:00:00 2001 From: Julien Poissonnier Date: Fri, 30 Aug 2024 11:21:02 +0200 Subject: [PATCH 1/2] Update more python templates to use dictionary literals With type checking for dictionary literals, we now prefer this style over args classes https://github.com/pulumi/pulumi/issues/12689 --- static-website-aws-python/__main__.py | 95 +++++++------- static-website-azure-python/__main__.py | 20 +-- static-website-gcp-python/__main__.py | 8 +- vm-aws-python/__main__.py | 85 ++++++++----- vm-azure-python/__main__.py | 158 +++++++++++------------- webapp-kubernetes-python/__main__.py | 118 ++++++++++-------- 6 files changed, 250 insertions(+), 234 deletions(-) diff --git a/static-website-aws-python/__main__.py b/static-website-aws-python/__main__.py index 149ce6e68..6d951cd5c 100644 --- a/static-website-aws-python/__main__.py +++ b/static-website-aws-python/__main__.py @@ -11,19 +11,19 @@ # Create an S3 bucket and configure it as a website. bucket = aws.s3.Bucket( "bucket", - website=aws.s3.BucketWebsiteArgs( - index_document=index_document, - error_document=error_document, - ), + website={ + "index_document": index_document, + "error_document": error_document, + }, ) # Set ownership controls for the new bucket ownership_controls = aws.s3.BucketOwnershipControls( "ownership-controls", bucket=bucket.bucket, - rule=aws.s3.BucketOwnershipControlsRuleArgs( - object_ownership="ObjectWriter", - ) + rule={ + "object_ownership": "ObjectWriter", + }, ) # Configure public ACL block on the new bucket @@ -39,10 +39,7 @@ acl="public-read", bucket_name=bucket.bucket, path=path, - opts=pulumi.ResourceOptions(depends_on=[ - ownership_controls, - public_access_block - ]) + opts=pulumi.ResourceOptions(depends_on=[ownership_controls, public_access_block]), ) # Create a CloudFront CDN to distribute and cache the website. @@ -50,56 +47,56 @@ "cdn", enabled=True, origins=[ - aws.cloudfront.DistributionOriginArgs( - origin_id=bucket.arn, - domain_name=bucket.website_endpoint, - custom_origin_config=aws.cloudfront.DistributionOriginCustomOriginConfigArgs( - origin_protocol_policy="http-only", - http_port=80, - https_port=443, - origin_ssl_protocols=["TLSv1.2"], - ), - ) + { + "origin_id": bucket.arn, + "domain_name": bucket.website_endpoint, + "custom_origin_config": { + "origin_protocol_policy": "http-only", + "http_port": 80, + "https_port": 443, + "origin_ssl_protocols": ["TLSv1.2"], + }, + } ], - default_cache_behavior=aws.cloudfront.DistributionDefaultCacheBehaviorArgs( - target_origin_id=bucket.arn, - viewer_protocol_policy="redirect-to-https", - allowed_methods=[ + default_cache_behavior={ + "target_origin_id": bucket.arn, + "viewer_protocol_policy": "redirect-to-https", + "allowed_methods": [ "GET", "HEAD", "OPTIONS", ], - cached_methods=[ + "cached_methods": [ "GET", "HEAD", "OPTIONS", ], - default_ttl=600, - max_ttl=600, - min_ttl=600, - forwarded_values=aws.cloudfront.DistributionDefaultCacheBehaviorForwardedValuesArgs( - query_string=True, - cookies=aws.cloudfront.DistributionDefaultCacheBehaviorForwardedValuesCookiesArgs( - forward="all", - ), - ), - ), + "default_ttl": 600, + "max_ttl": 600, + "min_ttl": 600, + "forwarded_values": { + "query_string": True, + "cookies": { + "forward": "all", + }, + }, + }, price_class="PriceClass_100", custom_error_responses=[ - aws.cloudfront.DistributionCustomErrorResponseArgs( - error_code=404, - response_code=404, - response_page_path=f"/{error_document}", - ) + { + "error_code": 404, + "response_code": 404, + "response_page_path": f"/{error_document}", + } ], - restrictions=aws.cloudfront.DistributionRestrictionsArgs( - geo_restriction=aws.cloudfront.DistributionRestrictionsGeoRestrictionArgs( - restriction_type="none", - ), - ), - viewer_certificate=aws.cloudfront.DistributionViewerCertificateArgs( - cloudfront_default_certificate=True, - ), + restrictions={ + "geo_restriction": { + "restriction_type": "none", + }, + }, + viewer_certificate={ + "cloudfront_default_certificate": True, + }, ) # Export the URLs and hostnames of the bucket and distribution. diff --git a/static-website-azure-python/__main__.py b/static-website-azure-python/__main__.py index 2d817528c..ec2824f05 100644 --- a/static-website-azure-python/__main__.py +++ b/static-website-azure-python/__main__.py @@ -17,9 +17,9 @@ "account", resource_group_name=resource_group.name, kind="StorageV2", - sku=azure_native.storage.SkuArgs( - name="Standard_LRS", - ), + sku={ + "name": "Standard_LRS", + }, ) # Configure the storage account as a website. @@ -44,9 +44,9 @@ profile = azure_native.cdn.Profile( "profile", resource_group_name=resource_group.name, - sku=azure_native.cdn.SkuArgs( - name="Standard_Microsoft", - ), + sku={ + "name": "Standard_Microsoft", + }, ) # Pull the hostname out of the storage-account endpoint. @@ -73,10 +73,10 @@ ], origin_host_header=origin_hostname, origins=[ - azure_native.cdn.DeepCreatedOriginArgs( - name=account.name, - host_name=origin_hostname, - ) + { + "name": account.name, + "host_name": origin_hostname, + } ], ) diff --git a/static-website-gcp-python/__main__.py b/static-website-gcp-python/__main__.py index afc372451..52ba07601 100644 --- a/static-website-gcp-python/__main__.py +++ b/static-website-gcp-python/__main__.py @@ -12,10 +12,10 @@ bucket = gcp.storage.Bucket( "bucket", location="US", - website=gcp.storage.BucketWebsiteArgs( - main_page_suffix=index_document, - not_found_page=error_document, - ), + website={ + "main_page_suffix": index_document, + "not_found_page": error_document, + }, ) # Create an IAM binding to allow public read access to the bucket. diff --git a/vm-aws-python/__main__.py b/vm-aws-python/__main__.py index e9e276a11..2ae159e34 100644 --- a/vm-aws-python/__main__.py +++ b/vm-aws-python/__main__.py @@ -11,12 +11,16 @@ vpc_network_cidr = "10.0.0.0/16" # Look up the latest Amazon Linux 2 AMI. -ami = aws.ec2.get_ami(filters=[aws.ec2.GetAmiFilterArgs( - name="name", - values=["amzn2-ami-hvm-*"], - )], +ami = aws.ec2.get_ami( + filters=[ + { + "name": "name", + "values": ["amzn2-ami-hvm-*"], + } + ], owners=["amazon"], - most_recent=True).id + most_recent=True, +).id # User data to start a HTTP server in the EC2 instance user_data = """#!/bin/bash @@ -25,53 +29,65 @@ """ # Create VPC. -vpc = aws.ec2.Vpc("vpc", +vpc = aws.ec2.Vpc( + "vpc", cidr_block=vpc_network_cidr, enable_dns_hostnames=True, - enable_dns_support=True) + enable_dns_support=True, +) # Create an internet gateway. gateway = aws.ec2.InternetGateway("gateway", vpc_id=vpc.id) # Create a subnet that automatically assigns new instances a public IP address. -subnet = aws.ec2.Subnet("subnet", - vpc_id=vpc.id, - cidr_block="10.0.1.0/24", - map_public_ip_on_launch=True) +subnet = aws.ec2.Subnet( + "subnet", vpc_id=vpc.id, cidr_block="10.0.1.0/24", map_public_ip_on_launch=True +) # Create a route table. -route_table = aws.ec2.RouteTable("routeTable", +route_table = aws.ec2.RouteTable( + "routeTable", vpc_id=vpc.id, - routes=[aws.ec2.RouteTableRouteArgs( - cidr_block="0.0.0.0/0", - gateway_id=gateway.id, - )]) + routes=[ + { + "cidr_block": "0.0.0.0/0", + "gateway_id": gateway.id, + } + ], +) # Associate the route table with the public subnet. -route_table_association = aws.ec2.RouteTableAssociation("routeTableAssociation", - subnet_id=subnet.id, - route_table_id=route_table.id) +route_table_association = aws.ec2.RouteTableAssociation( + "routeTableAssociation", subnet_id=subnet.id, route_table_id=route_table.id +) # Create a security group allowing inbound access over port 80 and outbound # access to anywhere. -sec_group = aws.ec2.SecurityGroup("secGroup", +sec_group = aws.ec2.SecurityGroup( + "secGroup", description="Enable HTTP access", vpc_id=vpc.id, - ingress=[aws.ec2.SecurityGroupIngressArgs( - from_port=80, - to_port=80, - protocol="tcp", - cidr_blocks=["0.0.0.0/0"], - )], - egress=[aws.ec2.SecurityGroupEgressArgs( - from_port=0, - to_port=0, - protocol="-1", - cidr_blocks=["0.0.0.0/0"], - )]) + ingress=[ + { + "from_port": 80, + "to_port": 80, + "protocol": "tcp", + "cidr_blocks": ["0.0.0.0/0"], + } + ], + egress=[ + { + "from_port": 0, + "to_port": 0, + "protocol": "-1", + "cidr_blocks": ["0.0.0.0/0"], + } + ], +) # Create and launch an EC2 instance into the public subnet. -server = aws.ec2.Instance("server", +server = aws.ec2.Instance( + "server", instance_type=instance_type, subnet_id=subnet.id, vpc_security_group_ids=[sec_group.id], @@ -79,7 +95,8 @@ ami=ami, tags={ "Name": "webserver", - }) + }, +) # Export the instance's publicly accessible IP address and hostname. pulumi.export("ip", server.public_ip) diff --git a/vm-azure-python/__main__.py b/vm-azure-python/__main__.py index 9d92af9bc..0fb55948e 100644 --- a/vm-azure-python/__main__.py +++ b/vm-azure-python/__main__.py @@ -17,8 +17,8 @@ # Create an SSH key ssh_key = tls.PrivateKey( "ssh-key", - algorithm = "RSA", - rsa_bits = 4096, + algorithm="RSA", + rsa_bits=4096, ) # Create a resource group @@ -28,16 +28,16 @@ virtual_network = network.VirtualNetwork( "network", resource_group_name=resource_group.name, - address_space=network.AddressSpaceArgs( - address_prefixes=[ + address_space={ + "address_prefixes": [ "10.0.0.0/16", ], - ), + }, subnets=[ - network.SubnetArgs( - name=f"{vm_name}-subnet", - address_prefix="10.0.1.0/24", - ), + { + "name": f"{vm_name}-subnet", + "address_prefix": "10.0.1.0/24", + }, ], ) # Use a random string to give the VM a unique DNS name @@ -53,9 +53,9 @@ "public-ip", resource_group_name=resource_group.name, public_ip_allocation_method=network.IpAllocationMethod.DYNAMIC, - dns_settings=network.PublicIPAddressDnsSettingsArgs( - domain_name_label=domain_name_label, - ), + dns_settings={ + "domain_name_label": domain_name_label, + }, ) # Create a security group allowing inbound access over ports 80 (for HTTP) and 22 (for SSH) @@ -63,20 +63,20 @@ "security-group", resource_group_name=resource_group.name, security_rules=[ - network.SecurityRuleArgs( - name=f"{vm_name}-securityrule", - priority=1000, - direction=network.AccessRuleDirection.INBOUND, - access="Allow", - protocol="Tcp", - source_port_range="*", - source_address_prefix="*", - destination_address_prefix="*", - destination_port_ranges=[ + { + "name": f"{vm_name}-securityrule", + "priority": 1000, + "direction": network.AccessRuleDirection.INBOUND, + "access": "Allow", + "protocol": "Tcp", + "source_port_range": "*", + "source_address_prefix": "*", + "destination_address_prefix": "*", + "destination_port_ranges": [ service_port, "22", ], - ), + }, ], ) @@ -84,20 +84,20 @@ network_interface = network.NetworkInterface( "network-interface", resource_group_name=resource_group.name, - network_security_group=network.NetworkSecurityGroupArgs( - id=security_group.id, - ), + network_security_group={ + "id": security_group.id, + }, ip_configurations=[ - network.NetworkInterfaceIPConfigurationArgs( - name=f"{vm_name}-ipconfiguration", - private_ip_allocation_method=network.IpAllocationMethod.DYNAMIC, - subnet=network.SubnetArgs( - id=virtual_network.subnets.apply(lambda subnets: subnets[0].id), - ), - public_ip_address=network.PublicIPAddressArgs( - id=public_ip.id, - ), - ), + { + "name": f"{vm_name}-ipconfiguration", + "private_ip_allocation_method": network.IpAllocationMethod.DYNAMIC, + "subnet": { + "id": virtual_network.subnets.apply(lambda subnets: subnets[0].id), + }, + "public_ip_address": { + "id": public_ip.id, + }, + }, ], ) @@ -121,45 +121,45 @@ vm = compute.VirtualMachine( "vm", resource_group_name=resource_group.name, - network_profile=compute.NetworkProfileArgs( - network_interfaces=[ - compute.NetworkInterfaceReferenceArgs( - id=network_interface.id, - primary=True, - ) + network_profile={ + "network_interfaces": [ + { + "id": network_interface.id, + "primary": True, + } ] - ), - hardware_profile=compute.HardwareProfileArgs( - vm_size=vm_size, - ), - os_profile=compute.OSProfileArgs( - computer_name=vm_name, - admin_username=admin_username, - custom_data=base64.b64encode(bytes(init_script, "utf-8")).decode("utf-8"), - linux_configuration=compute.LinuxConfigurationArgs( - disable_password_authentication=True, - ssh=compute.SshConfigurationArgs( - public_keys=[ - compute.SshPublicKeyArgs( - key_data=ssh_key.public_key_openssh, - path=f"/home/{admin_username}/.ssh/authorized_keys", - ), + }, + hardware_profile={ + "vm_size": vm_size, + }, + os_profile={ + "computer_name": vm_name, + "admin_username": admin_username, + "custom_data": base64.b64encode(bytes(init_script, "utf-8")).decode("utf-8"), + "linux_configuration": { + "disable_password_authentication": True, + "ssh": { + "public_keys": [ + { + "key_data": ssh_key.public_key_openssh, + "path": f"/home/{admin_username}/.ssh/authorized_keys", + }, ], - ), - ), - ), - storage_profile=compute.StorageProfileArgs( - os_disk=compute.OSDiskArgs( - name=f"{vm_name}-osdisk", - create_option=compute.DiskCreateOption.FROM_IMAGE, - ), - image_reference=compute.ImageReferenceArgs( - publisher=os_image_publisher, - offer=os_image_offer, - sku=os_image_sku, - version=os_image_version, - ), - ), + }, + }, + }, + storage_profile={ + "os_disk": { + "name": f"{vm_name}-osdisk", + "create_option": compute.DiskCreateOption.FROM_IMAGE, + }, + "image_reference": { + "publisher": os_image_publisher, + "offer": os_image_offer, + "sku": os_image_sku, + "version": os_image_version, + }, + }, ) # Once the machine is created, fetch its IP address and DNS hostname @@ -171,16 +171,8 @@ ) # Export the VM's hostname, public IP address, HTTP URL, and SSH private key -pulumi.export( - "ip", - vm_address.ip_address -) -pulumi.export( - "hostname", - vm_address.dns_settings.apply( - lambda settings: settings.fqdn - ) -) +pulumi.export("ip", vm_address.ip_address) +pulumi.export("hostname", vm_address.dns_settings.apply(lambda settings: settings.fqdn)) pulumi.export( "url", vm_address.dns_settings.apply( diff --git a/webapp-kubernetes-python/__main__.py b/webapp-kubernetes-python/__main__.py index 60a10cd31..7136b51b2 100644 --- a/webapp-kubernetes-python/__main__.py +++ b/webapp-kubernetes-python/__main__.py @@ -12,17 +12,17 @@ # Create a namespace webserverns = kubernetes.core.v1.Namespace( "webserver", - metadata=kubernetes.meta.v1.ObjectMetaArgs( - name=k8sNamespace, - ) + metadata={ + "name": k8sNamespace, + }, ) # Create a ConfigMap for the Nginx configuration webserverconfig = kubernetes.core.v1.ConfigMap( "webserverconfig", - metadata=kubernetes.meta.v1.ObjectMetaArgs( - namespace=webserverns.metadata.name, - ), + metadata={ + "namespace": webserverns.metadata.name, + }, data={ "nginx.conf": """events { } http { @@ -37,64 +37,74 @@ } } """, - } + }, ) # Create a Deployment with a user-defined number of replicas webserverdeployment = kubernetes.apps.v1.Deployment( "webserverdeployment", - metadata=kubernetes.meta.v1.ObjectMetaArgs( - namespace=webserverns.metadata.name, - ), - spec=kubernetes.apps.v1.DeploymentSpecArgs( - selector=kubernetes.meta.v1.LabelSelectorArgs( - match_labels=app_labels, - ), - replicas=numReplicas, - template=kubernetes.core.v1.PodTemplateSpecArgs( - metadata=kubernetes.meta.v1.ObjectMetaArgs( - labels=app_labels, - ), - spec=kubernetes.core.v1.PodSpecArgs( - containers=[kubernetes.core.v1.ContainerArgs( - image="nginx", - name="nginx", - volume_mounts=[kubernetes.core.v1.VolumeMountArgs( - mount_path="/etc/nginx/nginx.conf", - name="nginx-conf-volume", - read_only=True, - sub_path="nginx.conf", - )], - )], - volumes=[kubernetes.core.v1.VolumeArgs( - config_map=kubernetes.core.v1.ConfigMapVolumeSourceArgs( - items=[kubernetes.core.v1.KeyToPathArgs( - key="nginx.conf", - path="nginx.conf", - )], - name=webserverconfig.metadata.name, - ), - name="nginx-conf-volume", - )], - ), - ), - ) + metadata={ + "namespace": webserverns.metadata.name, + }, + spec={ + "selector": { + "match_labels": app_labels, + }, + "replicas": numReplicas, + "template": { + "metadata": { + "labels": app_labels, + }, + "spec": { + "containers": [ + { + "image": "nginx", + "name": "nginx", + "volume_mounts": [ + { + "mount_path": "/etc/nginx/nginx.conf", + "name": "nginx-conf-volume", + "read_only": True, + "sub_path": "nginx.conf", + } + ], + } + ], + "volumes": [ + { + "config_map": { + "items": [ + { + "key": "nginx.conf", + "path": "nginx.conf", + } + ], + "name": webserverconfig.metadata.name, + }, + "name": "nginx-conf-volume", + } + ], + }, + }, + }, ) # Expose the Deployment as a Kubernetes Service webserverservice = kubernetes.core.v1.Service( "webserverservice", - metadata=kubernetes.meta.v1.ObjectMetaArgs( - namespace=webserverns.metadata.name, - ), - spec=kubernetes.core.v1.ServiceSpecArgs( - ports=[kubernetes.core.v1.ServicePortArgs( - port=80, - target_port=80, - protocol="TCP", - )], - selector=app_labels, - ) + metadata={ + "namespace": webserverns.metadata.name, + }, + spec={ + "ports": [ + { + "port": 80, + "target_port": 80, + "protocol": "TCP", + } + ], + "selector": app_labels, + }, ) # Export some values for use elsewhere From 5b8b332b471dcfcb30e8e2c07db60df66c670c22 Mon Sep 17 00:00:00 2001 From: "user.email" Date: Mon, 2 Sep 2024 13:48:17 +0200 Subject: [PATCH 2/2] Reduce test parallelism to help with disk space on macOS --- .github/workflows/test-templates.yml | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/.github/workflows/test-templates.yml b/.github/workflows/test-templates.yml index e5097a277..dcbff33c8 100644 --- a/.github/workflows/test-templates.yml +++ b/.github/workflows/test-templates.yml @@ -67,7 +67,8 @@ jobs: id-token: write steps: - - name: Free Disk Space (Ubuntu) + - if: contains(matrix.platform, 'ubuntu') + name: Free Disk Space (Ubuntu) uses: jlumbroso/free-disk-space@v1.3.1 with: tool-cache: false @@ -167,12 +168,21 @@ jobs: TESTPARALLELISM: 3 SKIPPED_TESTS: "alicloud,digitalocean,kubernetes,openstack,equinix-metal,civo,aiven,auth0,github,oci,java-jbang,java-gradle,azuredevops,container,vm-azure,fsharp,gcp-visualbasic,azure-classic-visualbasic" - - if: contains(matrix.platform, 'macOS') || contains(matrix.platform, 'ubuntu') - name: Run non-Windows tests + - if: contains(matrix.platform, 'ubuntu') + name: Run Linux tests run: | set -euo pipefail cd tests && go test -v -json -count=1 -cover -timeout 6h -parallel ${{ env.TESTPARALLELISM }} . 2>&1 | gotestfmt + - if: contains(matrix.platform, 'macOS') + name: Run macOS tests + run: | + set -euo pipefail + cd tests && go test -v -json -count=1 -cover -timeout 6h -parallel ${{ env.TESTPARALLELISM }} . 2>&1 | gotestfmt + env: + TESTPARALLELISM: 6 + + - if: 'failure()' name: Notify Slack uses: 8398a7/action-slack@v3