Skip to content
This repository has been archived by the owner on Jan 24, 2023. It is now read-only.

Commit

Permalink
Merge pull request #302 from SUSE/v3-ui-tweaks-2
Browse files Browse the repository at this point in the history
Fixes/Improvements following helm walkthrough #2
  • Loading branch information
nwmac committed Feb 5, 2020
2 parents 1e93924 + f0cb680 commit 962bfd7
Show file tree
Hide file tree
Showing 31 changed files with 331 additions and 191 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ <h1>Dashboard Configuration</h1>
<div class="kubedash__ready" *ngIf="status.service && status.serviceAccount">
<div class="kubedash__access">
<app-boolean-indicator [showText]="false" [isTrue]="true" type="yes-no"></app-boolean-indicator>
<div>Kubernetes Dashboard is installed and a Service Account exists - you can access the dashboard using the 'View Dashboard' button on the Summary view for this cluster.</div>
<div>Kubernetes Dashboard is installed and a Service Account exists - you can access the dashboard using the
'View Dashboard' button on the Summary view for this cluster.</div>
</div>
<button *ngIf="kubeEndpointService.kubeDashboardConfigured$ | async" [routerLink]="dashboardLink" mat-button>
<mat-icon>dashboard</mat-icon>
Expand All @@ -31,7 +32,8 @@ <h1>Dashboard Configuration</h1>
<mat-card-header>
<mat-card-title>Kubernetes Dashboard Installation</mat-card-title>
<div class="kubedash__card-icon">
<app-boolean-indicator *ngIf="status.service" [showText]="false" [isTrue]="true" type="yes-no"></app-boolean-indicator>
<app-boolean-indicator *ngIf="status.service" [showText]="false" [isTrue]="true" type="yes-no">
</app-boolean-indicator>
<mat-icon *ngIf="!status.service">warning</mat-icon>
</div>
</mat-card-header>
Expand All @@ -41,15 +43,17 @@ <h1>Dashboard Configuration</h1>
<h2 class="kubedash__option">Manually install the Kubernetes Dashboard</h2>
<div class="kubedash__option-block">
<p>Manually install the Kubernetes Dashboard into your cluster. Please refer to
<a class="kubedash__card-link" target="_blank" href="https://github.com/kubernetes/dashboard#getting-started">https://github.com/kubernetes/dashboard#getting-started</a>.
<a class="kubedash__card-link" target="_blank"
href="https://github.com/kubernetes/dashboard#getting-started">https://github.com/kubernetes/dashboard#getting-started</a>.
</p>
</div>
</div>

<h2 class="kubedash__option">Install the Kubernetes Dashboard from Stratos</h2>
<div class="kubedash__option-block">
<p>Stratos will download the Dashboard yaml from the Dashboard GitHub repository and install it for you.</p>
<div class="kubedash__buttons">
<button (click)="installDashboard()" [disabled]="isBusy$ | async" mat-button color="primary">Install Dashboard</button>
<button (click)="installDashboard()" [disabled]="isBusy$ | async" mat-button color="primary">Install
Dashboard</button>
</div>
</div>
</mat-card-content>
Expand All @@ -62,7 +66,8 @@ <h2 class="kubedash__option">Install the Kubernetes Dashboard from Stratos</h2>
<app-metadata-item label="Namespace">{{ status.service.namespace }}</app-metadata-item>
</div>
<div class="kubedash__buttons" *ngIf="status.stratosInstalled">
<button (click)="deleteDashboard()" [disabled]="isBusy$ | async" mat-button color="primary">Delete Dashboard</button>
<button (click)="deleteDashboard()" [disabled]="isBusy$ | async" mat-button color="primary">Delete
Dashboard</button>
</div>
</mat-card-content>
</mat-card>
Expand All @@ -72,55 +77,69 @@ <h2 class="kubedash__option">Install the Kubernetes Dashboard from Stratos</h2>
<mat-card-header>
<mat-card-title>Service Account</mat-card-title>
<div class="kubedash__card-icon">
<app-boolean-indicator *ngIf="status.serviceAccount" [showText]="false" [isTrue]="true" type="yes-no"></app-boolean-indicator>
<app-boolean-indicator *ngIf="status.serviceAccount" [showText]="false" [isTrue]="true" type="yes-no">
</app-boolean-indicator>
<mat-icon *ngIf="!status.serviceAccount">warning</mat-icon>
</div>
</mat-card-header>

