CalvinKirs 4 anni fa
parent
commit
64b4715b73

+ 25 - 0
docker/kubernetes/dolphinscheduler/requirements.yaml~HEAD_0

@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+dependencies:
+- name: postgresql
+  version: 8.x.x
+  repository: https://charts.bitnami.com/bitnami
+  condition: postgresql.enabled
+- name: zookeeper
+  version: 5.x.x
+  repository: https://charts.bitnami.com/bitnami
+  condition: redis.enabled

+ 25 - 0
docker/kubernetes/dolphinscheduler/requirements.yaml~dev_0

@@ -0,0 +1,25 @@
+#
+# Licensed to the Apache Software Foundation (ASF) under one or more
+# contributor license agreements.  See the NOTICE file distributed with
+# this work for additional information regarding copyright ownership.
+# The ASF licenses this file to You under the Apache License, Version 2.0
+# (the "License"); you may not use this file except in compliance with
+# the License.  You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+dependencies:
+- name: postgresql
+  version: 8.x.x
+  repository: https://charts.bitnami.com/bitnami
+  condition: postgresql.enabled
+- name: zookeeper
+  version: 5.x.x
+  repository: https://charts.bitnami.com/bitnami
+  condition: redis.enabled

+ 5 - 5
dolphinscheduler-api/src/main/java/org/apache/dolphinscheduler/api/service/UsersService.java

