Skip to content

Commit

Permalink
feat: add connecting deployment target again (#307)
Browse files Browse the repository at this point in the history
Signed-off-by: Jakob Steiner <jakob.steiner@glasskube.eu>
  • Loading branch information
kosmoz authored Jan 17, 2025
1 parent 96b6651 commit fb18211
Show file tree
Hide file tree
Showing 6 changed files with 65 additions and 32 deletions.
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import {Component, inject, Input} from '@angular/core';
import {firstValueFrom} from 'rxjs';
import {displayedInToast, getFormDisplayedError} from '../../../util/errors';
import {DeploymentTargetsService} from '../../services/deployment-targets.service';
import {ToastService} from '../../services/toast.service';
import {DeploymentTarget} from '../../types/deployment-target';

@Component({
Expand All @@ -11,21 +12,29 @@ export class ConnectInstructionsComponent {
@Input({required: true}) deploymentTarget!: DeploymentTarget;

private readonly deploymentTargets = inject(DeploymentTargetsService);
private readonly toast = inject(ToastService);

modalConnectCommand?: string;
modalTargetId?: string;
modalTargetSecret?: string;
commandCopied = false;

ngOnInit() {
this.deploymentTargets.requestAccess(this.deploymentTarget.id!).subscribe((response) => {
this.modalConnectCommand =
this.deploymentTarget.type === 'docker'
? `curl "${response.connectUrl}" | docker compose -f - up -d`
: `kubectl apply -n ${this.deploymentTarget.namespace} -f "${response.connectUrl}"`;
this.modalTargetId = response.targetId;
this.modalTargetSecret = response.targetSecret;
});
this.deploymentTargets.requestAccess(this.deploymentTarget.id!).subscribe(
(response) => {
this.modalConnectCommand =
this.deploymentTarget.type === 'docker'
? `curl "${response.connectUrl}" | docker compose -f - up -d`
: `kubectl apply -n ${this.deploymentTarget.namespace} -f "${response.connectUrl}"`;
this.modalTargetId = response.targetId;
this.modalTargetSecret = response.targetSecret;
},
(e) => {
if (!displayedInToast(e)) {
this.toast.error(getFormDisplayedError(e) ?? e);
}
}
);
}

async copyConnectCommand() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,18 +147,12 @@
}
<td
class="px-4 py-3 font-medium text-gray-900 whitespace-nowrap dark:text-white flex justify-end space-x-2">
@if (!(auth.hasRole('vendor') && dt.createdBy?.userRole === 'customer')) {
@if (dt.currentStatus) {
@if (auth.hasRole('customer') || dt.createdBy?.userRole === 'vendor') {
@if (dt.currentStatus && !(dt.currentStatus | isStale)) {
<button
type="button"
(click)="newDeployment(dt, deploymentModal)"
aria-controls="manage-deployment-target-drawer"
class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-60 disabled:cursor-not-allowed"
[title]="
auth.hasRole('vendor') && dt.createdBy?.userRole === 'customer'
? 'Must be deployed by customer'
: undefined
">
class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-60 disabled:cursor-not-allowed">
<fa-icon
[icon]="shipIcon"
class="h-5 w-5 mr-2 -ml-0.5 text-gray-500 dark:text-gray-400"></fa-icon>
Expand All @@ -167,14 +161,13 @@
} @else {
<button
type="button"
(click)="showModal(instructionsModal)"
class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-60 disabled:cursor-not-allowed"
[title]="
auth.hasRole('vendor') && dt.createdBy?.userRole === 'customer'
? 'Must be deployed by customer'
: undefined
">
Connection instructions
(click)="openInstructionsModal(dt, instructionsModal)"
class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700 disabled:opacity-60 disabled:cursor-not-allowed">
@if (dt.currentStatus) {
Reconnect
} @else {
Connection instructions
}
</button>
}
@if (dt.deployment) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -385,6 +385,21 @@ export class DeploymentTargetsComponent implements OnInit, AfterViewInit, OnDest
}
}

async openInstructionsModal(deploymentTarget: DeploymentTarget, modal: TemplateRef<any>) {
if (deploymentTarget.currentStatus !== undefined) {
if (
!(await firstValueFrom(
this.overlay.confirm(
`Warning: If you continue, the previous authentication secret for ${deploymentTarget.name} becomes invalid. Continue?`
)
))
) {
return;
}
}
this.showModal(modal);
}

public async updateDeploymentTargetAgent(dt: DeploymentTarget): Promise<void> {
try {
const agentVersions = await firstValueFrom(this.agentVersions$);
Expand Down
12 changes: 9 additions & 3 deletions internal/handlers/agent.go
Original file line number Diff line number Diff line change
Expand Up @@ -60,9 +60,15 @@ func connectHandler() http.HandlerFunc {
log := internalctx.GetLogger(ctx)
deploymentTarget := internalctx.GetDeploymentTarget(ctx)

if deploymentTarget.CurrentStatus != nil {
log.Warn("deployment target has already been connected")
http.Error(w, "deployment target has already been connected", http.StatusBadRequest)
if deploymentTarget.CurrentStatus != nil &&
deploymentTarget.CurrentStatus.CreatedAt.Add(2*env.AgentInterval()).After(time.Now()) {
http.Error(
w,
fmt.Sprintf(
"deployment target is already connected and appears to be still running (last status %v)",
deploymentTarget.CurrentStatus.CreatedAt),
http.StatusBadRequest,
)
return
}

Expand Down
15 changes: 12 additions & 3 deletions internal/handlers/deployment_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"fmt"
"net/http"
"net/url"
"time"

"github.com/getsentry/sentry-go"
"github.com/glasskube/cloud/internal/auth"
Expand Down Expand Up @@ -130,9 +131,17 @@ func createAccessForDeploymentTarget(w http.ResponseWriter, r *http.Request) {
log := internalctx.GetLogger(ctx)
deploymentTarget := internalctx.GetDeploymentTarget(ctx)

if deploymentTarget.CurrentStatus != nil {
log.Warn("access key cannot be regenerated because deployment target has already been connected")
w.WriteHeader(http.StatusBadRequest)
if deploymentTarget.CurrentStatus != nil &&
deploymentTarget.CurrentStatus.CreatedAt.Add(2*env.AgentInterval()).After(time.Now()) {
http.Error(
w,
fmt.Sprintf(
"access key cannot be regenerated because deployment target is already connected "+
"and seems to be still running (last connection at %v)",
deploymentTarget.CurrentStatus.CreatedAt,
),
http.StatusBadRequest,
)
return
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -92,6 +92,7 @@ spec:
selector:
matchLabels:
app: glasskube-cloud-agent
replicas: 1
strategy:
type: Recreate
template:
Expand Down

0 comments on commit fb18211

Please sign in to comment.