Skip to content

Commit 3ecc806

Browse files
Merge pull request #6868 from microsoft/appservice-app-settings
[Task #1974373] Support edit app settings while deploy to Azure Web App
2 parents 18610e7 + 0ce58cf commit 3ecc806

File tree

30 files changed

+681
-350
lines changed

30 files changed

+681
-350
lines changed

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-appservice/src/main/java/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceComboBox.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,6 +71,7 @@ protected T convertAppServiceToConfig(final Supplier<T> supplier, AppServiceAppB
7171
config.setRuntime(appService.getRuntime());
7272
config.setRegion(appService.getRegion());
7373
config.setServicePlan(AppServicePlanConfig.fromResource(appService.getAppServicePlan()));
74+
config.setAppSettings(appService.getAppSettings());
7475
})).subscribe();
7576
return config;
7677
}

PluginsAndFeatures/azure-toolkit-for-intellij/azure-intellij-plugin-appservice/src/main/java/com/microsoft/azure/toolkit/intellij/legacy/appservice/AppServiceStreamingLogConsoleView.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,15 +27,16 @@ public class AppServiceStreamingLogConsoleView extends ConsoleViewImpl {
2727
public AppServiceStreamingLogConsoleView(@NotNull Project project, String resourceId) {
2828
super(project, true);
2929
this.isDisposed = false;
30+
this.setUpdateFoldingsEnabled(false);
3031
this.resourceId = resourceId;
3132
}
3233

3334
public void startStreamingLog(Flux<String> logStreaming) {
3435
if (!isActive()) {
3536
printlnToConsole(message("appService.logStreaming.hint.connect"), SYSTEM_OUTPUT);
3637
subscription = logStreaming.subscribeOn(Schedulers.boundedElastic())
37-
.doAfterTerminate(() -> printlnToConsole(message("appService.logStreaming.hint.disconnected"), SYSTEM_OUTPUT))
38-
.subscribe((log) -> printlnToConsole(log, NORMAL_OUTPUT));
38+
.doAfterTerminate(() -> printlnToConsole(message("appService.logStreaming.hint.disconnected"), SYSTEM_OUTPUT))
39+
.subscribe((log) -> printlnToConsole(log, NORMAL_OUTPUT));
3940
}
4041
}
4142

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<form xmlns="http://www.intellij.com/uidesigner/form/" version="1" bind-to-class="com.microsoft.azure.toolkit.intellij.legacy.appservice.table.AddAppSettingsDialog">
3+
<grid id="27dc6" binding="pnlRoot" layout-manager="GridLayoutManager" row-count="3" column-count="2" same-size-horizontally="false" same-size-vertically="false" hgap="-1" vgap="-1">
4+
<margin top="0" left="0" bottom="0" right="0"/>
5+
<constraints>
6+
<xy x="20" y="20" width="451" height="89"/>
7+
</constraints>
8+
<properties/>
9+
<border type="none"/>
10+
<children>
11+
<component id="a7673" class="javax.swing.JLabel" binding="lblName">
12+
<constraints>
13+
<grid row="0" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
14+
</constraints>
15+
<properties>
16+
<text value="Name:"/>
17+
</properties>
18+
</component>
19+
<vspacer id="1ceff">
20+
<constraints>
21+
<grid row="2" column="0" row-span="1" col-span="1" vsize-policy="6" hsize-policy="1" anchor="0" fill="2" indent="0" use-parent-layout="false"/>
22+
</constraints>
23+
</vspacer>
24+
<component id="d04e7" class="javax.swing.JLabel" binding="lblValue">
25+
<constraints>
26+
<grid row="1" column="0" row-span="1" col-span="1" vsize-policy="0" hsize-policy="0" anchor="8" fill="0" indent="0" use-parent-layout="false"/>
27+
</constraints>
28+
<properties>
29+
<text value="Value:"/>
30+
</properties>
31+
</component>
32+
<component id="3e900" class="com.microsoft.azure.toolkit.intellij.common.AzureTextInput" binding="txtName">
33+
<constraints>
34+
<grid row="0" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
35+
</constraints>
36+
<properties/>
37+
</component>
38+
<component id="2f5bb" class="com.microsoft.azure.toolkit.intellij.common.AzureTextInput" binding="txtValue">
39+
<constraints>
40+
<grid row="1" column="1" row-span="1" col-span="1" vsize-policy="3" hsize-policy="3" anchor="0" fill="1" indent="0" use-parent-layout="false"/>
41+
</constraints>
42+
<properties/>
43+
</component>
44+
</children>
45+
</grid>
46+
</form>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,100 @@
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+
package com.microsoft.azure.toolkit.intellij.legacy.appservice.table;
7+
8+
import com.microsoft.azure.toolkit.intellij.common.AzureDialog;
9+
import com.microsoft.azure.toolkit.intellij.common.AzureTextInput;
10+
import com.microsoft.azure.toolkit.lib.common.form.AzureForm;
11+
import com.microsoft.azure.toolkit.lib.common.form.AzureFormInput;
12+
import com.microsoft.azure.toolkit.lib.common.form.AzureValidationInfo;
13+
import org.apache.commons.lang.StringUtils;
14+
import org.apache.commons.lang3.tuple.Pair;
15+
import org.jetbrains.annotations.Nullable;
16+
17+
import javax.annotation.Nonnull;
18+
import javax.swing.*;
19+
import java.util.Arrays;
20+
import java.util.List;
21+
import java.util.regex.Pattern;
22+
23+
public class AddAppSettingsDialog extends AzureDialog<Pair<String, String>>
24+
implements AzureForm<Pair<String, String>> {
25+
26+
private static final Pattern APP_SETTINGS_NAME_PATTERN = Pattern.compile("^[a-zA-Z0-9_\\.]+$");
27+
28+
private JPanel pnlRoot;
29+
private AzureTextInput txtName;
30+
private AzureTextInput txtValue;
31+
private JLabel lblName;
32+
private JLabel lblValue;
33+
34+
private final AppSettingsTable table;
35+
36+
public AddAppSettingsDialog(@Nonnull final AppSettingsTable table) {
37+
super();
38+
this.table = table;
39+
$$$setupUI$$$();
40+
init();
41+
}
42+
43+
@Override
44+
protected void init() {
45+
super.init();
46+
txtName.setRequired(true);
47+
txtName.addValidator(this::validateName);
48+
txtValue.setRequired(false);
49+
50+
lblName.setLabelFor(txtName);
51+
lblValue.setLabelFor(txtValue);
52+
}
53+
54+
private AzureValidationInfo validateName() {
55+
final String value = txtName.getValue();
56+
if (StringUtils.isEmpty(value)) {
57+
return AzureValidationInfo.error("Name is a required property", txtName);
58+
} else if (!APP_SETTINGS_NAME_PATTERN.matcher(value).matches()) {
59+
return AzureValidationInfo.error("App setting names can only contain letters, numbers (0-9), periods (\".\"), and underscores (\"_\")", txtName);
60+
} else if (table.getAppSettings().containsKey(value)) {
61+
return AzureValidationInfo.error("App setting names must be unique", txtName);
62+
}
63+
return AzureValidationInfo.success(txtName);
64+
}
65+
66+
@Override
67+
public AzureForm<Pair<String, String>> getForm() {
68+
return this;
69+
}
70+
71+
@Override
72+
protected String getDialogTitle() {
73+
return "Add App Setting";
74+
}
75+
76+
@Override
77+
protected @Nullable JComponent createCenterPanel() {
78+
return pnlRoot;
79+
}
80+
81+
@Override
82+
public Pair<String, String> getValue() {
83+
return Pair.of(txtName.getValue(), txtValue.getValue());
84+
}
85+
86+
@Override
87+
public void setValue(Pair<String, String> data) {
88+
txtName.setValue(data.getKey());
89+
txtValue.setValue(data.getValue());
90+
}
91+
92+
@Override
93+
public List<AzureFormInput<?>> getInputs() {
94+
return Arrays.asList(txtName, txtValue);
95+
}
96+
97+
// CHECKSTYLE IGNORE check FOR NEXT 1 LINES
98+
void $$$setupUI$$$() {
99+
}
100+
}
Lines changed: 32 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,33 +3,34 @@
33
* Licensed under the MIT License. See License.txt in the project root for license information.
44
*/
55

6-
package com.microsoft.azure.toolkit.intellij.legacy.function.runner.component.table;
6+
package com.microsoft.azure.toolkit.intellij.legacy.appservice.table;
77

88
import com.microsoft.azure.toolkit.lib.common.task.AzureTaskManager;
99
import org.apache.commons.collections4.ListUtils;
1010
import org.apache.commons.lang3.StringUtils;
1111
import org.apache.commons.lang3.tuple.Pair;
1212

13+
import javax.annotation.Nonnull;
14+
import javax.annotation.Nullable;
1315
import javax.swing.event.TableModelEvent;
1416
import javax.swing.event.TableModelListener;
1517
import javax.swing.table.TableModel;
1618
import java.util.ArrayList;
1719
import java.util.HashMap;
20+
import java.util.HashSet;
1821
import java.util.List;
1922
import java.util.Map;
23+
import java.util.Set;
2024

2125
import static com.microsoft.azure.toolkit.intellij.common.AzureBundle.message;
2226

2327
public class AppSettingModel implements TableModel {
2428

25-
private static final String[] TITLE = {"Key", "Value"};
26-
private static final String FUNCTIONS_WORKER_RUNTIME_KEY = "FUNCTIONS_WORKER_RUNTIME";
27-
private static final String AZURE_WEB_JOB_STORAGE_KEY = "AzureWebJobsStorage";
28-
private static final String FUNCTIONS_WORKER_RUNTIME_VALUE = "java";
29-
private static final String AZURE_WEB_JOB_STORAGE_VALUE = "";
29+
private static final String[] TITLE = {"Name", "Value"};
3030

31-
private List<Pair<String, String>> appSettings = new ArrayList<>();
32-
private List<TableModelListener> tableModelListenerList = new ArrayList<>();
31+
private final List<Pair<String, String>> appSettings = new ArrayList<>();
32+
private final Set<String> requiredKeys = new HashSet<>();
33+
private final List<TableModelListener> tableModelListenerList = new ArrayList<>();
3334

3435
public AppSettingModel() {
3536
}
@@ -56,17 +57,17 @@ public Class<?> getColumnClass(int col) {
5657

5758
@Override
5859
public boolean isCellEditable(int row, int col) {
59-
if (!isRowValid(row)) {
60+
if (isRowInvalid(row)) {
6061
return false;
6162
}
6263
final Pair<String, String> target = appSettings.get(row);
63-
// Should not modify FUNCTIONS_WORKER_RUNTIME and AzureWebJobsStorage
64-
return !(FUNCTIONS_WORKER_RUNTIME_KEY.equals(target.getKey()) || (AZURE_WEB_JOB_STORAGE_KEY.equals(target.getKey()) && col == 0));
64+
return !requiredKeys.contains(target.getKey()) || col != 0;
6565
}
6666

6767
@Override
68+
@Nullable
6869
public Object getValueAt(int row, int col) {
69-
if (!isRowValid(row)) {
70+
if (isRowInvalid(row)) {
7071
return null;
7172
}
7273
final Pair<String, String> target = appSettings.get(row);
@@ -87,8 +88,8 @@ public void setValueAt(Object value, int row, int col) {
8788
}
8889

8990
public int addAppSettings(String key, String value) {
90-
final Pair result = Pair.of(key, value);
91-
final int index = ListUtils.indexOf(appSettings, pair -> StringUtils.equalsIgnoreCase(pair.getKey(), key));
91+
final Pair<String, String> result = Pair.of(key, value);
92+
final int index = getAppSettingsRow(key);
9293
if (index >= 0) {
9394
appSettings.set(index, result);
9495
} else {
@@ -98,28 +99,38 @@ public int addAppSettings(String key, String value) {
9899
return index > 0 ? index : appSettings.size() - 1;
99100
}
100101

102+
public int addRequiredAppSettings(@Nonnull final String key, final String value) {
103+
this.requiredKeys.add(key);
104+
return addAppSettings(key, value);
105+
}
106+
101107
public void removeAppSettings(int row) {
102-
if (!isRowValid(row)) {
108+
if (isRowInvalid(row)) {
103109
return;
104110
}
105111
final Pair<String, String> target = appSettings.get(row);
106-
if (FUNCTIONS_WORKER_RUNTIME_KEY.equals(target.getKey()) || AZURE_WEB_JOB_STORAGE_KEY.equals(target.getKey())) {
112+
if (requiredKeys.contains(target.getKey())) {
107113
throw new IllegalArgumentException(message("function.appSettings.validate.requiredParameter", target.getKey()));
108114
}
109115
appSettings.remove(row);
110116
fireTableChanged();
111117
}
112118

113119
public String getAppSettingsKey(int row) {
114-
if (appSettings == null || !isRowValid(row)) {
120+
if (isRowInvalid(row)) {
115121
return null;
116122
}
117123
return appSettings.get(row).getKey();
118124
}
119125

126+
public int getAppSettingsRow(@Nullable String key) {
127+
return ListUtils.indexOf(appSettings, pair -> StringUtils.equalsIgnoreCase(pair.getKey(), key));
128+
}
129+
130+
@Nonnull
120131
public Map<String, String> getAppSettings() {
121132
final Map<String, String> result = new HashMap<>();
122-
appSettings.stream().forEach(pair -> result.put(pair.getKey(), pair.getValue()));
133+
appSettings.forEach(pair -> result.put(pair.getKey(), pair.getValue()));
123134
return result;
124135
}
125136

@@ -129,7 +140,7 @@ public void clear() {
129140
}
130141

131142
public void fireTableChanged() {
132-
tableModelListenerList.stream().forEach(listener ->
143+
tableModelListenerList.forEach(listener ->
133144
AzureTaskManager.getInstance().runLater(() -> listener.tableChanged(new TableModelEvent(this))));
134145
}
135146

@@ -143,17 +154,7 @@ public void removeTableModelListener(TableModelListener tableModelListener) {
143154
tableModelListenerList.remove(tableModelListener);
144155
}
145156

146-
public void loadRequiredAttributes() {
147-
final Map<String, String> appSettingsMap = getAppSettings();
148-
if (!appSettingsMap.containsKey(FUNCTIONS_WORKER_RUNTIME_KEY)) {
149-
appSettings.add(Pair.of(FUNCTIONS_WORKER_RUNTIME_KEY, FUNCTIONS_WORKER_RUNTIME_VALUE));
150-
}
151-
if (!appSettingsMap.containsKey(AZURE_WEB_JOB_STORAGE_KEY)) {
152-
appSettings.add(Pair.of(AZURE_WEB_JOB_STORAGE_KEY, AZURE_WEB_JOB_STORAGE_VALUE));
153-
}
154-
}
155-
156-
private boolean isRowValid(int row) {
157-
return row >= 0 && row < appSettings.size();
157+
private boolean isRowInvalid(int row) {
158+
return row < 0 || row >= appSettings.size();
158159
}
159160
}

0 commit comments

Comments
 (0)