Skip to content

Commit 34421fb

Browse files
Merge pull request #1 from peterbom/feature/create-cluster-ux-builder
2 parents 9ccda56 + 04532be commit 34421fb

File tree

5 files changed

+127
-243
lines changed

5 files changed

+127
-243
lines changed

src/panels/CreateClusterPanel.ts

Lines changed: 51 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,23 @@
1-
import { ContainerServiceClient } from "@azure/arm-containerservice";
2-
import { ResourceGroup as ARMResourceGroup, Deployment, ResourceManagementClient } from "@azure/arm-resources";
1+
import { ContainerServiceClient, KubernetesVersion } from "@azure/arm-containerservice";
2+
import { ResourceGroup as ARMResourceGroup, ResourceManagementClient } from "@azure/arm-resources";
33
import { RestError } from "@azure/storage-blob";
44
import { ISubscriptionContext } from "@microsoft/vscode-azext-utils";
55
import { Uri, window } from "vscode";
6-
import meta from '../../package.json';
6+
import meta from "../../package.json";
77
import { getResourceGroupList } from "../commands/utils/clusters";
88
import { failed, getErrorMessage } from "../commands/utils/errorable";
99
import { isObject } from "../commands/utils/runtimeTypes";
1010
import { MessageHandler, MessageSink } from "../webview-contract/messaging";
11-
import { InitialState, ProgressEventType, ToVsCodeMsgDef, ToWebViewMsgDef, ResourceGroup as WebviewResourceGroup } from "../webview-contract/webviewDefinitions/createCluster";
11+
import {
12+
InitialState,
13+
Preset,
14+
ProgressEventType,
15+
ToVsCodeMsgDef,
16+
ToWebViewMsgDef,
17+
ResourceGroup as WebviewResourceGroup,
18+
} from "../webview-contract/webviewDefinitions/createCluster";
1219
import { BasePanel, PanelDataProvider } from "./BasePanel";
13-
import { ClusterSpec, ClusterSpecBuilder } from "./utilities/ClusterSpecCreationBuilder";
20+
import { ClusterSpec, ClusterDeploymentBuilder } from "./utilities/ClusterSpecCreationBuilder";
1421

1522
export class CreateClusterPanel extends BasePanel<"createCluster"> {
1623
constructor(extensionUri: Uri) {
@@ -27,8 +34,8 @@ export class CreateClusterDataProvider implements PanelDataProvider<"createClust
2734
readonly resourceManagementClient: ResourceManagementClient,
2835
readonly containerServiceClient: ContainerServiceClient,
2936
readonly portalUrl: string,
30-
readonly subscriptionContext: ISubscriptionContext
31-
) { }
37+
readonly subscriptionContext: ISubscriptionContext,
38+
) {}
3239

3340
getTitle(): string {
3441
return `Create Cluster in ${this.subscriptionContext.subscriptionDisplayName}`;
@@ -106,14 +113,23 @@ export class CreateClusterDataProvider implements PanelDataProvider<"createClust
106113
group: WebviewResourceGroup,
107114
location: string,
108115
name: string,
109-
preset: string,
116+
preset: Preset,
110117
webview: MessageSink<ToWebViewMsgDef>,
111118
) {
112119
if (isNewResourceGroup) {
113120
await createResourceGroup(group, webview, this.resourceManagementClient);
114121
}
115122

116-
await createCluster(group, location, name, preset, webview, this.containerServiceClient, this.resourceManagementClient, this.subscriptionContext);
123+
await createCluster(
124+
group,
125+
location,
126+
name,
127+
preset,
128+
webview,
129+
this.containerServiceClient,
130+
this.resourceManagementClient,
131+
this.subscriptionContext,
132+
);
117133
}
118134
}
119135