<mat-card-content *ngIf="!status.serviceAccount">
<div *ngIf="(isAzure$ | async)">
<p class="kubedash__warn"><mat-icon>warning</mat-icon>You are using the Azure deployed version of Kubernetes Dashboard.</p>
<p>This version uses the Service Account 'kubernetes-dashboard' to access the Dashboard UI. You will need to create a Cluster Role Binding as described
<a class="kubedash__card-link" target="_blank" href="https://docs.microsoft.com/en-us/azure/aks/kubernetes-dashboard" >here</a> to give this account permissions.
<p class="kubedash__warn">
<mat-icon>warning</mat-icon>You are using the Azure deployed version of Kubernetes Dashboard.
</p>
<p>This version uses the Service Account 'kubernetes-dashboard' to access the Dashboard UI. You will need to
create a Cluster Role Binding as described
<a class="kubedash__card-link" target="_blank"
href="https://docs.microsoft.com/en-us/azure/aks/kubernetes-dashboard">here</a> to give this account
permissions.
</p>
<p>You also need to add the following label to the Service Account in order for Stratos to know the account is configured:</p>
<p>You also need to add the following label to the Service Account in order for Stratos to know the account is
configured:</p>
<div class="kubedash__label">stratos-role: kubernetes-dashboard-user</div>
<p>You can add this label with the following command:</p>
<div class="kubedash__label">kubectl label serviceaccount -n kube-system kubernetes-dashboard stratos-role=kubernetes-dashboard-user</div>
<div class="kubedash__label">kubectl label serviceaccount -n kube-system kubernetes-dashboard
stratos-role=kubernetes-dashboard-user</div>
</div>
<div *ngIf="!(isAzure$ | async)">
<p>Service Account not found - you can create one manually or Stratos can do this for you.</p>
<h2 class="kubedash__option">Manually create a Service Account</h2>
<div class="kubedash__option-block">
<p>Create a Service Account with the appropriate permissions that will be used by the Dashboard to
access your Kubernetes cluster.</p>
access your Kubernetes cluster.</p>
<p>Ensure that this token is labelled with the label:</p>
<div class="kubedash__label">stratos-role: kubernetes-dashboard-user</div>
</div>
</div>
<h2 class="kubedash__option">Create a Service Account from Stratos</h2>
<div class="kubedash__option-block">
<div *ngIf="!status.service">
<p>Stratos can create a service account for accessing the Kubernetes Dashboard - please install the Dashboard first to enable this capability.</p>
<p>Stratos can create a service account for accessing the Kubernetes Dashboard - please install the
Dashboard first to enable this capability.</p>
</div>
<div *ngIf="status.service">
<p>Stratos will create a service account with a cluster role binding to the cluster-admin role. This user will
<p>Stratos will create a service account with a cluster role binding to the cluster-admin role. This user
will
have full permissions over the cluster.</p>
<p class="kubedash__warn"><mat-icon>warning</mat-icon>Please make sure you understand the risks involved</p>
<p class="kubedash__warn">
<mat-icon>warning</mat-icon>Please make sure you understand the risks involved
</p>
<div class="kubedash__buttons">
<button (click)="createServiceAccount()" [disabled]="isBusy$ | async" mat-button color="primary">Create Service Account</button>
<button (click)="createServiceAccount()" [disabled]="isBusy$ | async" mat-button color="primary">Create
Service Account</button>
</div>
</div>
</div>
</div>
</div>
</mat-card-content>

<mat-card-content *ngIf="status.serviceAccount">
<p>A Service Account was found:</p>
<p>A Service Account was found:</p>
<div class="kubedash__metadata">
<app-metadata-item label="Name">{{ status.serviceAccount.metadata.name }}</app-metadata-item>
<app-metadata-item label="Namespace">{{ status.serviceAccount.metadata.namespace }}</app-metadata-item>
<div class="kubedash__buttons">
<button (click)="deleteServiceAccount()" [disabled]="isBusy$ | async" mat-button color="primary">Delete Service Account</button>
<button (click)="deleteServiceAccount()" [disabled]="isBusy$ | async" mat-button color="primary">Delete
Service Account</button>
</div>
</div>
</mat-card-content>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,19 @@
import { IHeaderBreadcrumb } from './../../../../shared/components/page-header/page-header.types';
import {
KubernetesEndpointService
} from '../../services/kubernetes-endpoint.service';
import { KubernetesService } from '../../services/kubernetes.service';
import { ActivatedRoute } from '@angular/router';
import { BaseKubeGuid } from '../../kubernetes-page.types';
import { HttpClient } from '@angular/common/http';
import { Component, OnDestroy } from '@angular/core';
import { Observable, BehaviorSubject, Subscription } from 'rxjs';
import { map, distinctUntilChanged, filter } from 'rxjs/operators';
import { KubeDashboardStatus } from '../../store/kubernetes.effects';
import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material';
import { ActivatedRoute } from '@angular/router';
import { BehaviorSubject, Observable, Subscription } from 'rxjs';
import { distinctUntilChanged, filter, map } from 'rxjs/operators';

