From 2cfea7ef0807323c3b5f1e770a044998cf4d050e Mon Sep 17 00:00:00 2001 From: pycook Date: Fri, 8 Nov 2019 15:26:22 +0800 Subject: [PATCH 1/4] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit docker 一键安装说明补充 --- README.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index cf7a796..6ce40f9 100644 --- a/README.md +++ b/README.md @@ -56,9 +56,11 @@ cp api/settings.py.example api/settings.py - 浏览器打开: [http://127.0.0.1:8000](http://127.0.0.1:8000) - 如果是非本机访问, 要修改**ui/.env**里**VUE_APP_API_BASE_URL**里的IP地址为后端服务的ip地址 -docker运行 +docker 一键构建和运行 ---- -进入主目录 +- 进入主目录(首次镜像的构建需要**10分钟**左右,视网络情况而定) ``` docker-compose up -d ``` + +- 浏览器打开: [http://localhost](http://localhost) From ca0dd976268159802f2301fc9c492bbaec0bcd67 Mon Sep 17 00:00:00 2001 From: pycook Date: Sun, 10 Nov 2019 19:06:38 +0800 Subject: [PATCH 2/4] Docker to production --- Pipfile | 2 +- README.md | 2 +- api/Dockerfile | 1 - docker-compose.yml | 40 ++++++++++-------------------------- docs/nginx.cmdb.conf.example | 14 +++++++++++-- docs/requirements.txt | 4 ++-- ui/Dockerfile | 15 +++++++++----- 7 files changed, 37 insertions(+), 41 deletions(-) diff --git a/Pipfile b/Pipfile index 7459fd8..43b1257 100644 --- a/Pipfile +++ b/Pipfile @@ -19,7 +19,7 @@ redis = "==3.2.1" Flask-Migrate = "==2.5.2" # Deployment gevent = "==1.4.0" -gunicorn = ">=19.1.1" +gunicorn = "==19.1.1" supervisor = "==4.0.3" # Auth Flask-Login = "==0.4.1" diff --git a/README.md b/README.md index 6ce40f9..2c680bd 100644 --- a/README.md +++ b/README.md @@ -63,4 +63,4 @@ docker 一键构建和运行 docker-compose up -d ``` -- 浏览器打开: [http://localhost](http://localhost) +- 浏览器打开: [http://localhost:8000](http://localhost:8000) diff --git a/api/Dockerfile b/api/Dockerfile index 7b26ed7..9f11108 100644 --- a/api/Dockerfile +++ b/api/Dockerfile @@ -15,4 +15,3 @@ RUN yum install -y epel-release && yum clean all\ && pip install --no-cache-dir -r docs/requirements.txt CMD ["bash", "-c", "cp api/settings.py.example api/settings.py && sed -i 's#{user}:{password}@127.0.0.1:3306/{db}#:@127.0.0.1:3306/cmdb#g' api/settings.py && flask run"] - diff --git a/docker-compose.yml b/docker-compose.yml index a3817be..2ac8c46 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,24 +1,6 @@ version: '3.4' services: - cmdb-ui: - build: - context: ./ui - dockerfile: Dockerfile - image: cmdb-ui:0.1 - container_name: cmdb-ui - command: ["sh", "-c", "sed -i 's#http://127.0.0.1:5000##g' .env && yarn run serve"] - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:5000"] - interval: 5s - timeout: 5s - retries: 100 - start_period: 10s - depends_on: - - cmdb-api - networks: - - new - cmdb-api: build: context: . @@ -67,32 +49,32 @@ services: aliases: - redis - cmdb-proxy: - image: nginx:latest - container_name: cmdb-proxy + cmdb-ui: + build: + context: ./ui + dockerfile: Dockerfile + image: cmdb-ui:0.1 + container_name: cmdb-ui depends_on: - cmdb-api - - cmdb-ui - volumes: - - "$PWD/conf.d:/etc/nginx/conf.d" environment: CMDB_API_HOST: cmdb-api:5000 - CMDB_UI_HOST: cmdb-ui:8000 NGINX_PORT: 80 volumes: + - "$PWD/conf.d:/etc/nginx/conf.d" - ./docs/nginx.cmdb.conf.example:/etc/nginx/conf.d/nginx.cmdb.conf.example - command: + command: - /bin/bash - -c - | - envsubst '$$CMDB_API_HOST $$CMDB_UI_HOST $$NGINX_PORT' < /etc/nginx/conf.d/nginx.cmdb.conf.example > /etc/nginx/conf.d/cmdb.conf + envsubst '$$CMDB_API_HOST $$NGINX_PORT' < /etc/nginx/conf.d/nginx.cmdb.conf.example > /etc/nginx/conf.d/cmdb.conf rm -f /etc/nginx/conf.d/default.conf + curl http://cmdb-api:5000/api/v0.1/ci/flush nginx -g 'daemon off;' - curl http://localhost/api/v0.1/ci/flush networks: - new ports: - - "80:80" + - "8000:80" volumes: db-data: diff --git a/docs/nginx.cmdb.conf.example b/docs/nginx.cmdb.conf.example index ca5b246..cba57a5 100644 --- a/docs/nginx.cmdb.conf.example +++ b/docs/nginx.cmdb.conf.example @@ -25,9 +25,12 @@ server { application/xml application/rss+xml image/svg+xml; + + root /etc/nginx/html; location / { - proxy_pass http://${CMDB_UI_HOST}; - proxy_set_header Host $host; + root /etc/nginx/html; + index index.html; + try_files $uri $uri/ /index.html; } location /api { proxy_pass http://${CMDB_API_HOST}; @@ -41,4 +44,11 @@ server { proxy_set_header Upgrade $http_upgrade; proxy_set_header Connection "upgrade"; } + location ~* \.(css|js)$ { + access_log off; + add_header Pragma public; + add_header Cache-Control "public, max-age=7776000"; + #add_header Cache-Control "public,no-cache, max-age=0"; + add_header X-Asset "yes"; + } } diff --git a/docs/requirements.txt b/docs/requirements.txt index a3d813d..af6ef72 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -11,10 +11,10 @@ SQLAlchemy ==1.3.5 PyMySQL ==0.9.3 redis ==3.2.1 # Migrations -Flask-Migrate ==2.5.2 +Flask-Migrate == 2.5.2 # Deployment gevent ==1.4.0 -gunicorn>=19.1.1 +gunicorn == 19.1.1 supervisor ==4.0.3 # Auth Flask-Login ==0.4.1 diff --git a/ui/Dockerfile b/ui/Dockerfile index d8ce926..4701c4e 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,13 +1,18 @@ -FROM alpine:3.9 +FROM alpine:3.9 as builder LABEL description="cmdb-ui" -RUN mkdir -p /data/apps/cmdb-ui/logs - COPY . /data/apps/cmdb-ui WORKDIR /data/apps/cmdb-ui -RUN apk add yarn && yarn install +RUN apk add yarn && yarn install && sed -i 's#http://127.0.0.1:5000##g' .env && yarn build -CMD ["sh", "-c", "yarn run serve"] + +FROM nginx:latest + +RUN apt-get update && apt-get install -y curl && apt-get clean + +RUN mkdir /etc/nginx/html + +COPY --from=builder /data/apps/cmdb-ui/dist /etc/nginx/html/ From 08c96039e93c9292b8a4aa80bd81ae302bf3c455 Mon Sep 17 00:00:00 2001 From: pycook Date: Sun, 10 Nov 2019 19:10:23 +0800 Subject: [PATCH 3/4] gunicorn==19.5.0 --- Pipfile | 2 +- docs/requirements.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Pipfile b/Pipfile index 43b1257..182432c 100644 --- a/Pipfile +++ b/Pipfile @@ -19,7 +19,7 @@ redis = "==3.2.1" Flask-Migrate = "==2.5.2" # Deployment gevent = "==1.4.0" -gunicorn = "==19.1.1" +gunicorn = "==19.5.0" supervisor = "==4.0.3" # Auth Flask-Login = "==0.4.1" diff --git a/docs/requirements.txt b/docs/requirements.txt index af6ef72..9ed3509 100644 --- a/docs/requirements.txt +++ b/docs/requirements.txt @@ -14,7 +14,7 @@ redis ==3.2.1 Flask-Migrate == 2.5.2 # Deployment gevent ==1.4.0 -gunicorn == 19.1.1 +gunicorn == 19.5.0 supervisor ==4.0.3 # Auth Flask-Login ==0.4.1 From 58ad9d3f05461d750af8cadd15bb5c878a48e4a4 Mon Sep 17 00:00:00 2001 From: pycook Date: Mon, 11 Nov 2019 00:25:22 +0800 Subject: [PATCH 4/4] vue lint --- api/lib/cmdb/const.py | 7 +++- api/lib/cmdb/value.py | 2 + docker-compose.yml | 1 - ui/Dockerfile | 4 +- ui/src/api/index.js | 2 +- ui/src/api/login.js | 11 +++--- ui/src/config/defaultSettings.js | 2 +- ui/src/config/router.config.js | 4 +- ui/src/permission.js | 8 ++-- ui/src/views/cmdb/ci/index.vue | 38 +++++++++---------- .../cmdb/ci/modules/CreateInstanceForm.vue | 2 +- ui/src/views/user/Login.vue | 2 +- 12 files changed, 42 insertions(+), 41 deletions(-) diff --git a/api/lib/cmdb/const.py b/api/lib/cmdb/const.py index ffeabae..d7e0b39 100644 --- a/api/lib/cmdb/const.py +++ b/api/lib/cmdb/const.py @@ -1,5 +1,8 @@ # -*- coding:utf-8 -*- + +from __future__ import unicode_literals + import datetime import six @@ -37,8 +40,8 @@ type_map = { 'deserialize': { Attribute.INT: string2int, Attribute.FLOAT: float, - Attribute.TEXT: escape, - Attribute.TIME: escape, + Attribute.TEXT: lambda x: escape(x).encode('utf-8').decode('utf-8'), + Attribute.TIME: lambda x: escape(x).encode('utf-8').decode('utf-8'), Attribute.DATETIME: str2datetime, Attribute.DATE: str2datetime, }, diff --git a/api/lib/cmdb/value.py b/api/lib/cmdb/value.py index c320644..a9eb4fe 100644 --- a/api/lib/cmdb/value.py +++ b/api/lib/cmdb/value.py @@ -1,6 +1,8 @@ # -*- coding:utf-8 -*- +from __future__ import unicode_literals + import markupsafe from flask import abort diff --git a/docker-compose.yml b/docker-compose.yml index 2ac8c46..dadc603 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,7 +61,6 @@ services: CMDB_API_HOST: cmdb-api:5000 NGINX_PORT: 80 volumes: - - "$PWD/conf.d:/etc/nginx/conf.d" - ./docs/nginx.cmdb.conf.example:/etc/nginx/conf.d/nginx.cmdb.conf.example command: - /bin/bash diff --git a/ui/Dockerfile b/ui/Dockerfile index 4701c4e..86900f3 100644 --- a/ui/Dockerfile +++ b/ui/Dockerfile @@ -1,4 +1,4 @@ -FROM alpine:3.9 as builder +FROM node:alpine as builder LABEL description="cmdb-ui" @@ -6,7 +6,7 @@ COPY . /data/apps/cmdb-ui WORKDIR /data/apps/cmdb-ui -RUN apk add yarn && yarn install && sed -i 's#http://127.0.0.1:5000##g' .env && yarn build +RUN sed -i 's#http://127.0.0.1:5000##g' .env && yarn install && yarn build FROM nginx:latest diff --git a/ui/src/api/index.js b/ui/src/api/index.js index e422d8f..8ea0a5b 100644 --- a/ui/src/api/index.js +++ b/ui/src/api/index.js @@ -1,7 +1,7 @@ import config from '@/config/defaultSettings' const api = { - Login: config.useSSO ? '/api/sso/login' : '/login', + Login: config.useSSO ? '/api/sso/login' : '/login', Logout: config.useSSO ? '/api/sso/logout' : '/logout', ForgePassword: '/auth/forge-password', Register: '/auth/register', diff --git a/ui/src/api/login.js b/ui/src/api/login.js index 0bb542a..215950b 100644 --- a/ui/src/api/login.js +++ b/ui/src/api/login.js @@ -12,7 +12,7 @@ import config from '@/config/defaultSettings' * @param parameter * @returns {*} */ -export function login(parameter) { +export function login (parameter) { return axios({ url: api.Login, method: 'post', @@ -20,7 +20,7 @@ export function login(parameter) { }) } -export function getSmsCaptcha(parameter) { +export function getSmsCaptcha (parameter) { return axios({ url: api.SendSms, method: 'post', @@ -28,7 +28,7 @@ export function getSmsCaptcha(parameter) { }) } -export function getInfo() { +export function getInfo () { return axios({ url: api.UserInfo, method: 'get', @@ -38,7 +38,7 @@ export function getInfo() { }) } -export function logout() { +export function logout () { console.log('logout........') if (config.useSSO) { window.location.replace(api.Logout) @@ -51,14 +51,13 @@ export function logout() { } }) } - } /** * get user 2step code open? * @param parameter {*} */ -export function get2step(parameter) { +export function get2step (parameter) { return axios({ url: api.twoStepCode, method: 'post', diff --git a/ui/src/config/defaultSettings.js b/ui/src/config/defaultSettings.js index e617518..a7136e2 100644 --- a/ui/src/config/defaultSettings.js +++ b/ui/src/config/defaultSettings.js @@ -14,7 +14,7 @@ */ export default { - useSSO: false, + useSSO: false, primaryColor: '#1890ff', // primary color of ant design navTheme: 'dark', // theme for nav menu layout: 'sidemenu', // nav menu position: sidemenu or topmenu diff --git a/ui/src/config/router.config.js b/ui/src/config/router.config.js index a9f1ddd..28c94dd 100644 --- a/ui/src/config/router.config.js +++ b/ui/src/config/router.config.js @@ -1,7 +1,7 @@ // eslint-disable-next-line import store from '@/store' -import { UserLayout, BasicLayout, RouteView, PageView } from '@/layouts' +import { UserLayout, BasicLayout, RouteView } from '@/layouts' import { getPreference } from '@/api/cmdb/preference' const cmdbRouter = [ @@ -68,7 +68,7 @@ const cmdbRouter = [ } ] -function copyArray(arr) { +function copyArray (arr) { return arr.map((e) => { if (typeof e === 'object') { return Object.assign({}, e) diff --git a/ui/src/permission.js b/ui/src/permission.js index 8f11232..5dea6e6 100644 --- a/ui/src/permission.js +++ b/ui/src/permission.js @@ -7,7 +7,7 @@ import 'nprogress/nprogress.css' // progress bar style import notification from 'ant-design-vue/es/notification' import { setDocumentTitle, domTitle } from '@/utils/domUtil' import config from '@/config/defaultSettings' -import { ACCESS_TOKEN } from './store/mutation-types'; +import { ACCESS_TOKEN } from './store/mutation-types' NProgress.configure({ showSpinner: false }) // NProgress Configuration @@ -44,15 +44,13 @@ router.beforeEach((to, from, next) => { store.dispatch('Logout') }, 3000) }) - } else if (to.path === '/user/login' && !config.useSSO && store.getters.roles.length !== 0) { next({ path: '/' }) NProgress.done() - } else if (!config.useSSO && !Vue.ls.get(ACCESS_TOKEN) && to.path !== "/user/login") { + } else if (!config.useSSO && !Vue.ls.get(ACCESS_TOKEN) && to.path !== '/user/login') { next({ path: '/user/login', query: { redirect: to.fullPath } }) NProgress.done() - } - else { + } else { next() } }) diff --git a/ui/src/views/cmdb/ci/index.vue b/ui/src/views/cmdb/ci/index.vue index 5200568..678f033 100644 --- a/ui/src/views/cmdb/ci/index.vue +++ b/ui/src/views/cmdb/ci/index.vue @@ -107,7 +107,7 @@ export default { CreateInstanceForm, CiDetail }, - data() { + data () { return { loading: false, loadTip: '', @@ -185,25 +185,25 @@ export default { }, optionAlertShow: false, watch: { - '$route.path': function(newPath, oldPath) { + '$route.path': function (newPath, oldPath) { this.reload() } } } }, - created() { + created () { this.tableOption() this.loadColumns() }, watch: { - '$route.path': function(newPath, oldPath) { + '$route.path': function (newPath, oldPath) { this.reload() } }, inject: ['reload'], methods: { - setColumnWidth() { + setColumnWidth () { let rows = [] try { rows = document.querySelector('.ant-table-body').childNodes[0].childNodes[2].childNodes[0].childNodes @@ -225,7 +225,7 @@ export default { document.querySelector('.ant-table-fixed-right').offsetWidth this.scrollY = window.innerHeight - this.$refs.table.$el.offsetTop - 300 }, - tableOption() { + tableOption () { if (!this.optionAlertShow) { this.options = { alert: { @@ -258,7 +258,7 @@ export default { } }, - loadColumns() { + loadColumns () { getSubscribeAttributes(this.$router.currentRoute.meta.typeId).then(res => { const prefAttrList = res.attributes this.preferenceAttrList = prefAttrList @@ -294,16 +294,16 @@ export default { }) }, - onSelectChange(selectedRowKeys, selectedRows) { + onSelectChange (selectedRowKeys, selectedRows) { this.selectedRowKeys = selectedRowKeys this.selectedRows = selectedRows }, - refreshTable(bool = false) { + refreshTable (bool = false) { this.$refs.table.refresh(bool) }, - onCellChange(key, dataIndex, event, oldValue) { + onCellChange (key, dataIndex, event, oldValue) { const value = event[0] const payload = {} payload[dataIndex] = value @@ -317,14 +317,14 @@ export default { }) }) }, - async batchDownload() { + async batchDownload () { this.loading = true this.loadTip = '正在下载 ...' const promises = this.selectedRowKeys.map(ciId => { return searchCI(`q=_id:${ciId}`).then(res => { - let ciMap = {} + const ciMap = {} Object.keys(res.result[0]).forEach(k => { - if (!["ci_type", "_id", "ci_type_alias", "_type"].includes(k)) { + if (!['ci_type', '_id', 'ci_type_alias', '_type'].includes(k)) { ciMap[k] = res.result[0][k] } }) @@ -337,12 +337,12 @@ export default { return results }, - batchUpdate(values) { + batchUpdate (values) { const that = this this.$confirm({ title: '警告', content: '确认要批量修改吗 ?', - onOk() { + onOk () { that.loading = true that.loadTip = '正在批量修改 ...' const payload = {} @@ -379,12 +379,12 @@ export default { } }) }, - batchDelete() { + batchDelete () { const that = this this.$confirm({ title: '警告', content: '真的要删除吗 ?', - onOk() { + onOk () { that.loading = true that.loadTip = '正在删除 ...' const promises = that.selectedRowKeys.map(ciId => { @@ -412,12 +412,12 @@ export default { } }) }, - deleteCI(record) { + deleteCI (record) { const that = this this.$confirm({ title: '警告', content: '真的要删除吗 ?', - onOk() { + onOk () { deleteCI(record.key) .then(res => { that.$refs.table.refresh(true) diff --git a/ui/src/views/cmdb/ci/modules/CreateInstanceForm.vue b/ui/src/views/cmdb/ci/modules/CreateInstanceForm.vue index 9976526..5d148c2 100644 --- a/ui/src/views/cmdb/ci/modules/CreateInstanceForm.vue +++ b/ui/src/views/cmdb/ci/modules/CreateInstanceForm.vue @@ -130,7 +130,7 @@ export default { this.form.validateFields((err, values) => { Object.keys(values).forEach(k => { if (typeof values[k] === 'object') { - values[k] = values[k].format("YYYY-MM-DD HH:mm:ss") + values[k] = values[k].format('YYYY-MM-DD HH:mm:ss') } }) if (!err) { diff --git a/ui/src/views/user/Login.vue b/ui/src/views/user/Login.vue index 501b679..c9545c2 100644 --- a/ui/src/views/user/Login.vue +++ b/ui/src/views/user/Login.vue @@ -139,7 +139,7 @@ export default { } }) }, - + loginSuccess (res) { this.$router.push({ path: this.$route.query.redirect }) // 延迟 1 秒显示欢迎信息