Skip to content
This repository was archived by the owner on Apr 23, 2025. It is now read-only.

Commit b783e35

Browse files
authored
feat: Add registry management (#318)
* feat: Add registry management Fixes #271 Signed-off-by: Jeff MAURY <[email protected]>
1 parent fc09843 commit b783e35

31 files changed

+830
-26
lines changed
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2021 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.utils.odo;
12+
13+
import org.junit.Test;
14+
15+
import java.io.IOException;
16+
import java.util.List;
17+
18+
import static org.junit.Assert.assertTrue;
19+
20+
public class OdoCliRegistryTest extends OdoCliTest {
21+
22+
23+
@Test
24+
public void checkCreateRegistry() throws IOException, InterruptedException {
25+
String registryName = REGISTRY_PREFIX + random.nextInt();
26+
try {
27+
odo.createDevfileRegistry(registryName, "https://registry.devfile.io", null);
28+
} finally {
29+
try {
30+
odo.deleteDevfileRegistry(registryName);
31+
} catch (IOException e) {}
32+
}
33+
}
34+
35+
@Test
36+
public void checkListRegistries() throws IOException, InterruptedException {
37+
List<DevfileRegistry> registries = odo.listDevfileRegistries();
38+
assertTrue(registries.size() > 0);
39+
}
40+
}

src/it/java/org/jboss/tools/intellij/openshift/utils/odo/OdoCliTest.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,8 @@ public abstract class OdoCliTest extends BaseTest {
4040

4141
protected static final String STORAGE_PREFIX = "stor";
4242

43+
protected static final String REGISTRY_PREFIX = "reg";
44+
4345
protected static final String CLUSTER_URL = System.getenv("CLUSTER_URL");
4446

4547
protected static final String CLUSTER_USER = System.getenv("CLUSTER_USER");

src/main/java/org/jboss/tools/intellij/openshift/WindowToolFactory.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,7 @@ public void createToolWindowContent(@NotNull Project project, @NotNull ToolWindo
4848
Tree tree = new Tree(new AsyncTreeModel(model, project));
4949
tree.putClientProperty(Constants.STRUCTURE_PROPERTY, structure);
5050
tree.setCellRenderer(new NodeRenderer());
51+
tree.setRootVisible(false);
5152
PopupHandler.installPopupHandler(tree, "org.jboss.tools.intellij.tree", ActionPlaces.UNKNOWN);
5253
panel.add(new JBScrollPane(tree), BorderLayout.CENTER);
5354
toolWindow.getContentManager().addContent(contentFactory.createContent(panel, "", false));

src/main/java/org/jboss/tools/intellij/openshift/actions/OdoAction.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object s
4747

4848
private Odo getOdo(AnActionEvent anActionEvent) throws IOException {
4949
Tree tree = getTree(anActionEvent);
50-
return ((ApplicationsRootNode)((ApplicationsTreeStructure)tree.getClientProperty(Constants.STRUCTURE_PROPERTY)).getRootElement()).getOdo();
50+
return ((ApplicationsRootNode)((ApplicationsTreeStructure)tree.getClientProperty(Constants.STRUCTURE_PROPERTY)).getApplicationsRoot()).getOdo();
5151
}
5252

5353
public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object selected, Odo odo) {
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019-2020 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.actions.registry;
12+
13+
import com.intellij.openapi.actionSystem.AnActionEvent;
14+
import com.intellij.openapi.ui.Messages;
15+
import com.redhat.devtools.intellij.common.utils.ExecHelper;
16+
import com.redhat.devtools.intellij.common.utils.UIHelper;
17+
import org.jboss.tools.intellij.openshift.Constants;
18+
import org.jboss.tools.intellij.openshift.actions.OdoAction;
19+
import org.jboss.tools.intellij.openshift.tree.application.ApplicationsTreeStructure;
20+
import org.jboss.tools.intellij.openshift.tree.application.DevfileRegistriesNode;
21+
import org.jboss.tools.intellij.openshift.ui.registry.CreateRegistryDialog;
22+
import org.jboss.tools.intellij.openshift.utils.odo.Odo;
23+
24+
import javax.swing.tree.TreePath;
25+
26+
import java.io.IOException;
27+
28+
import static org.jboss.tools.intellij.openshift.telemetry.TelemetryService.TelemetryResult;
29+
30+
public class CreateRegistryAction extends OdoAction {
31+
public CreateRegistryAction() {
32+
super(DevfileRegistriesNode.class);
33+
}
34+
35+
@Override
36+
protected String getTelemetryActionName() { return "create registry"; }
37+
38+
@Override
39+
public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object selected, Odo odo) {
40+
DevfileRegistriesNode registriesNode = (DevfileRegistriesNode) selected;
41+
CreateRegistryDialog dialog = new CreateRegistryDialog();
42+
dialog.show();
43+
if (dialog.isOK()) {
44+
ExecHelper.submit(() -> {
45+
try {
46+
odo.createDevfileRegistry(dialog.getName(), dialog.getURL(), dialog.getToken());
47+
((ApplicationsTreeStructure)getTree(anActionEvent).getClientProperty(Constants.STRUCTURE_PROPERTY)).fireModified(registriesNode);
48+
sendTelemetryResults(TelemetryResult.SUCCESS);
49+
} catch (IOException e) {
50+
sendTelemetryError(e);
51+
UIHelper.executeInUI(() -> Messages.showErrorDialog("Error: " + e.getLocalizedMessage(), "Create URL"));
52+
}
53+
});
54+
} else {
55+
sendTelemetryResults(TelemetryResult.ABORTED);
56+
}
57+
}
58+
}
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019-2020 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.actions.registry;
12+
13+
import com.intellij.openapi.actionSystem.AnActionEvent;
14+
import com.intellij.openapi.ui.Messages;
15+
import com.redhat.devtools.intellij.common.utils.ExecHelper;
16+
import com.redhat.devtools.intellij.common.utils.UIHelper;
17+
import org.jboss.tools.intellij.openshift.Constants;
18+
import org.jboss.tools.intellij.openshift.actions.OdoAction;
19+
import org.jboss.tools.intellij.openshift.tree.application.ApplicationsTreeStructure;
20+
import org.jboss.tools.intellij.openshift.tree.application.DevfileRegistryNode;
21+
import org.jboss.tools.intellij.openshift.utils.odo.Odo;
22+
23+
import javax.swing.tree.TreePath;
24+
import java.io.IOException;
25+
26+
import static org.jboss.tools.intellij.openshift.telemetry.TelemetryService.TelemetryResult;
27+
28+
public class DeleteRegistryAction extends OdoAction {
29+
public DeleteRegistryAction() {
30+
super(DevfileRegistryNode.class);
31+
}
32+
33+
@Override
34+
protected String getTelemetryActionName() { return "delete registry"; }
35+
36+
@Override
37+
public void actionPerformed(AnActionEvent anActionEvent, TreePath path, Object selected, Odo odo) {
38+
DevfileRegistryNode registryNode = (DevfileRegistryNode) selected;
39+
if (Messages.NO == Messages.showYesNoDialog("Delete registry '" + registryNode.getName() + "'.\nAre you sure?", "Delete registry",
40+
Messages.getQuestionIcon())) {
41+
sendTelemetryResults(TelemetryResult.ABORTED);
42+
} else {
43+
ExecHelper.submit(() -> {
44+
try {
45+
odo.deleteDevfileRegistry(registryNode.getName());
46+
((ApplicationsTreeStructure)getTree(anActionEvent).getClientProperty(Constants.STRUCTURE_PROPERTY)).fireRemoved(registryNode);
47+
sendTelemetryResults(TelemetryResult.SUCCESS);
48+
} catch (IOException e) {
49+
sendTelemetryError(e);
50+
UIHelper.executeInUI(() -> Messages.showErrorDialog("Error: " + e.getLocalizedMessage(), "Delete registry"));
51+
}
52+
});
53+
}
54+
}
55+
}

src/main/java/org/jboss/tools/intellij/openshift/tree/application/ApplicationsTreeStructure.java

Lines changed: 71 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ public class ApplicationsTreeStructure extends AbstractTreeStructure implements
3737
private final ApplicationsRootNode root;
3838

3939
private final MutableModel<Object> mutableModelSupport = new MutableModelSupport<>();
40+
private DevfileRegistriesNode registries;
4041

4142
private final AtomicBoolean initialized = new AtomicBoolean(false);
4243

@@ -58,22 +59,39 @@ public class ApplicationsTreeStructure extends AbstractTreeStructure implements
5859
private static final Icon URL_ICON = IconLoader.findIcon("/images/url-node.png", ApplicationsTreeStructure.class);
5960
private static final Icon URL_SECURE_ICON = IconLoader.findIcon("/images/url-node-secure.png", ApplicationsTreeStructure.class);
6061

62+
private static final Icon COMPONENT_TYPE_ICON = IconLoader.findIcon("/images/component-type-light.png", ApplicationsTreeStructure.class);
63+
64+
private static final Icon STARTER_ICON = IconLoader.findIcon("/images/start-project-light.png", ApplicationsTreeStructure.class);
65+
66+
private static final Icon REGISTRY_ICON = IconLoader.findIcon("/images/registry.svg", ApplicationsTreeStructure.class);
67+
6168
public ApplicationsTreeStructure(Project project) {
6269
this.project = project;
6370
this.root = new ApplicationsRootNode(project, this);
71+
this.registries = new DevfileRegistriesNode(root);
6472
}
6573

6674
@Override
6775
public @NotNull Object getRootElement() {
76+
return this;
77+
}
78+
79+
public Object getApplicationsRoot() {
6880
if (!initialized.getAndSet(true)) {
69-
root.initializeOdo().thenAccept(tkn -> fireModified(root));
81+
root.initializeOdo().thenAccept(odo -> {
82+
fireModified(root);
83+
fireModified(registries);
84+
});
7085
}
7186
return root;
7287
}
7388

7489
@NotNull
7590
@Override
7691
public Object[] getChildElements(@NotNull Object element) {
92+
if (element == this) {
93+
return new Object[] {getApplicationsRoot(), registries};
94+
}
7795
Odo odo = root.getOdo();
7896
if (odo != null) {
7997
if (element instanceof ApplicationsRootNode) {
@@ -84,6 +102,12 @@ public Object[] getChildElements(@NotNull Object element) {
84102
return getComponentsAndServices((ApplicationNode) element);
85103
} else if (element instanceof ComponentNode) {
86104
return getStoragesAndURLs((ComponentNode) element);
105+
} else if (element instanceof DevfileRegistriesNode) {
106+
return getRegistries(root, odo);
107+
} else if (element instanceof DevfileRegistryNode) {
108+
return getRegistryComponentTypes((DevfileRegistryNode) element);
109+
} else if (element instanceof DevfileRegistryComponentTypeNode) {
110+
return getRegistryComponentTypeStarters((DevfileRegistryComponentTypeNode) element);
87111
}
88112
}
89113
return new Object[0];
@@ -164,19 +188,50 @@ private Object[] getStoragesAndURLs(ComponentNode element) {
164188
return results.toArray();
165189
}
166190

191+
private Object[] getRegistries(ApplicationsRootNode root, Odo odo) {
192+
List<DevfileRegistryNode> result = new ArrayList<>();
193+
194+
try {
195+
odo.listDevfileRegistries().forEach(registry -> result.add(new DevfileRegistryNode(root, registries, registry)));
196+
} catch (IOException e) {}
197+
return result.toArray();
198+
}
199+
200+
private Object[] getRegistryComponentTypes(DevfileRegistryNode element) {
201+
List<DevfileRegistryComponentTypeNode> result = new ArrayList<>();
202+
try {
203+
element.getRoot().getOdo().getComponentTypes(element.getName()).forEach(type -> result.add(new DevfileRegistryComponentTypeNode(root, element, type)));
204+
} catch (IOException e) {}
205+
return result.toArray();
206+
}
207+
208+
private Object[] getRegistryComponentTypeStarters(DevfileRegistryComponentTypeNode element) {
209+
List<DevfileRegistryComponentTypeStarterNode> result = new ArrayList<>();
210+
try {
211+
element.getRoot().getOdo().getComponentTypeInfo(element.getName()).getStarters().forEach(starter -> result.add(new DevfileRegistryComponentTypeStarterNode(element.getRoot(), element, starter)));
212+
} catch (IOException e) {}
213+
return result.toArray();
214+
}
215+
167216
@Override
168217
public Object getParentElement(@NotNull Object element) {
169218
if (element instanceof ParentableNode) {
170219
return ((ParentableNode) element).getParent();
171220
}
221+
if (element instanceof ApplicationsRootNode) {
222+
return this;
223+
}
172224
return null;
173225
}
174226

175227
@Override
176228
public NodeDescriptor createDescriptor(@NotNull Object element, @Nullable NodeDescriptor parentDescriptor) {
177-
if (element instanceof ApplicationsRootNode) {
178-
Odo odo = ((ApplicationsRootNode) element).getOdo();
179-
return new LabelAndIconDescriptor(project, element, () -> odo != null ? odo.getMasterUrl().toString() : "Loading", CLUSTER_ICON,
229+
if (element == this) {
230+
return new LabelAndIconDescriptor(project, element, "Root", null, parentDescriptor);
231+
}
232+
else if (element instanceof ApplicationsRootNode) {
233+
ApplicationsRootNode root = (ApplicationsRootNode) element;
234+
return new LabelAndIconDescriptor(project, element, () -> root.getOdo() != null?root.getOdo().getMasterUrl().toString():"Loading", CLUSTER_ICON,
180235
parentDescriptor);
181236
} else if (element instanceof NamespaceNode) {
182237
return new LabelAndIconDescriptor(project, element, ((NamespaceNode) element)::getName, NAMESPACE_ICON,
@@ -198,11 +253,19 @@ public NodeDescriptor createDescriptor(@NotNull Object element, @Nullable NodeDe
198253
URL url = ((URLNode) element).getUrl();
199254
return new LabelAndIconDescriptor(project, element,
200255
() -> url.getName() + " (" + url.getPort() + ") (" + url.getState() + ')',
201-
() -> url.isSecure() ? URL_SECURE_ICON : URL_ICON, parentDescriptor);
202-
} else if (element instanceof MessageNode<?>) {
203-
return new LabelAndIconDescriptor(project, element, ((MessageNode<?>) element).getName(), null, parentDescriptor);
256+
() -> url.isSecure()?URL_SECURE_ICON:URL_ICON, parentDescriptor);
257+
} else if (element instanceof MessageNode) {
258+
return new LabelAndIconDescriptor(project, element,((MessageNode)element).getName(), null, parentDescriptor);
259+
} else if (element instanceof DevfileRegistriesNode) {
260+
return new LabelAndIconDescriptor(project, element, "Devfile registries", REGISTRY_ICON, parentDescriptor);
261+
} else if (element instanceof DevfileRegistryNode) {
262+
return new LabelAndIconDescriptor(project, element, ((DevfileRegistryNode)element).getName(), ((DevfileRegistryNode)element).getRegistry().getURL(), REGISTRY_ICON, parentDescriptor);
263+
} else if (element instanceof DevfileRegistryComponentTypeNode) {
264+
return new LabelAndIconDescriptor(project, element, ((DevfileRegistryComponentTypeNode)element).getName(), ((DevfileRegistryComponentTypeNode)element).getComponentType().getDescription(), COMPONENT_TYPE_ICON, parentDescriptor);
265+
} else if (element instanceof DevfileRegistryComponentTypeStarterNode) {
266+
return new LabelAndIconDescriptor(project, element, ((DevfileRegistryComponentTypeStarterNode)element).getName(), ((DevfileRegistryComponentTypeStarterNode)element).getStarter().getDescription(), STARTER_ICON, parentDescriptor);
204267
}
205-
return null;
268+
return new LabelAndIconDescriptor(project, element, element.toString(), null, parentDescriptor);
206269
}
207270

208271
@Override
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019-2020 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.tree.application;
12+
13+
public class DevfileRegistriesNode extends ParentableNode<Object> {
14+
15+
public DevfileRegistriesNode(ApplicationsRootNode root) {
16+
super(root, null, "");
17+
}
18+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019-2020 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.tree.application;
12+
13+
import org.jboss.tools.intellij.openshift.utils.odo.DevfileComponentType;
14+
15+
public class DevfileRegistryComponentTypeNode extends ParentableNode<DevfileRegistryNode> {
16+
private final DevfileComponentType componentType;
17+
18+
public DevfileRegistryComponentTypeNode(ApplicationsRootNode root, DevfileRegistryNode parent, DevfileComponentType componentType) {
19+
super(root, parent, componentType.getName());
20+
this.componentType = componentType;
21+
}
22+
23+
public DevfileComponentType getComponentType() {
24+
return componentType;
25+
}
26+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
/*******************************************************************************
2+
* Copyright (c) 2019-2020 Red Hat, Inc.
3+
* Distributed under license by Red Hat, Inc. All rights reserved.
4+
* This program is made available under the terms of the
5+
* Eclipse Public License v2.0 which accompanies this distribution,
6+
* and is available at http://www.eclipse.org/legal/epl-v20.html
7+
*
8+
* Contributors:
9+
* Red Hat, Inc. - initial API and implementation
10+
******************************************************************************/
11+
package org.jboss.tools.intellij.openshift.tree.application;
12+
13+
import org.jboss.tools.intellij.openshift.utils.odo.Starter;
14+
15+
public class DevfileRegistryComponentTypeStarterNode extends ParentableNode<DevfileRegistryComponentTypeNode> {
16+
private final Starter starter;
17+
18+
public DevfileRegistryComponentTypeStarterNode(ApplicationsRootNode root, DevfileRegistryComponentTypeNode parent, Starter starter) {
19+
super(root, parent, starter.getName());
20+
this.starter = starter;
21+
}
22+
23+
public Starter getStarter() {
24+
return starter;
25+
}
26+
}

0 commit comments

Comments
 (0)