integrate the CTL cluster components with the UI

This integrates the cluster functions:
Init
Move
Status, though status is in an error state in CTL

Move and init have been deprecated and the UI has been updated

Currently in need of a CTL bug fix for status:
https://github.com/airshipit/airshipctl/issues/370

Change-Id: I0a85c3fa4c223a7c03d76fc37918f97e0f87e891
This commit is contained in:
Schiefelbein, Andrew 2020-10-13 16:51:56 -05:00
parent fde880397c
commit 63653daf89
11 changed files with 143 additions and 39 deletions

View File

@ -0,0 +1,44 @@
/*
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
*/
table {
width: 100%;
}
.mat-form-field {
font-size: 14px;
width: 100%;
}
th.mat-sort-header-sorted {
color: black;
}
/* add border & center the table */
.clusterBorder {
border-spacing: 10px;
border:1px gray solid;
border-radius: 5px;
align-self: center;
width: 100%;
}
.container {
padding-left: 10px;
padding-right: 10px;
}
.example-spacer {
flex: 1 1 auto;
}

View File

@ -1 +1,52 @@
<h1>Cluster component</h1>
<h1>Airship Cluster Operations</h1>
<div class="container">
<h2>Cluster Init</h2>
<table class="clusterBorder">
<tbody>
<tr>
<td>
<b>Deprecated:</b>
</td>
<td>
<mat-icon color="primary" svgIcon="error_outline"></mat-icon>
</td>
<td>
Functionality has moved to phases
</td>
</tr>
</tbody>
</table>
<h2>Cluster Move</h2>
<table class="clusterBorder">
<tbody>
<tr>
<td>
<b>Deprecated:</b>
</td>
<td>
<mat-icon color="primary" svgIcon="error_outline"></mat-icon>
</td>
<td>
Functionality has moved to phases
</td>
</tr>
</tbody>
</table>
<h2>Cluster Status</h2>
<table class="clusterBorder">
<tbody>
<tr>
<td>
<button type="submit" id="statusButton" disabled>Status</button>
</td>
<td>
<mat-icon color="primary" svgIcon="error_outline"></mat-icon>
</td>
<td>
Status is not currently operable see: https://github.com/airshipit/airshipctl/issues/370
</td>
</tr>
</tbody>
</table>
</div>

View File