@@ -151,11 +167,11 @@ async function createCluster(
151167
group: WebviewResourceGroup,
152168
location: string,
153169
name: string,
154-
preset: string,
170+
preset: Preset,
155171
webview: MessageSink<ToWebViewMsgDef>,
156172
containerServiceClient: ContainerServiceClient,
157173
resourceManagementClient: ResourceManagementClient,
158-
subscriptionContext: ISubscriptionContext
174+
subscriptionContext: ISubscriptionContext,
159175
) {
160176
const operationDescription = `Creating cluster ${name}`;
161177
webview.postProgressUpdate({
@@ -165,8 +181,11 @@ async function createCluster(
165181
});
166182

167183
// kubernetes version is required to create a cluster via deployments
168-
const kubernetesVersion = await containerServiceClient.managedClusters.listKubernetesVersions(location);
169-
if (!kubernetesVersion || !kubernetesVersion.values || kubernetesVersion.values.length === 0 || !kubernetesVersion.values[0].version) {
184+
const kubernetesVersionsResult = await containerServiceClient.managedClusters.listKubernetesVersions(location);
185+
const kubernetesVersions = kubernetesVersionsResult.values || [];
186+
const hasDefaultVersion = kubernetesVersions.some(isDefaultK8sVersion);
187+
const [kubernetesVersion] = hasDefaultVersion ? kubernetesVersions.filter(isDefaultK8sVersion) : kubernetesVersions;
188+
if (!kubernetesVersion?.version) {
170189
window.showErrorMessage(`No Kubernetes versions available for location ${location}`);
171190
webview.postProgressUpdate({
172191
event: ProgressEventType.Failed,
@@ -181,15 +200,24 @@ async function createCluster(
181200
name,
182201
resourceGroupName: group.name,
183202
subscriptionId: subscriptionContext.subscriptionId,
184-
kubernetesVersion: kubernetesVersion.values[0].version, // selecting the latest version since versions come in descending order
185-
username: subscriptionContext.userId
203+
kubernetesVersion: kubernetesVersion.version, // selecting the latest version since versions come in descending order
204+
username: subscriptionContext.userId,
186205
};
187206

188-
const deploymentSpec = getManagedClusterSpec(clusterSpec, preset);
207+
// Create a unique deployment name.
208+
const deploymentName = `${name}-${Math.random().toString(36).substring(5)}`;
209+
const deploymentSpec = new ClusterDeploymentBuilder()
210+
.buildCommonParameters(clusterSpec)
211+
.buildTemplate(preset)
212+
.getDeployment();
189213

190214
try {
191-
const poller = await resourceManagementClient.deployments.beginCreateOrUpdate(group.name, name, deploymentSpec);
192-
poller.onProgress(state => {
215+
const poller = await resourceManagementClient.deployments.beginCreateOrUpdate(
216+
group.name,
217+
deploymentName,
218+
deploymentSpec,
219+
);
220+
poller.onProgress((state) => {
193221
if (state.status === "canceled") {
194222
webview.postProgressUpdate({
195223
event: ProgressEventType.Cancelled,
@@ -227,20 +255,6 @@ async function createCluster(
227255
}
228256
}
229257

230-
function getManagedClusterSpec(clusterSpec: ClusterSpec, preset: string): Deployment {
231-
const specBuilder: ClusterSpecBuilder = new ClusterSpecBuilder();
232-
switch (preset) {
233-
case "dev":
234-
return specBuilder.buildDevTestClusterSpec(clusterSpec);
235-
case "economy":
236-
return specBuilder.buildProdEconomyClusterSpec(clusterSpec)
237-
case "enterprise":
238-
return specBuilder.buildProdEnterpriseClusterSpec(clusterSpec)
239-
default:
240-
return specBuilder.buildProdStandardClusterSpec(clusterSpec)
241-
}
242-
}
243-
244258
function getInvalidTemplateErrorMessage(ex: InvalidTemplateDeploymentRestError): string {
245259
const innerDetails = ex.details.error?.details || [];
246260
if (innerDetails.length > 0) {
@@ -275,4 +289,8 @@ function isInvalidTemplateDeploymentError(ex: unknown): ex is InvalidTemplateDep
275289

276290
function isRestError(ex: unknown): ex is RestError {
277291
return isObject(ex) && ex.constructor.name === "RestError";
278-
}
292+
}
293+
294+
function isDefaultK8sVersion(version: KubernetesVersion): boolean {
295+
return "isDefault" in version && version.isDefault === true;
296+
}

0 commit comments

Comments
 (0)