index.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403
  1. import * as R from 'ramda'
  2. import { RESTART_POLICY_OPTS } from '@K8S/constants'
  3. import { checkIpInSegment } from '@Compute/utils/createServer'
  4. import store from '@/store'
  5. import i18n from '@/locales'
  6. import validateForm from '@/utils/validate'
  7. import { removeHttp } from '@/utils/url'
  8. const validateValidPath = (rule, value, callback) => {
  9. if (value.startsWith('/')) {
  10. if (value === '/') {
  11. callback(new Error(i18n.t('k8s.text_130')))
  12. } else {
  13. callback()
  14. }
  15. } else {
  16. callback(new Error(i18n.t('k8s.text_131')))
  17. }
  18. }
  19. export const getSpecContainerParams = (fd, tabs) => {
  20. const tabKeys = tabs.map(val => val.key)
  21. const containers = tabKeys.map(val => {
  22. const env = []
  23. const volumeMounts = []
  24. const resources = {
  25. requests: {},
  26. }
  27. if (fd.containerEnvNames && R.is(Object, fd.containerEnvNames[val]) && !R.isEmpty(fd.containerEnvNames[val])) {
  28. Object.keys(fd.containerEnvNames[val]).forEach(key => {
  29. env.push({ name: fd.containerEnvNames[val][key], value: fd.containerEnvValues[val][key] })
  30. })
  31. }
  32. if (fd.containerVolumeMountNames && R.is(Object, fd.containerVolumeMountNames[val]) && !R.isEmpty(fd.containerVolumeMountNames[val])) {
  33. Object.keys(fd.containerVolumeMountNames[val]).forEach(key => {
  34. volumeMounts.push({ name: fd.containerVolumeMountNames[val][key], mountPath: fd.containerVolumeMountPaths[val][key] })
  35. })
  36. }
  37. const p = {
  38. name: fd.containerNames[val],
  39. image: (fd.registryImages?.[val] && removeHttp(fd.registryImages?.[val])) || fd.containerimages?.[val],
  40. securityContext: {
  41. privileged: fd.containerPrivilegeds[val],
  42. },
  43. }
  44. if (volumeMounts.length) p.volumeMounts = volumeMounts
  45. if (env.length) p.env = env
  46. if (fd.containerCommands[val]) {
  47. p.command = fd.containerCommands[val].split(' ')
  48. }
  49. if (fd.containerArgs[val]) {
  50. p.args = fd.containerArgs[val].split(' ')
  51. }
  52. if (fd.containerCpus[val]) resources.requests.cpu = fd.containerCpus[val] + 'm'
  53. if (fd.containerMemorys[val]) resources.requests.memory = fd.containerMemorys[val] + 'Mi'
  54. p.resources = resources
  55. return p
  56. })
  57. const params = {
  58. containers,
  59. }
  60. const volumesSum = params.containers.reduce((prev, next) => prev.concat(next.volumeMounts), []).filter(v => !!v)
  61. const volumesUnion = R.uniqBy(R.prop('name'), volumesSum) // 根据 name 去重
  62. const volumes = volumesUnion.map(val => ({
  63. name: val.name,
  64. persistentVolumeClaim: {
  65. claimName: val.name,
  66. },
  67. }))
  68. if (volumes && volumes.length) {
  69. params.volumes = volumes
  70. }
  71. return params
  72. }
  73. export const getLabels = (fd, key, value) => {
  74. const obj = {}
  75. if (R.is(Object, fd[key])) {
  76. const keys = Object.keys(fd[key])
  77. keys.forEach(k => {
  78. obj[fd[key][k]] = fd[value][k]
  79. })
  80. }
  81. return obj
  82. }
  83. export function getServiceConfigDecorators () {
  84. return {
  85. portMappings: {
  86. serviceType: [
  87. 'serviceType',
  88. {
  89. initialValue: 'internal',
  90. },
  91. ],
  92. loadBalancerCluster: [
  93. 'loadBalancerCluster',
  94. ],
  95. loadBalancerNetwork: [
  96. 'loadBalancerNetwork',
  97. ],
  98. loadBalancerAddress: (ip, network) => {
  99. return [
  100. 'loadBalancerAddress',
  101. {
  102. validateFirst: true,
  103. validateTrigger: ['blur', 'change'],
  104. rules: [
  105. {
  106. required: true,
  107. message: i18n.t('compute.text_218'),
  108. },
  109. {
  110. validator: validateForm('IPv4'),
  111. },
  112. {
  113. validator: checkIpInSegment(ip, network),
  114. },
  115. ],
  116. },
  117. ]
  118. },
  119. ports: {
  120. port: i => [
  121. `ports[${i}]`,
  122. {
  123. initialValue: 1,
  124. rules: [
  125. { required: true, message: i18n.t('k8s.text_134') },
  126. ],
  127. },
  128. ],
  129. targetPort: i => [
  130. `targetPorts[${i}]`,
  131. {
  132. initialValue: 1,
  133. rules: [
  134. { required: true, message: i18n.t('k8s.text_135') },
  135. ],
  136. },
  137. ],
  138. nodePort: i => [
  139. `nodePorts[${i}]`,
  140. {
  141. initialValue: 30000,
  142. rules: [
  143. { required: true, message: i18n.t('k8s.input_node_port') },
  144. {
  145. validator: (rule, val, cb) => {
  146. if ((val < 30000) || (val > 32767)) {
  147. cb(new Error(i18n.t('k8s.node_port.desc')))
  148. } else {
  149. cb()
  150. }
  151. },
  152. },
  153. ],
  154. },
  155. ],
  156. protocol: i => [
  157. `protocols[${i}]`,
  158. {
  159. initialValue: 'TCP',
  160. rules: [
  161. { required: true, message: i18n.t('k8s.text_136') },
  162. ],
  163. },
  164. ],
  165. },
  166. },
  167. }
  168. }
  169. export function getCreateDecorators (resource) {
  170. return {
  171. ...getServiceConfigDecorators(),
  172. name: [
  173. 'name',
  174. {
  175. validateFirst: true,
  176. rules: [
  177. { required: true, message: i18n.t('k8s.text_60') },
  178. { min: 2, max: 24, message: i18n.t('k8s.text_132'), trigger: 'blur' },
  179. { validator: this.$validate('k8sName') },
  180. ],
  181. },
  182. ],
  183. cluster: [
  184. 'cluster',
  185. {
  186. initialValue: store.state.common.k8s.cluster,
  187. rules: [
  188. { required: true, message: i18n.t('k8s.text_30'), trigger: 'blur' },
  189. ],
  190. },
  191. ],
  192. namespace: [
  193. 'namespace',
  194. {
  195. initialValue: store.state.common.k8s.namespace,
  196. rules: [
  197. { required: true, message: i18n.t('k8s.text_61'), trigger: 'blur' },
  198. ],
  199. },
  200. ],
  201. replicas: [
  202. 'replicas',
  203. {
  204. initialValue: 1,
  205. },
  206. ],
  207. imageSecrets: {
  208. secretType: [
  209. 'secretType',
  210. {
  211. initialValue: 'none',
  212. },
  213. ],
  214. imagePullSecrets: [
  215. 'imagePullSecrets',
  216. {
  217. rules: [
  218. { required: true, message: i18n.t('k8s.text_133') },
  219. ],
  220. },
  221. ],
  222. },
  223. restartPolicy: [
  224. 'restartPolicy',
  225. {
  226. initialValue: RESTART_POLICY_OPTS[resource][0].key,
  227. },
  228. ],
  229. schedule: [
  230. 'schedule',
  231. {
  232. rules: [
  233. { required: true, message: i18n.t('k8s.text_137') },
  234. ],
  235. },
  236. ],
  237. labels: {
  238. key: i => [
  239. `labelKeys[${i}]`,
  240. {
  241. rules: [
  242. { required: true, message: i18n.t('k8s.text_138') },
  243. { validator: this.$validate('k8sLabel') },
  244. ],
  245. },
  246. ],
  247. value: i => [
  248. `labelValues[${i}]`,
  249. {
  250. rules: [
  251. { required: true, message: i18n.t('k8s.text_139') },
  252. { validator: this.$validate('k8sLabel') },
  253. ],
  254. },
  255. ],
  256. },
  257. annotations: {
  258. key: i => [
  259. `annotationsKeys[${i}]`,
  260. {
  261. rules: [
  262. { required: true, message: i18n.t('k8s.text_138') },
  263. { validator: this.$validate('k8sLabel') },
  264. ],
  265. },
  266. ],
  267. value: i => [
  268. `annotationsValues[${i}]`,
  269. {
  270. rules: [
  271. { required: true, message: i18n.t('k8s.text_139') },
  272. { validator: this.$validate('k8sLabel') },
  273. ],
  274. },
  275. ],
  276. },
  277. containers: {
  278. name: i => [
  279. `containerNames[${i}]`,
  280. {
  281. rules: [
  282. { required: true, message: i18n.t('k8s.text_60') },
  283. { validator: this.$validate('k8sLabel') },
  284. ],
  285. },
  286. ],
  287. source: i => [
  288. `containerSources[${i}]`,
  289. {
  290. initialValue: 'custom',
  291. },
  292. ],
  293. registryImage: i => [
  294. `registryImages[${i}]`,
  295. {
  296. rules: [
  297. { required: true, message: i18n.t('common.tips.select', [i18n.t('k8s.repo.image.registry')]) },
  298. ],
  299. },
  300. ],
  301. image: i => [
  302. `containerimages[${i}]`,
  303. {
  304. rules: [
  305. { required: true, message: i18n.t('k8s.text_67') },
  306. ],
  307. },
  308. ],
  309. cpu: i => [
  310. `containerCpus[${i}]`,
  311. ],
  312. memory: i => [
  313. `containerMemorys[${i}]`,
  314. ],
  315. command: i => [
  316. `containerCommands[${i}]`,
  317. ],
  318. arg: i => [
  319. `containerArgs[${i}]`,
  320. ],
  321. volumeMount: i => ({
  322. key: j => [
  323. `containerVolumeMountNames[${i}][${j}]`,
  324. {
  325. rules: [
  326. { required: true, message: i18n.t('k8s.text_77') },
  327. ],
  328. },
  329. ],
  330. value: j => [
  331. `containerVolumeMountPaths[${i}][${j}]`,
  332. {
  333. rules: [
  334. { required: true, message: i18n.t('k8s.text_140') },
  335. { validator: validateValidPath, trigger: 'blur' },
  336. ],
  337. },
  338. ],
  339. }),
  340. env: i => ({
  341. key: j => [
  342. `containerEnvNames[${i}][${j}]`,
  343. {
  344. rules: [
  345. { required: true, message: i18n.t('k8s.text_140') },
  346. ],
  347. },
  348. ],
  349. value: j => [
  350. `containerEnvValues[${i}][${j}]`,
  351. {
  352. rules: [
  353. { required: true, message: i18n.t('k8s.text_140') },
  354. ],
  355. },
  356. ],
  357. }),
  358. privileged: i => [
  359. `containerPrivilegeds[${i}]`,
  360. {
  361. valuePropName: 'checked',
  362. initialValue: false,
  363. },
  364. ],
  365. },
  366. }
  367. }
  368. export function getServiceCreateParams (values) {
  369. const service = {}
  370. if (values.serviceType !== 'none') {
  371. service.isExternal = (values.serviceType === 'external')
  372. if (service.isExternal) {
  373. if (values.loadBalancerCluster) service.loadBalancerCluster = values.loadBalancerCluster
  374. if (values.loadBalancerNetwork) service.loadBalancerNetwork = values.loadBalancerNetwork
  375. if (values.loadBalancerAddress) service.loadBalancerAddress = values.loadBalancerAddress
  376. }
  377. const isNodePort = values.serviceType === 'nodePort'
  378. if (isNodePort) {
  379. service.type = 'NodePort'
  380. }
  381. if (values.ports) {
  382. const portMappings = Object.keys(values.ports).map(key => {
  383. const portMap = {
  384. port: +values.ports[key],
  385. targetPort: +values.targetPorts[key],
  386. protocol: values.protocols[key],
  387. }
  388. if (isNodePort) {
  389. portMap.nodePort = values.nodePorts[key]
  390. }
  391. return portMap
  392. })
  393. service.portMappings = portMappings
  394. }
  395. }
  396. return service
  397. }