Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Helm: Allow users to view and use repositories from Helm Hub #463

Merged
merged 48 commits into from
Sep 11, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
48 commits
Select commit Hold shift + click to select a range
3c157d1
Improve presentation and fix issue with development versions
nwmac Aug 25, 2020
46732d8
Merge remote-tracking branch 'origin/improve-monocular-ui' into helm-…
nwmac Aug 25, 2020
641ccf8
WIP
richard-cox Aug 26, 2020
303bbb7
Add support for Helm Upgrade and Helm history
nwmac Aug 27, 2020
62d1a77
Remove console logging
nwmac Aug 27, 2020
d2dbafd
Add comment
nwmac Aug 27, 2020
cc8e2ac
Minor tweaks following self-review
nwmac Aug 27, 2020
dc24e61
Merge remote-tracking branch 'origin/master' into helm-hub
richard-cox Aug 27, 2020
ac18f0b
WIP
richard-cox Aug 27, 2020
d665348
Merge remote-tracking branch 'origin/master' into helm-hub
richard-cox Aug 28, 2020
adcd11a
fix install button
richard-cox Aug 28, 2020
43b2c33
Fix actual helm install
richard-cox Aug 28, 2020
a0ab8b6
Remove helm repos view
richard-cox Aug 28, 2020
fd2ee0f
Show per endpoint type actions in endpoints table
richard-cox Aug 28, 2020
ffd0de0
Tidy up registration step
richard-cox Sep 1, 2020
8042df9
Tidy up provider interceptor pattern
richard-cox Sep 1, 2020
7916f8a
Tidy up services, fix charts list filter by repo/helm hub
richard-cox Sep 1, 2020
7247090
Add endpoint unRegisterable, make helm types sub types, tidy up
richard-cox Sep 1, 2020
412fbf2
Remove debug logging
nwmac Sep 2, 2020
c8250ee
Merge remote-tracking branch 'origin/master' into helm-features
nwmac Sep 2, 2020
cffb053
Fix whitespace
nwmac Sep 2, 2020
20d79e0
Minor tidy ups
nwmac Sep 2, 2020
d1915b8
Merge remote-tracking branch 'origin/master' into helm-features
nwmac Sep 2, 2020
4c09409
Fix compile issue
nwmac Sep 2, 2020
9dcdcce
Fixed versions again, and bugs following subtype split
richard-cox Sep 2, 2020
043c5fd
Merge remote-tracking branch 'origin/master' into helm-hub
richard-cox Sep 2, 2020
509e018
Fix unit tests
richard-cox Sep 2, 2020
e815dc4
Add db migration script to update existing helm endpoints with repo s…
richard-cox Sep 2, 2020
9e7e679
Fix front-end unit tests
nwmac Sep 3, 2020
0f2e499
Always show upgrade button
nwmac Sep 7, 2020
bb89eb5
Minor entity store type updates
richard-cox Sep 7, 2020
6409469
Convert unRegisterable to registeredLimit
richard-cox Sep 7, 2020
559ecc4
Changes following review
richard-cox Sep 8, 2020
1744b9a
Merge remote-tracking branch 'origin/master' into helm-hub
richard-cox Sep 8, 2020
150da8a
Fix display of helm type in favourite cards
richard-cox Sep 8, 2020
857c54c
Multiple Fixes
richard-cox Sep 8, 2020
b844e8c
Align icons in workload summary page
richard-cox Sep 8, 2020
14125c2
Fix lint failures
richard-cox Sep 8, 2020
f5eb911
Merge remote-tracking branch 'origin/master' into helm-features
nwmac Sep 9, 2020
ed15df6
Address PR feedback
nwmac Sep 9, 2020
ac5625a
Revert
nwmac Sep 9, 2020
7114563
Remove description when checking for similar charts
nwmac Sep 10, 2020
e85f7c2
Only show button when the helm chart is available
nwmac Sep 10, 2020
a357a83
Merge remote-tracking branch 'origin/helm-features' into helm-hub
richard-cox Sep 10, 2020
77869e1
Improve types, start work on helm hub upgrade
richard-cox Sep 10, 2020
19c6363
Fixes following merge
richard-cox Sep 10, 2020
d97a270
Merge remote-tracking branch 'origin/master' into helm-hub
richard-cox Sep 10, 2020
520aae9
Remove TODOs
richard-cox Sep 10, 2020
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 0 additions & 3 deletions src/frontend/packages/core/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -89,9 +89,6 @@ const storeDebugImports = environment.production ? [] : [
})
class AppStoreDebugModule { }

