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

Bug 1807868: fixes issue with knative service in edit flow #4528

Merged
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
Expand Up @@ -9,6 +9,7 @@ import NamespacedPage, { NamespacedPageVariants } from '../NamespacedPage';
import EditApplication from './EditApplication';
import { EditApplicationProps } from './edit-application-types';

const INSTANCE_LABEL = 'app.kubernetes.io/instance';
const EditApplicationComponentLoader: React.FunctionComponent<EditApplicationProps> = (
props: EditApplicationProps,
) => {
Expand Down Expand Up @@ -48,8 +49,11 @@ const EditApplicationPage: React.FunctionComponent<ImportPageProps> = ({ match,
{
kind: 'ImageStream',
prop: 'imageStream',
name: appName,
isList: true,
namespace,
selector: {
matchLabels: { [INSTANCE_LABEL]: appName },
},
optional: true,
},
{
Expand Down
Expand Up @@ -319,41 +319,43 @@ export const appResources: AppResources = {
imageStream: {
loaded: true,
loadError: '',
data: {
kind: 'ImageStream',
apiVersion: 'image.openshift.io/v1',
metadata: {
annotations: {
'app.openshift.io/vcs-ref': 'master',
'app.openshift.io/vcs-uri': 'https://github.com/divyanshiGupta/nationalparks-py',
data: [
{
kind: 'ImageStream',
apiVersion: 'image.openshift.io/v1',
metadata: {
annotations: {
'app.openshift.io/vcs-ref': 'master',
'app.openshift.io/vcs-uri': 'https://github.com/divyanshiGupta/nationalparks-py',
},
selfLink: '/apis/image.openshift.io/v1/namespaces/div/imagestreams/nationalparks-py',
resourceVersion: '676247',
name: 'nationalparks-py',
uid: '2bc985ac-f834-45e5-9a86-830edb6bc8bd',
creationTimestamp: '2020-01-15T15:51:47Z',
generation: 1,
namespace: 'div',
labels: {
app: 'nationalparks-py',
'app.kubernetes.io/component': 'nationalparks-py',
'app.kubernetes.io/instance': 'nationalparks-py',
'app.kubernetes.io/name': 'python',
'app.kubernetes.io/part-of': 'nodejs-rest-http-app',
'app.openshift.io/runtime': 'python',
'app.openshift.io/runtime-version': '3.6',
},
},
selfLink: '/apis/image.openshift.io/v1/namespaces/div/imagestreams/nationalparks-py',
resourceVersion: '676247',
name: 'nationalparks-py',
uid: '2bc985ac-f834-45e5-9a86-830edb6bc8bd',
creationTimestamp: '2020-01-15T15:51:47Z',
generation: 1,
namespace: 'div',
labels: {
app: 'nationalparks-py',
'app.kubernetes.io/component': 'nationalparks-py',
'app.kubernetes.io/instance': 'nationalparks-py',
'app.kubernetes.io/name': 'python',
'app.kubernetes.io/part-of': 'nodejs-rest-http-app',
'app.openshift.io/runtime': 'python',
'app.openshift.io/runtime-version': '3.6',
spec: {
lookupPolicy: {
local: false,
},
},
},
spec: {
lookupPolicy: {
local: false,
status: {
dockerImageRepository:
'image-registry.openshift-image-registry.svc:5000/div/nationalparks-py',
},
},
status: {
dockerImageRepository:
'image-registry.openshift-image-registry.svc:5000/div/nationalparks-py',
},
},
],
},
};

Expand Down
Expand Up @@ -5,7 +5,7 @@ export interface AppResources {
service?: FirehoseResult<K8sResourceKind>;
route?: FirehoseResult<K8sResourceKind>;
buildConfig?: FirehoseResult<K8sResourceKind>;
imageStream?: FirehoseResult<K8sResourceKind>;
imageStream?: FirehoseResult<K8sResourceKind[]>;
editAppResource?: FirehoseResult<K8sResourceKind>;
imageStreams?: FirehoseResult;
}
Expand Down
Expand Up @@ -266,11 +266,13 @@ export const getGitAndDockerfileInitialValues = (
return initialValues;
};

export const getExternalImageInitialValues = (imageStream: K8sResourceKind) => {
if (_.isEmpty(imageStream)) {
export const getExternalImageInitialValues = (appResources: AppResources) => {
const imageStreamList = appResources?.imageStream?.data;
if (_.isEmpty(imageStreamList)) {
return {};
}
const name = _.get(imageStream, 'spec.tags[0].from.name');
const imageStream = _.orderBy(imageStreamList, ['metadata.resourceVersion'], ['desc']);
const name = imageStream.length && imageStream[0]?.spec?.tags?.[0]?.from?.name;
const deployImageInitialValues = {
searchTerm: name,
registry: 'external',
Expand Down Expand Up @@ -367,7 +369,7 @@ export const getInitialValues = (
let internalImageValues = {};

if (_.isEmpty(gitDockerValues)) {
externalImageValues = getExternalImageInitialValues(_.get(appResources, 'imageStream.data'));
externalImageValues = getExternalImageInitialValues(appResources);
internalImageValues = _.isEmpty(externalImageValues)
? getInternalImageInitialValues(_.get(appResources, 'editAppResource.data'))
: {};
Expand Down
Expand Up @@ -18,6 +18,7 @@ import {
createService,
annotations,
dryRunOpt,
getRandomChars,
} from '../../utils/shared-submit-utils';
import { RegistryType } from '../../utils/imagestream-utils';
import { AppResources } from '../edit-application/edit-application-types';
Expand Down Expand Up @@ -56,6 +57,7 @@ export const createOrUpdateImageStream = (
dryRun: boolean,
originalImageStream?: K8sResourceKind,
verb: K8sVerb = 'create',
generatedImageStreamName: string = '',
): Promise<K8sResourceKind> => {
const {
project: { name: namespace },
Expand All @@ -69,7 +71,7 @@ export const createOrUpdateImageStream = (
apiVersion: 'image.openshift.io/v1',
kind: 'ImageStream',
metadata: {
name,
name: `${generatedImageStreamName || name}`,
namespace,
labels: { ...defaultLabels, ...userLabels },
},
Expand All @@ -90,12 +92,11 @@ export const createOrUpdateImageStream = (
],
},
};

const imageStream = mergeData(originalImageStream, newImageStream);

return verb === 'update'
? k8sUpdate(ImageStreamModel, imageStream)
: k8sCreate(ImageStreamModel, imageStream, dryRun ? dryRunOpt : {});
: k8sCreate(ImageStreamModel, newImageStream, dryRun ? dryRunOpt : {});
};

const getMetadata = (formData: DeployImageFormData) => {
Expand Down Expand Up @@ -357,14 +358,12 @@ export const createOrUpdateDeployImageResources = async (
formData.imageStream.grantAccess &&
requests.push(createSystemImagePullerRoleBinding(formData, dryRun));
}
const imageStreamList = appResources?.imageStream?.data;
const imageStreamData = _.orderBy(imageStreamList, ['metadata.resourceVersion'], ['desc']);
const originalImageStream = (imageStreamData.length && imageStreamData[0]) || {};
if (formData.resources !== Resources.KnativeService) {
registry === RegistryType.External &&
(await createOrUpdateImageStream(
formData,
dryRun,
_.get(appResources, 'imageStream.data'),
verb,
));
(await createOrUpdateImageStream(formData, dryRun, originalImageStream, verb));
if (formData.resources === Resources.Kubernetes) {
requests.push(
createOrUpdateDeployment(
Expand Down Expand Up @@ -402,11 +401,22 @@ export const createOrUpdateDeployImageResources = async (
// Do not run serverless call during the dry run.
let imageStreamUrl: string = image?.dockerImageReference;
if (registry === RegistryType.External) {
let generatedImageStreamName: string = '';
if (imageStreamList && imageStreamList.length && verb === 'update') {
const originalImageStreamTag = _.find(originalImageStream?.status?.tags, [
'tag',
imageStreamTag,
]);
if (!_.isEmpty(originalImageStreamTag)) {
generatedImageStreamName = `${name}-${getRandomChars()}`;
}
}
const imageStreamResponse = await createOrUpdateImageStream(
formData,
dryRun,
_.get(appResources, 'imageStream.data'),
verb,
originalImageStream,
generatedImageStreamName ? 'create' : verb,
generatedImageStreamName,
);
const imageStreamRepo = imageStreamResponse.status.dockerImageRepository;
imageStreamUrl = imageStreamTag ? `${imageStreamRepo}:${imageStreamTag}` : imageStreamRepo;
Expand Down
Expand Up @@ -23,7 +23,12 @@ import {
getAppAnnotations,
mergeData,
} from '../../utils/resource-label-utils';
import { createService, createRoute, dryRunOpt } from '../../utils/shared-submit-utils';
import {
createService,
createRoute,
dryRunOpt,
getRandomChars,
} from '../../utils/shared-submit-utils';
import { AppResources } from '../edit-application/edit-application-types';
import {
GitImportFormData,
Expand Down Expand Up @@ -59,9 +64,13 @@ export const createOrUpdateImageStream = (
formData: GitImportFormData,
imageStreamData: K8sResourceKind,
dryRun: boolean,
originalImageStream?: K8sResourceKind,
appResources: AppResources,
verb: K8sVerb = 'create',
generatedImageStreamName: string = '',
): Promise<K8sResourceKind> => {
const imageStreamList = appResources?.imageStream?.data;
const imageStreamFilterData = _.orderBy(imageStreamList, ['metadata.resourceVersion'], ['desc']);
const originalImageStream = (imageStreamFilterData.length && imageStreamFilterData[0]) || {};
const {
name,
project: { name: namespace },
Expand All @@ -77,17 +86,16 @@ export const createOrUpdateImageStream = (
apiVersion: 'image.openshift.io/v1',
kind: 'ImageStream',
metadata: {
name,
name: `${generatedImageStreamName || name}`,
namespace,
labels: { ...defaultLabels, ...userLabels },
annotations: defaultAnnotations,
},
};
const imageStream = mergeData(originalImageStream, newImageStream);

return verb === 'update'
? k8sUpdate(ImageStreamModel, imageStream)
: k8sCreate(ImageStreamModel, imageStream, dryRun ? dryRunOpt : {});
: k8sCreate(ImageStreamModel, newImageStream, dryRun ? dryRunOpt : {});
};

export const createWebhookSecret = (
Expand Down Expand Up @@ -121,6 +129,7 @@ export const createOrUpdateBuildConfig = (
dryRun: boolean,
originalBuildConfig?: K8sResourceKind,
verb: K8sVerb = 'create',
generatedImageStreamName: string = '',
): Promise<K8sResourceKind> => {
const {
name,
Expand Down Expand Up @@ -180,7 +189,7 @@ export const createOrUpdateBuildConfig = (
output: {
to: {
kind: 'ImageStreamTag',
name: `${name}:latest`,
name: `${generatedImageStreamName || name}:latest`,
},
},
source: {
Expand Down Expand Up @@ -409,27 +418,39 @@ export const createOrUpdateResources = async (
},
git: { url: repository, type: gitType, ref },
pipeline,
resources,
} = formData;
const imageStreamName = _.get(imageStream, 'metadata.name');

createNewProject && (await createProject(formData.project));

const requests: Promise<K8sResourceKind>[] = [];

let generatedImageStreamName: string = '';
const imageStreamList = appResources?.imageStream?.data;
if (
resources === Resources.KnativeService &&
imageStreamList &&
imageStreamList.length &&
verb === 'update'
) {
generatedImageStreamName = `${name}-${getRandomChars()}`;
}
requests.push(
createOrUpdateImageStream(
formData,
imageStream,
dryRun,
_.get(appResources, 'imageStream.data'),
verb,
appResources,
generatedImageStreamName ? 'create' : verb,
generatedImageStreamName,
),
createOrUpdateBuildConfig(
formData,
imageStream,
dryRun,
_.get(appResources, 'buildConfig.data'),
verb,
generatedImageStreamName,
),
);

Expand Down
@@ -1,6 +1,7 @@
import { cloneDeep } from 'lodash';
import { validationSchema } from '../pipeline-resource/pipelineResource-validation-utils';
import { getDefinedObj, getRandomChars } from '../pipeline-resource/pipelineResource-utils';
import { getDefinedObj } from '../pipeline-resource/pipelineResource-utils';
import { getRandomChars } from '../../../utils/shared-submit-utils';
import { mockPipelineResourceData } from '../__mocks__/pipeline-resource-mock';

describe('Validation Pipeline Resource', () => {
Expand Down
Expand Up @@ -5,7 +5,7 @@ import {
PipelineTaskParam,
PipelineTaskResource,
} from '../../../utils/pipeline-augment';
import { getRandomChars } from '../pipeline-resource/pipelineResource-utils';
import { getRandomChars } from '../../../utils/shared-submit-utils';
import { AddNodeDirection } from '../pipeline-topology/const';
import { TaskErrorType, UpdateOperationType } from './const';
import {
Expand Down
Expand Up @@ -2,18 +2,12 @@ import * as _ from 'lodash';
import { k8sCreate, K8sResourceKind } from '@console/internal/module/k8s';
import { SecretModel } from '@console/internal/models';
import { PipelineResourceModel } from '../../../models';
import { getRandomChars } from '../../../utils/shared-submit-utils';

export interface ParamData {
[key: string]: any;
}

export const getRandomChars = (digit = 6): string => {
return Math.random()
.toString(36)
.replace(/[^a-z0-9]+/g, '')
.substr(1, digit);
};

export const getDefinedObj = (objData: ParamData): ParamData => {
return _.omitBy(objData, (v) => _.isUndefined(v) || _.isNull(v) || v === '');
};
Expand Down
Expand Up @@ -4,10 +4,10 @@ import { k8sCreate, K8sKind, k8sPatch, referenceForModel } from '@console/intern
import { errorModal } from '@console/internal/components/modals';
import { PipelineModel, PipelineRunModel } from '../models';
import startPipelineModal from '../components/pipelines/pipeline-form/StartPipelineModal';
import { getRandomChars } from '../components/pipelines/pipeline-resource/pipelineResource-utils';
import { Pipeline, PipelineRun } from './pipeline-augment';
import { pipelineRunFilterReducer } from './pipeline-filter-reducer';
import { getPipelineRunParams } from './pipeline-utils';
import { getRandomChars } from './shared-submit-utils';

export const handlePipelineRunSubmit = (pipelineRun: PipelineRun) => {
history.push(
Expand Down
Expand Up @@ -145,3 +145,10 @@ export const createRoute = (

return route;
};

export const getRandomChars = (digit = 6): string => {
return Math.random()
.toString(36)
.replace(/[^a-z0-9]+/g, '')
.substr(1, digit);
};