import { ConfirmationDialogConfig } from '../../../../shared/components/confirmation-dialog.config';
import { HttpClient } from '@angular/common/http';
import { ConfirmationDialogService } from '../../../../shared/components/confirmation-dialog.service';
import { MatSnackBar, MatSnackBarRef, SimpleSnackBar } from '@angular/material';
import { BaseKubeGuid } from '../../kubernetes-page.types';
import { KubernetesEndpointService } from '../../services/kubernetes-endpoint.service';
import { KubernetesService } from '../../services/kubernetes.service';
import { KubeDashboardStatus } from '../../store/kubernetes.effects';
import { IHeaderBreadcrumb } from './../../../../shared/components/page-header/page-header.types';

type MessageUpdater = (msg: string) => void;
type ReadyFilter = (status: KubeDashboardStatus) => boolean;

@Component({
selector: 'app-kubedash-configuration',
Expand Down Expand Up @@ -94,9 +92,9 @@ export class KubedashConfigurationComponent implements OnDestroy {
private httpClient: HttpClient,
private confirmDialog: ConfirmationDialogService,
private snackBar: MatSnackBar,
) {
) {
this.kubeDashboardStatus$ = kubeEndpointService.kubeDashboardStatus$;
// Clear the updatind status when we get back new dashboard status
// Clear the updating status when we get back new dashboard status
this.sub = this.kubeDashboardStatus$.pipe(distinctUntilChanged()).subscribe(status => {
if (status !== null) {
this.isUpdatingStatus = false;
Expand Down Expand Up @@ -135,11 +133,11 @@ export class KubedashConfigurationComponent implements OnDestroy {

public doCreateServiceAccount() {
this.makeRequest('post',
'serviceAccount',
'Creating Service Account ...',
'Service Account created', 'An error occurred creating the Service Account',
this.serviceAccountBusy$,
(msg) => this.serviceAccountMsg = msg
'serviceAccount',
'Creating Service Account ...',
'Service Account created', 'An error occurred creating the Service Account',
this.serviceAccountBusy$,
(msg) => this.serviceAccountMsg = msg
);
}

Expand All @@ -165,11 +163,11 @@ export class KubedashConfigurationComponent implements OnDestroy {

public doInstallDashboard() {
this.makeRequest('post',
'installation',
'Installing Kubernetes Dashboard ...',
'Kubernetes Dashboard installed', 'An error occurred installing the Kubernetes Dashboard',
this.dashboardUIBusy$,
(msg) => this.dashboardUIMsg = msg
'installation',
'Installing Kubernetes Dashboard ...',
'Kubernetes Dashboard installed', 'An error occurred installing the Kubernetes Dashboard',
this.dashboardUIBusy$,
(msg) => this.dashboardUIMsg = msg
);
}

Expand All @@ -181,43 +179,49 @@ export class KubedashConfigurationComponent implements OnDestroy {

public doDeleteDashboard() {
this.makeRequest('delete',
'installation',
'Deleting Kubernetes Dashboard ...',
'Kubernetes Dashboard deleted', 'An error occurred deleting the Kubernetes Dashboard',
this.dashboardUIBusy$,
(msg) => this.dashboardUIMsg = msg
'installation',
'Deleting Kubernetes Dashboard ...',
'Kubernetes Dashboard deleted', 'An error occurred deleting the Kubernetes Dashboard',
this.dashboardUIBusy$,
(msg) => this.dashboardUIMsg = msg
);
}

private makeRequest(method: string, op: string, busyMsg: string, okMsg: string, errorMsg: string,
busy: BehaviorSubject<boolean>, msgUpdater: MessageUpdater) {
const guid = this.kubeEndpointService.kubeGuid;
const url = `/pp/v1/kubedash/${guid}/${op}`;
let obs;
msgUpdater(busyMsg);
busy.next(true);
this.isBusy$.next(true);
if (method === 'post') {
obs = this.httpClient.post(url, {});
} else if (method === 'delete') {
obs = this.httpClient.delete(url, {});
} else {
console.error('Unsupported http method');
return;
}

obs.subscribe(() => {
this.snackBar.open(okMsg, 'Dismiss', { duration: 3000 });
busy.next(false);
this.refresh();
}, (e) => {
let msg = errorMsg;
if (e && e.error && e.error.error) {
msg = e.error.error;
}
this.snackBarRef = this.snackBar.open(msg, 'Dismiss');
busy.next(false);
this.refresh();
private makeRequest(
method: string,
op: string,
busyMsg: string,
okMsg: string,
errorMsg: string,
busy: BehaviorSubject<boolean>,
msgUpdater: MessageUpdater) {
const guid = this.kubeEndpointService.kubeGuid;
const url = `/pp/v1/kubedash/${guid}/${op}`;
let obs;
msgUpdater(busyMsg);
busy.next(true);
this.isBusy$.next(true);
if (method === 'post') {
obs = this.httpClient.post(url, {});
} else if (method === 'delete') {
obs = this.httpClient.delete(url, {});
} else {
console.error('Unsupported http method');
return;
}

obs.subscribe(() => {
this.snackBar.open(okMsg, 'Dismiss', { duration: 3000 });
busy.next(false);
this.refresh();
}, (e) => {
let msg = errorMsg;
if (e && e.error && e.error.error) {
msg = e.error.error;
}
this.snackBarRef = this.snackBar.open(msg, 'Dismiss');
busy.next(false);
this.refresh();
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,9 @@ export class KubernetesNamespacePodsListConfigService extends BaseKubernetesPods
kubeId: BaseKubeGuid,
public kubeNamespaceService: KubernetesNamespaceService,
) {
super(kubeId.guid);
super(kubeId.guid, [
BaseKubernetesPodsListConfigService.namespaceColumnId,
]);
this.podsDataSource = new KubernetesNamespacePodsDataSource(store, kubeId, this, kubeNamespaceService);
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,16 +31,17 @@ export class KubernetesNamespacesListConfigService implements IListConfig<Kubern
},
cellFlex: '5',
},
{
columnId: 'view', headerCell: () => 'Dashboard',
cellDefinition: {
getValue: () => 'View',
getLink: (row: KubernetesNamespace) => {
return `/kubernetes/${this.kubeId.guid}/dashboard/overview?namespace=${row.metadata.name}`;
},
},
cellFlex: '3',
},
// FIXME: Hide link until the link is fixed
// {
// columnId: 'view', headerCell: () => 'Dashboard',
// cellDefinition: {
// getValue: () => 'View',
// getLink: (row: KubernetesNamespace) => {
// return `/kubernetes/${this.kubeId.guid}/dashboard/overview?namespace=${row.metadata.name}`;
// },
// },
// cellFlex: '3',
// },
{
columnId: 'pods', headerCell: () => 'Pods',
cellComponent: KubeNamespacePodCountComponent,
Expand Down Expand Up @@ -85,7 +86,7 @@ export class KubernetesNamespacesListConfigService implements IListConfig<Kubern
) {
this.podsDataSource = new KubernetesNamespacesDataSource(store, this.kubeId, this);

const hasDashboard = kubeService.kubeDashboardEnabled$.pipe(
const hasDashboard = kubeService.kubeDashboardConfigured$.pipe(
first(),
tap((enabled) => {
if (!enabled) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@ export class KubernetesNodePodsListConfigService extends BaseKubernetesPodsListC
kubeId: BaseKubeGuid,
public kubeNodeService: KubernetesNodeService,
) {
super(kubeId.guid);
super(kubeId.guid, [
BaseKubernetesPodsListConfigService.nodeColumnId
]);
this.podsDataSource = new KubernetesNodePodsDataSource(store, kubeId, this, kubeNodeService);
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,4 @@
<div class="kube-node-capacity">
<div class="legend-items-container">
<div class="legend-items">
<div class="legend-item" tabindex="-1">
<div class="item-value">{{ row.status.capacity.pods }}</div>
<div class="item-label">Pods</div>
</div>
</div>
</div>

<div class="legend-items-container">
<div class="legend-items">
<div class="legend-item" tabindex="-1">
Expand All @@ -25,4 +16,4 @@
</div>
</div>
</div>
</div>
</div>
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ export class KubernetesNodesListConfigService implements IListConfig<KubernetesN
{
columnId: 'capacity', headerCell: () => 'Capacity',
cellComponent: KubernetesNodeCapacityComponent,
cellFlex: '4',
cellFlex: '3',
},
// Display labels as the usual chip list
// {
Expand Down
Original file line number Diff line number Diff line change
@@ -1 +1 @@
<div class="pod-status {{ style }}">{{ row.status.phase }}</div>
<div class="pod-status {{ style }}">{{ row.expandedStatus.status }}</div>
Loading

0 comments on commit 962bfd7

Please sign in to comment.