Skip to content

Commit 3c860fd

Browse files
committed
v0.5.2
1 parent 97957fe commit 3c860fd

File tree

13 files changed

+101
-8
lines changed

13 files changed

+101
-8
lines changed

adapter/database/workspace.go

+8-4
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ type workspaceDTO struct {
4646
Type string `db:"type"`
4747
Title string `db:"title"`
4848
Data sql.NullString `db:"data"`
49-
Sort int64 `db:"sort"`
49+
Sort int `db:"sort"`
5050
Expanded bool `db:"expanded"`
5151
}
5252

@@ -64,6 +64,9 @@ func newWorkspaceDTO(in *entity.Workspace) (dto *workspaceDTO, err error) {
6464
}
6565
dto.Data = types.StringToSQL(string(data))
6666
}
67+
if in.Sort != nil {
68+
dto.Sort = *in.Sort
69+
}
6770

6871
return
6972
}
@@ -75,6 +78,7 @@ func (dto *workspaceDTO) entity() (*entity.Workspace, error) {
7578
HasChild: &dto.HasChild,
7679
Type: entity.WorkspaceType(dto.Type),
7780
Title: dto.Title,
81+
Sort: &dto.Sort,
7882
Expanded: &dto.Expanded,
7983
}
8084

@@ -168,7 +172,7 @@ func (repo *WorkspaceRepository) Get() ([]*entity.Workspace, error) {
168172
err := repo.db.Connector.SelectContext(repo.ctx, &dto, fmt.Sprintf(`
169173
SELECT %s
170174
FROM %s
171-
ORDER BY type, sort;`, workspaceTableFields, workspaceTable))
175+
ORDER BY type, sort, created_at;`, workspaceTableFields, workspaceTable))
172176
if err != nil {
173177
return nil, err
174178
}
@@ -197,8 +201,8 @@ func (repo *WorkspaceRepository) Create(in *entity.Workspace) (*entity.Workspace
197201
defer repo.commit(tx, err)
198202

199203
query, args, err = tx.BindNamed(fmt.Sprintf(`
200-
INSERT INTO %s (parent_id, has_child, type, title, data)
201-
VALUES (:parent_id, :has_child, :type, :title, :data)
204+
INSERT INTO %s (parent_id, has_child, type, title, data, sort)
205+
VALUES (:parent_id, :has_child, :type, :title, :data, :sort)
202206
RETURNING %s;`, workspaceTable, workspaceTableFields), dto)
203207
if err != nil {
204208
return nil, err

adapter/grpc/query.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,7 @@ func (c *Client) response(data proto.Message, header metadata.MD, trailer metada
518518
Received: c.receivedMessaged,
519519
}
520520

521-
resp.JsonString, err = c.getResponse(data)
521+
resp.JsonString, _ = c.getResponse(data)
522522

523523
c.responseCh <- resp
524524
}

adapter/k8s/client.go

+12-2
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,12 @@ func (c *Client) PortForward(r *entity.K8SPortForward) (entity.PortForwardContro
9696
return
9797
}
9898

99-
dialer := spdy.NewDialer(upgrader, &http.Client{Transport: transport}, http.MethodPost, &url.URL{Scheme: "https", Path: path, Host: u.Host})
99+
httpClient := &http.Client{
100+
Transport: transport,
101+
Timeout: time.Duration(*c.cfg.K8SRequestTimeout) * time.Second,
102+
}
103+
104+
dialer := spdy.NewDialer(upgrader, httpClient, http.MethodPost, &url.URL{Scheme: "https", Path: path, Host: u.Host})
100105
fw, err := portforward.New(dialer, []string{fmt.Sprintf("%d:%d", r.LocalPort, r.PodPort)}, ctrl.stopCh, readyCh, ctrl.out, ctrl.errOut)
101106
if err != nil {
102107
writeError(err)
@@ -120,7 +125,10 @@ func (c *Client) createClient(cfg *entity.K8SClientConfig) (*rest.Config, *kuber
120125
)
121126

122127
if cfg.GCSAuth != nil && cfg.GCSAuth.Enabled {
123-
restConfig, err = c.gcsAuth(c.ctx, cfg.GCSAuth)
128+
ctx, cancel := context.WithTimeout(c.ctx, time.Duration(*c.cfg.K8SRequestTimeout)*time.Second)
129+
defer cancel()
130+
131+
restConfig, err = c.gcsAuth(ctx, cfg.GCSAuth)
124132
if err != nil {
125133
return nil, nil, err
126134
}
@@ -140,6 +148,8 @@ func (c *Client) createClient(cfg *entity.K8SClientConfig) (*rest.Config, *kuber
140148
restConfig.BearerToken = cfg.BearerToken
141149
}
142150

151+
restConfig.Timeout = time.Duration(*c.cfg.K8SRequestTimeout) * time.Second
152+
143153
client, err := kubernetes.NewForConfig(restConfig)
144154
if err != nil {
145155
return nil, nil, err

business/entity/events.go

+1
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ const (
88
CmdGetWorkspace GUICommand = "workspace.get"
99
CmdSortingWorkspace GUICommand = "workspace.sorting"
1010
CmdDeleteWorkspace GUICommand = "workspace.delete"
11+
CmdDuplicateWorkspace GUICommand = "workspace.duplicate"
1112
CmdExpandWorkspace GUICommand = "workspace.expand"
1213
CmdCreateServer GUICommand = "server.create"
1314
CmdUpdateServer GUICommand = "server.update"

business/entity/workspace.go

+2
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ const (
1313
WorkspaceTypeFolder WorkspaceType = "f"
1414
WorkspaceTypeServer WorkspaceType = "s"
1515
WorkspaceTypeQuery WorkspaceType = "r"
16+
17+
WorkspaceDuplicatePostfix = "Copy"
1618
)
1719

1820
var (

business/usecase/grpc.go

+1
Original file line numberDiff line numberDiff line change
@@ -225,6 +225,7 @@ func (uc *GrpcUseCase) connect(serverID int64) error {
225225
}
226226

227227
if createForward {
228+
uc.curConnectedServerID = 0
228229
uc.addInfoMessage(&entity.Info{Message: entity.MsgCreatingPortForward})
229230
uc.curServer.K8SPortForward.ErrHandler = uc.getPortForwardErrorHandler(*uc.curServer, serverID)
230231
control, err := uc.k8sClient.PortForward(uc.curServer.K8SPortForward)

business/usecase/workspace.go

+28
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ package usecase
44
import (
55
"context"
66
"errors"
7+
"fmt"
78

89
"github.com/forest33/warthog/business/entity"
910
"github.com/forest33/warthog/pkg/logger"
@@ -134,6 +135,33 @@ func (uc *WorkspaceUseCase) Delete(payload map[string]interface{}) *entity.GUIRe
134135
return uc.Get(nil)
135136
}
136137

138+
// Duplicate duplicates workspace item
139+
func (uc *WorkspaceUseCase) Duplicate(payload map[string]interface{}) *entity.GUIResponse {
140+
if payload == nil {
141+
return entity.ErrorGUIResponse(errors.New("nil payload"))
142+
}
143+
if _, ok := payload["id"]; !ok {
144+
return entity.ErrorGUIResponse(errors.New("no workspace id"))
145+
}
146+
147+
item, err := uc.workspaceRepo.GetByID(int64(payload["id"].(float64)))
148+
if err != nil {
149+
return entity.ErrorGUIResponse(errors.New("failed to get workspace item"))
150+
}
151+
152+
if item.Type != entity.WorkspaceTypeServer && item.Type != entity.WorkspaceTypeQuery {
153+
return entity.ErrorGUIResponse(errors.New("wrong workspace item type"))
154+
}
155+
156+
item.Title = fmt.Sprintf("%s %s", item.Title, entity.WorkspaceDuplicatePostfix)
157+
158+
if _, err := uc.workspaceRepo.Create(item); err != nil {
159+
return entity.ErrorGUIResponse(err)
160+
}
161+
162+
return uc.Get(nil)
163+
}
164+
137165
// GetBreadcrumb returns the breadcrumbs
138166
func (uc *WorkspaceUseCase) GetBreadcrumb(id int64) ([]string, error) {
139167
w, err := uc.workspaceRepo.Get()

deploy/app/events.go

+2
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,8 @@ func eventsHandler(r *entity.GUIRequest) *entity.GUIResponse {
2828
resp = workspaceUseCase.Get(payload)
2929
case entity.CmdSortingWorkspace:
3030
resp = workspaceUseCase.Sorting(payload)
31+
case entity.CmdDuplicateWorkspace:
32+
resp = workspaceUseCase.Duplicate(payload)
3133
case entity.CmdDeleteWorkspace:
3234
resp = workspaceUseCase.Delete(payload)
3335
case entity.CmdExpandWorkspace:

deploy/testserver/testserver

14 MB
Binary file not shown.

resources/js/server.js

-1
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ function loadServer(srv, show) {
7272

7373
astilectron.sendMessage(req, function (message) {
7474
if (message.payload.status !== "ok") {
75-
console.log("server ", message.payload.data.server_id, " - ", srv.id)
7675
if (isNull(currentServer) || (!isNull(message.payload.data) && !isNull(currentServer) && message.payload.data.server_id === currentServer.id)) {
7776
showQueryError(message.payload.error);
7877
currentServer = undefined;

resources/js/settings.modal.js

+7
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,10 @@ function saveSettings() {
4949
$("#settings-modal-form-request-timeout").val(),
5050
10
5151
),
52+
k8s_request_timeout: parseInt(
53+
$("#settings-modal-form-k8s-request-timeout").val(),
54+
10
55+
),
5256
max_loop_depth: parseInt(
5357
$("#settings-modal-form-max-loop-depth").val(),
5458
10
@@ -82,6 +86,9 @@ function showSettingsModal() {
8286
$("#settings-modal-form-request-timeout").val(
8387
currentSettings.request_timeout
8488
);
89+
$("#settings-modal-form-k8s-request-timeout").val(
90+
currentSettings.k8s_request_timeout
91+
);
8592
$("#settings-modal-form-max-loop-depth").val(currentSettings.max_loop_depth);
8693
$("#settings-modal-form-non-blocking-connection").prop(
8794
"checked",

resources/js/tree.js

+32
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,9 @@ function initTreeDrag() {
7373
case "delete":
7474
treeMenuDelete(node);
7575
break;
76+
case "duplicate":
77+
treeMenuDuplicate(node);
78+
break;
7679
}
7780
});
7881

@@ -303,6 +306,13 @@ function getTreeDropdown(node) {
303306
'" data-action="edit-server"><i class="bi bi-pen"></i> Edit</a></li>'
304307
)
305308
);
309+
menu.append(
310+
$(
311+
'<li><a class="dropdown-item" data-id="' +
312+
node.data.id +
313+
'" data-action="duplicate"><i class="bi bi bi-files"></i> Duplicate</a></li>'
314+
)
315+
);
306316
menu.append(
307317
$(
308318
'<li><a class="dropdown-item' +
@@ -314,6 +324,13 @@ function getTreeDropdown(node) {
314324
);
315325
break;
316326
case WorkspaceTypeQuery:
327+
menu.append(
328+
$(
329+
'<li><a class="dropdown-item" data-id="' +
330+
node.data.id +
331+
'" data-action="duplicate"><i class="bi bi bi-files"></i> Duplicate</a></li>'
332+
)
333+
);
317334
menu.append(
318335
$(
319336
'<li><a class="dropdown-item" data-id="' +
@@ -451,6 +468,21 @@ function treeMenuDelete(node) {
451468
});
452469
}
453470

471+
function treeMenuDuplicate(node) {
472+
let req = {
473+
name: "workspace.duplicate",
474+
payload: {
475+
id: node.data.id,
476+
},
477+
};
478+
astilectron.sendMessage(req, function (message) {
479+
if (message.payload.status !== "ok") {
480+
return;
481+
}
482+
showTree(message.payload.data);
483+
});
484+
}
485+
454486
function treeNodeExpand(node, expand) {
455487
let req = {
456488
name: "workspace.expand",

resources/modal.settings.html

+7
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,13 @@ <h5 class="modal-title" id="settingsModalLabel">Settings</h5>
2222
</div>
2323
</div>
2424

25+
<div class="row mb-3">
26+
<label for="settings-modal-form-k8s-request-timeout" class="col-sm-9 col-form-label">Kubernetes request timeout, seconds</label>
27+
<div class="col-sm-3">
28+
<input type="number" class="form-control" id="settings-modal-form-k8s-request-timeout" min="0">
29+
</div>
30+
</div>
31+
2532
<div class="row mb-3">
2633
<label for="settings-modal-form-max-loop-depth" class="col-sm-9 col-form-label">Maximum depth of looped messages, max 100</label>
2734
<div class="col-sm-3">

0 commit comments

Comments
 (0)