Skip to content

Commit

Permalink
Merge remote-tracking branch '9lash/abiyer/add-arcgateway' into Publi…
Browse files Browse the repository at this point in the history
…cPreviewWifChanges
  • Loading branch information
deeksha345 committed Jul 2, 2024
2 parents f22f36d + 33c889f commit cd21daf
Show file tree
Hide file tree
Showing 28 changed files with 6,360 additions and 22 deletions.
13 changes: 13 additions & 0 deletions src/connectedk8s/azext_connectedk8s/_client_factory.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,19 @@ def cf_connectedk8s_prev_2023_11_01(cli_ctx, *_):
def cf_connected_cluster_prev_2023_11_01(cli_ctx, _):
return cf_connectedk8s_prev_2023_11_01(cli_ctx).connected_cluster

def cf_connectedk8s_prev_2024_07_01(cli_ctx, *_):
from azext_connectedk8s.vendored_sdks.preview_2024_07_01 import ConnectedKubernetesClient
if os.getenv(consts.Azure_Access_Token_Variable):
validate_custom_token()
credential = AccessTokenCredential(access_token=os.getenv(consts.Azure_Access_Token_Variable))
return get_mgmt_service_client(cli_ctx, ConnectedKubernetesClient,
subscription_id=os.getenv('AZURE_SUBSCRIPTION_ID'),
credential=credential)
return get_mgmt_service_client(cli_ctx, ConnectedKubernetesClient)


def cf_connected_cluster_prev_2024_07_01(cli_ctx, _):
return cf_connectedk8s_prev_2024_07_01(cli_ctx).connected_cluster

def cf_connectedmachine(cli_ctx, subscription_id):
from azure.mgmt.hybridcompute import HybridComputeManagementClient
Expand Down
4 changes: 3 additions & 1 deletion src/connectedk8s/azext_connectedk8s/_params.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from argcomplete.completers import FilesCompleter
from azure.cli.core.commands.parameters import get_location_type, get_enum_type, file_type, tags_type, get_three_state_flag
from azure.cli.core.commands.validators import get_default_location_from_resource_group
from azext_connectedk8s._constants import Distribution_Enum_Values, Infrastructure_Enum_Values, Feature_Values, AHB_Enum_Values
from azext_connectedk8s._constants import Distribution_Enum_Values, Infrastructure_Enum_Values, Feature_Values, AHB_Enum_Values, Connection_Type
from knack.arguments import (CLIArgumentType, CaseInsensitiveList)

from ._validators import validate_private_link_properties
Expand Down Expand Up @@ -51,6 +51,8 @@ def load_arguments(self, _):
c.argument('container_log_path', help='Override the default container log path to enable fluent-bit logging')
c.argument('skip_ssl_verification', action='store_true', help='Skip SSL verification for any cluster connection.')
c.argument('yes', options_list=['--yes', '-y'], help='Do not prompt for confirmation.', action='store_true')
c.argument('enable_gateway', options_list=['--enable_gateway'], help='pass this value to enable Arc Gateway')
c.argument('disable_gateway', options_list=['--disable_gateway'], help='pass this value to enable Arc Gateway')

with self.argument_context('connectedk8s update') as c:
c.argument('tags', tags_type)
Expand Down
57 changes: 50 additions & 7 deletions src/connectedk8s/azext_connectedk8s/_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -375,11 +375,11 @@ def add_helm_repo(kube_config, kube_context, helm_client_location):
summary='Failed to add helm repository')
raise CLIInternalError("Unable to add repository {} to helm: ".format(repo_url) + error_helm_repo.decode("ascii"))


