Adding Az Aci Up to the Extension (#9)
* Commit for ACI Up Code * Style Fixes * Style fix in resource file * Style Fix and Command Group Loading Fix * Argument Context Fix * Do Not Wait Fix * removing whitespaces * Fixing spaces in ResourceFiles * Fixes in up.apy for app name
This commit is contained in:
Родитель
e074fa92d2
Коммит
73e98bd577
|
@ -17,15 +17,19 @@ class DevCommandsLoader(AzCommandsLoader):
|
|||
def load_command_table(self, args):
|
||||
from azext_deploy_to_azure.dev.aks.commands import load_aks_commands
|
||||
from azext_deploy_to_azure.dev.functionapp.commands import load_functionapp_commands
|
||||
from azext_deploy_to_azure.dev.aci.commands import load_aci_commands
|
||||
load_aks_commands(self, args)
|
||||
load_functionapp_commands(self, args)
|
||||
load_aci_commands(self, args)
|
||||
return self.command_table
|
||||
|
||||
def load_arguments(self, command):
|
||||
from azext_deploy_to_azure.dev.aks.arguments import load_aks_arguments
|
||||
from azext_deploy_to_azure.dev.functionapp.arguments import load_functionapp_arguments
|
||||
from azext_deploy_to_azure.dev.aci.arguments import load_aci_arguments
|
||||
load_aks_arguments(self, command)
|
||||
load_functionapp_arguments(self, command)
|
||||
load_aci_arguments(self, command)
|
||||
|
||||
|
||||
COMMAND_LOADER_CLS = DevCommandsLoader
|
||||
|
|
|
@ -0,0 +1,10 @@
|
|||
# --------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
import pkg_resources
|
||||
from ._help import load_aci_help
|
||||
|
||||
pkg_resources.declare_namespace(__name__)
|
||||
|
||||
load_aci_help()
|
|
@ -0,0 +1,20 @@
|
|||
# --------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
from knack.help_files import helps
|
||||
|
||||
|
||||
def load_aci_help():
|
||||
helps['aci'] = """
|
||||
type: group
|
||||
short-summary: Commands to Manage Azure Container Instances App
|
||||
long-summary:
|
||||
"""
|
||||
|
||||
helps['aci up'] = """
|
||||
type: command
|
||||
short-summary: Deploy to Azure Container Instances using GitHub Actions
|
||||
long-summary:
|
||||
"""
|
|
@ -0,0 +1,9 @@
|
|||
# --------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
def load_aci_arguments(self, _):
|
||||
with self.argument_context('aci up') as c:
|
||||
c.argument('repository', options_list=['--repository'])
|
|
@ -0,0 +1,15 @@
|
|||
# --------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
from azure.cli.core.commands import CliCommandType
|
||||
|
||||
aciops = CliCommandType(
|
||||
operations_tmpl='azext_deploy_to_azure.dev.aci.up#{}'
|
||||
)
|
||||
|
||||
|
||||
def load_aci_commands(self, _):
|
||||
with self.command_group('aci', command_type=aciops) as g:
|
||||
g.command('up', 'aci_up')
|
|
@ -0,0 +1,153 @@
|
|||
# --------------------------------------------------------------------------------------------
|
||||
# Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
# Licensed under the MIT License. See License.txt in the project root for license information.
|
||||
# --------------------------------------------------------------------------------------------
|
||||
|
||||
from knack.util import CLIError
|
||||
from knack.log import get_logger
|
||||
|
||||
from azext_deploy_to_azure.dev.common.git import resolve_repository
|
||||
from azext_deploy_to_azure.dev.common.github_api_helper import (Files, get_work_flow_check_runID,
|
||||
push_files_to_repository,
|
||||
get_languages_for_repo,
|
||||
get_github_pat_token,
|
||||
get_default_branch,
|
||||
check_file_exists)
|
||||
from azext_deploy_to_azure.dev.common.github_workflow_helper import poll_workflow_status, get_new_workflow_yaml_name
|
||||
from azext_deploy_to_azure.dev.common.github_azure_secrets import get_azure_credentials
|
||||
from azext_deploy_to_azure.dev.common.const import (CHECKIN_MESSAGE_ACI, APP_NAME_PLACEHOLDER,
|
||||
ACR_PLACEHOLDER, RG_PLACEHOLDER, PORT_NUMBER_DEFAULT,
|
||||
PORT_NUMBER_PLACEHOLDER)
|
||||
from azext_deploy_to_azure.dev.aks.docker_helm_template import get_docker_templates
|
||||
|
||||
logger = get_logger(__name__)
|
||||
aci_token_prefix = "AciUpCLIExt_"
|
||||
|
||||
|
||||
# pylint: disable=too-many-statements
|
||||
def aci_up(acr=None, repository=None, port=None, branch_name=None,
|
||||
skip_secrets_generation=False, do_not_wait=False):
|
||||
"""Build and Deploy to Azure Container Instances using GitHub Actions
|
||||
:param acr: Name of the Azure Container Registry to be used for pushing the image
|
||||
:type acr: string
|
||||
:param repository: GitHub Repository URL e.g. https://github.com/contoso/webapp.
|
||||
:type repository: string
|
||||
:param port: Port on which your application runs. Default is 8080
|
||||
:type port: str
|
||||
:param branch_name: New Branch Name to be created to check in files and raise a PR
|
||||
:type branch_name: str
|
||||
:param skip_secrets_generation: Skip Generation of Azure Credentials
|
||||
:type skip_secrets_generation: bool
|
||||
:param do_not_wait: Do not wait for Workflow Completion
|
||||
:type do_not_wait: bool
|
||||
"""
|
||||
# TODO: Use the ACI Deploy Action when Published
|
||||
repo_name, repository = resolve_repository(repository)
|
||||
|
||||
get_github_pat_token(token_prefix=aci_token_prefix + repo_name, display_warning=True)
|
||||
logger.warning("Setting up your workflow")
|
||||
languages = get_languages_for_repo(repo_name)
|
||||
if not languages:
|
||||
raise CLIError("Language detection failed for this repository")
|
||||
|
||||
language = choose_supported_language(languages)
|
||||
if language:
|
||||
logger.warning('%s Repository Detected.', language)
|
||||
else:
|
||||
logger.debug('Languages detected: %s', languages)
|
||||
raise CLIError("The language in this repository are not yet supported from up command.")
|
||||
|
||||
from azext_deploy_to_azure.dev.common.azure_cli_resources import get_acr_details
|
||||
acr_details = get_acr_details(acr)
|
||||
logger.debug(acr_details)
|
||||
print('')
|
||||
|
||||
files = []
|
||||
if port is None:
|
||||
port = PORT_NUMBER_DEFAULT
|
||||
if 'Dockerfile' not in languages.keys():
|
||||
# check in Dockerfile and Dockerignore
|
||||
docker_files = get_docker_templates(language, port)
|
||||
if docker_files:
|
||||
files = files + docker_files
|
||||
else:
|
||||
logger.warning('Using the Dockerfile found in repository %s', repo_name)
|
||||
|
||||
# create Azure Service Principal and display JSON on the screen for the user to configure it as GitHub Secrets
|
||||
if not skip_secrets_generation:
|
||||
get_azure_credentials()
|
||||
|
||||
print('')
|
||||
workflow_files = get_yaml_template_for_repo(acr_details, repo_name, port)
|
||||
if workflow_files:
|
||||
files = files + workflow_files
|
||||
|
||||
# File checkin
|
||||
for file_name in files:
|
||||
logger.debug("Checkin file path: %s", file_name.path)
|
||||
logger.debug("Checkin file content: %s", file_name.content)
|
||||
|
||||
default_branch = get_default_branch(repo_name)
|
||||
workflow_commit_sha = push_files_to_repository(
|
||||
repo_name=repo_name, default_branch=default_branch, files=files,
|
||||
branch_name=branch_name, message=CHECKIN_MESSAGE_ACI
|
||||
)
|
||||
if workflow_commit_sha:
|
||||
print('Creating workflow...')
|
||||
check_run_id = get_work_flow_check_runID(repo_name, workflow_commit_sha)
|
||||
workflow_url = 'https://github.com/{repo_id}/runs/{checkID}'.format(repo_id=repo_name,
|
||||
checkID=check_run_id)
|
||||
print('GitHub Action Workflow has been created - {}'.format(workflow_url))
|
||||
|
||||
if not do_not_wait:
|
||||
poll_workflow_status(repo_name, check_run_id)
|
||||
list_name = repo_name.split("/")
|
||||
app_name = list_name[1].lower()
|
||||
app_url = get_app_url(acr_details, app_name)
|
||||
app_url_with_port = app_url + ":" + port + "/"
|
||||
print('Your app is deployed at: ', app_url_with_port)
|
||||
|
||||
|
||||
def choose_supported_language(languages):
|
||||
# check if one of top three languages are supported or not
|
||||
list_languages = list(languages.keys())
|
||||
first_language = list_languages[0]
|
||||
if first_language in ('JavaScript', 'Java', 'Python'):
|
||||
return first_language
|
||||
if len(list_languages) >= 1 and list_languages[1] in ('JavaScript', 'Java', 'Python'):
|
||||
return list_languages[1]
|
||||
if len(list_languages) >= 2 and list_languages[2] in ('JavaScript', 'Java', 'Python'):
|
||||
return list_languages[2]
|
||||
return None
|
||||
|
||||
|
||||
def get_yaml_template_for_repo(acr_details, repo_name, port):
|
||||
files_to_return = []
|
||||
github_workflow_path = '.github/workflows/'
|
||||
yaml_file_name = 'main.yml'
|
||||
workflow_yaml = github_workflow_path + yaml_file_name
|
||||
list_name = repo_name.split("/")
|
||||
app_name = list_name[1].lower()
|
||||
if check_file_exists(repo_name, workflow_yaml):
|
||||
yaml_file_name = get_new_workflow_yaml_name()
|
||||
workflow_yaml = github_workflow_path + yaml_file_name
|
||||
from azext_deploy_to_azure.dev.resources.resourcefiles import DEPLOY_TO_ACI_TEMPLATE
|
||||
files_to_return.append(Files(path=workflow_yaml,
|
||||
content=DEPLOY_TO_ACI_TEMPLATE
|
||||
.replace(APP_NAME_PLACEHOLDER, app_name)
|
||||
.replace(ACR_PLACEHOLDER, acr_details['name'])
|
||||
.replace(RG_PLACEHOLDER, acr_details['resourceGroup'])
|
||||
.replace(PORT_NUMBER_PLACEHOLDER, port)))
|
||||
return files_to_return
|
||||
|
||||
|
||||
def get_app_url(acr_details, app_name):
|
||||
import subprocess as sb
|
||||
resource_group = acr_details['resourceGroup']
|
||||
url_find_command = 'az container show \
|
||||
--name {app_name} --resource-group {resource_group_name} \
|
||||
--query ipAddress.fqdn'.format(app_name=app_name, resource_group_name=resource_group)
|
||||
url_result = sb.check_output(url_find_command, shell=True)
|
||||
url_result = url_result.decode().strip().lstrip('\"').rstrip('\"')
|
||||
app_url = "http://" + url_result
|
||||
return app_url
|
|
@ -17,6 +17,7 @@ RELEASE_NAME = 'aksappupdemo'
|
|||
# Checkin message strings
|
||||
|
||||
CHECKIN_MESSAGE_AKS = 'Setting up AKS deployment workflow'
|
||||
CHECKIN_MESSAGE_ACI = 'Setting up ACI deployment workflow'
|
||||
CHECKIN_MESSAGE_FUNCTIONAPP = 'Setting up Functionapp deployment workflow'
|
||||
|
||||
RELEASE_PLACEHOLDER = 'release_name_place_holder'
|
||||
|
|
|
@ -108,3 +108,37 @@ jobs:
|
|||
# For more information on GitHub Actions:
|
||||
# https://help.github.com/en/categories/automating-your-workflow-with-github-actions
|
||||
"""
|
||||
|
||||
DEPLOY_TO_ACI_TEMPLATE = """name: CI
|
||||
on: [push, pull_request]
|
||||
|
||||
jobs:
|
||||
build-and-deploy:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout GitHub Action'
|
||||
uses: actions/checkout@master
|
||||
|
||||
- name: 'Login via Azure CLI'
|
||||
uses: Azure/docker-login@v1
|
||||
with:
|
||||
login-server: container_registry_name_place_holder.azurecr.io
|
||||
username: ${{ SECRETS.REGISTRY_USERNAME }}
|
||||
password: ${{ SECRETS.REGISTRY_PASSWORD }}
|
||||
|
||||
- run: |
|
||||
docker build . -t container_registry_name_place_holder.azurecr.io/app_name_place_holder:${{ github.sha }}
|
||||
docker push container_registry_name_place_holder.azurecr.io/app_name_place_holder:${{ github.sha }}
|
||||
|
||||
- name: 'Azure Login'
|
||||
uses: azure/login@v1
|
||||
with:
|
||||
creds: ${{ SECRETS.AZURE_CREDENTIALS }}
|
||||
|
||||
- name: 'Deploy to Azure Container Instances'
|
||||
uses: azure/CLI@v1
|
||||
with:
|
||||
azcliversion: 2.0.77
|
||||
inlineScript: |
|
||||
az container create --resource-group resource_name_place_holder --name app_name_place_holder --image container_registry_name_place_holder.azurecr.io/app_name_place_holder:${{ github.sha }} --ports 80 port_number_place_holder --dns-name-label app_name_place_holder --registry-username ${{ SECRETS.REGISTRY_USERNAME }} --registry-password ${{ SECRETS.REGISTRY_PASSWORD }}
|
||||
"""
|
||||
|
|
Загрузка…
Ссылка в новой задаче