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

feat: templates support conditional rendering #4937

Merged
merged 39 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
39 commits
Select commit Hold shift + click to select a range
b8b28f8
feat: template support if endif exp
zijiren233 Jul 31, 2024
0a935a4
opt: use heap algorithm
zijiren233 Jul 31, 2024
e9c6a7e
feat: support else grammar
zijiren233 Jul 31, 2024
3f2db34
feat: support elif grammar
zijiren233 Jul 31, 2024
1457ab9
fix: use a more precise regular expression
zijiren233 Jul 31, 2024
313bf4b
fix: generate yaml list need skip empty
zijiren233 Aug 1, 2024
fff73a7
chore: rename and clean js-yaml import
zijiren233 Aug 1, 2024
da83940
feat: input support if exp
zijiren233 Aug 1, 2024
db241ff
feat: input type suooprt string | number | choice | boolean
zijiren233 Aug 2, 2024
f5f2f58
fix: from number type use default input
zijiren233 Aug 2, 2024
60ff774
fix: checkbox
zijiren233 Aug 2, 2024
c99a712
feat: safe run expression
zijiren233 Aug 2, 2024
5dbb8ee
feat: isolation environment
zijiren233 Aug 2, 2024
d0fe25d
fix: default must be string
zijiren233 Aug 2, 2024
92c980f
fix: input style
zijiren233 Aug 2, 2024
82f00dc
feat: support more syntax analysis
zijiren233 Aug 2, 2024
8944255
fix: delete force update
zijiren233 Aug 2, 2024
baba196
fix: select default value
zijiren233 Aug 3, 2024
84c909d
chore: add repo branch to env and dataset
zijiren233 Aug 3, 2024
d732327
fix: missing platformEnvs
zijiren233 Aug 3, 2024
257ec0c
fix: debounce not working
zijiren233 Aug 3, 2024
d6e0ba3
feat: conditional rendering across yaml lists
zijiren233 Aug 5, 2024
3ac8b17
fix: api v1alpha
zijiren233 Aug 5, 2024
5cc6987
fix: split yaml list need use reg to match top row
zijiren233 Aug 5, 2024
a6e9ecb
fix: show field
zijiren233 Aug 5, 2024
04f5281
fix: use callback
zijiren233 Aug 9, 2024
04bc531
fix: optimize editor and form performance
zijiren233 Aug 9, 2024
046e438
chore: del desc
zijiren233 Aug 9, 2024
1310940
fix: change editor localstorage name
zijiren233 Aug 9, 2024
3b87f6e
chore: predef evaldata
zijiren233 Aug 9, 2024
b504793
feat: cache form
zijiren233 Aug 10, 2024
656cb09
fix: cache getTemplateValues
zijiren233 Aug 10, 2024
9d8dde3
fix: instance yaml missing parse description
zijiren233 Aug 19, 2024
782fb8d
chore: add comment
zijiren233 Aug 19, 2024
b425dce
opt: template envs
zijiren233 Aug 19, 2024
a45c1ce
fix: javascript.lang.security.audit.unsafe-formatstring.unsafe-format…
zijiren233 Aug 19, 2024
6e00334
chore: remove unuse isEqual
zijiren233 Aug 20, 2024
1ecbb4c
fix: ensure conditional blocks without matching else() do not render …
zijiren233 Aug 20, 2024
08f14d2
fix: editor scrolling performance
zijiren233 Aug 21, 2024
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
10 changes: 10 additions & 0 deletions frontend/pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions frontend/providers/template/deploy/Kubefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ ENV cloudDomain="127.0.0.1.nip.io"
ENV cloudPort=""
ENV certSecretName="wildcard-cert"
ENV templateRepoUrl="https://github.com/labring-actions/templates"
ENV templateRepoBranch="main"
ENV templateRepoPath="templates"