def get_helm_registry(cmd, config_dp_endpoint, release_train_custom=None):
# TODO: DP version: July 2024
def get_helm_values(cmd, config_dp_endpoint, release_train_custom=None):
# Setting uri
api_version = "2019-11-01-preview"
chart_location_url_segment = "azure-arc-k8sagents/GetLatestHelmPackagePath?api-version={}".format(api_version)
api_version = "2024-07-01-preview"
chart_location_url_segment = "azure-arc-k8sagents/GetHelmSettings?api-version={}".format(api_version)
release_train = os.getenv('RELEASETRAIN') if os.getenv('RELEASETRAIN') else 'stable'
chart_location_url = "{}/{}".format(config_dp_endpoint, chart_location_url_segment)
if release_train_custom:
Expand All @@ -393,17 +393,59 @@ def get_helm_registry(cmd, config_dp_endpoint, release_train_custom=None):
r = send_request_with_retries(cmd.cli_ctx, 'post', chart_location_url, headers=headers, fault_type=consts.Get_HelmRegistery_Path_Fault_Type, summary='Error while fetching helm chart registry path', uri_parameters=uri_parameters, resource=resource)
if r.content:
try:
return r.json().get('repositoryPath')
return r.json()
except Exception as e:
telemetry.set_exception(exception=e, fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
summary='Error while fetching helm chart registry path')
raise CLIInternalError("Error while fetching helm chart registry path from JSON response: " + str(e))
summary='Error while fetching helm values from DP')
raise CLIInternalError("Error while fetching helm values from DP from JSON response: " + str(e))
else:
telemetry.set_exception(exception='No content in response', fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
summary='No content in acr path response')
raise CLIInternalError("No content was found in helm registry path response.")


def send_request_with_retries(cli_ctx, method, url, headers, fault_type, summary, uri_parameters=None, resource=None, retry_count=5, retry_delay=3):
for i in range(retry_count):
try:
response = send_raw_request(cli_ctx, method, url, headers=headers, uri_parameters=uri_parameters, resource=resource)
return response
except Exception as e:
if i == retry_count - 1:
telemetry.set_exception(exception=e, fault_type=fault_type, summary=summary)
raise CLIInternalError("Error while fetching helm chart registry path: " + str(e))
time.sleep(retry_delay)

def get_helm_registry():


# def get_helm_registry(cmd, config_dp_endpoint, release_train_custom=None):
# # Setting uri
# api_version = "2019-11-01-preview"
# chart_location_url_segment = "azure-arc-k8sagents/GetLatestHelmPackagePath?api-version={}".format(api_version)
# release_train = os.getenv('RELEASETRAIN') if os.getenv('RELEASETRAIN') else 'stable'
# chart_location_url = "{}/{}".format(config_dp_endpoint, chart_location_url_segment)
# if release_train_custom:
# release_train = release_train_custom
# uri_parameters = ["releaseTrain={}".format(release_train)]
# resource = cmd.cli_ctx.cloud.endpoints.active_directory_resource_id
# headers = None
# if os.getenv('AZURE_ACCESS_TOKEN'):
# headers = ["Authorization=Bearer {}".format(os.getenv('AZURE_ACCESS_TOKEN'))]
# # Sending request with retries
# r = send_request_with_retries(cmd.cli_ctx, 'post', chart_location_url, headers=headers, fault_type=consts.Get_HelmRegistery_Path_Fault_Type, summary='Error while fetching helm chart registry path', uri_parameters=uri_parameters, resource=resource)
# if r.content:
# try:
# return r.json().get('repositoryPath')
# except Exception as e:
# telemetry.set_exception(exception=e, fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
# summary='Error while fetching helm chart registry path')
# raise CLIInternalError("Error while fetching helm chart registry path from JSON response: " + str(e))
# else:
# telemetry.set_exception(exception='No content in response', fault_type=consts.Get_HelmRegistery_Path_Fault_Type,
# summary='No content in acr path response')
# raise CLIInternalError("No content was found in helm registry path response.")


