Skip to content

Commit a7b25b8

Browse files
author
Michael Winberry
committed
#1570. Update start.go by moving the tunnels routes under packages, updated the routes to take in a pkg and connection name instead of just connection so that tunnels can be created and removed by package. Remove api/packages list.go ListPackageConnections as it is no longer needed. Move api/tunnels/tunnels.go to api/packages/tunnels.go. Update api/packages tunnels.go with new typing and logic to connect, disconnect, and get connections by package, added ListConnections method that returns a map of package names to APIDeployedPackageConnections types, and removed the launch logic from the backend to be handled in the front end. Update packager deploy.go to add the connect strings to the pkg metadata prior to saving the deployed package information to k8s. Update types package.go ZarfMetadata with ConnectStrings field of Type ConnectStrings. Update types api.go with connection types for package connections/tunnels. Update ui api.ts with new endpoints and removed the tunnel endpoints. Update ui store.ts with update logic for the stores that use polling, added PackageTunnels interface. Update deployed-package-table with keys to prevent misrendering after adding a package. Update ui ConnectDeployedPackageDialog to use the new connections logic and api calls as well as opening the connection url in a new tab upon successfull connection. Update DeployedPackageMenu removed unused import. Update DisconnectDeployedPackageDialog to use new endpoints and logic for removing a connection. Update routes +page by extracting the asynchronous store methods into store.ts and added a poll for connections.
1 parent 7926f94 commit a7b25b8

File tree

18 files changed

+506
-436
lines changed

18 files changed

+506
-436
lines changed

docs/4-user-guide/3-zarf-schema.md

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,84 @@ Must be one of:
267267
</blockquote>
268268
</details>
269269