CMD ["kubectl apply -f manifests"]
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ spec:
- name: TEMPLATE_REPO_URL
value: {{ .templateRepoUrl }}
- name: TEMPLATE_REPO_BRANCH
value: "main"
value: {{ .templateRepoBranch }}
- name: SHOW_AUTHOR
value: "false"
image: ghcr.io/labring/sealos-template-frontend:latest
Expand Down
1 change: 1 addition & 0 deletions frontend/providers/template/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"i18next": "^23.11.5",
"immer": "^9.0.21",
"js-cookie": "^3.0.5",
"js-interpreter": "^5.1.2",
"js-yaml": "^4.1.0",
"jszip": "^3.10.1",
"lodash": "^4.17.21",
Expand Down
17 changes: 12 additions & 5 deletions frontend/providers/template/src/components/Select/index.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import React, { useRef, forwardRef, useMemo } from 'react';
import React, { useRef, forwardRef, useMemo, useState } from 'react';
import {
Menu,
Box,
Expand All @@ -14,6 +14,7 @@ import MyIcon, { type IconType } from '../Icon';

interface Props extends ButtonProps {
value?: string;
defaultValue?: string;
placeholder?: string;
list: {
icon?: string;
Expand All @@ -24,7 +25,7 @@ interface Props extends ButtonProps {
}

const MySelect = (
{ placeholder, value, width = 'auto', list, onchange, ...props }: Props,
{ placeholder, value, defaultValue, width = 'auto', list, onchange, ...props }: Props,
selectRef: any
) => {
const ref = useRef<HTMLButtonElement>(null);
Expand All @@ -40,14 +41,19 @@ const MySelect = (
};
const { isOpen, onOpen, onClose } = useDisclosure();

const [selectedValue, setSelectedValue] = useState(defaultValue || value || '');

useOutsideClick({
ref: SelectRef,
handler: () => {
onClose();
}
});

const activeMenu = useMemo(() => list.find((item) => item.value === value), [list, value]);
const activeMenu = useMemo(
() => list.find((item) => item.value === (value !== undefined ? value : selectedValue)),
[list, value, selectedValue]
);

return (
<Menu autoSelect={false} isOpen={isOpen} onOpen={onOpen} onClose={onClose}>
Expand Down Expand Up @@ -114,13 +120,14 @@ const MySelect = (
<MenuItem
key={item.value}
{...menuItemStyles}
{...(value === item.value
{...((value !== undefined ? value : selectedValue) === item.value
? {
color: 'myBlue.600'
}
: {})}
onClick={() => {
if (onchange && value !== item.value) {
setSelectedValue(item.value);
if (onchange) {
onchange(item.value);
}
}}
Expand Down
38 changes: 15 additions & 23 deletions frontend/providers/template/src/pages/api/getTemplateSource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,17 @@ import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { TemplateType } from '@/types/app';
import { getTemplateDataSource, handleTemplateToInstanceYaml } from '@/utils/json-yaml';
import {
getTemplateDataSource,
handleTemplateToInstanceYaml,
getYamlTemplate,
} from '@/utils/json-yaml';
import fs from 'fs';
import yaml from 'js-yaml';
import JsYaml from 'js-yaml';
import type { NextApiRequest, NextApiResponse } from 'next';
import path from 'path';
import { replaceRawWithCDN } from './listTemplate';
import { EnvResponse } from '@/types';
import { getTemplateEnvs } from '@/utils/tools';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
Expand All @@ -26,7 +30,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
console.log(error, 'Unauthorized allowed');
}

const { code, message, dataSource, templateYaml, TemplateEnvs, yamlList } =
const { code, message, dataSource, templateYaml, TemplateEnvs, appYaml } =
await GetTemplateByName({
namespace: user_namespace,
templateName: templateName
Expand All @@ -43,8 +47,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...dataSource,
...TemplateEnvs
},
yamlList: yamlList,
templateYaml: templateYaml
appYaml,
templateYaml
}
});
} catch (err: any) {
Expand All @@ -66,15 +70,7 @@ export async function GetTemplateByName({
const cdnUrl = process.env.CDN_URL;
const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template';

const TemplateEnvs: EnvResponse = {
SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io',
SEALOS_CERT_SECRET_NAME: process.env.SEALOS_CERT_SECRET_NAME || 'wildcard-cert',
TEMPLATE_REPO_URL:
process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates',
SEALOS_NAMESPACE: namespace || '',
SEALOS_SERVICE_ACCOUNT: namespace.replace('ns-', ''),
SHOW_AUTHOR: process.env.SHOW_AUTHOR || 'false'
};
const TemplateEnvs = getTemplateEnvs(namespace)

const originalPath = process.cwd();
const targetPath = path.resolve(originalPath, 'templates', targetFolder);
Expand All @@ -87,10 +83,7 @@ export async function GetTemplateByName({
? fs.readFileSync(_tempalte?.spec?.filePath, 'utf-8')
: fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8');

const yamlData = yaml.loadAll(yamlString);
const templateYaml: TemplateType = yamlData.find(
(item: any) => item.kind === 'Template'
) as TemplateType;
let { appYaml, templateYaml } = getYamlTemplate(yamlString, TemplateEnvs);
if (!templateYaml) {
return {
code: 40000,
Expand All @@ -103,8 +96,7 @@ export async function GetTemplateByName({
templateYaml.spec.icon = replaceRawWithCDN(templateYaml.spec.icon, cdnUrl);
}

const yamlList = yamlData.filter((item: any) => item.kind !== 'Template');
const dataSource = getTemplateDataSource(templateYaml, TemplateEnvs);
const dataSource = getTemplateDataSource(templateYaml);

// Convert template to instance
const instanceName = dataSource?.defaults?.['app_name']?.value;
Expand All @@ -115,14 +107,14 @@ export async function GetTemplateByName({
};
}
const instanceYaml = handleTemplateToInstanceYaml(templateYaml, instanceName);
yamlList.unshift(instanceYaml);
appYaml = `${JsYaml.dump(instanceYaml)}\n---\n${appYaml}`

return {
code: 20000,
message: 'success',
dataSource,
TemplateEnvs,
yamlList,
appYaml,
templateYaml
};
}
11 changes: 2 additions & 9 deletions frontend/providers/template/src/pages/api/platform/getEnv.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { EnvResponse } from '@/types/index';
import { getTemplateEnvs } from '@/utils/tools';
import type { NextApiRequest, NextApiResponse } from 'next';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
Expand All @@ -18,14 +19,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
}

jsonRes<EnvResponse>(res, {
data: {
SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io',
SEALOS_CERT_SECRET_NAME: process.env.SEALOS_CERT_SECRET_NAME || 'wildcard-cert',
TEMPLATE_REPO_URL:
process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates',
SEALOS_NAMESPACE: user_namespace || '',
SEALOS_SERVICE_ACCOUNT: user_namespace.replace('ns-', ''),
SHOW_AUTHOR: process.env.SHOW_AUTHOR || 'false'
}
data: getTemplateEnvs(user_namespace)
});
}
19 changes: 11 additions & 8 deletions frontend/providers/template/src/pages/api/updateRepo.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,12 @@ import { ApiResp } from '@/services/kubernet';
import { TemplateType } from '@/types/app';
import { exec } from 'child_process';
import fs from 'fs';
import JSYAML from 'js-yaml';
import type { NextApiRequest, NextApiResponse } from 'next';
import path from 'path';
import util from 'util';
import * as k8s from '@kubernetes/client-node';
import { getYamlTemplate } from '@/utils/json-yaml';
import { getTemplateEnvs } from '@/utils/tools';
const execAsync = util.promisify(exec);

const readFileList = (targetPath: string, fileList: unknown[] = []) => {
Expand Down Expand Up @@ -73,6 +74,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const jsonPath = path.resolve(originalPath, 'templates.json');
const branch = process.env.TEMPLATE_REPO_BRANCH || 'main';

const TemplateEnvs = getTemplateEnvs()

try {
const gitConfigResult = await execAsync(
'git config --global --add safe.directory /app/providers/template/templates',
Expand Down Expand Up @@ -105,13 +108,13 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
if (!item) return;
const fileName = path.basename(item);
const content = fs.readFileSync(item, 'utf-8');
const yamlTemplate = JSYAML.loadAll(content)[0] as TemplateType;
if (!!yamlTemplate) {
const appTitle = yamlTemplate.spec.title.toUpperCase();
yamlTemplate.spec['deployCount'] = templateStaticMap[appTitle];
yamlTemplate.spec['filePath'] = item;
yamlTemplate.spec['fileName'] = fileName;
jsonObjArr.push(yamlTemplate);
const { templateYaml } = getYamlTemplate(content, TemplateEnvs)
if (!!templateYaml) {
const appTitle = templateYaml.spec.title.toUpperCase();
templateYaml.spec['deployCount'] = templateStaticMap[appTitle];
templateYaml.spec['filePath'] = item;
templateYaml.spec['fileName'] = fileName;
jsonObjArr.push(templateYaml);
}
} catch (error) {
console.log(error, 'yaml parse error');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import { getK8s } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { generateYamlList, parseTemplateString } from '@/utils/json-yaml';
import JSYAML from 'js-yaml';
import { mapValues, reduce } from 'lodash';
import type { NextApiRequest, NextApiResponse } from 'next';
import { GetTemplateByName } from '../getTemplateSource';
Expand All @@ -19,7 +18,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
kubeconfig: await authSession(req.headers)
});

const { code, message, dataSource, templateYaml, TemplateEnvs, yamlList } =
const { code, message, dataSource, templateYaml, TemplateEnvs, appYaml } =
await GetTemplateByName({
namespace,
templateName
Expand All @@ -40,9 +39,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
},
{}
);
const yamlString = yamlList?.map((item) => JSYAML.dump(item)).join('---\n');

const generateStr = parseTemplateString(yamlString!, /\$\{\{\s*(.*?)\s*\}\}/g, {
const generateStr = parseTemplateString(appYaml || '', {
...TemplateEnvs,
defaults: _defaults,
inputs: { ..._inputs, ...templateForm }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import { authSession } from '@/services/backend/auth';
import { getK8s } from '@/services/backend/kubernetes';
import { parseTemplateString, generateYamlList } from '@/utils/json-yaml';
import { mapValues, reduce } from 'lodash';
import JSYAML from 'js-yaml';
import JsYaml from 'js-yaml';

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
Expand All @@ -19,7 +19,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
kubeconfig: await authSession(req.headers)
});

const { code, message, dataSource, templateYaml, TemplateEnvs, yamlList } =
const { code, message, dataSource, templateYaml, TemplateEnvs, appYaml } =
await GetTemplateByName({
namespace,
templateName
Expand All @@ -40,15 +40,14 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
},
{}
);
const yamlString = yamlList?.map((item) => JSYAML.dump(item)).join('---\n');

const generateStr = parseTemplateString(yamlString!, /\$\{\{\s*(.*?)\s*\}\}/g, {
const generateStr = parseTemplateString(appYaml || '', {
...TemplateEnvs,
defaults: _defaults,
inputs: { ..._inputs, ...templateForm }
});
const correctYaml = generateYamlList(generateStr, app_name);
const yaml = JSYAML.loadAll(correctYaml[0].value);
const yaml = JsYaml.loadAll(correctYaml[0].value);

jsonRes(res, {
code: 200,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
kubeconfig: await authSession(req.headers)
});

const { code, message, dataSource, templateYaml, TemplateEnvs, yamlList } =
const { code, message, dataSource, templateYaml, TemplateEnvs, appYaml } =
await GetTemplateByName({
namespace,
templateName
Expand All @@ -30,8 +30,8 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
...dataSource,
...TemplateEnvs
},
yamlList: yamlList,
templateYaml: templateYaml
appYaml,
templateYaml
}
});
} catch (err: any) {
Expand Down
Loading
Loading