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

fix(gitops): manifest validation warning [EE-6859] #11664

Merged
merged 1 commit into from
May 13, 2024
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
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { IFormController } from 'angular';
import { FormikErrors } from 'formik';

import { GitFormModel } from '@/react/portainer/gitops/types';
import { DeployMethod, GitFormModel } from '@/react/portainer/gitops/types';
import { validateGitForm } from '@/react/portainer/gitops/GitForm';
import { notifyError } from '@/portainer/services/notifications';
import { IAuthenticationService } from '@/portainer/services/types';
Expand All @@ -26,6 +26,8 @@ export default class GitFormController {

createdFromCustomTemplateId?: number;

deployMethod?: DeployMethod;

/* @ngInject */
constructor(
$async: <T>(fn: () => Promise<T>) => Promise<T>,
Expand Down Expand Up @@ -67,7 +69,8 @@ export default class GitFormController {
this.errors = await validateGitForm(
this.gitCredentials,
value,
isCreatedFromCustomTemplate
isCreatedFromCustomTemplate,
this.deployMethod
);
if (this.errors && Object.keys(this.errors).length > 0) {
this.gitForm?.$setValidity('gitForm', false, this.gitForm);
Expand Down
6 changes: 3 additions & 3 deletions app/react/portainer/gitops/GitForm.stories.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { withUserProvider } from '@/react/test-utils/withUserProvider';
import { GitCredential } from '@/react/portainer/account/git-credentials/types';

import { GitForm, buildGitValidationSchema } from './GitForm';
import { GitFormModel } from './types';
import { DeployMethod, GitFormModel } from './types';

export default {
component: GitForm,
Expand Down Expand Up @@ -45,7 +45,7 @@ interface Args {
isAdditionalFilesFieldVisible: boolean;
isAuthExplanationVisible: boolean;
isDockerStandalone: boolean;
deployMethod: 'compose' | 'manifest';
deployMethod: DeployMethod;
isForcePullVisible: boolean;
}

Expand Down Expand Up @@ -73,7 +73,7 @@ export function Primary({
return (
<Formik
initialValues={initialValues}
validationSchema={() => buildGitValidationSchema([], false)}
validationSchema={() => buildGitValidationSchema([], false, 'compose')}
onSubmit={() => {}}
>
{({ values, errors, setValues }) => (
Expand Down
21 changes: 15 additions & 6 deletions app/react/portainer/gitops/GitForm.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import { useState } from 'react';
import { ComposePathField } from '@/react/portainer/gitops/ComposePathField';
import { RefField } from '@/react/portainer/gitops/RefField';
import { GitFormUrlField } from '@/react/portainer/gitops/GitFormUrlField';
import { GitFormModel } from '@/react/portainer/gitops/types';
import { DeployMethod, GitFormModel } from '@/react/portainer/gitops/types';
import { TimeWindowDisplay } from '@/react/portainer/gitops/TimeWindowDisplay';

import { FormSection } from '@@/form-components/FormSection';
Expand All @@ -24,7 +24,7 @@ interface Props {
value: GitFormModel;
onChange: (value: Partial<GitFormModel>) => void;
environmentType?: 'DOCKER' | 'KUBERNETES' | undefined;
deployMethod?: 'compose' | 'manifest';
deployMethod?: DeployMethod;
isDockerStandalone?: boolean;
isAdditionalFilesFieldVisible?: boolean;
isForcePullVisible?: boolean;
Expand Down Expand Up @@ -142,17 +142,24 @@ export function GitForm({
export async function validateGitForm(
gitCredentials: Array<GitCredential>,
formValues: GitFormModel,
isCreatedFromCustomTemplate: boolean
isCreatedFromCustomTemplate: boolean,
deployMethod: DeployMethod = 'compose'
) {
return validateForm<GitFormModel>(
() => buildGitValidationSchema(gitCredentials, isCreatedFromCustomTemplate),
() =>
buildGitValidationSchema(
gitCredentials,
isCreatedFromCustomTemplate,
deployMethod
),
formValues
);
}

export function buildGitValidationSchema(
gitCredentials: Array<GitCredential>,
isCreatedFromCustomTemplate: boolean
isCreatedFromCustomTemplate: boolean,
deployMethod: DeployMethod
): SchemaOf<GitFormModel> {
return object({
RepositoryURL: string()
Expand All @@ -171,7 +178,9 @@ export function buildGitValidationSchema(
.required('Repository URL is required'),
RepositoryReferenceName: refFieldValidation(),
ComposeFilePathInRepository: string().required(
'Compose file path is required'
deployMethod === 'compose'
? 'Compose file path is required'
: 'Manifest file path is required'
),
AdditionalFiles: array(string().required('Path is required')).default([]),
RepositoryURLValid: boolean().default(false),
Expand Down
2 changes: 2 additions & 0 deletions app/react/portainer/gitops/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -52,6 +52,8 @@ export type GitNewCredentialModel = {

export type GitAuthModel = GitCredentialsModel & GitNewCredentialModel;

export type DeployMethod = 'compose' | 'manifest';

export interface GitFormModel extends GitAuthModel {
RepositoryURL: string;
RepositoryURLValid?: boolean;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@ import { EnvironmentId } from '@/react/portainer/environments/types';
import { useEnvironmentDeploymentOptions } from '@/react/portainer/environments/queries/useEnvironment';
import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment';
import { isKubernetesEnvironment } from '@/react/portainer/environments/utils';
import { DeployMethod } from '@/react/portainer/gitops/types';

import { useInitialValues } from './useInitialValues';
import { FormValues, initialBuildMethods } from './types';
Expand All @@ -23,10 +24,12 @@ export function CreateForm({
viewType: 'kube' | 'docker' | 'edge';
defaultType: StackType;
}) {
const deployMethod: DeployMethod =
defaultType === StackType.Kubernetes ? 'manifest' : 'compose';
const isEdge = !environmentId;
const router = useRouter();
const mutation = useCreateTemplateMutation();
const validation = useValidation({ viewType });
const validation = useValidation({ viewType, deployMethod });
const buildMethods = useBuildMethods();

const initialValues = useInitialValues({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,10 @@ export function useInitialValues({

const { appTemplateId, type = defaultType } = useAppTemplateParams();

// don't make the file path 'docker-compose.yml' in a kube environment. Keep it empty with the existing 'manifest.yml' placeholder
const initialFilePathInRepository =
type === StackType.Kubernetes ? '' : 'docker-compose.yml';

const {
params: { fileContent = '' },
} = useCurrentStateAndParams();
Expand All @@ -49,7 +53,7 @@ export function useInitialValues({
RepositoryAuthentication: false,
RepositoryUsername: '',
RepositoryPassword: '',
ComposeFilePathInRepository: 'docker-compose.yml',
ComposeFilePathInRepository: initialFilePathInRepository,
AdditionalFiles: [],
RepositoryURLValid: true,
TLSSkipVerify: false,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useGitCredentials } from '@/react/portainer/account/git-credentials/git
import { useCurrentUser } from '@/react/hooks/useUser';
import { useCustomTemplates } from '@/react/portainer/templates/custom-templates/queries/useCustomTemplates';
import { edgeFieldsetValidation } from '@/react/portainer/templates/custom-templates/CreateView/EdgeSettingsFieldset.validation';
import { DeployMethod } from '@/react/portainer/gitops/types';

import { file } from '@@/form-components/yup-file-validation';
import {
Expand All @@ -22,8 +23,10 @@ import { initialBuildMethods } from './types';

export function useValidation({
viewType,
deployMethod,
}: {
viewType: 'kube' | 'docker' | 'edge';
deployMethod: DeployMethod;
}) {
const { user } = useCurrentUser();
const gitCredentialsQuery = useGitCredentials(user.Id);
Expand Down Expand Up @@ -58,7 +61,11 @@ export function useValidation({
Git: mixed().when('Method', {
is: git.value,
then: () =>
buildGitValidationSchema(gitCredentialsQuery.data || [], false),
buildGitValidationSchema(
gitCredentialsQuery.data || [],
false,
deployMethod
),
}),
Variables: variablesValidation(),
EdgeSettings: viewType === 'edge' ? edgeFieldsetValidation() : mixed(),
Expand All @@ -68,6 +75,11 @@ export function useValidation({
viewType,
})
),
[customTemplatesQuery.data, gitCredentialsQuery.data, viewType]
[
customTemplatesQuery.data,
gitCredentialsQuery.data,
viewType,
deployMethod,
]
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ import { EnvironmentId } from '@/react/portainer/environments/types';
import { useEnvironmentDeploymentOptions } from '@/react/portainer/environments/queries/useEnvironment';
import { useCurrentEnvironment } from '@/react/hooks/useCurrentEnvironment';
import { isKubernetesEnvironment } from '@/react/portainer/environments/utils';
import { DeployMethod } from '@/react/portainer/gitops/types';
import { StackType } from '@/react/common/stacks/types';

import { CustomTemplate } from '../types';
import { useUpdateTemplateMutation } from '../queries/useUpdateTemplateMutation';
Expand All @@ -32,10 +34,13 @@ export function EditForm({
const router = useRouter();
const disableEditor = useDisableEditor(isGit);
const mutation = useUpdateTemplateMutation();
const deployMethod: DeployMethod =
template.Type === StackType.Kubernetes ? 'manifest' : 'compose';
const validation = useValidation({
viewType,
isGit,
templateId: template.Id,
deployMethod,
});

const fileContentQuery = useCustomTemplateFile(template.Id);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import { useGitCredentials } from '@/react/portainer/account/git-credentials/git
import { useCurrentUser } from '@/react/hooks/useUser';
import { useCustomTemplates } from '@/react/portainer/templates/custom-templates/queries/useCustomTemplates';
import { edgeFieldsetValidation } from '@/react/portainer/templates/custom-templates/CreateView/EdgeSettingsFieldset.validation';
import { DeployMethod } from '@/react/portainer/gitops/types';

import { CustomTemplate } from '../types';
import { TemplateViewType } from '../useViewType';
Expand All @@ -18,10 +19,12 @@ export function useValidation({
isGit,
templateId,
viewType,
deployMethod,
}: {
isGit: boolean;
templateId: CustomTemplate['Id'];
viewType: TemplateViewType;
deployMethod: DeployMethod;
}) {
const { user } = useCurrentUser();
const gitCredentialsQuery = useGitCredentials(user.Id);
Expand All @@ -47,7 +50,11 @@ export function useValidation({
FileContent: string().required('Template is required.'),

Git: isGit
? buildGitValidationSchema(gitCredentialsQuery.data || [], false)
? buildGitValidationSchema(
gitCredentialsQuery.data || [],
false,
deployMethod
)
: mixed(),
Variables: variablesValidation(),
EdgeSettings: viewType === 'edge' ? edgeFieldsetValidation() : mixed(),
Expand All @@ -64,6 +71,7 @@ export function useValidation({
isGit,
templateId,
viewType,
deployMethod,
]
);
}