You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@ambari.apache.org by yu...@apache.org on 2016/08/09 20:15:05 UTC
[12/12] ambari git commit: AMBARI-17213. Create ambari workflow
designer contrib view. (Venkat Ranganathan via yusaku)
AMBARI-17213. Create ambari workflow designer contrib view. (Venkat Ranganathan via yusaku)
Project: http://git-wip-us.apache.org/repos/asf/ambari/repo
Commit: http://git-wip-us.apache.org/repos/asf/ambari/commit/c7742e7f
Tree: http://git-wip-us.apache.org/repos/asf/ambari/tree/c7742e7f
Diff: http://git-wip-us.apache.org/repos/asf/ambari/diff/c7742e7f
Branch: refs/heads/trunk
Commit: c7742e7f1e4435bd9d9395a3dce3b36a4bf21896
Parents: 2ae4e07
Author: Yusaku Sako <yu...@hortonworks.com>
Authored: Tue Aug 9 13:14:43 2016 -0700
Committer: Yusaku Sako <yu...@hortonworks.com>
Committed: Tue Aug 9 13:14:43 2016 -0700
----------------------------------------------------------------------
contrib/views/pom.xml | 4 +
contrib/views/wfmanager/pom.xml | 304 ++++
.../views/wfmanager/src/assembly/assembly.xml | 26 +
.../apache/oozie/ambari/view/FileServices.java | 61 +
.../ambari/view/OozieProxyImpersonator.java | 569 ++++++++
.../src/main/resources/WEB-INF/web.xml | 22 +
.../wfmanager/src/main/resources/ui/README.md | 117 ++
.../wfmanager/src/main/resources/ui/app/app.js | 39 +
.../app/components/action-credential-config.js | 39 +
.../ui/app/components/action-version-select.js | 26 +
.../ui/app/components/archive-config.js | 41 +
.../resources/ui/app/components/arg-config.js | 45 +
.../ui/app/components/bundle-job-details.js | 32 +
.../ui/app/components/coord-job-details.js | 32 +
.../ui/app/components/credentials-config.js | 189 +++
.../ui/app/components/decision-add-branch.js | 87 ++
.../ui/app/components/decision-config.js | 50 +
.../ui/app/components/designer-errors.js | 21 +
.../ui/app/components/distcp-action.js | 63 +
.../resources/ui/app/components/email-action.js | 66 +
.../resources/ui/app/components/field-error.js | 27 +
.../resources/ui/app/components/file-config.js | 60 +
.../resources/ui/app/components/file-upload.js | 48 +
.../ui/app/components/flow-designer.js | 643 +++++++++
.../resources/ui/app/components/fs-action.js | 102 ++
.../ui/app/components/global-config.js | 70 +
.../resources/ui/app/components/hdfs-browser.js | 114 ++
.../ui/app/components/header-logo-user-bar.js | 19 +
.../resources/ui/app/components/help-icon.js | 22 +
.../resources/ui/app/components/hive-action.js | 104 ++
.../resources/ui/app/components/hive2-action.js | 109 ++
.../resources/ui/app/components/java-action.js | 101 ++
.../resources/ui/app/components/jdbc-url.js | 21 +
.../resources/ui/app/components/job-details.js | 141 ++
.../main/resources/ui/app/components/job-log.js | 44 +
.../main/resources/ui/app/components/job-row.js | 87 ++
.../ui/app/components/jobxml-config.js | 38 +
.../ui/app/components/map-red-action.js | 88 ++
.../ui/app/components/name-value-config.js | 48 +
.../ui/app/components/named-properties.js | 32 +
.../resources/ui/app/components/pass-word.js | 21 +
.../resources/ui/app/components/pig-action.js | 76 +
.../ui/app/components/prepare-config-fs.js | 209 +++
.../ui/app/components/prepare-config.js | 66 +
.../ui/app/components/search-create-new-bar.js | 202 +++
.../resources/ui/app/components/search-table.js | 128 ++
.../resources/ui/app/components/shell-action.js | 74 +
.../resources/ui/app/components/sla-info.js | 147 ++
.../resources/ui/app/components/spark-action.js | 119 ++
.../resources/ui/app/components/sqoop-action.js | 85 ++
.../resources/ui/app/components/ssh-action.js | 88 ++
.../resources/ui/app/components/sub-workflow.js | 58 +
.../ui/app/components/transition-config.js | 67 +
.../ui/app/components/version-settings.js | 61 +
.../ui/app/components/workflow-action-editor.js | 190 +++
.../ui/app/components/workflow-actions.js | 28 +
.../ui/app/components/workflow-config.js | 228 +++
.../ui/app/components/workflow-credentials.js | 92 ++
.../ui/app/components/workflow-job-details.js | 31 +
.../ui/app/components/workflow-node.js | 91 ++
.../ui/app/components/workflow-parameters.js | 80 ++
.../resources/ui/app/components/workflow-sla.js | 50 +
.../resources/ui/app/controllers/application.js | 21 +
.../resources/ui/app/controllers/dashboard.js | 81 ++
.../main/resources/ui/app/controllers/design.js | 26 +
.../main/resources/ui/app/controllers/job.js | 60 +
.../ui/app/domain/actionjob_hanlder.js | 411 ++++++
.../ui/app/domain/default-layout-manager.js | 50 +
.../resources/ui/app/domain/findnode-mixin.js | 103 ++
.../src/main/resources/ui/app/domain/id-gen.js | 35 +
.../resources/ui/app/domain/layout-manager1.js | 88 ++
.../resources/ui/app/domain/layout-manager2.js | 87 ++
.../resources/ui/app/domain/mapping-utils.js | 254 ++++
.../resources/ui/app/domain/node-factory.js | 120 ++
.../resources/ui/app/domain/node-handler.js | 251 ++++
.../resources/ui/app/domain/node-visitor.js | 38 +
.../src/main/resources/ui/app/domain/node.js | 212 +++
.../resources/ui/app/domain/schema-versions.js | 70 +
.../main/resources/ui/app/domain/sla-info.js | 59 +
.../main/resources/ui/app/domain/transition.js | 53 +
.../resources/ui/app/domain/workflow-context.js | 34 +
.../ui/app/domain/workflow-importer.js | 134 ++
.../ui/app/domain/workflow-xml-generator.js | 144 ++
.../main/resources/ui/app/domain/workflow.js | 266 ++++
.../ui/app/domain/workflow_xml_mapper.js | 135 ++
.../resources/ui/app/helpers/date-helper.js | 29 +
.../src/main/resources/ui/app/index.html | 77 +
.../main/resources/ui/app/initializers/init.js | 25 +
.../src/main/resources/ui/app/resolver.js | 20 +
.../src/main/resources/ui/app/router.js | 33 +
.../resources/ui/app/routes/connection-error.js | 35 +
.../main/resources/ui/app/routes/dashboard.js | 146 ++
.../src/main/resources/ui/app/routes/design.js | 25 +
.../main/resources/ui/app/routes/designtest.js | 65 +
.../src/main/resources/ui/app/routes/index.js | 24 +
.../src/main/resources/ui/app/routes/job.js | 84 ++
.../resources/ui/app/services/file-browser.js | 27 +
.../main/resources/ui/app/services/history.js | 31 +
.../ui/app/services/property-extractor.js | 61 +
.../src/main/resources/ui/app/styles/app.css | 1335 ++++++++++++++++++
.../resources/ui/app/templates/application.hbs | 21 +
.../components/action-credential-config.hbs | 33 +
.../components/action-version-select.hbs | 27 +
.../app/templates/components/archive-config.hbs | 44 +
.../ui/app/templates/components/arg-config.hbs | 49 +
.../templates/components/bundle-job-details.hbs | 132 ++
.../templates/components/coord-job-details.hbs | 188 +++
.../templates/components/credentials-config.hbs | 83 ++
.../components/decision-add-branch.hbs | 64 +
.../templates/components/decision-config.hbs | 36 +
.../templates/components/designer-errors.hbs | 37 +
.../app/templates/components/distcp-action.hbs | 70 +
.../app/templates/components/email-action.hbs | 68 +
.../ui/app/templates/components/field-error.hbs | 21 +
.../ui/app/templates/components/file-config.hbs | 57 +
.../ui/app/templates/components/file-upload.hbs | 17 +
.../app/templates/components/flow-designer.hbs | 245 ++++
.../ui/app/templates/components/fs-action.hbs | 59 +
.../app/templates/components/global-config.hbs | 68 +
.../app/templates/components/hdfs-browser.hbs | 87 ++
.../components/header-logo-user-bar.hbs | 41 +
.../ui/app/templates/components/help-icon.hbs | 22 +
.../ui/app/templates/components/hive-action.hbs | 99 ++
.../app/templates/components/hive2-action.hbs | 116 ++
.../ui/app/templates/components/java-action.hbs | 102 ++
.../ui/app/templates/components/jdbc-url.hbs | 18 +
.../ui/app/templates/components/job-details.hbs | 95 ++
.../ui/app/templates/components/job-log.hbs | 39 +
.../ui/app/templates/components/job-row.hbs | 82 ++
.../app/templates/components/jobxml-config.hbs | 18 +
.../app/templates/components/map-red-action.hbs | 69 +
.../templates/components/name-value-config.hbs | 65 +
.../templates/components/named-properties.hbs | 26 +
.../ui/app/templates/components/pass-word.hbs | 18 +
.../ui/app/templates/components/pig-action.hbs | 78 +
.../templates/components/prepare-config-fs.hbs | 418 ++++++
.../app/templates/components/prepare-config.hbs | 69 +
.../components/search-create-new-bar.hbs | 43 +
.../app/templates/components/search-table.hbs | 101 ++
.../app/templates/components/shell-action.hbs | 101 ++
.../ui/app/templates/components/sla-info.hbs | 93 ++
.../app/templates/components/spark-action.hbs | 120 ++
.../app/templates/components/sqoop-action.hbs | 84 ++
.../ui/app/templates/components/ssh-action.hbs | 70 +
.../app/templates/components/sub-workflow.hbs | 56 +
.../templates/components/transition-config.hbs | 54 +
.../templates/components/version-settings.hbs | 48 +
.../components/workflow-action-editor.hbs | 86 ++
.../templates/components/workflow-actions.hbs | 50 +
.../templates/components/workflow-config.hbs | 109 ++
.../components/workflow-credentials.hbs | 44 +
.../components/workflow-job-details.hbs | 235 +++
.../app/templates/components/workflow-node.hbs | 65 +
.../components/workflow-parameters.hbs | 43 +
.../app/templates/components/workflow-sla.hbs | 36 +
.../ui/app/templates/connection-error.hbs | 18 +
.../resources/ui/app/templates/dashboard.hbs | 40 +
.../main/resources/ui/app/templates/design.hbs | 18 +
.../resources/ui/app/templates/designtest.hbs | 49 +
.../ui/app/templates/error-template.hbs | 18 +
.../src/main/resources/ui/app/templates/job.hbs | 18 +
.../main/resources/ui/app/templates/loading.hbs | 26 +
.../main/resources/ui/app/utils/common-utils.js | 26 +
.../main/resources/ui/app/utils/constants.js | 47 +
.../main/resources/ui/app/utils/hdfsviewer.js | 29 +
.../wfmanager/src/main/resources/ui/bower.json | 27 +
.../src/main/resources/ui/config/environment.js | 74 +
.../src/main/resources/ui/ember-cli-build.js | 112 ++
.../hdfs-directory-viewer/.bowerrc | 4 +
.../hdfs-directory-viewer/.editorconfig | 34 +
.../hdfs-directory-viewer/.ember-cli | 27 +
.../hdfs-directory-viewer/.gitignore | 17 +
.../hdfs-directory-viewer/.jshintrc | 32 +
.../hdfs-directory-viewer/.npmignore | 30 +
.../hdfs-directory-viewer/.travis.yml | 50 +
.../hdfs-directory-viewer/.watchmanconfig | 21 +
.../hdfs-directory-viewer/LICENSE.md | 27 +
.../hdfs-directory-viewer/README.md | 97 ++
.../addon/components/directory-viewer.js | 196 +++
.../templates/components/directory-viewer.hbs | 17 +
.../addon/utils/viewer-config.js | 59 +
.../app/components/directory-viewer.js | 19 +
.../app/utils/viewer-config.js | 19 +
.../hdfs-directory-viewer/bower.json | 19 +
.../hdfs-directory-viewer/config/ember-try.js | 54 +
.../hdfs-directory-viewer/config/environment.js | 24 +
.../hdfs-directory-viewer/ember-cli-build.js | 36 +
.../hdfs-directory-viewer/index.js | 32 +
.../hdfs-directory-viewer/package.json | 51 +
.../hdfs-directory-viewer/testem.json | 12 +
.../hdfs-directory-viewer/tests/.jshintrc | 52 +
.../tests/dummy/app/app.js | 36 +
.../tests/dummy/app/controllers/application.js | 32 +
.../tests/dummy/app/index.html | 43 +
.../tests/dummy/app/router.js | 29 +
.../tests/dummy/app/styles/app.css | 23 +
.../tests/dummy/app/templates/application.hbs | 36 +
.../tests/dummy/app/utils/my-viewer-config.js | 35 +
.../tests/dummy/config/environment.js | 65 +
.../tests/dummy/public/crossdomain.xml | 31 +
.../tests/dummy/public/robots.txt | 3 +
.../tests/helpers/destroy-app.js | 23 +
.../tests/helpers/module-for-acceptance.js | 41 +
.../tests/helpers/resolver.js | 29 +
.../tests/helpers/start-app.js | 36 +
.../hdfs-directory-viewer/tests/index.html | 52 +
.../hdfs-directory-viewer/tests/test-helper.js | 24 +
.../src/main/resources/ui/package.json | 56 +
.../wfmanager/src/main/resources/ui/pom.xml | 214 +++
.../wfmanager/src/main/resources/ui/proxy.js | 73 +
.../main/resources/ui/public/crossdomain.xml | 32 +
.../resources/ui/public/dialog-templates.html | 1288 +++++++++++++++++
.../resources/ui/public/node-templates.html | 158 +++
.../src/main/resources/ui/public/robots.txt | 3 +
.../resources/ui/public/sampledata/workflow.xml | 73 +
.../wfmanager/src/main/resources/ui/testem.json | 12 +
.../src/main/resources/ui/tests/.jshintrc | 52 +
.../resources/ui/tests/helpers/destroy-app.js | 22 +
.../ui/tests/helpers/module-for-acceptance.js | 40 +
.../main/resources/ui/tests/helpers/resolver.js | 28 +
.../resources/ui/tests/helpers/start-app.js | 35 +
.../src/main/resources/ui/tests/index.html | 51 +
.../components/action-credential-config-test.js | 40 +
.../components/action-version-select-test.js | 40 +
.../components/archive-config-test.js | 40 +
.../integration/components/arg-config-test.js | 40 +
.../components/bundle-job-details-test.js | 40 +
.../components/coord-job-details-test.js | 40 +
.../components/credentials-config-test.js | 40 +
.../components/decision-config-test.js | 40 +
.../components/designer-errors-test.js | 40 +
.../components/distcp-action-test.js | 40 +
.../integration/components/email-action-test.js | 40 +
.../integration/components/field-error-test.js | 40 +
.../integration/components/file-config-test.js | 40 +
.../integration/components/fs-action-test.js | 40 +
.../components/global-config-test.js | 40 +
.../components/header-logo-user-bar-test.js | 34 +
.../integration/components/help-icon-test.js | 40 +
.../integration/components/hive-action-test.js | 40 +
.../integration/components/hive2-action-test.js | 40 +
.../integration/components/java-action-test.js | 40 +
.../integration/components/jdbc-url-test.js | 40 +
.../components/job-details-modal-test.js | 40 +
.../integration/components/job-details-test.js | 40 +
.../integration/components/job-log-test.js | 40 +
.../integration/components/job-row-test.js | 40 +
.../components/jobxml-config-test.js | 40 +
.../components/map-red-action-test.js | 40 +
.../components/name-value-config-test.js | 40 +
.../components/named-properties-test.js | 40 +
.../integration/components/pass-word-test.js | 40 +
.../integration/components/pig-action-test.js | 40 +
.../components/prepare-config-fs-test.js | 40 +
.../components/prepare-config-test.js | 40 +
.../components/search-create-new-bar-test.js | 43 +
.../integration/components/search-table-test.js | 37 +
.../integration/components/shell-action-test.js | 40 +
.../integration/components/sla-info-test.js | 40 +
.../integration/components/spark-action-test.js | 40 +
.../integration/components/sqoop-action-test.js | 40 +
.../integration/components/ssh-action-test.js | 40 +
.../integration/components/sub-workflow-test.js | 40 +
.../components/target-node-selector-test.js | 40 +
.../components/transition-config-test.js | 40 +
.../components/version-settings-test.js | 40 +
.../components/workflow-action-editor-test.js | 40 +
.../components/workflow-actions-test.js | 40 +
.../components/workflow-credentials-test.js | 40 +
.../components/workflow-designer-test.js | 57 +
.../components/workflow-job-details-test.js | 40 +
.../components/workflow-node-test.js | 40 +
.../components/workflow-parameters-test.js | 40 +
.../integration/components/workflow-sla-test.js | 40 +
.../src/main/resources/ui/tests/test-helper.js | 23 +
.../ui/tests/unit/controllers/dashboard-test.js | 29 +
.../ui/tests/unit/controllers/design-test.js | 29 +
.../tests/unit/controllers/job-details-test.js | 28 +
.../ui/tests/unit/helpers/date-helper-test.js | 38 +
.../ui/tests/unit/initializers/init-test.js | 39 +
.../resources/ui/tests/unit/models/jobs-test.js | 28 +
.../tests/unit/routes/connection-error-test.js | 27 +
.../ui/tests/unit/routes/dashboard-test.js | 28 +
.../ui/tests/unit/routes/design-test.js | 28 +
.../resources/ui/tests/unit/routes/job-test.js | 27 +
.../ui/tests/unit/services/file-browser-test.js | 28 +
.../ui/tests/unit/services/history-test.js | 28 +
.../unit/services/property-extractor-test.js | 126 ++
.../views/wfmanager/src/main/resources/view.xml | 132 ++
pom.xml | 3 +
290 files changed, 21748 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/pom.xml b/contrib/views/pom.xml
index d442444..2370d35 100644
--- a/contrib/views/pom.xml
+++ b/contrib/views/pom.xml
@@ -46,6 +46,7 @@
<module>zeppelin</module>
<module>hueambarimigration</module>
<module>hive-next</module>
+ <module>wfmanager</module>
</modules>
<build>
<pluginManagement>
@@ -93,8 +94,11 @@
<exclude>**/vendor/**</exclude>
<exclude>**/public/**</exclude>
<exclude>**/dist/**</exclude>
+ <exclude>**/robots.txt</exclude>
+ <exclude>**/externaladdons/**</exclude>
<exclude>**/bower_components/**</exclude>
<exclude>**/bower/**</exclude>
+ <exclude>**/.bowerrc</exclude>
<exclude>**/node/**</exclude>
<exclude>**/runner.js</exclude>
<exclude>**/assets/javascripts/**</exclude>
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/pom.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/pom.xml b/contrib/views/wfmanager/pom.xml
new file mode 100644
index 0000000..092bfe3
--- /dev/null
+++ b/contrib/views/wfmanager/pom.xml
@@ -0,0 +1,304 @@
+<!-- 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. -->
+<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xmlns="http://maven.apache.org/POM/4.0.0"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+ <artifactId>wfmanager</artifactId>
+ <groupId>org.apache.ambari.contrib.views</groupId>
+ <version>0.1.0.0-SNAPSHOT</version>
+ <name>WF Manager View</name>
+ <parent>
+ <groupId>org.apache.ambari.contrib.views</groupId>
+ <artifactId>ambari-contrib-views</artifactId>
+ <version>2.4.0.0.0</version>
+ </parent>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.apache.ambari.contrib.views</groupId>
+ <artifactId>ambari-views-utils</artifactId>
+ <version>2.4.0.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ambari</groupId>
+ <artifactId>ambari-views</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.ambari.contrib.views</groupId>
+ <artifactId>ambari-views-commons</artifactId>
+ <version>2.4.0.0.0</version>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-core</artifactId>
+ </dependency>
+ <!-- <dependency> <groupId>javax.xml.bind</groupId> <artifactId>jaxb-api</artifactId>
+ <version>2.2.2</version> </dependency> <dependency> <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId> <version>2.1.2</version> </dependency> -->
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-client</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>com.sun.jersey</groupId>
+ <artifactId>jersey-json</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.servlet</groupId>
+ <artifactId>javax.servlet-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.google.code.gson</groupId>
+ <artifactId>gson</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>commons-io</groupId>
+ <artifactId>commons-io</artifactId>
+ <version>2.4</version>
+ </dependency>
+ <dependency>
+ <groupId>org.slf4j</groupId>
+ <artifactId>slf4j-api</artifactId>
+ </dependency>
+ <dependency>
+ <groupId>javax.inject</groupId>
+ <artifactId>javax.inject</artifactId>
+ <version>1</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-common</artifactId>
+ <version>${hadoop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>tomcat</groupId>
+ <artifactId>jasper-runtime</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.hadoop</groupId>
+ <artifactId>hadoop-hdfs</artifactId>
+ <version>${hadoop.version}</version>
+ <exclusions>
+ <exclusion>
+ <groupId>tomcat</groupId>
+ <artifactId>jasper-runtime</artifactId>
+ </exclusion>
+ </exclusions>
+ </dependency>
+
+
+ </dependencies>
+ <properties>
+ <uicode.dir>../</uicode.dir>
+ <checkstyle.skip>true</checkstyle.skip>
+ <ambari.dir>${project.parent.parent.parent.basedir}</ambari.dir>
+ <ui.directory>${basedir}/src/main/resources/ui</ui.directory>
+ </properties>
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${ui.directory}</directory>
+ <followSymlinks>false</followSymlinks>
+ <includes>
+ <include>tmp/**</include>
+ <!--
+ <include>node_modules/**</include>
+ <include>bower_components/**</include>
+ -->
+ <include>node/**</include>
+ </includes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-clean-plugin</artifactId>
+ <version>2.5</version>
+ <configuration>
+ <filesets>
+ <fileset>
+ <directory>${ui.directory}</directory>
+ <followSymlinks>false</followSymlinks>
+ <includes>
+ <include>tmp/**</include>
+ <!--
+ <include>node_modules/**</include>
+ <include>bower_components/**</include>
+ -->
+ <include>node/**</include>
+ </includes>
+ </fileset>
+ </filesets>
+ </configuration>
+ </plugin>
+ <plugin>
+ <groupId>com.github.eirslett</groupId>
+ <artifactId>frontend-maven-plugin</artifactId>
+ <version>1.0</version>
+ <configuration>
+ <nodeVersion>v0.12.2</nodeVersion>
+ <npmVersion>1.4.8</npmVersion>
+ <workingDirectory>src/main/resources/ui/</workingDirectory>
+ </configuration>
+ <executions>
+ <execution>
+ <id>install node and npm</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>install-node-and-npm</goal>
+ </goals>
+ </execution>
+ <execution>
+ <id>npm install</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>npm</goal>
+ </goals>
+ <configuration>
+ <arguments>install
+ --python="${project.basedir}/../src/main/unix/ambari-python-wrap"
+ --unsafe-perm</arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <artifactId>exec-maven-plugin</artifactId>
+ <groupId>org.codehaus.mojo</groupId>
+ <version>1.3.2</version>
+ <executions>
+ <execution>
+ <id>Bower install</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <workingDirectory>${ui.directory}</workingDirectory>
+ <executable>${ui.directory}/node/${node.executable}</executable>
+ <arguments>
+ <argument>${ui.directory}/node_modules/bower/bin/bower</argument>
+ <argument>install</argument>
+ <argument>--allow-root</argument>
+ </arguments>
+ </configuration>
+ </execution>
+ <execution>
+ <id>Files build</id>
+ <phase>generate-sources</phase>
+ <goals>
+ <goal>exec</goal>
+ </goals>
+ <configuration>
+ <workingDirectory>${basedir}/src/main/resources/ui</workingDirectory>
+ <executable>node/node</executable>
+ <arguments>
+ <argument>node_modules/.bin/ember</argument>
+ <argument>build</argument>
+
+ </arguments>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.1</version>
+ <configuration>
+ <source>1.7</source>
+ <target>1.7</target>
+ </configuration>
+ </plugin>
+ <plugin>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <executions>
+ <execution>
+ <phase>generate-resources</phase>
+ <goals>
+ <goal>copy-dependencies</goal>
+ </goals>
+ <configuration>
+ <outputDirectory>${project.build.directory}/lib</outputDirectory>
+ <includeScope>runtime</includeScope>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ <resources>
+ <resource>
+ <directory>src/main/resources</directory>
+ <filtering>false</filtering>
+ <includes>
+ <include>META-INF/**/*</include>
+ <include>view.xml</include>
+ </includes>
+ </resource>
+ <resource>
+ <directory>src/main/resources/ui/dist</directory>
+ <filtering>false</filtering>
+ </resource>
+ <!-- <resource> <directory>src/main/resources/ui/</directory> <filtering>false</filtering>
+ </resource> -->
+ <resource>
+ <directory>${uicode.dir}/dist</directory>
+ <filtering>false</filtering>
+ </resource>
+ <resource>
+ <targetPath>WEB-INF/lib</targetPath>
+ <filtering>false</filtering>
+ <directory>target/lib</directory>
+ </resource>
+ </resources>
+ </build>
+ <profiles>
+ <profile>
+ <id>windows</id>
+ <activation>
+ <os>
+ <family>win</family>
+ </os>
+ </activation>
+ <properties>
+ <node.executable>node.exe</node.executable>
+ <skip.nodegyp.chmod>true</skip.nodegyp.chmod>
+ </properties>
+ </profile>
+ <profile>
+ <id>linux</id>
+ <activation>
+ <os>
+ <family>unix</family>
+ </os>
+ </activation>
+ <properties>
+ <node.executable>node</node.executable>
+ <skip.nodegyp.chmod>false</skip.nodegyp.chmod>
+ </properties>
+ </profile>
+ </profiles>
+</project>
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/assembly/assembly.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/assembly/assembly.xml b/contrib/views/wfmanager/src/assembly/assembly.xml
new file mode 100644
index 0000000..1911da1
--- /dev/null
+++ b/contrib/views/wfmanager/src/assembly/assembly.xml
@@ -0,0 +1,26 @@
+<!--
+ 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.
+-->
+<assembly
+ xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.0 http://maven.apache.org/xsd/assembly-1.1.0.xsd">
+ <containerDescriptorHandlers>
+ <containerDescriptorHandler>
+ <handlerName>metaInf-services</handlerName>
+ </containerDescriptorHandler>
+ </containerDescriptorHandlers>
+</assembly>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/FileServices.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/FileServices.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/FileServices.java
new file mode 100644
index 0000000..ab286b2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/FileServices.java
@@ -0,0 +1,61 @@
+/**
+ * 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.oozie.ambari.view;
+
+import javax.ws.rs.Path;
+
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.commons.hdfs.FileOperationService;
+import org.apache.ambari.view.commons.hdfs.UploadService;
+import org.apache.ambari.view.commons.hdfs.UserService;
+
+public class FileServices {
+
+ private ViewContext context;
+
+ public FileServices(ViewContext viewContext) {
+ this.context=viewContext;
+ }
+
+ /**
+ * @see UploadService
+ * @return service
+ */
+ @Path("/upload")
+ public UploadService upload() {
+ return new UploadService(context);
+ }
+
+ /**
+ * @see org.apache.ambari.view.commons.hdfs.FileOperationService
+ * @return service
+ */
+ @Path("/fileops")
+ public FileOperationService fileOps() {
+ return new FileOperationService(context);
+ }
+
+ /**
+ * @see org.apache.ambari.view.commons.hdfs.UserService
+ * @return service
+ */
+ @Path("/user")
+ public UserService userService() {
+ return new UserService(context);
+ }
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
new file mode 100644
index 0000000..3ed6352
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/java/org/apache/oozie/ambari/view/OozieProxyImpersonator.java
@@ -0,0 +1,569 @@
+/**
+ * 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
+ * <p>
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * <p>
+ * 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.oozie.ambari.view;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.StringReader;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+import javax.inject.Inject;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HttpMethod;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.Produces;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.WebApplicationException;
+import javax.ws.rs.core.Context;
+import javax.ws.rs.core.HttpHeaders;
+import javax.ws.rs.core.MediaType;
+import javax.ws.rs.core.MultivaluedMap;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.StreamingOutput;
+import javax.ws.rs.core.UriInfo;
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+import javax.xml.transform.OutputKeys;
+import javax.xml.transform.Transformer;
+import javax.xml.transform.TransformerException;
+import javax.xml.transform.TransformerFactory;
+import javax.xml.transform.TransformerFactoryConfigurationError;
+import javax.xml.transform.dom.DOMSource;
+import javax.xml.transform.stream.StreamResult;
+
+import org.apache.ambari.view.URLStreamProvider;
+import org.apache.ambari.view.ViewContext;
+import org.apache.ambari.view.utils.ambari.AmbariApi;
+import org.apache.ambari.view.utils.hdfs.HdfsApi;
+import org.apache.ambari.view.utils.hdfs.HdfsUtil;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.hadoop.fs.FSDataInputStream;
+import org.apache.hadoop.fs.FSDataOutputStream;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.InputSource;
+import org.xml.sax.SAXException;
+
+/**
+ * This is a class used to bridge the communication between the and the Oozie
+ * API executing inside ambari.
+ */
+public class OozieProxyImpersonator {
+
+ private static final String OOZIE_WF_APPLICATION_PATH_CONF_KEY = "oozie.wf.application.path";
+ private static final String OOZIE_WF_RERUN_FAILNODES_CONF_KEY = "oozie.wf.rerun.failnodes";
+ private static final String OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY = "oozie.use.system.libpath";
+ private static final String XML_INDENT_SPACES = "4";
+ private static final String XML_INDENT_AMT_PROP_NAME = "{http://xml.apache.org/xslt}indent-amount";
+ private ViewContext viewContext;
+ private AmbariApi ambariApi;
+ private HdfsApi _hdfsApi = null;
+
+ private static final String USER_NAME_HEADER = "user.name";
+ private static final String USER_OOZIE_SUPER = "oozie";
+ private static final String DO_AS_HEADER = "doAs";
+
+ private static final String SERVICE_URI_PROP = "oozie.service.uri";
+ private static final String DEFAULT_SERVICE_URI = "http://sandbox.hortonworks.com:11000/oozie";
+
+ private final static Logger LOGGER = LoggerFactory
+ .getLogger(OozieProxyImpersonator.class);
+
+ @Inject
+ public OozieProxyImpersonator(ViewContext viewContext) {
+ this.viewContext = viewContext;
+ this.ambariApi = new AmbariApi(viewContext);
+ LOGGER.info(String.format(
+ "OozieProxyImpersonator initialized for instance: %s",
+ viewContext.getInstanceName()));
+ }
+
+ @Path("/fileServices")
+ public FileServices fileServices() {
+ return new FileServices(viewContext);
+ }
+
+ @POST
+ @Path("/submitWorkflow")
+ @Consumes({MediaType.TEXT_PLAIN + "," + MediaType.TEXT_XML})
+ public Response submitWorkflow(String postBody, @Context HttpHeaders headers,
+ @Context UriInfo ui, @QueryParam("app.path") String appPath,
+ @DefaultValue("false") @QueryParam("overwrite") Boolean overwrite) {
+ LOGGER.info("submit workflow job called");
+ try {
+ if (StringUtils.isEmpty(appPath)) {
+ throw new RuntimeException("app path can't be empty.");
+ }
+ appPath = appPath.trim();
+ if (!overwrite) {
+ boolean fileExists = getHdfsgetApi().exists(appPath);
+ LOGGER.info("FILE exists for [" + appPath + "] returned [" + fileExists
+ + "]");
+ if (fileExists) {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", "workflow.folder.exists");
+ resp.put("message", "Workflow Folder exists");
+ return Response.status(Response.Status.BAD_REQUEST).entity(resp)
+ .build();
+ }
+ }
+ String workflowFile = null;
+ if (appPath.endsWith(".xml")) {
+ workflowFile = appPath;
+ } else {
+ workflowFile = appPath + (appPath.endsWith("/") ? "" : "/")
+ + "workflow.xml";
+ }
+ postBody = formatXml(postBody);
+ try {
+ String filePath = createWorkflowFile(postBody, workflowFile, overwrite);
+ LOGGER.info(String.format("submit workflow job done. filePath=[%s]",
+ filePath));
+ } catch (org.apache.hadoop.security.AccessControlException ace) {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", "workflow.oozie.error");
+ resp.put("message", "You dont seem to have access to folder path.");
+ return Response.status(Response.Status.BAD_REQUEST).entity(resp)
+ .build();
+ }
+
+ String response = submitWorkflowJobToOozie(headers, appPath,
+ ui.getQueryParameters());
+ if (response != null && response.trim().startsWith("{")) {
+ // dealing with oozie giving error but with 200 response.
+ return Response.status(Response.Status.OK).entity(response).build();
+ } else {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", "workflow.oozie.error");
+ resp.put("message", response);
+ return Response.status(Response.Status.BAD_REQUEST).entity(resp)
+ .build();
+ }
+ } catch (InterruptedException e) {
+ throw new RuntimeException(e);
+ } catch (Exception e) {
+ LOGGER.error("Error in submit workflow", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @GET
+ @Path("/readWorkflowXml")
+ public Response readWorkflowXxml(
+ @QueryParam("workflowXmlPath") String workflowPath) {
+ if (StringUtils.isEmpty(workflowPath)) {
+ throw new RuntimeException("workflowXmlPath can't be empty.");
+ }
+ try {
+ final FSDataInputStream is = getHdfsgetApi().open(workflowPath);
+ StreamingOutput streamer = new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream os) throws IOException,
+ WebApplicationException {
+ IOUtils.copy(is, os);
+ is.close();
+ os.close();
+ }
+ };
+ return Response.ok(streamer).status(200).build();
+ } catch (org.apache.hadoop.security.AccessControlException ace) {
+ HashMap<String, String> resp = new HashMap<String, String>();
+ resp.put("status", "workflow.oozie.error");
+ resp.put("message", "Access denied to file path");
+ return Response.status(Response.Status.FORBIDDEN).entity(resp).build();
+ } catch (IOException e) {
+ LOGGER.error("Error in read worfklow file", e);
+ throw new RuntimeException(e);
+ } catch (InterruptedException e) {
+ LOGGER.error("Error in read worfklow file", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ @GET
+ @Path("/getDag")
+ @Produces("image/png")
+ public Response submitWorkflow(@Context HttpHeaders headers,
+ @Context UriInfo ui, @QueryParam("jobid") String jobid) {
+ String imgUrl = getServiceUri() + "/v2/job/" + jobid + "?show=graph";
+ Map<String, String> newHeaders = getHeaders(headers);
+ final InputStream is = readFromOozie(headers, imgUrl, HttpMethod.GET, null,
+ newHeaders);
+ StreamingOutput streamer = new StreamingOutput() {
+
+ @Override
+ public void write(OutputStream os) throws IOException,
+ WebApplicationException {
+ IOUtils.copy(is, os);
+ is.close();
+ os.close();
+ }
+
+ };
+ return Response.ok(streamer).status(200).build();
+ }
+
+ @GET
+ @Path("/{path: .*}")
+ public Response handleGet(@Context HttpHeaders headers, @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.GET, null);
+ } catch (Exception ex) {
+ LOGGER.error("Error in GET proxy", ex);
+ return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
+ .build();
+ }
+ }
+
+ @POST
+ @Path("/{path: .*}")
+ public Response handlePost(String xml, @Context HttpHeaders headers, @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.POST, xml);
+ } catch (Exception ex) {
+ LOGGER.error("Error in POST proxy", ex);
+ return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
+ .build();
+ }
+ }
+
+ @DELETE
+ @Path("/{path: .*}")
+ public Response handleDelete(@Context HttpHeaders headers, @Context UriInfo ui) {
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.POST, null);
+ } catch (Exception ex) {
+ LOGGER.error("Error in DELETE proxy", ex);
+ return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
+ .build();
+ }
+ }
+
+ @PUT
+ @Path("/{path: .*}")
+ public Response handlePut(String body, @Context HttpHeaders headers, @Context UriInfo ui) {
+
+ try {
+ String serviceURI = buildURI(ui);
+ return consumeService(headers, serviceURI, HttpMethod.PUT, body);
+ } catch (Exception ex) {
+ LOGGER.error("Error in PUT proxy", ex);
+ return Response.status(Response.Status.BAD_REQUEST).entity(ex.toString())
+ .build();
+ }
+ }
+
+ private String submitWorkflowJobToOozie(HttpHeaders headers, String filePath,
+ MultivaluedMap<String, String> queryParams) {
+ String nameNode = "hdfs://" + viewContext.getCluster().getConfigurationValue("hdfs-site", "dfs.namenode.rpc-address");
+
+ if (!queryParams.containsKey("config.nameNode")) {
+ ArrayList<String> nameNodes = new ArrayList<String>();
+ LOGGER.info("Namenode===" + nameNode);
+ nameNodes.add(nameNode);
+ queryParams.put("config.nameNode", nameNodes);
+ }
+
+ HashMap<String, String> workflowConigs = new HashMap<String, String>();
+ if (queryParams.containsKey("resourceManager")
+ && "useDefault".equals(queryParams.getFirst("resourceManager"))) {
+ String jobTrackerNode = viewContext.getCluster().getConfigurationValue(
+ "yarn-site", "yarn.resourcemanager.address");
+ LOGGER.info("jobTrackerNode===" + jobTrackerNode);
+ workflowConigs.put("resourceManager", jobTrackerNode);
+ workflowConigs.put("jobTracker", jobTrackerNode);
+ }
+ if (queryParams != null) {
+ for (Map.Entry<String, List<String>> entry : queryParams.entrySet()) {
+ if (entry.getKey().startsWith("config.")) {
+ if (entry.getValue() != null && entry.getValue().size() > 0) {
+ workflowConigs.put(entry.getKey().substring(7), entry.getValue()
+ .get(0));
+ }
+ }
+ }
+ }
+
+ if (queryParams.containsKey("oozieconfig.useSystemLibPath")) {
+ String useSystemLibPath = queryParams
+ .getFirst("oozieconfig.useSystemLibPath");
+ workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY, useSystemLibPath);
+ } else {
+ workflowConigs.put(OOZIE_USE_SYSTEM_LIBPATH_CONF_KEY, "true");
+ }
+ if (queryParams.containsKey("oozieconfig.rerunOnFailure")) {
+ String rerunFailnodes = queryParams
+ .getFirst("oozieconfig.rerunOnFailure");
+ workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY, rerunFailnodes);
+ } else {
+ workflowConigs.put(OOZIE_WF_RERUN_FAILNODES_CONF_KEY, "true");
+ }
+
+ workflowConigs.put("user.name", viewContext.getUsername());
+ workflowConigs.put(OOZIE_WF_APPLICATION_PATH_CONF_KEY, nameNode + filePath);
+ String configXMl = generateConigXml(workflowConigs);
+ LOGGER.info("Config xml==" + configXMl);
+ HashMap<String, String> customHeaders = new HashMap<String, String>();
+ customHeaders.put("Content-Type", "application/xml;charset=UTF-8");
+ Response serviceResponse = consumeService(headers, getServiceUri()
+ + "/v2/jobs", HttpMethod.POST, configXMl, customHeaders);
+
+ LOGGER
+ .info("REsp from oozie status entity==" + serviceResponse.getEntity());
+ if (serviceResponse.getEntity() instanceof String) {
+ return (String) serviceResponse.getEntity();
+ } else {
+ return "success";
+ }
+
+ }
+
+ private String createWorkflowFile(String postBody, String workflowFile, boolean overwrite) throws IOException, InterruptedException {
+ FSDataOutputStream fsOut = getHdfsgetApi().create(workflowFile, overwrite);
+ fsOut.write(postBody.getBytes());
+ fsOut.close();
+ return workflowFile;
+ }
+
+ private String buildURI(UriInfo ui) {
+ String uiURI = ui.getAbsolutePath().getPath();
+ int index = uiURI.indexOf("proxy/") + 5;
+ uiURI = uiURI.substring(index);
+ String serviceURI = getServiceUri();
+ serviceURI += uiURI;
+
+ MultivaluedMap<String, String> parameters = ui.getQueryParameters();
+ StringBuilder urlBuilder = new StringBuilder(serviceURI);
+ boolean firstEntry = true;
+ for (Map.Entry<String, List<String>> entry : parameters.entrySet()) {
+ if ("user.name".equals(entry.getKey())) {
+ ArrayList<String> vals = new ArrayList<String>();
+ vals.add(viewContext.getUsername());
+ entry.setValue(vals);
+ }
+ if (firstEntry) {
+ urlBuilder.append("?");
+ } else {
+ urlBuilder.append("&");
+ }
+ boolean firstVal = true;
+ for (String val : entry.getValue()) {
+ urlBuilder.append(firstVal ? "" : "&").append(entry.getKey())
+ .append("=").append(val);
+ firstVal = false;
+ }
+ firstEntry = false;
+ }
+ return urlBuilder.toString();
+ }
+
+ private String getServiceUri() {
+ String serviceURI = viewContext.getProperties().get(SERVICE_URI_PROP) != null ? viewContext
+ .getProperties().get(SERVICE_URI_PROP) : DEFAULT_SERVICE_URI;
+ return serviceURI;
+ }
+
+ public Response consumeService(HttpHeaders headers, String urlToRead,
+ String method, String body, Map<String, String> customHeaders) {
+ Response response = null;
+ InputStream stream = readFromOozie(headers, urlToRead, method, body,
+ customHeaders);
+ String stringResponse = null;
+ try {
+ stringResponse = IOUtils.toString(stream);
+ } catch (IOException e) {
+ LOGGER.error("Error while converting stream to string", e);
+ throw new RuntimeException(e);
+ }
+ if (stringResponse.contains(Response.Status.BAD_REQUEST.name())) {
+ response = Response.status(Response.Status.BAD_REQUEST)
+ .entity(stringResponse).type(MediaType.TEXT_PLAIN).build();
+ } else {
+ response = Response.status(Response.Status.OK).entity(stringResponse)
+ .type(deduceType(stringResponse)).build();
+ }
+ return response;
+ }
+
+ private InputStream readFromOozie(HttpHeaders headers, String urlToRead,
+ String method, String body, Map<String, String> customHeaders) {
+ URLStreamProvider streamProvider = viewContext.getURLStreamProvider();
+ Map<String, String> newHeaders = getHeaders(headers);
+ newHeaders.put(USER_NAME_HEADER, USER_OOZIE_SUPER);
+
+ newHeaders.put(DO_AS_HEADER, viewContext.getUsername());
+ newHeaders.put("Accept", MediaType.APPLICATION_JSON);
+ if (customHeaders != null) {
+ newHeaders.putAll(customHeaders);
+ }
+ LOGGER.info(String.format("Proxy request for url: [%s] %s", method,
+ urlToRead));
+ boolean securityEnabled = isSecurityEnabled();
+ LOGGER.debug(String.format("IS security enabled:[%b]", securityEnabled));
+ InputStream stream = null;
+ try {
+ if (securityEnabled) {
+ stream = streamProvider.readAsCurrent(urlToRead, method, body, newHeaders);
+
+ } else {
+ stream = streamProvider.readFrom(urlToRead, method, body, newHeaders);
+ }
+ } catch (IOException e) {
+ LOGGER.error("error talking to oozie", e);
+ throw new RuntimeException(e);
+ }
+ return stream;
+ }
+
+ public Response consumeService(HttpHeaders headers, String urlToRead,
+ String method, String body) throws Exception {
+ return consumeService(headers, urlToRead, method, body, null);
+ }
+
+ public Map<String, String> getHeaders(HttpHeaders headers) {
+ MultivaluedMap<String, String> requestHeaders = headers.getRequestHeaders();
+ Set<Entry<String, List<String>>> headerEntrySet = requestHeaders.entrySet();
+ HashMap<String, String> headersMap = new HashMap<String, String>();
+ for (Entry<String, List<String>> headerEntry : headerEntrySet) {
+ String key = headerEntry.getKey();
+ List<String> values = headerEntry.getValue();
+ headersMap.put(key, strJoin(values, ","));
+ }
+ return headersMap;
+ }
+
+ public String strJoin(List<String> strings, String separator) {
+ StringBuilder stringBuilder = new StringBuilder();
+ for (int i = 0, il = strings.size(); i < il; i++) {
+ if (i > 0) {
+ stringBuilder.append(separator);
+ }
+ stringBuilder.append(strings.get(i));
+ }
+ return stringBuilder.toString();
+ }
+
+ private MediaType deduceType(String stringResponse) {
+ if (stringResponse.startsWith("{")) {
+ return MediaType.APPLICATION_JSON_TYPE;
+ } else if (stringResponse.startsWith("<")) {
+ return MediaType.TEXT_XML_TYPE;
+ } else {
+ return MediaType.APPLICATION_JSON_TYPE;
+ }
+ }
+
+ private HdfsApi getHdfsgetApi() {
+ if (_hdfsApi == null) {
+ try {
+ _hdfsApi = HdfsUtil.connectToHDFSApi(viewContext);
+ } catch (Exception ex) {
+ LOGGER.error("Error in getting HDFS Api", ex);
+ throw new RuntimeException("HdfsApi connection failed. Check \"webhdfs.url\" property", ex);
+ }
+ }
+ return _hdfsApi;
+ }
+
+ private String generateConigXml(Map<String, String> map) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ DocumentBuilder db;
+ try {
+ db = dbf.newDocumentBuilder();
+ Document doc = db.newDocument();
+ Element configElement = doc.createElement("configuration");
+ doc.appendChild(configElement);
+ for (Map.Entry<String, String> entry : map.entrySet()) {
+ Element propElement = doc.createElement("property");
+ configElement.appendChild(propElement);
+ Element nameElem = doc.createElement("name");
+ nameElem.setTextContent(entry.getKey());
+ Element valueElem = doc.createElement("value");
+ valueElem.setTextContent(entry.getValue());
+ propElement.appendChild(nameElem);
+ propElement.appendChild(valueElem);
+ }
+ DOMSource domSource = new DOMSource(doc);
+ StringWriter writer = new StringWriter();
+ StreamResult result = new StreamResult(writer);
+ TransformerFactory tf = TransformerFactory.newInstance();
+ Transformer transformer = tf.newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer
+ .setOutputProperty(XML_INDENT_AMT_PROP_NAME, XML_INDENT_SPACES);
+ transformer.transform(domSource, result);
+ return writer.toString();
+ } catch (ParserConfigurationException | TransformerException e) {
+ LOGGER.error("error in generating config xml", e);
+ throw new RuntimeException(e);
+ }
+
+ }
+
+ private String formatXml(String xml) {
+ DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
+ try {
+ DocumentBuilder db = dbf.newDocumentBuilder();
+ StreamResult result = new StreamResult(new StringWriter());
+ Document document = db.parse(new InputSource(new StringReader(xml)));
+ Transformer transformer = TransformerFactory.newInstance()
+ .newTransformer();
+ transformer.setOutputProperty(OutputKeys.INDENT, "yes");
+ transformer
+ .setOutputProperty(XML_INDENT_AMT_PROP_NAME, XML_INDENT_SPACES);
+ DOMSource source = new DOMSource(document);
+ transformer.transform(source, result);
+ return result.getWriter().toString();
+ } catch (ParserConfigurationException | SAXException | IOException
+ | TransformerFactoryConfigurationError | TransformerException e) {
+ LOGGER.error("Error in formatting xml", e);
+ throw new RuntimeException(e);
+ }
+ }
+
+ private boolean isSecurityEnabled() {
+ boolean securityEnabled = Boolean.valueOf(getHadoopConfigs().get(
+ "security_enabled"));
+ return securityEnabled;
+ }
+
+ private Map<String, String> getHadoopConfigs() {
+ return viewContext.getInstanceData();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/WEB-INF/web.xml b/contrib/views/wfmanager/src/main/resources/WEB-INF/web.xml
new file mode 100644
index 0000000..aad4c20
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/WEB-INF/web.xml
@@ -0,0 +1,22 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+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. Kerberos, LDAP, Custom. Binary/Htt
+-->
+<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
+ version="3.1">
+</web-app>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/README.md
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/README.md b/contrib/views/wfmanager/src/main/resources/ui/README.md
new file mode 100644
index 0000000..dcac346
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/README.md
@@ -0,0 +1,117 @@
+<!---
+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](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.
+-->
+# Workflow Manager-UI
+
+This is the repository for the Workflow Manager web UI . This has Dashboard where Oozie jobs can be monitored, run, stip etc..It also has a desiger which allows
+you to develop a oozie work flow in a graphical interface.
+
+Technologies Used.
+it uses Ember as underline JS framework.
+JsPlbumb for designer.
+Dagre for layout in designer.
+bootstrap for css.
+
+## Prerequisites
+
+If you are not building using maven, you will need the following things properly installed on your computer. Maven build would download and setup the prerequisites for you.
+
+* [Git](http://git-scm.com/)
+* [Node.js](http://nodejs.org/) (with NPM)
+* [Bower](http://bower.io/)
+* [Ember CLI](http://www.ember-cli.com/)
+* [PhantomJS](http://phantomjs.org/)
+
+## Installation
+
+* `git clone <repository-url>` this repository
+* change into the new directory
+* To build the deployable war file, run `mvn clean package`
+
+in the main directory, just do mvn install.
+
+For doing local development
+==============================
+Go to folder under wfmanager\src\main\resources\ui.
+* `npm install`
+* `bower install`
+
+
+## Running / Development using node and ember-cli
+
+In development mode (and in non Ambari View mode), you might want to connect the UI with already running remote/local oozie server. To do so you can run the proxy so that UI can route the requests through it.
+
+* `node proxy.js <local-port> <remote-oozie-host> <remote-oozie-port>`
+
+By default local port is `11002`, default oozie host is `localhost` with default port as `11000`
+
+* `node proxy.js`
+* `Proxy on: localhost:11002 -> localhost:11000`
+
+If you want to use different local port (other than `11002`) then update the API_URL in `environment.js` accordingly.
+
+* `ember server`
+* Visit your app at [http://localhost:4300](http://localhost:4300).
+
+### Building and Running through Maven
+
+* `mvn clean package` (Build web ui and puts into /dist)
+* `mvn test -Pproxy` (start proxy for the oozie API)
+* In another console tab `mvn test -Pserver` (does ember server)
+* Wheather you use maven or ember, your app would be accessible at [http://localhost:4300](http://localhost:4300).
+
+### Setup and Run sample Oozie workflows, bundles and coordinators
+
+* Get and start the latest Hortonworks Sandbox (if you haven't yet)
+* From the host machine, `ssh root@127.0.0.1 -p 2222` to get into Sandbox
+* Switch to a `guest` user using `su - guest`
+* Inside the sandbox, `tar -xvf /usr/hdp/current/oozie-client/doc/oozie-examples.tar.gz`
+* Correct job.properties `find ./examples/apps/ -iname "job.properties" | xargs sed -i 's/localhost/sandbox.hortonworks.com/g'`
+* Set hadoop user: `export HADOOP_USER_NAME=guest`
+* Move the examples into HDFS: `hdfs dfs -put ./examples/ /user/guest/examples`
+* Set oozie user `export OOZIE_USER_NAME=guest`
+* Submit and run all the jobs: `find ./examples/apps/ -iname "job.properties" | xargs -i oozie job -oozie http://localhost:11000/oozie -config {} -run`
+
+### Oozie Ambari View
+
+This UI can be built and deployed as an Ambari view. Below are the steps to build the Ambari view.
+
+* `cd oozie-ambari-view`
+* `mvn clean package` - This builds `target/oozie-ambari-view-0.0.0.1-SNAPSHOT.jar`
+* `cp target/oozie-ambari-view-0.0.0.1-SNAPSHOT.jar </var/lib/ambari-server/resources/views/>`
+* restart your ambari server and Oozie Amabri View would be available in Ambari
+
+### Code Generators
+
+Make use of the many generators for code, try `ember help generate` for more details
+
+### Running Tests
+
+* `ember test`
+* `ember test --server`
+
+## Further Reading / Useful Links
+
+* [ember.js](http://emberjs.com/)
+* [ember-cli](http://www.ember-cli.com/)
+* Development Browser Extensions
+ * [ember inspector for chrome](https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi)
+ * [ember inspector for firefox](https://addons.mozilla.org/en-US/firefox/addon/ember-inspector/)
+
+How the code is organized.
+There are 2 main components- Dashboard and Designer.
+1) Designer
+
+
+2) Dashboard.
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/app.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/app.js b/contrib/views/wfmanager/src/main/resources/ui/app/app.js
new file mode 100644
index 0000000..f87a2c3
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/app.js
@@ -0,0 +1,39 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+import Resolver from './resolver';
+import loadInitializers from 'ember-load-initializers';
+import config from './config/environment';
+
+let App;
+
+Ember.MODEL_FACTORY_INJECTIONS = true;
+
+App = Ember.Application.extend({
+ modulePrefix: config.modulePrefix,
+ podModulePrefix: config.podModulePrefix,
+ Resolver
+});
+Ember.$.ajaxSetup({
+ beforeSend: function(xhr) {
+ xhr.setRequestHeader("X-XSRF-HEADER", Math.round(Math.random()*100000));
+ }
+});
+loadInitializers(App, config.modulePrefix);
+
+export default App;
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/action-credential-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/action-credential-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/action-credential-config.js
new file mode 100644
index 0000000..1c20c86
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/action-credential-config.js
@@ -0,0 +1,39 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ elementsInserted : function(){
+ if(this.get('actionCredentials')){
+ var credentials = this.get('actionCredentials').split(",");
+ credentials.forEach((credential)=>{
+ this.$('input[name="' + credential +'"]').prop('checked','checked');
+ });
+ }
+ }.on('didInsertElement'),
+ actions : {
+ onClick (name){
+ var checked = this.$('.cbox:checked');
+ var selectedCredentials = [];
+ checked.each((index, checkbox)=>{
+ selectedCredentials.push(this.$(checkbox).prop('name'));
+ });
+ this.set('actionCredentials', selectedCredentials.join());
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/action-version-select.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/action-version-select.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/action-version-select.js
new file mode 100644
index 0000000..944c3be
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/action-version-select.js
@@ -0,0 +1,26 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions: {
+ versionChanged (version){
+ this.sendAction('versionChanged',this.get('actionVersion.name'), version);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
new file mode 100644
index 0000000..d53b459
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/archive-config.js
@@ -0,0 +1,41 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+import EmberValidations from 'ember-validations';
+
+export default Ember.Component.extend(EmberValidations,{
+ fileBrowser : Ember.inject.service('file-browser'),
+ initialize : function(){
+ this.on('fileSelected',function(fileName){
+ this.set(this.get('filePathModel'), fileName);
+ }.bind(this));
+ }.on('init'),
+ actions : {
+ addArchive () {
+ this.get('archives').unshiftObjects(this.get('archive'));
+ this.set('archive', "");
+ },
+ deleteArchive(index){
+ this.get('archives').removeAt(index);
+ },
+ openFileBrowser(model){
+ this.set('filePathModel', model);
+ this.sendAction("openFileBrowser", model, this);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/arg-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/arg-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/arg-config.js
new file mode 100644
index 0000000..9943a55
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/arg-config.js
@@ -0,0 +1,45 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ multivalued : true,
+ initialize : function(){
+ this.sendAction('register', this, this);
+ this.on('bindInputPlaceholder',function () {
+ this.set('addUnboundValue', true);
+ }.bind(this));
+ }.on('init'),
+ bindInputPlaceholder : function () {
+ if(this.get('addUnboundValue') && !Ember.isBlank(this.get('arg'))){
+ this.addArg();
+ }
+ }.on('willDestroyElement'),
+ addArg (){
+ this.get('args').pushObject({value:this.get('arg')});
+ this.set('arg', "");
+ },
+ actions : {
+ addArg () {
+ this.addArg();
+ },
+ deleteArg (index) {
+ this.get('args').removeAt(index);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-job-details.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-job-details.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-job-details.js
new file mode 100644
index 0000000..ba0beb2
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/bundle-job-details.js
@@ -0,0 +1,32 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions :{
+ getJobLog (params) {
+ this.sendAction('getJobLog', params);
+ },
+ getActionDetails(action){
+ this.sendAction('getActionDetails',action);
+ },
+ showCoord(id){
+ this.sendAction('showCoord',id);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-job-details.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-job-details.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-job-details.js
new file mode 100644
index 0000000..c04c089
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/coord-job-details.js
@@ -0,0 +1,32 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+
+export default Ember.Component.extend({
+ actions :{
+ getJobLog (params) {
+ this.sendAction('getJobLog', params);
+ },
+ getCoordActionReruns(){
+ this.sendAction('getCoordActionReruns',this.get('rerunActionList'));
+ },
+ showWorkflow(id){
+ this.sendAction('showWorkflow',id);
+ }
+ }
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
new file mode 100644
index 0000000..f100808
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/credentials-config.js
@@ -0,0 +1,189 @@
+/*
+* 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.
+*/
+import Ember from 'ember';
+import EmberValidations from 'ember-validations';
+
+export default Ember.Component.extend(EmberValidations, {
+ childComponents : new Map(),
+ initialize : function(){
+ if(this.get('mode') === 'edit'){
+ this.sendAction('register', this, this);
+ }
+ this.get('childComponents').clear();
+ this.set('credentialType',Ember.A([]));
+ this.get('credentialType').pushObject({value:'',displayName:'Select'});
+ this.get('credentialType').pushObject({value:'hcat',displayName:'HCat'});
+ this.get('credentialType').pushObject({value:'hive2',displayName:'Hive2'});
+ this.get('credentialType').pushObject({value:'hbase',displayName:'HBase'});
+
+ Ember.addObserver(this, 'credential.type', this, this.credentialTypeObserver);
+
+ this.initializeCredentialDetails();
+
+ if(this.get('mode') === 'create'){
+ this.set("credential", {});
+ this.set("credential.property", Ember.A([]));
+ }
+ if(this.get('credential.type') && this.get('credential.property')){
+ this.set('staticProps', Ember.copy(this.get('credentialDetails').findBy('name',this.get('credential.type')).staticProps));
+ var configProperties = this.get('credential.property');
+ configProperties.forEach((property)=>{
+ var existingStaticProp = this.get('staticProps').findBy('name',property.name);
+ if (existingStaticProp) {
+ Ember.set(existingStaticProp,'value', property.value);
+ Ember.set(property,'static', true);
+ }
+ });
+ }
+ }.on('init'),
+ rendered : function(){
+ if(this.get('mode') === 'create'){
+ this.$('.collapse').collapse('show');
+ }else if(this.get('mode') === 'edit'){
+ this.$('.collapse').collapse('hide');
+ }
+ }.on('didInsertElement'),
+ initializeCredentialDetails : function(){
+ this.set('credentialDetails', Ember.A([]));
+ this.get('credentialDetails').pushObject({
+ name:'hcat',
+ staticProps:
+ [{name:'hcat.metastore.principal',displayName:'Hcat Metastore principal', value:'', belongsTo:'credential.property'},
+ {name:'hcat.metastore.uri',displayName:'Hcat Metastore uri', value:'', belongsTo:'credential.property'}]
+ });
+ this.get('credentialDetails').pushObject({
+ name:'hive2',
+ staticProps:
+ [{name:'hive2.jdbc.url',displayName:'Hive2 Jdbc Url', value:'', belongsTo:'credential.property'},
+ {name:'hive2.server.principal',displayName:'Hive2 Server principal', value:'', belongsTo:'credential.property'}]
+ });
+ this.get('credentialDetails').pushObject({
+ name:'hbase',
+ staticProps:
+ [{name:'hadoop.security.authentication',displayName:'Hadoop security auth', value:'', belongsTo:'credential.property'},
+ {name:'hbase.security.authentication',displayName:'Hbase security auth', value:'', belongsTo:'credential.property'},
+ {name:'hbase.master.kerberos.principal',displayName:'Hbase Master kerberos principal', value:'', belongsTo:'credential.property'},
+ {name:'hbase.regionserver.kerberos.principal',displayName:'Hbase regionserver kerberos principal', value:'', belongsTo:'credential.property'},
+ {name:'hbase.zookeeper.quorum',displayName:'Hbase zookeeper quorum', value:'', belongsTo:'credential.property'},
+ {name:'hadoop.rpc.protection',displayName:'Hadoop Rpc protection', value:'', belongsTo:'credential.property'},
+ {name:'hbase.rpc.protection',displayName:'Hbase Rpc protection', value:'', belongsTo:'credential.property'}]
+ });
+ },
+ credentialTypeObserver : function(){
+ var credentialType = this.get('credential.type');
+ if(!credentialType){
+ return;
+ }
+ this.set('staticProps', Ember.copy(this.get('credentialDetails').findBy('name',credentialType).staticProps));
+ },
+ processMultivaluedComponents(){
+ this.get('childComponents').forEach((childComponent)=>{
+ if(childComponent.get('multivalued')){
+ childComponent.trigger('bindInputPlaceholder');
+ }
+ });
+ },
+ resetForm : function(){
+ this.set('credential', {});
+ this.set('credential.property',Ember.A([]));
+ this.get('staticProps').clear();
+ this.initializeCredentialDetails();
+ },
+ validateChildrenComponents(){
+ var validationPromises = [];
+ var deferred = Ember.RSVP.defer();
+ if(this.get('childComponents').size === 0){
+ deferred.resolve(true);
+ }else{
+ this.get('childComponents').forEach((childComponent)=>{
+ if(!childComponent.validations){
+ return;
+ }
+ var validationDeferred = Ember.RSVP.defer();
+ childComponent.validate().then(()=>{
+ validationDeferred.resolve();
+ }).catch((e)=>{
+ validationDeferred.reject(e);
+ });
+ validationPromises.push(validationDeferred.promise);
+ });
+ Ember.RSVP.Promise.all(validationPromises).then(function(){
+ deferred.resolve(true);
+ }).catch(function(e){
+ deferred.reject(e);
+ });
+ }
+ return deferred;
+ },
+ validations : {
+ 'credential.name': {
+ presence: {
+ 'message' : 'Required',
+ }
+ },
+ 'credential.type': {
+ presence: {
+ 'message' : 'Required',
+ }
+ }
+ },
+ actions : {
+ register(component, context){
+ if(this.get('mode') === 'edit'){
+ this.sendAction('register', component, context);
+ }
+ this.get('childComponents').set(component, context);
+ },
+ add(){
+ var isFormValid = this.validateChildrenComponents();
+ isFormValid.promise.then(function(){
+ this.validate().then(function(){
+ var staticProps = this.get('staticProps');
+ var index = 0;
+ staticProps.forEach((property)=>{
+ var existingStaticProp = this.get('credential.property').findBy('name',property.name);
+ if (existingStaticProp) {
+ Ember.set(existingStaticProp,'value',property.value);
+ index++;
+ } else {
+ var propObj = {name : property.name, value:property.value, static:true};
+ this.get('credential.property').insertAt(index++, propObj);
+ }
+ });
+ this.processMultivaluedComponents();
+ this.sendAction('add',this.get('credential'));
+ this.resetForm();
+ }.bind(this)).catch(function(e){
+ }.bind(this));
+ }.bind(this)).catch(function (e) {
+ });
+
+ },
+ delete(name){
+ this.sendAction('delete',name);
+ },
+ togglePanel (){
+ this.$('.collapse').collapse('toggle');
+ if(this.$('.collapse').hasClass('in')){
+ this.set('isOpen', true);
+ }else{
+ this.set('isOpen', false);
+ }
+ }
+ }
+
+});
http://git-wip-us.apache.org/repos/asf/ambari/blob/c7742e7f/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
----------------------------------------------------------------------
diff --git a/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
new file mode 100644
index 0000000..84d1393
--- /dev/null
+++ b/contrib/views/wfmanager/src/main/resources/ui/app/components/decision-add-branch.js
@@ -0,0 +1,87 @@
+/*
+* 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.
+*/
+
+import Ember from 'ember';
+import {FindNodeMixin} from '../domain/findnode-mixin';
+import EmberValidations from 'ember-validations';
+
+export default Ember.Component.extend(EmberValidations, FindNodeMixin,{
+ isInsertAction: false,
+ condition:"",
+ targetNode:"",
+ newNodeType:null,
+ initialize : function(){
+ var self=this;
+
+ this.on("showBranchOptions",function(){
+ if (self.$("#selector-content").is(":visible")){
+ self.$("#selector-content").hide();
+ }else{
+ self.set("isInsertAction",false);
+ this.set("newNodeType",null);
+ this.set('descendantNodes',this.getDesendantNodes(this.get('node')));
+ self.$("#selector-content").show();
+ }
+ });
+ }.on('init'),
+ setup : function(){
+ this.sendAction('registerAddBranchAction',this);
+ }.on('didInsertElement'),
+ validations : {
+ 'condition': {
+ presence: {
+ 'if' : 'canValidate',
+ 'message' : 'Required',
+ }
+ },
+ 'targetNode': {
+ presence: {
+ 'if' : 'canValidate',
+ 'message' : 'Required',
+ }
+ }
+ },
+ actions:{
+ addNewNode(type){
+ this.set("newNodeType",type);
+ },
+ onTargetNodeChange(value){
+ var node = this.get('descendantNodes').findBy('id',value);
+ this.set('targetNode', node);
+ },
+ save(){
+ this.set('canValidate', true);
+ this.validate().then(function(){
+ this.sendAction("addDecisionBranch",{
+ sourceNode: this.get("node"),
+ condition:this.get("condition"),
+ targetNode:this.get("targetNode"),
+ newNodeType:this.get("newNodeType")
+ });
+ this.$("#selector-content").hide();
+ this.set('canValidate', false);
+ this.set('condition',"");
+ this.set('targetNode',"");
+ this.$('#target-node-select').prop('selectedIndex', 0);
+ }.bind(this)).catch(function(e){
+ }.bind(this));
+ },
+ cancel(){
+ this.$("#selector-content").hide();
+ }
+ }
+});