/**
* `HttpXsrfTokenExtractor` which retrieves the token from a cookie.
*/

@NgModule({
declarations: [
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import { Component } from '@angular/core';
import { Store } from '@ngrx/store';
import { Observable } from 'rxjs';
import { first, map } from 'rxjs/operators';
import { combineLatest, filter, first, map } from 'rxjs/operators';

import { RouterNav } from '../../../../../../store/src/actions/router.actions';
import { GeneralEntityAppState } from '../../../../../../store/src/app-state';
import { entityCatalog } from '../../../../../../store/src/entity-catalog/entity-catalog';
import {
StratosCatalogEndpointEntity,
} from '../../../../../../store/src/entity-catalog/entity-catalog-entity/entity-catalog-entity';
import { IStratosEndpointDefinition } from '../../../../../../store/src/entity-catalog/entity-catalog.types';
import { selectSessionData } from '../../../../../../store/src/reducers/auth.reducer';
import { stratosEntityCatalog } from '../../../../../../store/src/stratos-entity-catalog';
import { BASE_REDIRECT_QUERY } from '../../../../shared/components/stepper/stepper.types';
import { TileConfigManager } from '../../../../shared/components/tile/tile-selector.helpers';
import { ITileConfig, ITileData } from '../../../../shared/components/tile/tile-selector.types';
Expand All @@ -17,6 +21,10 @@ interface ICreateEndpointTilesData extends ITileData {
parentType: string;
}

type EndpointsByType = {
[endpointType: string]: number,
};

@Component({
selector: 'app-create-endpoint-base-step',
templateUrl: './create-endpoint-base-step.component.html',
Expand Down Expand Up @@ -67,7 +75,7 @@ export class CreateEndpointBaseStepComponent {
}
// Both A & B are equal. Unlikely.
return 0;
}
};

get selectedTile() {
return this.pSelectedTile;
Expand All @@ -83,13 +91,15 @@ export class CreateEndpointBaseStepComponent {
}));
}
}
constructor(public store: Store<GeneralEntityAppState>, ) {
constructor(public store: Store<GeneralEntityAppState>,) {
// Need to filter the endpoint types on the tech preview flag
this.tileSelectorConfig$ = store.select(selectSessionData()).pipe(
combineLatest(this.getEndpointTypesByCount()),
first(),
map(sessionData => {
map(([sessionData, endpointTypesByCount]) => {
const techPreviewIsEnabled = sessionData.config.enableTechPreview || false;
return entityCatalog.getAllEndpointTypes(techPreviewIsEnabled)
.filter(endpoint => this.filterByEndpointCount(endpoint, endpointTypesByCount))
.sort((endpointA, endpointB) => this.sortEndpointTiles(endpointA.definition, endpointB.definition))
.map(catalogEndpoint => {
const endpoint = catalogEndpoint.definition;
Expand All @@ -112,4 +122,38 @@ export class CreateEndpointBaseStepComponent {
);
}

private getEndpointDefinitionKey = (type: string, subType: string): string => type + '_sep_' + subType;
private getEndpointTypesByCount = (): Observable<EndpointsByType> =>
stratosEntityCatalog.endpoint.store.getAll.getPaginationService().entities$.pipe(
filter(endpoints => !!endpoints),
map(endpoints => {
const endpointsByType: { [endpointType: string]: number; } = {};
return endpoints.reduce((res, endpoint) => {
const type = this.getEndpointDefinitionKey(endpoint.cnsi_type, endpoint.sub_type);
if (!res[type]) {
res[type] = 0;
}
res[type]++;
return res;
}, endpointsByType);
}),
);
private filterByEndpointCount = (endpoint: StratosCatalogEndpointEntity, endpointTypesByCount: EndpointsByType) => {
// No limit applied, always show endpoint
if (typeof endpoint.definition.registeredLimit !== 'number') {
return true;
}
// Zero limit, never show endpoint
if (endpoint.definition.registeredLimit === 0) {
return false;
}

// Check that the limit is not exceeded by endpoints already registered
const type = endpoint.definition.parentType ?
this.getEndpointDefinitionKey(endpoint.definition.parentType, endpoint.definition.type) :
this.getEndpointDefinitionKey(endpoint.definition.type, '');
const count = endpointTypesByCount[type] || 0;
return count < endpoint.definition.registeredLimit;
};

}
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
font-size: 40px;
height: 40px;
margin-right: 12px;
text-align: center;
width: 40px;
}
&__label {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,6 @@
font-size: 14px;
font-weight: normal;
margin-right: 8px;
margin-top: -2px;
padding: 2px 4px;
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<mat-card class="meta-card {{status$ && statusBackground? (status$ | async): '' }}" [ngClass]="{'meta-card-pointer': clickAction}"
(click)="clickAction ? clickAction() : null">
<mat-card class="meta-card {{status$ && statusBackground? (status$ | async): '' }}"
[ngClass]="{'meta-card-pointer': clickAction}" (click)="clickAction ? clickAction() : null">
<div *ngIf="isDeleting$ | async" class="meta-card__deleting-overlay">
<div class="meta-card__deleting-overlay-inner">
<div class="meta-card__deleting-text">Deleting</div>
Expand All @@ -9,7 +9,8 @@
<app-card-status *ngIf="status$" [status$]="status$">
</app-card-status>
<mat-card-header class="meta-card__header" *ngIf="title">
<div [ngClass]="statusIconByTitle ? 'meta-card__header-container__title--with-icon' : 'meta-card__header-container__title'">
<div
[ngClass]="statusIconByTitle ? 'meta-card__header-container__title--with-icon' : 'meta-card__header-container__title'">
<div
[ngClass]="statusIconByTitle ? 'meta-card__header-container__title__content--with-icon' : 'meta-card__header-container__title__content'">
<ng-container *ngTemplateOutlet="title.content"></ng-container>
Expand All @@ -18,20 +19,24 @@
<ng-container *ngTemplateOutlet="statusIconTmple"></ng-container>
</div>
</div>
<app-entity-favorite-star [confirmRemoval]="confirmFavoriteRemoval" class="meta-card__favorite" *ngIf="favorite" [favorite]="favorite">
<app-entity-favorite-star [confirmRemoval]="confirmFavoriteRemoval" class="meta-card__favorite" *ngIf="favorite"
[favorite]="favorite">
</app-entity-favorite-star>
<div class="meta-card__header-container__actions" *ngIf="actionMenu && (showMenu$ | async)" appClickStopPropagation>
<button mat-icon-button class="meta-card__header__button" color="basic" [matMenuTriggerFor]="menu" [disabled]="isDeleting$ | async">
<button mat-icon-button class="meta-card__header__button" color="basic" [matMenuTriggerFor]="menu"
[disabled]="isDeleting$ | async">
<mat-icon>more_vert</mat-icon>
</button>
<mat-menu class="meta-card__header__popup" #menu="matMenu" xPosition="before" >
<mat-menu class="meta-card__header__popup" #menu="matMenu" xPosition="before">
<ng-container *ngFor="let menuItem of actionMenu">
<button class="meta-card__header__popup__btn" [disabled]="menuItem.disabled | async" mat-menu-item *ngIf="menuItem.can | async"
(click)="menuItem.action()">
<mat-icon *ngIf="menuItem.icon">{{menuItem.icon}}</mat-icon>
<span>{{menuItem.label}}</span>
</button>
<div *ngIf="menuItem.separator" class="meta-card__header__popup-separator"></div>
<ng-container *ngIf="menuItem.can | async">
<button *ngIf="!menuItem.separator" class="meta-card__header__popup__btn"
[disabled]="menuItem.disabled | async" mat-menu-item (click)="menuItem.action()">
<mat-icon *ngIf="menuItem.icon">{{menuItem.icon}}</mat-icon>
<span>{{menuItem.label}}</span>
</button>
<div *ngIf="menuItem.separator" class="meta-card__header__popup-separator"></div>
</ng-container>
</ng-container>
</mat-menu>
</div>
Expand All @@ -48,6 +53,7 @@
</mat-card-content>
</mat-card>
<ng-template #statusIconTmple>
<app-application-state-icon *ngIf="statusIcon && status$" [status]="status$ | async" matTooltip="{{statusIconTooltip}}">
<app-application-state-icon *ngIf="statusIcon && status$" [status]="status$ | async"
matTooltip="{{statusIconTooltip}}">
</app-application-state-icon>
</ng-template>
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Component, ContentChild, ContentChildren, Input, OnDestroy, QueryList } from '@angular/core';
import { combineLatest, Observable, of as observableOf, Subscription } from 'rxjs';
import { combineLatest, Observable, of as observableOf, of, Subscription } from 'rxjs';
import { first, map, tap } from 'rxjs/operators';

import { FavoritesConfigMapper } from '../../../../../../../../store/src/favorite-config-mapper';
Expand All @@ -13,7 +13,7 @@ import { MetaCardItemComponent } from '../meta-card-item/meta-card-item.componen
import { MetaCardTitleComponent } from '../meta-card-title/meta-card-title.component';


export function createMetaCardMenuItemSeparator() {
export function createMetaCardMenuItemSeparator(): MenuItem {
return {
label: '-',
separator: true,
Expand Down Expand Up @@ -86,15 +86,18 @@ export class MetaCardComponent implements OnDestroy {
this.pActionMenu = actionMenu.map(menuItem => {
if (!menuItem.can) {
menuItem.separator = menuItem.label === '-';
menuItem.can = observableOf(!menuItem.separator);
menuItem.can = of(true);
}
if (!menuItem.disabled) {
menuItem.disabled = observableOf(false);
}
return menuItem;
});

this.showMenu$ = combineLatest(actionMenu.map(menuItem => menuItem.can)).pipe(
const nonSeparators = actionMenu
.filter(menuItem => !menuItem.separator)
.map(menuItem => menuItem.can);
this.showMenu$ = combineLatest(nonSeparators).pipe(
map(cans => cans.some(can => can))
);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,13 +93,18 @@ export class EndpointCardComponent extends CardCell<EndpointModel> implements On
@Input('dataSource')
set dataSource(ds: BaseEndpointsDataSource) {
this.pDs = ds;

// Don't show card menu if the ds only provides a single endpoint type (for instance the cf endpoint page)
if (ds && !ds.dsEndpointType && !this.cardMenu) {
this.cardMenu = this.endpointListHelper.endpointActions().map(endpointAction => ({
label: endpointAction.label,
action: () => endpointAction.action(this.pRow),
can: endpointAction.createVisible(this.rowObs)
}));
this.cardMenu = this.endpointListHelper.endpointActions(true).map(endpointAction => {
const separator = endpointAction.label === '-';
return {
label: endpointAction.label,
action: () => endpointAction.action(this.pRow),
can: endpointAction.createVisible ? endpointAction.createVisible(this.rowObs) : null,
separator
};
});

// Add a copy address to clipboard
this.cardMenu.push(createMetaCardMenuItemSeparator());
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { ComponentFactoryResolver, ComponentRef, Injectable, ViewContainerRef } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
import { Store } from '@ngrx/store';
import { combineLatest, Observable } from 'rxjs';
import { combineLatest, Observable, of } from 'rxjs';
import { map, pairwise } from 'rxjs/operators';

import { RouterNav } from '../../../../../../../store/src/actions/router.actions';
Expand All @@ -19,6 +19,7 @@ import {
import { SnackBarService } from '../../../../services/snackbar.service';
import { ConfirmationDialogConfig } from '../../../confirmation-dialog.config';
import { ConfirmationDialogService } from '../../../confirmation-dialog.service';
import { createMetaCardMenuItemSeparator } from '../../list-cards/meta-card/meta-card-base/meta-card.component';
import { IListAction } from '../../list.component.types';
import { TableCellCustom } from '../../list.types';

Expand All @@ -37,6 +38,27 @@ function isEndpointListDetailsComponent(obj: any): EndpointListDetailsComponent
return obj ? obj.isEndpointListDetailsComponent ? obj as EndpointListDetailsComponent : null : null;
}

/**
* Combine the result of all createVisibles functions for the given actions
*/
function combineCreateVisibles(
customActions: IListAction<EndpointModel>[]
): (row$: Observable<EndpointModel>) => Observable<boolean> {
const createVisiblesFns = customActions
.map(action => action.createVisible)
.filter(createVisible => !!createVisible);
if (createVisiblesFns.length === 0) {
return () => of(false);
} else {
return (row$: Observable<EndpointModel>) => {
const createVisibles = createVisiblesFns.map(createVisible => createVisible(row$));
return combineLatest(createVisibles).pipe(
map(allRes => allRes.some(res => res))
);
};
}
}

@Injectable()
export class EndpointListHelper {
constructor(
Expand All @@ -48,7 +70,23 @@ export class EndpointListHelper {
private snackBarService: SnackBarService,
) { }

endpointActions(): IListAction<EndpointModel>[] {
endpointActions(includeSeparators = false): IListAction<EndpointModel>[] {
// Add any additional actions that are per endpoint type
const customActions = entityCatalog.getAllEndpointTypes()
.map(endpoint => endpoint.definition.endpointListActions)
.filter(endpointListActions => !!endpointListActions)
.map(endpointListActions => endpointListActions(this.store))
.reduce((res, actions) => res.concat(actions), []);

if (includeSeparators && customActions.length) {
// Only show the separator if we have custom actions to separate AND at least one is visible
const createVisibleFn = combineCreateVisibles(customActions);
customActions.splice(0, 0, {
...createMetaCardMenuItemSeparator(),
createVisible: createVisibleFn
});
}

return [
{
action: (item) => {
Expand Down Expand Up @@ -126,7 +164,8 @@ export class EndpointListHelper {
label: 'Edit endpoint',
description: 'Edit the endpoint',
createVisible: () => this.currentUserPermissionsService.can(StratosCurrentUserPermissions.ENDPOINT_REGISTER)
}
},
...customActions
];
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { Component, EventEmitter, Input, Output } from '@angular/core';

import { ITileConfig } from '../tile/tile-selector.types';


Expand All @@ -12,6 +13,9 @@ export class TileSelectorComponent {
public hiddenOptions: ITileConfig[] = [];
public showingMore = false;
@Input() set options(options: ITileConfig[]) {
if (!options) {
return;
}
const groupedOptions = options.reduce((grouped, option) => {
if (option.hidden) {
grouped.hidden.push(option);
Expand All @@ -20,9 +24,9 @@ export class TileSelectorComponent {
}
return grouped;
}, {
show: [],
hidden: []
});
show: [],
hidden: []
});
this.pOptions = groupedOptions.show;
this.hiddenOptions = groupedOptions.hidden;
}
Expand Down
3 changes: 3 additions & 0 deletions src/frontend/packages/core/xsrf.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ import { tap } from 'rxjs/operators';

const STRATOS_XSRF_HEADER_NAME = 'X-XSRF-Token';

/**
* `HttpXsrfTokenExtractor` which retrieves the token from a cookie.
*/
@Injectable()
export class HttpXsrfHeaderExtractor implements HttpXsrfTokenExtractor {

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -176,7 +176,7 @@ class EntityCatalog {
return Array.from(this.endpoints.values());
}

public getAllEndpointTypes(techPreviewEnabled = false) {
public getAllEndpointTypes(techPreviewEnabled = false): StratosCatalogEndpointEntity[] {
const baseEndpoints = Array.from(this.endpoints.values())
.filter(item => !item.definition.techPreview || item.definition.techPreview && techPreviewEnabled);
return baseEndpoints.reduce((allEndpoints, baseEndpoint) => {
Expand Down
Loading