@@ -131,7 +131,7 @@ public class UsersService extends BaseService {
                                           String queue,
                                           int state) throws Exception {
 
-        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> result = new HashMap<>(5);
 
         //check all user params
         String msg = this.checkUserParams(userName, userPassword, email, phone);
@@ -773,7 +773,7 @@ public class UsersService extends BaseService {
      * @return user list
      */
     public Map<String, Object> queryAllGeneralUsers(User loginUser) {
-        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> result = new HashMap<>(5);
         //only admin can operate
         if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
             return result;
@@ -794,7 +794,7 @@ public class UsersService extends BaseService {
      * @return user list
      */
     public Map<String, Object> queryUserList(User loginUser) {
-        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> result = new HashMap<>(5);
         //only admin can operate
         if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
             return result;
@@ -838,7 +838,7 @@ public class UsersService extends BaseService {
      */
     public Map<String, Object> unauthorizedUser(User loginUser, Integer alertgroupId) {
 
-        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> result = new HashMap<>(5);
         //only admin can operate
         if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
             return result;
@@ -874,7 +874,7 @@ public class UsersService extends BaseService {
      * @return authorized result code
      */
     public Map<String, Object> authorizedUser(User loginUser, Integer alertgroupId) {
-        Map<String, Object> result = new HashMap<>();
+        Map<String, Object> result = new HashMap<>(5);
         //only admin can operate
         if (check(result, !isAdmin(loginUser), Status.USER_NO_OPERATION_PERM)) {
             return result;

+ 47 - 0
dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~HEAD

@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.common.utils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * hive conf utils test
+ */
+public class HiveConfUtilsTest {
+
+    /**
+     * test is hive conf var
+     */
+    @Test
+    public void testIsHiveConfVar() {
+
+        String conf = "hive.exec.script.wrapper=123";
+        boolean hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertTrue(hiveConfVar);
+
+        conf = "hive.test.v1=v1";
+        hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertFalse(hiveConfVar);
+
+        conf = "tez.queue.name=tezQueue";
+        hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertTrue(hiveConfVar);
+
+    }
+}

+ 47 - 0
dolphinscheduler-common/src/test/java/org/apache/dolphinscheduler/common/utils/HiveConfUtilsTest.java~dev

@@ -0,0 +1,47 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.dolphinscheduler.common.utils;
+
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * hive conf utils test
+ */
+public class HiveConfUtilsTest {
+
+    /**
+     * test is hive conf var
+     */
+    @Test
+    public void testIsHiveConfVar() {
+
+        String conf = "hive.exec.script.wrapper=123";
+        boolean hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertTrue(hiveConfVar);
+
+        conf = "hive.test.v1=v1";
+        hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertFalse(hiveConfVar);
+
+        conf = "tez.queue.name=tezQueue";
+        hiveConfVar = HiveConfUtils.isHiveConfVar(conf);
+        Assert.assertTrue(hiveConfVar);
+
+    }
+}

+ 36 - 1
dolphinscheduler-ui/src/js/conf/home/pages/dag/_source/formModel/tasks/sql.vue

@@ -55,6 +55,18 @@
           </el-input>
         </div>
       </m-list-box>
+      <m-list-box>
+        <div slot="text"><strong class='requiredIcon'>*</strong>{{$t('Recipient')}}</div>
+        <div slot="content">
+          <m-email ref="refEmail" v-model="receivers" :disabled="isDetails" :repeat-data="receiversCc"></m-email>
+        </div>
+      </m-list-box>
+      <m-list-box>
+        <div slot="text">{{$t('Cc')}}</div>
+        <div slot="content">
+          <m-email ref="refCc" v-model="receiversCc" :disabled="isDetails" :repeat-data="receivers"></m-email>
+        </div>
+      </m-list-box>
     </template>
     <m-list-box v-show="type === 'HIVE'">
       <div slot="text">{{$t('SQL Parameter')}}</div>
@@ -143,6 +155,7 @@
   import mLocalParams from './_source/localParams'
   import mStatementList from './_source/statementList'
   import disabledState from '@/module/mixin/disabledState'
+  import mEmail from '@/conf/home/pages/projects/pages/definition/pages/list/_source/email'
   import codemirror from '@/conf/home/pages/resource/pages/file/pages/_source/codemirror'
 
   let editor
@@ -265,6 +278,10 @@
         if (this.sqlType === 0 && !this.$refs.refEmail._manualEmail()) {
           return false
         }
+        // receiversCc Subcomponent verification
+        if (this.sqlType === 0 && !this.$refs.refCc._manualEmail()) {
+          return false
+        }
         // udfs Subcomponent verification Verification only if the data type is HIVE
         if (this.type === 'HIVE') {
           if (!this.$refs.refUdfs._verifUdfs()) {
@@ -349,6 +366,19 @@
 
         return editor
       },
+      _getReceiver () {
+        let param = {}
+        let current = this.router.history.current
+        if (current.name === 'projects-definition-details') {
+          param.processDefinitionId = current.params.id
+        } else {
+          param.processInstanceId = current.params.id
+        }
+        this.store.dispatch('dag/getReceiver', param).then(res => {
+          this.receivers = res.receivers && res.receivers.split(',') || []
+          this.receiversCc = res.receiversCc && res.receiversCc.split(',') || []
+        })
+      },
       _cacheParams () {
         this.$emit('on-cache-params', {
           type: this.type,
@@ -389,6 +419,8 @@
         }
         if (val !== 0) {
           this.title = ''
+          this.receivers = []
+          this.receiversCc = []
         }
       },
       // Listening data source
@@ -423,10 +455,13 @@
         this.preStatements = o.params.preStatements || []
         this.postStatements = o.params.postStatements || []
         this.title = o.params.title || ''
+        this.receivers = o.params.receivers && o.params.receivers.split(',') || []
+        this.receiversCc = o.params.receiversCc && o.params.receiversCc.split(',') || []
       }
       // read tasks from cache
       if (!_.some(this.store.state.dag.cacheTasks, { id: this.createNodeId }) &&
         this.router.history.current.name !== 'definition-create') {
+        this._getReceiver()
       }
     },
     mounted () {
@@ -469,6 +504,6 @@
         }
       }
     },
-    components: { mListBox, mDatasource, mLocalParams, mUdfs, mSqlType, mStatementList, mScriptBox }
+    components: { mListBox, mDatasource, mLocalParams, mUdfs, mSqlType, mStatementList, mEmail, mScriptBox }
   }
 </script>

+ 23 - 4
dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/list.vue

@@ -177,6 +177,8 @@
         timingDialog: false,
         timingData: {
           item: {},
+          receiversD: [],
+          receiversCcD: [],
           type: ''
         },
         relatedItemsDialog: false,
@@ -189,7 +191,7 @@
       pageSize: Number
     },
     methods: {
-      ...mapActions('dag', ['editProcessState', 'getStartCheck', 'deleteDefinition', 'batchDeleteDefinition', 'exportDefinition', 'getProcessDefinitionVersionsPage', 'copyProcess', 'switchProcessDefinitionVersion', 'deleteProcessDefinitionVersion', 'moveProcess']),
+      ...mapActions('dag', ['editProcessState', 'getStartCheck', 'getReceiver', 'deleteDefinition', 'batchDeleteDefinition', 'exportDefinition', 'getProcessDefinitionVersionsPage', 'copyProcess', 'switchProcessDefinitionVersion', 'deleteProcessDefinitionVersion', 'moveProcess']),
       ...mapActions('security', ['getWorkerGroupsAll']),
 
       selectable (row, index) {
@@ -224,13 +226,30 @@
       closeStart () {
         this.startDialog = false
       },
+      /**
+       * get emial
+       */
+      _getReceiver (id) {
+        return new Promise((resolve, reject) => {
+          this.getReceiver({ processDefinitionId: id }).then(res => {
+            resolve({
+              receivers: res.receivers && res.receivers.split(',') || [],
+              receiversCc: res.receiversCc && res.receiversCc.split(',') || []
+            })
+          })
+        })
+      },
       /**
        * timing
        */
       _timing (item) {
-        this.timingData.item = item
-        this.timingData.type = 'timing'
-        this.timingDialog = true
+        this._getReceiver(item.id).then(res => {
+          this.timingData.item = item
+          this.timingData.receiversD = res.receivers
+          this.timingData.receiversCcD = res.receiversCc
+          this.timingData.type = 'timing'
+          this.timingDialog = true
+        })
       },
       onUpdateTiming () {
         this._onUpdate()

+ 26 - 1
dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/pages/list/_source/timing.vue

@@ -136,6 +136,22 @@
         </el-select>
       </div>
     </div>
+    <div class="clearfix list">
+      <div class="text">
+        {{$t('Recipient')}}
+      </div>
+      <div class="cont" style="width: 680px;">
+        <m-email v-model="receivers" :repeat-data="receiversCc"></m-email>
+      </div>
+    </div>
+    <div class="clearfix list">
+      <div class="text">
+        {{$t('Cc')}}
+      </div>
+      <div class="cont" style="width: 680px;">
+        <m-email v-model="receiversCc" :repeat-data="receivers"></m-email>
+      </div>
+    </div>
     <div class="submit">
       <el-button type="text" size="small" @click="close()"> {{$t('Cancel')}} </el-button>
       <el-button type="primary" size="small" round :loading="spinnerLoading" @click="ok()">{{spinnerLoading ? 'Loading...' : (timingData.item.crontab ? $t('Edit') : $t('Create'))}} </el-button>
@@ -143,7 +159,9 @@
   </div>
 </template>
 <script>
+  import _ from 'lodash'
   import i18n from '@/module/i18n'
+  import mEmail from './email.vue'
   import store from '@/conf/home/store'
   import { warningTypeList } from './util'
   import { vCrontab } from '@/module/components/crontab/index'
@@ -166,6 +184,8 @@
         scheduleTime: '',
         crontab: '0 0 * * * ? *',
         cronPopover: false,
+        receivers: [],
+        receiversCc: [],
         i18n: i18n.globalScope.LOCALE,
         processInstancePriority: 'MEDIUM',
         workerGroup: '',
@@ -209,6 +229,8 @@
             warningType: this.warningType,
             processInstancePriority: this.processInstancePriority,
             warningGroupId: this.warningGroupId === '' ? 0 : this.warningGroupId,
+            receivers: this.receivers.join(',') || '',
+            receiversCc: this.receiversCc.join(',') || '',
             workerGroup: this.workerGroup
           }
           let msg = ''
@@ -315,6 +337,8 @@
         this.crontab = '0 0 * * * ? *'
         this.scheduleTime = times
       }
+      this.receivers = _.cloneDeep(this.timingData.receiversD)
+      this.receiversCc = _.cloneDeep(this.timingData.receiversCcD)
     },
     mounted () {
       let item = this.timingData.item
@@ -327,6 +351,7 @@
         this.processInstancePriority = item.processInstancePriority
         this._getNotifyGroupList().then(() => {
           this.$nextTick(() => {
+            // let list = _.filter(this.notifyGroupList, v => v.id === item.warningGroupId)
             this.warningGroupId = item.warningGroupId
           })
         }).catch(() => { this.warningGroupId = '' })
@@ -338,7 +363,7 @@
         }).catch(() => { this.warningGroupId = '' })
       }
     },
-    components: { vCrontab, mPriority, mWorkerGroups }
+    components: { vCrontab, mEmail, mPriority, mWorkerGroups }
   }
 </script>
 

+ 23 - 4
dolphinscheduler-ui/src/js/conf/home/pages/projects/pages/definition/timing/_source/list.vue

@@ -124,14 +124,16 @@
         list: [],
         timingDialog: false,
         timingData: {
-          item: {}
+          item: {},
+          receiversD: [],
+          receiversCcD: []
         }
       }
     },
     props: {
     },
     methods: {
-      ...mapActions('dag', ['getScheduleList', 'scheduleOffline', 'scheduleOnline', 'deleteTiming']),
+      ...mapActions('dag', ['getScheduleList', 'scheduleOffline', 'scheduleOnline', 'getReceiver', 'deleteTiming']),
       /**
        * delete
        */
@@ -226,12 +228,29 @@
           this.$message.error(e.msg || '')
         })
       },
