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

refactor(kubernetes): convert scale manifest stage to react #10151

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
2 changes: 0 additions & 2 deletions packages/kubernetes/src/kubernetes.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ import { KUBERNETES_MANIFEST_STATUS } from './manifest/status/status.component';
import { ManifestWizard } from './manifest/wizard/ManifestWizard';
import './pipelines/stages';
import { KUBERNETES_FIND_ARTIFACTS_FROM_RESOURCE_STAGE } from './pipelines/stages/findArtifactsFromResource/findArtifactsFromResourceStage';
import { KUBERNETES_SCALE_MANIFEST_STAGE } from './pipelines/stages/scaleManifest/scaleManifestStage';
import { KUBERNETES_DISABLE_MANIFEST_STAGE } from './pipelines/stages/traffic/disableManifest.stage';
import { KUBERNETES_ENABLE_MANIFEST_STAGE } from './pipelines/stages/traffic/enableManifest.stage';
import { KUBERNETES_UNDO_ROLLOUT_MANIFEST_STAGE } from './pipelines/stages/undoRolloutManifest/undoRolloutManifestStage';
Expand Down Expand Up @@ -73,7 +72,6 @@ const requires = [
KUBERNETES_MANIFEST_ARTIFACT,
KUBERNETES_LOAD_BALANCER_TRANSFORMER,
KUBERNETES_SECURITY_GROUP_TRANSFORMER,
KUBERNETES_SCALE_MANIFEST_STAGE,
KUBERNETES_UNDO_ROLLOUT_MANIFEST_STAGE,
KUBERNETES_FIND_ARTIFACTS_FROM_RESOURCE_STAGE,
KUBERNETES_MANIFEST_SELECTOR,
Expand Down
43 changes: 43 additions & 0 deletions packages/kubernetes/src/manifest/scale/ScaleSettingsForm.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
import React, { useState } from 'react';
import { NumberInput, StageConfigField } from '@spinnaker/core';
import type { IScaleCommand } from './scale.controller';

export interface IScaleSettingsFormProps {
options: IScaleCommand;
onChange(options: IScaleCommand): void;
}

export interface IScaleSettingsFormState {
options: IScaleCommand;
}

export function ScaleSettingsForm({ options, onChange }: IScaleSettingsFormProps) {
const [state, setState] = useState<IScaleSettingsFormState>({
options: options,
});

const updateReplicas = (newReplicas: number) => {
state.options.replicas = newReplicas;
if (onChange) {
onChange(state.options);
}
setState({ options: state.options });
};

return (
<div className="form-horizontal">
<StageConfigField label="Replicas" fieldColumns={4} groupClassName="form-group form-inline">
<div className="input-group">
<NumberInput
inputClassName="input-sm highlight-pristine"
onChange={(e: React.ChangeEvent<HTMLInputElement>) => {
updateReplicas(e.target.valueAsNumber);
}}
value={options.replicas}
min={0}
/>
</div>
</StageConfigField>
</div>
);
}
17 changes: 11 additions & 6 deletions packages/kubernetes/src/manifest/scale/scale.controller.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import type { IController } from 'angular';
import type { IController, IScope } from 'angular';
import { copy, module } from 'angular';
import type { IModalServiceInstance } from 'angular-ui-bootstrap';

Expand All @@ -7,7 +7,7 @@ import { ManifestWriter, TaskMonitor } from '@spinnaker/core';
import type { IManifestCoordinates } from '../IManifestCoordinates';
import { KUBERNETES_SCALE_MANIFEST_SETTINGS_FORM } from './scaleSettingsForm.component';

interface IScaleCommand {
export interface IScaleCommand {
manifestName: string;
location: string;
account: string;
Expand All @@ -17,13 +17,13 @@ interface IScaleCommand {

class KubernetesManifestScaleController implements IController {
public taskMonitor: TaskMonitor;
public command: IScaleCommand;
public verification = {
verified: false,
};

public static $inject = ['coordinates', 'currentReplicas', '$uibModalInstance', 'application'];
public static $inject = ['$scope', 'coordinates', 'currentReplicas', '$uibModalInstance', 'application'];
constructor(
private $scope: IScope,
coordinates: IManifestCoordinates,
currentReplicas: number,
private $uibModalInstance: IModalServiceInstance,
Expand All @@ -35,13 +35,18 @@ class KubernetesManifestScaleController implements IController {
modalInstance: $uibModalInstance,
});

this.command = {
this.$scope.command = {
manifestName: coordinates.name,
location: coordinates.namespace,
account: coordinates.account,
reason: null,
replicas: currentReplicas,
};

// used by react components to update command fields in parent (angular) scope
this.$scope.onChange = () => {
this.$scope.$applyAsync();
};
}

public isValid(): boolean {
Expand All @@ -54,7 +59,7 @@ class KubernetesManifestScaleController implements IController {

public scale(): void {
this.taskMonitor.submit(() => {
const payload = copy(this.command) as any;
const payload = copy(this.$scope.command) as any;
payload.cloudProvider = 'kubernetes';

return ManifestWriter.scaleManifest(payload, this.application);
Expand Down
13 changes: 9 additions & 4 deletions packages/kubernetes/src/manifest/scale/scale.html
mattgogerly marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@
<form role="form" name="scaleForm">
<modal-close dismiss="$dismiss()"></modal-close>
<div class="modal-header">
<h4 class="modal-title">Scale {{ctrl.command.manifestName | robotToHuman}} in {{ctrl.command.location}}</h4>
<h4 class="modal-title">
Scale {{ctrl.$scope.command.manifestName | robotToHuman}} in {{ctrl.$scope.command.location}}
</h4>
</div>
<div class="modal-body confirmation-modal">
<kubernetes-scale-manifest-settings-form settings="ctrl.command"></kubernetes-scale-manifest-settings-form>
<task-reason command="ctrl.command"></task-reason>
<kubernetes-scale-manifest-settings-form
options="ctrl.$scope.command"
on-change="ctrl.$scope.onChange"
></kubernetes-scale-manifest-settings-form>
<task-reason command="ctrl.$scope.command"></task-reason>
</div>
<div class="modal-footer">
<user-verification account="ctrl.command.account" verification="ctrl.verification"></user-verification>
<user-verification account="ctrl.$scope.command.account" verification="ctrl.verification"></user-verification>
<button type="submit" ng-click="ctrl.scale()" style="display: none"></button>
<!-- Allows form submission via enter keypress-->
<button class="btn btn-default" ng-click="ctrl.cancel()">Cancel</button>
Expand Down
Original file line number Diff line number Diff line change
@@ -1,29 +1,11 @@
import type { IComponentOptions } from 'angular';
import { module } from 'angular';

const kubernetesScaleManifestSettingsFormComponent: IComponentOptions = {
bindings: { settings: '=' },
controllerAs: 'ctrl',
template: `
<div class="form-horizontal">
<div class="form-group form-inline">
<div class="col-md-3 sm-label-right">
Replicas
</div>
<div class="col-md-4">
<input type="text"
class="form-control input-sm highlight-pristine"
ng-model="ctrl.settings.replicas"
min="0"/>
</div>
</div>
</div>
`,
};
import { react2angular } from 'react2angular';
import { withErrorBoundary } from '@spinnaker/core';
import { ScaleSettingsForm } from './ScaleSettingsForm';

export const KUBERNETES_SCALE_MANIFEST_SETTINGS_FORM =
'spinnaker.kubernetes.v2.kubernetes.manifest.scale.settingsForm.component';
module(KUBERNETES_SCALE_MANIFEST_SETTINGS_FORM, []).component(
'kubernetesScaleManifestSettingsForm',
kubernetesScaleManifestSettingsFormComponent,
react2angular(withErrorBoundary(ScaleSettingsForm, 'kubernetesScaleManifestSettingsForm'), ['options', 'onChange']),
);
1 change: 1 addition & 0 deletions packages/kubernetes/src/pipelines/stages/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,4 @@ export * from './deployManifest/deployManifestStage';
export * from './patchManifest/patchManifestStage';
export * from './rolloutRestartManifest/rolloutRestartManifestStage';
export * from './runJob/runJobStage';
export * from './scaleManifest/scaleManifestStage';
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
import { defaults } from 'lodash';
import React, { useEffect } from 'react';

import type { IFormikStageConfigInjectedProps, IStageConfigProps } from '@spinnaker/core';
import { FormikStageConfig } from '@spinnaker/core';

import { ScaleManifestStageForm } from './ScaleManifestStageForm';

export function ScaleManifestStageConfig({
application,
pipeline,
stage,
updateStage,
stageFieldUpdated,
}: IStageConfigProps) {
useEffect(() => {
defaults(stage, {
app: application.name,
cloudProvider: 'kubernetes',
});

if (stage.isNew) {
stage.replicas = 0;
}
}, []);

return (
<FormikStageConfig
application={application}
pipeline={pipeline}
stage={stage}
onChange={updateStage}
render={(props: IFormikStageConfigInjectedProps) => (
<ScaleManifestStageForm {...props} stageFieldUpdated={stageFieldUpdated} />
)}
/>
);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
import React from 'react';

import type { IFormikStageConfigInjectedProps } from '@spinnaker/core';

import type { IScaleCommand } from '../../../manifest';
import { ScaleSettingsForm } from '../../../manifest/scale/ScaleSettingsForm';
import type { IManifestSelector } from '../../../manifest/selector/IManifestSelector';
import { SelectorMode } from '../../../manifest/selector/IManifestSelector';
import { ManifestSelector } from '../../../manifest/selector/ManifestSelector';

interface IScaleManifestStageConfigFormProps {
stageFieldUpdated: () => void;
}

export function ScaleManifestStageForm({
application,
formik,
stageFieldUpdated,
}: IScaleManifestStageConfigFormProps & IFormikStageConfigInjectedProps) {
const stage = formik.values;

const onManifestSelectorChange = () => {
stageFieldUpdated();
};

const onScaleSettingsFormChange = () => {
stageFieldUpdated();
};

return (
<div className="form-horizontal">
<h4>Manifest</h4>
<div className="horizontal-rule" />
<ManifestSelector
application={application}
selector={(stage as unknown) as IManifestSelector}
modes={[SelectorMode.Static, SelectorMode.Dynamic]}
onChange={onManifestSelectorChange}
includeSpinnakerKinds={null}
/>
<h4>Settings</h4>
<div className="horizontal-rule" />
<ScaleSettingsForm options={(stage as unknown) as IScaleCommand} onChange={onScaleSettingsFormChange} />
</div>
);
}

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,33 +1,21 @@
import { module } from 'angular';

import type { IStage } from '@spinnaker/core';
import { ExecutionDetailsTasks, Registry } from '@spinnaker/core';

import { manifestExecutionDetails } from '../ManifestExecutionDetails';
import { KUBERNETES_SCALE_MANIFEST_SETTINGS_FORM } from '../../../manifest/scale/scaleSettingsForm.component';
import { KubernetesV2ScaleManifestConfigCtrl } from './scaleManifestConfig.controller';
import { ScaleManifestStageConfig } from './ScaleManifestConfig';
import { manifestSelectorValidators } from '../validators/manifestSelectorValidators';

export const KUBERNETES_SCALE_MANIFEST_STAGE = 'spinnaker.kubernetes.v2.pipeline.stage.scaleManifestStage';
const STAGE_NAME = 'Scale (Manifest)';
const STAGE_KEY = 'scaleManifest';

module(KUBERNETES_SCALE_MANIFEST_STAGE, [KUBERNETES_SCALE_MANIFEST_SETTINGS_FORM])
.config(() => {
Registry.pipeline.registerStage({
label: 'Scale (Manifest)',
description: 'Scale a Kubernetes object created from a manifest.',
key: STAGE_KEY,
cloudProvider: 'kubernetes',
templateUrl: require('./scaleManifestConfig.html'),
controller: 'KubernetesV2ScaleManifestConfigCtrl',
controllerAs: 'ctrl',
executionDetailsSections: [manifestExecutionDetails(STAGE_KEY), ExecutionDetailsTasks],
accountExtractor: (stage: IStage): string[] => (stage.account ? [stage.account] : []),
configAccountExtractor: (stage: any): string[] => (stage.account ? [stage.account] : []),
validators: [
{ type: 'requiredField', fieldName: 'location', fieldLabel: 'Namespace' },
{ type: 'requiredField', fieldName: 'account', fieldLabel: 'Account' },
{ type: 'requiredField', fieldName: 'replicas', fieldLabel: 'Replicas' },
],
});
})
.controller('KubernetesV2ScaleManifestConfigCtrl', KubernetesV2ScaleManifestConfigCtrl);
Registry.pipeline.registerStage({
label: STAGE_NAME,
description: 'Scale a Kubernetes object created from a manifest.',
key: STAGE_KEY,
cloudProvider: 'kubernetes',
component: ScaleManifestStageConfig,
executionDetailsSections: [manifestExecutionDetails(STAGE_KEY), ExecutionDetailsTasks],
validators: [
...manifestSelectorValidators(STAGE_NAME),
{ type: 'requiredField', fieldName: 'replicas', fieldLabel: 'Replicas' },
],
});
Loading