1# -------------------------------------------------------------------------------------------- 2# Copyright (c) Microsoft Corporation. All rights reserved. 3# Licensed under the MIT License. See License.txt in the project root for license information. 4# -------------------------------------------------------------------------------------------- 5 6# pylint: disable=line-too-long 7import argparse 8 9from azure.cli.command_modules.servicefabric._validators import ( 10 validate_create_application, validate_create_managed_application, 11 validate_create_managed_cluster, validate_create_managed_service, 12 validate_create_service, validate_update_application, 13 validate_update_managed_application, validate_update_managed_service, 14 validate_create_managed_service_correlation, validate_create_managed_service_load_metric, 15 validate_update_managed_service_load_metric, validate_update_managed_service_correlation) 16from azure.cli.core.commands.parameters import (get_enum_type, 17 get_three_state_flag, 18 resource_group_name_type, 19 tags_type) 20from azure.cli.core.commands.validators import get_default_location_from_resource_group 21from azure.cli.core.util import CLIError, get_json_object 22from azure.mgmt.servicefabricmanagedclusters.models import (FailureAction, 23 MoveCost, 24 PartitionScheme, 25 RollingUpgradeMode, 26 ServiceKind, 27 DiskType, 28 ClusterUpgradeMode, 29 ClusterUpgradeCadence) 30from knack.arguments import CLIArgumentType 31 32 33def load_arguments(self, _): # pylint: disable=too-many-statements 34 # PARAMETER REGISTRATION 35 application_parameters = CLIArgumentType( 36 options_list=['--parameters', '--application-parameters'], 37 action=AddAppParamsAction, 38 nargs='+', 39 help='Specify the application parameters as key/value pairs. These parameters must exist in the application manifest. ' 40 'for example: --application-parameters param1=value1 param2=value2') 41 42 minimum_nodes = CLIArgumentType( 43 options_list=['--min-nodes', '--minimum-nodes'], 44 help='Specify the minimum number of nodes where Service Fabric will reserve capacity for this application, ' 45 'this does not mean that the application is guaranteed to have replicas on all those nodes. The value of this parameter must be a non-negative integer. ' 46 'Default value for this is zero, which means no capacity is reserved for the application.') 47 48 maximum_nodes = CLIArgumentType( 49 options_list=['--max-nodes', '--maximum-nodes'], 50 help='Specify the maximum number of nodes on which to place an application. ' 51 'The value of this parameter must be a non-negative integer. The default value is 0, which indicates the application can be placed on any number of nodes in the cluster.') 52 53 application_type_version = CLIArgumentType( 54 options_list=['--version', '--application-type-version'], 55 help='Specify the application type version.') 56 57 package_url = CLIArgumentType( 58 help='Specify the url of the application package sfpkg file.') 59 60 with self.argument_context('sf') as c: 61 c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None, help='Specify the resource group name. You can configure the default group using `az configure --defaults group=<name>`') 62 c.argument('cluster_name', options_list=['--cluster-name', '-c'], help='Specify the name of the cluster, if not given it will be same as resource group name') 63 c.argument('location', validator=get_default_location_from_resource_group) 64 c.argument('secret_identifier', help='The existing Azure key vault secret URL') 65 c.argument('certificate_file', help='The existing certificate file path for the primary cluster certificate.') 66 c.argument('parameter_file', help='The path to the template parameter file.') 67 c.argument('template_file', help='The path to the template file.') 68 c.argument('vm_password', help='The password of the Vm') 69 c.argument('certificate_output_folder', options_list=['--certificate-output-folder', '--cert-out-folder'], help='The folder of the new certificate file to be created.') 70 c.argument('certificate_password', help='The password of the certificate file.') 71 c.argument('certificate_subject_name', options_list=['--certificate-subject-name', '--cert-subject-name'], help='The subject name of the certificate to be created.') 72 c.argument('vault_resource_group_name', options_list=['--vault-rg', c.deprecate(target='--vault-resource-group', redirect='--vault-rg', hide=True)], 73 help='Key vault resource group name, if not given it will be cluster resource group name') 74 c.argument('vault_name', help='Azure key vault name, it not given it will be the cluster resource group name') 75 c.argument('cluster_size', options_list=['--cluster-size', '-s'], help='The number of nodes in the cluster. Default are 5 nodes') 76 c.argument('vm_sku', help='VM Sku') 77 c.argument('vm_user_name', help='The user name for logging to Vm. Default will be adminuser') 78 c.argument('vm_os', arg_type=get_enum_type(['WindowsServer2012R2Datacenter', 79 'WindowsServer2016Datacenter', 80 'WindowsServer2016DatacenterwithContainers', 81 'UbuntuServer1604', 82 'WindowsServer1709', 83 'WindowsServer1709withContainers', 84 'WindowsServer1803withContainers', 85 'WindowsServer1809withContainers', 86 'WindowsServer2019Datacenter', 87 'WindowsServer2019DatacenterwithContainers']), 88 default='WindowsServer2016Datacenter', options_list=['--vm-os', '--os'], 89 help='The Operating System of the VMs that make up the cluster.') 90 c.argument('node_type', help='the Node type name.') 91 92 # cluster 93 with self.argument_context('sf cluster list') as c: 94 c.argument('resource_group_name', arg_type=resource_group_name_type, id_part=None, help='The resource group name') 95 96 with self.argument_context('sf client certificate') as c: 97 c.argument('certificate_common_name', help='client certificate common name.') 98 c.argument('admin_client_thumbprints', options_list=['--admin-client-thumbprints', '--admin-client-tps'], nargs='+', help='Space-separated list of client certificate thumbprint that only has admin permission, ') 99 c.argument('certificate_issuer_thumbprint', options_list=['--certificate-issuer-thumbprint', '--cert-issuer-tp'], help='client certificate issuer thumbprint.') 100 101 with self.argument_context('sf cluster client-certificate') as c: 102 c.argument('is_admin', help='Client authentication type.') 103 c.argument('certificate_issuer_thumbprint', options_list=['--certificate-issuer-thumbprint', '--cert-issuer-tp'], help='client certificate issuer thumbprint.') 104 c.argument('certificate_common_name', options_list=['--certificate-common-name', '--cert-common-name'], help='client certificate common name.') 105 c.argument('admin_client_thumbprints', options_list=['--admin-client-thumbprints', '--admin-client-tps'], nargs='+', help='client certificate thumbprint that only has admin permission.') 106 c.argument('readonly_client_thumbprints', options_list=['--readonly-client-thumbprints', '--readonly-client-tps'], nargs='+', help='Space-separated list of client certificate thumbprint that has read only permission.') 107 108 with self.argument_context('sf cluster client-certificate add') as c: 109 c.argument('thumbprint', help='client certificate thumbprint.') 110 111 with self.argument_context('sf cluster client-certificate remove') as c: 112 c.argument('thumbprints', nargs='+', help='A single or Space-separated list of client certificate thumbprint(s) to be remove.') 113 114 with self.argument_context('sf cluster node') as c: 115 c.argument('number_of_nodes_to_add', options_list=['--number-of-nodes-to-add', '--nodes-to-add'], help='number of nodes to add.') 116 c.argument('number_of_nodes_to_remove', options_list=['--number-of-nodes-to-remove', '--nodes-to-remove'], help='number of nodes to remove.') 117 118 with self.argument_context('sf cluster node-type') as c: 119 c.argument('capacity', help='The capacity tag applied to nodes in the node type. The cluster resource manager uses these tags to understand how much capacity a node has.') 120 c.argument('vm_tier', help='VM tier.') 121 122 with self.argument_context('sf cluster') as c: 123 c.argument('durability_level', arg_type=get_enum_type(['Bronze', 'Silver', 'Gold']), help='durability level.') 124 125 with self.argument_context('sf cluster setting') as c: 126 c.argument('parameter', help='parameter name') 127 c.argument('section', help='section name') 128 c.argument('value', help='Specify the value') 129 c.argument('settings_section_description', options_list=['--settings-section-description', '--settings-section'], help='Specify the value') 130 131 with self.argument_context('sf cluster upgrade-type set') as c: 132 c.argument('version', help='cluster code version') 133 c.argument('upgrade_mode', arg_type=get_enum_type(['manual', 'automatic']), help='cluster upgrade mode') 134 135 with self.argument_context('sf cluster reliability') as c: 136 c.argument('reliability_level', arg_type=get_enum_type(['Bronze', 'Silver', 'Gold', 'Platinum']), help='durability level.') 137 c.argument('auto_add_node', help='Add node count automatically when changing reliability.') 138 139 with self.argument_context('sf cluster setting set') as c: 140 c.argument('settings_section_description', options_list=['--settings-section-description', '--settings-section'], type=get_json_object, 141 help='JSON encoded parameters configuration. Use @{file} to load from a file. ' 142 'For example: [{"section": "NamingService","parameter": "MaxOperationTimeout","value": 1000},{"section": "MaxFileOperationTimeout","parameter": "Max2","value": 1000]') 143 144 with self.argument_context('sf cluster setting remove') as c: 145 c.argument('settings_section_description', options_list=['--settings-section-description', '--settings-section'], type=get_json_object, 146 help='JSON encoded parameters configuration. Use @{file} to load from a file. ' 147 'For example: [{"section": "NamingService","parameter": "MaxOperationTimeout"}]') 148 149 with self.argument_context('sf cluster client-certificate remove') as c: 150 c.argument('client_certificate_common_names', options_list=['--client-certificate-common-names', '--client-cert-cn'], type=get_json_object, 151 help='JSON encoded parameters configuration. Use @{file} to load from a file. ' 152 'For example: [{"certificateCommonName": "test.com","certificateIssuerThumbprint": "22B4AE296B504E512DF880A77A2CAE20200FF922"}]') 153 154 with self.argument_context('sf cluster client-certificate add') as c: 155 c.argument('client_certificate_common_names', options_list=['--client-certificate-common-names', '--client-cert-cn'], type=get_json_object, 156 help='JSON encoded parameters configuration. Use @{file} to load from a file. ' 157 'For example: [{"isAdmin":true, "certificateCommonName": "test.com", ' 158 '"certificateIssuerThumbprint": "22B4AE296B504E512DF880A77A2CAE20200FF922"}]') 159 160 # application-type 161 with self.argument_context('sf application-type') as c: 162 c.argument('application_type_name', options_list=['--name', '--application-type-name'], help='Specify the application type name.') 163 164 # application-type version 165 with self.argument_context('sf application-type version') as c: 166 c.argument('version', arg_type=application_type_version) 167 c.argument('package_url', arg_type=package_url) 168 169 # application 170 with self.argument_context('sf application') as c: 171 c.argument('application_name', options_list=['--name', '--application-name'], help='Specify the application name.') 172 173 with self.argument_context('sf application update', validator=validate_update_application) as c: 174 c.argument('application_type_version', arg_type=application_type_version) 175 c.argument('application_parameters', arg_type=application_parameters) 176 c.argument('minimum_nodes', arg_type=minimum_nodes) 177 c.argument('maximum_nodes', arg_type=maximum_nodes) 178 c.argument('force_restart', arg_type=get_three_state_flag(), 179 help='Indicates that the service host restarts even if the upgrade is a configuration-only change.') 180 c.argument('service_type_health_policy_map', options_list=['--service-type-health-policy-map', '--service-type-policy'], 181 help='Specify the map of the health policy to use for different service types as a hash table in the following format: {\"ServiceTypeName\" : \"MaxPercentUnhealthyPartitionsPerService,MaxPercentUnhealthyReplicasPerPartition,MaxPercentUnhealthyServices\"}. For example: @{ \"ServiceTypeName01\" = \"5,10,5\"; \"ServiceTypeName02\" = \"5,5,5\" }') 182 183 with self.argument_context('sf application update', arg_group='Upgrade description') as c: 184 c.argument('upgrade_replica_set_check_timeout', options_list=['--upgrade-replica-set-check-timeout', '--replica-check-timeout', '--rep-check-timeout'], 185 help='Specify the maximum time, in seconds, that Service Fabric waits for a service to reconfigure into a safe state, if not already in a safe state, before Service Fabric proceeds with the upgrade.') 186 c.argument('failure_action', arg_type=get_enum_type(['Rollback', 'Manual']), 187 help='Specify the action to take if the monitored upgrade fails. The acceptable values for this parameter are Rollback or Manual.') 188 c.argument('health_check_retry_timeout', options_list=['--hc-retry-timeout', '--health-check-retry-timeout'], 189 help='Specify the duration, in seconds, after which Service Fabric retries the health check if the previous health check fails.') 190 c.argument('health_check_wait_duration', options_list=['--hc-wait-duration', '--health-check-wait-duration'], 191 help='Specify the duration, in seconds, that Service Fabric waits before it performs the initial health check after it finishes the upgrade on the upgrade domain.') 192 c.argument('health_check_stable_duration', options_list=['--hc-stable-duration', '--health-check-stable-duration'], 193 help='Specify the duration, in seconds, that Service Fabric waits in order to verify that the application is stable before moving to the next upgrade domain or completing the upgrade. This wait duration prevents undetected changes of health right after the health check is performed.') 194 c.argument('upgrade_domain_timeout', options_list=['--ud-timeout', '--upgrade-domain-timeout'], 195 help='Specify the maximum time, in seconds, that Service Fabric takes to upgrade a single upgrade domain. After this period, the upgrade fails.') 196 c.argument('upgrade_timeout', 197 help='Specify the maximum time, in seconds, that Service Fabric takes for the entire upgrade. After this period, the upgrade fails.') 198 c.argument('consider_warning_as_error', options_list=['--warning-as-error', '--consider-warning-as-error'], arg_type=get_three_state_flag(), 199 help='Indicates whether to treat a warning health event as an error event during health evaluation.') 200 c.argument('default_service_type_max_percent_unhealthy_partitions_per_service', options_list=['--max-porcent-unhealthy-partitions', '--max-unhealthy-parts'], 201 help='Specify the maximum percent of unhelthy partitions per service allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are form 0 to 100.') 202 c.argument('default_service_type_max_percent_unhealthy_replicas_per_partition', options_list=['--max-porcent-unhealthy-replicas', '--max-unhealthy-reps'], 203 help='Specify the maximum percent of unhelthy replicas per service allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are form 0 to 100.') 204 c.argument('default_service_type_max_percent_unhealthy_services', options_list=['--max-porcent-unhealthy-services', '--max-unhealthy-servs'], 205 help='Specify the maximum percent of unhelthy services allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are form 0 to 100.') 206 c.argument('max_percent_unhealthy_deployed_applications', options_list=['--max-porcent-unhealthy-apps', '--max-unhealthy-apps'], 207 help='Specify the maximum percentage of the application instances deployed on the nodes in the cluster that have a health state of error before the application health state for the cluster is error. Allowed values are form 0 to 100.') 208 209 with self.argument_context('sf application create', validator=validate_create_application) as c: 210 c.argument('application_type_name', options_list=['--type-name', '--application-type-name'], help='Specify the application type name.') 211 c.argument('application_type_version', arg_type=application_type_version) 212 c.argument('package_url', arg_type=package_url) 213 c.argument('application_parameters', arg_type=application_parameters) 214 c.argument('minimum_nodes', arg_type=minimum_nodes) 215 c.argument('maximum_nodes', arg_type=maximum_nodes) 216 217 # service 218 with self.argument_context('sf service') as c: 219 c.argument('service_name', options_list=['--name', '--service-name'], 220 help='Specify the name of the service. The application name must be a prefix of the service name, for example: appName~serviceName') 221 222 with self.argument_context('sf service create', validator=validate_create_service) as c: 223 c.argument('service_type', 224 help='Specify the service type name of the application, it should exist in the application manifest.') 225 c.argument('application_name', options_list=['--application', '--application-name'], 226 help='Specify the name of the service. The application name must be a prefix of the service name, for example: appName~serviceName') 227 c.argument('state', arg_type=get_enum_type(['stateless', 'stateful']), help='Specify if the service is stateless or stateful.') 228 c.argument('instance_count', help='Specify the instance count for the stateless service. If -1 is used, it means it will run on all the nodes.') 229 c.argument('min_replica_set_size', options_list=['--min-replica-set-size', '--min-replica'], help='Specify the min replica set size for the stateful service.') 230 c.argument('target_replica_set_size', options_list=['--target-replica-set-size', '--target-replica'], help='Specify the target replica set size for the stateful service.') 231 c.argument('default_move_cost', arg_type=get_enum_type(['Zero', 'Low', 'Medium', 'High']), 232 help='Specify the default cost for a move. Higher costs make it less likely that the Cluster Resource Manager will move the replica when trying to balance the cluster.') 233 c.argument('partition_scheme', arg_type=get_enum_type(['singleton', 'uniformInt64', 'named']), 234 help='Specify what partition scheme to use. ' 235 'Singleton partitions are typically used when the service does not require any additional routing. ' 236 'UniformInt64 means that each partition owns a range of int64 keys. ' 237 'Named is usually for services with data that can be bucketed, within a bounded set. Some common examples of data fields used as named partition keys would be regions, postal codes, customer groups, or other business boundaries.') 238 239 # managed cluster 240 241 with self.argument_context('sf managed-cluster create', validator=validate_create_managed_cluster) as c: 242 c.argument('admin_password', help='Admin password used for the virtual machines.') 243 c.argument('admin_user_name', help='Admin user used for the virtual machines.', default='vmadmin') 244 c.argument('dns_name', help='Cluster\'s dns name.') 245 c.argument('sku', help='Cluster\'s Sku, the options are Basic: it will have a minimum of 3 seed nodes and only allows 1 node type and Standard: it will have a minimum of 5 seed nodes and allows multiple node types.', default='Basic') 246 c.argument('client_connection_port', options_list=['--client-connection-port', '--client-port'], help='Port used for client connections to the cluster.', default=19000) 247 c.argument('gateway_connection_port', options_list=['--gateway-connection-port', '--gateway-port'], help='Port used for http connections to the cluster.', default=19080) 248 c.argument('client_cert_is_admin', options_list=['--client-cert-is-admin', '--cert-is-admin'], arg_type=get_three_state_flag(), help='Client authentication type.') 249 c.argument('client_cert_thumbprint', options_list=['--client-cert-thumbprint', '--cert-thumbprint'], help='Client certificate thumbprint.') 250 c.argument('client_cert_common_name', options_list=['--client-cert-common-name', '--cert-common-name'], help='Client certificate common name.') 251 c.argument('client_cert_issuer_thumbprint', options_list=['--client-cert-issuer-thumbprint', '--cert-issuer-thumbprint', '--cert-issuer-tp'], nargs='+', help='Space-separated list of issuer thumbprints.') 252 c.argument('upgrade_mode', arg_type=get_enum_type(ClusterUpgradeMode), options_list=['--cluster-upgrade-mode', '--upgrade-mode'], 253 help='The upgrade mode of the cluster when new Service Fabric runtime version is available ' 254 'Automatic: The cluster will be automatically upgraded to the latest Service Fabric runtime version, upgrade_cadence will determine when the upgrade starts after the new version becomes available.' 255 'Manual: The cluster will not be automatically upgraded to the latest Service Fabric runtime version. The cluster is upgraded by setting the code_version property in the cluster resource.') 256 c.argument('upgrade_cadence', arg_type=get_enum_type(ClusterUpgradeCadence), options_list=['--cluster-upgrade-cadence', '--upgrade-cadence'], 257 help='The upgrade mode of the cluster when new Service Fabric runtime version is available ' 258 'Wave0: Cluster upgrade starts immediately after a new version is rolled out. Recommended for Test/Dev clusters.' 259 'Wave1: Cluster upgrade starts 7 days after a new version is rolled out. Recommended for Pre-prod clusters.' 260 'Wave2: Cluster upgrade starts 14 days after a new version is rolled out. Recommended for Production clusters.') 261 c.argument('code_version', options_list=['--cluster-code-version', '--code-version'], 262 help='Cluster service fabric code version. Only use if upgrade mode is Manual.') 263 c.argument('tags', arg_type=tags_type) 264 265 with self.argument_context('sf managed-cluster update') as c: 266 c.argument('client_connection_port', options_list=['--client-connection-port', '--client-port'], help='Port used for client connections to the cluster.') 267 c.argument('gateway_connection_port', options_list=['--gateway-connection-port', '--gateway-port'], help='Port used for http connections to the cluster.') 268 c.argument('dns_name', help='Cluster\'s dns name') 269 c.argument('tags', arg_type=tags_type) 270 271 with self.argument_context('sf managed-cluster client-certificate add') as c: 272 c.argument('is_admin', arg_type=get_three_state_flag(), help='Client authentication type.') 273 c.argument('thumbprint', help='Client certificate thumbprint.') 274 c.argument('common_name', help='Client certificate common name.') 275 c.argument('issuer_thumbprint', nargs='+', help='Space-separated list of issuer thumbprints.') 276 277 with self.argument_context('sf managed-cluster client-certificate delete') as c: 278 c.argument('thumbprint', nargs='+', help='A single or Space-separated list of client certificate thumbprint(s) to be remove.') 279 c.argument('common_name', nargs='+', help='A single or Space-separated list of client certificate common name(s) to be remove.') 280 281 # managed node type 282 283 capacity = CLIArgumentType( 284 options_list=['--capacity'], 285 action=AddNodeTypeCapacityAction, 286 nargs='+', 287 help='Capacity tags applied to the nodes in the node type as key/value pairs, the cluster resource manager uses these tags to understand how much resource a node has. Updating this will override the current values.' 288 'for example: --capacity ClientConnections=65536 param2=value2') 289 290 placement_property = CLIArgumentType( 291 options_list=['--placement-property'], 292 action=AddNodeTypePlacementPropertyAction, 293 nargs='+', 294 help='Placement tags applied to nodes in the node type as key/value pairs, which can be used to indicate where certain services (workload) should run. Updating this will override the current values.' 295 'for example: --placement-property NodeColor=Green SomeProperty=5') 296 297 with self.argument_context('sf managed-node-type') as c: 298 c.argument('node_type_name', options_list=['-n', '--name', '--node-type-name'], help='node type name.') 299 c.argument('instance_count', help='essage = "The number of nodes in the node type.') 300 c.argument('primary', arg_type=get_three_state_flag(), help='Specify if the node type is primary. On this node type will run system services. Only one node type should be marked as primary. Primary node type cannot be deleted or changed for existing clusters.') 301 c.argument('disk_size', type=int, options_list=['--disk-size', '--data-disk-size'], help='Disk size for each vm in the node type in GBs.', default=100) 302 c.argument('disk_type', arg_type=get_enum_type(DiskType), options_list=['--disk-type', '--data-disk-type'], 303 help='Managed data disk type. IOPS and throughput are given by the disk size, to see more information go to https://docs.microsoft.com/azure/virtual-machines/disks-types. Default StandardSSD_LRS' 304 'Standard_LRS: Standard HDD locally redundant storage. Best for backup, non-critical, and infrequent access.' 305 'StandardSSD_LRS: Standard SSD locally redundant storage. Best for web servers, lightly used enterprise applications and dev/test.' 306 'Premium_LRS: Premium SSD locally redundant storage. Best for production and performance sensitive workloads.') 307 c.argument('application_start_port', options_list=['--application-start-port', '--app-start-port'], help='Application start port of a range of ports.') 308 c.argument('application_end_port', options_list=['--application-end-port', '--app-end-port'], help='Application End port of a range of ports.') 309 c.argument('ephemeral_start_port', help='Ephemeral start port of a range of ports.') 310 c.argument('ephemeral_end_port', help='Ephemeral end port of a range of ports.') 311 c.argument('vm_size', help='The size of virtual machines in the pool. All virtual machines in a pool are the same size.', default='Standard_D2') 312 c.argument('vm_image_publisher', help='The publisher of the Azure Virtual Machines Marketplace image.', default='MicrosoftWindowsServer') 313 c.argument('vm_image_offer', help='The offer type of the Azure Virtual Machines Marketplace image.', default='WindowsServer') 314 c.argument('vm_image_sku', help='The SKU of the Azure Virtual Machines Marketplace image.', default='2019-Datacenter') 315 c.argument('vm_image_version', help='The version of the Azure Virtual Machines Marketplace image. ', default='latest') 316 c.argument('capacity', arg_type=capacity) 317 c.argument('placement_property', arg_type=placement_property) 318 c.argument('is_stateless', arg_type=get_three_state_flag(), help='Indicates if the node type can only host Stateless workloads.', default=False) 319 c.argument('multiple_placement_groups', options_list=['--multiple-placement-groups', '--multi-place-groups'], arg_type=get_three_state_flag(), 320 help='Indicates if scale set associated with the node type can be composed of multiple placement groups.', default=False) 321 322 with self.argument_context('sf managed-node-type node') as c: 323 c.argument('node_name', nargs='+', help='list of target nodes to perform the operation.') 324 c.argument('force', arg_type=get_three_state_flag(), help='Using this flag will force the operation even if service fabric is unable to disable the nodes. Use with caution as this might cause data loss if stateful workloads are running on the node.') 325 326 with self.argument_context('sf managed-node-type vm-extension') as c: 327 c.argument('extension_name', help='extension name.') 328 c.argument('force_update_tag', help='If a value is provided and is different from the previous value, the extension handler will be forced to update even if the extension configuration has not changed.') 329 c.argument('publisher', help='The name of the extension handler publisher.') 330 c.argument('extension_type', help='Specifies the type of the extension; an example is \"CustomScriptExtension\".') 331 c.argument('type_handler_version', help='Specifies the version of the script handler.') 332 c.argument('auto_upgrade_minor_version', options_list=['--auto-upgrade-minor-version', '--auto-upgrade'], arg_type=get_three_state_flag(), help='Indicates whether the extension should use a newer minor version if one is available at deployment time. Once deployed, however, the extension will not upgrade minor versions unless redeployed, even with this property set to true.') 333 c.argument('setting', help='Json formatted public settings for the extension.') 334 c.argument('protected_setting', help='The extension can contain either protectedSettings or protectedSettingsFromKeyVault or no protected settings at all.') 335 c.argument('provision_after_extension', options_list=['--provision-after-extension', '--provision-after'], help='Collection of extension names after which this extension needs to be provisioned.') 336 337 with self.argument_context('sf managed-node-type vm-secret') as c: 338 c.argument('source_vault_id', help='Key Vault resource id containing the certificates.') 339 c.argument('certificate_url', help='This is the URL of a certificate that has been uploaded to Key Vault as a secret. For adding a secret to the Key Vault, see [Add a key or secret to the key vault](https://docs.microsoft.com/azure/key-vault/key-vault-get-started/#add). In this case, your certificate needs to be It is the Base64 encoding of the following JSON Object which is encoded in UTF-8: <br><br> {<br> \"data\":\"<Base64-encoded-certificate>\",<br> \"dataType\":\"pfx\",<br> \"password\":\"<pfx-file-password>\"<br>}/') 340 c.argument('certificate_store', help='Specifies the certificate store on the Virtual Machine to which the certificate should be added. The specified certificate store is implicitly in the LocalMachine account.') 341 342 # managed-application-type 343 with self.argument_context('sf managed-application-type') as c: 344 c.argument('application_type_name', options_list=['--name', '--application-type-name'], help='Specify the application type name.') 345 c.argument('tags', arg_type=tags_type) 346 347 # managed-application-type version 348 with self.argument_context('sf managed-application-type version') as c: 349 c.argument('version', arg_type=application_type_version) 350 c.argument('package_url', arg_type=package_url) 351 c.argument('tags', arg_type=tags_type) 352 353 # managed-application 354 service_type_health_policy_map = CLIArgumentType( 355 options_list=['--service-type-health-policy-map', '--service-type-policy'], 356 action=AddServiceTypeHealthPolicyAction, 357 nargs='*', 358 help='Specify the map of the health policy to use for different service types as key/value pairs in the following format: \"ServiceTypeName\"=\"MaxPercentUnhealthyPartitionsPerService,MaxPercentUnhealthyReplicasPerPartition,MaxPercentUnhealthyServices\". ' 359 'for example: --service-type-health-policy-map \"ServiceTypeName01\"=\"5,10,5\" \"ServiceTypeName02\"=\"5,5,5\"') 360 361 with self.argument_context('sf managed-application') as c: 362 c.argument('application_name', options_list=['--name', '--application-name'], help='Specify the application name.') 363 c.argument('tags', arg_type=tags_type) 364 365 with self.argument_context('sf managed-application update', validator=validate_update_managed_application) as c: 366 c.argument('application_type_version', arg_type=application_type_version) 367 c.argument('application_parameters', arg_type=application_parameters) 368 369 with self.argument_context('sf managed-application update', arg_group='Upgrade description') as c: 370 c.argument('force_restart', arg_type=get_three_state_flag(), 371 help='Indicates that the service host restarts even if the upgrade is a configuration-only change.') 372 c.argument('recreate_application', arg_type=get_three_state_flag(), 373 help='Determines whether the application should be recreated on update. If value=true, the rest of the upgrade policy parameters are not allowed.') 374 c.argument('upgrade_replica_set_check_timeout', options_list=['--upgrade-replica-set-check-timeout', '--replica-check-timeout', '--rep-check-timeout'], 375 help='Specify the maximum time, in seconds, that Service Fabric waits for a service to reconfigure into a safe state, if not already in a safe state, before Service Fabric proceeds with the upgrade.') 376 c.argument('instance_close_delay_duration', options_list=['--instance-close-delay-duration', '--instance-close-duration', '--close-duration'], 377 help='Specify the duration in seconds, to wait before a stateless instance is closed, to allow the active requests to drain gracefully. This would be effective when the instance is closing during the application/cluster upgrade, only for those instances which have a non-zero delay duration configured in the service description.') 378 c.argument('failure_action', arg_type=get_enum_type(FailureAction), 379 help='Specify the action to take if the monitored upgrade fails. The acceptable values for this parameter are Rollback or Manual.') 380 c.argument('upgrade_mode', arg_type=get_enum_type(RollingUpgradeMode), 381 help='Specify the mode used to monitor health during a rolling upgrade. The values are Monitored, and UnmonitoredAuto.') 382 c.argument('health_check_retry_timeout', options_list=['--hc-retry-timeout', '--health-check-retry-timeout'], 383 help='Specify the duration, in seconds, after which Service Fabric retries the health check if the previous health check fails.') 384 c.argument('health_check_wait_duration', options_list=['--hc-wait-duration', '--health-check-wait-duration'], 385 help='Specify the duration, in seconds, that Service Fabric waits before it performs the initial health check after it finishes the upgrade on the upgrade domain.') 386 c.argument('health_check_stable_duration', options_list=['--hc-stable-duration', '--health-check-stable-duration'], 387 help='Specify the duration, in seconds, that Service Fabric waits in order to verify that the application is stable before moving to the next upgrade domain or completing the upgrade. This wait duration prevents undetected changes of health right after the health check is performed.') 388 c.argument('upgrade_domain_timeout', options_list=['--ud-timeout', '--upgrade-domain-timeout'], 389 help='Specify the maximum time, in seconds, that Service Fabric takes to upgrade a single upgrade domain. After this period, the upgrade fails.') 390 c.argument('upgrade_timeout', 391 help='Specify the maximum time, in seconds, that Service Fabric takes for the entire upgrade. After this period, the upgrade fails.') 392 c.argument('consider_warning_as_error', options_list=['--warning-as-error', '--consider-warning-as-error'], arg_type=get_three_state_flag(), 393 help='Indicates whether to treat a warning health event as an error event during health evaluation.') 394 c.argument('default_service_type_max_percent_unhealthy_partitions_per_service', options_list=['--max-percent-unhealthy-partitions', '--max-unhealthy-parts'], 395 help='Specify the maximum percent of unhelthy partitions per service allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are from 0 to 100.') 396 c.argument('default_service_type_max_percent_unhealthy_replicas_per_partition', options_list=['--max-percent-unhealthy-replicas', '--max-unhealthy-reps'], 397 help='Specify the maximum percent of unhelthy replicas per service allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are from 0 to 100.') 398 c.argument('default_service_type_max_percent_unhealthy_services', options_list=['--max-percent-unhealthy-services', '--max-unhealthy-servs'], 399 help='Specify the maximum percent of unhelthy services allowed by the health policy for the default service type to use for the monitored upgrade. Allowed values are from 0 to 100.') 400 c.argument('service_type_health_policy_map', arg_type=service_type_health_policy_map) 401 c.argument('max_percent_unhealthy_deployed_applications', options_list=['--max-percent-unhealthy-deployed-applications', '--max-percent-unhealthy-apps', '--max-unhealthy-apps'], 402 help='Specify the maximum percentage of the application instances deployed on the nodes in the cluster that have a health state of error before the application health state for the cluster is error. Allowed values are form 0 to 100.') 403 404 with self.argument_context('sf managed-application create', validator=validate_create_managed_application) as c: 405 c.argument('application_type_name', options_list=['--type-name', '--application-type-name'], help='Specify the application type name.') 406 c.argument('application_type_version', arg_type=application_type_version) 407 c.argument('package_url', arg_type=package_url) 408 c.argument('application_parameters', arg_type=application_parameters) 409 410 # managed-service 411 partition_names = CLIArgumentType( 412 nards="+", 413 help='Specify the array for the names of the partitions. This is only used with Named partition scheme.') 414 415 with self.argument_context('sf managed-service') as c: 416 c.argument('service_name', options_list=['--name', '--service-name'], 417 help='Specify the name of the service.') 418 c.argument('application_name', options_list=['--application', '--application-name'], 419 help='Specify the name of the service.') 420 c.argument('tags', arg_type=tags_type) 421 422 with self.argument_context('sf managed-service create', validator=validate_create_managed_service) as c: 423 c.argument('service_type', options_list=['--type', '--service-type'], 424 help='Specify the service type name of the application, it should exist in the application manifest.') 425 c.argument('default_move_cost', arg_type=get_enum_type(MoveCost), 426 help='Specify the default cost for a move. Higher costs make it less likely that the Cluster Resource Manager will move the replica when trying to balance the cluster.') 427 c.argument('placement_constraints', 428 help='Specify the placement constraints as a string. Placement constraints are boolean expressions on node properties and allow for restricting a service to particular nodes based on the service requirements. For example, to place a service on nodes where NodeType is blue specify the following: \"NodeColor == blue)\".') 429 c.argument('service_package_activation_mode', options_list=['--service-package-activation-mode', '--package-activation-mode', '--activation-mode'], 430 help='Specify the activation mode of the service package.') 431 c.argument('state', arg_type=get_enum_type(ServiceKind), help='Specify if the service is stateless or stateful.') 432 # Stateful arguments 433 c.argument('min_replica_set_size', options_list=['--min-replica-set-size', '--min-replica'], help='Specify the min replica set size for the stateful service.') 434 c.argument('target_replica_set_size', options_list=['--target-replica-set-size', '--target-replica'], help='Specify the target replica set size for the stateful service.') 435 c.argument('has_persisted_state', arg_type=get_three_state_flag(), 436 help='Determines whether this is a persistent service which stores states on the local disk. If it is then the value of this property is true, if not it is false.') 437 c.argument('service_placement_time_limit', options_list=['--service-placement-time-limit', '--plcmt-time-limit'], 438 help='Specify the duration for which replicas can stay InBuild before reporting that build is stuck, represented in ISO 8601 format "hh:mm:ss".') 439 c.argument('stand_by_replica_keep_duration', options_list=['--stand-by-replica-keep-duration', '--stand-by-keep-duration', '--keep-duration'], 440 help='Specify the definition on how long StandBy replicas should be maintained before being removed, represented in ISO 8601 format "hh:mm:ss".') 441 c.argument('quorum_loss_wait_duration', options_list=['--quorum-loss-wait-duration', '--quorum-loss-wait'], 442 help='Specify the maximum duration for which a partition is allowed to be in a state of quorum loss, represented in ISO 8601 format "hh:mm:ss".') 443 c.argument('replica_restart_wait_duration', options_list=['--replica-restart-wait-duration', '--replica-restart-wait'], 444 help='Specify the duration between when a replica goes down and when a new replica is created, represented in ISO 8601 format "hh:mm:ss".') 445 # Stateless arguments 446 c.argument('instance_count', help='Specify the instance count for the stateless service. If -1 is used, it means it will run on all the nodes.') 447 c.argument('min_instance_count', help='Specify the minimum number of instances that must be up to meet the EnsureAvailability safety check during operations like upgrade or deactivate node. The actual number that is used is max( MinInstanceCount, ceil( MinInstancePercentage/100.0 * InstanceCount) ). Note, if InstanceCount is set to -1, during MinInstanceCount computation -1 is first converted into the number of nodes on which the instances are allowed to be placed according to the placement constraints on the service.') 448 c.argument('min_instance_percentage', options_list=['--min-instance-percentage', '--min-inst-pct'], 449 help='Specify the minimum percentage of InstanceCount that must be up to meet the EnsureAvailability safety check during operations like upgrade or deactivate node. The actual number that is used is max( MinInstanceCount, ceil( MinInstancePercentage/100.0 * InstanceCount) ). Note, if InstanceCount is set to -1, during MinInstancePercentage computation, -1 is first converted into the number of nodes on which the instances are allowed to be placed according to the placement constraints on the service. Allowed values are from 0 to 100.') 450 # Partition arguments 451 c.argument('partition_scheme', arg_type=get_enum_type(PartitionScheme), 452 help='Specify what partition scheme to use. ' 453 'Singleton partitions are typically used when the service does not require any additional routing. ' 454 'UniformInt64 means that each partition owns a range of int64 keys. ' 455 'Named is usually for services with data that can be bucketed, within a bounded set. Some common examples of data fields used as named partition keys would be regions, postal codes, customer groups, or other business boundaries.') 456 c.argument('partition_count', 457 help='Specify the number of partitions. This is only used with UniformInt64 partition scheme.') 458 c.argument('low_key', 459 help='Specify the lower bound of the partition key range that should be split between the partition ‘Count’ This is only used with UniformInt64 partition scheme.') 460 c.argument('high_key', 461 help='Specify the upper bound of the partition key range that should be split between the partition ‘Count’ This is only used with UniformInt64 partition scheme.') 462 c.argument('partition_names', arg_type=partition_names) 463 464 with self.argument_context('sf managed-service update', validator=validate_update_managed_service) as c: 465 c.argument('default_move_cost', arg_type=get_enum_type(MoveCost), 466 help='Specify the default cost for a move. Higher costs make it less likely that the Cluster Resource Manager will move the replica when trying to balance the cluster.') 467 c.argument('placement_constraints', 468 help='Specify the placement constraints as a string. Placement constraints are boolean expressions on node properties and allow for restricting a service to particular nodes based on the service requirements. For example, to place a service on nodes where NodeType is blue specify the following: \"NodeColor == blue)\".') 469 # Stateful arguments 470 c.argument('min_replica_set_size', options_list=['--min-replica-set-size', '--min-replica'], help='Specify the min replica set size for the stateful service.') 471 c.argument('target_replica_set_size', options_list=['--target-replica-set-size', '--target-replica'], help='Specify the target replica set size for the stateful service.') 472 c.argument('service_placement_time_limit', options_list=['--service-placement-time-limit', '--plcmt-time-limit'], 473 help='Specify the duration for which replicas can stay InBuild before reporting that build is stuck, represented in ISO 8601 format "hh:mm:ss".') 474 c.argument('stand_by_replica_keep_duration', options_list=['--stand-by-replica-keep-duration', '--stand-by-keep-duration', '--keep-duration'], 475 help='Specify the definition on how long StandBy replicas should be maintained before being removed, represented in ISO 8601 format "hh:mm:ss".') 476 c.argument('quorum_loss_wait_duration', options_list=['--quorum-loss-wait-duration', '--quorum-loss-wait'], 477 help='Specify the maximum duration for which a partition is allowed to be in a state of quorum loss, represented in ISO 8601 format "hh:mm:ss".') 478 c.argument('replica_restart_wait_duration', options_list=['--replica-restart-wait-duration', '--replica-restart-wait'], 479 help='Specify the duration between when a replica goes down and when a new replica is created, represented in ISO 8601 format "hh:mm:ss".') 480 # Stateless arguments 481 c.argument('instance_count', help='Specify the instance count for the stateless service. If -1 is used, it means it will run on all the nodes.') 482 c.argument('min_instance_count', help='Specify the minimum number of instances that must be up to meet the EnsureAvailability safety check during operations like upgrade or deactivate node. The actual number that is used is max( MinInstanceCount, ceil( MinInstancePercentage/100.0 * InstanceCount) ). Note, if InstanceCount is set to -1, during MinInstanceCount computation -1 is first converted into the number of nodes on which the instances are allowed to be placed according to the placement constraints on the service.') 483 c.argument('min_instance_percentage', options_list=['--min-instance-percentage', '--min-inst-pct'], 484 help='Specify the minimum percentage of InstanceCount that must be up to meet the EnsureAvailability safety check during operations like upgrade or deactivate node. The actual number that is used is max( MinInstanceCount, ceil( MinInstancePercentage/100.0 * InstanceCount) ). Note, if InstanceCount is set to -1, during MinInstancePercentage computation, -1 is first converted into the number of nodes on which the instances are allowed to be placed according to the placement constraints on the service. Allowed values are from 0 to 100.') 485 486 with self.argument_context('sf managed-service correlation-scheme create', validator=validate_create_managed_service_correlation) as c: 487 c.argument('correlated_service_name', options_list=['--correlated-service-name', '--correlated-name'], 488 help='Specify the Arm Resource ID of the service that the correlation relationship is established with.') 489 c.argument('scheme', help='Specify the ServiceCorrelationScheme which describes the relationship between this service and the service specified via correlated_service_name.') 490 491 with self.argument_context('sf managed-service correlation-scheme update', validator=validate_update_managed_service_correlation) as c: 492 c.argument('correlated_service_name', options_list=['--correlated-service-name', '--correlated-name'], 493 help='Specify the Arm Resource ID of the service that the correlation relationship is established with.') 494 c.argument('scheme', help='Specify the ServiceCorrelationScheme which describes the relationship between this service and the service specified via correlated_service_name.') 495 496 with self.argument_context('sf managed-service correlation-scheme delete') as c: 497 c.argument('correlated_service_name', options_list=['--correlated-service-name', '--correlated-name'], 498 help='Specify the Arm Resource ID of the service that the correlation relationship is established with.') 499 500 with self.argument_context('sf managed-service load-metrics create', validator=validate_create_managed_service_load_metric) as c: 501 c.argument('metric_name', help='Specify the name of the metric.') 502 c.argument('weight', help='Specify the service load metric relative weight, compared to other metrics configured for this service, as a number.') 503 c.argument('primary_default_load', help='Specify the default amount of load, as a number, that this service creates for this metric when it is a Primary replica. Used only for Stateful services.') 504 c.argument('secondary_default_load', help='Specify the default amount of load, as a number, that this service creates for this metric when it is a Secondary replica. Used only for Stateful services.') 505 c.argument('default_load', help='Specify the default amount of load, as a number, that this service creates for this metric. Used only for Stateless services.') 506 507 with self.argument_context('sf managed-service load-metrics update', validator=validate_update_managed_service_load_metric) as c: 508 c.argument('metric_name', help='Specify the name of the metric.') 509 c.argument('weight', help='Specify the service load metric relative weight, compared to other metrics configured for this service, as a number.') 510 c.argument('primary_default_load', help='Specify the default amount of load, as a number, that this service creates for this metric when it is a Primary replica. Used only for Stateful services.') 511 c.argument('secondary_default_load', help='Specify the default amount of load, as a number, that this service creates for this metric when it is a Secondary replica. Used only for Stateful services.') 512 c.argument('default_load', help='Specify the default amount of load, as a number, that this service creates for this metric. Used only for Stateless services.') 513 514 with self.argument_context('sf managed-service load-metrics delete') as c: 515 c.argument('metric_name', help='Specify the name of the metric.') 516 517 518def paramToDictionary(values): 519 params = {} 520 for item in values: 521 key, value = item.split('=', 1) 522 params[key] = value 523 return params 524 525 526# pylint: disable=protected-access 527# pylint: disable=too-few-public-methods 528class AddAppParamsAction(argparse._AppendAction): 529 530 def __call__(self, parser, namespace, values, option_string=None): 531 try: 532 namespace.application_parameters = paramToDictionary(values) 533 except ValueError: 534 raise CLIError('usage error: {} KEY=VALUE [KEY=VALUE ...]'.format(option_string)) 535 536 537# pylint: disable=protected-access 538# pylint: disable=too-few-public-methods 539class AddServiceTypeHealthPolicyAction(argparse._AppendAction): 540 541 def __call__(self, parser, namespace, values, option_string=None): 542 try: 543 namespace.service_type_health_policy_map = paramToDictionary(values) 544 except ValueError: 545 raise CLIError('usage error: {} KEY=VALUE1,VALUE2,VALUE3 [KEY=VALUE1,VALUE2,VALUE3 ...]'.format(option_string)) 546 547 548class ManagedClusterClientCertAddAction(argparse._AppendAction): 549 550 def __call__(self, parser, namespace, values, option_string=None): 551 ClientCertificate = namespace._cmd.get_models('ClientCertificate') 552 try: 553 kwargs = paramToDictionary(values.split()) 554 return ClientCertificate(**kwargs) 555 except ValueError: 556 raise CLIError('usage error: {} KEY=VALUE [KEY=VALUE ...]'.format(option_string)) 557 558 559# pylint: disable=protected-access 560# pylint: disable=too-few-public-methods 561class AddNodeTypeCapacityAction(argparse._AppendAction): 562 563 def __call__(self, parser, namespace, values, option_string=None): 564 try: 565 namespace.capacity = paramToDictionary(values) 566 except ValueError: 567 raise CLIError('usage error: {} KEY=VALUE [KEY=VALUE ...]'.format(option_string)) 568 569 570# pylint: disable=protected-access 571# pylint: disable=too-few-public-methods 572class AddNodeTypePlacementPropertyAction(argparse._AppendAction): 573 574 def __call__(self, parser, namespace, values, option_string=None): 575 try: 576 namespace.placement_property = paramToDictionary(values) 577 except ValueError: 578 raise CLIError('usage error: {} KEY=VALUE [KEY=VALUE ...]'.format(option_string)) 579