+      /**
+       * get email
+       */
+      _getReceiver (id) {
+        return new Promise((resolve, reject) => {
+          this.getReceiver({ processDefinitionId: id }).then(res => {
+            resolve({
+              receivers: res.receivers && res.receivers.split(',') || [],
+              receiversCc: res.receiversCc && res.receiversCc.split(',') || []
+            })
+          })
+        })
+      },
       /**
        * timing
        */
       _editTiming (item) {
-        this.timingData.item = item
-        this.timingDialog = true
+        this._getReceiver(item.processDefinitionId).then(res => {
+          this.timingData.item = item
+          this.timingData.receiversD = res.receivers
+          this.timingData.receiversCcD = res.receiversCc
+          this.timingDialog = true
+        })
       },
       onUpdateTiming () {
         this.pageNo = 1

+ 56 - 3
dolphinscheduler-ui/src/js/conf/home/pages/security/pages/warningGroups/_source/list.vue

@@ -38,6 +38,9 @@
         </el-table-column>
         <el-table-column :label="$t('Operation')" width="130">
           <template slot-scope="scope">
+            <el-tooltip :content="$t('Managing Users')" placement="top">
+              <el-button type="primary" size="mini" icon="el-icon-user" @click="_mangeUser(scope.row, scope.$index)" circle></el-button>
+            </el-tooltip>
             <el-tooltip :content="$t('Edit')" placement="top">
               <span><el-button type="primary" size="mini" icon="el-icon-edit-outline" @click="_edit(scope.row)" circle></el-button></span>
             </el-tooltip>
@@ -57,17 +60,33 @@
         </el-table-column>
       </el-table>
     </div>
+    <el-dialog
+      :visible.sync="transferDialog"
+      width="auto">
+      <m-transfer :transferData="transferData" @onUpdate="onUpdate" @close="close"></m-transfer>
+    </el-dialog>
   </div>
 </template>
 <script>
+  import _ from 'lodash'
+  import i18n from '@/module/i18n'
   import { mapActions } from 'vuex'
+  import mTransfer from '@/module/components/transfer/transfer'
 
   export default {
     name: 'user-list',
     data () {
       return {
         list: [],
-        item: {}
+        transferDialog: false,
+        item: {},
+        transferData: {
+          sourceListPrs: [],
+          targetListPrs: [],
+          type: {
+            name: `${i18n.$t('Managing Users')}`
+          }
+        }
       }
     },
     props: {
@@ -76,7 +95,7 @@
       pageSize: Number
     },
     methods: {
-      ...mapActions('security', ['deleteAlertgrou', 'grantAuthorization']),
+      ...mapActions('security', ['deleteAlertgrou', 'getAuthList', 'grantAuthorization']),
       _delete (item, i) {
         this.deleteAlertgrou({
           id: item.id
@@ -90,6 +109,40 @@
       _edit (item) {
         this.$emit('on-edit', item)
       },
+      _mangeUser (item, i) {
+        this.getAuthList({
+          id: item.id,
+          type: 'user',
+          category: 'users'
+        }).then(data => {
+          let sourceListPrs = _.map(data[0], v => {
+            return {
+              id: v.id,
+              name: v.userName
+            }
+          })
+          let targetListPrs = _.map(data[1], v => {
+            return {
+              id: v.id,
+              name: v.userName
+            }
+          })
+          this.item = item
+          this.transferData.sourceListPrs = sourceListPrs
+          this.transferData.targetListPrs = targetListPrs
+          this.transferDialog = true
+        })
+      },
+      onUpdate (userIds) {
+        this._grantAuthorization('alert-group/grant-user', {
+          userIds: userIds,
+          alertgroupId: this.item.id
+        })
+        this.transferDialog = false
+      },
+      close () {
+        this.transferDialog = false
+      },
 
       _grantAuthorization (api, param) {
         this.grantAuthorization({
@@ -115,6 +168,6 @@
     },
     mounted () {
     },
-    components: {}
+    components: { mTransfer }
   }
 </script>