Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Karenchen/enable draftv2 #4651

Merged
merged 78 commits into from
May 23, 2022
Merged
Show file tree
Hide file tree
Changes from 44 commits
Commits
Show all changes
78 commits
Select commit Hold shift + click to select a range
547441e
starting point
Mar 21, 2022
4aacf22
command makes call correctly. Need to reach out to DraftV2
Mar 22, 2022
6cd1e00
attempting to download binaries, but headers may be blocking
Mar 22, 2022
48ec4bc
Downloading binary, but it's not located in the correct path
Mar 24, 2022
a15212e
download into the correct directory works. Need to check existence of…
Mar 25, 2022
1eceebf
adding check to ensure download is correct for users os
Mar 25, 2022
6f775df
download and run binary
Mar 28, 2022
577a65a
fixing msg
Mar 29, 2022
cac9fc8
adding copywrite comment
Mar 30, 2022
275ea32
addressng PR comments, function naming conventions, etc.
Mar 30, 2022
29db02f
fixing copywrite typo
Mar 30, 2022
8b05aa4
The linter seems to be complaining about the List type hints. Resolvi…
Mar 31, 2022
6e9614c
fixing whitespace. The linter does not seem to like type annotations …
Mar 31, 2022
525652a
adding missing whitespaces after ,
Mar 31, 2022
c617cef
adding space before operatiors for linter
Mar 31, 2022
b6d5e0f
changing type hint import
Apr 1, 2022
b9e52b5
more whitespace
Apr 1, 2022
8a643e8
adding empty line
Apr 1, 2022
3d103b2
removing whitespace from blank linke
Apr 1, 2022
e7e9c93
adding disable too many lines
Apr 1, 2022
0ef773c
delting draftv2 dir
Apr 1, 2022
a52fedb
setup new branch
karenychen Apr 7, 2022
8cc6b05
refactoring
karenychen Apr 7, 2022
6ebaf5e
linked draftv2 create
karenychen Apr 7, 2022
448188f
clean up
karenychen Apr 7, 2022
c911b77
rediected stdout and stderr
karenychen Apr 7, 2022
f68643b
fixing style checks
karenychen Apr 7, 2022
1b872cf
resolved comments
karenychen Apr 9, 2022
61bdabf
resolved comments
karenychen Apr 9, 2022
e6ea3d0
fixed extra imports
karenychen Apr 9, 2022
daac6fc
added help menu
karenychen Apr 10, 2022
fd314e5
small fix
karenychen Apr 10, 2022
df31dbf
style fixes
karenychen Apr 10, 2022
2725913
Merge branch 'main' into karenchen/enable-draftv2
karenychen Apr 13, 2022
85fb982
fixes and added version check
karenychen Apr 13, 2022
cc16119
Merge branch 'karenchen/enable-draftv2' of github.com:karenychen/azur…
karenychen Apr 13, 2022
90e216b
quick revert
karenychen Apr 13, 2022
84e693a
quick revert
karenychen Apr 13, 2022
6433574
some refractoring
karenychen Apr 13, 2022
76644f3
renaming functions
karenychen Apr 13, 2022
a3eab7e
further refractor
karenychen Apr 13, 2022
3091bdc
quick fixes
karenychen Apr 13, 2022
dd5f2b7
more fixes
karenychen Apr 13, 2022
9738354
clean up import statements
karenychen Apr 13, 2022
d2febd1
change to use logging
karenychen Apr 18, 2022
dca6a1c
name change
karenychen Apr 18, 2022
fe44121
more renaming
karenychen Apr 18, 2022
bd06547
refractoring
karenychen Apr 18, 2022
c458df9
refractoring
karenychen Apr 18, 2022
93f3156
refractoring
karenychen Apr 18, 2022
d51b743
refractoring
karenychen Apr 18, 2022
bd4a8ef
quick fix
karenychen Apr 18, 2022
ce33eca
quick fix
karenychen Apr 19, 2022
5c355d9
remove debug msg
karenychen Apr 19, 2022
6f40dc2
fix version
karenychen Apr 19, 2022
1836550
Karenchen/enable-app-up-draftv2 (#1)
karenychen May 20, 2022
c6db3c1
Merge branch 'main' into karenchen/enable-draftv2
karenychen May 20, 2022
c40d9b1
retrigger checks
karenychen May 20, 2022
4247f00
Merge branch 'karenchen/enable-draftv2' of github.com:karenychen/azur…
karenychen May 20, 2022
c2e869a
added help and fixed tests
karenychen May 20, 2022
b97861c
changing tests
karenychen May 21, 2022
f8355d0
styling
karenychen May 21, 2022
86ad0ac
added auto download for draft binary
karenychen May 21, 2022
9807f52
small fixes
karenychen May 21, 2022
f7d6676
download logic fix
karenychen May 23, 2022
11baae4
fixing things
karenychen May 23, 2022
4ae096f
fixing tests
karenychen May 23, 2022
c80cda3
fixing tests
karenychen May 23, 2022
74fbf95
fixing recordings
karenychen May 23, 2022
eadc8ea
added examples in help menu
karenychen May 23, 2022
efe8c73
added help menu
karenychen May 23, 2022
0532e51
changing tests to live only
karenychen May 23, 2022
472e2af
fixing concurency tests
karenychen May 23, 2022
de30662
fixes mkdir issue
karenychen May 23, 2022
ecd10df
fixes mkdir issue
karenychen May 23, 2022
5abea0c
fixes mkdir issue
karenychen May 23, 2022
3e5a089
fixes mkdir issue
karenychen May 23, 2022
a6653e8
fixes download location
karenychen May 23, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions src/aks-preview/azext_aks_preview/_help.py
Original file line number Diff line number Diff line change
Expand Up @@ -1628,3 +1628,27 @@
type: command
short-summary: Delete a nodepool snapshot.
"""

helps['aks app init'] = """
type: command
short-summary: Generate a Dockerfile and the minimum required Kubernetes deployment files (helm, kustomize, manifests) for your project directory.
parameters:
- name: --destination
type: string
short-summary: Specify the path to the project directory.
- name: --app-name
type: string
short-summary: Specify the name of the helm release.
- name: --language
type: string
short-summary: Specify the language used to create the Kubernetes deployment.
- name: --create-config
type: string
short-summary: Specify the path to the configuration file.
- name: --dockerfile-only
type: string
short-summary: Only generate Dockerfile for the Kubernetes deployment.
- name: --deployment-only
type: string
short-summary: Only generate deployment files (helm, kustomize, manifests) for the Kubernetes deployment.
"""
205 changes: 205 additions & 0 deletions src/aks-preview/azext_aks_preview/aks_app_commands/aksappcommands.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,205 @@
# pylint: disable=too-many-lines
# --------------------------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# --------------------------------------------------------------------------------------------

import json
from typing import Dict, List, Optional
import subprocess
import requests
import os
import platform
from pathlib import Path
from knack.prompting import prompt_y_n


# `az aks app init` function
def aks_draft_app_init(destination: str,
app_name: str,
language: str,
create_config: str,
dockerfile_only: str,
deployment_only: str) -> None:
file_path = _binary_pre_check()
if not file_path:
raise ValueError('Binary check was NOT executed successfully')

arguments = _build_init_arguments(destination, app_name, language, create_config, dockerfile_only, deployment_only)
run_successful = _run_init(file_path, arguments)
if run_successful:
karenychen marked this conversation as resolved.
Show resolved Hide resolved
_init_finish()
else:
raise ValueError('`az aks app init` was NOT executed successfully')


# Returns the path to Draft binary. None if missing the required binary
def _binary_pre_check() -> Optional[str]:
print('The Draft setup is in progress...')
draft_binary_path = _get_existing_path()

if draft_binary_path: # found binary
if _is_latest_version(draft_binary_path): # no need to update
print('Your local version of Draft is up to date.')
else: # prompt the user to update
msg = 'We have detected a newer version of Draft. Would you like to download it?'
response = prompt_y_n(msg, default='n')
if response:
return _download_binary()
return draft_binary_path
else: # prompt the user to download binary
# If users says no, we error out and tell them that this requires the binary
msg = 'The required binary was not found. Would you like us to download the required binary for you?'

if not prompt_y_n(msg, default='n'):
raise ValueError('`az aks app` requires the missing dependency')

return _download_binary()


# Returns the latest version str of Draft on Github
def _get_latest_version() -> str:
response = requests.get('https://api.github.com/repos/Azure/aks-app/releases/latest')
response_json = json.loads(response.text)
return response_json.get('tag_name')


# Returns True if the local binary is the latest version, False otherwise
def _is_latest_version(binary_path: str) -> bool:
latest_version = _get_latest_version()
process = subprocess.Popen([binary_path, 'version'], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = process.communicate()
if stderr.decode():
return False
# return string of result is "version: v0.0.x"
current_version = stdout.decode().strip().split()[-1]
return latest_version == current_version


# Returns the filename for the current os and architecture
# Returns None if the current system is not supported in Draft
def _get_filename() -> Optional[str]:
operating_system = platform.system().lower()
architecture = platform.machine().lower()

if architecture == 'x86_64':
architecture = 'amd64'
if architecture not in ['arm64', 'amd64']:
print('Cannot find a suitable download for the current system architecture. Draft only supports AMD64 and ARM64.')
return None

return f'draftv2-{operating_system}-{architecture}'


# Returns path to existing draft binary, None otherwise
def _get_existing_path() -> Optional[str]:
print('Checking if Draft binary exists locally...')

filename = _get_filename()
if not filename:
return None

paths = _get_potential_paths()
if not paths:
print('List of potential Draft paths is empty')
return None

for path in paths:
binary_file_path = path + '/' + filename
if os.path.exists(binary_file_path):
print('Existing binary found at: ' + binary_file_path)
return binary_file_path
return None


# Returns a list of potential draftV2 binary paths
def _get_potential_paths() -> List[str]:
paths = os.environ['PATH'].split(':')
karenychen marked this conversation as resolved.
Show resolved Hide resolved
# the download location of _download_binary()
default_dir = str(Path.home()) + '/' + '.aksapp'
paths.append(default_dir)

return paths


# Downloads the latest binary to ~/.aksapp
# Returns path to the binary if sucessful, None otherwise
def _download_binary() -> Optional[str]:
print('Attempting to download dependency...')

filename = _get_filename()
if not filename:
return None

url = f'https://github.com/Azure/aks-app/releases/latest/download/{filename}'
karenychen marked this conversation as resolved.
Show resolved Hide resolved
headers = {'Accept': 'application/octet-stream'}

dir_name = '.aksapp'
# Downloading the file by sending the request to the URL
response = requests.get(url, headers=headers)
binary_path = str(Path.home()) + '/' + dir_name

# Directory
if os.path.exists(binary_path) is False:
os.chdir(str(Path.home()))
os.mkdir(dir_name)
print(f'Directory {dir_name} was created inside of your HOME directory')

if response.ok:
# Split URL to get the file name 'draftv2-darwin-amd64'
os.chdir(binary_path)
# Writing the file to the local file system
with open(filename, 'wb') as output_file:
output_file.write(response.content)
print('Download of Draft binary was successful with a status code: ' + str(response.status_code))
os.chmod(binary_path + '/' + filename, 0o755)
return binary_path + '/' + filename

print('Download of Draft binary was unsuccessful with a status code: ' + str(response.status_code))
return None


# Returns a list of arguments following the format `--arg=value`
def _build_args(options: Dict[str, str]) -> List[str]:
args_list = []
for arg, val in options.items():
if val:
args_list.append(f'--{arg}={val}')
return args_list


# Returns a list of arguments for `az aks app init`
def _build_init_arguments(destination: str,
app_name: str,
language: str,
create_config: str,
dockerfile_only: str,
deployment_only: str) -> List[str]:
options = {
'destination': destination,
'app-name': app_name,
'language': language,
'create-config': create_config,
'dockerfile-only': dockerfile_only,
'deployment-only': deployment_only
}
return _build_args(options)


# Executes the `draft create` command
# Returns True if the process executed sucessfully, False otherwise
def _run_init(binary_path: str, arguments: List[str]) -> bool:
if binary_path is None:
raise ValueError('The given Binary path was null or empty')

print('Running Draft Binary ...')
cmd = [binary_path, 'create'] + arguments
process = subprocess.Popen(cmd)
exit_code = process.wait()
return exit_code == 0


# Function for clean up logic
def _init_finish():
# Clean up logic can go here if needed
print('Finishing running `az aks app init`')
5 changes: 5 additions & 0 deletions src/aks-preview/azext_aks_preview/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,11 @@ def load_command_table(self, _):
g.custom_command('stop', 'aks_agentpool_stop', supports_no_wait=True)
g.custom_command('start', 'aks_agentpool_start', supports_no_wait=True)

# AKS App commands
with self.command_group('aks app', managed_clusters_sdk, client_factory=cf_managed_clusters) as g:
g.custom_command('init', 'aks_app_init')
# g.custom_command('up', 'aks_app_up')

# AKS pod identity commands
with self.command_group('aks pod-identity', managed_clusters_sdk, client_factory=cf_managed_clusters) as g:
g.custom_command('add', 'aks_pod_identity_add')
Expand Down
13 changes: 13 additions & 0 deletions src/aks-preview/azext_aks_preview/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -149,6 +149,10 @@
UserAssignedIdentity,
)

from .aks_app_commands.aksappcommands import (
aks_draft_app_init
)

logger = get_logger(__name__)


Expand Down Expand Up @@ -2813,6 +2817,15 @@ def _get_http_proxy_config(file_path):
return config_object


def aks_app_init(destination='.',
app_name=None,
language=None,
create_config=None,
dockerfile_only=None,
deployment_only=None):
aks_draft_app_init(destination, app_name, language, create_config, dockerfile_only, deployment_only)


def aks_pod_identity_add(cmd, client, resource_group_name, cluster_name,
identity_name, identity_namespace, identity_resource_id,
binding_selector=None,
Expand Down