YARN-7129. Application Catalog for YARN applications. Contributed by Eric Yang
This commit is contained in:
parent
56f1e131ec
commit
7ee32a2eb1
|
@ -147,7 +147,13 @@
|
|||
<surefire.fork.timeout>900</surefire.fork.timeout>
|
||||
<aws-java-sdk.version>1.11.375</aws-java-sdk.version>
|
||||
<hsqldb.version>2.3.4</hsqldb.version>
|
||||
<frontend-maven-plugin.version>1.5</frontend-maven-plugin.version>
|
||||
<frontend-maven-plugin.version>1.6</frontend-maven-plugin.version>
|
||||
<maven-dependency-plugin.version>3.0.1</maven-dependency-plugin.version>
|
||||
<jasmine-maven-plugin.version>2.1</jasmine-maven-plugin.version>
|
||||
<phantomjs-maven-plugin.version>0.7</phantomjs-maven-plugin.version>
|
||||
<yuicompressor-maven-plugin.version>1.5.1</yuicompressor-maven-plugin.version>
|
||||
<maven-project-info-reports-plugin.version>2.9</maven-project-info-reports-plugin.version>
|
||||
|
||||
<!-- the version of Hadoop declared in the version resources; can be overridden
|
||||
so that Hadoop 3.x can declare itself a 2.x artifact. -->
|
||||
<declared.hadoop.version>${hadoop.version}</declared.hadoop.version>
|
||||
|
@ -161,6 +167,8 @@
|
|||
<junit.vintage.version>5.3.1</junit.vintage.version>
|
||||
<junit.platform.version>1.3.1</junit.platform.version>
|
||||
<jline.version>3.9.0</jline.version>
|
||||
<powermock.version>1.5.6</powermock.version>
|
||||
<solr.version>7.7.0</solr.version>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
@ -465,6 +473,19 @@
|
|||
<type>test-jar</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-services-api</artifactId>
|
||||
<version>${hadoop.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog-webapp</artifactId>
|
||||
<version>${hadoop.version}</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-mapreduce-client-jobclient</artifactId>
|
||||
|
@ -1651,6 +1672,31 @@
|
|||
<artifactId>hadoop-maven-plugins</artifactId>
|
||||
<version>${hadoop.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>${maven-dependency-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.alchim31.maven</groupId>
|
||||
<artifactId>yuicompressor-maven-plugin</artifactId>
|
||||
<version>${yuicompressor-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.klieber</groupId>
|
||||
<artifactId>phantomjs-maven-plugin</artifactId>
|
||||
<version>${phantomjs-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.searls</groupId>
|
||||
<artifactId>jasmine-maven-plugin</artifactId>
|
||||
<version>${jasmine-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
<version>${frontend-maven-plugin.version}</version>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
|
|
|
@ -0,0 +1,50 @@
|
|||
<!--
|
||||
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.
|
||||
-->
|
||||
# Apache Hadoop YARN Application Catalog
|
||||
|
||||
## Introduction
|
||||
|
||||
YARN Application Catalog is application catalog for
|
||||
deploying docker enabled cloud application on Hadoop.
|
||||
|
||||
check it out:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/apache/hadoop.git
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
* Firefox or Chrome
|
||||
* [npm](https://www.npmjs.org)
|
||||
* [nodejs](http://nodejs.org)
|
||||
* [JDK](http://www.oracle.com/technetwork/java/javaee/downloads/index.html)
|
||||
* [IDE](http://www.jetbrains.com/)
|
||||
* [bower](http://bower.io)
|
||||
* [PhantomJs](http://phantomjs.org) or `brew install phantomjs`
|
||||
* [Docker](http://docker.io)
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
mvn package
|
||||
```
|
||||
|
||||
When running this command a couple of things happen:
|
||||
* YARN Application Catalog web application is built
|
||||
* YARN Application Docker image is built
|
||||
|
||||
## Status of the project
|
||||
|
||||
See Apache [JIRA](http://issues.apache.org/jira/browse/HADOOP)
|
|
@ -0,0 +1,37 @@
|
|||
# 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.
|
||||
|
||||
FROM centos:7
|
||||
|
||||
RUN yum -y install tomcat lsof krb5-workstation sssd-client curl
|
||||
SHELL ["/bin/bash", "-o", "pipefail", "-c"]
|
||||
RUN mkdir -p /opt/apache/solr && \
|
||||
curl -SL http://archive.apache.org/dist/lucene/solr/7.7.0/solr-7.7.0.tgz | \
|
||||
tar -xzC /opt/apache/solr --strip 1
|
||||
COPY src/main/scripts/setup-image.sh /setup-image.sh
|
||||
COPY src/main/resources/samples.xml /tmp/samples.xml
|
||||
COPY src/main/resources/jaas.config /etc/tomcat/jaas.config.template
|
||||
COPY src/main/scripts/entrypoint.sh /usr/bin/entrypoint.sh
|
||||
COPY target/ROOT.war /var/lib/tomcat/webapps/ROOT.war
|
||||
RUN chmod 755 /setup-image.sh
|
||||
RUN chmod 755 /usr/bin/entrypoint.sh
|
||||
RUN /setup-image.sh
|
||||
|
||||
EXPOSE 8080
|
||||
EXPOSE 8983
|
||||
WORKDIR /
|
||||
|
||||
ENTRYPOINT ["/usr/bin/entrypoint.sh" ]
|
|
@ -0,0 +1,43 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
# Apache Hadoop YARN AppCatalog Docker Image
|
||||
|
||||
## Introduction
|
||||
|
||||
AppCatalog Docker image is pre-packaged docker container for Hadoop Application Catalog.
|
||||
|
||||
check it out:
|
||||
|
||||
```
|
||||
git clone https://github.com/apache/hadoop.git
|
||||
```
|
||||
|
||||
## Compile
|
||||
|
||||
```
|
||||
mvn package
|
||||
```
|
||||
|
||||
## Run
|
||||
|
||||
```
|
||||
docker run -d -p 8080:8080 -p 8983:8983 hadoop/appcatalog-docker:1.0-SNAPSHOT
|
||||
```
|
||||
|
||||
When running this command a couple of things happens:
|
||||
* Solr server will create appcatalog collection for hosting application catalog
|
||||
* Sample applications are registered in Embedded Solr
|
||||
* Tomcat will run appcatalog-webapp on port 8080
|
||||
|
||||
User can browse port 8080 to deploy application on a Hadoop cluster.
|
|
@ -0,0 +1,108 @@
|
|||
<?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.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog-docker</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>hadoop-yarn-applications-catalog</artifactId>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>YARN Application Catalog Docker Image</name>
|
||||
<url>http://maven.apache.org</url>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<type>war</type>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.rat</groupId>
|
||||
<artifactId>apache-rat-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>src/main/resources/jaas.config</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>docker</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.0.1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-dependencies</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog-webapp</artifactId>
|
||||
<version>${project.version}</version>
|
||||
<destFileName>ROOT.war</destFileName>
|
||||
<type>war</type>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}</outputDirectory>
|
||||
<overWriteReleases>false</overWriteReleases>
|
||||
<overWriteSnapshots>true</overWriteSnapshots>
|
||||
<excludeTransitive>true</excludeTransitive>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.spotify</groupId>
|
||||
<artifactId>dockerfile-maven-plugin</artifactId>
|
||||
<version>1.3.4</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>default</id>
|
||||
<goals>
|
||||
<goal>build</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<repository>apache/hadoop-yarn-applications-catalog-docker</repository>
|
||||
<tag>${project.version}</tag>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
|
@ -0,0 +1,9 @@
|
|||
com.sun.security.jgss.krb5.initiate {
|
||||
com.sun.security.auth.module.Krb5LoginModule required
|
||||
doNotPrompt=true
|
||||
principal="${PRINCIPAL}"
|
||||
useKeyTab=true
|
||||
keyTab="${KEYTAB}"
|
||||
storeKey=true
|
||||
useTicketCache=false;
|
||||
};
|
|
@ -0,0 +1,135 @@
|
|||
<?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.
|
||||
-->
|
||||
<add>
|
||||
<doc>
|
||||
<field name="id">appStore_1</field>
|
||||
<field name="type_s">AppStoreEntry</field>
|
||||
<field name="org_s">Apache</field>
|
||||
<field name="name_s">Http Server Project</field>
|
||||
<field name="desc_s">The Number One HTTP Server On The Internet</field>
|
||||
<field name="like_i">50000</field>
|
||||
<field name="download_i">100000</field>
|
||||
<field name="yarnfile_s">{
|
||||
"name": "httpd",
|
||||
"version": "1.0",
|
||||
"components" :
|
||||
[
|
||||
{
|
||||
"name": "httpd",
|
||||
"number_of_containers": 2,
|
||||
"artifact": {
|
||||
"id": "centos/httpd-24-centos7:latest",
|
||||
"type": "DOCKER"
|
||||
},
|
||||
"resource": {
|
||||
"cpus": 1,
|
||||
"memory": "256"
|
||||
},
|
||||
"configuration": {
|
||||
"env": {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_PORTS_MAPPING":"8080:8080"
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"quicklinks": {
|
||||
"Httpd UI": "http://httpd.${SERVICE_NAME}.${USER}.${DOMAIN}:8080/"
|
||||
}
|
||||
}
|
||||
</field>
|
||||
</doc>
|
||||
<doc>
|
||||
<field name="id">appStore_2</field>
|
||||
<field name="type_s">AppStoreEntry</field>
|
||||
<field name="org_s">Jenkins-ci.org</field>
|
||||
<field name="name_s">Jenkins</field>
|
||||
<field name="desc_s">The leading open source automation server</field>
|
||||
<field name="like_i">100000</field>
|
||||
<field name="download_i">1000000</field>
|
||||
<field name="yarnfile_s">{
|
||||
"name": "httpd",
|
||||
"version": "1.0",
|
||||
"components" :
|
||||
[
|
||||
{
|
||||
"name": "jenkins",
|
||||
"number_of_containers": 1,
|
||||
"artifact": {
|
||||
"id": "jenkins/jenkins:latest",
|
||||
"type": "DOCKER"
|
||||
},
|
||||
"resource": {
|
||||
"cpus": 1,
|
||||
"memory": "1024"
|
||||
},
|
||||
"run_privileged_container": true,
|
||||
"configuration": {
|
||||
"env": {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_PORTS_MAPPING":"8080:8080"
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"quicklinks": {
|
||||
"Jenkins UI": "http://jenkins.${SERVICE_NAME}.${USER}.${DOMAIN}:8080/"
|
||||
}
|
||||
}
|
||||
</field>
|
||||
</doc>
|
||||
<doc>
|
||||
<field name="id">appStore_3</field>
|
||||
<field name="type_s">AppStoreEntry</field>
|
||||
<field name="org_s">Docker</field>
|
||||
<field name="name_s">Registry</field>
|
||||
<field name="desc_s">The Docker Registry 2.0 implementation for storing and distributing Docker images.</field>
|
||||
<field name="like_i">360</field>
|
||||
<field name="download_i">1</field>
|
||||
<field name="yarnfile_s">{
|
||||
"name": "docker-registry",
|
||||
"version": "1.0",
|
||||
"components" :
|
||||
[
|
||||
{
|
||||
"name": "registry",
|
||||
"number_of_containers": 1,
|
||||
"artifact": {
|
||||
"id": "registry:latest",
|
||||
"type": "DOCKER"
|
||||
},
|
||||
"resource": {
|
||||
"cpus": 1,
|
||||
"memory": "1024"
|
||||
},
|
||||
"configuration": {
|
||||
"env": {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_PORTS_MAPPING":"5000:5000"
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
</field>
|
||||
</doc>
|
||||
</add>
|
|
@ -0,0 +1,45 @@
|
|||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
template_generator() {
|
||||
REGEX='(\$\{[a-zA-Z_][a-zA-Z_0-9]*\})'
|
||||
if [ -e "$2" ]; then
|
||||
mv -f "$2" "$2.bak"
|
||||
fi
|
||||
while IFS='' read -r line || [[ -n "$line" ]]; do
|
||||
while [[ "$line" =~ $REGEX ]] ; do
|
||||
LHS=${BASH_REMATCH[1]}
|
||||
RHS="$(eval echo "\"$LHS\"")"
|
||||
line=${line//$LHS/$RHS}
|
||||
done
|
||||
echo "$line" >> "$2"
|
||||
done < "$1"
|
||||
}
|
||||
|
||||
export JAVA_HOME=/usr/lib/jvm/jre
|
||||
export HADOOP_CONF_DIR=/etc/hadoop/conf
|
||||
/opt/apache/solr/bin/solr start -p 8983 -force
|
||||
/opt/apache/solr/bin/solr create_core -c appcatalog -force
|
||||
/opt/apache/solr/bin/post -c appcatalog /tmp/samples.xml
|
||||
if [ -d /etc/hadoop/conf ]; then
|
||||
sed -i.bak 's/shared.loader=.*$/shared.loader=\/etc\/hadoop\/conf/g' /etc/tomcat/catalina.properties
|
||||
fi
|
||||
if [ -e "$KEYTAB" ]; then
|
||||
export JAVA_OPTS="$JAVA_OPTS -Djava.security.auth.login.config=/etc/tomcat/jaas.config -Djava.security.krb5.conf=/etc/krb5.conf -Djavax.security.auth.useSubjectCredsOnly=false"
|
||||
template_generator /etc/tomcat/jaas.config.template /etc/tomcat/jaas.config
|
||||
fi
|
||||
/usr/libexec/tomcat/server start
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash
|
||||
|
||||
# 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.
|
||||
|
||||
mkdir -p /etc/hadoop
|
||||
mkdir -p /opt/apache/solr/server/logs
|
||||
chmod -R 777 /opt/apache/solr/server/logs /var/log/tomcat /var/cache/tomcat /var/lib/tomcat/webapps /opt/apache/solr/server/solr
|
||||
chmod 777 /etc/tomcat
|
|
@ -0,0 +1,3 @@
|
|||
.classpath
|
||||
.project
|
||||
/target/
|
|
@ -0,0 +1 @@
|
|||
--modules-folder target/generated-sources/vendor
|
|
@ -0,0 +1,51 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
# Apache Hadoop YARN Application Catalog
|
||||
|
||||
## Introduction
|
||||
|
||||
Hadoop YARN Application Catalog is application catalog for
|
||||
deploying docker enabled cloud application on Hadoop.
|
||||
|
||||
check it out:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/apache/hadoop.git
|
||||
```
|
||||
|
||||
## Prerequisites
|
||||
* Firefox or Chrome
|
||||
* [npm](https://www.npmjs.org)
|
||||
* [nodejs](http://nodejs.org)
|
||||
* [JDK](http://www.oracle.com/technetwork/java/javaee/downloads/index.html)
|
||||
* [IDE](http://www.jetbrains.com/)
|
||||
* [bower](http://bower.io)
|
||||
* [PhantomJs](http://phantomjs.org) or `brew install phantomjs`
|
||||
* [Application Server](https://glassfish.java.net/download.html) or `brew install glassfish`
|
||||
|
||||
## Installation
|
||||
|
||||
```bash
|
||||
mvn package
|
||||
```
|
||||
|
||||
When running this command a couple of things happen:
|
||||
* Npm and yarnpkg install will be run
|
||||
* JSLint will be run in src/main/javascript sources
|
||||
* Javascript will be minified
|
||||
* All the other standard maven phases.
|
||||
|
||||
## Status of the project
|
||||
|
||||
See Apache [JIRA](http://issues.apache.org/jira/browse/YARN)
|
|
@ -0,0 +1,20 @@
|
|||
<?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.
|
||||
-->
|
||||
<FindBugsFilter>
|
||||
|
||||
</FindBugsFilter>
|
|
@ -0,0 +1,40 @@
|
|||
{
|
||||
"name": "AppCatalog",
|
||||
"private": true,
|
||||
"version": "0.0.0",
|
||||
"description": "YARN App Catalog",
|
||||
"repository": "git://git.apache.org/hadoop.git",
|
||||
"license": "Apache 2.0",
|
||||
"dependencies": {
|
||||
"jquery": "3.3.1",
|
||||
"angular-loader": "~1.6.4",
|
||||
"angular-mocks": "~1.6.4",
|
||||
"angular-route": "~1.6.4",
|
||||
"angular": "~1.6.4",
|
||||
"bootstrap": "~3.3.7",
|
||||
"roboto-fontface": "0.10.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"http-server": "^0.6.1",
|
||||
"requirejs": "^2.1.0",
|
||||
"karma": "4.0.0",
|
||||
"karma-requirejs": "^0.2.2",
|
||||
"karma-script-launcher": "^0.1.0",
|
||||
"karma-chrome-launcher": "^0.1.4",
|
||||
"karma-firefox-launcher": "^0.1.3",
|
||||
"karma-jasmine": "^0.1.5",
|
||||
"karma-junit-reporter": "^0.2.2",
|
||||
"shelljs": "^0.2.6",
|
||||
"apidoc": "0.17.7"
|
||||
},
|
||||
"scripts": {
|
||||
"prestart": "npm install & mvn clean package",
|
||||
"start": "http-server target/app -a localhost -p 8000",
|
||||
"pretest": "npm install",
|
||||
"test": "karma start src/test/javascript/karma.conf.js",
|
||||
"test-single-run": "karma start src/test/javascript/karma.conf.js --single-run",
|
||||
"preupdate-webdriver": "npm install",
|
||||
"update-webdriver": "webdriver-manager update",
|
||||
"update-index-async": "node -e \"require('shelljs/global'); sed('-i', /\\/\\/@@NG_LOADER_START@@[\\s\\S]*\\/\\/@@NG_LOADER_END@@/, '//@@NG_LOADER_START@@\\n' + cat('src/main/webapp/vendor/angular-loader/angular-loader.min.js') + '\\n//@@NG_LOADER_END@@', 'src/main/webapp/index.html');\""
|
||||
}
|
||||
}
|
|
@ -0,0 +1,455 @@
|
|||
<?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.
|
||||
-->
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog-webapp</artifactId>
|
||||
<packaging>war</packaging>
|
||||
|
||||
<parent>
|
||||
<artifactId>hadoop-yarn-applications-catalog</artifactId>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<name>YARN Application Catalog Webapp</name>
|
||||
|
||||
<url>http://hadoop.apache.org</url>
|
||||
|
||||
<properties>
|
||||
<artifact.name>app</artifact.name>
|
||||
<endorsed.dir>${project.build.directory}/endorsed</endorsed.dir>
|
||||
<vendor.loc>target/generated-sources/vendor</vendor.loc>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
<dependency.locations.enabled>false</dependency.locations.enabled>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>io.swagger</groupId>
|
||||
<artifactId>swagger-annotations</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
<version>1.9.5</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-module-junit4</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.powermock</groupId>
|
||||
<artifactId>powermock-api-mockito</artifactId>
|
||||
<version>${powermock.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.mockito</groupId>
|
||||
<artifactId>mockito-all</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.glassfish.jersey.media</groupId>
|
||||
<artifactId>jersey-media-json-jackson</artifactId>
|
||||
<version>2.12</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.javassist</groupId>
|
||||
<artifactId>javassist</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||
<artifactId>jackson-jaxrs-base</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.sun.jersey</groupId>
|
||||
<artifactId>jersey-json</artifactId>
|
||||
<version>${jersey.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-solrj</artifactId>
|
||||
<version>${solr.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-core</artifactId>
|
||||
<version>${solr.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.solr</groupId>
|
||||
<artifactId>solr-test-framework</artifactId>
|
||||
<version>${solr.version}</version>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
</exclusion>
|
||||
<exclusion>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-io</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>jcl-over-slf4j</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.slf4j</groupId>
|
||||
<artifactId>slf4j-api</artifactId>
|
||||
<version>${slf4j.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-auth</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-common</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-services-core</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-services-api</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-core</artifactId>
|
||||
<version>${jackson2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-annotations</artifactId>
|
||||
<version>${jackson2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
<version>${jackson2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||
<artifactId>jackson-jaxrs-json-provider</artifactId>
|
||||
<version>${jackson2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.fasterxml.jackson.jaxrs</groupId>
|
||||
<artifactId>jackson-jaxrs-base</artifactId>
|
||||
<version>${jackson2.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
<build>
|
||||
<finalName>${artifact.name}</finalName>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>src/main/javascript</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
<filtering>true</filtering>
|
||||
</resource>
|
||||
</resources>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>com.github.eirslett</groupId>
|
||||
<artifactId>frontend-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install node and yarn</id>
|
||||
<goals>
|
||||
<goal>install-node-and-yarn</goal>
|
||||
</goals>
|
||||
<phase>generate-resources</phase>
|
||||
<configuration>
|
||||
<nodeVersion>v8.11.3</nodeVersion>
|
||||
<yarnVersion>v1.7.0</yarnVersion>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>yarn install</id>
|
||||
<goals>
|
||||
<goal>yarn</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.8</source>
|
||||
<target>1.8</target>
|
||||
<compilerArguments>
|
||||
<endorseddirs>${endorsed.dir}</endorseddirs>
|
||||
</compilerArguments>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<systemPropertyVariables>
|
||||
<log4j.configuration>file:${project.build.testOutputDirectory}/log4j.properties</log4j.configuration>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-war-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
<webResources>
|
||||
<resource>
|
||||
<directory>target/generated-sources</directory>
|
||||
<includes>
|
||||
<include>vendor/jquery/**</include>
|
||||
<include>vendor/angular/**</include>
|
||||
<include>vendor/angular-route/**</include>
|
||||
<include>vendor/bootstrap/**</include>
|
||||
<include>vendor/roboto-fontface/fonts/roboto/Roboto-Regular.woff</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</webResources>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>copy</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputDirectory>${endorsed.dir}</outputDirectory>
|
||||
<silent>true</silent>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>javax</groupId>
|
||||
<artifactId>javaee-endorsed-api</artifactId>
|
||||
<version>7.0</version>
|
||||
<type>jar</type>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>net.alchim31.maven</groupId>
|
||||
<artifactId>yuicompressor-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>compress-js</id>
|
||||
<phase>process-resources</phase>
|
||||
<goals>
|
||||
<!--<goal>jslint</goal>-->
|
||||
<goal>compress</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<failOnWarning>true</failOnWarning>
|
||||
<!--<outputDirectory>src/main/webapp/js</outputDirectory>-->
|
||||
<outputDirectory>target/${artifact.name}/js</outputDirectory>
|
||||
<nosuffix>true</nosuffix>
|
||||
<excludes>
|
||||
<exclude>**/js/**/*js</exclude>
|
||||
<exclude>vendor/**</exclude>
|
||||
<exclude>**/*min.css</exclude>
|
||||
<exclude>**/*min.js</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.klieber</groupId>
|
||||
<artifactId>phantomjs-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>install</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<version>2.1.1</version>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>com.github.searls</groupId>
|
||||
<artifactId>jasmine-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<goals>
|
||||
<goal>test</goal>
|
||||
<goal>bdd</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<webDriverClassName>org.openqa.selenium.phantomjs.PhantomJSDriver</webDriverClassName>
|
||||
<webDriverCapabilities>
|
||||
<capability>
|
||||
<name>phantomjs.binary.path</name>
|
||||
<value>${phantomjs.binary}</value>
|
||||
</capability>
|
||||
</webDriverCapabilities>
|
||||
<preloadSources>
|
||||
<source>${vendor.loc}/jquery/dist/jquery.js</source>
|
||||
<source>${vendor.loc}/angular/angular.min.js</source>
|
||||
<source>${vendor.loc}/angular-route/angular-route.min.js</source>
|
||||
<source>${vendor.loc}/angular-mocks/angular-mocks.js</source>
|
||||
</preloadSources>
|
||||
<jsSrcDir>src/main/javascript</jsSrcDir>
|
||||
<jsTestSrcDir>src/test/javascript</jsTestSrcDir>
|
||||
<specIncludes>
|
||||
<include>*Spec.js</include>
|
||||
</specIncludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.rat</groupId>
|
||||
<artifactId>apache-rat-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>src/main/webapp/vendor/**</exclude>
|
||||
<exclude>src/main/resources/appcatalog.properties</exclude>
|
||||
<exclude>src/main/webapp//**/*.svg</exclude>
|
||||
<exclude>src/test/javascript/karma.conf.js</exclude>
|
||||
<exclude>src/test/resources/configsets/exampleCollection/conf/params.json</exclude>
|
||||
<exclude>src/test/resources/log4j.properties</exclude>
|
||||
<exclude>src/test/resources/jaas.config</exclude>
|
||||
<exclude>.bowerrc</exclude>
|
||||
<exclude>.yarnrc</exclude>
|
||||
<exclude>bower.json</exclude>
|
||||
<exclude>package.json</exclude>
|
||||
<exclude>yarn.lock</exclude>
|
||||
<exclude>node/**</exclude>
|
||||
<exclude>node_modules/**</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-javadoc-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludePackageNames>org.apache.hadoop.yarn.appcatalog</excludePackageNames>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<!--
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>rest-docs</id>
|
||||
<activation>
|
||||
<file>
|
||||
<exists>${basedir}/node_modules/.bin/apidoc</exists>
|
||||
</file>
|
||||
</activation>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>exec-maven-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>apidocs</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>exec</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<outputFile>${project.build.directory}/apidocs.log</outputFile>
|
||||
<executable>${basedir}/node/node</executable>
|
||||
<commandlineArgs>${basedir}/node_modules/.bin/apidoc -i src/main/java -o ${project.build.directory}/site/apidocs</commandlineArgs>
|
||||
<silent>true</silent>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
-->
|
||||
|
||||
</project>
|
|
@ -0,0 +1,60 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.application;
|
||||
|
||||
import javax.ws.rs.ApplicationPath;
|
||||
import javax.ws.rs.core.Application;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.controller.AppDetailsController;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Jackson resource configuration class for Application Catalog.
|
||||
*/
|
||||
@ApplicationPath("service")
|
||||
public class AppCatalog extends Application {
|
||||
|
||||
@Override
|
||||
public Set<Class<?>> getClasses() {
|
||||
final Set<Class<?>> resources = new java.util.HashSet<>();
|
||||
// following code can be used to customize Jersey 2.0 JSON provider:
|
||||
try {
|
||||
final Class<?> jsonProvider =
|
||||
Class.forName("org.glassfish.jersey.jackson.JacksonFeature");
|
||||
// Class jsonProvider =
|
||||
// Class.forName("org.glassfish.jersey.moxy.json.MoxyJsonFeature");
|
||||
// Class jsonProvider =
|
||||
// Class.forName("org.glassfish.jersey.jettison.JettisonFeature");
|
||||
resources.add(jsonProvider);
|
||||
} catch (final ClassNotFoundException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
addRestResourceClasses(resources);
|
||||
return resources;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add your own resources here.
|
||||
*/
|
||||
private void addRestResourceClasses(final Set<Class<?>> resources) {
|
||||
resources.add(AppDetailsController.class);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,359 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.application;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.Random;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppStoreEntry;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.Application;
|
||||
import org.apache.hadoop.yarn.appcatalog.utils.RandomWord;
|
||||
import org.apache.hadoop.yarn.appcatalog.utils.WordLengthException;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrQuery;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.impl.HttpSolrClient;
|
||||
import org.apache.solr.client.solrj.response.QueryResponse;
|
||||
import org.apache.solr.client.solrj.response.UpdateResponse;
|
||||
import org.apache.solr.common.SolrDocument;
|
||||
import org.apache.solr.common.SolrInputDocument;
|
||||
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
||||
/**
|
||||
* Driver class for accessing Solr.
|
||||
*/
|
||||
public class AppCatalogSolrClient {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(AppCatalogSolrClient.class);
|
||||
private static String urlString;
|
||||
|
||||
public AppCatalogSolrClient() {
|
||||
// Locate Solr URL
|
||||
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
|
||||
InputStream input =
|
||||
classLoader.getResourceAsStream("appcatalog.properties");
|
||||
Properties properties = new Properties();
|
||||
try {
|
||||
properties.load(input);
|
||||
urlString = properties.getProperty("solr_url");
|
||||
} catch (IOException e) {
|
||||
LOG.error("Error reading appcatalog configuration: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public SolrClient getSolrClient() {
|
||||
return new HttpSolrClient.Builder(urlString).build();
|
||||
}
|
||||
|
||||
public List<AppStoreEntry> getRecommendedApps() {
|
||||
List<AppStoreEntry> apps = new ArrayList<AppStoreEntry>();
|
||||
SolrClient solr = getSolrClient();
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
query.setFilterQueries("type_s:AppStoreEntry");
|
||||
query.setRows(40);
|
||||
QueryResponse response;
|
||||
try {
|
||||
response = solr.query(query);
|
||||
Iterator<SolrDocument> list = response.getResults().listIterator();
|
||||
while (list.hasNext()) {
|
||||
SolrDocument d = list.next();
|
||||
AppStoreEntry entry = new AppStoreEntry();
|
||||
entry.setId(d.get("id").toString());
|
||||
entry.setOrg(d.get("org_s").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setDesc(d.get("desc_s").toString());
|
||||
if (d.get("icon_s")!=null) {
|
||||
entry.setIcon(d.get("icon_s").toString());
|
||||
}
|
||||
entry.setLike(Integer.valueOf(d.get("like_i").toString()));
|
||||
entry.setDownload(Integer.valueOf(d.get("download_i").toString()));
|
||||
apps.add(entry);
|
||||
}
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error getting a list of recommended applications: ", e);
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
public List<AppStoreEntry> search(String keyword) {
|
||||
List<AppStoreEntry> apps = new ArrayList<AppStoreEntry>();
|
||||
SolrClient solr = getSolrClient();
|
||||
SolrQuery query = new SolrQuery();
|
||||
if (keyword.length()==0) {
|
||||
query.setQuery("*:*");
|
||||
query.setFilterQueries("type_s:AppStoreEntry");
|
||||
} else {
|
||||
query.setQuery(keyword);
|
||||
query.setFilterQueries("type_s:AppStoreEntry");
|
||||
}
|
||||
query.setRows(40);
|
||||
QueryResponse response;
|
||||
try {
|
||||
response = solr.query(query);
|
||||
Iterator<SolrDocument> list = response.getResults().listIterator();
|
||||
while (list.hasNext()) {
|
||||
SolrDocument d = list.next();
|
||||
AppStoreEntry entry = new AppStoreEntry();
|
||||
entry.setId(d.get("id").toString());
|
||||
entry.setOrg(d.get("org_s").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setDesc(d.get("desc_s").toString());
|
||||
entry.setLike(Integer.valueOf(d.get("like_i").toString()));
|
||||
entry.setDownload(Integer.valueOf(d.get("download_i").toString()));
|
||||
apps.add(entry);
|
||||
}
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error in searching for applications: ", e);
|
||||
}
|
||||
return apps;
|
||||
}
|
||||
|
||||
public List<AppEntry> listAppEntries() {
|
||||
List<AppEntry> list = new ArrayList<AppEntry>();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
SolrClient solr = getSolrClient();
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("*:*");
|
||||
query.setFilterQueries("type_s:AppEntry");
|
||||
query.setRows(40);
|
||||
QueryResponse response;
|
||||
try {
|
||||
response = solr.query(query);
|
||||
Iterator<SolrDocument> appList = response.getResults().listIterator();
|
||||
while (appList.hasNext()) {
|
||||
SolrDocument d = appList.next();
|
||||
AppEntry entry = new AppEntry();
|
||||
entry.setId(d.get("id").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setApp(d.get("app_s").toString());
|
||||
entry.setYarnfile(mapper.readValue(d.get("yarnfile_s").toString(),
|
||||
Service.class));
|
||||
list.add(entry);
|
||||
}
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error in listing deployed applications: ", e);
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
public AppStoreEntry findAppStoreEntry(String id) {
|
||||
AppStoreEntry entry = new AppStoreEntry();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
SolrClient solr = getSolrClient();
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("id:" + id);
|
||||
query.setFilterQueries("type_s:AppStoreEntry");
|
||||
query.setRows(1);
|
||||
|
||||
QueryResponse response;
|
||||
try {
|
||||
response = solr.query(query);
|
||||
Iterator<SolrDocument> appList = response.getResults().listIterator();
|
||||
while (appList.hasNext()) {
|
||||
SolrDocument d = appList.next();
|
||||
entry.setId(d.get("id").toString());
|
||||
entry.setOrg(d.get("org_s").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setDesc(d.get("desc_s").toString());
|
||||
entry.setLike(Integer.valueOf(d.get("like_i").toString()));
|
||||
entry.setDownload(Integer.valueOf(d.get("download_i").toString()));
|
||||
Service yarnApp = mapper.readValue(d.get("yarnfile_s").toString(),
|
||||
Service.class);
|
||||
String name;
|
||||
try {
|
||||
Random r = new Random();
|
||||
int low = 3;
|
||||
int high = 10;
|
||||
int seed = r.nextInt(high-low) + low;
|
||||
int seed2 = r.nextInt(high-low) + low;
|
||||
name = RandomWord.getNewWord(seed).toLowerCase() + "-" + RandomWord
|
||||
.getNewWord(seed2).toLowerCase();
|
||||
} catch (WordLengthException e) {
|
||||
name = "c" + java.util.UUID.randomUUID().toString().substring(0, 11);
|
||||
}
|
||||
yarnApp.setName(name);
|
||||
entry.setApp(yarnApp);
|
||||
}
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error in finding deployed application: " + id, e);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
public AppEntry findAppEntry(String id) {
|
||||
AppEntry entry = new AppEntry();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
|
||||
SolrClient solr = getSolrClient();
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("id:" + id);
|
||||
query.setFilterQueries("type_s:AppEntry");
|
||||
query.setRows(1);
|
||||
|
||||
QueryResponse response;
|
||||
try {
|
||||
response = solr.query(query);
|
||||
Iterator<SolrDocument> appList = response.getResults().listIterator();
|
||||
while (appList.hasNext()) {
|
||||
SolrDocument d = appList.next();
|
||||
entry.setId(d.get("id").toString());
|
||||
entry.setApp(d.get("app_s").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setYarnfile(mapper.readValue(d.get("yarnfile_s").toString(),
|
||||
Service.class));
|
||||
}
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error in finding deployed application: " + id, e);
|
||||
}
|
||||
return entry;
|
||||
}
|
||||
|
||||
public void deployApp(String id, Service service) throws SolrServerException,
|
||||
IOException {
|
||||
long download = 0;
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
Collection<SolrInputDocument> docs = new HashSet<SolrInputDocument>();
|
||||
SolrClient solr = getSolrClient();
|
||||
// Find application information from AppStore
|
||||
SolrQuery query = new SolrQuery();
|
||||
query.setQuery("id:" + id);
|
||||
query.setFilterQueries("type_s:AppStoreEntry");
|
||||
query.setRows(1);
|
||||
QueryResponse response = solr.query(query);
|
||||
Iterator<SolrDocument> appList = response.getResults().listIterator();
|
||||
AppStoreEntry entry = new AppStoreEntry();
|
||||
while (appList.hasNext()) {
|
||||
SolrDocument d = appList.next();
|
||||
entry.setOrg(d.get("org_s").toString());
|
||||
entry.setName(d.get("name_s").toString());
|
||||
entry.setDesc(d.get("desc_s").toString());
|
||||
entry.setLike(Integer.valueOf(d.get("like_i").toString()));
|
||||
entry.setDownload(Integer.valueOf(d.get("download_i").toString()));
|
||||
download = entry.getDownload() + 1;
|
||||
|
||||
// Update download count
|
||||
docs.add(incrementDownload(d, download));
|
||||
}
|
||||
|
||||
// increment download count for application
|
||||
|
||||
if (service!=null) {
|
||||
// Register deployed application instance with AppList
|
||||
SolrInputDocument request = new SolrInputDocument();
|
||||
String name = service.getName();
|
||||
request.addField("type_s", "AppEntry");
|
||||
request.addField("id", name);
|
||||
request.addField("name_s", name);
|
||||
request.addField("app_s", entry.getOrg()+"/"+entry.getName());
|
||||
request.addField("yarnfile_s", mapper.writeValueAsString(service));
|
||||
docs.add(request);
|
||||
}
|
||||
|
||||
// Commit Solr changes.
|
||||
UpdateResponse detailsResponse = solr.add(docs);
|
||||
if (detailsResponse.getStatus() != 0) {
|
||||
throw new IOException("Unable to register docker instance "
|
||||
+ "with application entry.");
|
||||
}
|
||||
solr.commit();
|
||||
}
|
||||
|
||||
private SolrInputDocument incrementDownload(SolrDocument doc,
|
||||
long download) {
|
||||
Collection<String> names = doc.getFieldNames();
|
||||
SolrInputDocument s = new SolrInputDocument();
|
||||
for (String name : names) {
|
||||
if(!name.equals("_version_")) {
|
||||
s.addField(name, doc.getFieldValues(name));
|
||||
}
|
||||
}
|
||||
s.setField("download_i", download++);
|
||||
return s;
|
||||
}
|
||||
|
||||
public void deleteApp(String id) {
|
||||
SolrClient solr = getSolrClient();
|
||||
try {
|
||||
solr.deleteById(id);
|
||||
solr.commit();
|
||||
} catch (SolrServerException | IOException e) {
|
||||
LOG.error("Error in removing deployed application: "+id, e);
|
||||
}
|
||||
}
|
||||
|
||||
public void register(Application app) throws IOException {
|
||||
Collection<SolrInputDocument> docs = new HashSet<SolrInputDocument>();
|
||||
SolrClient solr = getSolrClient();
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
try {
|
||||
SolrInputDocument buffer = new SolrInputDocument();
|
||||
buffer.setField("id", java.util.UUID.randomUUID().toString()
|
||||
.substring(0, 11));
|
||||
buffer.setField("org_s", app.getOrganization());
|
||||
buffer.setField("name_s", app.getName());
|
||||
buffer.setField("desc_s", app.getDescription());
|
||||
if (app.getIcon() != null) {
|
||||
buffer.setField("icon_s", app.getIcon());
|
||||
}
|
||||
buffer.setField("type_s", "AppStoreEntry");
|
||||
buffer.setField("like_i", 0);
|
||||
buffer.setField("download_i", 0);
|
||||
|
||||
// Keep only YARN data model for yarnfile field
|
||||
String yarnFile = mapper.writeValueAsString(app);
|
||||
LOG.info("app:"+yarnFile);
|
||||
Service yarnApp = mapper.readValue(yarnFile, Service.class);
|
||||
buffer.setField("yarnfile_s", mapper.writeValueAsString(yarnApp));
|
||||
|
||||
docs.add(buffer);
|
||||
// Commit Solr changes.
|
||||
UpdateResponse detailsResponse = solr.add(docs);
|
||||
if (detailsResponse.getStatus() != 0) {
|
||||
throw new IOException("Unable to register application " +
|
||||
"in Application Store.");
|
||||
}
|
||||
solr.commit();
|
||||
} catch (SolrServerException | IOException e) {
|
||||
throw new IOException("Unable to register application " +
|
||||
"in Application Store. "+ e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,174 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.application;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.hadoop.conf.Configuration;
|
||||
import org.apache.hadoop.security.UserGroupInformation;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.apache.hadoop.yarn.service.api.records.KerberosPrincipal;
|
||||
import org.apache.hadoop.yarn.service.client.ApiServiceClient;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.sun.jersey.api.client.ClientHandlerException;
|
||||
import com.sun.jersey.api.client.ClientResponse;
|
||||
import com.sun.jersey.api.client.UniformInterfaceException;
|
||||
import com.sun.jersey.api.client.config.ClientConfig;
|
||||
import com.sun.jersey.api.client.config.DefaultClientConfig;
|
||||
|
||||
/**
|
||||
* Driver class for calling YARN Resource Manager REST API.
|
||||
*/
|
||||
public class YarnServiceClient {
|
||||
|
||||
private static final Log LOG = LogFactory.getLog(YarnServiceClient.class);
|
||||
private static Configuration conf = new Configuration();
|
||||
private static ClientConfig getClientConfig() {
|
||||
ClientConfig config = new DefaultClientConfig();
|
||||
config.getProperties().put(ClientConfig.PROPERTY_CHUNKED_ENCODING_SIZE, 0);
|
||||
config.getProperties()
|
||||
.put(ClientConfig.PROPERTY_BUFFER_RESPONSE_ENTITY_ON_EXCEPTION, true);
|
||||
return config;
|
||||
}
|
||||
|
||||
private ApiServiceClient asc;
|
||||
|
||||
public YarnServiceClient() {
|
||||
try {
|
||||
asc = new ApiServiceClient(conf);
|
||||
} catch (Exception e) {
|
||||
LOG.error("Error initialize YARN Service Client: {}", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void createApp(Service app) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
ClientResponse response;
|
||||
try {
|
||||
boolean useKerberos = UserGroupInformation.isSecurityEnabled();
|
||||
if (useKerberos) {
|
||||
KerberosPrincipal kerberos = new KerberosPrincipal();
|
||||
String[] temp = System.getenv("PRINCIPAL").split("@");
|
||||
String[] temp2 = temp[0].split("/");
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(temp2[0]);
|
||||
sb.append("/");
|
||||
sb.append("_HOST");
|
||||
sb.append("@");
|
||||
sb.append(temp[1]);
|
||||
String keytab = System.getenv("KEYTAB");
|
||||
if (!keytab.startsWith("file://")) {
|
||||
keytab = "file://" + keytab;
|
||||
}
|
||||
kerberos.setPrincipalName(sb.toString());
|
||||
kerberos.setKeytab(keytab);
|
||||
app.setKerberosPrincipal(kerberos);
|
||||
}
|
||||
response = asc.getApiClient().post(ClientResponse.class,
|
||||
mapper.writeValueAsString(app));
|
||||
if (response.getStatus() >= 299) {
|
||||
String message = response.getEntity(String.class);
|
||||
throw new RuntimeException("Failed : HTTP error code : "
|
||||
+ response.getStatus() + " error: " + message);
|
||||
}
|
||||
} catch (UniformInterfaceException | ClientHandlerException
|
||||
| IOException e) {
|
||||
LOG.error("Error in deploying application: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void deleteApp(String appInstanceId) {
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = asc.getApiClient(asc.getServicePath(appInstanceId))
|
||||
.delete(ClientResponse.class);
|
||||
if (response.getStatus() >= 299) {
|
||||
String message = response.getEntity(String.class);
|
||||
throw new RuntimeException("Failed : HTTP error code : "
|
||||
+ response.getStatus() + " error: " + message);
|
||||
}
|
||||
} catch (UniformInterfaceException | ClientHandlerException
|
||||
| IOException e) {
|
||||
LOG.error("Error in deleting application: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void restartApp(Service app) throws JsonProcessingException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
String appInstanceId = app.getName();
|
||||
String yarnFile = mapper.writeValueAsString(app);
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = asc.getApiClient(asc.getServicePath(appInstanceId))
|
||||
.put(ClientResponse.class, yarnFile);
|
||||
if (response.getStatus() >= 299) {
|
||||
String message = response.getEntity(String.class);
|
||||
throw new RuntimeException("Failed : HTTP error code : "
|
||||
+ response.getStatus() + " error: " + message);
|
||||
}
|
||||
} catch (UniformInterfaceException | ClientHandlerException
|
||||
| IOException e) {
|
||||
LOG.error("Error in restarting application: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void stopApp(Service app) throws JsonProcessingException {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
String appInstanceId = app.getName();
|
||||
String yarnFile = mapper.writeValueAsString(app);
|
||||
ClientResponse response;
|
||||
try {
|
||||
response = asc.getApiClient(asc.getServicePath(appInstanceId))
|
||||
.put(ClientResponse.class, yarnFile);
|
||||
if (response.getStatus() >= 299) {
|
||||
String message = response.getEntity(String.class);
|
||||
throw new RuntimeException("Failed : HTTP error code : "
|
||||
+ response.getStatus() + " error: " + message);
|
||||
}
|
||||
} catch (UniformInterfaceException | ClientHandlerException
|
||||
| IOException e) {
|
||||
LOG.error("Error in stopping application: ", e);
|
||||
}
|
||||
}
|
||||
|
||||
public void getStatus(AppEntry entry) {
|
||||
ObjectMapper mapper = new ObjectMapper();
|
||||
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
|
||||
String appInstanceId = entry.getName();
|
||||
Service app = null;
|
||||
try {
|
||||
String yarnFile = asc.getApiClient(asc.getServicePath(appInstanceId))
|
||||
.get(String.class);
|
||||
app = mapper.readValue(yarnFile, Service.class);
|
||||
entry.setYarnfile(app);
|
||||
} catch (UniformInterfaceException | IOException e) {
|
||||
LOG.error("Error in fetching application status: ", e);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Application Catalog.
|
||||
*/
|
||||
package org.apache.hadoop.yarn.appcatalog.application;
|
|
@ -0,0 +1,265 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.application.AppCatalogSolrClient;
|
||||
import org.apache.hadoop.yarn.appcatalog.application.YarnServiceClient;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.apache.hadoop.yarn.service.api.records.ServiceState;
|
||||
|
||||
import com.fasterxml.jackson.core.JsonProcessingException;
|
||||
|
||||
/**
|
||||
* Application catalog REST API for displaying application details.
|
||||
*/
|
||||
@Path("/app_details")
|
||||
public class AppDetailsController {
|
||||
|
||||
public AppDetailsController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* List detail information about the deployed application.
|
||||
*
|
||||
* @apiGroup AppDetailController
|
||||
* @apiName getDetails
|
||||
* @api {get} /app_details/config/{id} Check config of application instance.
|
||||
* @apiParam {String} id Application ID to fetch configuration.
|
||||
* @apiSuccess {Object} AppEntry Application configuration.
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "id":"howita_man",
|
||||
* "name":"howita_man",
|
||||
* "app":"Jenkins-ci.org/Jenkins",
|
||||
* "yarnfile":{
|
||||
* "name":"howita_man",
|
||||
* "lifetime":3600,
|
||||
* "containers":[
|
||||
* ],
|
||||
* "components":[
|
||||
* {
|
||||
* "name":"jenkins",
|
||||
* "dependencies":[
|
||||
* ],
|
||||
* "artifact":{
|
||||
* "id":"eyang-1.openstacklocal:5000/jenkins:latest",
|
||||
* "type":"DOCKER"
|
||||
* },
|
||||
* "launch_command":"",
|
||||
* "resource":{
|
||||
* "uri":null,
|
||||
* "profile":null,
|
||||
* "cpus":1,
|
||||
* "memory":"2048"
|
||||
* },
|
||||
* "number_of_containers":1,
|
||||
* "run_privileged_container":false,
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":[
|
||||
* ],
|
||||
* "containers":[
|
||||
* ]
|
||||
* }
|
||||
* ],
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":{
|
||||
* "Jenkins UI":"http://jenkins.howita_man.yarn.${DOMAIN}:8080/"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* @param id - Application ID
|
||||
* @return application entry-
|
||||
*/
|
||||
@Path("config/{id}")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public AppEntry getDetails(@PathParam("id") String id) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
return sc.findAppEntry(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check application status.
|
||||
*
|
||||
* @apiGroup AppDetailController
|
||||
* @apiName getStatus
|
||||
* @api {get} /app_details/status/{id} Check status of application instance.
|
||||
* @apiParam {String} id Application ID to check.
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* {
|
||||
* "id":"howita_man",
|
||||
* "name":"howita_man",
|
||||
* "app":"Jenkins-ci.org/Jenkins",
|
||||
* "yarnfile":{
|
||||
* "name":"howita_man",
|
||||
* "lifetime":3099,
|
||||
* "containers":[
|
||||
* ],
|
||||
* "id":"application_1503694240849_0043",
|
||||
* "components":[
|
||||
* {
|
||||
* "name":"jenkins",
|
||||
* "dependencies":[
|
||||
* ],
|
||||
* "artifact":{
|
||||
* "id":"eyang-1.openstacklocal:5000/jenkins:latest",
|
||||
* "type":"DOCKER"
|
||||
* },
|
||||
* "launch_command":"",
|
||||
* "resource":{
|
||||
* "uri":null,
|
||||
* "profile":null,
|
||||
* "cpus":1,
|
||||
* "memory":"2048"
|
||||
* },
|
||||
* "number_of_containers":1,
|
||||
* "run_privileged_container":false,
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":[
|
||||
* ],
|
||||
* "containers":[
|
||||
* {
|
||||
* "id":"container_1503694240849_0043_01_000002",
|
||||
* "launch_time":1504630535403,
|
||||
* "bare_host":"eyang-4.openstacklocal",
|
||||
* "state":"READY",
|
||||
* "component_name":"jenkins-0"
|
||||
* }
|
||||
* ]
|
||||
* }
|
||||
* ],
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":{
|
||||
* "Jenkins UI":"http://jenkins.howita_man.yarn.${DOMAIN}:8080/"
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* @apiSuccess {Object} text Give status
|
||||
* @param id - Application ID
|
||||
* @return application entry
|
||||
*/
|
||||
@Path("status/{id}")
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public AppEntry getStatus(@PathParam("id") String id) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
AppEntry appEntry = sc.findAppEntry(id);
|
||||
YarnServiceClient yc = new YarnServiceClient();
|
||||
yc.getStatus(appEntry);
|
||||
return appEntry;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop an application.
|
||||
*
|
||||
* @apiGroup AppDetailController
|
||||
* @apiName stopApp
|
||||
* @api {post} /app_details/stop/{id} Stop one instance of application.
|
||||
* @apiParam {String} id Application ID to stop.
|
||||
* @apiSuccess {String} text Give deployment status
|
||||
* @apiError BadRequest Requested application does not stop.
|
||||
* @param id - Application ID
|
||||
* @return Web response code
|
||||
*/
|
||||
@Path("stop/{id}")
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response stopApp(@PathParam("id") String id) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
AppEntry app = sc.findAppEntry(id);
|
||||
Service yarnApp = app.getYarnfile();
|
||||
yarnApp.setState(ServiceState.STOPPED);
|
||||
try {
|
||||
YarnServiceClient yc = new YarnServiceClient();
|
||||
yc.stopApp(yarnApp);
|
||||
} catch (JsonProcessingException e) {
|
||||
return Response.status(Status.BAD_REQUEST).build();
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Restart an application.
|
||||
*
|
||||
* @apiGroup AppDetailController
|
||||
* @apiName restartApp
|
||||
* @api {post} /app_details/restart/{id} Restart one instance of application.
|
||||
* @apiParam {String} id Application ID to restart.
|
||||
* @apiSuccess {String} text Give deployment status
|
||||
* @apiError BadRequest Requested application does not restart.
|
||||
* @param id - Application ID
|
||||
* @return Web response code
|
||||
*/
|
||||
@Path("restart/{id}")
|
||||
@POST
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response restartApp(@PathParam("id") String id) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
AppEntry app = sc.findAppEntry(id);
|
||||
Service yarnApp = app.getYarnfile();
|
||||
yarnApp.setState(ServiceState.STARTED);
|
||||
try {
|
||||
YarnServiceClient yc = new YarnServiceClient();
|
||||
yc.restartApp(yarnApp);
|
||||
} catch (JsonProcessingException e) {
|
||||
return Response.status(Status.BAD_REQUEST).build();
|
||||
}
|
||||
return Response.ok().build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,182 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.Consumes;
|
||||
import javax.ws.rs.DELETE;
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.application.AppCatalogSolrClient;
|
||||
import org.apache.hadoop.yarn.appcatalog.application.YarnServiceClient;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
|
||||
/**
|
||||
* Application deployment module.
|
||||
*/
|
||||
@Path("/app_list")
|
||||
@Produces({ MediaType.APPLICATION_JSON })
|
||||
public class AppListController {
|
||||
|
||||
public AppListController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Get Application List.
|
||||
*
|
||||
* @apiGroup AppListController
|
||||
* @apiName get
|
||||
* @api {get} /app_list Get list of deployed applications.
|
||||
* @apiSuccess {Object[]} List<AppEntry> List of deployed Applications.
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* [
|
||||
* {
|
||||
* "id":"howita-man",
|
||||
* "name":"howita-man",
|
||||
* "app":"Jenkins-ci.org/Jenkins",
|
||||
* "yarnfile":{
|
||||
* "name":"howita_man",
|
||||
* "lifetime":3600,
|
||||
* "containers":[
|
||||
* ],
|
||||
* "components":[
|
||||
* {
|
||||
* "name":"jenkins",
|
||||
* "dependencies":[
|
||||
* ],
|
||||
* "artifact":{
|
||||
* "id":"eyang-1.openstacklocal:5000/jenkins:latest",
|
||||
* "type":"DOCKER"
|
||||
* },
|
||||
* "launch_command":"",
|
||||
* "resource":{
|
||||
* "uri":null,
|
||||
* "profile":null,
|
||||
* "cpus":1,
|
||||
* "memory":"2048"
|
||||
* },
|
||||
* "number_of_containers":1,
|
||||
* "run_privileged_container":false,
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":[
|
||||
* ],
|
||||
* "containers":[
|
||||
* ]
|
||||
* }
|
||||
* ],
|
||||
* "configuration":{
|
||||
* "properties":{
|
||||
* },
|
||||
* "env":{
|
||||
* },
|
||||
* "files":[
|
||||
* ]
|
||||
* },
|
||||
* "quicklinks":{
|
||||
* "Jenkins UI":"http://jenkins.${SERVICE_NAME}.${USER}.${DOMAIN}:8080/"
|
||||
* }
|
||||
* }
|
||||
* },
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* ]
|
||||
* @return - Active application deployed by current user.
|
||||
*/
|
||||
@GET
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<AppEntry> getList() {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
return sc.listAppEntries();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete an application.
|
||||
*
|
||||
* @apiGroup AppListController
|
||||
* @apiName delete
|
||||
* @api {delete} /app_list Delete one instance of application.
|
||||
* @apiParam {String} id Application name to delete.
|
||||
* @apiSuccess {String} text Delete request accepted
|
||||
* @param id - application ID
|
||||
* @param name - application name
|
||||
* @return Web response
|
||||
*/
|
||||
@DELETE
|
||||
@Path("{id}/{name}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response delete(@PathParam("id") String id,
|
||||
@PathParam("name") String name) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
sc.deleteApp(id);
|
||||
YarnServiceClient yc = new YarnServiceClient();
|
||||
yc.deleteApp(name);
|
||||
return Response.status(Status.ACCEPTED).build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Deploy an application.
|
||||
*
|
||||
* @apiGroup AppListController
|
||||
* @apiName deploy
|
||||
* @api {post} /app_list/{id} Deploy one instance of application.
|
||||
* @apiParam {String} id Application ID to deploy.
|
||||
* @apiSuccess {String} text Give deployment status
|
||||
* @apiError BadRequest Unable to deploy requested application.
|
||||
* @param id - application ID
|
||||
* @return Web response
|
||||
*/
|
||||
@POST
|
||||
@Path("{id}")
|
||||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response deploy(@PathParam("id") String id, Service service) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
try {
|
||||
sc.deployApp(id, service);
|
||||
} catch (SolrServerException | IOException e) {
|
||||
return Response.status(Status.BAD_REQUEST).entity(e.toString()).build();
|
||||
}
|
||||
YarnServiceClient yc = new YarnServiceClient();
|
||||
yc.createApp(service);
|
||||
String output = "{\"status\":\"Application deployed.\",\"id\":\"" +
|
||||
service.getName() + "\"}";
|
||||
return Response.status(Status.ACCEPTED).entity(output).build();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,198 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
|
||||
import javax.ws.rs.GET;
|
||||
import javax.ws.rs.POST;
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.PathParam;
|
||||
import javax.ws.rs.Produces;
|
||||
import javax.ws.rs.QueryParam;
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import javax.ws.rs.core.Response;
|
||||
import javax.ws.rs.core.Response.Status;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.application.AppCatalogSolrClient;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppStoreEntry;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.Application;
|
||||
|
||||
/**
|
||||
* Application catalog REST API for searching and recommending
|
||||
* applications.
|
||||
*
|
||||
*/
|
||||
@Path("/app_store")
|
||||
public class AppStoreController {
|
||||
|
||||
public AppStoreController() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the most frequently used applications on YARN AppCatalog home page.
|
||||
*
|
||||
* @apiGroup AppStoreController
|
||||
* @apiName get
|
||||
* @api {get} /app_store/recommended Display recommended applications.
|
||||
* @apiSuccess {Object} AppEntry Application configuration.
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* [
|
||||
* {
|
||||
* "id":"96b7833a-e3",
|
||||
* "org":"Hortonworks",
|
||||
* "name":"LAMP",
|
||||
* "desc":"Linux Apache MySQL PHP web application",
|
||||
* "icon":"/css/img/feather.png",
|
||||
* "like":0,
|
||||
* "download":0,
|
||||
* "app":null
|
||||
* },
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* ]
|
||||
* @return - List of YARN applications
|
||||
*/
|
||||
@GET
|
||||
@Path("recommended")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<AppStoreEntry> get() {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
return sc.getRecommendedApps();
|
||||
}
|
||||
|
||||
/**
|
||||
* Search for yarn applications from solr.
|
||||
*
|
||||
* @apiGroup AppStoreController
|
||||
* @apiName search
|
||||
* @api {get} /app_store/search Find application from appstore.
|
||||
* @apiParam {String} q Keyword to search.
|
||||
* @apiSuccess {Object} AppStoreEntry List of matched applications.
|
||||
* @apiSuccessExample {json} Success-Response:
|
||||
* HTTP/1.1 200 OK
|
||||
* [
|
||||
* {
|
||||
* "id":"96b7833a-e3",
|
||||
* "org":"Hortonworks",
|
||||
* "name":"LAMP",
|
||||
* "desc":"Linux Apache MySQL PHP web application",
|
||||
* "icon":"/css/img/feather.png",
|
||||
* "like":0,
|
||||
* "download":0,
|
||||
* "app":null
|
||||
* },
|
||||
* {
|
||||
* ...
|
||||
* }
|
||||
* ]
|
||||
* @param keyword - search for keyword
|
||||
* @return - List of YARN applications matching keyword search.
|
||||
*/
|
||||
@GET
|
||||
@Path("search")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public List<AppStoreEntry> search(@QueryParam("q") String keyword) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
return sc.search(keyword);
|
||||
}
|
||||
|
||||
/**
|
||||
* Find yarn application from solr.
|
||||
*
|
||||
* @param id Application ID
|
||||
* @return AppEntry
|
||||
*/
|
||||
@GET
|
||||
@Path("get/{id}")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public AppStoreEntry get(@PathParam("id") String id) {
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
return sc.findAppStoreEntry(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Register an application.
|
||||
*
|
||||
* @apiGroup AppStoreController
|
||||
* @apiName register
|
||||
* @api {post} /app_store/register Register an application in appstore.
|
||||
* @apiParam {Object} app Application definition.
|
||||
* @apiParamExample {json} Request-Example:
|
||||
* {
|
||||
* "name": "Jenkins",
|
||||
* "organization": "Jenkins-ci.org",
|
||||
* "description": "The leading open source automation server",
|
||||
* "icon": "/css/img/jenkins.png",
|
||||
* "lifetime": "3600",
|
||||
* "components": [
|
||||
* {
|
||||
* "name": "jenkins",
|
||||
* "number_of_containers": 1,
|
||||
* "artifact": {
|
||||
* "id": "eyang-1.openstacklocal:5000/jenkins:latest",
|
||||
* "type": "DOCKER"
|
||||
* },
|
||||
* "launch_command": "",
|
||||
* "resource": {
|
||||
* "cpus": 1,
|
||||
* "memory": "2048"
|
||||
* },
|
||||
* "configuration": {
|
||||
* "env": {
|
||||
* },
|
||||
* "files": [
|
||||
* ]
|
||||
* }
|
||||
* }
|
||||
* ],
|
||||
* "quicklinks": {
|
||||
* "Jenkins UI": "http://jenkins.${SERVICE_NAME}.${USER}.${DOMAIN}:8080/"
|
||||
* }
|
||||
* }
|
||||
* @apiSuccess {String} Response Application register result.
|
||||
* @apiError BadRequest Error in process application registration.
|
||||
* @param app - Yarnfile in JSON form
|
||||
* @return Web response
|
||||
*/
|
||||
@POST
|
||||
@Path("register")
|
||||
@Produces(MediaType.APPLICATION_JSON)
|
||||
public Response register(Application app) {
|
||||
try {
|
||||
if (app.getName()==null) {
|
||||
throw new IOException("Application name can not be empty.");
|
||||
}
|
||||
if (app.getOrganization()==null) {
|
||||
throw new IOException("Application organization can not be empty.");
|
||||
}
|
||||
if (app.getDescription()==null) {
|
||||
throw new IOException("Application description can not be empty.");
|
||||
}
|
||||
AppCatalogSolrClient sc = new AppCatalogSolrClient();
|
||||
sc.register(app);
|
||||
} catch (IOException e) {
|
||||
return Response.status(Status.BAD_REQUEST).entity(e.getMessage()).build();
|
||||
}
|
||||
return Response.status(Status.ACCEPTED).build();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Application Catalog controllers.
|
||||
*/
|
||||
package org.apache.hadoop.yarn.appcatalog.controller;
|
|
@ -0,0 +1,76 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.model;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
/**
|
||||
* Data model for user defined application configuration.
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
|
||||
public class AppDetails {
|
||||
private String image;
|
||||
private String version;
|
||||
private String[] ports;
|
||||
private String[] volumes;
|
||||
private String[] env;
|
||||
|
||||
public String getImage() {
|
||||
return image;
|
||||
}
|
||||
|
||||
public void setImage(String image) {
|
||||
this.image = image;
|
||||
}
|
||||
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
public String[] getPorts() {
|
||||
return ports;
|
||||
}
|
||||
|
||||
public void setPorts(String[] ports2) {
|
||||
this.ports = ports2;
|
||||
}
|
||||
|
||||
public String[] getVolumes() {
|
||||
return volumes;
|
||||
}
|
||||
|
||||
public void setVolumes(String[] volumes) {
|
||||
this.volumes = volumes;
|
||||
}
|
||||
|
||||
public String[] getEnv() {
|
||||
return env;
|
||||
}
|
||||
|
||||
public void setEnv(String[] env) {
|
||||
this.env = env;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.model;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
import javax.xml.bind.annotation.XmlType;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
|
||||
/**
|
||||
* Data model for deployed application.
|
||||
*
|
||||
*/
|
||||
@XmlType(namespace="http://hadoop.apache.org", name="AppEntry")
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
|
||||
public class AppEntry {
|
||||
private String id;
|
||||
private String name;
|
||||
private String app;
|
||||
private Service yarnfile;
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(String app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public Service getYarnfile() {
|
||||
return yarnfile;
|
||||
}
|
||||
|
||||
public void setYarnfile(Service yarnfile) {
|
||||
this.yarnfile = yarnfile;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,106 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.model;
|
||||
|
||||
import javax.xml.bind.annotation.XmlAccessType;
|
||||
import javax.xml.bind.annotation.XmlAccessorType;
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
|
||||
/**
|
||||
* Data model of application template stored in application catalog.
|
||||
*/
|
||||
@XmlRootElement
|
||||
@XmlAccessorType(XmlAccessType.PUBLIC_MEMBER)
|
||||
public class AppStoreEntry {
|
||||
private String id;
|
||||
private String org;
|
||||
private String name;
|
||||
private String desc;
|
||||
private String icon = "/css/img/feather.png";
|
||||
private long like;
|
||||
private long download;
|
||||
private Service app;
|
||||
|
||||
public String getOrg() {
|
||||
return org;
|
||||
}
|
||||
|
||||
public void setOrg(String org) {
|
||||
this.org = org;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getDesc() {
|
||||
return desc;
|
||||
}
|
||||
|
||||
public void setDesc(String desc) {
|
||||
this.desc = desc;
|
||||
}
|
||||
|
||||
public long getLike() {
|
||||
return like;
|
||||
}
|
||||
|
||||
public void setLike(long like) {
|
||||
this.like = like;
|
||||
}
|
||||
|
||||
public long getDownload() {
|
||||
return download;
|
||||
}
|
||||
|
||||
public void setDownload(long download) {
|
||||
this.download = download;
|
||||
}
|
||||
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
public void setId(String id) {
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
public Service getApp() {
|
||||
return app;
|
||||
}
|
||||
|
||||
public void setApp(Service app) {
|
||||
this.app = app;
|
||||
}
|
||||
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
}
|
||||
|
||||
public void setIcon(String icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.model;
|
||||
|
||||
import javax.xml.bind.annotation.XmlRootElement;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.annotation.JsonProperty;
|
||||
import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
|
||||
/**
|
||||
* Data model of display recommended applications and descriptions.
|
||||
*/
|
||||
@XmlRootElement
|
||||
@JsonInclude(JsonInclude.Include.NON_NULL)
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
@JsonPropertyOrder({ "organization", "name", "description", "icon" })
|
||||
public class Application extends Service {
|
||||
private static final long serialVersionUID = -1776203219305414248L;
|
||||
|
||||
private String organization;
|
||||
private String description;
|
||||
private String icon;
|
||||
|
||||
@JsonProperty("organization")
|
||||
public String getOrganization() {
|
||||
return organization;
|
||||
}
|
||||
public void setOrganization(String organization) {
|
||||
this.organization = organization;
|
||||
}
|
||||
|
||||
@JsonProperty("description")
|
||||
public String getDescription() {
|
||||
return description;
|
||||
}
|
||||
public void setDescription(String description) {
|
||||
this.description = description;
|
||||
}
|
||||
|
||||
@JsonProperty("icon")
|
||||
public String getIcon() {
|
||||
return icon;
|
||||
}
|
||||
public void setIcon(String icon) {
|
||||
this.icon = icon;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Application Catalog Data Models.
|
||||
*/
|
||||
package org.apache.hadoop.yarn.appcatalog.model;
|
|
@ -0,0 +1,422 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.utils;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Random;
|
||||
|
||||
/**
|
||||
* Random word generator utility.
|
||||
*/
|
||||
public final class RandomWord {
|
||||
|
||||
private RandomWord() {
|
||||
}
|
||||
|
||||
public static String getNewWord(int wordLength) throws WordLengthException {
|
||||
if (wordLength < 3 || wordLength > 15) {
|
||||
throw new WordLengthException(
|
||||
"Word length error, words must be between 3 and 15 characters long.");
|
||||
}
|
||||
String theNewWord = "e";
|
||||
while (theNewWord.equals("e")) {
|
||||
try {
|
||||
theNewWord = generateRandomWord(wordLength);
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
return theNewWord;
|
||||
}
|
||||
|
||||
private static String generateRandomWord(int wordLength) {
|
||||
String randomWord;
|
||||
// -----------------------------------------------------------------------
|
||||
// Bigram source and general concept based on
|
||||
// https://github.com/scrollback/scrollback & described in
|
||||
// https://www.hackerearth.com/notes/random-pronouncable-text-generator/
|
||||
String[] startBiGram = {"TH", "OF", "AN", "IN", "TO", "CO", "BE", "HE",
|
||||
"RE", "HA", "WA", "FO", "WH", "MA", "WI", "ON", "HI", "PR", "ST", "NO",
|
||||
"IS", "IT", "SE", "WE", "AS", "CA", "DE", "SO", "MO", "SH", "DI", "AL",
|
||||
"AR", "LI", "WO", "FR", "PA", "ME", "AT", "SU", "BU", "SA", "FI", "NE",
|
||||
"CH", "PO", "HO", "DO", "OR", "UN", "LO", "EX", "BY", "FA", "LA", "LE",
|
||||
"PE", "MI", "SI", "YO", "TR", "BA", "GO", "BO", "GR", "TE", "EN", "OU",
|
||||
"RA", "AC", "FE", "PL", "CL", "SP", "BR", "EV", "TA", "DA", "AB", "TI",
|
||||
"RO", "MU", "EA", "NA", "SC", "AD", "GE", "YE", "AF", "AG", "UP", "AP",
|
||||
"DR", "US", "PU", "CE", "IF", "RI", "VI", "IM", "AM", "KN", "OP", "CR",
|
||||
"OT", "JU", "QU", "TW", "GA", "VA", "VE", "PI", "GI", "BI", "FL", "BL",
|
||||
"EL", "JO", "FU", "HU", "CU", "RU", "OV", "MY", "OB", "KE", "EF", "PH",
|
||||
"CI", "KI", "NI", "SL", "EM", "SM", "VO", "MR", "WR", "ES", "DU", "TU",
|
||||
"AU", "NU", "GU", "OW", "SY", "JA", "OC", "EC", "ED", "ID", "JE", "AI",
|
||||
"EI", "SK", "OL", "GL", "EQ", "LU", "AV", "SW", "AW", "EY", "TY"};
|
||||
String[] lookupBiGram = {"TH", "AN", "IN", "IO", "EN", "TI", "FO", "HE",
|
||||
"HA", "HI", "TE", "AT", "ER", "AL", "WA", "VE", "CO", "RE", "IT", "WI",
|
||||
"ME", "NC", "ON", "PR", "AR", "ES", "EV", "ST", "EA", "IV", "EC", "NO",
|
||||
"OU", "PE", "IL", "IS", "MA", "AV", "OM", "IC", "GH", "DE", "AI", "CT",
|
||||
"IG", "ID", " OR", "OV", "UL", "YO", "BU", "RA", "FR", "RO", "WH", "OT",
|
||||
"BL", "NT", "UN", "TR", "HO", "AC", "TU", "WE", "CA", "SH", "UR", "IE",
|
||||
"PA", "TO", "EE", "LI", "RI", "UG", "AM", "ND", "US", "LL", "AS", "TA",
|
||||
"LE", "MO", "WO", "MI", "AB", "EL", "IA", "NA", "SS", "AG", "TT", "NE",
|
||||
"PL", " LA", "OS", "CE", "DI", "BE", "AP", "SI", "NI", "OW", "SO", "AK",
|
||||
"CH", "EM", "IM", "SE", "NS", "PO", "EI", "EX", "KI", "UC", "AD", "GR",
|
||||
"IR", "NG", "OP", "SP", "OL", "DA", "NL", "TL", "LO", "BO", "RS", "FE",
|
||||
"FI", "SU", "GE", "MP", "UA", "OO", "RT", "SA", "CR", "FF", "IK", "MB",
|
||||
" KE", "FA", "CI", "EQ", "AF", "ET", "AY", "MU", "UE", "HR", "TW", "GI",
|
||||
"OI", "VI", "CU", "FU", "ED", "QU", "UT", "RC", "OF", "CL", "FT", "IZ",
|
||||
"PP", "RG", "DU", "RM", "YE", "RL", "DO", "AU", "EP", "BA", "JU", "RD",
|
||||
"RU", "OG", "BR", "EF", "KN", "LS", "GA", "PI", "YI", "BI", "IB", "UB",
|
||||
"VA", "OC", "IF", "RN", "RR", "SC", "TC", "CK", "DG", "DR", "MM", "NN",
|
||||
"OD", "RV", "UD", "XP", "JE", "UM", "EG", "DL", "PH", "SL", "GO", "CC",
|
||||
"LU", "OA", "PU", "UI", "YS", "ZA", "HU", "MR", "OE", "SY", "EO", "TY",
|
||||
"UP", "FL", "LM", "NF", "RP", "OH", "NU", "XA", "OB", "VO", "DM", "GN",
|
||||
" LD", "PT", "SK", "WR", "JO", "LT", "YT", "UF", "BJ", "DD", "EY", "GG",
|
||||
"GL", "GU", "HT", "LV", "MS", "NM", "NV", "OK", "PM", "RK", "SW", "TM",
|
||||
"XC", "ZE", "AW", "SM"};
|
||||
String[][][] nextCharLookup = {
|
||||
{{"E", "A", "I", "O", "R"}, {"E", "O"}},
|
||||
{{"D", "T", "Y", "C", "S", "G", "N", "I", "O", "E", "A", "K"},
|
||||
{"D", "T", "Y", "S", "G", "O", "E", "A", "K"}},
|
||||
{{"G", "T", "E", "D", "S", "C", "A", "I", "K", "V", "U", "N", "F"},
|
||||
{"G", "T", "E", "D", "S", "A", "K"}},
|
||||
{{"N", "U", "R"}, {"N", "U", "R"}},
|
||||
{{"T", "C", "D", "S", "E", "I", "G", "O", "N", "A"},
|
||||
{"T", "D", "S", "E", "G", "O", "A"}},
|
||||
{{"O", "N", "C", "V", "M", "L", "E", "T", "S", "A", "R", "F"},
|
||||
{"N", "C", "M", "L", "E", "T", "S", "A", "R", "F"}},
|
||||
{{"R", "U", "O", "L"}, {"R", "U", "O", "L"}},
|
||||
{{"R", "N", "Y", "S", "M", "I", "A", "L", "D", "T"},
|
||||
{"R", "N", "Y", "S", "M", "A", "L", "D", "T"}},
|
||||
{{"T", "D", "V", "N", "S", "R", "P", "L"},
|
||||
{"T", "D", "N", "S", "R", "L"}},
|
||||
{{"S", "N", "C", "M", "L", "P", "G", "T", "R", "E"},
|
||||
{"S", "N", "C", "M", "L", "P", "G", "T", "R", "E"}},
|
||||
{{"R", "D", "N", "S", "M", "L", "E", "C", "A"},
|
||||
{"R", "D", "N", "S", "M", "L", "E", "A"}},
|
||||
{{"I", "E", "T", "H", "U", "O", "C"}, {"E", "H", "O"}},
|
||||
{{"E", "S", "I", "A", "N", "Y", "T", "V", "M", "R", "O", "L", "G",
|
||||
"F", "C"}, {"E", "S", "A", "N", "Y", "T", "M"}},
|
||||
{{"L", "S", "I", "T", "E", "U", "O", "M", "K", "F", "A"},
|
||||
{"L", "S", "T", "E", "F"}},
|
||||
{{"S", "Y", "R", "T", "N", "L"}, {"S", "Y", "R", "T", "N", "L"}},
|
||||
{{"R", "N", "L", "S", "D"}, {"R", "N", "L", "S", "D"}},
|
||||
{{"N", "M", "U", "R", "L", "V", "S", "O"},
|
||||
{"N", "M", "U", "R", "L", "O"}},
|
||||
{{"S", "A", "D", "N", "E", "C", "L", "T", "P", "M", "V", "G", "F",
|
||||
"Q"}, {"S", "A", "D", "N", "E", "L", "T", "P", "M"}},
|
||||
{{"H", "I", "Y", "E", "S", "T", "A", "U"},
|
||||
{"H", "Y", "E", "S", "A"}},
|
||||
{{"T", "L", "N", "S"}, {"T", "L", "N", "S"}},
|
||||
{{"N", "R", "D", "T", "S", "M", "A"},
|
||||
{"N", "R", "D", "T", "S", "M", "A"}},
|
||||
{{"E", "I", "H", "T", "R", "O", "L"}, {"E", "H", "T"}},
|
||||
{{"S", "E", "T", "G", "A", "D", "L", "C", "V", "O", "I", "F"},
|
||||
{"S", "E", "T", "G", "A", "D", "O"}},
|
||||
{{"O", "E", "I", "A"}, {"E", "A"}},
|
||||
{{"E", "T", "D", "Y", "S", "I", "R", "L", "M", "K", "G", "A", "O",
|
||||
"N", "C"}, {"E", "T", "D", "Y", "S", "M", "K", "A", "N"}},
|
||||
{{"S", "T", "E", "I", "P", "U", "C"}, {"S", "T", "E"}},
|
||||
{{"E", "I"}, {"E"}},
|
||||
{{"A", "R", "I", "E", "O", "U", "S"}, {"A", "E", "O", "S"}},
|
||||
{{"R", "S", "T", "D", "L", "C", "N", "V", "M", "K"},
|
||||
{"R", "S", "T", "D", "L", "N", "M"}},
|
||||
{{"E", "I", "A"}, {"E"}},
|
||||
{{"T", "O", "I", "E", "A", "U", "R", "H"}, {"T", "E", "H"}},
|
||||
{{"T", "W", "R", "U", "N", "M"}, {"T", "W", "R", "U", "N", "M"}},
|
||||
{{"T", "L", "R", "N", "S", "G", "P", "B"},
|
||||
{"T", "L", "R", "N", "S", "P"}},
|
||||
{{"R", "N", "C", "A", "D", "T", "O"}, {"R", "N", "A", "D", "T"}},
|
||||
{{"L", "E", "I", "Y", "D", "A"}, {"L", "E", "Y", "D"}},
|
||||
{{"T", "H", "S", "I", "E", "C", "M"}, {"T", "H", "S", "E", "M"}},
|
||||
{{"N", "T", "L", "K", "D", "S", "I", "G"},
|
||||
{"N", "T", "L", "D", "S"}},
|
||||
{{"E", "I", "A"}, {"E"}},
|
||||
{{"E", "P", "M", "I", "A"}, {"E"}},
|
||||
{{"A", "H", "E", "I", "T", "K", "U", "S"},
|
||||
{"H", "E", "T", "K", "S"}},
|
||||
{{"T"}, {"T"}},
|
||||
{{"R", "N", "S", "D", "A", "V", "P", "T", "M", "L", "F"},
|
||||
{"R", "N", "S", "D", "A", "P", "T", "M", "L"}},
|
||||
{{"N", "D", "R", "L", "T"}, {"N", "D", "R", "L", "T"}},
|
||||
{{"I", "E", "U", "S", "O"}, {"E", "S", "O"}},
|
||||
{{"H", "N", "I"}, {"H", "N"}}, {{"E"}, {"E"}},
|
||||
{{"E", "T", "M", "D", "S", "K", "I", "Y", "L", "G", "A", "R", "N",
|
||||
"C"}, {"E", "T", "M", "D", "S", "K", "Y", "A", "N"}},
|
||||
{{"E", "I"}, {"E"}},
|
||||
{{"D", "T", "A", "L"}, {"D", "T", "L"}}, {{"U"}, {"U"}},
|
||||
{{"T", "S", "R", "I"}, {"T", "S", "R"}},
|
||||
{{"T", "N", "L", "C", "I", "M", "D", "S", "R", "P", "G", "B"},
|
||||
{"T", "N", "L", "M", "D", "S", "R"}},
|
||||
{{"O", "E", "A"}, {"E", "A"}},
|
||||
{{"M", "U", "V", "P", "N", "W", "S", "O", "L", "D", "C", "B", "A",
|
||||
"T", "G"}, {"M", "U", "P", "N", "W", "O", "L", "D", "T"}},
|
||||
{{"I", "E", "O", "A"}, {"E", "O"}},
|
||||
{{"H", "E", "T", "I"}, {"H", "E"}},
|
||||
{{"E", "I", "Y", "O", "A"}, {"E", "Y"}},
|
||||
{{"E", "I", "S", "R", "O", "A", "L", "Y", "U", "H"},
|
||||
{"E", "S", "O", "A", "Y", "H"}},
|
||||
{{"D", "T", "I", "C", "G"}, {"D", "T", "G"}},
|
||||
{{"A", "I", "O", "E", "U", "Y"}, {"A", "E", "Y"}},
|
||||
{{"U", "W", "S", "R", "L", "O", "M", "T", "P", "N", "D"},
|
||||
{"U", "W", "R", "L", "O", "M", "T", "P", "N", "D"}},
|
||||
{{"T", "E", "K", "H", "C", "R", "I"}, {"T", "E", "K", "H"}},
|
||||
{{"R", "D", "A", "T"}, {"R", "T"}},
|
||||
{{"R", "L", "E", "V", "S", "N", "A"},
|
||||
{"R", "L", "E", "S", "N", "A"}},
|
||||
{{"L", "N", "T", "R", "U", "S", "M", "P"},
|
||||
{"L", "N", "T", "R", "S", "M"}},
|
||||
{{"E", "O", "I", "A"}, {"E", "O"}},
|
||||
{{"E", "N", "T", "S", "I", "A", "Y", "R", "P", "C"},
|
||||
{"E", "N", "T", "S", "A", "Y"}},
|
||||
{{"S", "N", "D", "T", "W", "V", "R", "L", "F"},
|
||||
{"S", "N", "D", "T", "W", "R", "L"}},
|
||||
{{"R", "T", "S", "N", "L", "I", "C"}, {"R", "T", "S", "N", "L"}},
|
||||
{{"R", "O", "N", "W", "P", "M", "L"},
|
||||
{"R", "O", "N", "W", "P", "M", "L"}},
|
||||
{{"N", "D", "T", "M", "S", "R", "P", "L", "K"},
|
||||
{"N", "D", "T", "M", "S", "R", "P", "L", "K"}},
|
||||
{{"N", "T", "S", "C", "K", "G", "E", "F", "Z", "V", "O", "M", "A"},
|
||||
{"N", "T", "S", "C", "G", "E", "F", "M", "A"}},
|
||||
{{"N", "E", "C", "T", "S", "G", "A", "V", "O", "P", "M", "L", "D",
|
||||
"B"}, {"N", "E", "C", "T", "S", "G", "A", "P", "M", "L", "D"}},
|
||||
{{"H", "G"}, {"H"}}, {{"E", "P", "I", "O", "A"}, {"E"}},
|
||||
{{"E", "I", "S", "A", "U", "O"}, {"E", "S", "O"}},
|
||||
{{"E", "T", "I", "S", "L", "H"}, {"E", "T", "S", "H"}},
|
||||
{{"Y", "E", "O", "I", "S", "A"}, {"Y", "E", "S"}},
|
||||
{{"T", "S", "E", "I", "U", "O", "K", "H"},
|
||||
{"T", "S", "E", "O", "H"}},
|
||||
{{"T", "N", "L", "I", "R", "K", "B", "G", "C"},
|
||||
{"T", "N", "L", "R"}},
|
||||
{{"S", "D", "A", "T", "C", "R", "N", "M", "G", "V", "F"},
|
||||
{"S", "D", "A", "T", "R", "N", "M"}},
|
||||
{{"R", "S", "V", "T", "U", "D"}, {"R", "T", "U", "D"}},
|
||||
{{"R", "U"}, {"R", "U"}},
|
||||
{{"N", "L", "S", "T", "C", "G"}, {"N", "L", "S", "T", "C", "G"}},
|
||||
{{"L", "O", "I"}, {}},
|
||||
{{"L", "Y", "I", "E", "F", "O", "A", "T", "S", "P", "D"},
|
||||
{"L", "Y", "E", "F", "T", "S", "D"}},
|
||||
{{"L", "N", "T"}, {"L", "N", "T"}},
|
||||
{{"L", "T", "R", "N", "M"}, {"L", "T", "R", "N", "M"}},
|
||||
{{"I", "E", "U", "O", "A"}, {"E", "O"}},
|
||||
{{"E", "A", "O"}, {"E", "O"}}, {{"E", "L", "I"}, {"E"}},
|
||||
{{"D", "S", "W", "R", "E", "Y", "V", "T", "L", "C", "A"},
|
||||
{"D", "S", "W", "R", "E", "Y", "T", "L", "A"}},
|
||||
{{"A", "E", "I", "Y", "O"}, {"E", "Y"}},
|
||||
{{"T", "N", "R", "S", "C", "Y", "W", "I", "B"},
|
||||
{"T", "N", "R", "S", "Y", "W"}},
|
||||
{{"T", "E", "S", "I"}, {"T", "E", "S"}},
|
||||
{{"S", "N", "R", "D", "P", "L", "I"},
|
||||
{"S", "N", "R", "D", "P", "L"}},
|
||||
{{"S", "N", "T", "D", "F", "E", "C", "A", "V", "R"},
|
||||
{"S", "N", "T", "D", "F", "E", "C", "A", "R"}},
|
||||
{{"R", "E", "C", "T", "L", "F", "S", "I", "G", "D", "A"},
|
||||
{"R", "E", "T", "L", "S", "D", "A"}},
|
||||
{{"P", "E", "A"}, {"E"}},
|
||||
{{"O", "N", "D", "T", "S", "G", "C", "B", "V", "M", "A"},
|
||||
{"N", "D", "T", "S", "G", "C", "M", "A"}},
|
||||
{{"N", "T", "S", "C", "Z", "O", "G", "F"},
|
||||
{"N", "T", "S", "C", "G", "F"}},
|
||||
{{"N", "E", "S", "I", "A"}, {"N", "E", "S"}},
|
||||
{{"N", "M", "U", "L", "C", "R"}, {"N", "M", "U", "L", "R"}},
|
||||
{{"E", "I"}, {"E"}},
|
||||
{{"E", "A", "I", "O", "U", "R"}, {"E", "O"}},
|
||||
{{"E", "S", "P", "O", "B", "A", "I"}, {"E", "S"}},
|
||||
{{"E", "P", "I", "A", "S", "M"}, {"E", "S"}},
|
||||
{{"D", "N", "L", "S", "R", "E", "C", "T", "V", "A"},
|
||||
{"D", "N", "L", "S", "R", "E", "T", "A"}},
|
||||
{{"T", "I", "E"}, {"T", "E"}},
|
||||
{{"S", "R", "N", "L", "W", "T", "I"}, {"R", "N", "L", "W", "T"}},
|
||||
{{"R", "N", "G", "T"}, {"R", "N", "G", "T"}},
|
||||
{{"P", "T", "I", "C", "A"}, {"T"}}, {{"N"}, {"N"}},
|
||||
{{"H", "T", "K", "E"}, {"H", "T", "K", "E"}},
|
||||
{{"E", "I", "Y", "V", "M", "D"}, {"E", "Y"}},
|
||||
{{"E", "A", "O"}, {"E", "A"}},
|
||||
{{"E", "S", "T", "L", "I"}, {"E", "S", "T"}},
|
||||
{{"E", "S", "L", "T", "R", "I"}, {"E", "S"}},
|
||||
{{"E", "P", "L"}, {"E"}}, {{"E", "O", "I", "A"}, {"E"}},
|
||||
{{"D", "L", "I", "O", "E", "U"}, {"D", "L", "E"}},
|
||||
{{"Y", "T", "R", "N"}, {"Y", "T", "R", "N"}},
|
||||
{{"Y"}, {"Y"}}, {{"Y", "E"}, {"Y", "E"}},
|
||||
{{"W", "N", "O", "S", "C", "V", "U", "T", "R", "P", "G"},
|
||||
{"W", "N", "O", "U", "T", "R", "P"}},
|
||||
{{"U", "T", "R", "O", "D", "A"}, {"U", "T", "R", "O", "D"}},
|
||||
{{"T", "E", "O", "I"}, {"T", "E", "O"}},
|
||||
{{"R", "E", "W", "L", "C", "A"}, {"R", "E", "W", "L", "A"}},
|
||||
{{"R", "N", "C", "E", "L", "G"}, {"R", "N", "C", "E", "L", "G"}},
|
||||
{{"R", "C", "P", "B", "M", "L", "A"}, {"R", "P", "M", "L"}},
|
||||
{{"N", "T", "S", "R", "D"}, {"N", "T", "S", "R", "D"}},
|
||||
{{"L", "O", "A", "T", "R", "E"}, {"T", "E"}},
|
||||
{{"L", "T", "R"}, {"L", "T", "R"}},
|
||||
{{"K", "D", "L", "T", "R", "N", "M"},
|
||||
{"K", "D", "L", "T", "R", "N", "M"}},
|
||||
{{"I", "H", "A", "E", "Y", "U", "S"}, {"H", "A", "E", "Y", "S"}},
|
||||
{{"I", "M", "Y", "N", "L"}, {"M", "Y", "N", "L"}},
|
||||
{{"E", "I", "O", "A"}, {"E", "A"}}, {{"E", "I"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"D", "N", "T", "S", "R", "E"}, {"D", "N", "T", "S", "R", "E"}},
|
||||
{{"C", "R", "M", "I"}, {"R", "M"}},
|
||||
{{"A", "T", "E", "S", "P", "N"}, {"A", "T", "E", "S", "P", "N"}},
|
||||
{{"U"}, {}}, {{"T", "F"}, {"T", "F"}},
|
||||
{{"T", "I", "H", "E", "Y", "W", "S", "A"},
|
||||
{"H", "E", "Y", "S", "A"}},
|
||||
{{"S", "E"}, {"S"}},
|
||||
{{"S", "N", "L", "C"}, {"S", "N", "L"}},
|
||||
{{"S", "N"}, {"S", "N"}}, {{"O", "E", "I"}, {"E"}},
|
||||
{{"O", "E"}, {"O", "E"}},
|
||||
{{"N", "V", "O", "C"}, {"N", "C"}}, {{"N"}, {"N"}},
|
||||
{{"N", "D", "S", "C", "T", "O", "L", "E"},
|
||||
{"N", "D", "S", "C", "T", "L", "E"}},
|
||||
{{"L", "R", "T", "S"}, {"L", "R", "T", "S"}},
|
||||
{{"L", "R", "N"}, {"L", "R", "N"}},
|
||||
{{"I", "U", "E"}, {"E"}}, {{"I", "E", "A"}, {"E"}},
|
||||
{{"I", "H", "E"}, {"H", "E"}}, {{"H", "E"}, {"H", "E"}},
|
||||
{{"F", "T"}, {"F", "T"}}, {{"E", "A", "U", "O"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E", "A"}, {"E"}},
|
||||
{{"E", "O", "R", "L"}, {"E"}}, {{"E", "A"}, {"E"}},
|
||||
{{"C", "S", "R", "A"}, {"S", "R"}},
|
||||
{{"A", "S", "I", "E"}, {"S", "E"}},
|
||||
{{"A", "S", "D"}, {"A", "S", "D"}},
|
||||
{{"Y", "D"}, {"Y", "D"}},
|
||||
{{"W", "N", "M", "E"}, {"W", "N", "M"}},
|
||||
{{"T", "S"}, {"T", "S"}},
|
||||
{{"T", "O", "E", "A"}, {"T", "E"}},
|
||||
{{"S", "C", "R", "N", "L"}, {"S", "R", "N", "L"}},
|
||||
{{"S"}, {"S"}}, {{"S", "E", "I"}, {"S", "E"}},
|
||||
{{"S", "N", "C"}, {"S", "N"}}, {{"R", "I"}, {}},
|
||||
{{"O", "I", "E", "A"}, {"E", "A"}},
|
||||
{{"O", "F", "U", "T", "E"}, {"F", "T", "E"}},
|
||||
{{"O", "E"}, {"O", "E"}}, {{"O"}, {"O"}},
|
||||
{{"N", "I", "T", "R"}, {"N", "T", "R"}},
|
||||
{{"N", "T", "R", "E", "C"}, {"N", "T", "R", "E", "C"}},
|
||||
{{"N"}, {"N"}}, {{"L", "T", "N"}, {"L", "T", "N"}},
|
||||
{{"L", "I", "E"}, {"E"}}, {{"L"}, {}},
|
||||
{{"L", "T", "R", "N"}, {"L", "T", "R", "N"}},
|
||||
{{"K", "I", "E", "C", "A"}, {"K", "E"}},
|
||||
{{"I", "F", "E", "T"}, {"F", "E", "T"}},
|
||||
{{"I", "E", "M", "A"}, {"E", "A"}},
|
||||
{{"I", "E", "Y", "O"}, {"E", "Y"}},
|
||||
{{"H", "R", "O", "I", "A"}, {"H"}}, {{"H"}, {"H"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"E", "O", "I", "A"}, {"E", "A"}},
|
||||
{{"E", "U", "I"}, {"E"}}, {{"E", "O", "I"}, {"E", "O"}},
|
||||
{{"E", "Y", "U"}, {"E", "Y"}}, {{"E", "I"}, {"E"}},
|
||||
{{"E", "I"}, {"E"}}, {{"E"}, {"E"}}, {{"C"}, {}},
|
||||
{{"B", "E"}, {"E"}}, {{"A", "R", "I", "E"}, {"E"}},
|
||||
{{"Y", "E"}, {"Y", "E"}},
|
||||
{{"Y", "O", "I", "E"}, {"Y", "O", "E"}},
|
||||
{{"Y", "A"}, {"Y"}}, {{"V", "T", "O"}, {"T", "O"}},
|
||||
{{"U", "O", "E"}, {"E"}},
|
||||
{{"T", "S", "M", "E", "D"}, {"T", "S", "M", "E"}},
|
||||
{{"T", "R", "D"}, {"T", "R", "D"}},
|
||||
{{"T", "R", "L", "B"}, {"T", "R", "L"}},
|
||||
{{"T", "R", "L"}, {"T", "R", "L"}}, {{"T"}, {"T"}},
|
||||
{{"T"}, {"T"}},
|
||||
{{"S", "R", "N", "M"}, {"S", "R", "N", "M"}},
|
||||
{{"S"}, {"S"}}, {{"S"}, {"S"}}, {{"S"}, {"S"}},
|
||||
{{"R", "P"}, {"R", "P"}}, {{"P"}, {}}, {{"P", "O"}, {}},
|
||||
{{"O", "E"}, {"E"}}, {{"O"}, {}}, {{"O"}, {}},
|
||||
{{"O"}, {}}, {{"N"}, {}}, {{"M"}, {"M"}},
|
||||
{{"M"}, {"M"}}, {{"L"}, {}}, {{"L"}, {"L"}},
|
||||
{{"I"}, {}}, {{"I"}, {}}, {{"I", "E"}, {"E"}},
|
||||
{{"I"}, {}}, {{"I", "E"}, {"E"}}, {{"I"}, {}},
|
||||
{{"H"}, {}}, {{"H", "E"}, {"H", "E"}}, {{"H"}, {"H"}},
|
||||
{{"F"}, {"F"}}, {{"E"}, {}}, {{"E"}, {"E"}},
|
||||
{{"E"}, {}}, {{"E"}, {"E"}}, {{"E", "A"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"E"}, {"E"}}, {{"E"}, {"E"}}, {{"E"}, {"E"}},
|
||||
{{"D"}, {"D"}}, {{"A"}, {}}, {{"A"}, {}}};
|
||||
// ------------------------------------------------------------------------
|
||||
randomWord = startBiGram[indexGenerator(startBiGram.length)];
|
||||
int flag = 0;
|
||||
int count = 0;
|
||||
String previousWord;
|
||||
while (randomWord.length() != wordLength) {
|
||||
previousWord = randomWord;
|
||||
randomWord = addCharacter(startBiGram, wordLength, randomWord,
|
||||
lookupBiGram, nextCharLookup, flag);
|
||||
if (previousWord.equals(randomWord)) {
|
||||
count++;
|
||||
} else {
|
||||
flag = 0;
|
||||
}
|
||||
if (count == 5) {
|
||||
flag = 1;
|
||||
count++;
|
||||
} else if (count == 20) {
|
||||
randomWord = startBiGram[indexGenerator(startBiGram.length)];
|
||||
count = 0;
|
||||
}
|
||||
}
|
||||
return randomWord;
|
||||
}
|
||||
|
||||
private static String addCharacter(String[] startBiGram, int desiredLength,
|
||||
String currentWord, String[] lookupBiGram, String[][][] nextCharLookup,
|
||||
int flag) {
|
||||
int mainIndex = getLookupIndex(currentWord, lookupBiGram);
|
||||
int type = 0;
|
||||
if (currentWord.length() == (desiredLength - 1)) {
|
||||
type = 1;
|
||||
}
|
||||
while (mainIndex < 0 || mainIndex > 263
|
||||
|| nextCharLookup[mainIndex][type].length <= 0) {
|
||||
if (currentWord.length() == 2) {
|
||||
return startBiGram[indexGenerator(startBiGram.length)];
|
||||
}
|
||||
if (flag == 1) {
|
||||
currentWord = backtrack(currentWord, 2);
|
||||
flag = 0;
|
||||
} else {
|
||||
currentWord = backtrack(currentWord, 1);
|
||||
}
|
||||
mainIndex = getLookupIndex(currentWord, lookupBiGram);
|
||||
if (type == 1) {
|
||||
type = 0;
|
||||
}
|
||||
}
|
||||
String updatedWord = currentWord
|
||||
+ getNextCharacter(type, mainIndex, nextCharLookup);
|
||||
return updatedWord;
|
||||
}
|
||||
|
||||
private static int indexGenerator(int arrayLength) {
|
||||
int theIndex;
|
||||
Random generator = new Random();
|
||||
theIndex = generator.nextInt(arrayLength);
|
||||
return theIndex;
|
||||
}
|
||||
|
||||
private static String getNextCharacter(int type, int mainIndex,
|
||||
String[][][] theCharacterVault) {
|
||||
String nextChar;
|
||||
int i = indexGenerator(theCharacterVault[mainIndex][type].length);
|
||||
nextChar = theCharacterVault[mainIndex][type][i];
|
||||
return nextChar;
|
||||
}
|
||||
|
||||
private static String backtrack(String theWord, int numberChars) {
|
||||
theWord = theWord.substring(0, theWord.length() - numberChars);
|
||||
return theWord;
|
||||
}
|
||||
|
||||
private static int getLookupIndex(String theWord, String[] lookupArray) {
|
||||
String lookupCharacters = theWord.substring(theWord.length() - 2);
|
||||
int lookupIndex = Arrays.asList(lookupArray).indexOf(lookupCharacters);
|
||||
return lookupIndex;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.utils;
|
||||
|
||||
/**
|
||||
* Word length exception class.
|
||||
*/
|
||||
public class WordLengthException extends Exception {
|
||||
private static final long serialVersionUID = -217354336577036950L;
|
||||
|
||||
public WordLengthException(String message){
|
||||
super(message);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* 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.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* Application Catalog Utilities classes.
|
||||
*/
|
||||
package org.apache.hadoop.yarn.appcatalog.utils;
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
var app = angular.module('app', [
|
||||
'ngRoute',
|
||||
'filters',
|
||||
'controllers'
|
||||
]);
|
||||
|
||||
app.directive('jsonText', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
require: 'ngModel',
|
||||
link: function(scope, element, attr, ngModel) {
|
||||
function into(input) {
|
||||
console.log(JSON.parse(input));
|
||||
return JSON.parse(input);
|
||||
}
|
||||
function out(data) {
|
||||
return JSON.stringify(data);
|
||||
}
|
||||
ngModel.$parsers.push(into);
|
||||
ngModel.$formatters.push(out);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.config(['$routeProvider',
|
||||
function ($routeProvider) {
|
||||
$routeProvider.when('/', {
|
||||
templateUrl: 'partials/home.html',
|
||||
controller: 'AppStoreController'
|
||||
}).when('/app/:id', {
|
||||
templateUrl: 'partials/details.html',
|
||||
controller: 'AppDetailsController'
|
||||
}).when('/new', {
|
||||
templateUrl: 'partials/new.html',
|
||||
controller: 'NewAppController'
|
||||
}).when('/deploy/:id', {
|
||||
templateUrl: 'partials/deploy.html',
|
||||
controller: 'DeployAppController'
|
||||
}).otherwise({
|
||||
redirectTo: '/'
|
||||
});
|
||||
}]);
|
|
@ -0,0 +1,320 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
var controllers = angular.module("controllers", []);
|
||||
|
||||
controllers.controller("AppListController", [ '$scope', '$rootScope', '$http',
|
||||
function($scope, $rootScope, $http) {
|
||||
$scope.appList = [];
|
||||
|
||||
function successCallback(response) {
|
||||
$scope.appList = response.data;
|
||||
$rootScope.$emit("hideLoadScreen", {});
|
||||
}
|
||||
|
||||
function errorCallback(response) {
|
||||
$rootScope.$emit("hideLoadScreen", {});
|
||||
console.log("Error in downloading application list");
|
||||
}
|
||||
|
||||
$rootScope.$on("RefreshAppList", function() {
|
||||
$scope.refreshList();
|
||||
});
|
||||
|
||||
$scope.refreshList = function() {
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_list'
|
||||
}).then(successCallback, errorCallback);
|
||||
}
|
||||
|
||||
$scope.deleteApp = function(id, name) {
|
||||
$rootScope.$emit("showLoadScreen", {});
|
||||
$http({
|
||||
method: 'DELETE',
|
||||
url: '/v1/app_list/' + id + '/' + name
|
||||
}).then(function(response) {
|
||||
$rootScope.$emit("RefreshAppList", {});
|
||||
window.location = '/#';
|
||||
}, function(response) {
|
||||
console.log(response);
|
||||
});
|
||||
}
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_list'
|
||||
}).then(successCallback, errorCallback);
|
||||
} ]);
|
||||
|
||||
controllers.controller("AppStoreController", [ '$scope', '$rootScope', '$http',
|
||||
function($scope, $rootScope, $http) {
|
||||
$scope.canDeployApp = function() {
|
||||
return false;
|
||||
};
|
||||
$scope.appStore = [];
|
||||
$scope.searchText = null;
|
||||
|
||||
function successCallback(response) {
|
||||
$scope.appStore = response.data;
|
||||
}
|
||||
|
||||
function errorCallback(response) {
|
||||
console.log("Error in downloading AppStore information.");
|
||||
}
|
||||
|
||||
$scope.deployApp = function(id) {
|
||||
window.location = '/#!/deploy/' + id;
|
||||
}
|
||||
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_store/recommended'
|
||||
}).then(successCallback, errorCallback);
|
||||
|
||||
$scope.change = function(text) {
|
||||
var q = $scope.searchText;
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_store/search?q=' + q
|
||||
}).then(successCallback, errorCallback);
|
||||
}
|
||||
} ]);
|
||||
|
||||
controllers.controller("AppDetailsController", [ '$scope', '$interval', '$rootScope', '$http',
|
||||
'$routeParams', function($scope, $interval, $rootScope, $http, $routeParams) {
|
||||
$scope.details = {"yarnfile":{"state":"UNKNOWN"}};
|
||||
$scope.appName = $routeParams.id;
|
||||
var timer = $interval(function() {
|
||||
$scope.refreshAppDetails();
|
||||
}, 2000);
|
||||
|
||||
$scope.refreshAppDetails = function() {
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_details/status/' + $scope.appName
|
||||
}).then(successCallback, errorCallback);
|
||||
}
|
||||
|
||||
$scope.stopApp = function(id) {
|
||||
$http({
|
||||
method : 'POST',
|
||||
url : '/v1/app_details/stop/' + id
|
||||
}).then(function(data, status, header, config) {
|
||||
$scope.refreshAppDetails();
|
||||
}, errorCallback);
|
||||
}
|
||||
|
||||
$scope.restartApp = function(id) {
|
||||
$http({
|
||||
method : 'POST',
|
||||
url : '/v1/app_details/restart/' + id
|
||||
}).then(function(data, status, header, config) {
|
||||
$scope.refreshAppDetails();
|
||||
}, errorCallback);
|
||||
}
|
||||
|
||||
$scope.canDeployApp = function() {
|
||||
return true;
|
||||
};
|
||||
|
||||
$scope.checkServiceLink = function() {
|
||||
if ($scope.details.yarnfile.state != "STABLE") {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function successCallback(response) {
|
||||
if (response.data.yarnfile.components.length!=0) {
|
||||
$scope.details = response.data;
|
||||
} else {
|
||||
// When application is in accepted or failed state, it does not
|
||||
// have components detail, hence we update states only.
|
||||
$scope.details.yarnfile.state = response.data.yarnfile.state;
|
||||
}
|
||||
}
|
||||
|
||||
function errorCallback(response) {
|
||||
console.log("Error in getting application detail");
|
||||
}
|
||||
|
||||
$rootScope.$on("RefreshAppDetails", function() {
|
||||
$scope.refreshAppDetails();
|
||||
});
|
||||
|
||||
$scope.$on("$locationChangeStart", function() {
|
||||
$interval.cancel(timer);
|
||||
});
|
||||
|
||||
$scope.$on('$destroy', function() {
|
||||
$interval.cancel(timer);
|
||||
});
|
||||
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_details/config/' + $scope.appName
|
||||
}).then(successCallback, errorCallback);
|
||||
|
||||
} ]);
|
||||
|
||||
controllers.controller("NewAppController", [ '$scope', '$rootScope', '$http', function($scope, $rootScope, $http) {
|
||||
$scope.details = {
|
||||
"name" : "",
|
||||
"version" : "",
|
||||
"organization" : "",
|
||||
"description" : "",
|
||||
"quicklinks": {
|
||||
"UI": "http://${SERVICE_NAME}.${USER}.${DOMAIN}:8080/"
|
||||
},
|
||||
"icon" : "",
|
||||
"components" : [
|
||||
{
|
||||
"name" : "",
|
||||
"number_of_containers" : 1,
|
||||
"artifact" : {
|
||||
"id": "centos:latest"
|
||||
},
|
||||
"launch_command": "",
|
||||
"resource" : {
|
||||
"cpus" : 1,
|
||||
"memory" : 2048
|
||||
},
|
||||
"run_privileged_container" : false,
|
||||
"dependencies" : [],
|
||||
"placement_policy" : {
|
||||
"constraints" : []
|
||||
},
|
||||
"configuration" : {
|
||||
"env" : {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true"
|
||||
},
|
||||
"properties" : {
|
||||
"docker.network":"host"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
};
|
||||
|
||||
$scope.template = {
|
||||
"name" : "",
|
||||
"number_of_containers" : 1,
|
||||
"artifact" : {
|
||||
"id": "centos:latest"
|
||||
},
|
||||
"launch_command": "",
|
||||
"resource" : {
|
||||
"cpus" : 1,
|
||||
"memory" : 2048
|
||||
},
|
||||
"run_privileged_container" : false,
|
||||
"dependencies" : [],
|
||||
"placement_policy" : {
|
||||
"constraints" : []
|
||||
},
|
||||
"configuration" : {
|
||||
"env" : {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true"
|
||||
},
|
||||
"properties" : {
|
||||
"docker.network":"host"
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
$scope.message = null;
|
||||
$scope.error = null;
|
||||
|
||||
$scope.save = function() {
|
||||
$http({
|
||||
method : 'POST',
|
||||
url : '/v1/app_store/register',
|
||||
data : JSON.stringify($scope.details)
|
||||
}).then(successCallback, errorCallback)
|
||||
}
|
||||
|
||||
$scope.add = function() {
|
||||
$scope.details.components.push($scope.template);
|
||||
}
|
||||
|
||||
$scope.remove = function(index) {
|
||||
$scope.details.components.splice(index, 1);
|
||||
}
|
||||
|
||||
function successCallback(response) {
|
||||
$scope.message = "Application published successfully.";
|
||||
setTimeout(function() {
|
||||
$scope.$apply(function() {
|
||||
window.location = '/#';
|
||||
});
|
||||
}, 5000);
|
||||
}
|
||||
|
||||
function errorCallback(response) {
|
||||
$scope.error = "Error in registering application configuration.";
|
||||
}
|
||||
|
||||
} ]);
|
||||
|
||||
controllers.controller("DeployAppController", [ '$scope', '$rootScope', '$http',
|
||||
'$routeParams', function($scope, $rootScope, $http, $routeParams) {
|
||||
$scope.id = $routeParams.id;
|
||||
|
||||
function successCallback(response) {
|
||||
$scope.details = response.data;
|
||||
$rootScope.$emit("hideLoadScreen", {});
|
||||
}
|
||||
|
||||
function errorCallback(response) {
|
||||
$rootScope.$emit("hideLoadScreen", {});
|
||||
console.log("Error in downloading application template.");
|
||||
}
|
||||
|
||||
$scope.launchApp = function(app) {
|
||||
$rootScope.$emit("showLoadScreen", {});
|
||||
$http({
|
||||
method : 'POST',
|
||||
url : '/v1/app_list/' + $scope.id,
|
||||
data : JSON.stringify($scope.details.app)
|
||||
}).then(function(data, status, headers, config) {
|
||||
$rootScope.$emit("RefreshAppList", {});
|
||||
window.location = '/#!/app/' + data.data.id;
|
||||
}, function(data, status, headers, config) {
|
||||
console.log('error', data, status);
|
||||
});
|
||||
}
|
||||
|
||||
$http({
|
||||
method : 'GET',
|
||||
url : '/v1/app_store/get/' + $scope.id
|
||||
}).then(successCallback, errorCallback);
|
||||
|
||||
}]);
|
||||
|
||||
controllers.controller("LoadScreenController", [ '$scope', '$rootScope', '$http', function($scope, $rootScope, $http) {
|
||||
$scope.loadScreen = "hide";
|
||||
|
||||
$rootScope.$on("showLoadScreen", function() {
|
||||
$scope.loadScreen = "show";
|
||||
});
|
||||
|
||||
$rootScope.$on("hideLoadScreen", function() {
|
||||
$scope.loadScreen = "hide";
|
||||
});
|
||||
|
||||
}]);
|
|
@ -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.
|
||||
*/
|
||||
var app = angular.module("filters", []);
|
||||
|
||||
app.filter("counterValue",function(){
|
||||
return function(value){
|
||||
var count=parseInt(value), suffix="";
|
||||
if (count>=1000000){
|
||||
count=Math.round(count/1000000);
|
||||
suffix="M"
|
||||
} else if (count>=1000){
|
||||
count=Math.round(count/1000);
|
||||
suffix="K"
|
||||
}
|
||||
return""+count+suffix
|
||||
}
|
||||
});
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
|
@ -0,0 +1,17 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
|
@ -0,0 +1 @@
|
|||
solr_url=http://localhost:8983/solr/appcatalog/
|
|
@ -0,0 +1,23 @@
|
|||
# Licensed 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.
|
||||
|
||||
log4j.rootLogger = INFO, CATALINA
|
||||
|
||||
# Define all the appenders
|
||||
log4j.appender.CATALINA = org.apache.log4j.DailyRollingFileAppender
|
||||
log4j.appender.CATALINA.File = ${catalina.base}/logs/appcatalog.log
|
||||
log4j.appender.CATALINA.Append = true
|
||||
log4j.appender.CATALINA.Encoding = UTF-8
|
||||
# Roll-over the log once per day
|
||||
log4j.appender.CATALINA.DatePattern = '.'yyyy-MM-dd'.log'
|
||||
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
|
||||
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
|
|
@ -0,0 +1 @@
|
|||
vendor/
|
|
@ -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.
|
||||
-->
|
||||
<beans 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/beans_1_1.xsd"
|
||||
bean-discovery-mode="annotated">
|
||||
</beans>
|
|
@ -0,0 +1,75 @@
|
|||
<?xml version="1.0" encoding="ISO-8859-1"?>
|
||||
<!--
|
||||
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.
|
||||
-->
|
||||
|
||||
<web-app xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
|
||||
version="3.0">
|
||||
|
||||
<context-param>
|
||||
<param-name>local-deployment</param-name>
|
||||
<param-value>true</param-value>
|
||||
</context-param>
|
||||
|
||||
|
||||
<description>
|
||||
YARN Application Catalog
|
||||
</description>
|
||||
<display-name>appcatalog</display-name>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>REST_API</servlet-name>
|
||||
<servlet-class>com.sun.jersey.spi.container.servlet.ServletContainer</servlet-class>
|
||||
<init-param>
|
||||
<param-name>com.sun.jersey.config.property.packages</param-name>
|
||||
<param-value>org.apache.hadoop.yarn.appcatalog.controller;com.wordnik.swagger.jaxrs.listing;com.wordnik.swagger.jaxrs.json</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>DefaultJaxrsConfig</servlet-name>
|
||||
<servlet-class>com.wordnik.swagger.jaxrs.config.DefaultJaxrsConfig</servlet-class>
|
||||
<init-param>
|
||||
<param-name>api.version</param-name>
|
||||
<param-value>3</param-value>
|
||||
</init-param>
|
||||
<init-param>
|
||||
<param-name>swagger.api.basepath</param-name>
|
||||
<param-value>http://localhost:8080/v1</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
<servlet-name>REST_API</servlet-name>
|
||||
<url-pattern>/v1/*</url-pattern>
|
||||
</servlet-mapping>
|
||||
|
||||
<filter>
|
||||
<filter-name>CorsFilter</filter-name>
|
||||
<filter-class>org.apache.catalina.filters.CorsFilter</filter-class>
|
||||
</filter>
|
||||
<filter-mapping>
|
||||
<filter-name>CorsFilter</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
</web-app>
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
Binary file not shown.
After Width: | Height: | Size: 5.9 KiB |
Binary file not shown.
After Width: | Height: | Size: 23 KiB |
|
@ -0,0 +1,8 @@
|
|||
<svg width="200px" height="200px" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" preserveAspectRatio="xMidYMid" class="lds-dual-ring" style="background: none;">
|
||||
<circle cx="50" cy="50" ng-attr-r="{{config.radius}}" ng-attr-stroke-width="{{config.width}}" ng-attr-stroke="{{config.c1}}" ng-attr-stroke-dasharray="{{config.dasharray}}" fill="none" stroke-linecap="round" r="40" stroke-width="4" stroke="#84de5c" stroke-dasharray="62.83185307179586 62.83185307179586" transform="rotate(318 50 50)">
|
||||
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
|
||||
</circle>
|
||||
<circle cx="50" cy="50" ng-attr-r="{{config.radius2}}" ng-attr-stroke-width="{{config.width}}" ng-attr-stroke="{{config.c2}}" ng-attr-stroke-dasharray="{{config.dasharray2}}" ng-attr-stroke-dashoffset="{{config.dashoffset2}}" fill="none" stroke-linecap="round" r="35" stroke-width="4" stroke="#21d129" stroke-dasharray="54.97787143782138 54.97787143782138" stroke-dashoffset="54.97787143782138" transform="rotate(-318 50 50)">
|
||||
<animateTransform attributeName="transform" type="rotate" calcMode="linear" values="0 50 50;-360 50 50" keyTimes="0;1" dur="1s" begin="0s" repeatCount="indefinite"></animateTransform>
|
||||
</circle>
|
||||
</svg>
|
After Width: | Height: | Size: 1.3 KiB |
Binary file not shown.
After Width: | Height: | Size: 27 KiB |
|
@ -0,0 +1,252 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
|
||||
.tile {
|
||||
margin: 5px 5px 0px 5px;
|
||||
padding: 5px;
|
||||
border: 1px solid #cdcdcd;
|
||||
height: 210px;
|
||||
overflow: hidden;
|
||||
background-color: #ffffff;
|
||||
border-top-left-radius: 4px;
|
||||
border-top-right-radius: 4px;
|
||||
min-width: 250px;
|
||||
}
|
||||
|
||||
.panel {
|
||||
margin: 5px 0px 0px 0px;
|
||||
padding: 5px;
|
||||
border: 1px solid #cdcdcd;
|
||||
}
|
||||
|
||||
.desc {
|
||||
position: relative;
|
||||
top: 100px;
|
||||
margin: 5px;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
height: 60px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.appBanner {
|
||||
display: block;
|
||||
height: 40px;
|
||||
}
|
||||
|
||||
.appList {
|
||||
display: block;
|
||||
}
|
||||
|
||||
html, body, .container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.container {
|
||||
display:table;
|
||||
width: 100%;
|
||||
margin: 0;
|
||||
padding: 0; /*set left/right padding according to needs*/
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.row {
|
||||
height: 100%;
|
||||
display: table-row;
|
||||
}
|
||||
|
||||
.wizard {
|
||||
height: 100%;
|
||||
border: none;
|
||||
}
|
||||
|
||||
.wizard-body {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.navigation-header div.btn-group div {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.navigation-header div.btn-group div a:hover {
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li {
|
||||
color: #999;
|
||||
}
|
||||
|
||||
.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li:hover {
|
||||
background-color: #404351;
|
||||
}
|
||||
|
||||
.navigation-menu-item {
|
||||
padding-left: 30px;
|
||||
}
|
||||
|
||||
ul.nav.side-nav-menu li {
|
||||
height: 55px;
|
||||
}
|
||||
|
||||
.navigation-bar-container ul.nav.side-nav-menu li.mainmenu-li>a {
|
||||
color: #b8bec4;
|
||||
}
|
||||
|
||||
.navigation-bar {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.navigation-bar-container {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
.content {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.mdl-shadow-4dp {
|
||||
box-shadow: 0 4px 5px 0 rgba(0,0,0,.14), 0 1px 10px 0 rgba(0,0,0,.12), 0 2px 4px -1px rgba(0,0,0,.2);
|
||||
}
|
||||
|
||||
/*
|
||||
* hexagon
|
||||
*/
|
||||
.hexa, .hexa div {
|
||||
position: absolute;
|
||||
top: -5px;
|
||||
left: 0px;
|
||||
overflow: hidden;
|
||||
width: 128px;
|
||||
height: 128px;
|
||||
}
|
||||
.hexa {
|
||||
width: 128px;
|
||||
height: 96px;
|
||||
}
|
||||
.hexa div {
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.hexa {
|
||||
-webkit-transform: rotate(120deg);
|
||||
-moz-transform: rotate(120deg);
|
||||
-ms-transform: rotate(120deg);
|
||||
-o-transform: rotate(120deg);
|
||||
transform: rotate(120deg);
|
||||
}
|
||||
.hex1 {
|
||||
-webkit-transform: rotate(-60deg);
|
||||
-moz-transform: rotate(-60deg);
|
||||
-ms-transform: rotate(-60deg);
|
||||
-o-transform: rotate(-60deg);
|
||||
transform: rotate(-60deg);
|
||||
}
|
||||
.hex2 {
|
||||
box-shadow: 0 4px 5px 0 rgba(0,0,0,.14), 0 1px 10px 0 rgba(0,0,0,.12), 0 2px 4px -1px rgba(0,0,0,.2);
|
||||
-webkit-transform: rotate(-60deg);
|
||||
-moz-transform: rotate(-60deg);
|
||||
-ms-transform: rotate(-60deg);
|
||||
-o-transform: rotate(-60deg);
|
||||
transform: rotate(-60deg);
|
||||
}
|
||||
|
||||
/*
|
||||
* card title
|
||||
*/
|
||||
.card-title {
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
left: 128px;
|
||||
}
|
||||
|
||||
.card-desc {
|
||||
margin: 10px;
|
||||
padding-right: 25px;
|
||||
}
|
||||
|
||||
.card-footer {
|
||||
position: relative;
|
||||
margin: 0px 5px 5px 5px;
|
||||
padding: 5px;
|
||||
background-color: #eeeeee;
|
||||
line-height: 25px;
|
||||
height: 45px;
|
||||
color: #666;
|
||||
font-family: Roboto,sans-serif!important;
|
||||
font-size: 14;
|
||||
min-width: 250px;
|
||||
border-bottom-left-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
|
||||
.toparea {
|
||||
position: fixed;
|
||||
top: 0px;
|
||||
left: 230px;
|
||||
width: calc(100% - 230px);
|
||||
height: 300px;
|
||||
color: #2c2e3b;
|
||||
background: -webkit-linear-gradient(left,#2e3b51 ,#181d2b);
|
||||
background: -moz-linear-gradient(right,#2e3b51,#181d2b);
|
||||
background: -o-linear-gradient(right,#2e3b51,#181d2b);
|
||||
background: linear-gradient(to right,#2e3b51 ,#181d2b);
|
||||
}
|
||||
|
||||
.pattern-wrapper {
|
||||
width: 100%;
|
||||
height: 300px;
|
||||
background-image: url(img/pattern-f61c2e99f82389a67432f54155c5f483.png);
|
||||
background-repeat: no-repeat;
|
||||
background-position: 0px 30px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
}
|
||||
|
||||
.recommended {
|
||||
color: #fff;
|
||||
}
|
||||
|
||||
.loader-wrapper {
|
||||
position: fixed;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
background: #222222;
|
||||
z-index: 1000;
|
||||
opacity: 0.3;
|
||||
}
|
||||
|
||||
.loader {
|
||||
display: table;
|
||||
margin: 0 auto;
|
||||
position: relative;
|
||||
top: 50%;
|
||||
transform: translateY(-50%);
|
||||
}
|
||||
|
||||
.loader img {
|
||||
width: 300px;
|
||||
height: 225px;
|
||||
}
|
||||
|
||||
.infobox {
|
||||
font-size:14px;
|
||||
margin:20px;
|
||||
padding:10px;
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
.theme-dropdown .dropdown-menu {
|
||||
position: static;
|
||||
display: block;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.theme-showcase > p > .btn {
|
||||
margin: 5px 0;
|
||||
}
|
||||
|
||||
.theme-showcase .navbar .container {
|
||||
width: auto;
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<!doctype html>
|
||||
<html lang="en" data-ng-app="app">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<title>YARN Application Catalog</title>
|
||||
<link rel="stylesheet" href="vendor/bootstrap/dist/css/bootstrap.min.css">
|
||||
<link rel="stylesheet" href="vendor/bootstrap/dist/css/bootstrap-theme.min.css">
|
||||
<link href="css/bootstrap-hadoop.css" rel="stylesheet">
|
||||
<link rel="stylesheet" href="css/theme.css">
|
||||
<link rel="stylesheet" href="css/specific.css">
|
||||
</head>
|
||||
<body role="document">
|
||||
<div ng-controller="LoadScreenController" class="loader-wrapper {{loadScreen}}">
|
||||
<div class="loader"><img src="/css/img/loading.svg"></div>
|
||||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="navigation-bar-container col-sm-3 col-md-3 col-lg-3" ng-controller="AppListController">
|
||||
<ul class="side-nav-header nav nav-pills nav-stacked">
|
||||
<li class="navigation-header">
|
||||
<div class="btn-group">
|
||||
<div>
|
||||
<a href="#"><span class="ambari-header">Applications</span></a>
|
||||
</div>
|
||||
<div class="dropdown-toggle" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
|
||||
<span class="toggle-icon glyphicon glyphicon-menu-down"></span>
|
||||
</div>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#!/">Appstore</a></li>
|
||||
<li><a href="#!/new">Register App</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="side-nav-menu nav nav-pills nav-stacked">
|
||||
<li class="mainmenu-li" ng-repeat="yarnApp in appList">
|
||||
<a href="#!/app/{{yarnApp.id}}"><span class="glyphicon glyphicon-ok-sign"></span> {{yarnApp.name}}</a>
|
||||
<a ng-click="deleteApp(yarnApp.id,yarnApp.name)" class="icon-width"><span class="glyphicon glyphicon-remove pull-right"></span></a>
|
||||
<span class="navigation-menu-item">{{yarnApp.app}}</span>
|
||||
</li>
|
||||
</ul>
|
||||
<ul class="side-nav-footer nav nav-pills nav-stacked">
|
||||
<li class="navigation-footer">
|
||||
<a href="#" data-toggle="collapse-side-nav">
|
||||
<span class="navigation-icon fa fa-angle-double-left"></span>
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="col-xs-9 col-md-9 col-lg-9">
|
||||
<div data-ng-view></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script src="vendor/jquery/dist/jquery.min.js"></script>
|
||||
<script src="vendor/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="vendor/angular/angular.min.js"></script>
|
||||
<script src="vendor/angular-route/angular-route.min.js"></script>
|
||||
<script src="js/bootstrap-hadoop.min.js"></script>
|
||||
<script src="js/app.js"></script>
|
||||
<script src="js/controllers.js"></script>
|
||||
<script src="js/filters.js"></script>
|
||||
<script src="js/routes.js"></script>
|
||||
<script src="js/services.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,284 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
'use strict';
|
||||
|
||||
$(document).ready(function () {
|
||||
var $accordionToggler = $(this).find('[data-toggle="collapseAccordion"]');
|
||||
$accordionToggler.off('click').on('click', function (event) {
|
||||
var $this = $(this);
|
||||
$this.siblings('.panel-body').slideToggle(500);
|
||||
$this.children().children('.panel-toggle').toggleClass('fa-angle-down fa-angle-up');
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
});
|
||||
'use strict';
|
||||
|
||||
(function ($) {
|
||||
|
||||
/**
|
||||
* jQuery plugin for navigation bars
|
||||
* Usage:
|
||||
* <pre>
|
||||
* $('.navigation-bar').navigationBar();
|
||||
* </pre>
|
||||
*
|
||||
* @param {object} options see <code>$.fn.navigationBar.defaults</code>
|
||||
* @returns {$}
|
||||
*/
|
||||
|
||||
$.fn.navigationBar = function (options) {
|
||||
|
||||
var settings = $.extend({}, $.fn.navigationBar.defaults, options);
|
||||
|
||||
return this.each(function () {
|
||||
var _this = this;
|
||||
|
||||
var containerSelector = '.navigation-bar-container';
|
||||
var $navigationContainer = $(this).find(containerSelector);
|
||||
var $sideNavToggler = $(this).find('[data-toggle=' + settings.navBarToggleDataAttr + ']');
|
||||
var $subMenuToggler = $(this).find('[data-toggle=' + settings.subMenuNavToggleDataAttr + ']');
|
||||
var firstLvlMenuItemsSelector = '.side-nav-menu>li';
|
||||
var secondLvlMenuItemsSelector = '.side-nav-menu>li>ul>li';
|
||||
var $moreActions = $(this).find('.more-actions');
|
||||
var $dropdownMenu = $moreActions.children('.dropdown-menu');
|
||||
|
||||
$subMenuToggler.each(function (index, toggler) {
|
||||
return $(toggler).parent().addClass('has-sub-menu');
|
||||
});
|
||||
|
||||
if (settings.fitHeight) {
|
||||
$(this).addClass('navigation-bar-fit-height');
|
||||
|
||||
// make scrolling effect on side nav ONLY, i.e. not effected on ambari main contents
|
||||
$(this).find('.side-nav-menu').on('DOMMouseScroll mousewheel', function (ev) {
|
||||
var $this = $(this),
|
||||
scrollTop = this.scrollTop,
|
||||
scrollHeight = this.scrollHeight,
|
||||
height = $this.innerHeight(),
|
||||
delta = ev.originalEvent.wheelDelta,
|
||||
up = delta > 0;
|
||||
var prevent = function prevent() {
|
||||
ev.stopPropagation();
|
||||
ev.preventDefault();
|
||||
ev.returnValue = false;
|
||||
return false;
|
||||
};
|
||||
|
||||
if (!up && -delta > scrollHeight - height - scrollTop) {
|
||||
// Scrolling down, but this will take us past the bottom.
|
||||
$this.scrollTop(scrollHeight);
|
||||
return prevent();
|
||||
} else if (up && delta > scrollTop) {
|
||||
// Scrolling up, but this will take us past the top.
|
||||
$this.scrollTop(0);
|
||||
return prevent();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
//set main content left margin based on the width of side-nav
|
||||
var containerWidth = $navigationContainer.width();
|
||||
if (settings.moveLeftContent) {
|
||||
$(settings.content).css('margin-left', containerWidth);
|
||||
}
|
||||
if (settings.moveLeftFooter) {
|
||||
$(settings.footer).css('margin-left', containerWidth);
|
||||
}
|
||||
|
||||
function popStateHandler() {
|
||||
var path = window.location.pathname + window.location.hash;
|
||||
$navigationContainer.find('li a').each(function (index, link) {
|
||||
var $link = $(link);
|
||||
var href = $link.attr('data-href') || $link.attr('href');
|
||||
if (path.indexOf(href) !== -1 && ['', '#'].indexOf(href) === -1) {
|
||||
$link.parent().addClass('active');
|
||||
} else {
|
||||
$link.parent().removeClass('active');
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (settings.handlePopState) {
|
||||
popStateHandler();
|
||||
$(window).bind('popstate', popStateHandler);
|
||||
}
|
||||
|
||||
function clickHandler(el) {
|
||||
var $li = $(el).parent();
|
||||
var activeClass = settings.activeClass;
|
||||
|
||||
var activeMenuItems = firstLvlMenuItemsSelector + '.' + activeClass;
|
||||
var activeSubMenuItems = secondLvlMenuItemsSelector + '.' + activeClass;
|
||||
$navigationContainer.find(activeMenuItems).removeClass(activeClass);
|
||||
$navigationContainer.find(activeSubMenuItems).removeClass(activeClass);
|
||||
$li.addClass(activeClass);
|
||||
}
|
||||
|
||||
/**
|
||||
* Click on menu item
|
||||
*/
|
||||
$(firstLvlMenuItemsSelector + '>a').on('click', function () {
|
||||
clickHandler(this);
|
||||
});
|
||||
|
||||
/**
|
||||
* Click on sub menu item
|
||||
*/
|
||||
$(secondLvlMenuItemsSelector + '>a').on('click', function () {
|
||||
clickHandler(this);
|
||||
$(this).parent().parent().parent().addClass(settings.activeClass);
|
||||
});
|
||||
|
||||
/**
|
||||
* Slider for sub menu
|
||||
*/
|
||||
$subMenuToggler.off('click').on('click', function (event) {
|
||||
// ignore click if navigation-bar is collapsed
|
||||
if ($navigationContainer.hasClass('collapsed')) {
|
||||
return false;
|
||||
}
|
||||
var $this = $(this);
|
||||
$this.siblings('.sub-menu').slideToggle(600, function () {
|
||||
var $topMenuItem = $this.parent();
|
||||
var $subMenu = $topMenuItem.find('ul');
|
||||
return $subMenu.is(':visible') ? $topMenuItem.removeClass('collapsed') : $topMenuItem.addClass('collapsed');
|
||||
});
|
||||
$this.children('.toggle-icon').toggleClass(settings.menuLeftClass + ' ' + settings.menuDownClass);
|
||||
event.stopPropagation();
|
||||
return false;
|
||||
});
|
||||
|
||||
/**
|
||||
* Hovering effects for "more actions icon": "..."
|
||||
*/
|
||||
$(this).find('.mainmenu-li>a').hover(function () {
|
||||
var $moreIcon = $(this).siblings('.more-actions');
|
||||
if ($moreIcon.length && !$navigationContainer.hasClass('collapsed')) {
|
||||
$moreIcon.css('display', 'inline-block');
|
||||
}
|
||||
}, function () {
|
||||
var $moreIcon = $(this).siblings('.more-actions');
|
||||
if ($moreIcon.length && !$navigationContainer.hasClass('collapsed')) {
|
||||
$moreIcon.hide();
|
||||
}
|
||||
});
|
||||
$moreActions.hover(function () {
|
||||
$(this).css('display', 'inline-block');
|
||||
});
|
||||
if (settings.fitHeight) {
|
||||
$moreActions.on('click', function () {
|
||||
// set actions submenu position
|
||||
var $moreIcon = $(this);
|
||||
var $header = $('.side-nav-header');
|
||||
$dropdownMenu.css({
|
||||
top: $moreIcon.offset().top - $header.offset().top + 20 + 'px',
|
||||
left: $moreIcon.offset().left + 'px'
|
||||
});
|
||||
});
|
||||
}
|
||||
$dropdownMenu.on('click', function () {
|
||||
// some action was triggered, should hide this icon
|
||||
var moreIcon = $(this).parent();
|
||||
setTimeout(function () {
|
||||
moreIcon.hide();
|
||||
}, 1000);
|
||||
});
|
||||
$navigationContainer.children('.side-nav-menu').scroll(function () {
|
||||
$moreActions.removeClass('open');
|
||||
});
|
||||
|
||||
/**
|
||||
* Expand/collapse navigation bar
|
||||
*/
|
||||
$sideNavToggler.click(function () {
|
||||
|
||||
$navigationContainer.toggleClass('collapsed').promise().done(function () {
|
||||
var subMenuSelector = 'ul.sub-menu';
|
||||
var $subMenus = $navigationContainer.find(subMenuSelector);
|
||||
var $subMenuItems = $navigationContainer.find('.side-nav-menu>li');
|
||||
if ($navigationContainer.hasClass('collapsed')) {
|
||||
// set sub menu invisible when collapsed
|
||||
$subMenus.hide();
|
||||
$moreActions.hide();
|
||||
// set the hover effect when collapsed, should show sub-menu on hovering
|
||||
$subMenuItems.hover(function () {
|
||||
$(this).find(subMenuSelector).show();
|
||||
// set sub-menu position
|
||||
var $parent = $(this);
|
||||
var $header = $('.side-nav-header');
|
||||
if (settings.fitHeight) {
|
||||
$(this).find(subMenuSelector).css({
|
||||
position: 'fixed',
|
||||
top: $parent.offset().top - $header.offset().top + 'px',
|
||||
left: 50 + 'px'
|
||||
});
|
||||
}
|
||||
}, function () {
|
||||
$(this).find(subMenuSelector).hide();
|
||||
});
|
||||
} else {
|
||||
// keep showing all sub menu
|
||||
$subMenus.show().each(function (index, item) {
|
||||
return $(item).parent().removeClass('collapsed');
|
||||
});
|
||||
$subMenuItems.unbind('mouseenter mouseleave');
|
||||
$navigationContainer.find('.toggle-icon').removeClass(settings.menuLeftClass).addClass(settings.menuDownClass);
|
||||
// set sub-menu position
|
||||
if (settings.fitHeight) {
|
||||
$(_this).find(subMenuSelector).css({
|
||||
position: 'relative',
|
||||
top: 0,
|
||||
left: 0
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
$navigationContainer.on('transitionend', function () {
|
||||
//set main content left margin based on the width of side-nav
|
||||
var containerWidth = $navigationContainer.width();
|
||||
if (settings.moveLeftContent) {
|
||||
$(settings.content).css('margin-left', containerWidth);
|
||||
}
|
||||
if (settings.moveLeftFooter) {
|
||||
$(settings.footer).css('margin-left', containerWidth);
|
||||
}
|
||||
});
|
||||
$sideNavToggler.find('span').toggleClass(settings.collapseNavBarClass + ' ' + settings.expandNavBarClass);
|
||||
});
|
||||
return false;
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
$.fn.navigationBar.defaults = {
|
||||
handlePopState: true,
|
||||
fitHeight: false,
|
||||
content: '#main',
|
||||
footer: 'footer',
|
||||
moveLeftContent: true,
|
||||
moveLeftFooter: true,
|
||||
menuLeftClass: 'glyphicon-menu-right',
|
||||
menuDownClass: 'glyphicon-menu-down',
|
||||
collapseNavBarClass: 'fa-angle-double-left',
|
||||
expandNavBarClass: 'fa-angle-double-right',
|
||||
activeClass: 'active',
|
||||
navBarToggleDataAttr: 'collapse-side-nav',
|
||||
subMenuNavToggleDataAttr: 'collapse-sub-menu'
|
||||
};
|
||||
})(jQuery);
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
* 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.
|
||||
*/
|
||||
"use strict";$(document).ready(function(){$(this).find('[data-toggle="collapseAccordion"]').off("click").on("click",function(n){var l=$(this);return l.siblings(".panel-body").slideToggle(500),l.children().children(".panel-toggle").toggleClass("fa-angle-down fa-angle-up"),n.stopPropagation(),!1})});
|
||||
"use strict";!function(e){e.fn.navigationBar=function(n){var t=e.extend({},e.fn.navigationBar.defaults,n);return this.each(function(){function n(){var n=window.location.pathname+window.location.hash;i.find("li a").each(function(t,a){var s=e(a),i=s.attr("data-href")||s.attr("href");-1!==n.indexOf(i)&&-1===["","#"].indexOf(i)?s.parent().addClass("active"):s.parent().removeClass("active")})}function a(n){var a=e(n).parent(),s=t.activeClass,o=r+"."+s,l=f+"."+s;i.find(o).removeClass(s),i.find(l).removeClass(s),a.addClass(s)}var s=this,i=e(this).find(".navigation-bar-container"),o=e(this).find("[data-toggle="+t.navBarToggleDataAttr+"]"),l=e(this).find("[data-toggle="+t.subMenuNavToggleDataAttr+"]"),r=".side-nav-menu>li",f=".side-nav-menu>li>ul>li",c=e(this).find(".more-actions"),u=c.children(".dropdown-menu");l.each(function(n,t){return e(t).parent().addClass("has-sub-menu")}),t.fitHeight&&(e(this).addClass("navigation-bar-fit-height"),e(this).find(".side-nav-menu").on("DOMMouseScroll mousewheel",function(n){var t=e(this),a=this.scrollTop,s=this.scrollHeight,i=t.innerHeight(),o=n.originalEvent.wheelDelta,l=o>0,r=function(){return n.stopPropagation(),n.preventDefault(),n.returnValue=!1,!1};return!l&&-o>s-i-a?(t.scrollTop(s),r()):l&&o>a?(t.scrollTop(0),r()):void 0}));var d=i.width();t.moveLeftContent&&e(t.content).css("margin-left",d),t.moveLeftFooter&&e(t.footer).css("margin-left",d),t.handlePopState&&(n(),e(window).bind("popstate",n)),e(r+">a").on("click",function(){a(this)}),e(f+">a").on("click",function(){a(this),e(this).parent().parent().parent().addClass(t.activeClass)}),l.off("click").on("click",function(n){if(i.hasClass("collapsed"))return!1;var a=e(this);return a.siblings(".sub-menu").slideToggle(600,function(){var e=a.parent();return e.find("ul").is(":visible")?e.removeClass("collapsed"):e.addClass("collapsed")}),a.children(".toggle-icon").toggleClass(t.menuLeftClass+" "+t.menuDownClass),n.stopPropagation(),!1}),e(this).find(".mainmenu-li>a").hover(function(){var n=e(this).siblings(".more-actions");n.length&&!i.hasClass("collapsed")&&n.css("display","inline-block")},function(){var n=e(this).siblings(".more-actions");n.length&&!i.hasClass("collapsed")&&n.hide()}),c.hover(function(){e(this).css("display","inline-block")}),t.fitHeight&&c.on("click",function(){var n=e(this),t=e(".side-nav-header");u.css({top:n.offset().top-t.offset().top+20+"px",left:n.offset().left+"px"})}),u.on("click",function(){var n=e(this).parent();setTimeout(function(){n.hide()},1e3)}),i.children(".side-nav-menu").scroll(function(){c.removeClass("open")}),o.click(function(){return i.toggleClass("collapsed").promise().done(function(){var n=i.find("ul.sub-menu"),a=i.find(".side-nav-menu>li");i.hasClass("collapsed")?(n.hide(),c.hide(),a.hover(function(){e(this).find("ul.sub-menu").show();var n=e(this),a=e(".side-nav-header");t.fitHeight&&e(this).find("ul.sub-menu").css({position:"fixed",top:n.offset().top-a.offset().top+"px",left:"50px"})},function(){e(this).find("ul.sub-menu").hide()})):(n.show().each(function(n,t){return e(t).parent().removeClass("collapsed")}),a.unbind("mouseenter mouseleave"),i.find(".toggle-icon").removeClass(t.menuLeftClass).addClass(t.menuDownClass),t.fitHeight&&e(s).find("ul.sub-menu").css({position:"relative",top:0,left:0})),i.on("transitionend",function(){var n=i.width();t.moveLeftContent&&e(t.content).css("margin-left",n),t.moveLeftFooter&&e(t.footer).css("margin-left",n)}),o.find("span").toggleClass(t.collapseNavBarClass+" "+t.expandNavBarClass)}),!1})})},e.fn.navigationBar.defaults={handlePopState:!0,fitHeight:!1,content:"#main",footer:"footer",moveLeftContent:!0,moveLeftFooter:!0,menuLeftClass:"glyphicon-menu-right",menuDownClass:"glyphicon-menu-down",collapseNavBarClass:"fa-angle-double-left",expandNavBarClass:"fa-angle-double-right",activeClass:"active",navBarToggleDataAttr:"collapse-side-nav",subMenuNavToggleDataAttr:"collapse-sub-menu"}}(jQuery);
|
|
@ -0,0 +1,80 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<div class="container content">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<div class="form-group">
|
||||
<h1>Deploy Application</h1>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-2 col-md-2 col-lg-2">
|
||||
<img ng-src="{{details.icon}}" alt="" width="128" height="128" ng-if="details.icon != null" />
|
||||
</div>
|
||||
<div class="col-xs-10 col-md-10 col-lg-10">
|
||||
<div class="form-group">
|
||||
<h2>{{details.org}}/{{details.name}}</h2>
|
||||
{{details.desc}}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<div class="form-group">
|
||||
<label>Application Name</label>
|
||||
<input type=text name="name" class="form-control" ng-model="details.app.name" autofocus />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Queue</label>
|
||||
<input type=text name="queue" class="form-control" ng-model="details.app.queue" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12" ng-repeat="docker in details.app.components track by $index">
|
||||
<div class="panel">
|
||||
<div class="form-group">
|
||||
<label>Component {{docker.name}}</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Number of containers</label>
|
||||
<input type=text name="artifact_id" class="form-control" ng-model="docker.number_of_containers" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Environments</label>
|
||||
<textarea json-text name="env" class="form-control" ng-model="docker.configuration.env"/></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Properties</label>
|
||||
<textarea json-text name="properties" class="form-control" ng-model="docker.configuration.properties"/></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<p>
|
||||
<a class="btn btn-secondary" ng-click="launchApp(details.app)">LAUNCH</a>
|
||||
<a class="btn btn-secondary" href="/">CANCEL</a>
|
||||
<span class="infobox bg-info" ng-if="message">{{message}}</span>
|
||||
<span class="infobox bg-danger" ng-if="error">{{error}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,64 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<div class="container content">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<a ng-click="stopApp(appName)" class="btn btn-secondary"><span class="glyphicon glyphicon-stop"></span> Stop</a>
|
||||
<a ng-click="restartApp(appName)" class="btn btn-secondary"><span class="glyphicon glyphicon-refresh"></span> Start</a>
|
||||
<div style="display:inline-block;" ng-repeat="(key, value) in details.yarnfile.quicklinks">
|
||||
<a href="{{value}}" class="btn btn-secondary" ng-hide="checkServiceLink()"><span class="glyphicon glyphicon-new-window"></span> {{key}}</a>
|
||||
</div>
|
||||
{{details.yarnfile.state}}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12" ng-repeat="docker in details.yarnfile.components">
|
||||
<div class="panel">
|
||||
<h3>{{docker.name}}</h3>
|
||||
<p>Artifact: {{docker.artifact.id}}</p>
|
||||
<p>Number of containers: {{docker.number_of_containers}}</p>
|
||||
<p>CPU: {{docker.resource.cpus}}</p>
|
||||
<p>Memory: {{docker.resource.memory}}</p>
|
||||
<p>Environments
|
||||
<table class="table">
|
||||
<tbody class="table-striped">
|
||||
<tr ng-repeat="(key, value) in docker.configuration.env">
|
||||
<td>{{key}}</td><td>{{value}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</p>
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Hostname</th>
|
||||
<th>Container ID</th>
|
||||
<th>Launch Time</th>
|
||||
<th>State</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody class="table-striped">
|
||||
<tr ng-repeat="container in docker.containers">
|
||||
<td>{{container.bare_host}}</td>
|
||||
<td><a href="http://{{container.bare_host}}:8042/terminal/terminal.template?container={{container.id}}" target="_blank">{{container.id}}</a></td>
|
||||
<td>{{container.launch_time | date:'yyyy-MM-dd HH:mm:ss Z'}}</td>
|
||||
<td>{{container.state}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,52 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<div class="toparea"><div class="pattern-wrapper"></div></div>
|
||||
<div class="container content toparea pattern-wrapper">
|
||||
<form>
|
||||
<div class="input-group input-group-lg">
|
||||
<div class="input-group-addon">
|
||||
<span class="glyphicon glyphicon-search" id="search"></span>
|
||||
</div>
|
||||
<input type="text" class="form-control" placeholder="Search for applications from HDFS" aria-describedby="search" ng-model="searchText" ng-change="change(text)" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<p></p>
|
||||
<p class="recommended">Recommended</p>
|
||||
|
||||
<div ng-repeat="a in appStore" ng-if="$index % 3 == 0" class="row">
|
||||
<div ng-repeat="i in [$index, $index + 1, $index + 2]"
|
||||
ng-if="appStore[i] != null" class="col-xs-4 col-md-4 col-lg-4">
|
||||
<div class="tile mdl-shadow-4dp">
|
||||
<img ng-src="{{appStore[i].icon}}" alt="" width="128" height="128" ng-if="appStore[i] != null" />
|
||||
<div class="card-title">
|
||||
<h3>{{appStore[i].org}}</h3>
|
||||
<h2>{{appStore[i].name}}</h2>
|
||||
</div>
|
||||
<div class="card-desc">
|
||||
<p>{{appStore[i].desc}}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-footer mdl-shadow-4dp">
|
||||
<div class="pull-left">
|
||||
<!-- <span class="glyphicon glyphicon-thumbs-up"></span> {{appStore[i].like | counterValue}} -->
|
||||
<span class="glyphicon glyphicon-cloud-download"></span> {{appStore[i].download | counterValue}}
|
||||
</div>
|
||||
<div class="pull-right">
|
||||
<button class="btn btn-secondary" ng-click="deployApp(appStore[i].id)">DEPLOY</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,111 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<div class="container content">
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<div class="form-group">
|
||||
<h1>Register Application</h1>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Organization Name</label>
|
||||
<input type=text name="org" class="form-control" ng-model="details.organization" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Application Name</label>
|
||||
<input type=text name="name" class="form-control" ng-model="details.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Version</label>
|
||||
<input type=text name="version" class="form-control" ng-model="details.version" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Description</label>
|
||||
<textarea name="desc" class="form-control" ng-model="details.description"></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Quick Link</label>
|
||||
<textarea json-text name="quicklink" class="form-control" ng-model="details.quicklinks"/></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Icon</label>
|
||||
<input type=text name="icon" class="form-control" ng-model="details.icon" />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12" ng-repeat="docker in details.components track by $index">
|
||||
<div class="panel">
|
||||
<div class="pull-right">
|
||||
<a class="btn btn-secondary" ng-click="remove($index)">-</a>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Component Name</label>
|
||||
<input type=text name="name" class="form-control" ng-model="docker.name" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Artifact</label>
|
||||
<input type=text name="artifact_id" class="form-control" ng-model="docker.artifact.id" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Number of containers</label>
|
||||
<input type=text name="artifact_id" class="form-control" ng-model="docker.number_of_containers" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Launch Command</label>
|
||||
<input type=text name="launch_command" class="form-control" ng-model="docker.launch_command" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>CPU</label>
|
||||
<input type=text name="cpus" class="form-control" ng-model="docker.resource.cpus" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Memory</label>
|
||||
<input type=text name="memory" class="form-control" ng-model="docker.resource.memory" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="checkbox" ng-attr-id="{{'checkbox-priv-' + $index}}" ng-model="docker.run_privileged_container">
|
||||
<label for="checkbox-priv-{{$index}}"> Privileged Container</label>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Dependencies</label>
|
||||
<input json-text type=text name="dependencies" class="form-control" ng-model="docker.dependencies" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Placement Policy</label>
|
||||
<input type=text name="placement" class="form-control" ng-model="docker.placement_policy.constraints" />
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Environments</label>
|
||||
<textarea json-text name="env" class="form-control" ng-model="docker.configuration.env"/></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>Properties</label>
|
||||
<textarea json-text name="properties" class="form-control" ng-model="docker.configuration.properties"/></textarea>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<br>
|
||||
<div class="row">
|
||||
<div class="col-xs-12 col-md-12 col-lg-12">
|
||||
<p>
|
||||
<a class="btn btn-secondary" ng-click="add()">+</a>
|
||||
<a class="btn btn-secondary" ng-click="save()">Publish</a>
|
||||
<span class="infobox bg-info" ng-if="message">{{message}}</span>
|
||||
<span class="infobox bg-danger" ng-if="error">{{error}}</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
|
@ -0,0 +1,649 @@
|
|||
<!---
|
||||
Licensed 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. See accompanying LICENSE file.
|
||||
-->
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="">
|
||||
<meta name="author" content="">
|
||||
|
||||
<title>Theme Template for Bootstrap</title>
|
||||
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="vendor/bootstrap/dist/css/bootstrap.min.css" rel="stylesheet">
|
||||
<!-- Bootstrap theme -->
|
||||
<link href="vendor/bootstrap/dist/css/bootstrap-theme.min.css" rel="stylesheet">
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="css/theme.css" rel="stylesheet">
|
||||
<link href="css/bootstrap-hadoop.min.css" rel="stylesheet">
|
||||
|
||||
</head>
|
||||
|
||||
<body role="document">
|
||||
|
||||
<!-- Fixed navbar -->
|
||||
<div class="navbar navbar-inverse navbar-fixed-top" role="navigation">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Bootstrap theme</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="index.html">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="container theme-showcase" role="main">
|
||||
|
||||
<!-- Main jumbotron for a primary marketing message or call to action -->
|
||||
<div class="jumbotron">
|
||||
<h1>Hello, world!</h1>
|
||||
|
||||
<p>This is a template for a simple marketing or informational website. It includes a large callout called a
|
||||
jumbotron and three supporting pieces of content. Use it as a starting point to create something more
|
||||
unique.</p>
|
||||
|
||||
<p><a href="#" class="btn btn-primary btn-lg" role="button">Learn more »</a></p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Buttons</h1>
|
||||
</div>
|
||||
<p>
|
||||
<button type="button" class="btn btn-lg btn-default">Default</button>
|
||||
<button type="button" class="btn btn-lg btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-lg btn-success">Success</button>
|
||||
<button type="button" class="btn btn-lg btn-info">Info</button>
|
||||
<button type="button" class="btn btn-lg btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-lg btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-lg btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default">Default</button>
|
||||
<button type="button" class="btn btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-success">Success</button>
|
||||
<button type="button" class="btn btn-info">Info</button>
|
||||
<button type="button" class="btn btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-sm btn-default">Default</button>
|
||||
<button type="button" class="btn btn-sm btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-sm btn-success">Success</button>
|
||||
<button type="button" class="btn btn-sm btn-info">Info</button>
|
||||
<button type="button" class="btn btn-sm btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-sm btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-sm btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-xs btn-default">Default</button>
|
||||
<button type="button" class="btn btn-xs btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-xs btn-success">Success</button>
|
||||
<button type="button" class="btn btn-xs btn-info">Info</button>
|
||||
<button type="button" class="btn btn-xs btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-xs btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-xs btn-link">Link</button>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Tables</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Larry</td>
|
||||
<td>the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Larry</td>
|
||||
<td>the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="2">1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@TwBootstrap</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td colspan="2">Larry the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td colspan="2">Larry the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Thumbnails</h1>
|
||||
</div>
|
||||
<img data-src="holder.js/200x200" class="img-thumbnail"
|
||||
alt="A generic square placeholder image with a white border around it, making it resemble a photograph taken with an old instant camera">
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Labels</h1>
|
||||
</div>
|
||||
<h1>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h1>
|
||||
|
||||
<h2>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h2>
|
||||
|
||||
<h3>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h3>
|
||||
<h4>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h4>
|
||||
<h5>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h5>
|
||||
<h6>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h6>
|
||||
|
||||
<p>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Badges</h1>
|
||||
</div>
|
||||
<p>
|
||||
<a href="#">Inbox <span class="badge">42</span></a>
|
||||
</p>
|
||||
<ul class="nav nav-pills">
|
||||
<li class="active"><a href="#">Home <span class="badge">42</span></a></li>
|
||||
<li><a href="#">Profile</a></li>
|
||||
<li><a href="#">Messages <span class="badge">3</span></a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Dropdown menus</h1>
|
||||
</div>
|
||||
<div class="dropdown theme-dropdown clearfix">
|
||||
<a id="dropdownMenu1" href="#" role="button" class="sr-only dropdown-toggle" data-toggle="dropdown">Dropdown <span
|
||||
class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu" aria-labelledby="dropdownMenu1">
|
||||
<li class="active" role="presentation"><a role="menuitem" tabindex="-1" href="#">Action</a></li>
|
||||
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Another action</a></li>
|
||||
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Something else here</a></li>
|
||||
<li role="presentation" class="divider"></li>
|
||||
<li role="presentation"><a role="menuitem" tabindex="-1" href="#">Separated link</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Navs</h1>
|
||||
</div>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#">Profile</a></li>
|
||||
<li><a href="#">Messages</a></li>
|
||||
</ul>
|
||||
<ul class="nav nav-pills">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#">Profile</a></li>
|
||||
<li><a href="#">Messages</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Navbars</h1>
|
||||
</div>
|
||||
|
||||
<div class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Project name</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="navbar navbar-inverse">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Project name</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" role="menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!--/.nav-collapse -->
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Alerts</h1>
|
||||
</div>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<strong>Well done!</strong> You successfully read this important alert message.
|
||||
</div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
<strong>Heads up!</strong> This alert needs your attention, but it's not super important.
|
||||
</div>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<strong>Warning!</strong> Best check yo self, you're not looking too good.
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<strong>Oh snap!</strong> Change a few things up and try submitting again.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Progress bars</h1>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100"
|
||||
style="width: 60%;"><span class="sr-only">60% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 40%"><span class="sr-only">40% Complete (success)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 20%"><span class="sr-only">20% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete (warning)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 80%"><span class="sr-only">80% Complete (danger)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="60" aria-valuemin="0"
|
||||
aria-valuemax="100" style="width: 60%"><span class="sr-only">100% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 35%"><span
|
||||
class="sr-only">35% Complete (success)</span></div>
|
||||
<div class="progress-bar progress-bar-warning" style="width: 20%"><span
|
||||
class="sr-only">20% Complete (warning)</span></div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: 10%"><span class='sr-only'>10% Complete (danger)</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>List groups</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">Cras justo odio</li>
|
||||
<li class="list-group-item">Dapibus ac facilisis in</li>
|
||||
<li class="list-group-item">Morbi leo risus</li>
|
||||
<li class="list-group-item">Porta ac consectetur ac</li>
|
||||
<li class="list-group-item">Vestibulum at eros</li>
|
||||
</ul>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item active">
|
||||
Cras justo odio
|
||||
</a>
|
||||
<a href="#" class="list-group-item">Dapibus ac facilisis in</a>
|
||||
<a href="#" class="list-group-item">Morbi leo risus</a>
|
||||
<a href="#" class="list-group-item">Porta ac consectetur ac</a>
|
||||
<a href="#" class="list-group-item">Vestibulum at eros</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item active">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget
|
||||
risus varius blandit.</p>
|
||||
</a>
|
||||
<a href="#" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget
|
||||
risus varius blandit.</p>
|
||||
</a>
|
||||
<a href="#" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget
|
||||
risus varius blandit.</p>
|
||||
</a>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Panels</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.col-sm-4 -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Wells</h1>
|
||||
</div>
|
||||
<div class="well">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non
|
||||
magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque
|
||||
nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi
|
||||
erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p>
|
||||
</div>
|
||||
|
||||
|
||||
</div>
|
||||
<!-- /container -->
|
||||
|
||||
|
||||
<!-- Bootstrap core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script src="vendor/jquery/dist/jquery.min.js"></script>
|
||||
<script src="vendor/bootstrap/dist/js/bootstrap.min.js"></script>
|
||||
<script src="js/bootstrap-hadoop.min.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -0,0 +1,104 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.application;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.apache.solr.client.solrj.SolrServerException;
|
||||
import org.apache.solr.client.solrj.embedded.EmbeddedSolrServer;
|
||||
import org.apache.solr.client.solrj.request.CoreAdminRequest;
|
||||
import org.apache.solr.core.NodeConfig;
|
||||
import org.apache.solr.core.SolrResourceLoader;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
|
||||
/**
|
||||
* Embedded solr server factory class for unit tests.
|
||||
*/
|
||||
public final class EmbeddedSolrServerFactory {
|
||||
|
||||
private EmbeddedSolrServerFactory() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans the given solrHome directory and creates a new EmbeddedSolrServer.
|
||||
*
|
||||
* @param solrHome
|
||||
* the Solr home directory to use
|
||||
* @param configSetHome
|
||||
* the directory containing config sets
|
||||
* @param coreName
|
||||
* the name of the core, must have a matching directory in configHome
|
||||
*
|
||||
* @return an EmbeddedSolrServer with a core created for the given coreName
|
||||
* @throws IOException
|
||||
*/
|
||||
public static SolrClient create(final String solrHome,
|
||||
final String configSetHome, final String coreName)
|
||||
throws IOException, SolrServerException {
|
||||
return create(solrHome, configSetHome, coreName, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param solrHome
|
||||
* the Solr home directory to use
|
||||
* @param configSetHome
|
||||
* the directory containing config sets
|
||||
* @param coreName
|
||||
* the name of the core, must have a matching directory in configHome
|
||||
* @param cleanSolrHome
|
||||
* if true the directory for solrHome will be deleted and re-created
|
||||
* if it already exists
|
||||
*
|
||||
* @return an EmbeddedSolrServer with a core created for the given coreName
|
||||
* @throws IOException
|
||||
*/
|
||||
public static SolrClient create(final String solrHome,
|
||||
final String configSetHome, final String coreName,
|
||||
final boolean cleanSolrHome) throws IOException, SolrServerException {
|
||||
|
||||
final File solrHomeDir = new File(solrHome);
|
||||
if (solrHomeDir.exists()) {
|
||||
FileUtils.deleteDirectory(solrHomeDir);
|
||||
solrHomeDir.mkdirs();
|
||||
} else {
|
||||
solrHomeDir.mkdirs();
|
||||
}
|
||||
|
||||
final SolrResourceLoader loader = new SolrResourceLoader(
|
||||
solrHomeDir.toPath());
|
||||
final Path configSetPath = Paths.get(configSetHome).toAbsolutePath();
|
||||
|
||||
final NodeConfig config = new NodeConfig.NodeConfigBuilder(
|
||||
"embeddedSolrServerNode", loader)
|
||||
.setConfigSetBaseDirectory(configSetPath.toString()).build();
|
||||
|
||||
final EmbeddedSolrServer embeddedSolrServer = new EmbeddedSolrServer(config,
|
||||
coreName);
|
||||
|
||||
final CoreAdminRequest.Create createRequest = new CoreAdminRequest.Create();
|
||||
createRequest.setCoreName(coreName);
|
||||
createRequest.setConfigSet(coreName);
|
||||
embeddedSolrServer.request(createRequest);
|
||||
|
||||
return embeddedSolrServer;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.application;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppStoreEntry;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.Application;
|
||||
import org.apache.solr.client.solrj.SolrClient;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.api.mockito.PowerMockito;
|
||||
import static org.powermock.api.mockito.PowerMockito.when;
|
||||
import static org.powermock.api.support.membermodification.MemberMatcher.method;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for AppCatalogSolrClient.
|
||||
*/
|
||||
public class TestAppCatalogSolrClient {
|
||||
|
||||
static final String CONFIGSET_DIR = "src/test/resources/configsets";
|
||||
private static SolrClient solrClient;
|
||||
private static AppCatalogSolrClient spy;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
String targetLocation = EmbeddedSolrServerFactory.class
|
||||
.getProtectionDomain().getCodeSource().getLocation().getFile() + "/..";
|
||||
|
||||
String solrHome = targetLocation + "/solr";
|
||||
solrClient = EmbeddedSolrServerFactory.create(solrHome, CONFIGSET_DIR,
|
||||
"exampleCollection");
|
||||
spy = PowerMockito.spy(new AppCatalogSolrClient());
|
||||
when(spy, method(AppCatalogSolrClient.class, "getSolrClient"))
|
||||
.withNoArguments().thenReturn(solrClient);
|
||||
}
|
||||
|
||||
@After
|
||||
public void teardown() throws Exception {
|
||||
try {
|
||||
solrClient.close();
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister() throws Exception {
|
||||
Application example = new Application();
|
||||
example.setOrganization("jenkins-ci.org");
|
||||
example.setName("jenkins");
|
||||
example.setDescription("World leading open source automation system.");
|
||||
example.setIcon("/css/img/feather.png");
|
||||
spy.register(example);
|
||||
List<AppStoreEntry> apps = spy.getRecommendedApps();
|
||||
assertEquals(1, apps.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
Application example = new Application();
|
||||
example.setOrganization("jenkins-ci.org");
|
||||
example.setName("jenkins");
|
||||
example.setDescription("World leading open source automation system.");
|
||||
example.setIcon("/css/img/feather.png");
|
||||
spy.register(example);
|
||||
List<AppStoreEntry> results = spy.search("name_s:jenkins");
|
||||
int expected = 1;
|
||||
int actual = results.size();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNotFoundSearch() throws Exception {
|
||||
Application example = new Application();
|
||||
example.setOrganization("jenkins-ci.org");
|
||||
example.setName("jenkins");
|
||||
example.setDescription("World leading open source automation system.");
|
||||
example.setIcon("/css/img/feather.png");
|
||||
spy.register(example);
|
||||
List<AppStoreEntry> results = spy.search("name_s:abc");
|
||||
int expected = 0;
|
||||
int actual = results.size();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRecommendedApps() throws Exception {
|
||||
List<AppStoreEntry> expected = spy.getRecommendedApps();
|
||||
List<AppStoreEntry> actual = spy.getRecommendedApps();
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,138 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.service.api.records.Component;
|
||||
import org.apache.hadoop.yarn.service.api.records.Container;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for AppDetailsController.
|
||||
*/
|
||||
public class AppDetailsControllerTest {
|
||||
|
||||
private AppDetailsController controller;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.controller = new AppDetailsController();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetDetails() throws Exception {
|
||||
String id = "application 1";
|
||||
AppDetailsController ac = Mockito.mock(AppDetailsController.class);
|
||||
|
||||
AppEntry actual = new AppEntry();
|
||||
actual.setName(id);
|
||||
when(ac.getDetails(id)).thenReturn(actual);
|
||||
final AppEntry result = ac.getDetails(id);
|
||||
assertEquals(result, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetStatus() throws Exception {
|
||||
String id = "application 1";
|
||||
AppDetailsController ac = Mockito.mock(AppDetailsController.class);
|
||||
|
||||
Service yarnfile = new Service();
|
||||
Component comp = new Component();
|
||||
Container c = new Container();
|
||||
c.setId("container-1");
|
||||
List<Container> containers = new ArrayList<Container>();
|
||||
containers.add(c);
|
||||
comp.setContainers(containers);
|
||||
yarnfile.addComponent(comp);
|
||||
AppEntry actual = new AppEntry();
|
||||
actual.setName(id);
|
||||
actual.setYarnfile(yarnfile);
|
||||
when(ac.getStatus(id)).thenReturn(actual);
|
||||
final AppEntry result = ac.getStatus(id);
|
||||
assertEquals(result, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStopApp() throws Exception {
|
||||
String id = "application 1";
|
||||
AppDetailsController ac = Mockito.mock(AppDetailsController.class);
|
||||
|
||||
Service yarnfile = new Service();
|
||||
Component comp = new Component();
|
||||
Container c = new Container();
|
||||
c.setId("container-1");
|
||||
List<Container> containers = new ArrayList<Container>();
|
||||
containers.add(c);
|
||||
comp.setContainers(containers);
|
||||
yarnfile.addComponent(comp);
|
||||
Response expected = Response.ok().build();
|
||||
when(ac.stopApp(id)).thenReturn(Response.ok().build());
|
||||
final Response actual = ac.stopApp(id);
|
||||
assertEquals(expected.getStatus(), actual.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRestartApp() throws Exception {
|
||||
String id = "application 1";
|
||||
AppDetailsController ac = Mockito.mock(AppDetailsController.class);
|
||||
|
||||
Service yarnfile = new Service();
|
||||
Component comp = new Component();
|
||||
Container c = new Container();
|
||||
c.setId("container-1");
|
||||
List<Container> containers = new ArrayList<Container>();
|
||||
containers.add(c);
|
||||
comp.setContainers(containers);
|
||||
yarnfile.addComponent(comp);
|
||||
Response expected = Response.ok().build();
|
||||
when(ac.restartApp(id)).thenReturn(Response.ok().build());
|
||||
final Response actual = ac.restartApp(id);
|
||||
assertEquals(expected.getStatus(), actual.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathAnnotation() throws Exception {
|
||||
assertNotNull(this.controller.getClass()
|
||||
.getAnnotations());
|
||||
assertThat("The controller has the annotation Path",
|
||||
this.controller.getClass()
|
||||
.isAnnotationPresent(Path.class));
|
||||
|
||||
final Path path = this.controller.getClass()
|
||||
.getAnnotation(Path.class);
|
||||
assertThat("The path is /app_details", path.value(),
|
||||
is("/app_details"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppEntry;
|
||||
import org.apache.hadoop.yarn.service.api.records.Service;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit test for AppListController.
|
||||
*/
|
||||
public class AppListControllerTest {
|
||||
|
||||
private AppListController controller;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.controller = new AppListController();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetList() throws Exception {
|
||||
AppListController ac = Mockito.mock(AppListController.class);
|
||||
|
||||
List<AppEntry> actual = new ArrayList<AppEntry>();
|
||||
when(ac.getList()).thenReturn(actual);
|
||||
final List<AppEntry> result = ac.getList();
|
||||
assertEquals(result, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDelete() throws Exception {
|
||||
String id = "application 1";
|
||||
AppListController ac = Mockito.mock(AppListController.class);
|
||||
|
||||
Response expected = Response.ok().build();
|
||||
when(ac.delete(id, id)).thenReturn(Response.ok().build());
|
||||
final Response actual = ac.delete(id, id);
|
||||
assertEquals(expected.getStatus(), actual.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDeploy() throws Exception {
|
||||
String id = "application 1";
|
||||
AppListController ac = Mockito.mock(AppListController.class);
|
||||
Service service = new Service();
|
||||
Response expected = Response.ok().build();
|
||||
when(ac.deploy(id, service)).thenReturn(Response.ok().build());
|
||||
final Response actual = ac.deploy(id, service);
|
||||
assertEquals(expected.getStatus(), actual.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathAnnotation() throws Exception {
|
||||
assertNotNull(this.controller.getClass()
|
||||
.getAnnotations());
|
||||
assertThat("The controller has the annotation Path",
|
||||
this.controller.getClass().isAnnotationPresent(Path.class));
|
||||
|
||||
final Path path = this.controller.getClass()
|
||||
.getAnnotation(Path.class);
|
||||
assertThat("The path is /app_list", path.value(), is("/app_list"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,97 @@
|
|||
/*
|
||||
* 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.hadoop.yarn.appcatalog.controller;
|
||||
|
||||
import org.apache.hadoop.yarn.appcatalog.model.AppStoreEntry;
|
||||
import org.apache.hadoop.yarn.appcatalog.model.Application;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import javax.ws.rs.Path;
|
||||
import javax.ws.rs.core.Response;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.core.Is.is;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Unit tests for AppStoreController.
|
||||
*/
|
||||
public class AppStoreControllerTest {
|
||||
|
||||
private AppStoreController controller;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
this.controller = new AppStoreController();
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetRecommended() throws Exception {
|
||||
AppStoreController ac = Mockito.mock(AppStoreController.class);
|
||||
List<AppStoreEntry> actual = new ArrayList<AppStoreEntry>();
|
||||
when(ac.get()).thenReturn(actual);
|
||||
final List<AppStoreEntry> result = ac.get();
|
||||
assertEquals(result, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearch() throws Exception {
|
||||
String keyword = "jenkins";
|
||||
AppStoreController ac = Mockito.mock(AppStoreController.class);
|
||||
List<AppStoreEntry> expected = new ArrayList<AppStoreEntry>();
|
||||
when(ac.search(keyword)).thenReturn(expected);
|
||||
final List<AppStoreEntry> actual = ac.search(keyword);
|
||||
assertEquals(expected, actual);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegister() throws Exception {
|
||||
AppStoreController ac = Mockito.mock(AppStoreController.class);
|
||||
Application app = new Application();
|
||||
app.setName("jenkins");
|
||||
app.setOrganization("jenkins.org");
|
||||
app.setDescription("This is a description");
|
||||
app.setIcon("/css/img/feather.png");
|
||||
Response expected = Response.ok().build();
|
||||
when(ac.register(app)).thenReturn(Response.ok().build());
|
||||
final Response actual = ac.register(app);
|
||||
assertEquals(expected.getStatus(), actual.getStatus());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPathAnnotation() throws Exception {
|
||||
assertNotNull(this.controller.getClass()
|
||||
.getAnnotations());
|
||||
assertThat("The controller has the annotation Path",
|
||||
this.controller.getClass()
|
||||
.isAnnotationPresent(Path.class));
|
||||
|
||||
final Path path = this.controller.getClass()
|
||||
.getAnnotation(Path.class);
|
||||
assertThat("The path is /app_store", path.value(), is("/app_store"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,249 @@
|
|||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
describe('Controller tests', function () {
|
||||
|
||||
// Unit test for listing, and start/stop applications.
|
||||
describe('AppListController', function() {
|
||||
var scope, ctrl, http, httpBackend;
|
||||
|
||||
beforeEach(module('app'));
|
||||
beforeEach(inject(function ($controller, $rootScope, $http, $httpBackend) {
|
||||
scope = $rootScope.$new();
|
||||
rootScope = $rootScope;
|
||||
http = $http;
|
||||
httpBackend = $httpBackend;
|
||||
ctrl = $controller('AppListController', {$scope: scope});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
httpBackend.verifyNoOutstandingExpectation();
|
||||
httpBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
it('should contain appList', function () {
|
||||
httpBackend.expectGET('/v1/app_list').respond(200, [{id:"jenkins",name:"jenkins",app:"",yarnfile:{}}]);
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.flush();
|
||||
expect(scope.appList.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should test to delete app', function () {
|
||||
httpBackend.expectGET('/v1/app_list').respond(200, [{id:"jenkins",name:"jenkins",app:"",yarnfile:{}}]);
|
||||
httpBackend.expectDELETE('/v1/app_list/jenkins/jenkins').respond(200, {data:"Application Deleted."});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
spyOn(rootScope, '$emit');
|
||||
scope.$apply(function() {
|
||||
scope.deleteApp("jenkins","jenkins");
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(rootScope.$emit).toHaveBeenCalledWith('RefreshAppList', {});
|
||||
});
|
||||
|
||||
it('should test to refresh appList', function() {
|
||||
spyOn(rootScope, '$emit');
|
||||
httpBackend.expectGET('/v1/app_list').respond(200, [{id:"jenkins",name:"jenkins",app:"",yarnfile:{}}]);
|
||||
httpBackend.expectGET('/v1/app_list').respond(200, [{id:"jenkins",name:"jenkins",app:"",yarnfile:{}}]);
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
scope.$apply(function() {
|
||||
scope.refreshList();
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(rootScope.$emit).toHaveBeenCalledWith('hideLoadScreen', {});
|
||||
})
|
||||
});
|
||||
|
||||
// Unit test for inspect YARN application details.
|
||||
describe('AppDetailsController', function() {
|
||||
var scope, ctrl, http, routeParams, httpBackend;
|
||||
|
||||
beforeEach(module('app'));
|
||||
beforeEach(inject(function ($controller, $rootScope, $http, $routeParams, $httpBackend) {
|
||||
scope = $rootScope.$new();
|
||||
rootScope = $rootScope;
|
||||
http = $http;
|
||||
routeParams = $routeParams;
|
||||
httpBackend = $httpBackend;
|
||||
ctrl = $controller('AppDetailsController', {$scope: scope});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
httpBackend.verifyNoOutstandingExpectation();
|
||||
httpBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
it('should contain unknown state', function () {
|
||||
httpBackend.expectGET('/v1/app_details/config/undefined').respond(200, {"yarnfile":{"state":"UNKNOWN","components":[]}});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.flush();
|
||||
expect(scope.details.yarnfile.state).toBe("UNKNOWN");
|
||||
});
|
||||
|
||||
it('should run test to refrshed details', function () {
|
||||
httpBackend.expectGET('/v1/app_details/config/undefined').respond(200, {"yarnfile":{"state":"UNKNOWN","components":[]}});
|
||||
httpBackend.expectGET('/v1/app_details/status/aabbccdd').respond(200, {yarnfile:{state: "ACCEPTED", components:[]}});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
scope.$apply(function() {
|
||||
routeParams.id = "aabbccdd";
|
||||
scope.appName = "aabbccdd";
|
||||
scope.refreshAppDetails();
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.details.yarnfile.state).toBe("ACCEPTED");
|
||||
});
|
||||
|
||||
it('should run test to restart app', function () {
|
||||
httpBackend.expectGET('/v1/app_details/config/undefined').respond(200, {"yarnfile":{"state":"UNKNOWN","components":[]}});
|
||||
httpBackend.expectPOST('/v1/app_details/restart/aabbccdd').respond(200, {yarnfile:{state: "ACCEPTED", components:[]}});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.expectGET('/v1/app_details/status/undefined').respond(200, {yarnfile:{state: "ACCEPTED", components:[]}});
|
||||
scope.$apply(function() {
|
||||
scope.restartApp("aabbccdd");
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.details.yarnfile.components).toBe();
|
||||
});
|
||||
|
||||
it('should run test to stop app', function () {
|
||||
httpBackend.expectGET('/v1/app_details/config/undefined').respond(200, {"yarnfile":{"state":"UNKNOWN","components":[]}});
|
||||
httpBackend.expectPOST('/v1/app_details/stop/aabbccdd').respond(200, {yarnfile:{state: "STOPPED", components:[]}});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.expectGET('/v1/app_details/status/undefined').respond(200, {yarnfile:{state: "ACCEPTED", components:[]}});
|
||||
scope.$apply(function() {
|
||||
scope.stopApp("aabbccdd");
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.details.yarnfile.components).toBe();
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Unit test for deploying app, and search for apps from Yarn Appstore.
|
||||
describe('AppStoreController', function() {
|
||||
var scope, ctrl, http, httpBackend;
|
||||
|
||||
beforeEach(module('app'));
|
||||
beforeEach(inject(function ($controller, $rootScope, $http, $httpBackend) {
|
||||
scope = $rootScope.$new();
|
||||
http = $http;
|
||||
httpBackend = $httpBackend;
|
||||
ctrl = $controller('AppStoreController', {$scope: scope});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
httpBackend.verifyNoOutstandingExpectation();
|
||||
httpBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
it('should contain appStore', function () {
|
||||
httpBackend.expectGET('/v1/app_store/recommended').respond(200, "");
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.flush();
|
||||
expect(scope.appStore.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should run test to deploy app', function() {
|
||||
httpBackend.expectGET('/v1/app_store/recommended').respond(200, "");
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.flush();
|
||||
scope.$apply(function() {
|
||||
scope.deployApp("aabbccdd");
|
||||
});
|
||||
expect(scope.appStore.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should run test to search for apps', function() {
|
||||
httpBackend.expectGET('/v1/app_store/recommended').respond(200, "");
|
||||
httpBackend.expectGET('/v1/app_store/search?q=aabbccdd').respond(204, {data:'ACCEPTED'});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
scope.$apply(function() {
|
||||
scope.searchText = "aabbccdd";
|
||||
scope.change("aabbccdd");
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.appStore.data).toBe('ACCEPTED');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
// Unit test cases for creating a new YARN application.
|
||||
describe('NewAppController', function() {
|
||||
var scope, ctrl, http, httpBackend;
|
||||
|
||||
beforeEach(module('app'));
|
||||
beforeEach(inject(function ($controller, $rootScope, $http, $httpBackend) {
|
||||
scope = $rootScope.$new();
|
||||
http = $http;
|
||||
httpBackend = $httpBackend;
|
||||
ctrl = $controller('NewAppController', {$scope: scope});
|
||||
}));
|
||||
|
||||
afterEach(function() {
|
||||
httpBackend.verifyNoOutstandingExpectation();
|
||||
httpBackend.verifyNoOutstandingRequest();
|
||||
});
|
||||
|
||||
it('should contain details', function () {
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
httpBackend.flush();
|
||||
expect(scope.details.name).toBe("");
|
||||
});
|
||||
|
||||
it('should run test to register data to backend', function() {
|
||||
httpBackend.expectPOST('/v1/app_store/register').respond(204, {data:'ACCEPTED'});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
scope.$apply(function() {
|
||||
scope.save();
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.message).toEqual("Application published successfully.");
|
||||
});
|
||||
|
||||
it('should run test to fail register data to backend', function() {
|
||||
httpBackend.expectPOST('/v1/app_store/register').respond(500, {data:'INTERNAL SERVER ERROR'});
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
scope.$apply(function() {
|
||||
scope.save();
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.error).toEqual("Error in registering application configuration.");
|
||||
});
|
||||
|
||||
it('should run test to add more component to details', function() {
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
expect(scope.details.components.length).toEqual(1);
|
||||
scope.$apply(function() {
|
||||
scope.add();
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.details.components.length).toEqual(2);
|
||||
});
|
||||
|
||||
it('should run test to remove second component', function() {
|
||||
httpBackend.expectGET('partials/home.html').respond(200, "");
|
||||
expect(scope.details.components.length).toEqual(1);
|
||||
scope.$apply(function() {
|
||||
scope.add();
|
||||
scope.remove(1);
|
||||
});
|
||||
httpBackend.flush();
|
||||
expect(scope.details.components.length).toEqual(1);
|
||||
});
|
||||
});
|
||||
|
||||
});
|
|
@ -0,0 +1,34 @@
|
|||
module.exports = function(config){
|
||||
config.set({
|
||||
|
||||
basePath : '../../../',
|
||||
|
||||
files : [
|
||||
'target/generated-sources/vendor/angular**/**.min.js',
|
||||
'target/generated-sources/vendor/angular-mocks/angular-mocks.js',
|
||||
'src/main/javascript/**/*.js',
|
||||
'src/test/javascript/**/*Spec.js',
|
||||
'src/test/javascript/**/!(karma.conf).js'
|
||||
],
|
||||
|
||||
autoWatch : true,
|
||||
|
||||
frameworks: ['jasmine'],
|
||||
|
||||
browsers: ['PhantomJS'],
|
||||
|
||||
plugins : [
|
||||
'karma-chrome-launcher',
|
||||
'karma-firefox-launcher',
|
||||
'karma-phantomjs-launcher',
|
||||
'karma-jasmine',
|
||||
'karma-junit-reporter'
|
||||
],
|
||||
|
||||
junitReporter : {
|
||||
outputFile: 'target/test_out/unit.xml',
|
||||
suite: 'src/test/javascript'
|
||||
}
|
||||
|
||||
});
|
||||
};
|
Binary file not shown.
|
@ -0,0 +1,54 @@
|
|||
# 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.
|
||||
|
||||
# a couple of test stopwords to test that the words are really being
|
||||
# configured from this file:
|
||||
stopworda
|
||||
stopwordb
|
||||
|
||||
# Standard english stop words taken from Lucene's StopAnalyzer
|
||||
a
|
||||
an
|
||||
and
|
||||
are
|
||||
as
|
||||
at
|
||||
be
|
||||
but
|
||||
by
|
||||
for
|
||||
if
|
||||
in
|
||||
into
|
||||
is
|
||||
it
|
||||
no
|
||||
not
|
||||
of
|
||||
on
|
||||
or
|
||||
such
|
||||
that
|
||||
the
|
||||
their
|
||||
then
|
||||
there
|
||||
these
|
||||
they
|
||||
this
|
||||
to
|
||||
was
|
||||
will
|
||||
with
|
|
@ -0,0 +1,20 @@
|
|||
{"params":{
|
||||
"query":{
|
||||
"defType":"edismax",
|
||||
"q.alt":"*:*",
|
||||
"rows":"10",
|
||||
"fl":"*,score",
|
||||
"":{"v":0}
|
||||
},
|
||||
"facets":{
|
||||
"facet":"on",
|
||||
"facet.mincount": "1",
|
||||
"":{"v":0}
|
||||
},
|
||||
"velocity":{
|
||||
"wt": "velocity",
|
||||
"v.template":"browse",
|
||||
"v.layout": "layout",
|
||||
"":{"v":0}
|
||||
}
|
||||
}}
|
|
@ -0,0 +1,20 @@
|
|||
# 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.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
# Use a protected word file to protect against the stemmer reducing two
|
||||
# unrelated words to the same base word.
|
||||
|
||||
# Some non-words that normally won't be encountered,
|
||||
# just to test that they won't be stemmed.
|
||||
dontstems
|
||||
zwhacky
|
|
@ -0,0 +1,115 @@
|
|||
<?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.
|
||||
-->
|
||||
|
||||
<schema name="exampleCollection" version="1.6">
|
||||
|
||||
<!-- Defined fields -->
|
||||
<field name="id" type="string" indexed="true" stored="true" required="true" multiValued="false" docValues="true" />
|
||||
<field name="type_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="org_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="name_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="desc_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="icon_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="yarnfile_s" type="string" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="like_i" type="int" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="download_i" type="int" indexed="true" stored="true" required="false" multiValued="false" docValues="true" />
|
||||
<field name="_version_" type="long" indexed="true" stored="false"/>
|
||||
|
||||
<uniqueKey>id</uniqueKey>
|
||||
|
||||
<!-- Field types -->
|
||||
<fieldType name="string" class="solr.StrField" sortMissingLast="true" docValues="true" />
|
||||
<fieldType name="strings" class="solr.StrField" sortMissingLast="true" multiValued="true" docValues="true" />
|
||||
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
|
||||
<fieldType name="booleans" class="solr.BoolField" sortMissingLast="true" multiValued="true"/>
|
||||
<fieldType name="int" class="solr.TrieIntField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
|
||||
<fieldType name="float" class="solr.TrieFloatField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
|
||||
<fieldType name="long" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
|
||||
<fieldType name="double" class="solr.TrieDoubleField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
|
||||
<fieldType name="ints" class="solr.TrieIntField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="floats" class="solr.TrieFloatField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="longs" class="solr.TrieLongField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="doubles" class="solr.TrieDoubleField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="tint" class="solr.TrieIntField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
|
||||
<fieldType name="tfloat" class="solr.TrieFloatField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
|
||||
<fieldType name="tlong" class="solr.TrieLongField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
|
||||
<fieldType name="tdouble" class="solr.TrieDoubleField" docValues="true" precisionStep="8" positionIncrementGap="0"/>
|
||||
<fieldType name="tints" class="solr.TrieIntField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="tfloats" class="solr.TrieFloatField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="tlongs" class="solr.TrieLongField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="tdoubles" class="solr.TrieDoubleField" docValues="true" precisionStep="8" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="date" class="solr.TrieDateField" docValues="true" precisionStep="0" positionIncrementGap="0"/>
|
||||
<fieldType name="dates" class="solr.TrieDateField" docValues="true" precisionStep="0" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="tdate" class="solr.TrieDateField" docValues="true" precisionStep="6" positionIncrementGap="0"/>
|
||||
<fieldType name="tdates" class="solr.TrieDateField" docValues="true" precisionStep="6" positionIncrementGap="0" multiValued="true"/>
|
||||
<fieldType name="binary" class="solr.BinaryField"/>
|
||||
<fieldType name="random" class="solr.RandomSortField" indexed="true" />
|
||||
|
||||
<!-- A text field with defaults appropriate for English: it
|
||||
tokenizes with StandardTokenizer, removes English stop words
|
||||
(lang/stopwords_en.txt), down cases, protects words from protwords.txt, and
|
||||
finally applies Porter's stemming. The query time analyzer
|
||||
also applies synonyms from synonyms.txt. -->
|
||||
<fieldType name="text_en" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer type="index">
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<!-- in this example, we will only use synonyms at query time
|
||||
<filter class="solr.SynonymFilterFactory" synonyms="index_synonyms.txt" ignoreCase="true" expand="false"/> -->
|
||||
<!-- Case insensitive stop word removal. -->
|
||||
<filter class="solr.StopFilterFactory"
|
||||
ignoreCase="true"
|
||||
words="lang/stopwords_en.txt"
|
||||
/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.EnglishPossessiveFilterFactory"/>
|
||||
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
|
||||
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
|
||||
<filter class="solr.EnglishMinimalStemFilterFactory"/>
|
||||
-->
|
||||
<filter class="solr.PorterStemFilterFactory"/>
|
||||
</analyzer>
|
||||
<analyzer type="query">
|
||||
<tokenizer class="solr.StandardTokenizerFactory"/>
|
||||
<filter class="solr.SynonymFilterFactory" synonyms="synonyms.txt" ignoreCase="true" expand="true"/>
|
||||
<filter class="solr.StopFilterFactory"
|
||||
ignoreCase="true"
|
||||
words="lang/stopwords_en.txt"
|
||||
/>
|
||||
<filter class="solr.LowerCaseFilterFactory"/>
|
||||
<filter class="solr.EnglishPossessiveFilterFactory"/>
|
||||
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
|
||||
<!-- Optionally you may want to use this less aggressive stemmer instead of PorterStemFilterFactory:
|
||||
<filter class="solr.EnglishMinimalStemFilterFactory"/>
|
||||
-->
|
||||
<filter class="solr.PorterStemFilterFactory"/>
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- lowercases the entire field value, keeping it as a single token. -->
|
||||
<fieldType name="lowercase" class="solr.TextField" positionIncrementGap="100">
|
||||
<analyzer>
|
||||
<tokenizer class="solr.KeywordTokenizerFactory"/>
|
||||
<filter class="solr.LowerCaseFilterFactory" />
|
||||
</analyzer>
|
||||
</fieldType>
|
||||
|
||||
<!-- since fields of this type are by default not stored or indexed,
|
||||
any data added to them will be ignored outright. -->
|
||||
<fieldType name="ignored" stored="false" indexed="false" docValues="false" multiValued="true" class="solr.StrField" />
|
||||
|
||||
</schema>
|
|
@ -0,0 +1,36 @@
|
|||
<?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.
|
||||
-->
|
||||
<config>
|
||||
<luceneMatchVersion>6.2.1</luceneMatchVersion>
|
||||
|
||||
<dataDir>${solr.data.dir:}</dataDir>
|
||||
|
||||
<schemaFactory class="ClassicIndexSchemaFactory"/>
|
||||
|
||||
<indexConfig>
|
||||
<lockType>single</lockType>
|
||||
</indexConfig>
|
||||
|
||||
<requestDispatcher handleSelect="false">
|
||||
<httpCaching never304="true" />
|
||||
</requestDispatcher>
|
||||
|
||||
<requestHandler name="/select" class="solr.SearchHandler" />
|
||||
<requestHandler name="/update" class="solr.UpdateRequestHandler" />
|
||||
|
||||
</config>
|
|
@ -0,0 +1,14 @@
|
|||
# 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.
|
|
@ -0,0 +1,28 @@
|
|||
# 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.
|
||||
|
||||
#-----------------------------------------------------------------------
|
||||
#some test synonym mappings unlikely to appear in real input text
|
||||
aaafoo => aaabar
|
||||
bbbfoo => bbbfoo bbbbar
|
||||
cccfoo => cccbar cccbaz
|
||||
fooaaa,baraaa,bazaaa
|
||||
|
||||
# Some synonym groups specific to this example
|
||||
GB,gib,gigabyte,gigabytes
|
||||
MB,mib,megabyte,megabytes
|
||||
Television, Televisions, TV, TVs
|
||||
#notice we use "gib" instead of "GiB" so any WordDelimiterFilter coming
|
||||
#after us won't split it into two words.
|
||||
|
||||
# Synonym mappings can be used for spelling correction too
|
||||
pixima => pixma
|
|
@ -0,0 +1,11 @@
|
|||
log4j.rootLogger = INFO, CATALINA
|
||||
|
||||
# Define all the appenders
|
||||
log4j.appender.CATALINA = org.apache.log4j.DailyRollingFileAppender
|
||||
log4j.appender.CATALINA.File = target/appcatalog.log
|
||||
log4j.appender.CATALINA.Append = true
|
||||
log4j.appender.CATALINA.Encoding = UTF-8
|
||||
# Roll-over the log once per day
|
||||
log4j.appender.CATALINA.DatePattern = '.'yyyy-MM-dd'.log'
|
||||
log4j.appender.CATALINA.layout = org.apache.log4j.PatternLayout
|
||||
log4j.appender.CATALINA.layout.ConversionPattern = %d [%t] %-5p %c- %m%n
|
|
@ -0,0 +1,37 @@
|
|||
<?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.
|
||||
-->
|
||||
<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/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>hadoop-yarn-applications</artifactId>
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<version>3.3.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.apache.hadoop</groupId>
|
||||
<artifactId>hadoop-yarn-applications-catalog</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>YARN Application Catalog</name>
|
||||
|
||||
<url>http://hadoop.apache.org</url>
|
||||
|
||||
<modules>
|
||||
<module>hadoop-yarn-applications-catalog-webapp</module>
|
||||
<module>hadoop-yarn-applications-catalog-docker</module>
|
||||
</modules>
|
||||
</project>
|
|
@ -77,6 +77,13 @@ public class ApiServiceClient extends AppAdminClient {
|
|||
private static final Base64 BASE_64_CODEC = new Base64(0);
|
||||
protected YarnClient yarnClient;
|
||||
|
||||
public ApiServiceClient() {
|
||||
}
|
||||
|
||||
public ApiServiceClient(Configuration c) throws Exception {
|
||||
serviceInit(c);
|
||||
}
|
||||
|
||||
@Override protected void serviceInit(Configuration configuration)
|
||||
throws Exception {
|
||||
yarnClient = YarnClient.createYarnClient();
|
||||
|
@ -151,7 +158,7 @@ public class ApiServiceClient extends AppAdminClient {
|
|||
* @return URI to API Service
|
||||
* @throws IOException
|
||||
*/
|
||||
protected String getServicePath(String appName) throws IOException {
|
||||
public String getServicePath(String appName) throws IOException {
|
||||
String url = getRMWebAddress();
|
||||
StringBuilder api = new StringBuilder();
|
||||
api.append(url)
|
||||
|
@ -215,7 +222,7 @@ public class ApiServiceClient extends AppAdminClient {
|
|||
}
|
||||
}
|
||||
|
||||
private Builder getApiClient() throws IOException {
|
||||
public Builder getApiClient() throws IOException {
|
||||
return getApiClient(getServicePath(null));
|
||||
}
|
||||
|
||||
|
@ -226,7 +233,7 @@ public class ApiServiceClient extends AppAdminClient {
|
|||
* @return
|
||||
* @throws IOException
|
||||
*/
|
||||
private Builder getApiClient(String requestPath)
|
||||
public Builder getApiClient(String requestPath)
|
||||
throws IOException {
|
||||
Client client = Client.create(getClientConfig());
|
||||
client.setChunkedEncodingSize(null);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
{
|
||||
"name": "appcatalog",
|
||||
"version": "1",
|
||||
"components" :
|
||||
[
|
||||
{
|
||||
"name": "catalog",
|
||||
"number_of_containers": 1,
|
||||
"artifact": {
|
||||
"id": "apache/hadoop-yarn-applications-catalog-docker:3.3.0-SNAPSHOT",
|
||||
"type": "DOCKER"
|
||||
},
|
||||
"resource": {
|
||||
"cpus": 1,
|
||||
"memory": "2048"
|
||||
},
|
||||
"configuration": {
|
||||
"env": {
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_RUN_OVERRIDE_DISABLE":"true",
|
||||
"YARN_CONTAINER_RUNTIME_DOCKER_MOUNTS":"/etc/hadoop/conf:/etc/hadoop/conf:ro,/var/lib/sss/pipes:/var/lib/sss/pipes:rw",
|
||||
"JAVA_HOME":"/usr/lib/jvm/jre-1.8.0"
|
||||
},
|
||||
"properties": {
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -37,6 +37,7 @@
|
|||
<module>hadoop-yarn-applications-distributedshell</module>
|
||||
<module>hadoop-yarn-applications-unmanaged-am-launcher</module>
|
||||
<module>hadoop-yarn-services</module>
|
||||
<module>hadoop-yarn-applications-catalog</module>
|
||||
</modules>
|
||||
|
||||
<profiles>
|
||||
|
|
|
@ -165,6 +165,19 @@ where `service-name` is optional. If omitted, it uses the name defined in the `Y
|
|||
Look up your IPs at the RM REST endpoint `http://<RM host>:8088/app/v1/services/httpd-service`.
|
||||
Then visit port 8080 for each IP to view the pages.
|
||||
|
||||
## Application Catalog - appcatalog
|
||||
|
||||
Application Catalog introduces many exciting new features for deploying Hadoop software that benefit both administrators and end users. With Application Catalog, user gets a personalized view of the software status in Hadoop. In addition, users can install or register applications by using web-based user interface.
|
||||
|
||||
To start Application Catalog service with the command:
|
||||
```
|
||||
yarn app -launch <service-name> appcatalog
|
||||
```
|
||||
where `service-name` is user defined name.
|
||||
|
||||
The deployment progress of the application catalog is located in Resource Manager UI. When the service reaches STABLE state, application catalog UI is available at:
|
||||
http://appcatalog.${SERVICE_NAME}.${USER}.${DOMAIN}:8080/
|
||||
|
||||
## Docker image ENTRYPOINT support
|
||||
|
||||
Docker images may have built with ENTRYPOINT to enable start up of docker image without any parameters.
|
||||
|
|
Loading…
Reference in New Issue