Skip to content

Commit

Permalink
feat: Name modification and deployment count display
Browse files Browse the repository at this point in the history
Signed-off-by: jingyang <3161362058@qq.com>
  • Loading branch information
zjy365 committed Jan 3, 2024
1 parent d73becb commit 4f46d33
Show file tree
Hide file tree
Showing 21 changed files with 403 additions and 169 deletions.
5 changes: 4 additions & 1 deletion frontend/.gitignore
@@ -1 +1,4 @@
node_modules/
node_modules/
.next
.env*.local
next-env.d.ts
4 changes: 3 additions & 1 deletion frontend/providers/template/.env.template
@@ -1,4 +1,6 @@
NEXT_PUBLIC_MOCK_USER=
SEALOS_CLOUD_DOMAIN=
SEALOS_CERT_SECRET_NAME=
TEMPLATE_REPO_URL="https://github.com/labring-actions/templates"
TEMPLATE_REPO_URL="https://github.com/labring-actions/templates"
# The CDN_URL environment variable is used to specify a CDN address; when set, it replaces raw.githubusercontent.com in the resource loading URL. If not set, the default address is used.
CDN_URL=
49 changes: 48 additions & 1 deletion frontend/providers/template/deploy/manifests/deploy.yaml.tmpl
Expand Up @@ -83,4 +83,51 @@ spec:
protocol: TCP
targetPort: 3000
selector:
app: template-frontend
app: template-frontend
---
apiVersion: batch/v1
kind: CronJob
metadata:
namespace: template-frontend
name: template-static
spec:
schedule: "0 0 * * *"
jobTemplate:
spec:
template:
spec:
serviceAccountName: default
containers:
- name: template-static
image: bitnami/kubectl:latest
command:
- /bin/sh
- -c
args:
- >
echo "$(kubectl get instances -A -o=jsonpath='{range .items[*]}{.spec.title}{"\n"}{end}' | tr a-z A-Z | sort | uniq -c | sort -nr | sed 's/ *//g')" > install-count
kubectl create configmap -n template-frontend template-static --from-file=install-count -o yaml --dry-run=client | kubectl apply -f -
imagePullPolicy: IfNotPresent
restartPolicy: OnFailure
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRole
metadata:
name: template-frontend-static-role
rules:
- apiGroups: [""]
resources: ["configmaps"]
verbs: ["get", "list", "watch", "create", "update", "patch", "delete"]
---
apiVersion: rbac.authorization.k8s.io/v1
kind: ClusterRoleBinding
metadata:
name: template-frontend-static-role-binding
subjects:
- kind: ServiceAccount
name: default
namespace: template-frontend
roleRef:
kind: ClusterRole
name: template-frontend-static-role
apiGroup: rbac.authorization.k8s.io
10 changes: 7 additions & 3 deletions frontend/providers/template/public/locales/en/common.json
Expand Up @@ -148,15 +148,15 @@
"Heading to sealos soon": "Heading to sealos soon",
"develop": {
"publish": "publish",
"YAML Detection Tool": "YAML Detection Tool",
"Development": "Development",
"Please enter YAML code": "Please enter YAML code",
"Preview": "Preview",
"Configure Form": "Configure Form",
"YAML File": "YAML File",
"Template Development": "Template Development",
"Dryrun Deploy": "Dryrun Deploy",
"Formal Deploy": "Formal Deploy"
"Formal Deploy": "Formal Deploy",
"Debugging Template": "Debugging Template"
},
"SideBar": {
"Applications": "Applications",
Expand All @@ -183,5 +183,9 @@
"Markdown Part": "Markdown Part",
"Button Effect": "Button Effect",
"Type": "Type",
"Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view"
"Deployment successful, please go to My Application to view": "Deployment successful, please go to My Application to view",
"Edit": "Edit",
"Edit App Name": "Edit App Name",
"Installation Time": "Installation Time",
"users installed the app": "{{count}} users have installed the app"
}
10 changes: 7 additions & 3 deletions frontend/providers/template/public/locales/zh/common.json
Expand Up @@ -154,15 +154,15 @@
"Heading to sealos soon": "即将前往sealos",
"develop": {
"publish": "发布",
"YAML Detection Tool": "YAML 检测工具",
"Development": "开发",
"Please enter YAML code": "请输入yaml代码",
"Preview": "预览",
"Configure Form": "配置表单",
"YAML File": "YAML 文件",
"Template Development": "模板开发",
"Dryrun Deploy": "试运行部署",
"Formal Deploy": "正式部署"
"Formal Deploy": "正式部署",
"Debugging Template": "在线调试模板"
},
"SideBar": {
"Applications": "所有应用",
Expand All @@ -189,5 +189,9 @@
"Markdown Part": "Markdown 片段",
"Button Effect": "按钮效果",
"Deployment successful, please go to My Application to view": "部署成功,请前往我的应用查看",
"Type": "类型"
"Type": "类型",
"Edit": "编辑",
"Edit App Name": "编辑应用名称",
"Installation Time": "安装时间",
"users installed the app": "已有 {{count}} 名用户安装应用"
}
8 changes: 3 additions & 5 deletions frontend/providers/template/src/components/layout/appmenu.tsx
Expand Up @@ -26,8 +26,7 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) {
width="16"
height="17"
viewBox="0 0 16 17"
fill="none"
>
fill="none">
<path
d="M14.4733 14.2786L12 11.8252C12.9601 10.6282 13.425 9.10876 13.2992 7.57942C13.1734 6.05009 12.4664 4.62708 11.3237 3.60299C10.1809 2.57889 8.6892 2.03156 7.15528 2.07354C5.62136 2.11551 4.16181 2.7436 3.07676 3.82865C1.99171 4.9137 1.36362 6.37325 1.32164 7.90717C1.27967 9.44109 1.827 10.9328 2.85109 12.0756C3.87519 13.2183 5.2982 13.9253 6.82753 14.0511C8.35686 14.1769 9.87627 13.712 11.0733 12.7519L13.5267 15.2052C13.5886 15.2677 13.6624 15.3173 13.7436 15.3512C13.8249 15.385 13.912 15.4024 14 15.4024C14.088 15.4024 14.1751 15.385 14.2564 15.3512C14.3376 15.3173 14.4114 15.2677 14.4733 15.2052C14.5935 15.0809 14.6607 14.9148 14.6607 14.7419C14.6607 14.569 14.5935 14.4029 14.4733 14.2786ZM7.33333 12.7519C6.41035 12.7519 5.5081 12.4782 4.74067 11.9654C3.97324 11.4526 3.3751 10.7238 3.02189 9.87108C2.66868 9.01836 2.57627 8.08005 2.75633 7.1748C2.9364 6.26956 3.38085 5.43804 4.0335 4.78539C4.68614 4.13275 5.51766 3.68829 6.42291 3.50822C7.32815 3.32816 8.26646 3.42058 9.11919 3.77378C9.97191 4.12699 10.7007 4.72513 11.2135 5.49256C11.7263 6.25999 12 7.16224 12 8.08522C12 9.3229 11.5083 10.5099 10.6332 11.3851C9.75799 12.2602 8.57101 12.7519 7.33333 12.7519Z"
fill="#5A646E"
Expand Down Expand Up @@ -62,12 +61,11 @@ export default function AppMenu({ isMobile }: { isMobile: boolean }) {
borderRadius={'40px'}
bottom={'28px'}
userSelect={'none'}
onClick={() => router.push('/develop')}
>
onClick={() => router.push('/develop')}>
<MyIcon name="tool" fill={'transparent'} />
{!isMobile && (
<Text ml="8px" color={'#485058'} fontWeight={500} cursor={'pointer'} fontSize={'12px'}>
{t('develop.YAML Detection Tool')}
{t('develop.Debugging Template')}
</Text>
)}
</Flex>
Expand Down
2 changes: 2 additions & 0 deletions frontend/providers/template/src/constants/keys.ts
Expand Up @@ -10,6 +10,8 @@ export const gpuNodeSelectorKey = 'nvidia.com/gpu.product';
export const gpuResourceKey = 'nvidia.com/gpu';
// template
export const templateDeployKey = 'cloud.sealos.io/deploy-on-sealos';
export const templateDisplayNameKey = 'cloud.sealos.io/deploy-on-sealos-displayName';

// db
export const kubeblocksTypeKey = 'clusterdefinition.kubeblocks.io/name';
export const dbProviderKey = 'sealos-db-provider-cr';
Expand Down
Expand Up @@ -63,6 +63,8 @@ export async function GetTemplateByName({
templateName: string;
}) {
const cdnUrl = process.env.CDN_URL;
const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template';

const TemplateEnvs = {
SEALOS_CLOUD_DOMAIN: process.env.SEALOS_CLOUD_DOMAIN || 'cloud.sealos.io',
SEALOS_CERT_SECRET_NAME: process.env.SEALOS_CERT_SECRET_NAME || 'wildcard-cert',
Expand All @@ -72,13 +74,15 @@ export async function GetTemplateByName({
};

const originalPath = process.cwd();
const targetPath = path.resolve(originalPath, 'FastDeployTemplates', 'template');
const targetPath = path.resolve(originalPath, 'FastDeployTemplates', targetFolder);
// Query by file name in template details
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
const jsonData: TemplateType[] = JSON.parse(fs.readFileSync(jsonPath, 'utf8'));
const _tempalte = jsonData.find((item) => item.metadata.name === templateName);
const _tempalteName = _tempalte ? _tempalte.spec.fileName : `${templateName}.yaml`;
const yamlString = fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8');
const yamlString = _tempalte?.spec?.filePath
? fs.readFileSync(_tempalte?.spec?.filePath, 'utf-8')
: fs.readFileSync(`${targetPath}/${_tempalteName}`, 'utf-8');

const yamlData = yaml.loadAll(yamlString);
const templateYaml: TemplateType = yamlData.find(
Expand All @@ -90,6 +94,7 @@ export async function GetTemplateByName({
message: 'Lack of kind template'
};
}
templateYaml.spec.deployCount = _tempalte?.spec?.deployCount;
if (cdnUrl) {
templateYaml.spec.readme = replaceRawWithCDN(templateYaml.spec.readme, cdnUrl);
templateYaml.spec.icon = replaceRawWithCDN(templateYaml.spec.icon, cdnUrl);
Expand Down
1 change: 0 additions & 1 deletion frontend/providers/template/src/pages/api/listTemplate.ts
Expand Up @@ -20,7 +20,6 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
const originalPath = process.cwd();
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
const cdnUrl = process.env.CDN_URL;

try {
if (fs.existsSync(jsonPath)) {
const jsonData = fs.readFileSync(jsonPath, 'utf8');
Expand Down
38 changes: 34 additions & 4 deletions frontend/providers/template/src/pages/api/updateRepo.ts
@@ -1,3 +1,4 @@
import { K8sApiDefault } from '@/services/backend/kubernetes';
import { jsonRes } from '@/services/backend/response';
import { ApiResp } from '@/services/kubernet';
import { TemplateType } from '@/types/app';
Expand All @@ -7,9 +8,10 @@ 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';
const execAsync = util.promisify(exec);

const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath: string) => {
const readFileList = (targetPath: string, fileList: unknown[] = []) => {
// fix ci
const sanitizePath = (inputPath: string) => {
if (typeof inputPath !== 'string') {
Expand All @@ -26,16 +28,39 @@ const readFileList = (targetPath: string, fileList: unknown[] = [], handlePath:
const isYamlFile = path.extname(item) === '.yaml' || path.extname(item) === '.yml';
if (stats.isFile() && isYamlFile && item !== 'template.yaml') {
fileList.push(filePath);
} else if (stats.isDirectory() && item === handlePath) {
readFileList(filePath, fileList, handlePath);
} else if (stats.isDirectory()) {
readFileList(filePath, fileList);
}
});
};

export async function GetTemplateStatic() {
try {
const defaultKC = K8sApiDefault();
const result = await defaultKC
.makeApiClient(k8s.CoreV1Api)
.readNamespacedConfigMap('template-static', 'template-frontend');

const inputString = result?.body?.data?.['install-count'] || '';
const installCountArray = inputString.split(/\n/).filter(Boolean);

const temp: { [key: string]: number } = {};
installCountArray.forEach((item) => {
const [count, name] = item.trim().split(/\s/);
temp[name] = parseInt(count, 10);
});
return temp;
} catch (error) {
console.log(error, 'error: kubectl get configmap/template-static ');
return {};
}
}

export default async function handler(req: NextApiRequest, res: NextApiResponse<ApiResp>) {
try {
const repoHttpUrl =
process.env.TEMPLATE_REPO_URL || 'https://github.com/labring-actions/templates';
const targetFolder = process.env.TEMPLATE_REPO_FOLDER || 'template';
const originalPath = process.cwd();
const targetPath = path.resolve(originalPath, 'FastDeployTemplates');
const jsonPath = path.resolve(originalPath, 'fast_deploy_template.json');
Expand All @@ -60,8 +85,10 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
}

let fileList: unknown[] = [];
readFileList(targetPath, fileList, 'template');
const _targetPath = path.join(targetPath, targetFolder);
readFileList(_targetPath, fileList);

const templateStaticMap: { [key: string]: number } = await GetTemplateStatic();
let jsonObjArr: unknown[] = [];
fileList.forEach((item: any) => {
try {
Expand All @@ -70,6 +97,9 @@ export default async function handler(req: NextApiRequest, res: NextApiResponse<
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);
}
Expand Down

0 comments on commit 4f46d33

Please sign in to comment.