зеркало из https://github.com/microsoft/CCF.git
Create minimal pipeilne for SNP which is stable (#4652)
This commit is contained in:
Родитель
d0ccf76da1
Коммит
889790064d
|
@ -8,7 +8,7 @@ jobs:
|
|||
clean: true
|
||||
- script: |
|
||||
echo "Determine if any code has changed."
|
||||
if git diff --ignore-submodules=dirty --quiet origin/${SYSTEM_PULLREQUEST_TARGETBRANCH:-origin/main} -- ':!doc' ':!*.md' ':!tla'; then
|
||||
if git diff --ignore-submodules=dirty --quiet origin/${SYSTEM_PULLREQUEST_TARGETBRANCH:-origin/main} -- ':!doc' ':!*.md' ':!tla' ':!scripts/azure_deployment'; then
|
||||
echo " - Documentation change only"
|
||||
echo "##vso[task.setvariable variable=docOnly;isOutput=true]true" #set variable docOnly to true
|
||||
else
|
||||
|
|
|
@ -0,0 +1,73 @@
|
|||
pr:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
paths:
|
||||
include:
|
||||
- .azure_pipelines_snp.yml
|
||||
- .snpcc_canary
|
||||
|
||||
trigger:
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
- "release/*"
|
||||
exclude:
|
||||
- "release/1.x"
|
||||
- "release/2.x"
|
||||
|
||||
schedules:
|
||||
- cron: "0 9-18/3 * * Mon-Fri"
|
||||
displayName: Regular build
|
||||
branches:
|
||||
include:
|
||||
- main
|
||||
always: true
|
||||
|
||||
jobs:
|
||||
- template: .azure-pipelines-templates/configure.yml
|
||||
|
||||
- job: deploy_aci
|
||||
displayName: "Deploy ACI"
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
steps:
|
||||
- script: |
|
||||
echo -e "\nInstalling Azure CLI..."
|
||||
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||
az login --service-principal -u $(CCF_SNP_CI_APP_ID) -p $(CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD) --tenant $(CCF_SNP_CI_TENANT)
|
||||
pip install azure-mgmt-resource azure-identity azure-mgmt-containerinstance
|
||||
echo -e "\nInstalled Azure CLI and logged in"
|
||||
echo -e "\nDeploying Azure Container Instance/s..."
|
||||
python3.8 scripts/azure_deployment/arm_template.py deploy aci --subscription-id $(CCF_AZURE_SUBSCRIPTION_ID) --resource-group ccf-aci --aci-type dynamic-agent --deployment-name ci-$(Build.BuildNumber) > ~/aci_ips
|
||||
echo "##vso[task.setvariable variable=aciIp;isOutput=true]`cat ~/aci_ips`"
|
||||
echo -e "\nDone"
|
||||
echo -e `cat ~/aci_ips`
|
||||
env:
|
||||
CCF_SNP_CI_APP_ID: $(CCF_SNP_CI_APP_ID)
|
||||
CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD: $(CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD)
|
||||
CCF_SNP_CI_TENANT: $(CCF_SNP_CI_TENANT)
|
||||
CCF_AZURE_SUBSCRIPTION_ID: $(CCF_AZURE_SUBSCRIPTION_ID)
|
||||
name: deploy
|
||||
|
||||
- job: cleanup_aci
|
||||
displayName: "Cleanup ACI"
|
||||
pool:
|
||||
vmImage: ubuntu-20.04
|
||||
dependsOn: SNPCC_Debug
|
||||
condition: always()
|
||||
steps:
|
||||
- script: |
|
||||
echo -e "\Installing Azure CLI..."
|
||||
curl -sL https://aka.ms/InstallAzureCLIDeb | sudo bash
|
||||
az login --service-principal -u $(CCF_SNP_CI_APP_ID) -p $(CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD) --tenant $(CCF_SNP_CI_TENANT)
|
||||
pip install azure-mgmt-resource azure-identity azure-mgmt-containerinstance
|
||||
echo -e "\nInstalled Azure CLI and logged in"
|
||||
echo -e "\nRemoving Azure Container Instance/s..."
|
||||
python3.8 scripts/azure_deployment/arm_template.py remove aci --subscription-id $(CCF_AZURE_SUBSCRIPTION_ID) --resource-group ccf-aci --aci-type dynamic-agent --deployment-name ci-$(Build.BuildNumber)
|
||||
echo -e "\nDone"
|
||||
env:
|
||||
CCF_SNP_CI_APP_ID: $(CCF_SNP_CI_APP_ID)
|
||||
CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD: $(CCF_SNP_CI_SERVICE_PRINCIPAL_PASSWORD)
|
||||
CCF_SNP_CI_TENANT: $(CCF_SNP_CI_TENANT)
|
||||
CCF_AZURE_SUBSCRIPTION_ID: $(CCF_AZURE_SUBSCRIPTION_ID)
|
|
@ -0,0 +1,186 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the Apache 2.0 License.
|
||||
|
||||
import os
|
||||
from argparse import ArgumentParser, Namespace
|
||||
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from azure.mgmt.resource.resources.models import (
|
||||
Deployment,
|
||||
DeploymentProperties,
|
||||
DeploymentMode,
|
||||
)
|
||||
from azure.mgmt.containerinstance import ContainerInstanceManagementClient
|
||||
|
||||
|
||||
def get_pubkey():
|
||||
pubkey_path = os.path.expanduser("~/.ssh/id_rsa.pub")
|
||||
return (
|
||||
open(pubkey_path, "r").read().replace("\n", "")
|
||||
if os.path.exists(pubkey_path)
|
||||
else ""
|
||||
)
|
||||
|
||||
|
||||
STARTUP_COMMANDS = {
|
||||
"dynamic-agent": lambda args, i: [
|
||||
"apt-get update",
|
||||
"apt-get install -y openssh-server rsync",
|
||||
"sed -i 's/PubkeyAuthentication no/PubkeyAuthentication yes/g' /etc/ssh/sshd_config",
|
||||
"sed -i 's/PasswordAuthentication yes/PasswordAuthentication no/g' /etc/ssh/sshd_config",
|
||||
"useradd -m agent",
|
||||
'echo "agent ALL=(ALL) NOPASSWD: ALL" >> /etc/sudoers',
|
||||
"service ssh restart",
|
||||
"mkdir /home/agent/.ssh",
|
||||
*[
|
||||
f"echo {ssh_key} >> /home/agent/.ssh/authorized_keys"
|
||||
for ssh_key in [get_pubkey(), *args.aci_ssh_keys]
|
||||
if ssh_key
|
||||
],
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
def make_aci_deployment(parser: ArgumentParser) -> Deployment:
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-image",
|
||||
help="The name of the image to deploy in the ACI",
|
||||
type=str,
|
||||
default="ccfmsrc.azurecr.io/ccf/ci:oe-0.18.4-snp",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-type",
|
||||
help="The type of ACI to deploy",
|
||||
type=str,
|
||||
choices=STARTUP_COMMANDS.keys(),
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-pat",
|
||||
help="The PAT to deploy an ACI with",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-ms-user",
|
||||
help="The Microsoft User",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-github-user",
|
||||
help="The Github User who owns a CCF clone to checkout",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-github-name",
|
||||
help="The name to commit with",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--aci-ssh-keys",
|
||||
help="The ssh keys to add to the dev box",
|
||||
default="",
|
||||
type=lambda comma_sep_str: comma_sep_str.split(","),
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
return Deployment(
|
||||
properties=DeploymentProperties(
|
||||
mode=DeploymentMode.INCREMENTAL,
|
||||
parameters={},
|
||||
template={
|
||||
"$schema": "https://schema.management.azure.com/schemas/2019-04-01/deploymentTemplate.json#",
|
||||
"contentVersion": "1.0.0.0",
|
||||
"parameters": {},
|
||||
"variables": {},
|
||||
"resources": [
|
||||
{
|
||||
"type": "Microsoft.ContainerInstance/containerGroups",
|
||||
"apiVersion": "2022-04-01-preview",
|
||||
"name": f"{args.deployment_name}-{i}",
|
||||
"location": "westeurope",
|
||||
"properties": {
|
||||
"sku": "Standard",
|
||||
"confidentialComputeProperties": {
|
||||
"isolationType": "SevSnp",
|
||||
"ccePolicy": "eyJhbGxvd19hbGwiOnRydWUsImNvbnRhaW5lcnMiOnsibGVuZ3RoIjowLCJlbGVtZW50cyI6bnVsbH19",
|
||||
},
|
||||
"containers": [
|
||||
{
|
||||
"name": f"{args.deployment_name}-{i}",
|
||||
"properties": {
|
||||
"image": args.aci_image,
|
||||
"command": [
|
||||
"/bin/sh",
|
||||
"-c",
|
||||
" && ".join(
|
||||
[
|
||||
*STARTUP_COMMANDS[args.aci_type](
|
||||
args,
|
||||
i,
|
||||
),
|
||||
"tail -f /dev/null",
|
||||
]
|
||||
),
|
||||
],
|
||||
"ports": [
|
||||
{"protocol": "TCP", "port": 8000},
|
||||
{"protocol": "TCP", "port": 22},
|
||||
],
|
||||
"environmentVariables": [],
|
||||
"resources": {
|
||||
"requests": {"memoryInGB": 16, "cpu": 4}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"initContainers": [],
|
||||
"restartPolicy": "Never",
|
||||
"ipAddress": {
|
||||
"ports": [
|
||||
{"protocol": "TCP", "port": 8000},
|
||||
{"protocol": "TCP", "port": 22},
|
||||
],
|
||||
"type": "Public",
|
||||
},
|
||||
"osType": "Linux",
|
||||
},
|
||||
}
|
||||
for i in range(args.count)
|
||||
],
|
||||
},
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def remove_aci_deployment(args: Namespace, deployment: Deployment):
|
||||
|
||||
container_client = ContainerInstanceManagementClient(
|
||||
DefaultAzureCredential(), args.subscription_id
|
||||
)
|
||||
|
||||
for resource in deployment.properties.output_resources:
|
||||
container_name = resource.id.split("/")[-1]
|
||||
container_client.container_groups.begin_delete(
|
||||
args.resource_group, container_name
|
||||
).wait()
|
||||
|
||||
|
||||
def check_aci_deployment(args: Namespace, deployment: Deployment) -> str:
|
||||
|
||||
container_client = ContainerInstanceManagementClient(
|
||||
DefaultAzureCredential(), args.subscription_id
|
||||
)
|
||||
|
||||
for resource in deployment.properties.output_resources:
|
||||
container_name = resource.id.split("/")[-1]
|
||||
container_group = container_client.container_groups.get(
|
||||
args.resource_group, container_name
|
||||
)
|
||||
print(container_group.ip_address.ip)
|
|
@ -0,0 +1,120 @@
|
|||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the Apache 2.0 License.
|
||||
|
||||
import argparse
|
||||
from azure.identity import DefaultAzureCredential
|
||||
from azure.mgmt.resource import ResourceManagementClient
|
||||
from arm_aci import (
|
||||
check_aci_deployment,
|
||||
make_aci_deployment,
|
||||
remove_aci_deployment,
|
||||
)
|
||||
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Python interface for Azure ARM deployments",
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"operation",
|
||||
help="Whether to deploy or remove template",
|
||||
type=str,
|
||||
choices=["deploy", "remove", "check"],
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"deployment_type",
|
||||
help="The type of Azure deployment to deploy",
|
||||
type=str,
|
||||
choices=[
|
||||
"aci",
|
||||
],
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--count",
|
||||
help="The number of deployments",
|
||||
type=int,
|
||||
default=1,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--subscription-id",
|
||||
help="The subscription ID used to deploy",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--resource-group",
|
||||
help="The resource group used to deploy",
|
||||
default="ccf-aci",
|
||||
type=str,
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"--deployment-name",
|
||||
help="The name of the Azure deployment, used for agent names and cleanup",
|
||||
type=lambda in_str: str(in_str).replace(".", ""),
|
||||
)
|
||||
|
||||
args, unknown_args = parser.parse_known_args()
|
||||
|
||||
resource_client = ResourceManagementClient(
|
||||
DefaultAzureCredential(), args.subscription_id
|
||||
)
|
||||
|
||||
deployment_type_to_funcs = {
|
||||
"aci": (make_aci_deployment, check_aci_deployment, remove_aci_deployment),
|
||||
}
|
||||
|
||||
|
||||
def deploy(make_template, print_status) -> str:
|
||||
|
||||
try:
|
||||
resource_client.deployments.begin_create_or_update(
|
||||
args.resource_group,
|
||||
args.deployment_name,
|
||||
make_template(parser),
|
||||
).wait()
|
||||
print_status(
|
||||
args,
|
||||
resource_client.deployments.get(
|
||||
args.resource_group,
|
||||
args.deployment_name,
|
||||
),
|
||||
)
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
def remove(args, remove_deployment_items):
|
||||
|
||||
try:
|
||||
remove_deployment_items(
|
||||
args,
|
||||
resource_client.deployments.get(
|
||||
args.resource_group,
|
||||
args.deployment_name,
|
||||
),
|
||||
)
|
||||
resource_client.deployments.begin_delete(
|
||||
args.resource_group,
|
||||
args.deployment_name,
|
||||
).wait()
|
||||
except Exception as e:
|
||||
print(e)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
|
||||
if args.operation == "deploy":
|
||||
deploy(*deployment_type_to_funcs[args.deployment_type][:2])
|
||||
elif args.operation == "check":
|
||||
deployment_type_to_funcs[args.deployment_type][1](
|
||||
args,
|
||||
resource_client.deployments.get(
|
||||
args.resource_group,
|
||||
args.deployment_name,
|
||||
),
|
||||
)
|
||||
elif args.operation == "remove":
|
||||
remove(args, deployment_type_to_funcs[args.deployment_type][2])
|
Загрузка…
Ссылка в новой задаче