Skip to content

Commit

Permalink
Add pipeline credential management section to start pipeline modal
Browse files Browse the repository at this point in the history
  • Loading branch information
karthik committed Apr 7, 2020
1 parent beb4b53 commit 87bf035
Show file tree
Hide file tree
Showing 10 changed files with 131 additions and 11 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,12 @@ export enum PipelineResourceType {
storage = 'Storage',
}

export enum SecretAnnotationId {
Git = 'git',
Image = 'docker',
}
export const SecretAnnotationType = {
[SecretAnnotationId.Git]: 'Git',
[SecretAnnotationId.Image]: 'Image',
};
export const PIPELINE_SERVICE_ACCOUNT = 'pipeline';
Original file line number Diff line number Diff line change
@@ -1,10 +1,15 @@
.odc-pipeline-secret-section {
margin-top: calc(-1 * var(--pf-global--spacer--sm));
padding-left: var(--pf-global--spacer--lg);
&__secrets {
padding-left: var(--pf-global--spacer--lg);
}
&__secret-form {
border: 1px dashed var(--pf-global--BorderColor--100);
padding: var(--pf-global--spacer--md);
}
&__secret-action {
margin-top: calc(-1 * var(--pf-global--spacer--sm));
padding-left: 0;
}
}
.odc-pipeline-expandable-content {
margin-top: var(--pf-global--spacer--sm);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,19 @@ import { SecretType } from '@console/internal/components/secrets/create-secret';
import { SecretModel } from '@console/internal/models';
import { k8sCreate } from '@console/internal/module/k8s';
import SecretForm from './SecretForm';
import { associateServiceAccountToSecret } from '../../../utils/pipeline-utils';
import {
associateServiceAccountToSecret,
getTektonSecretAnnotations,
} from '../../../utils/pipeline-utils';
import SecretsList from './SecretsList';
import { advancedSectionValidationSchema } from './pipelineForm-validation-utils';
import { SecretAnnotationId } from '../const';

import './PipelineSecretSection.scss';

const initialValues = {
secretName: '',
annotations: { key: SecretAnnotationId.Image, value: '' },
type: SecretType.dockerconfigjson,
formData: {},
};
Expand All @@ -32,11 +39,11 @@ const PipelineSecretSection: React.FC<PipelineSecretSectionProps> = ({ namespace
metadata: {
name: values.secretName,
namespace,
annotations: getTektonSecretAnnotations(values.annotations),
},
type: values.type,
stringData: values.formData,
};

k8sCreate(SecretModel, newSecret)
.then((resp) => {
actions.setSubmitting(false);
Expand Down Expand Up @@ -65,12 +72,22 @@ const PipelineSecretSection: React.FC<PipelineSecretSectionProps> = ({ namespace
<SecretsList namespace={namespace} />
{addSecret ? (
<div className="odc-pipeline-secret-section__secret-form">
<Formik initialValues={initialValues} onSubmit={handleSubmit} onReset={handleReset}>
<Formik
initialValues={initialValues}
validationSchema={advancedSectionValidationSchema}
onSubmit={handleSubmit}
onReset={handleReset}
>
{(props) => <SecretForm {...props} />}
</Formik>
</div>
) : (
<Button variant="link" onClick={handleAddSecret} icon={<PlusCircleIcon />}>
<Button
variant="link"
onClick={handleAddSecret}
className="odc-pipeline-secret-section__secret-action"
icon={<PlusCircleIcon />}
>
Add Secret
</Button>
)}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import * as React from 'react';
import { TextInputTypes } from '@patternfly/react-core';
import { InputField, DropdownField } from '@console/shared';
import { SecretAnnotationType } from '../const';

type SecretAnnotationParam = {
addLabel?: string;
fieldName: string;
isReadOnly?: boolean;
};

const SecretAnnotation: React.FC<SecretAnnotationParam> = (props) => {
const { fieldName, isReadOnly = false } = props;
return (
<div className="row">
<div className="col-lg-6">
<DropdownField
name={`${fieldName}.key`}
items={SecretAnnotationType}
label="Access to"
disabled={isReadOnly}
fullWidth
required
/>
</div>
<div className="col-lg-6">
<InputField
name={`${fieldName}.value`}
type={TextInputTypes.text}
isReadOnly={isReadOnly}
label="Server URL"
required
/>
</div>
</div>
);
};

export default SecretAnnotation;
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import {
CreateConfigSubform,
} from '@console/internal/components/secrets/create-secret';
import { DropdownField, InputField } from '@console/shared';
import SecretAnnotation from './SecretAnnotation';
import './SecretForm.scss';

const authTypes = {
Expand Down Expand Up @@ -70,7 +71,7 @@ const SecretForm: React.FC<FormikValues> = ({
};

const onDataChanged = (event) => {
setStringData((prevState) => ({ ...prevState, [values.type]: event }));
setStringData((prevState) => _.merge({}, prevState, { [values.type]: event }));
setValues(values.type);
};

Expand All @@ -93,6 +94,9 @@ const SecretForm: React.FC<FormikValues> = ({
helpText="Unique name of the new secret."
/>
</div>
<div className="form-group">
<SecretAnnotation fieldName="annotations" />
</div>
<div className="form-group">
<DropdownField
name="type"
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
.odc-secrets-list {
&__secrets {
padding-left: var(--pf-global--spacer--lg);
padding-bottom: var(--pf-global--spacer--lg);
&--item {
margin-top: var(--pf-global--spacer--sm);
}
padding-bottom: var(--pf-global--spacer--md);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ const Secrets: React.FC<SecretsProps> = ({ secrets, serviceaccounts }) => {
{sortedFilterData.map((secret) => {
return (
<ResourceLink
className="odc-secrets-list__secrets--item"
key={secret.metadata.uid}
kind={SecretModel.kind}
name={secret.metadata.name}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,3 +37,12 @@ export const startPipelineSchema = yup.object().shape({
}),
),
});

export const advancedSectionValidationSchema = yup.object().shape({
secretName: yup.string().required('Required'),
type: yup.string().required('Required'),
annotations: yup.object().shape({
key: yup.string().required('Required'),
value: yup.string().required('Required'),
}),
});
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,14 @@ import {
constructCurrentPipeline,
getPipelineRunParams,
pipelineRunDuration,
getTektonSecretAnnotations
} from '../pipeline-utils';
import {
constructPipelineData,
mockPipelinesJSON,
mockRunDurationTest,
} from './pipeline-test-data';
import { SecretAnnotationId } from '../../components/pipelines/const';

describe('pipeline-utils ', () => {
it('For first pipeline there should be 1 stages of length 2', () => {
Expand Down Expand Up @@ -93,4 +95,22 @@ describe('pipeline-utils ', () => {
expect(duration).not.toBeNull();
expect(duration).toBe('1m 13s');
});
it('expect annotation to return an empty object if keyValue pair is not passed', () => {
const annotation = getTektonSecretAnnotations(null);
expect(annotation).toEqual({});
});

it('expect annotation to have a valid git annotation key and value', () => {
const annotation = getTektonSecretAnnotations({ key: SecretAnnotationId.Git, value: 'github.com' });
expect(annotation).toEqual({
'tekton.dev/git-0': 'github.com'
});
});

it('expect annotation to have a valid image annotation key and value', () => {
const annotation = getTektonSecretAnnotations({ key: SecretAnnotationId.Image, value: 'docker.io' });
expect(annotation).toEqual({
'tekton.dev/docker-0': 'docker.io'
});
});
});
17 changes: 16 additions & 1 deletion frontend/packages/dev-console/src/utils/pipeline-utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ import {
PipelineTaskRef,
} from './pipeline-augment';
import { pipelineFilterReducer, pipelineRunStatus } from './pipeline-filter-reducer';
import { PIPELINE_SERVICE_ACCOUNT } from '../components/pipelines/const';
import { PIPELINE_SERVICE_ACCOUNT, SecretAnnotationId } from '../components/pipelines/const';

interface Resources {
inputs?: Resource[];
Expand Down Expand Up @@ -345,3 +345,18 @@ export const associateServiceAccountToSecret = (secret: SecretKind, namespace: s
errorModal({ error: err.message });
});
};

type keyValuePair = {
key: string;
value: string;
};
export const getTektonSecretAnnotations = (annotation: keyValuePair) => {
const annotations = {};
const annotationPrefix = 'tekton.dev';
if (annotation?.key === SecretAnnotationId.Git) {
annotations[`${annotationPrefix}/${SecretAnnotationId.Git}-0`] = annotation?.value;
} else if (annotation?.key === SecretAnnotationId.Image) {
annotations[`${annotationPrefix}/${SecretAnnotationId.Image}-0`] = annotation?.value;
}
return annotations;
};

0 comments on commit 87bf035

Please sign in to comment.