Conversation
Codecov Report
@@ Coverage Diff @@
## master #2834 +/- ##
==========================================
+ Coverage 63.11% 63.19% +0.07%
==========================================
Files 464 466 +2
Lines 25916 26125 +209
Branches 3948 3995 +47
==========================================
+ Hits 16358 16509 +151
- Misses 8507 8536 +29
- Partials 1051 1080 +29
Continue to review full report at Codecov.
|
tjprescott
left a comment
There was a problem hiding this comment.
Main concerns:
- The api conditional check needs to be improved.
- I don't understand when it is appropriate to use get_sdk_attr and get_versioned_models. They seem to do the same thing and it seems they are used interchangeably.
- How are we testing this?? Are we to expect that once merged, these services will work correctly against Stack and other clouds?
|
|
||
| def has_endpoint_set(self, endpoint_name): | ||
| try: | ||
| getattr(self, endpoint_name) |
There was a problem hiding this comment.
Can't this just be simplified to
return hasattr(self, endpoint_name)| self.is_active = is_active | ||
|
|
||
| def __str__(self): | ||
| o = {} |
There was a problem hiding this comment.
Could be simplfied:
o = {
'profile': self.profile,
...
}|
|
||
| def model_choice_list(resource_type, model_name): | ||
| model = get_versioned_models(resource_type, model_name) | ||
| return enum_choice_list(model) if model else {} |
There was a problem hiding this comment.
Should this return [] as the else since it's an choice list?
There was a problem hiding this comment.
enum_choice_list returns an empty dict so it made sense to do the same here.
Actually since the usage is **model_choice_list(), it has to be a dict, not a list.
$ python
>>> val = {'n': 1}
>>>
>>> def f(**kwargs):
... print(kwargs)
...
>>> f(**val)
{'n': 1}
>>>
>>> l = []
>>> f(**l)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: f() argument after ** must be a mapping, not list
>>>
| try: | ||
| return getattr(mod, enum_val_name).value | ||
| except AttributeError: | ||
| return None |
There was a problem hiding this comment.
I'm still concerned about trying to debug a mysterious typo with all of these things being strings. If we were to issue a logger.error, how much spam would we get in --debug for this?
There was a problem hiding this comment.
Hmm yes could do that.
Does this work?
logger.debug('Unable to get param default %s.%s for %s', enum_name, enum_val_name, resource_type)
In logs, it would look like:
Unable to get param default Kind.storage for ResourceType.MGMT_STORAGE
There was a problem hiding this comment.
Or Skipping param default Kind.storage for ResourceType.MGMT_STORAGE
There was a problem hiding this comment.
That's fine--my main question is, does this introduce a ton of spam to --debug? I guess it wouldn't if you were mainly developing against latest, in which case, it would be useful.
There was a problem hiding this comment.
Currently, it only appears once. Don't expect it to be too much.
| raise APIVersionException(resource_type, api_profile) | ||
|
|
||
|
|
||
| def get_client_class(resource_type): |
There was a problem hiding this comment.
For this change, exposing the minimum public surface area is important. Right now these all show up as public. Can we update the ones that we don't intend to have used by command authors to use the leading _?
There was a problem hiding this comment.
All the methods/attributes/properties in this file are public.
There was a problem hiding this comment.
IMO there are way too many public methods then. When people ask "how do I support multiple versions", I would have no idea what to tell them other than to ask you.
There was a problem hiding this comment.
This whole shared.py file should not be used by anyone else.
azure/cli/core/profiles/__init__.py is what will be used by others and that has the following public methods: get_api_version, get_sdk, get_versioned_sdk_path each of which has their use.
I have renamed shared.py to _shared.py to make this clearer.
|
|
||
| def cloud_storage_account_service_factory(kwargs): | ||
| from azure.storage import CloudStorageAccount | ||
| CloudStorageAccount = get_sdk_attr('azure.multiapi.storage#CloudStorageAccount') |
There was a problem hiding this comment.
How is "get_sdk_attr" different from "get_versioned_models"?? It seems like you can do the same thing with either.
There was a problem hiding this comment.
Yes they are similar. Looking at combining them into one.
| TablePayloadFormat = get_sdk_attr('azure.multiapi.storage.table#TablePayloadFormat') | ||
| QueueService = get_sdk_attr('azure.multiapi.storage.queue#QueueService') | ||
| QueuePermissions = get_sdk_attr('azure.multiapi.storage.queue.models#QueuePermissions') | ||
| PublicAccess = get_sdk_attr('azure.multiapi.storage.blob.models#PublicAccess') |
There was a problem hiding this comment.
Why are you not using the "get_versioned_models" to eliminate all these copy-paste redundancy?
| register_cli_argument('storage account {}'.format(item), 'encryption', nargs='+', help='Specifies which service(s) to encrypt.', validator=validate_encryption, **enum_choice_list(list(EncryptionServices._attribute_map.keys()))) # pylint: disable=protected-access | ||
| register_cli_argument('storage account {}'.format(item), 'sku', help='The storage account SKU.', **model_choice_list(ResourceType.MGMT_STORAGE, 'SkuName')) | ||
| es_model = get_versioned_models(ResourceType.MGMT_STORAGE, 'EncryptionServices') | ||
| if es_model: |
There was a problem hiding this comment.
This seems like an implicit way of saying "if API version > blah". I would highly recommend we be specific here and call out API version explicitly.
Also, why are we using "get_versioned_models" instead of "get_sdk_attr"?
|
|
||
| if get_api_version(ResourceType.MGMT_STORAGE) in ['2015-06-15']: | ||
| cli_command(__name__, 'storage account create', custom_path + 'create_storage_account_with_account_type') | ||
| else: |
There was a problem hiding this comment.
So any API versions lower or greater than this should use the newer method?
There was a problem hiding this comment.
There aren't versions lower than 2015-06-15 so it'd be only newer API versions.
| cli_command(__name__, 'image show', mgmt_path.format(op_var, op_class, 'get'), cf_images, exception_handler=empty_on_404) | ||
| cli_command(__name__, 'image delete', mgmt_path.format(op_var, op_class, 'delete'), cf_images) | ||
|
|
||
| if get_api_version(ResourceType.MGMT_COMPUTE) in ['2016-04-30-preview']: |
There was a problem hiding this comment.
What about VM and VMSS create? Managed disks didn't exist before this API version. I can't image those commands would work as is. I don't see different versions of those commands like Storage Account create.
There was a problem hiding this comment.
VM and VMSS create don't fully support older API versions.
This would be part of #2272.
yugangw-msft
left a comment
There was a problem hiding this comment.
Left one extra comment. Thanks for the great effort!
| # Build VMSS | ||
| vmss_properties = { | ||
| 'overprovision': overprovision, | ||
| 'singlePlacementGroup': single_placement_group, |
There was a problem hiding this comment.
We should keep this, but we need to conditionly to add this if the VM's api-version is >= 2016-04-30-preview
There was a problem hiding this comment.
I thought this PR was not intended to make VM/VMSS create "profile compliant"?
There was a problem hiding this comment.
I am fine with different options to address it. But since this PR aims to get into master, then we should not just drop the property, as this clearly makes creating large scale-set no longer work.
There was a problem hiding this comment.
Oh, yes, definitely. great catch!
- Use published SDKs available on PyPI now - Loading versioned models for network and resources, object model initialization changes for 2015-* profile (#2812) - Custom ca certs - Setting Requests_ca_bundle environment variable (#2813) - changes for 2015-* profile to work against azure stack (#2794) - Loading versioned Resources client and versioned models in VM - Updating the supported api-versions for the 2015-example profile - Fixing network, compute sdk load errors for 2015-* profiles (+5 squashed commit) - Support multi-API versioned Storage dataplane SDK (#2796) - Support multi-versioned mgmt SDK (#2526) - Fix token "management" endpoint is being used in the place of "activeDirectoryResourceId" (#2410) - Add profile switching params and profile listing command (#2398) - Use ARM 'resource manager' endpoint if ASM 'management' endpoint not set
154f99f to
3797a17
Compare
|
@tjprescott Can you take another look? |
1 requires an api ordering which is currently not known. |
Fix pylint and pep8 (+7 squashed commits) Squashed commits: [f1d4d52] Refactor to use joint method [f43785a] Use generic method to get versioned SDK attributes [2100dd2] Add log debug if enum default not found [5767f41] Add single_placement_group back in for vmss [05ca8bc] Revert a test change. It has been fixed in master. [cdf4211] Simplify str override method [281c755] Clarify use of getattr
c4842ac to
bef3a48
Compare
|
I'm still struggling with these issues:
|
| logger.debug("Current active cloud '%s'", CLOUD.name) | ||
| logger.debug(pformat(vars(CLOUD.endpoints))) | ||
| logger.debug(pformat(vars(CLOUD.suffixes))) | ||
| logger.debug(str(CLOUD)) |
There was a problem hiding this comment.
Unless the to string conversion includes a readable explanation of what it is, I would suggest print a more readable message like:
logger.debug('Current cloud is {}'.format(str(CLOUD)))There was a problem hiding this comment.
It looks like this:
{'endpoints': {'active_directory': 'https://login.microsoftonline.com',
'active_directory_graph_resource_id': 'https://graph.windows.net/',
'active_directory_resource_id': 'https://management.core.windows.net/',
'batch_resource_id': None,
'gallery': 'https://gallery.azure.com/',
'management': 'https://management.core.windows.net/',
'resource_manager': 'https://management.azure.com/',
'sql_management': 'https://management.core.windows.net:8443/'},
'is_active': True,
'name': 'AzureCloud',
'profile': '2016-sample',
'suffixes': {'azure_datalake_analytics_catalog_and_job_endpoint': 'azuredatalakeanalytics.net',
'azure_datalake_store_file_system_endpoint': 'azuredatalakestore.net',
'keyvault_dns': '.vault.azure.net',
'sql_server_hostname': '.database.windows.net',
'storage_endpoint': 'core.windows.net'}}
I've added a message though so at least it's possible to search for the string to find which line of code creates that log message.
| setattr(c.suffixes, option.replace('suffix_', ''), config.get(section, option)) | ||
| if c.profile is None: | ||
| # If profile isn't set, use latest | ||
| c.profile = 'latest' # pylint: disable=redefined-variable-type |
There was a problem hiding this comment.
will use setAttr avoid the the pylint error?
There was a problem hiding this comment.
yes that works. thanks for the suggestion!
|
@tjprescott |
tjprescott
left a comment
There was a problem hiding this comment.
LGTM! Thanks for putting up with me! 😁
|
merged 🎉 🍾 |
Closes #2578
Closes #2579
Closes #2577
This checklist is used to make sure that common guidelines for a pull request are followed.
General Guidelines
Command Guidelines
(see Authoring Command Modules)