270+
<details open>
271+
<summary>
272+
<strong> <a name="metadata_connectStrings"></a>connectStrings</strong>
273+
</summary>
274+
&nbsp;
275+
<blockquote>
276+
277+
## metadata > connectStrings
278+
279+
**Description:** List of connection strings for the package
280+
281+
| | |
282+
| ------------------------- | --------------------------------------------------------------------------------------------------------------------------------- |
283+
| **Type** | `object` |
284+
| **Additional properties** | [![Any type: allowed](https://img.shields.io/badge/Any%20type-allowed-green)](# "Additional Properties of any type are allowed.") |
285+
286+
<details open>
287+
<summary>
288+
<strong> <a name="metadata_connectStrings_pattern1"></a>Pattern Property ConnectString</strong>
289+
</summary>
290+
&nbsp;
291+
<blockquote>
292+
293+
## metadata > connectStrings > ConnectString
294+
:::note
295+
All properties whose name matches the regular expression
296+
```.*``` ([Test](https://regex101.com/?regex=.%2A))
297+
must respect the following conditions
298+
:::
299+
300+
| | |
301+
| ------------------------- | -------------------------------------------------------------------------------------------------------- |
302+
| **Type** | `object` |
303+
| **Additional properties** | [![Not allowed](https://img.shields.io/badge/Not%20allowed-red)](# "Additional Properties not allowed.") |
304+
| **Defined in** | #/definitions/ConnectString |
305+
306+
<details>
307+
<summary>
308+
<strong> <a name="metadata_connectStrings_pattern1_description"></a>description *</strong>
309+
</summary>
310+
&nbsp;
311+
<blockquote>
312+
313+
![Required](https://img.shields.io/badge/Required-red)
314+
315+
**Description:** Descriptive text that explains what the resource you would be connecting to is used for
316+
317+
| | |
318+
| -------- | -------- |
319+
| **Type** | `string` |
320+
321+
</blockquote>
322+
</details>
323+
324+
<details>
325+
<summary>
326+
<strong> <a name="metadata_connectStrings_pattern1_url"></a>url *</strong>
327+
</summary>
328+
&nbsp;
329+
<blockquote>
330+
331+
![Required](https://img.shields.io/badge/Required-red)
332+
333+
**Description:** URL path that gets appended to the k8s port-forward result
334+
335+
| | |
336+
| -------- | -------- |
337+
| **Type** | `string` |
338+
339+
</blockquote>
340+
</details>
341+
342+
</blockquote>
343+
</details>
344+
345+
</blockquote>
346+
</details>
347+
270348
</blockquote>
271349
</details>
272350

src/internal/api/packages/list.go

Lines changed: 0 additions & 59 deletions
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,9 @@ package packages
77
import (
88
"net/http"
99

10-
"github.com/defenseunicorns/zarf/src/config"
1110
"github.com/defenseunicorns/zarf/src/internal/api/common"
1211
"github.com/defenseunicorns/zarf/src/internal/cluster"
1312
"github.com/defenseunicorns/zarf/src/pkg/message"
14-
"github.com/defenseunicorns/zarf/src/types"
15-
"github.com/go-chi/chi/v5"
1613
)
1714

1815
// ListDeployedPackages writes a list of packages that have been deployed to the connected cluster.
@@ -31,59 +28,3 @@ func ListDeployedPackages(w http.ResponseWriter, _ *http.Request) {
3128

3229
common.WriteJSONResponse(w, deployedPackages, http.StatusOK)
3330
}
34-
35-
// ListPackageConnections lists the zarf connections for a package.
36-
func ListPackageConnections(w http.ResponseWriter, r *http.Request) {
37-
data := types.APIPackageConnections{}
38-
39-
pkgName := chi.URLParam(r, "name")
40-
41-
c, err := cluster.NewCluster()
42-
43-
if err != nil {
44-
message.ErrorWebf(err, w, "Could not connect to cluster")
45-
return
46-
}
47-
48-
// Get the package from the cluster.
49-
pkg, err := c.GetDeployedPackage(pkgName)
50-
51-
if err != nil {
52-
message.ErrorWebf(err, w, "Unable to get package %s", pkgName)
53-
return
54-
}
55-
56-
// Get a list of namespaces from the package component charts.
57-
namespaces := make(map[string]string)
58-
for _, component := range pkg.DeployedComponents {
59-
for _, chart := range component.InstalledCharts {
60-
namespaces[chart.Namespace] = chart.Namespace
61-
}
62-
}
63-
64-
// Get a list of zarf connections from the namespaces.
65-
connections := make(types.ConnectStrings)
66-
for namespace := range namespaces {
67-
// Get a list of services in the namespace with the zarf connect label.
68-
serviceList, err := c.Kube.GetServicesByLabelExists(namespace, config.ZarfConnectLabelName)
69-
70-
if err != nil {
71-
message.ErrorWebf(err, w, "Unable to get a list of the zarf connections for package %s", pkgName)
72-
return
73-
}
74-
75-
for _, svc := range serviceList.Items {
76-
name := svc.Labels[config.ZarfConnectLabelName]
77-
78-
// Add the connectString.
79-
connections[name] = types.ConnectString{
80-
Description: svc.Annotations[config.ZarfConnectAnnotationDescription],
81-
URL: svc.Annotations[config.ZarfConnectAnnotationURL],
82-
}
83-
}
84-
85-
}
86-
data.ConnectStrings = connections
87-
88-
common.WriteJSONResponse(w, data, http.StatusOK)
89-
}

src/internal/api/packages/tunnels.go

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,109 @@
1+
// SPDX-License-Identifier: Apache-2.0
2+
// SPDX-FileCopyrightText: 2021-Present The Zarf Authors
3+
4+
// Package packages provides api functions for managing Zarf packages.
5+
package packages
6+
7+
import (
8+
"errors"
9+
"net/http"
10+
11+
"github.com/defenseunicorns/zarf/src/internal/api/common"
12+
"github.com/defenseunicorns/zarf/src/internal/cluster"
13+
"github.com/defenseunicorns/zarf/src/pkg/message"
14+
"github.com/defenseunicorns/zarf/src/types"
15+
"github.com/go-chi/chi/v5"
16+
)
17+
18+
type PackageTunnel struct {
19+
tunnel *cluster.Tunnel
20+
Connection types.APIDeployedPackageConnection `json:"connection,omitempty"`
21+
}
22+
type PackageTunnels map[string]map[string]PackageTunnel
23+
24+
// tunnels is a map of package names to tunnel objects used for storing connected tunnels
25+
var tunnels = make(PackageTunnels)
26+
27+
// ListConnections returns a map of pkgName to a list of connections
28+
func ListConnections(w http.ResponseWriter, _ *http.Request) {
29+
allConnections := make(types.APIConnections)
30+
for name, pkgTunnels := range tunnels {
31+
for _, pkgTunnel := range pkgTunnels {
32+
if allConnections[name] == nil {
33+
allConnections[name] = make(types.APIDeployedPackageConnections, 0)
34+
}
35+
allConnections[name] = append(allConnections[name], pkgTunnel.Connection)
36+
}
37+
}
38+
common.WriteJSONResponse(w, allConnections, http.StatusOK)
39+
}
40+
41+
// ListPackageConnections lists all tunnel names
42+
func ListPackageConnections(w http.ResponseWriter, r *http.Request) {
43+
pkgName := chi.URLParam(r, "pkg")
44+
if tunnels[pkgName] == nil {
45+
message.ErrorWebf(errors.New("No tunnels for package %s"), w, pkgName)
46+
return
47+
}
48+
pkgTunnels := make(types.APIDeployedPackageConnections, 0, len(tunnels[pkgName]))
49+
for _, pkgTunnel := range tunnels[pkgName] {
50+
pkgTunnels = append(pkgTunnels, pkgTunnel.Connection)
51+
}
52+
53+
common.WriteJSONResponse(w, pkgTunnels, http.StatusOK)
54+
}
55+
56+
// ConnectTunnel establishes a tunnel for the requested resource
57+
func ConnectTunnel(w http.ResponseWriter, r *http.Request) {
58+
pkgName := chi.URLParam(r, "pkg")
59+
connectionName := chi.URLParam(r, "name")
60+
61+
if tunnels[pkgName] == nil {
62+
tunnels[pkgName] = make(map[string]PackageTunnel)
63+
}
64+
65+
pkgTunnels := tunnels[pkgName]
66+
67+
if pkgTunnels[connectionName].tunnel != nil {
68+
common.WriteJSONResponse(w, tunnels[pkgName][connectionName].Connection, http.StatusOK)
69+
return
70+
}
71+
72+
tunnel, err := cluster.NewZarfTunnel()
73+
74+
if err != nil {
75+
message.ErrorWebf(err, w, "Failed to create tunnel for %s", connectionName)
76+
return
77+
}
78+
79+
err = tunnel.Connect(connectionName, false)
80+
if err != nil {
81+
message.ErrorWebf(err, w, "Failed to connect to %s", connectionName)
82+
return
83+
}
84+
85+
tunnels[pkgName][connectionName] = PackageTunnel{
86+
tunnel: tunnel,
87+
Connection: types.APIDeployedPackageConnection{
88+
Name: connectionName,
89+
URL: tunnel.FullURL(),
90+
},
91+
}
92+
common.WriteJSONResponse(w, tunnels[pkgName][connectionName].Connection, http.StatusCreated)
93+
}
94+
95+
// DisconnectTunnel closes the tunnel for the requested resource
96+
func DisconnectTunnel(w http.ResponseWriter, r *http.Request) {
97+
pkgName := chi.URLParam(r, "pkg")
98+
connectionName := chi.URLParam(r, "name")
99+
pkgTunnel := tunnels[pkgName][connectionName]
100+
if pkgTunnel.tunnel == nil {
101+
message.ErrorWebf(errors.New("Tunnel not found"), w, "Failed to disconnect from %s", connectionName)
102+
return
103+
}
104+
105+
pkgTunnel.tunnel.Close()
106+
delete(tunnels[pkgName], connectionName)
107+
108+
common.WriteJSONResponse(w, true, http.StatusOK)
109+
}

src/internal/api/start.go

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ import (
1818
"github.com/defenseunicorns/zarf/src/internal/api/cluster"
1919
"github.com/defenseunicorns/zarf/src/internal/api/components"
2020
"github.com/defenseunicorns/zarf/src/internal/api/packages"
21-
"github.com/defenseunicorns/zarf/src/internal/api/tunnels"
2221
"github.com/defenseunicorns/zarf/src/pkg/message"
2322
"github.com/defenseunicorns/zarf/src/pkg/utils"
2423
"github.com/defenseunicorns/zarf/src/pkg/utils/exec"
@@ -92,21 +91,18 @@ func LaunchAPIServer() {
9291
r.Get("/find-init", packages.FindInitPackage)
9392
r.Get("/read/{path}", packages.Read)
9493
r.Get("/list", packages.ListDeployedPackages)
95-
r.Get("/list/connections/{name}", packages.ListPackageConnections)
9694
r.Put("/deploy", packages.DeployPackage)
9795
r.Get("/deploy-stream", packages.StreamDeployPackage)
9896
r.Delete("/remove/{name}", packages.RemovePackage)
97+
r.Put("/{pkg}/connect/{name}", packages.ConnectTunnel)
98+
r.Delete("/{pkg}/disconnect/{name}", packages.DisconnectTunnel)
99+
r.Get("/{pkg}/connections", packages.ListPackageConnections)
100+
r.Get("/connections", packages.ListConnections)
99101
})
100102

101103
r.Route("/components", func(r chi.Router) {
102104
r.Get("/deployed", components.ListDeployingComponents)
103105
})
104-
105-
r.Route("/tunnels", func(r chi.Router) {
106-
r.Get("/list", tunnels.ListTunnels)
107-
r.Put("/connect/{name}", tunnels.ConnectTunnel)
108-
r.Delete("/disconnect/{name}", tunnels.DisconnectTunnel)
109-
})
110106
})
111107

112108
// If no dev port specified, use the server port for the URL and try to open it

src/internal/api/tunnels/tunnels.go

Lines changed: 0 additions & 87 deletions
This file was deleted.

0 commit comments

Comments
 (0)