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

Estebanreyl/admin enabled fixes #341

Merged

Conversation

estebanreyl
Copy link

@estebanreyl estebanreyl commented Jul 31, 2018

-Fixes #336, fixes #359

  • Eliminated bugs related to failing to fetch a single container registry for any particular reason.

  • Eliminated the need for registries to be admin enabled at all to be listed in Azure Container Registries explorer.

  • Provided a fix for launching to app services after the aforementioned change and an overall fix due to a very obscure bug that prevented launches when an available resource group had a location outside of the locations available for a subscription.

  • As a side note rather than a feature, speed for container registries has further increased as a result of admin enabled elimination.

Esteban Rey added 3 commits July 30, 2018 09:51
…es deployment

-Additionally included code for future updates of Azure  app services when non admin enabled registries are allowed.
node.userName = element.userName;
node.created = moment(new Date(JSON.parse(manifest.history[0].v1Compatibility).created)).fromNow();
imageNodes.push(node);
let data: any;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

looks data is only used in try-catch block?

@@ -172,9 +177,16 @@ class ResourceGroupStep extends WebAppCreatorStepBase {
resourceGroups = results[0];
locations = results[1];
resourceGroups.forEach(rg => {
let location: string;
try {
location = `(${locations.find(l => l.name.toLowerCase() === rg.location.toLowerCase()).displayName})`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

` [](start = 31, length = 1)

is backtick needed here?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, that was a leftover from before

@@ -172,9 +177,16 @@ class ResourceGroupStep extends WebAppCreatorStepBase {
resourceGroups = results[0];
locations = results[1];
resourceGroups.forEach(rg => {
let location: string;
try {
location = `(${locations.find(l => l.name.toLowerCase() === rg.location.toLowerCase()).displayName})`;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

location [](start = 20, length = 8)

You might want to change the name to locationDisplayName or locationDescription.

this._serverPassword = context.password;
this._serverUserName = context.userName;
}
if (context instanceof AzureImageNode) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

if [](start = 8, length = 2)

else if to avoid additional check

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

you also might to log if context is neither DockerHubImageNode or AzureImageNode


In reply to: 206671989 [](ancestors = 206671989)

@@ -447,6 +468,12 @@ class WebsiteStep extends WebAppCreatorStepBase {
await vscode.window.showWarningMessage(nameAvailability.message);
}
}
try {
await this.loginCredentials();
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

loginCredentials [](start = 23, length = 16)

Can you rename to something like acquireRegistryLoginCredentials? It's not clear from the name what credentials are about since it's in WebsiteStep class.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That seems reasonable to me

}
}
await vscode.window.showErrorMessage('Azure App service currently only supports running images from Azure Container Registries with admin enabled');
throw new Error(('Admin not enabled'));
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Admin [](start = 26, length = 5)

Azure Container Registry Admin is not enabled.

// Un-Comment when Admin enabled is not required
// let convertedCredentials: { password: string, username: string } = await this.getSessionCredentials();
// this._serverUserName = convertedCredentials.password;
// this._serverPassword = convertedCredentials.username;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the support of service principal ready?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It can be done on our side and it will probably be added on a per feature thing as we add functionality such as pull and push but app services itself does not seem to support them at the moment.

Copy link
Member

@northtyphoon northtyphoon left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🕐

Esteban Rey added 2 commits July 31, 2018 13:56
Removed methods that would be used if App services started supporting non admin enabled registries. These were removed to avoid confusions.
@estebanreyl
Copy link
Author

@sajayantony

import WebSiteManagementClient = require('azure-arm-website');
import * as fs from 'fs';
import * as path from 'path';
import * as request from 'request-promise';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import, remove.

import * as vscode from 'vscode';
import * as WebSiteModels from '../../node_modules/azure-arm-website/lib/models';
import { reporter } from '../../telemetry/telemetry';
import { AzureAccount, AzureLoginStatus, AzureSession } from '../../typings/azure-account.api';

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

unused import, remove.

this._serverUserName = creds.username;
return;
} catch (error) {
vscode.window.showErrorMessage(error.message);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

await?

Copy link
Author

@estebanreyl estebanreyl Aug 1, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this case await pauses execution until the user clicks to exit the error message window which is not a guarantee, additionally it makes no difference as the error is shown when ready and execution ends nonetheless.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We shouldn't need to both show a message and throw an error - the error should get displayed by the caller, is that not happening?

One issue is that this code was copied from elsewhere and we need to actually update it to use the shared code in https://github.com/Microsoft/vscode-azuretools, so maybe that needs to be done before integrating these changes.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This does not happen indeed, in fact there is no visible information about an error occurring if I propagate it all the way to the code I didn't write, although I could modify it to act in this way. Additionally, while I agree that we should update the original code for the whole deploy to app services, this PR is essentially an important bugfix which by the nature of the bug broke the existing app services functionality and thus required me to solve a small number of issues on that side to keep existing functionality post the PR. Would it not be best to integrate this functional code with the added bugfixes before attempting the necessary refactoring that appears to me as less pressing?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Makes sense. Added #358 to track that we want telemetry for such failures.

BTW, with my merge of #350, the caller should now be catching and handling (telemetry and error messages) anything you throw from commands. That should now be the correct way to handle things (let exceptions bubble up), except for cases like there where you need to continue.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sweet, Ill update accordingly


if (this._registry.adminUserEnabled) {
try {
let creds = await client.registries.listCredentials(resourceGroup, this._registry.name);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

move this to _util file inside a new function listRegistryCredentials ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

While this makes sense to me conceptually I am honestly having trouble with how to go about it, I could create a function say in azureUtils that takes an azure account, a subscription, and a registry to do this and while this seems reasonable, and maybe I am biased because of PR #332 , it doesn't seem to follow the existing pattern of this file and seems more like something to add to my unified credentials that would look odd anywhere else. It seems most reasonable to me to add it to the Unified credentials branch and leave this like it is, at some point it may be good to refactor this code around that other branch however but that goes for the overall file,

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, you can consider refactoring in the other branch. Also, you are right about the overall file in general.

Copy link

@ankurkhemani ankurkhemani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

let locationDisplayName: string;
try {
locationDisplayName = locations.find(l => l.name.toLowerCase() === rg.location.toLowerCase()).displayName;
} catch (error) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What error is occurring? Null ref? I'd rather avoid exceptions than catch and recover.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exactly, I could also store the result in a variable and check if it is available before assigning the value, say :
const location : Location = locations.find(l => l.name.toLowerCase() === rg.location.toLowerCase());

if(location){
locationDisplayName = location.displayName;
}else{
...
}

Alternatively I could try changing the location acquisition by subscription strategy and do so by overall locations which would prevent the error in the grand majority of the very rare cases although I suspect this would have problems in cases when there is a private azure location. Also, is there a specific reason as to prefer avoiding rather than catch and recover?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, that's preferable, thanks. Exceptions should be for things that are exceptional. Really you should never see a null ref exception, it's completely avoidable with proper checking. Having the location not match is a fully normal event that we just need to handle.

(Also, having a bunch of exceptions throw all over the place is darn annoying when you're trying to debug.)

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good, I'll try to follow that paradigm.

'registries': regs
});
} catch (error) {
vscode.window.showErrorMessage(error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let caller show error.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

and other places.

Let me know if the caller is not showing the error. There are further changes around command registration and error handling that I intend to make.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean handle this within asyncpool? I could do that so its a single location for this.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's keep it as is for now.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Except change to show parseError(error).message

imageNodes.push(node);

} catch (error) {
vscode.window.showErrorMessage(error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm trying to understand where you expect the error to be coming from. Is it from the parse, or the request? I don't see lines 209-213 causing an error.

If you're surer of where the error is expected to come from, it might be better to wrap just that line in a catch.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I anticipate it would come from the request , that seems reasonable, I think I just moved it to the try to avoid having an additional check in case it failed but it is more unreadable.

await this.acquireRegistryLoginCredentials();
} catch (error) {
//Admin was not enabled, cannot proceed
throw new Error(('Admin not enabled'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: double parens

await this.acquireRegistryLoginCredentials();
} catch (error) {
//Admin was not enabled, cannot proceed
throw new Error(('Admin not enabled'));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You're making an assumption about why this failed - it could fail for any number of reasons, including network out - this message could mislead users.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should simply not have the try/catch here - let the exception bubble up (sync up with my PR I mentioned above).

throw new Error(('Azure Container Registry Admin is not enabled'));
}
}
vscode.window.showErrorMessage('Azure App service currently only supports running images from Azure Container Registries with admin enabled');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Again, you can't make that assumption. Does the error that you get back in this scenario have a particular code that you can check for in order to throw a more specific error in this case?

Copy link
Author

@estebanreyl estebanreyl Aug 6, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I could check for whether the list failed because of admin not enabled specifically and then throw accordingly. As for the Azure App service does not support... etc I have to make the assumption as the only way to identify this error is to go into the azure portal and note that your web app fails due to admin not being enabled, no error is actually given to the user from the API as long as credentials are valid.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm confused - you're throwing this error specifically when you get an exception. Can you not check for the error code?

throw new Error(('Azure Container Registry Admin is not enabled'));
}
}
vscode.window.showErrorMessage('Azure App service currently only supports running images from Azure Container Registries with admin enabled');
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just throw (use the longer message), don't show a message.

Esteban Rey added 2 commits August 7, 2018 16:13
…es deployment

-Additionally included code for future updates of Azure  app services when non admin enabled registries are allowed.
Esteban Rey added 7 commits August 7, 2018 16:13
@estebanreyl
Copy link
Author

Ive updated the error handling, nonetheless, bubbling up all the way to the item in command registration does not seem to yield either the telemetry logging (based on console output I've seen) or an error for the user. Note I have rebased my branch with master. I am manually outputting the error to the user however at the highest level possible, let me know if this is better.

@StephenWeatherford
Copy link
Contributor

StephenWeatherford commented Aug 9, 2018

@estebanreyl Okay, I see the problem. I've pushed a fix into your branch.

}
});
} catch (error) {
vscode.window.showErrorMessage(error);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

vscode.window.showErrorMessage(parseError(error).message);

@StephenWeatherford
Copy link
Contributor

Okay, just a couple minor changes left. The wizard code has much improved since it was copied into this repo. Thx.

@estebanreyl
Copy link
Author

Okay, I think its ready, just fixed the merge conflicts as well.

@StephenWeatherford
Copy link
Contributor

What happened to my error-handling fix (setting output channel) from b28431b?

@estebanreyl
Copy link
Author

estebanreyl commented Aug 10, 2018

Oh I was confused about that, Ill add it now. Think I removed it on the merge by mistake.

@estebanreyl
Copy link
Author

@StephenWeatherford I added the set output channel again.

@StephenWeatherford StephenWeatherford merged commit 1d98281 into microsoft:master Aug 11, 2018
@microsoft microsoft locked and limited conversation to collaborators Oct 27, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Show non-admin-enabled Azure container registries in tree Error when listing Azure Registries
5 participants