index.vue 9.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295
  1. <template>
  2. <div>
  3. <page-header :title="id ? $t('compute.text_247') : $t('compute.text_248')" />
  4. <a-form class="mt-3" :form="form" v-bind="formItemLayout">
  5. <a-form-item :label="$t('compute.text_228')">
  6. <a-input :disabled="!!id" v-decorator="decorators.name" :placeholder="$t('validator.serverName')" />
  7. </a-form-item>
  8. <a-form-item :label="$t('compute.text_90')">
  9. <code-mirror v-decorator="decorators.hosts" @input="(v) => handleCodeInput('hosts', v)" :options="cmOptions" style="line-height: 25px" view-height="120px" :is-scroll="true" />
  10. </a-form-item>
  11. <!-- 文件上传 -->
  12. <upload :defaultFiles="defaultFiles" />
  13. <a-form-item label="playbook" required>
  14. <code-mirror v-decorator="decorators.playbook" @input="(v) => handleCodeInput('playbook', v)" :options="cmOptions" style="line-height: 25px" view-height="300px" :is-scroll="true" />
  15. </a-form-item>
  16. <a-form-item :label="$t('compute.text_249')" required>
  17. <a-switch :defaultChecked="decorators.start[1].initialValue" v-decorator="decorators.start" :checkedChildren="$t('compute.text_115')" :unCheckedChildren="$t('compute.text_116')" />
  18. <span slot="extra">{{$t('compute.text_250')}}</span>
  19. </a-form-item>
  20. <a-form-item :label="$t('compute.text_242')" required>
  21. <a-input-number v-decorator="decorators.hour" :min="1" @blur="handleNumBlur" />
  22. <span slot="extra">{{$t('compute.text_251')}}</span>
  23. </a-form-item>
  24. </a-form>
  25. <page-footer>
  26. <a-button type="primary" @click="handleConfirm" :loading="loading" class="ml-3">{{$t('compute.text_162')}}</a-button>
  27. <a-button type="primary" @click="handleCancel" :loading="loading" class="ml-3">{{$t('compute.text_135')}}</a-button>
  28. </page-footer>
  29. </div>
  30. </template>
  31. <script>
  32. // import * as R from 'ramda'
  33. import Upload from './components/Upload'
  34. import { CreateServerForm } from '@Compute/constants'
  35. export default {
  36. name: 'AnsibleTemplateCreate',
  37. components: {
  38. Upload,
  39. },
  40. data () {
  41. return {
  42. id: undefined,
  43. loading: false,
  44. retData: {},
  45. form: this.$form.createForm(this, { onFieldsChange: this.onFieldsChange }),
  46. cmOptions: {
  47. tabSize: 2,
  48. styleActiveLine: true,
  49. lineNumbers: true,
  50. line: true,
  51. mode: 'text/x-yaml',
  52. theme: 'material',
  53. },
  54. formItemLayout: {
  55. wrapperCol: { span: CreateServerForm.wrapperCol },
  56. labelCol: { span: CreateServerForm.labelCol },
  57. },
  58. modNames: ['yum', 'package', 'group', 'user', 'get_url', 'file', 'unarchive', 'template', 'service'],
  59. }
  60. },
  61. computed: {
  62. defaultFiles () {
  63. const { playbook = {} } = this.retData
  64. return playbook.files || []
  65. },
  66. decorators () {
  67. const { name, playbook = {}, start, hour } = this.retData
  68. const { inventory, modules } = playbook
  69. let hostStr = ''
  70. if (inventory && inventory.hosts && inventory.hosts.length > 0) {
  71. const _arr = []
  72. const { name, vars } = playbook.inventory.hosts[0]
  73. _arr.push(name)
  74. if (vars) {
  75. Object.keys(vars).forEach(k => {
  76. _arr.push(`${k}=${vars[k]}`)
  77. })
  78. }
  79. hostStr = _arr.join(' ')
  80. }
  81. let moduleStr = ''
  82. if (modules && modules.length > 0) {
  83. playbook.modules.forEach((item, i) => {
  84. item.args = item.args || []
  85. const { name, args } = item
  86. moduleStr += `${i ? '\r' : ''}${name} ${args.join(' ')}`
  87. })
  88. }
  89. return {
  90. name: [
  91. 'name',
  92. {
  93. initialValue: name,
  94. validateTrigger: 'blur',
  95. validateFirst: true,
  96. rules: [
  97. { required: true, message: this.$t('compute.text_210') },
  98. { validator: this.$validate('serverName') },
  99. ],
  100. },
  101. ],
  102. hosts: [
  103. 'hosts',
  104. {
  105. initialValue: hostStr,
  106. validateFirst: true,
  107. rules: [
  108. { required: true, message: this.$t('compute.text_252') },
  109. {
  110. validator: (rule, value, _callback) => {
  111. const arr = value.split(' ')
  112. if (arr && arr.length > 0) {
  113. if (arr[0] !== 'HOSTNAME') {
  114. return _callback(this.$t('compute.text_253'))
  115. }
  116. for (let i = 1; i < arr.length; i++) {
  117. const _itemArr = arr[i].split('=')
  118. if (_itemArr.length !== 2) {
  119. return _callback(this.$t('compute.text_253'))
  120. }
  121. }
  122. }
  123. return _callback()
  124. },
  125. },
  126. ],
  127. },
  128. ],
  129. playbook: [
  130. 'playbook',
  131. {
  132. validateFirst: true,
  133. initialValue: moduleStr,
  134. rules: [
  135. { required: true, message: this.$t('compute.text_254') },
  136. {
  137. validator: (rule, value, _callback) => {
  138. const modeItems = value.replace(/[\r\n]/g, '<br/>').split('<br/>')
  139. if (modeItems && modeItems.length > 0) {
  140. for (let i = 0; i < modeItems.length; i++) {
  141. const items = modeItems[i].split(' ')
  142. const [name, ...values] = items
  143. if (this.modNames.indexOf(name) === -1) {
  144. return _callback(this.$t('compute.text_255'))
  145. }
  146. if (!values || values.length === 0) {
  147. return _callback(this.$t('compute.text_255'))
  148. }
  149. for (let j = 0; j < values.length; j++) {
  150. const arr = values[j].split('=')
  151. if (arr.length !== 2) {
  152. return _callback(this.$t('compute.text_255'))
  153. }
  154. }
  155. }
  156. }
  157. return _callback()
  158. },
  159. },
  160. ],
  161. },
  162. ],
  163. start: [
  164. 'start',
  165. {
  166. initialValue: start === undefined ? true : start,
  167. },
  168. ],
  169. hour: [
  170. 'hour',
  171. {
  172. initialValue: hour || 24,
  173. },
  174. ],
  175. }
  176. },
  177. },
  178. provide () {
  179. return {
  180. form: this.form,
  181. }
  182. },
  183. created () {
  184. this.manager = new this.$Manager('devtool_templates')
  185. const { id } = this.$route.query
  186. this.id = this.$route.query.id
  187. if (id) {
  188. this.queryInfo(id)
  189. }
  190. },
  191. methods: {
  192. handleCodeInput (key, value) {
  193. this.form.setFieldsValue({
  194. [key]: value,
  195. }, () => {
  196. this.form.validateFields([key])
  197. })
  198. },
  199. validateForm () {
  200. return new Promise((resolve, reject) => {
  201. this.form.validateFields((err, values) => {
  202. if (err || document.querySelector('.ant-form .error-color')) {
  203. reject(err)
  204. return false
  205. }
  206. const { name, hour, start, hosts, files } = values
  207. const params = { name, hour, start, enabled: true }
  208. const playbook = {
  209. files,
  210. inventory: {
  211. hosts: [],
  212. },
  213. modules: [],
  214. }
  215. const hostItem = {
  216. vars: {},
  217. }
  218. hosts.split(' ').forEach(item => {
  219. item = item.replace("'", '')
  220. if (!item || item === '--host' || item === '\\') return false
  221. const arr = item.split('=')
  222. if (arr.length === 2) {
  223. const [key, value] = arr
  224. hostItem.vars[key] = value
  225. } else {
  226. hostItem.name = item
  227. }
  228. })
  229. playbook.inventory.hosts.push(hostItem)
  230. if (values.playbook) {
  231. const modules = []
  232. const modeItems = values.playbook.replace(/[\r\n]/g, '<br/>').split('<br/>')
  233. modeItems.forEach(item => {
  234. const _arr = []
  235. const moduleItem = {}
  236. item.split(' ').forEach(subItem => {
  237. subItem = subItem.replace("'", '')
  238. if (subItem && subItem !== '\\') {
  239. _arr.push(subItem)
  240. }
  241. })
  242. if (_arr && _arr.length > 0) {
  243. moduleItem.name = _arr.shift()
  244. moduleItem.args = _arr
  245. modules.push(moduleItem)
  246. }
  247. })
  248. playbook.modules = modules
  249. }
  250. params.playbook = playbook
  251. resolve(params)
  252. })
  253. })
  254. },
  255. handleNumBlur ({ target }) {
  256. this.form.setFieldsValue({
  257. hour: target.value || 1,
  258. })
  259. },
  260. handleCancel () {
  261. this.form.resetFields()
  262. this.$router.push('/ansibletemplate')
  263. },
  264. async handleConfirm () {
  265. try {
  266. const values = await this.validateForm()
  267. this.loading = true
  268. if (this.id) {
  269. await this.manager.update({
  270. id: this.id,
  271. data: values,
  272. })
  273. } else {
  274. await this.manager.create({
  275. data: values,
  276. })
  277. }
  278. this.$router.push('/ansibletemplate')
  279. } catch (err) {
  280. throw err
  281. } finally {
  282. this.loading = false
  283. }
  284. },
  285. async queryInfo (id) {
  286. try {
  287. const { data } = await this.manager.get({ id })
  288. this.retData = data
  289. } catch (err) {
  290. throw err
  291. }
  292. },
  293. },
  294. }
  295. </script>