def send_request_with_retries(cli_ctx, method, url, headers, fault_type, summary, uri_parameters=None, resource=None, retry_count=5, retry_delay=3):
for i in range(retry_count):
try:
Expand Down Expand Up @@ -655,6 +697,7 @@ def helm_install_release(resource_manager, chart_path, subscription_id, kubernet
logger.warning("Please check if the azure-arc namespace was deployed and run 'kubectl get pods -n azure-arc' to check if all the pods are in running state. A possible cause for pods stuck in pending state could be insufficient resources on the kubernetes cluster to onboard to arc.")
raise CLIInternalError("Unable to install helm release: " + error_helm_install.decode("ascii"))

# TODO: implement a new helm_release command where you just consume the dp_helm_values and run a for loop and end up creating the helm values command.

def get_release_namespace(kube_config, kube_context, helm_client_location, release_name='azure-arc'):
cmd_helm_release = [helm_client_location, "list", "-a", "--all-namespaces", "--output", "json"]
Expand Down
60 changes: 46 additions & 14 deletions src/connectedk8s/azext_connectedk8s/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
from azext_connectedk8s._client_factory import cf_resource_groups
from azext_connectedk8s._client_factory import resource_providers_client
from azext_connectedk8s._client_factory import \
cf_connected_cluster_prev_2022_10_01, cf_connected_cluster_prev_2023_11_01
cf_connected_cluster_prev_2022_10_01, cf_connected_cluster_prev_2023_11_01, cf_connected_cluster_prev_2024_07_01
from azext_connectedk8s._client_factory import cf_connectedmachine
import azext_connectedk8s._constants as consts
import azext_connectedk8s._utils as utils
Expand All @@ -65,7 +65,7 @@
def create_connectedk8s(cmd, client, resource_group_name, cluster_name, correlation_id=None, https_proxy="", http_proxy="", no_proxy="", proxy_cert="", location=None,
kube_config=None, kube_context=None, no_wait=False, tags=None, distribution='generic', infrastructure='generic',
disable_auto_upgrade=False, cl_oid=None, onboarding_timeout="600", enable_private_link=None, private_link_scope_resource_id=None,
distribution_version=None, azure_hybrid_benefit=None, skip_ssl_verification=False, yes=False, container_log_path=None):
distribution_version=None, azure_hybrid_benefit=None, skip_ssl_verification=False, yes=False, container_log_path=None, connection_type="direct"):
logger.warning("This operation might take a while...\n")

# changing cli config to push telemetry in 1 hr interval
Expand Down Expand Up @@ -137,6 +137,10 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, correlat
if enable_private_link is not None or distribution_version is not None or azure_hybrid_benefit is not None:
client = cf_connected_cluster_prev_2023_11_01(cmd.cli_ctx, None)

# Set preview client if the connection-type is provided. (TODO: To test whether overriding the client factory to 2024 will retain the 2023 private link feature as in the line above)
if connection_type is not None and connection_type == "gateway":
client = cf_connected_cluster_prev_2024_07_01(cmd.cli_ctx, None)

# Checking whether optional extra values file has been provided.
values_file = utils.get_values_file()
if cmd.cli_ctx.cloud.endpoints.resource_manager == consts.Dogfood_RMEndpoint:
Expand Down Expand Up @@ -218,6 +222,9 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, correlat
logger.warning("There is no storage space available on your device and hence not saving cluster \
diagnostic check logs on your device")

# TODO: Add DP health check call