@ -15,6 +15,9 @@
import { async, ComponentFixture, TestBed } from '@angular/core/testing';
import { ClusterComponent } from './cluster.component';
import { ToastrModule } from 'ngx-toastr';
import { MatIconModule } from '@angular/material/icon';
import { HttpClientModule } from '@angular/common/http';
describe('ClusterComponent', () => {
let component: ClusterComponent;
@ -23,6 +26,8 @@ describe('ClusterComponent', () => {
beforeEach(async(() => {
TestBed.configureTestingModule({
imports: [
MatIconModule,
HttpClientModule,
ToastrModule.forRoot()
],
declarations: [

View File

@ -19,8 +19,9 @@ import { Log } from '../../../services/log/log.service';
import { LogMessage } from '../../../services/log/log-message';
@Component({
selector: 'app-bare-metal',
selector: 'app-cluster',
templateUrl: './cluster.component.html',
styleUrls: ['./cluster.component.css']
})
export class ClusterComponent implements WSReceiver {
@ -37,8 +38,11 @@ export class ClusterComponent implements WSReceiver {
if (message.hasOwnProperty('error')) {
this.websocketService.printIfToast(message);
} else {
// TODO (aschiefe): determine what should be notifications and what should be 86ed
Log.Debug(new LogMessage('Message received in cluster', this.className, message));
switch (message.subComponent) {
default:
Log.Error(new LogMessage('Cluster message sub component not handled', this.className, message));
break;
}
}
}
}

View File

@ -14,13 +14,16 @@
import { NgModule } from '@angular/core';
import { ClusterComponent } from './cluster.component';
import { ToastrModule } from 'ngx-toastr';
import { MatIconModule } from '@angular/material/icon';
@NgModule({
imports: [
MatIconModule,
ToastrModule.forRoot()
],
declarations: [
ClusterComponent
],
providers: []
]
})
export class ClusterModule { }

View File

@ -17,6 +17,7 @@ import { RouterModule } from '@angular/router';
import { CtlComponent } from './ctl.component';
import { DocumentModule } from './document/document.module';
import { BaremetalModule } from './baremetal/baremetal.module';
import { ClusterModule } from './cluster/cluster.module';
import { CtlRoutingModule } from './ctl-routing.module';
import { PhaseModule } from './phase/phase.module';
import { SecretModule } from './secret/secret.module';
@ -24,7 +25,7 @@ import { SecretModule } from './secret/secret.module';
@NgModule({
imports: [
CtlRoutingModule,
ClusterModule,
RouterModule,
DocumentModule,
BaremetalModule,

View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" height="24" viewBox="0 0 24 24" width="24"><path d="M0 0h24v24H0V0z" fill="none"/><path d="M11 15h2v2h-2zm0-8h2v6h-2zm.99-5C6.47 2 2 6.48 2 12s4.47 10 9.99 10C17.52 22 22 17.52 22 12S17.52 2 11.99 2zM12 20c-4.42 0-8-3.58-8-8s3.58-8 8-8 8 3.58 8 8-3.58 8-8 8z"/></svg>

After

Width:  |  Height:  |  Size: 307 B

View File

@ -22,6 +22,7 @@ export enum Icons {
launch = 'launch',
text_snippet = 'text_snippet',
error = 'error',
error_outline = 'error_outline',
open_in_new = 'open_in_new',
filter = 'filter',
security = 'security',

View File

@ -19,6 +19,7 @@ import (
"opendev.org/airship/airshipctl/pkg/log"
"opendev.org/airship/airshipui/pkg/configs"
uiLog "opendev.org/airship/airshipui/pkg/log"
"opendev.org/airship/airshipui/pkg/statistics"
"opendev.org/airship/airshipui/pkg/webservice"
)
@ -123,3 +124,15 @@ func (cw *LogInterceptor) Write(data []byte) (n int, err error) {
return len(data), nil
}
// errorHelper formats & sends errors for the ctl components
func errorHelper(err error, transaction *statistics.Transaction, response configs.WsMessage) {
uiLog.Error(err)
e := err.Error()
response.Error = &e
transaction.Complete(false)
err = webservice.WebSocketSend(response)
if err != nil {
uiLog.Error(err)
}
}

View File

@ -40,7 +40,7 @@ type phaseInfo struct {
ClusterName string `json:"clusterName,omitempty"`
}
type defaultData struct {
type baremetalData struct {
Nodes []nodeInfo `json:"nodes,omitempty"`
Phases []phaseInfo `json:"phases,omitempty"`
}
@ -66,7 +66,7 @@ func HandleBaremetalRequest(user *string, request configs.WsMessage) configs.WsM
switch subComponent {
case configs.GetDefaults:
response.Data, err = getDefaults(request)
response.Data, err = getBaremetalDefaults(request)
case configs.EjectMedia:
err = doAction(user, request)
case configs.PowerOff:
@ -93,7 +93,7 @@ func HandleBaremetalRequest(user *string, request configs.WsMessage) configs.WsM
return response
}
func getDefaults(request configs.WsMessage) (defaultData, error) {
func getBaremetalDefaults(request configs.WsMessage) (baremetalData, error) {
nodeInfo, err := getNodeInfo(request)
phaseInfo, err2 := getPhaseInfo()
@ -103,7 +103,7 @@ func getDefaults(request configs.WsMessage) (defaultData, error) {
err = err2
}
return defaultData{
return baremetalData{
Nodes: nodeInfo,
Phases: phaseInfo,
}, err
@ -189,7 +189,7 @@ func actionHelper(user *string, target string, phase string, request configs.WsM
response := configs.WsMessage{
Type: configs.CTL,
Component: configs.Baremetal,
SubComponent: configs.EjectMedia,
SubComponent: request.SubComponent,
SessionID: request.SessionID,
ActionType: request.ActionType,
Target: &target,
@ -200,14 +200,7 @@ func actionHelper(user *string, target string, phase string, request configs.WsM
client, err := NewClient(AirshipConfigPath, KubeConfigPath, response)
if err != nil {
log.Error(err)
e := err.Error()
response.Error = &e
transaction.Complete(false)
err = webservice.WebSocketSend(response)
if err != nil {
log.Error(err)
}
errorHelper(err, transaction, response)
return
}
@ -219,14 +212,7 @@ func actionHelper(user *string, target string, phase string, request configs.WsM
}
m, err := remote.NewManager(client.Config, phase, selectors...)
if err != nil {
log.Error(err)
e := err.Error()
response.Error = &e
transaction.Complete(false)
err = webservice.WebSocketSend(response)
if err != nil {
log.Error(err)
}
errorHelper(err, transaction, response)
return
}
@ -256,14 +242,7 @@ func actionHelper(user *string, target string, phase string, request configs.WsM
}
if err != nil {
log.Error(err)
e := err.Error()
response.Error = &e
transaction.Complete(false)
err = webservice.WebSocketSend(response)
if err != nil {
log.Error(err)
}
errorHelper(err, transaction, response)
return
}

View File

@ -25,7 +25,7 @@ import (
func HandleClusterRequest(user *string, request configs.WsMessage) configs.WsMessage {
response := configs.WsMessage{
Type: configs.CTL,
Component: configs.Baremetal,
Component: configs.Cluster,
SubComponent: request.SubComponent,
}
@ -34,10 +34,12 @@ func HandleClusterRequest(user *string, request configs.WsMessage) configs.WsMes
subComponent := request.SubComponent
switch subComponent {
case configs.GetDefaults:
err = fmt.Errorf("Subcomponent %s deprecated", request.SubComponent)
case configs.Init:
err = fmt.Errorf("Subcomponent %s not implemented", request.SubComponent)
err = fmt.Errorf("Subcomponent %s deprecated", request.SubComponent)
case configs.Move:
err = fmt.Errorf("Subcomponent %s not implemented", request.SubComponent)
err = fmt.Errorf("Subcomponent %s deprecated", request.SubComponent)
case configs.Status:
err = fmt.Errorf("Subcomponent %s not implemented", request.SubComponent)
default: