diff --git a/README.md b/README.md index 6366b0dedd..5ca17aec73 100644 --- a/README.md +++ b/README.md @@ -42,6 +42,9 @@ $ docker run -p 4443:443 splatform/stratos-ui:latest You can access the UI on `https://localhost:4443` +## Troubleshooting +Please see our [Troubleshooting](docs/troubleshooting) page. + ## Project Planning We use [ZenHub](https://zenhub.com) for project planning. Feel free to head over to the [Boards](https://github.com/SUSE/stratos#boards) tab and have a look through our pipelines and milestones. Please note in order to view the Github ZenHub Boards tab you will need the [ZenHub diff --git a/deploy/cloud-foundry/README.md b/deploy/cloud-foundry/README.md index 0bd7c20a78..c4bdf1f0c2 100644 --- a/deploy/cloud-foundry/README.md +++ b/deploy/cloud-foundry/README.md @@ -2,7 +2,7 @@ ## Deployment Steps -The quickest way to install Stratos UI is to deploy it as a Cloud Foundry application. To do so, clone the `stratos` repository, cd into the newly cloned repository and push to Cloud Foundry. This can be done with: +The quickest way to install Stratos is to deploy it as a Cloud Foundry application. To do so, clone the `stratos` repository, cd into the newly cloned repository and push to Cloud Foundry. This can be done with: ``` git clone https://github.com/cloudfoundry-incubator/stratos @@ -63,11 +63,11 @@ cf logs console --recent | tee cfconsole.log ### Application Security Groups -If you have problems when deploying Stratos UI as a CLoud Foundry application, check that the Application Security Group you have will allow the Stratos UI to communicate with the Cloud Foundry API. +If you have problems when deploying Stratos UI as a Cloud Foundry application, check that the Application Security Group you have will allow Stratos to communicate with the Cloud Foundry API. For information on the default ASGs, see [here](https://docs.cloudfoundry.org/concepts/asg.html#default-asg). -To configure a new ASG for the organization and space that are using for the Stratos UI, first create a new ASG definition, for example: +To configure a new ASG for the organization and space that are using Stratos, first create a new ASG definition, for example: ``` [ @@ -102,7 +102,7 @@ cf bind-security-group NAME ORG SPACE ### Console fails to start -The Stratos UI Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the `cf_api` value inside the `VCAP_APPLICATION` environment variable. +The Stratos Console will automatically detect the API endpoint for your Cloud Foundry. To do so, it relies on the `cf_api` value inside the `VCAP_APPLICATION` environment variable. To check if the variable is present, use the CF CLI to list environment variables, and inspect the `VCAP_APPLICATION` variable under `System-Provided`. ``` diff --git a/docs/developers-guide.md b/docs/developers-guide.md index a61f883a5f..ae8abfa3a2 100644 --- a/docs/developers-guide.md +++ b/docs/developers-guide.md @@ -31,7 +31,7 @@ Configuration information can be found in two places * If the backend is deployed via the instructions above this will be the same address as the V1 console's frontend address. For instance `https://localhost` would translate to - ```const PROXY_CONFIG = { + ```const PROXY_CONFIG = { "/pp": { "target": { "host": "localhost", diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md new file mode 100644 index 0000000000..603c12a4e5 --- /dev/null +++ b/docs/troubleshooting.md @@ -0,0 +1,16 @@ +# Troubleshooting + +## Deploying as a Cloud Foundry Application +See the custom troubleshooting guide [here](../deploy/cloud-foundry/README#Troubleshooting). + +## Usernames appear as long random characters when connected to IBM Cloud + +### Problem +Connecting to an IBM Cloud with the address `https://api..bluemix.net` avoids a proxy, `https://mccp..bluemix.net`, +that IBM tools use to flesh out users with their username. This results in a missing `username` field, which we fill with the user's `guid` +instead. + +### Solution +Unregister the IBM Cloud endpoint that contains the address `https://api..bluemix.net` and register again with the address +`https://mccp..bluemix.net` + diff --git a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss index 7999adb3e7..3e0708c301 100644 --- a/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss +++ b/src/frontend/app/shared/components/list/list-table/table-row/table-row.component.scss @@ -2,6 +2,9 @@ &__blocked { .table-row { cursor: not-allowed; + mat-checkbox { + cursor: not-allowed; + } &__inner { * { opacity: .65; diff --git a/src/frontend/app/shared/components/list/list-types/cf-users/cf-user-data-source.service.ts b/src/frontend/app/shared/components/list/list-types/cf-users/cf-user-data-source.service.ts index 9de23b10d3..0c3d399ce2 100644 --- a/src/frontend/app/shared/components/list/list-types/cf-users/cf-user-data-source.service.ts +++ b/src/frontend/app/shared/components/list/list-types/cf-users/cf-user-data-source.service.ts @@ -1,53 +1,26 @@ import { Store } from '@ngrx/store'; -import { tap } from 'rxjs/operators'; import { getRowMetadata } from '../../../../../features/cloud-foundry/cf.helpers'; import { cfUserSchemaKey, entityFactory } from '../../../../../store/helpers/entity-factory'; import { PaginatedAction } from '../../../../../store/types/pagination.types'; -import { PaginationMonitor } from '../../../../monitors/pagination-monitor'; import { ListDataSource } from '../../data-sources-controllers/list-data-source'; -import { TableRowStateManager } from '../../list-table/table-row/table-row-state-manager'; import { ListConfig } from '../../list.component.types'; import { AppState } from './../../../../../store/app-state'; import { APIResource } from './../../../../../store/types/api.types'; import { CfUser } from './../../../../../store/types/user.types'; -function setupStateManager(paginationMonitor: PaginationMonitor>) { - const rowStateManager = new TableRowStateManager(); - const sub = paginationMonitor.currentPage$.pipe( - tap(users => { - users.forEach(user => { - rowStateManager.setRowState(user.metadata.guid, { - blocked: !user.entity.username - }); - }); - }) - ).subscribe(); - return { - sub, - rowStateManager - }; -} - export class CfUserDataSourceService extends ListDataSource> { constructor(store: Store, action: PaginatedAction, listConfigService: ListConfig>) { - const { paginationKey } = action; - const paginationMonitor = new PaginationMonitor>(store, paginationKey, entityFactory(cfUserSchemaKey)); - - const { sub, rowStateManager } = setupStateManager(paginationMonitor); - super({ store, action, schema: entityFactory(cfUserSchemaKey), getRowUniqueId: getRowMetadata, - paginationKey, + paginationKey: action.paginationKey, isLocal: true, transformEntities: [{ type: 'filter', field: 'entity.username' }], - listConfig: listConfigService, - rowsState: rowStateManager.observable, - destroy: () => sub.unsubscribe() + listConfig: listConfigService }); } diff --git a/src/frontend/app/store/helpers/entity-factory.ts b/src/frontend/app/store/helpers/entity-factory.ts index 066ddb9c42..aaf0cae4bf 100644 --- a/src/frontend/app/store/helpers/entity-factory.ts +++ b/src/frontend/app/store/helpers/entity-factory.ts @@ -1,6 +1,8 @@ import { Schema, schema } from 'normalizr'; import { getAPIResourceGuid } from '../selectors/api.selectors'; +import { APIResource } from '../types/api.types'; +import { CfUser } from '../types/user.types'; export const applicationSchemaKey = 'application'; export const stackSchemaKey = 'stack'; @@ -114,15 +116,15 @@ const DomainSchema = new EntitySchema(domainSchemaKey, {}, { // correct values - so remove them to avoid this processStrategy: (value) => { const newValue = { - entity: {...value.entity}, - metadata: {...value.metadata} + entity: { ...value.entity }, + metadata: { ...value.metadata } }; if (newValue.entity.router_group_type === null) { delete newValue.entity.router_group_type; } return newValue; } - }); +}); entityCache[domainSchemaKey] = DomainSchema; const ServiceSchema = new EntitySchema(serviceSchemaKey, { @@ -359,7 +361,22 @@ const CFUserSchema = new EntitySchema(cfUserSchemaKey, { managed_spaces: [SpaceManagedSchema], audited_spaces: [SpaceAuditedSchema], } -}, { idAttribute: getAPIResourceGuid }); +}, { + idAttribute: getAPIResourceGuid, + processStrategy: (user: APIResource) => { + if (user.entity.username) { + return user; + } + + return { + entity: { + ...user.entity, + username: user.metadata.guid + }, + metadata: { ...user.metadata } + }; + } + }); entityCache[cfUserSchemaKey] = CFUserSchema; export function entityFactory(key: string): EntitySchema {