except Exception as e:
telemetry.set_exception(exception="An exception has occured while trying to execute pre-onboarding diagnostic \
checks : {}".format(str(e)),
Expand Down Expand Up @@ -435,18 +442,6 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, correlat
if os.getenv('HELMREPONAME') and os.getenv('HELMREPOURL'):
utils.add_helm_repo(kube_config, kube_context, helm_client_location)

# Retrieving Helm chart OCI Artifact location
registry_path = os.getenv('HELMREGISTRY') if os.getenv('HELMREGISTRY') else \
utils.get_helm_registry(cmd, config_dp_endpoint, release_train)

# Get azure-arc agent version for telemetry
azure_arc_agent_version = registry_path.split(':')[1]
telemetry.add_extension_event('connectedk8s',
{'Context.Default.AzureCLI.AgentVersion': azure_arc_agent_version})

# Get helm chart path
chart_path = utils.get_chart_path(registry_path, kube_config, kube_context, helm_client_location)

# Generate public-private key pair
try:
key_pair = RSA.generate(4096)
Expand Down Expand Up @@ -477,9 +472,46 @@ def create_connectedk8s(cmd, client, resource_group_name, cluster_name, correlat
put_cc_response = create_cc_resource(client, resource_group_name, cluster_name, cc, no_wait)
put_cc_response = LongRunningOperation(cmd.cli_ctx)(put_cc_response)
print("Azure resource provisioning has finished.")

# Checking if custom locations rp is registered and fetching oid if it is registered
enable_custom_locations, custom_locations_oid = check_cl_registration_and_get_oid(cmd, cl_oid, subscription_id)

# Change: Calling DP for Helm values
# Retrieving Helm chart OCI Artifact location
helm_values_dp = utils.get_helm_values(cmd, config_dp_endpoint, release_train)

# Parses the helm_values_dp
# {
# "repositoryPath": "mcr.microsoft.com/azurearck8s/canary/stable/azure-arc-k8sagents:0.2.62",
# "helmValuesContent": {
# "global.subscriptionId": "ca3b2020-292e-4ebc-9939-0b52415846ef",
# "global.resourceGroupName": "bs_testing",
# "global.resourceName": "bs_oci",
# "global.location": "westeurope",
# "global.httpsProxy": "ClientKnown",
# "global.httpProxy": "ClientKnown",
# "global.noProxy": "ClientKnown",
# "global.proxyCert": "ClientKnown",
# "global.isCustomCert": "true",
# "global.isProxyEnabled": "true",
# "systemDefaultValues.fluent-bit.containerLogPath": "/sample/test/path"
# },
# "apiServerFlags": null
# }

registry_path = os.getenv('HELMREGISTRY') if os.getenv('HELMREGISTRY') else \
helm_values_dp["repositoryPath"]

# Get azure-arc agent version for telemetry
azure_arc_agent_version = registry_path.split(':')[1]
telemetry.add_extension_event('connectedk8s',
{'Context.Default.AzureCLI.AgentVersion': azure_arc_agent_version})

# Get helm chart path
chart_path = utils.get_chart_path(registry_path, kube_config, kube_context, helm_client_location)

# TODO: use a new helm_values file to construct the helm install cmd

print("Starting to install Azure arc agents on the Kubernetes cluster.")
# Install azure-arc agents
utils.helm_install_release(cmd.cli_ctx.cloud.endpoints.resource_manager, chart_path, subscription_id,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from ._connected_kubernetes_client import ConnectedKubernetesClient
from ._version import VERSION

__version__ = VERSION

try:
from ._patch import __all__ as _patch_all
from ._patch import * # pylint: disable=unused-wildcard-import
except ImportError:
_patch_all = []
from ._patch import patch_sdk as _patch_sdk

__all__ = [
"ConnectedKubernetesClient",
]
__all__.extend([p for p in _patch_all if p not in __all__])

_patch_sdk()
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
# coding=utf-8
# --------------------------------------------------------------------------
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License. See License.txt in the project root for license information.
# Code generated by Microsoft (R) AutoRest Code Generator.
# Changes may cause incorrect behavior and will be lost if the code is regenerated.
# --------------------------------------------------------------------------

from typing import Any, TYPE_CHECKING

from azure.core.pipeline import policies
from azure.mgmt.core.policies import ARMChallengeAuthenticationPolicy, ARMHttpLoggingPolicy

from ._version import VERSION

if TYPE_CHECKING:
# pylint: disable=unused-import,ungrouped-imports
from azure.core.credentials import TokenCredential


class ConnectedKubernetesClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long
"""Configuration for ConnectedKubernetesClient.
Note that all parameters used to create this instance are saved as instance
attributes.
:param credential: Credential needed for the client to connect to Azure. Required.
:type credential: ~azure.core.credentials.TokenCredential
:param subscription_id: The ID of the target subscription. Required.
:type subscription_id: str
:keyword api_version: Api Version. Default value is "2024-07-01-preview". Note that overriding
this default value may result in unsupported behavior.
:paramtype api_version: str
"""

def __init__(self, credential: "TokenCredential", subscription_id: str, **kwargs: Any) -> None:
api_version: str = kwargs.pop("api_version", "2024-07-01-preview")

if credential is None:
raise ValueError("Parameter 'credential' must not be None.")
if subscription_id is None:
raise ValueError("Parameter 'subscription_id' must not be None.")

self.credential = credential
self.subscription_id = subscription_id
self.api_version = api_version
self.credential_scopes = kwargs.pop("credential_scopes", ["https://management.azure.com/.default"])
kwargs.setdefault("sdk_moniker", "mgmt-hybridkubernetes/{}".format(VERSION))
self.polling_interval = kwargs.get("polling_interval", 30)
self._configure(**kwargs)

def _configure(self, **kwargs: Any) -> None:
self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs)
self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs)
self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs)
self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs)
self.http_logging_policy = kwargs.get("http_logging_policy") or ARMHttpLoggingPolicy(**kwargs)
self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs)
self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs)
self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs)
self.authentication_policy = kwargs.get("authentication_policy")
if self.credential and not self.authentication_policy:
self.authentication_policy = ARMChallengeAuthenticationPolicy(
self.credential, *self.credential_scopes, **kwargs
)
Loading

0 comments on commit cd21daf

Please sign in to comment.