Retiring App Catalog
This commit removes content associated with the app catalog. This is part of the first step, following the guide at: https://docs.openstack.org/infra/manual/drivers.html#retiring-a-project Earlier this year the TC agreed to retire this project: https://review.openstack.org/#/c/452086/ In July, Fungi sent a note to the operators list as well: http://lists.openstack.org/pipermail/openstack-operators/2017-July/013965.html Depends-On: I52ce13057643d69a0fd87bce20ee460c6b7c2f17 Change-Id: Idd69df495663e5ab6466c8d06945c9257a93842a
@ -1,7 +0,0 @@
|
||||
[run]
|
||||
branch = True
|
||||
source = openstack_catalog
|
||||
omit = openstack_catalog/tests/*,openstack_catalog/openstack/*
|
||||
|
||||
[report]
|
||||
ignore_errors = True
|
13
.eslintrc
@ -1,13 +0,0 @@
|
||||
# use standard openstack linting profile
|
||||
extends: openstack
|
||||
|
||||
env:
|
||||
# browser global variables.
|
||||
browser: true
|
||||
|
||||
rules:
|
||||
# Require camel case names
|
||||
# http://eslint.org/docs/rules/camelcase
|
||||
camelcase:
|
||||
- 1 # report camelcase properties as warnings
|
||||
- properties: "never"
|
53
.gitignore
vendored
@ -1,53 +0,0 @@
|
||||
*.py[cod]
|
||||
|
||||
# C extensions
|
||||
*.so
|
||||
|
||||
# Packages
|
||||
*.egg
|
||||
*.egg-info
|
||||
dist
|
||||
build
|
||||
eggs
|
||||
parts
|
||||
bin
|
||||
var
|
||||
sdist
|
||||
develop-eggs
|
||||
.installed.cfg
|
||||
lib
|
||||
lib64
|
||||
|
||||
# Installer logs
|
||||
pip-log.txt
|
||||
|
||||
# Unit test / coverage reports
|
||||
.coverage
|
||||
.tox
|
||||
nosetests.xml
|
||||
.testrepository
|
||||
.venv
|
||||
|
||||
# Translations
|
||||
*.mo
|
||||
|
||||
# Mr Developer
|
||||
.mr.developer.cfg
|
||||
.project
|
||||
.pydevproject
|
||||
|
||||
# Complexity
|
||||
output/*.html
|
||||
output/*/index.html
|
||||
|
||||
# Sphinx
|
||||
doc/build
|
||||
|
||||
# pbr generates these
|
||||
AUTHORS
|
||||
ChangeLog
|
||||
|
||||
# Editors
|
||||
*~
|
||||
.*.swp
|
||||
.*sw?
|
@ -1,4 +0,0 @@
|
||||
[gerrit]
|
||||
host=review.openstack.org
|
||||
port=29418
|
||||
project=openstack/app-catalog.git
|
3
.mailmap
@ -1,3 +0,0 @@
|
||||
# Format is:
|
||||
# <preferred e-mail> <other e-mail 1>
|
||||
# <preferred e-mail> <other e-mail 2>
|
@ -1,7 +0,0 @@
|
||||
[DEFAULT]
|
||||
test_command=OS_STDOUT_CAPTURE=${OS_STDOUT_CAPTURE:-1} \
|
||||
OS_STDERR_CAPTURE=${OS_STDERR_CAPTURE:-1} \
|
||||
OS_TEST_TIMEOUT=${OS_TEST_TIMEOUT:-60} \
|
||||
${PYTHON:-python} -m subunit.run discover -t ./ . $LISTOPT $IDOPTION
|
||||
test_id_option=--load-list $IDFILE
|
||||
test_list_option=--list
|
@ -1,16 +0,0 @@
|
||||
If you would like to contribute to the development of OpenStack,
|
||||
you must follow the steps in this page:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html
|
||||
|
||||
Once those steps have been completed, changes to OpenStack
|
||||
should be submitted for review via the Gerrit tool, following
|
||||
the workflow documented at:
|
||||
|
||||
http://docs.openstack.org/infra/manual/developers.html#development-workflow
|
||||
|
||||
Pull requests submitted through GitHub will be ignored.
|
||||
|
||||
Bugs should be filed on Launchpad, not GitHub:
|
||||
|
||||
https://bugs.launchpad.net/catalog
|
@ -1,4 +0,0 @@
|
||||
catalog Style Commandments
|
||||
===============================================
|
||||
|
||||
Read the OpenStack Style Commandments http://docs.openstack.org/developer/hacking/
|
180
LICENSE
@ -1,180 +0,0 @@
|
||||
Some files from:
|
||||
http://www.iconarchive.com/show/beautiful-flat-icons-by-elegantthemes/plugin-icon.html
|
||||
|
||||
Everything else:
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
@ -1,6 +0,0 @@
|
||||
include AUTHORS
|
||||
include ChangeLog
|
||||
exclude .gitignore
|
||||
exclude .gitreview
|
||||
|
||||
global-exclude *.pyc
|
54
README.rst
@ -1,48 +1,10 @@
|
||||
===============================
|
||||
OpenStack Community App Catalog
|
||||
===============================
|
||||
Application Catalog for OpenStack
|
||||
This project is no longer maintained.
|
||||
|
||||
The OpenStack Community App Catalog will help you make
|
||||
applications available on your OpenStack cloud by providing
|
||||
a community driven catalog containing Glance images, Heat
|
||||
templates and Murano applications.
|
||||
The contents of this repository are still available in the Git
|
||||
source code management system. To see the contents of this
|
||||
repository before it reached its end of life, please check out the
|
||||
previous commit with "git checkout HEAD^1".
|
||||
|
||||
Overview
|
||||
--------
|
||||
|
||||
By providing a public location where OpenStack users can
|
||||
publish and consume artifacts to share and add additional
|
||||
capabilities, all OpenStack clouds become more valuable. For
|
||||
example vendors can publish Glance images for launching new
|
||||
VMs, Heat templates for creating new stacks, or Murano app
|
||||
packages for installing complete applications. When many
|
||||
OpenStack community members are publishing artifacts that
|
||||
users can easily download and install into their clouds this
|
||||
will multiply the value of their OpenStack cloud. Easy
|
||||
access to images, templates and apps will solve the "what
|
||||
now" question some user consider after successfully
|
||||
deploying an OpenStack environment.
|
||||
|
||||
* Free software: Apache 2.0 License. See LICENSE file.
|
||||
* Documentation: http://wiki.openstack.org/wiki/App-Catalog
|
||||
|
||||
Getting started with the Community App Catalog
|
||||
----------------------------------------------
|
||||
|
||||
See the wiki page to see how to get started using or
|
||||
contributing to the App Catalog. Visit
|
||||
https://wiki.openstack.org/wiki/App-Catalog for more
|
||||
details.
|
||||
|
||||
Project Info
|
||||
------------
|
||||
|
||||
* Web-site: http://apps.openstack.org
|
||||
* Source: http://git.openstack.org/cgit/openstack/app-catalog
|
||||
* Wiki: https://wiki.openstack.org/wiki/App-Catalog
|
||||
* Launchpad: https://launchpad.net/app-catalog
|
||||
* Blueprints: https://blueprints.launchpad.net/app-catalog
|
||||
* Bugs: http://bugs.launchpad.net/app-catalog
|
||||
* Code Reviews: https://review.openstack.org/#q,status:open+app-catalog,n,z
|
||||
* IRC: #openstack-app-catalog at freenode
|
||||
For any further questions, please email
|
||||
openstack-dev@lists.openstack.org or join #openstack-dev on
|
||||
Freenode.
|
||||
|
40
bindep.txt
@ -1,40 +0,0 @@
|
||||
# This is a cross-platform list tracking distribution packages needed by tests;
|
||||
# see http://docs.openstack.org/infra/bindep/ for additional information.
|
||||
|
||||
apt-transport-https
|
||||
lsb-release
|
||||
ant
|
||||
build-essential [platform:dpkg]
|
||||
curl
|
||||
cyrus-sasl-devel [platform:rpm]
|
||||
dbus
|
||||
firefox [!platform:debian]
|
||||
gawk
|
||||
iceweasel [platform:debian]
|
||||
language-pack-en [platform:ubuntu]
|
||||
libcurl-devel [platform:rpm]
|
||||
libcurl4-gnutls-dev [platform:dpkg]
|
||||
libffi-dev [platform:dpkg]
|
||||
libffi-devel [platform:rpm]
|
||||
libjpeg-dev [platform:dpkg]
|
||||
libjpeg-turbo-devel [platform:rpm]
|
||||
libldap2-dev [platform:dpkg]
|
||||
libsasl2-dev [platform:dpkg]
|
||||
libselinux-python [platform:rpm]
|
||||
libuuid-devel [platform:rpm]
|
||||
locales [platform:debian]
|
||||
pkg-config [platform:dpkg]
|
||||
pkgconfig [platform:rpm]
|
||||
python-dev [platform:dpkg]
|
||||
python-devel [platform:rpm]
|
||||
python-libvirt [platform:dpkg]
|
||||
python-lxml
|
||||
python3-all-dev [platform:ubuntu-trusty]
|
||||
python3-dev [platform:dpkg]
|
||||
python3-devel [platform:fedora]
|
||||
python3.4 [platform:ubuntu-trusty]
|
||||
python34-devel [platform:centos]
|
||||
unzip
|
||||
uuid-dev [platform:dpkg]
|
||||
xorg-x11-server-Xvfb [platform:rpm]
|
||||
xvfb [platform:dpkg]
|
@ -1,48 +0,0 @@
|
||||
app-catalog-ci
|
||||
===============
|
||||
|
||||
Description
|
||||
-----------
|
||||
|
||||
This is a collection of deployment scripts for app-catalog CI project.
|
||||
It consists of Puppet module catalog_ci and an additional shell script.
|
||||
The scripts allow to setup Jenkins with access to Gerrit to trigger
|
||||
appropriate jobs on a commit to the app-catalog project.
|
||||
|
||||
Deployment
|
||||
----------
|
||||
|
||||
Execute deploy.sh script to begin deployment:
|
||||
(some operations require superuser access rights)
|
||||
|
||||
./deploy.sh
|
||||
|
||||
The script will install necessary packages and deploy/configure Jenkins.
|
||||
You will be able to access it at http://server_ip:8080
|
||||
The following steps are required after deployment:
|
||||
- Setup access rights. By default Jenkins uses Launchpad OpenID and all users
|
||||
have full access to Jenkins.
|
||||
Proceed to Manage Jenkins -> Configure Global Security and setup security.
|
||||
- Finish Gerrit auth setup:
|
||||
Add a private key file (id_rsa) to Jenkins ssh directory:
|
||||
* sudo mkdir -p /var/lib/jenkins/.ssh
|
||||
* sudo cp id_rsa /var/lib/jenkins/.ssh
|
||||
* sudo chown -R jenkins:jenkins /var/lib/jenkins/.ssh
|
||||
* sudo chmod 600 /var/lib/jenkins/.ssh/id_rsa
|
||||
Then proceed to Manage Jenkins -> Gerrit Trigger and press the button
|
||||
in 'Status' column. If button will change its color to green, your connection
|
||||
to Gerrit works OK and Jenkins is receiving Gerrit events. Otherwise please
|
||||
check Gerrit server parameters.
|
||||
- rclone (http://rclone.org/) is used to upload images to CDN.
|
||||
Please install and configure it manually, if it's required.
|
||||
'jenkins' user should be able to access default rclone configuration file
|
||||
in order to use it.
|
||||
|
||||
Jenkins Jobs
|
||||
------------
|
||||
|
||||
Jenkins Job Builder is used to configure Jenkins jobs. It will be automatically
|
||||
installed by deployment scripts. Jobs configuration files will be placed to
|
||||
/etc/jenkins_jobs/jobs. You can use the following command to apply your changes
|
||||
|
||||
jenkins-jobs update /etc/jenkins_jobs/jobs
|
@ -1 +0,0 @@
|
||||
include catalog_ci
|
@ -1,45 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<hudson>
|
||||
<disabledAdministrativeMonitors/>
|
||||
<version>1.596.2</version>
|
||||
<numExecutors>3</numExecutors>
|
||||
<mode>NORMAL</mode>
|
||||
<useSecurity>true</useSecurity>
|
||||
<authorizationStrategy class="hudson.security.GlobalMatrixAuthorizationStrategy">
|
||||
<permission>hudson.model.Hudson.Administer:anonymous</permission>
|
||||
<permission>hudson.model.Hudson.Read:anonymous</permission>
|
||||
<permission>hudson.model.Item.Read:anonymous</permission>
|
||||
</authorizationStrategy>
|
||||
<securityRealm class="hudson.plugins.openid.OpenIdSsoSecurityRealm" plugin="openid@2.1.1">
|
||||
<endpoint>https://login.launchpad.net/+openid</endpoint>
|
||||
</securityRealm>
|
||||
<disableRememberMe>false</disableRememberMe>
|
||||
<projectNamingStrategy class="jenkins.model.ProjectNamingStrategy$DefaultProjectNamingStrategy"/>
|
||||
<workspaceDir>${JENKINS_HOME}/workspace/${ITEM_FULLNAME}</workspaceDir>
|
||||
<buildsDir>${ITEM_ROOTDIR}/builds</buildsDir>
|
||||
<markupFormatter class="hudson.markup.RawHtmlMarkupFormatter" plugin="antisamy-markup-formatter@1.1">
|
||||
<disableSyntaxHighlighting>false</disableSyntaxHighlighting>
|
||||
</markupFormatter>
|
||||
<jdks/>
|
||||
<viewsTabBar class="hudson.views.DefaultViewsTabBar"/>
|
||||
<myViewsTabBar class="hudson.views.DefaultMyViewsTabBar"/>
|
||||
<clouds/>
|
||||
<slaves/>
|
||||
<quietPeriod>5</quietPeriod>
|
||||
<scmCheckoutRetryCount>0</scmCheckoutRetryCount>
|
||||
<views>
|
||||
<hudson.model.AllView>
|
||||
<owner class="hudson" reference="../../.."/>
|
||||
<name>All</name>
|
||||
<filterExecutors>false</filterExecutors>
|
||||
<filterQueue>false</filterQueue>
|
||||
<properties class="hudson.model.View$PropertyList"/>
|
||||
</hudson.model.AllView>
|
||||
</views>
|
||||
<primaryView>All</primaryView>
|
||||
<slaveAgentPort>0</slaveAgentPort>
|
||||
<label></label>
|
||||
<nodeProperties/>
|
||||
<globalNodeProperties/>
|
||||
<noUsageStatistics>true</noUsageStatistics>
|
||||
</hudson>
|
@ -1,67 +0,0 @@
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
<com.sonyericsson.hudson.plugins.gerrit.trigger.PluginImpl plugin="gerrit-trigger@2.13.0">
|
||||
<servers class="java.util.concurrent.CopyOnWriteArrayList">
|
||||
<com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer>
|
||||
<name>review.openstack.org</name>
|
||||
<noConnectionOnStartup>false</noConnectionOnStartup>
|
||||
<config class="com.sonyericsson.hudson.plugins.gerrit.trigger.config.Config">
|
||||
<gerritHostName>review.openstack.org</gerritHostName>
|
||||
<gerritSshPort>29418</gerritSshPort>
|
||||
<gerritProxy></gerritProxy>
|
||||
<gerritUserName>catalog-ci</gerritUserName>
|
||||
<gerritEMail>catalog-ci@mirantis.com</gerritEMail>
|
||||
<gerritAuthKeyFile>/var/lib/jenkins/.ssh/id_rsa</gerritAuthKeyFile>
|
||||
<useRestApi>false</useRestApi>
|
||||
<restCodeReview>false</restCodeReview>
|
||||
<restVerified>false</restVerified>
|
||||
<gerritBuildCurrentPatchesOnly>false</gerritBuildCurrentPatchesOnly>
|
||||
<gerritVerifiedCmdBuildSuccessful>gerrit review <CHANGE>,<PATCHSET> --message 'Build Successful <BUILDS_STATS>' --verified <VERIFIED> --code-review <CODE_REVIEW></gerritVerifiedCmdBuildSuccessful>
|
||||
<gerritVerifiedCmdBuildUnstable>gerrit review <CHANGE>,<PATCHSET> --message 'Build Unstable <BUILDS_STATS>' --verified <VERIFIED> --code-review <CODE_REVIEW></gerritVerifiedCmdBuildUnstable>
|
||||
<gerritVerifiedCmdBuildFailed>gerrit review <CHANGE>,<PATCHSET> --message 'Build Failed <BUILDS_STATS>' --verified <VERIFIED> --code-review <CODE_REVIEW></gerritVerifiedCmdBuildFailed>
|
||||
<gerritVerifiedCmdBuildStarted></gerritVerifiedCmdBuildStarted>
|
||||
<gerritVerifiedCmdBuildNotBuilt>gerrit review <CHANGE>,<PATCHSET> --message 'No Builds Executed <BUILDS_STATS>' --verified <VERIFIED> --code-review <CODE_REVIEW></gerritVerifiedCmdBuildNotBuilt>
|
||||
<gerritFrontEndUrl>https://review.openstack.org/</gerritFrontEndUrl>
|
||||
<gerritBuildStartedVerifiedValue>0</gerritBuildStartedVerifiedValue>
|
||||
<gerritBuildStartedCodeReviewValue>0</gerritBuildStartedCodeReviewValue>
|
||||
<gerritBuildSuccessfulVerifiedValue>1</gerritBuildSuccessfulVerifiedValue>
|
||||
<gerritBuildSuccessfulCodeReviewValue>0</gerritBuildSuccessfulCodeReviewValue>
|
||||
<gerritBuildFailedVerifiedValue>-1</gerritBuildFailedVerifiedValue>
|
||||
<gerritBuildFailedCodeReviewValue>0</gerritBuildFailedCodeReviewValue>
|
||||
<gerritBuildUnstableVerifiedValue>0</gerritBuildUnstableVerifiedValue>
|
||||
<gerritBuildUnstableCodeReviewValue>0</gerritBuildUnstableCodeReviewValue>
|
||||
<gerritBuildNotBuiltVerifiedValue>0</gerritBuildNotBuiltVerifiedValue>
|
||||
<gerritBuildNotBuiltCodeReviewValue>0</gerritBuildNotBuiltCodeReviewValue>
|
||||
<enableManualTrigger>true</enableManualTrigger>
|
||||
<enablePluginMessages>true</enablePluginMessages>
|
||||
<buildScheduleDelay>3</buildScheduleDelay>
|
||||
<dynamicConfigRefreshInterval>30</dynamicConfigRefreshInterval>
|
||||
<categories class="linked-list">
|
||||
<com.sonyericsson.hudson.plugins.gerrit.trigger.VerdictCategory>
|
||||
<verdictValue>CRVW</verdictValue>
|
||||
<verdictDescription>Code Review</verdictDescription>
|
||||
</com.sonyericsson.hudson.plugins.gerrit.trigger.VerdictCategory>
|
||||
<com.sonyericsson.hudson.plugins.gerrit.trigger.VerdictCategory>
|
||||
<verdictValue>VRIF</verdictValue>
|
||||
<verdictDescription>Verified</verdictDescription>
|
||||
</com.sonyericsson.hudson.plugins.gerrit.trigger.VerdictCategory>
|
||||
</categories>
|
||||
<replicationConfig>
|
||||
<enableReplication>false</enableReplication>
|
||||
<slaves class="linked-list"/>
|
||||
<enableSlaveSelectionInJobs>false</enableSlaveSelectionInJobs>
|
||||
</replicationConfig>
|
||||
<watchdogTimeoutMinutes>0</watchdogTimeoutMinutes>
|
||||
<watchTimeExceptionData>
|
||||
<daysOfWeek/>
|
||||
<timesOfDay class="linked-list"/>
|
||||
</watchTimeExceptionData>
|
||||
<notificationLevel>ALL</notificationLevel>
|
||||
</config>
|
||||
</com.sonyericsson.hudson.plugins.gerrit.trigger.GerritServer>
|
||||
</servers>
|
||||
<pluginConfig>
|
||||
<numberOfReceivingWorkerThreads>3</numberOfReceivingWorkerThreads>
|
||||
<numberOfSendingWorkerThreads>1</numberOfSendingWorkerThreads>
|
||||
<replicationCacheExpirationInMinutes>360</replicationCacheExpirationInMinutes>
|
||||
</pluginConfig>
|
||||
</com.sonyericsson.hudson.plugins.gerrit.trigger.PluginImpl>
|
@ -1,67 +0,0 @@
|
||||
- job:
|
||||
name: check-image
|
||||
node: master
|
||||
project-type: freestyle
|
||||
description: "This job checks glance images"
|
||||
defaults: global
|
||||
disabled: false
|
||||
concurrent: true
|
||||
|
||||
scm:
|
||||
- git:
|
||||
url: https://git.openstack.org/openstack/app-catalog
|
||||
refspec: $GERRIT_REFSPEC
|
||||
name:
|
||||
choosing-strategy: gerrit
|
||||
skip-tag: false
|
||||
wipe-workspace: true
|
||||
branches:
|
||||
- "$GERRIT_BRANCH"
|
||||
|
||||
triggers:
|
||||
- gerrit:
|
||||
server-name: "review.openstack.org"
|
||||
trigger-on-patchset-uploaded-event: true
|
||||
projects:
|
||||
- project-compare-type: 'PLAIN'
|
||||
project-pattern: 'openstack/app-catalog'
|
||||
branch-compare-type: 'PLAIN'
|
||||
branch-pattern: master
|
||||
|
||||
builders:
|
||||
- shell: "git checkout $FETCH_HEAD\
|
||||
\n$JENKINS_HOME/scripts/app-catalog.sh"
|
||||
|
||||
- job:
|
||||
name: merge-image
|
||||
node: master
|
||||
project-type: freestyle
|
||||
description: "This job checks and uploads glance images to CDN"
|
||||
defaults: global
|
||||
disabled: false
|
||||
concurrent: true
|
||||
|
||||
scm:
|
||||
- git:
|
||||
url: https://git.openstack.org/openstack/app-catalog
|
||||
refspec: $GERRIT_REFSPEC
|
||||
name:
|
||||
choosing-strategy: gerrit
|
||||
skip-tag: false
|
||||
wipe-workspace: true
|
||||
branches:
|
||||
- "$GERRIT_BRANCH"
|
||||
|
||||
triggers:
|
||||
- gerrit:
|
||||
server-name: "review.openstack.org"
|
||||
trigger-on-change-merged-event: true
|
||||
projects:
|
||||
- project-compare-type: 'PLAIN'
|
||||
project-pattern: 'openstack/app-catalog'
|
||||
branch-compare-type: 'PLAIN'
|
||||
branch-pattern: master
|
||||
|
||||
builders:
|
||||
- shell: "git checkout $FETCH_HEAD\
|
||||
\n$JENKINS_HOME/scripts/app-catalog.sh"
|
@ -1,96 +0,0 @@
|
||||
#!/bin/bash -x
|
||||
|
||||
WDIR=$JENKINS_HOME/scripts
|
||||
PATCH=$GERRIT_CHANGE_NUMBER
|
||||
CODES=(100 200 302)
|
||||
TMP_DIR=$(mktemp -d)
|
||||
TMP_FILE=$(mktemp)
|
||||
EVENT=$GERRIT_EVENT_TYPE
|
||||
FILE_LIST=$(git diff HEAD~1 --name-only)
|
||||
IMAGE_CONFIG="openstack_catalog/web/static/glance_images.yaml"
|
||||
IMAGE_CDN_PATH="catalog_ci:catalog/images"
|
||||
|
||||
clean() {
|
||||
rm -rf $TMP_DIR
|
||||
rm -f $TMP_FILE
|
||||
}
|
||||
|
||||
upload_image () {
|
||||
local CONFIG
|
||||
local OLD_CONFIG
|
||||
local IMAGE_NAME
|
||||
local IMAGE_PATH
|
||||
|
||||
IMAGE_PATH=$1
|
||||
CONFIG=$TMP_DIR/$(basename $IMAGE_CONFIG)
|
||||
OLD_CONFIG=$TMP_DIR/$(basename $IMAGE_CONFIG).old
|
||||
IMAGE_NAME=$(python $WDIR/generate_names.py glance $OLD_CONFIG $CONFIG)
|
||||
if [ -z "$IMAGE_NAME" ]; then
|
||||
echo "Image file can't be generated"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Uploading image $IMAGE_NAME from $IMAGE_PATH"
|
||||
mv $IMAGE_PATH $(dirname $IMAGE_PATH)/$IMAGE_NAME
|
||||
rclone copy $(dirname $IMAGE_PATH)/$IMAGE_NAME $IMAGE_CDN_PATH
|
||||
clean
|
||||
}
|
||||
|
||||
main() {
|
||||
local URL
|
||||
local HASH
|
||||
local REAL_HASH
|
||||
local HTTP_CODE
|
||||
local IMAGE
|
||||
|
||||
ssh -p 29418 catalog-ci@review.openstack.org gerrit query $PATCH > $TMP_FILE
|
||||
URL=$(cat $TMP_FILE | egrep "^\s*Image-URL:\s(https?|ftp)://.*" | egrep -o "(https?|ftp)://.*$")
|
||||
HASH=$(cat $TMP_FILE | egrep "^\s*Image-hash:\s[A-Za-z0-9]*$" | egrep -o "[A-Za-z0-9]*$")
|
||||
|
||||
cat $TMP_FILE | grep Image-URL | grep -q Unknown && exit 0
|
||||
# if [ $(cat $TMP_FILE | grep Image-URL | grep Unknown) ]; then
|
||||
# echo "Image URL is unknown, no checks and changes will be performed"
|
||||
# exit 0
|
||||
# fi
|
||||
|
||||
if [ -z "$URL" -o -z "$HASH" ]; then
|
||||
echo "Image URL or hash wasn't found"
|
||||
clean
|
||||
exit 0
|
||||
else
|
||||
HTTP_CODE=$(curl -o /dev/null --silent --head --write-out '%{http_code}\n' $URL)
|
||||
if ! [[ " ${CODES[*]} " == *" $HTTP_CODE "* ]]; then
|
||||
echo "File wasn't found"
|
||||
clean
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
|
||||
wget $URL -P $TMP_DIR
|
||||
if [ "$HASH" == "Unknown" ]; then
|
||||
echo "Image hash is unknown, skipping checks..."
|
||||
else
|
||||
REAL_HASH=$(md5sum $TMP_DIR/* | awk '{print $1}')
|
||||
if [ "$REAL_HASH" != "$HASH" ]; then
|
||||
echo "Hash mismatch"
|
||||
clean
|
||||
exit 1
|
||||
else
|
||||
echo "Image hash is correct"
|
||||
fi
|
||||
fi
|
||||
|
||||
if [ "$EVENT" == "change-merged" ]; then
|
||||
IMAGE=$(ls $TMP_DIR/*)
|
||||
cp $IMAGE_CONFIG $TMP_DIR
|
||||
git checkout HEAD~1
|
||||
cp $IMAGE_CONFIG $TMP_DIR/$(basename $IMAGE_CONFIG).old
|
||||
upload_image $IMAGE
|
||||
else
|
||||
clean
|
||||
fi
|
||||
}
|
||||
|
||||
if [[ ${FILE_LIST[*]} =~ "$IMAGE_CONFIG" ]]; then
|
||||
main "$@"
|
||||
fi
|
@ -1,50 +0,0 @@
|
||||
#!/usr/bin/python
|
||||
# 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.
|
||||
|
||||
import itertools
|
||||
import re
|
||||
from sys import argv
|
||||
import yaml
|
||||
|
||||
|
||||
def yaml_to_dict(infile, k):
|
||||
stream = open(infile, 'r')
|
||||
rdict = yaml.safe_load(stream)[k]
|
||||
return rdict
|
||||
|
||||
|
||||
def diff_images_config(images1, images2):
|
||||
if images1 == images2:
|
||||
return ''
|
||||
intersec = [item for item in images1 if item in images2]
|
||||
sym_diff = [item for item in itertools.chain(
|
||||
images1, images2) if item not in intersec]
|
||||
name = ''
|
||||
d_size = len(sym_diff)
|
||||
if d_size <= 2:
|
||||
i = d_size - 1
|
||||
else:
|
||||
return ''
|
||||
|
||||
if 'name' in sym_diff[i].keys() and 'format' in sym_diff[i].keys():
|
||||
i_name = re.sub('[(){}<>]', '', sym_diff[i]['name'])
|
||||
i_type = sym_diff[i]['format']
|
||||
name = i_name + '.' + i_type
|
||||
name = name.lower().replace(" ", "_")
|
||||
return name
|
||||
|
||||
if __name__ == '__main__':
|
||||
if argv[1] == 'glance':
|
||||
images1 = yaml_to_dict(argv[2], 'images')
|
||||
images2 = yaml_to_dict(argv[3], 'images')
|
||||
print(diff_images_config(images1, images2))
|
@ -1,123 +0,0 @@
|
||||
class catalog_ci {
|
||||
|
||||
$user = 'admin'
|
||||
$password = 'adminpassword'
|
||||
$jenkins_config = '/var/lib/jenkins/config.xml'
|
||||
$gerrit_config = '/var/lib/jenkins/gerrit-trigger.xml'
|
||||
|
||||
class{ 'jenkins':
|
||||
lts => true,
|
||||
install_java => true,
|
||||
plugin_hash => {
|
||||
'git' => {},
|
||||
'parameterized-trigger' => {},
|
||||
'token-macro' => {},
|
||||
'mailer' => {},
|
||||
'scm-api' => {},
|
||||
'promoted-builds' => {},
|
||||
'matrix-project' => {},
|
||||
'git-client' => {},
|
||||
'ssh-credentials' => {},
|
||||
'credentials' => {},
|
||||
'gerrit-trigger' => {},
|
||||
'rebuild' => {},
|
||||
'git-client' => {},
|
||||
'rabbitmq-consumer' => {},
|
||||
'openid' => {},
|
||||
'openid4java' => {},
|
||||
}
|
||||
}
|
||||
|
||||
jenkins::user { "$user":
|
||||
email => 'admin@example.com',
|
||||
password => "$password",
|
||||
}
|
||||
|
||||
class{ 'jenkins::security':
|
||||
security_model => 'full_control',
|
||||
}
|
||||
|
||||
Class['jenkins'] -> Jenkins::User["$user"] -> Class['jenkins::security']
|
||||
-> Exec['create_jobs'] -> File["$jenkins_config"]
|
||||
|
||||
package {'python-pip':
|
||||
ensure => present,
|
||||
}
|
||||
|
||||
package {'deepdiff':
|
||||
ensure => present,
|
||||
provider => 'pip',
|
||||
}
|
||||
|
||||
package {'pyyaml':
|
||||
ensure => present,
|
||||
provider => 'pip',
|
||||
}
|
||||
|
||||
package {'jenkins-job-builder':
|
||||
ensure => present,
|
||||
provider => 'pip',
|
||||
}
|
||||
|
||||
file {'/var/lib/jenkins/scripts':
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
ensure => directory,
|
||||
source => 'puppet:///modules/catalog_ci/scripts',
|
||||
recurse => true,
|
||||
require => File['/etc/jenkins_jobs'],
|
||||
}
|
||||
|
||||
file {'/etc/jenkins_jobs':
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
ensure => directory,
|
||||
require => Package['jenkins-job-builder'],
|
||||
}
|
||||
|
||||
file {'/etc/jenkins_jobs/jenkins_jobs.ini':
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
content => template('catalog_ci/jenkins_jobs.ini.erb'),
|
||||
require => File['/etc/jenkins_jobs'],
|
||||
}
|
||||
|
||||
file {'/etc/jenkins_jobs/jobs':
|
||||
owner => 'root',
|
||||
group => 'root',
|
||||
ensure => directory,
|
||||
source => 'puppet:///modules/catalog_ci/jobs',
|
||||
recurse => true,
|
||||
require => File['/etc/jenkins_jobs'],
|
||||
}
|
||||
|
||||
file {"$jenkins_config":
|
||||
owner => 'jenkins',
|
||||
group => 'jenkins',
|
||||
ensure => present,
|
||||
source => 'puppet:///modules/catalog_ci/config.xml',
|
||||
}
|
||||
|
||||
file {"$gerrit_config":
|
||||
owner => 'jenkins',
|
||||
group => 'jenkins',
|
||||
ensure => present,
|
||||
source => 'puppet:///modules/catalog_ci/gerrit-trigger.xml',
|
||||
require => File["$jenkins_config"],
|
||||
}
|
||||
|
||||
exec {'create_jobs':
|
||||
command => 'jenkins-jobs update /etc/jenkins_jobs/jobs',
|
||||
path => '/bin:/sbin:/usr/bin:/usr/sbin:/usr/local/bin',
|
||||
require => File['/etc/jenkins_jobs/jobs'],
|
||||
}
|
||||
|
||||
exec{'restart_jenkins':
|
||||
command => 'service jenkins restart',
|
||||
path => '/bin:/sbin:/usr/bin:/usr/sbin',
|
||||
subscribe => [ File["$jenkins_config"], File["$gerrit_config"] ],
|
||||
}
|
||||
|
||||
Package['python-pip'] -> Package['deepdiff'] ->
|
||||
Package['pyyaml'] -> Package['jenkins-job-builder']
|
||||
}
|
@ -1,8 +0,0 @@
|
||||
[job_builder]
|
||||
ignore_cache=True
|
||||
|
||||
[jenkins]
|
||||
user=<%= @user %>
|
||||
password=<%= @password %>
|
||||
url=http://127.0.0.1:8080
|
||||
query_plugins_info=False
|
@ -1,19 +0,0 @@
|
||||
#!/bin/bash -e
|
||||
|
||||
# Generate a password for service account
|
||||
ADMIN_PASS=$(< /dev/urandom tr -dc _A-Z-a-z-0-9 | head -c10)
|
||||
sed -i "s/adminpassword/$ADMIN_PASS/g" catalog-ci-jenkins/modules/catalog_ci/manifests/init.pp
|
||||
|
||||
sudo apt-get update
|
||||
sudo apt-get install git puppet -y
|
||||
|
||||
# Using custom (forked) puppet-jenkins module
|
||||
# due to critical problem in the upstream one
|
||||
git clone https://github.com/skolekonov/puppet-jenkins.git
|
||||
tar czf rtyler-jenkins-1.3.0.tar.gz puppet-jenkins/*
|
||||
sudo puppet module install rtyler-jenkins-1.3.0.tar.gz
|
||||
|
||||
sudo puppet apply -vd --modulepath catalog-ci-jenkins/modules:/etc/puppet/modules catalog-ci-jenkins/manifests/site.pp
|
||||
|
||||
echo "Deployment completed"
|
||||
echo "WARNING. Please open Jenkins WebUI and setup user access matrix"
|
@ -1,75 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
sys.path.insert(0, os.path.abspath('../..'))
|
||||
# -- General configuration ----------------------------------------------------
|
||||
|
||||
# Add any Sphinx extension module names here, as strings. They can be
|
||||
# extensions coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
|
||||
extensions = [
|
||||
'sphinx.ext.autodoc',
|
||||
#'sphinx.ext.intersphinx',
|
||||
'oslosphinx'
|
||||
]
|
||||
|
||||
# autodoc generation is a bit aggressive and a nuisance when doing heavy
|
||||
# text edit cycles.
|
||||
# execute "export SPHINX_DEBUG=1" in your terminal to disable
|
||||
|
||||
# The suffix of source filenames.
|
||||
source_suffix = '.rst'
|
||||
|
||||
# The master toctree document.
|
||||
master_doc = 'index'
|
||||
|
||||
# General information about the project.
|
||||
project = u'catalog'
|
||||
copyright = u'2013, OpenStack Foundation'
|
||||
|
||||
# If true, '()' will be appended to :func: etc. cross-reference text.
|
||||
add_function_parentheses = True
|
||||
|
||||
# If true, the current module name will be prepended to all description
|
||||
# unit titles (such as .. function::).
|
||||
add_module_names = True
|
||||
|
||||
# The name of the Pygments (syntax highlighting) style to use.
|
||||
pygments_style = 'sphinx'
|
||||
|
||||
# -- Options for HTML output --------------------------------------------------
|
||||
|
||||
# The theme to use for HTML and HTML Help pages. Major themes that come with
|
||||
# Sphinx are currently 'default' and 'sphinxdoc'.
|
||||
# html_theme_path = ["."]
|
||||
# html_theme = '_theme'
|
||||
# html_static_path = ['static']
|
||||
|
||||
# Output file base name for HTML help builder.
|
||||
htmlhelp_basename = '%sdoc' % project
|
||||
|
||||
# Grouping the document tree into LaTeX files. List of tuples
|
||||
# (source start file, target name, title, author, documentclass
|
||||
# [howto/manual]).
|
||||
latex_documents = [
|
||||
('index',
|
||||
'%s.tex' % project,
|
||||
u'%s Documentation' % project,
|
||||
u'OpenStack Foundation', 'manual'),
|
||||
]
|
||||
|
||||
# Example configuration for intersphinx: refer to the Python standard library.
|
||||
#intersphinx_mapping = {'http://docs.python.org/': None}
|
@ -1,4 +0,0 @@
|
||||
============
|
||||
Contributing
|
||||
============
|
||||
.. include:: ../../CONTRIBUTING.rst
|
@ -1,24 +0,0 @@
|
||||
.. catalog documentation master file, created by
|
||||
sphinx-quickstart on Tue Jul 9 22:26:36 2013.
|
||||
You can adapt this file completely to your liking, but it should at least
|
||||
contain the root `toctree` directive.
|
||||
|
||||
Welcome to catalog's documentation!
|
||||
========================================================
|
||||
|
||||
Contents:
|
||||
|
||||
.. toctree::
|
||||
:maxdepth: 2
|
||||
|
||||
readme
|
||||
installation
|
||||
usage
|
||||
contributing
|
||||
|
||||
Indices and tables
|
||||
==================
|
||||
|
||||
* :ref:`genindex`
|
||||
* :ref:`search`
|
||||
|
@ -1,12 +0,0 @@
|
||||
============
|
||||
Installation
|
||||
============
|
||||
|
||||
At the command line::
|
||||
|
||||
$ pip install catalog
|
||||
|
||||
Or, if you have virtualenvwrapper installed::
|
||||
|
||||
$ mkvirtualenv catalog
|
||||
$ pip install catalog
|
@ -1 +0,0 @@
|
||||
.. include:: ../../README.rst
|
@ -1,7 +0,0 @@
|
||||
========
|
||||
Usage
|
||||
========
|
||||
|
||||
To use catalog in a project::
|
||||
|
||||
import openstack_catalog
|
25
manage.py
@ -1,25 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
if __name__ == "__main__":
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE",
|
||||
"openstack_catalog.settings")
|
||||
|
||||
from django.core.management import execute_from_command_line
|
||||
|
||||
execute_from_command_line(sys.argv)
|
@ -1,19 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
import pbr.version
|
||||
|
||||
|
||||
__version__ = pbr.version.VersionInfo(
|
||||
'openstack_catalog').version_string()
|
@ -1,39 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
from flask import Flask
|
||||
from flask import Response
|
||||
|
||||
api = Flask('api')
|
||||
api.debug = True
|
||||
|
||||
|
||||
def cors_allow(resp):
|
||||
h = ['Origin',
|
||||
'Accept-Encoding',
|
||||
'Content-Type',
|
||||
'X-App-Catalog-Versions']
|
||||
resp.headers['Access-Control-Allow-Origin'] = '*'
|
||||
resp.headers['Access-Control-Allow-Headers'] = ', '.join(h)
|
||||
|
||||
|
||||
@api.route('/')
|
||||
def index():
|
||||
data = "v1\n"
|
||||
resp = Response(data, status=200, mimetype='plain/text')
|
||||
cors_allow(resp)
|
||||
return resp
|
||||
|
||||
# Pull in v1 api into the server.
|
||||
from openstack_catalog.api.v1 import * # noqa
|
@ -1,52 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
from flask import request
|
||||
from flask import Response
|
||||
|
||||
from openstack_catalog.api import api
|
||||
from openstack_catalog.api import cors_allow
|
||||
|
||||
from openstack_catalog import settings
|
||||
|
||||
|
||||
@api.route('/v1')
|
||||
def v1_index():
|
||||
data = "assets\nmurano_repo\n"
|
||||
resp = Response(data, status=200, mimetype='plain/text')
|
||||
cors_allow(resp)
|
||||
return resp
|
||||
|
||||
|
||||
@api.route('/v1/assets', methods=['GET', 'OPTIONS'])
|
||||
def assets_index():
|
||||
if request.method == 'OPTIONS':
|
||||
data = ''
|
||||
else:
|
||||
f = open(settings.ASSETS_FILE, 'r')
|
||||
data = f.read()
|
||||
f.close()
|
||||
resp = Response(data, status=200, mimetype='application/json')
|
||||
resp.headers['Access-Control-Max-Age'] = '3600'
|
||||
resp.headers['Cache-Control'] = 'max-age=3600'
|
||||
cors_allow(resp)
|
||||
return resp
|
||||
|
||||
|
||||
@api.route('/v1/murano_repo/<release>/<path:path>')
|
||||
def murano_repo_index(release, path):
|
||||
resp = Response('', status=302)
|
||||
resp.headers['Location'] = \
|
||||
"http://storage.apps.openstack.org/{}".format(path)
|
||||
return resp
|
@ -1,107 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
"""
|
||||
Django settings for openstack_catalog project.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.6/topics/settings/
|
||||
|
||||
For the full list of settings and their values, see
|
||||
https://docs.djangoproject.com/en/1.6/ref/settings/
|
||||
"""
|
||||
|
||||
import os.path
|
||||
|
||||
from openstack_catalog.static_settings import get_staticfiles_dirs
|
||||
|
||||
ASSETS_FILE = 'openstack_catalog/web/api/v1/assets'
|
||||
STATIC_URL = '/static/'
|
||||
STATIC_ROOT = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
'web',
|
||||
'static'))
|
||||
STATICFILES_DIRS = get_staticfiles_dirs(STATIC_URL)
|
||||
|
||||
BASE_DIR = os.path.dirname(os.path.dirname(__file__))
|
||||
|
||||
SECRET_KEY = 'notused'
|
||||
|
||||
DEBUG = True
|
||||
ALLOWED_HOSTS = []
|
||||
|
||||
PROJECT_PATH = os.path.realpath(os.path.dirname(__file__))
|
||||
TEMPLATES = [
|
||||
{
|
||||
'BACKEND': 'django.template.backends.django.DjangoTemplates',
|
||||
'DIRS': [
|
||||
PROJECT_PATH + '/templates/'
|
||||
],
|
||||
'APP_DIRS': True,
|
||||
'OPTIONS': {
|
||||
'context_processors': [
|
||||
'django.contrib.auth.context_processors.auth',
|
||||
'django.template.context_processors.debug',
|
||||
'django.template.context_processors.i18n',
|
||||
'django.template.context_processors.media',
|
||||
'django.template.context_processors.static',
|
||||
'django.template.context_processors.tz',
|
||||
'django.contrib.messages.context_processors.messages',
|
||||
],
|
||||
'debug': True
|
||||
},
|
||||
},
|
||||
]
|
||||
|
||||
COMPRESS_ENABLED = False
|
||||
COMPRESS_CSS_HASHING_METHOD = 'hash'
|
||||
COMPRESS_PARSER = 'compressor.parser.HtmlParser'
|
||||
|
||||
COMPRESS_OFFLINE_CONTEXT = {
|
||||
'STATIC_URL': STATIC_URL,
|
||||
}
|
||||
|
||||
|
||||
STATICFILES_FINDERS = (
|
||||
'django.contrib.staticfiles.finders.FileSystemFinder',
|
||||
'django.contrib.staticfiles.finders.AppDirectoriesFinder',
|
||||
'compressor.finders.CompressorFinder',
|
||||
)
|
||||
|
||||
INSTALLED_APPS = (
|
||||
'django.contrib.auth',
|
||||
'django.contrib.contenttypes',
|
||||
'django.contrib.staticfiles',
|
||||
'compressor',
|
||||
)
|
||||
|
||||
MIDDLEWARE_CLASSES = (
|
||||
'django.middleware.common.CommonMiddleware',
|
||||
)
|
||||
|
||||
ROOT_URLCONF = 'openstack_catalog.urls'
|
||||
WSGI_APPLICATION = 'openstack_catalog.wsgi.application'
|
||||
|
||||
LANGUAGE_CODE = 'en-us'
|
||||
TIME_ZONE = 'UTC'
|
||||
USE_I18N = True
|
||||
USE_L10N = True
|
||||
USE_TZ = True
|
||||
|
||||
# Override some values from local_settings.py if found
|
||||
try:
|
||||
from openstack_catalog.local_settings import * # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
# Static files (CSS, JavaScript, Images)
|
||||
# https://docs.djangoproject.com/en/1.6/howto/static-files/
|
@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
import xstatic.main
|
||||
import xstatic.pkg.angular
|
||||
import xstatic.pkg.magic_search
|
||||
|
||||
|
||||
def get_staticfiles_dirs(webroot='/'):
|
||||
return [
|
||||
('lib/angular',
|
||||
xstatic.main.XStatic(xstatic.pkg.angular,
|
||||
root_url=webroot).base_dir),
|
||||
('lib/magic_search',
|
||||
xstatic.main.XStatic(xstatic.pkg.magic_search,
|
||||
root_url=webroot).base_dir),
|
||||
]
|
@ -1,6 +0,0 @@
|
||||
{% load compress %}
|
||||
|
||||
{% compress js %}
|
||||
<script src="{{ STATIC_URL }}lib/angular/angular.js" type='text/javascript' charset="utf-8"></script>
|
||||
<script src="{{ STATIC_URL }}lib/magic_search/magic_search.js" type='text/javascript' charset="utf-8"></script>
|
||||
{% endcompress %}
|
@ -1,523 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
|
||||
<!-- The above 3 meta tags *must* come first in the head; any other head content must come *after* these tags -->
|
||||
|
||||
<meta name="description" content="OpenStack market place" />
|
||||
<meta name="keywords" content="openstack, glance images, heat templates, murano applications, tosca templates, tosca csar" />
|
||||
<meta name="author" content="Mirantis on behalf of OpenStack Foundation" />
|
||||
|
||||
<title>Community App Catalog</title>
|
||||
|
||||
<link href="/static/images/favicon.ico" rel="shortcut icon" type="image/x-icon" />
|
||||
|
||||
{% include "_scripts.html" %}
|
||||
{% verbatim %}
|
||||
<!-- Bootstrap core CSS -->
|
||||
<link href="//cdn.jsdelivr.net/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" type="text/css" />
|
||||
|
||||
<!-- Custom styles for this template -->
|
||||
<link href="static/css/theme.css" rel="stylesheet" type="text/css" />
|
||||
<link href="//cdn.jsdelivr.net/fontawesome/4.3.0/css/font-awesome.min.css" rel="stylesheet" type="text/css" />
|
||||
<link href="//fonts.googleapis.com/css?family=Open+Sans:400italic,400,700" rel="stylesheet" type="text/css" />
|
||||
|
||||
<link rel="stylesheet" type="text/css" href="//code.jquery.com/ui/1.11.4/themes/cupertino/jquery-ui.css" />
|
||||
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.datatables/1.10.4/css/jquery.dataTables.min.css" />
|
||||
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/select2/3.5.2/select2.css" />
|
||||
|
||||
<!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
|
||||
<!--[if lt IE 9]>
|
||||
<script src="//oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
|
||||
<script src="//oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
|
||||
<![endif]-->
|
||||
</head>
|
||||
|
||||
<body role="document">
|
||||
|
||||
<!-- Google Tag Manager -->
|
||||
<noscript><iframe src="//www.googletagmanager.com/ns.html?id=GTM-K2J65K"
|
||||
height="0" width="0"
|
||||
style="display:none;visibility:hidden"></iframe></noscript>
|
||||
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
|
||||
new Date().getTime(),event:'gtm.js'});var
|
||||
f=d.getElementsByTagName(s)[0],
|
||||
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
|
||||
'//www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
|
||||
})(window,document,'script','dataLayer','GTM-K2J65K');</script>
|
||||
<!-- End Google Tag Manager -->
|
||||
<script>
|
||||
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
|
||||
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
|
||||
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
|
||||
})(window,document,'script','//www.google-analytics.com/analytics.js','ga');
|
||||
ga('create', 'UA-17511903-16', {'allowAnchor': true});
|
||||
ga('send', 'pageview', { 'page': location.pathname + location.search + location.hash});
|
||||
</script>
|
||||
<!-- Fixed navbar -->
|
||||
<div class="masthead navbar-fixed-top">
|
||||
<div class="container">
|
||||
<a class="navbar-brand" href="https://www.openstack.org" target="_blank"></a>
|
||||
<h1><a href="#">Community App Catalog <sup><small>[beta]</small></sup></a></h1>
|
||||
<a href="https://wiki.openstack.org/wiki/App-Catalog#FAQ" target="_blank" class="btn btn-default pull-right">FAQ</a>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-inverse">
|
||||
<div class="container">
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul id="navbar" class="nav navbar-nav">
|
||||
<li><a href="#murano-apps">Murano packages</a></li>
|
||||
<li><a href="#heat-templates">Heat Templates</a></li>
|
||||
<li><a href="#glance-images">Glance Images</a></li>
|
||||
<li><a href="#tosca-templates">TOSCA Templates</a></li>
|
||||
<li><a href="#addContent">Add New Content</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="container" role="main">
|
||||
|
||||
<!-- Main jumbotron for a primary marketing message or call to
|
||||
action -->
|
||||
|
||||
<div id="landing-page" class="content" style="display:none">
|
||||
|
||||
<h1>The OpenStack Application Catalog will help you make applications available on your cloud. </h1>
|
||||
<div class="row featured">
|
||||
|
||||
<div class="col-md-2 col-sm-6">
|
||||
<div class="inner title">
|
||||
<div>Recently Added Apps</div>
|
||||
<p>(Requires OpenStack)</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row pluginbox">
|
||||
<div class="col-sm-2">
|
||||
<a href="https://wiki.openstack.org/wiki/App-Catalog#Horizon_Plugin_for_Native_Access" target="_blank">
|
||||
<img src="static/images/plugin-icon.png">
|
||||
<div class='lbl'>Horizon Plugin</div>
|
||||
</a>
|
||||
</div><div class="col-sm-10">
|
||||
<p><strong>Want this catalog included in your OpenStack environment?</strong></p>
|
||||
<p>There is a Horizon plugin available at <a href="https://git.openstack.org/cgit/openstack/app-catalog-ui" target="_blank">https://git.openstack.org/cgit/openstack/app-catalog-ui</a> which gives users the ability to search and retrieve App Catalog contents directly from Horizon — see <a href="https://wiki.openstack.org/wiki/App-Catalog#Horizon_Plugin_for_Native_Access" target="_blank">https://wiki.openstack.org/wiki/App-Catalog#Horizon_Plugin_for_Native_Access</a> for more details. Add it to your environment today!</p>
|
||||
</div>
|
||||
</div>
|
||||
<p><strong>Don't have OpenStack yet?</strong></p>
|
||||
<p>Visit the <a href="https://www.openstack.org/marketplace/" target="_blank">OpenStack Marketplace</a> and select tools and methods for building your cloud. Then come back to the OpenStack Application Catalog to make your cloud sing with applications.</p>
|
||||
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-4 bluebox">
|
||||
<div class="inner">
|
||||
<a href="#tab=murano-apps">
|
||||
<h2>Murano Packages</h2>
|
||||
<img src="static/images/murano-diagram.png">
|
||||
</a>
|
||||
<p>
|
||||
In Murano Packages you will find complete
|
||||
applications, in both simple and clustered configurations, ready to deploy
|
||||
on your cloud. To use them:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Verify that you have <A href="http://docs.openstack.org/developer/murano/" target="_blank">Murano</a> installed</li>
|
||||
<li>Browse the list and find the app package you want</li>
|
||||
<li>Highlight and copy the name of the app package</li>
|
||||
<li>In Horizon, navigate to Murano > Manage > Package Definitions and click Import Package</li>
|
||||
<li>Paste the app package name into the labeled text field, and click Next. This will download and install the package components.</li>
|
||||
<li>Now deploy the app on your cloud by navigating to Application Catalog > Environments, then creating and deploying that environment.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 bluebox">
|
||||
<div class="inner">
|
||||
<a href="#tab=heat-templates">
|
||||
<h2>Heat Templates</h2>
|
||||
<img src="static/images/heat-diagram.png"
|
||||
class="text-center">
|
||||
</a>
|
||||
<p>
|
||||
In Heat Templates you will find templates for creating
|
||||
complete stacks in your cloud. To use them:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Browse the list and find the one you want</li>
|
||||
<li>Download the template yaml (.yml) file to your local machine</li>
|
||||
<li>Use Horizon to add the template to Heat (by uploading it via file selector, or copy/pasting it into the editable field)</li>
|
||||
<li>Use the <a href="http://docs.openstack.org/cli-reference/heat.html" target="_blank">Heat client</a> to create a stack</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 bluebox">
|
||||
<div class="inner">
|
||||
<a href="#tab=glance-images">
|
||||
<h2>Glance Images</h2>
|
||||
<img src="static/images/glance-diagram.png">
|
||||
</a>
|
||||
<br/><br/>
|
||||
<p>
|
||||
In Glance Images you will find a library of
|
||||
preconfigured images ready to launch virtual machines
|
||||
on your cloud. To use them:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Browse the list and find the one you want</li>
|
||||
<li>Copy the URL for the image file</li>
|
||||
<li>Use the <a href="http://docs.openstack.org/cli-reference/glance.html" target="_blank">Glance client</a> to add it to your cloud with the --copy-from option, or add the image from Horizon by creating a new image, and specifying the URL as the image location.</li>
|
||||
<li>You can use Nova to launch a VM from the new image; or, you can choose an image to launch from the Glance images list shown in Horizon. Of course, if a service is preconfigured to launch VMs by itself directly from specific guest images, you're good to go.
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="col-md-4 bluebox">
|
||||
<div class="inner">
|
||||
<a href="#tab=tosca-templates">
|
||||
<h2>TOSCA Templates</h2>
|
||||
<img src="static/images/tosca-diagram.png"
|
||||
class="text-center">
|
||||
</a>
|
||||
<p>
|
||||
In TOSCA Templates you will find templates and Cloud Service Archives (CSAR). To use them:
|
||||
</p>
|
||||
<ol>
|
||||
<li>Browse the list and find the one you want</li>
|
||||
<li>Download the raw template file or CSAR to your local machine</li>
|
||||
<li>Use the template or CSAR per your need</li>
|
||||
<li>To deploy template with OpenStack Heat, provide the template or CSAR to the OpenStack <a href="http://docs.openstack.org/developer/heat-translator/usage.html" target="_blank">Heat-Translator</a> which will produce a Heat Orchestration Template (HOT) as an output.</li>
|
||||
<li>To simply parse the template, use it with OpenStack <a href="http://docs.openstack.org/developer/tosca-parser/usage.html" target="_blank">TOSCA-Parser</a> project.</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<p><strong>Contributing to the OpenStack Application Catalog</strong></p>
|
||||
<p>
|
||||
The application catalog is built from the YAML files found in the
|
||||
<a href="https://git.openstack.org/cgit/openstack/app-catalog" target="_blank">repository</a>.
|
||||
Consistent with other OpenStack projects, additions to the
|
||||
catalog take the form of git commits which are reviewed with Gerrit
|
||||
prior to being merged. Detailed instructions for adding to
|
||||
the YAML files can be found on the
|
||||
<a href="https://wiki.openstack.org/wiki/App-Catalog" target="_blank">
|
||||
OpenStack wiki</a>.
|
||||
</p>
|
||||
<p><strong>Catalogue Disclaimer</strong></p>
|
||||
<p>Please keep in mind that this catalog contains content from many sources,
|
||||
contributed by the community, for the community. The OpenStack Foundation is not endorsing any particular item listed. Read the <a href="https://wiki.openstack.org/wiki/App-Catalog/Catalogue_Disclaimer" target="_blank">Catalog Disclaimer</a> for additional information.</p>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
|
||||
<div id="glance-images" class="content" style="display:none">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 filters">
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table id="glance-images-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Image Name</th>
|
||||
<th>Description</th>
|
||||
<th>Format</th>
|
||||
<th>License</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="heat-templates" class="content" style="display:none">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 filters">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label>Release</label>
|
||||
<input type="hidden" id="heat-release"
|
||||
style="width:10em" data-placeholder="Any release"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table id="heat-templates-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Template Name</th>
|
||||
<th>Description</th>
|
||||
<th>Release</th>
|
||||
<th>Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="murano-apps" class="content" style="display:none">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 filters">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label>Release</label>
|
||||
<input type="hidden" id="murano-release"
|
||||
style="width:10em" data-placeholder="Any release"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table id="murano-apps-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Package Name</th>
|
||||
<th>Description</th>
|
||||
<th>Release</th>
|
||||
<th>Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="tosca-templates" class="content" style="display:none">
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6 filters">
|
||||
<form class="form-inline">
|
||||
<div class="form-group">
|
||||
<label>Release</label>
|
||||
<input type="hidden" id="tosca-release"
|
||||
style="width:10em" data-placeholder="Any release"/>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<table id="tosca-templates-table" class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Template Name</th>
|
||||
<th>Description</th>
|
||||
<th>Release</th>
|
||||
<th>Format</th>
|
||||
</tr>
|
||||
</thead>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div id="info-page" class="content">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<div id="info-content"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="info-dialog" title="Details">
|
||||
<div id="info-container"></div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- core JavaScript
|
||||
================================================== -->
|
||||
<!-- Placed at the end of the document so the pages load faster -->
|
||||
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery/2.1.3/jquery.min.js"></script>
|
||||
<script type="text/javascript" src="//code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
|
||||
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.datatables/1.10.4/js/jquery.dataTables.min.js"></script>
|
||||
<script type="text/javascript" src="//cdn.jsdelivr.net/select2/3.5.2/select2.min.js"></script>
|
||||
<script type="text/javascript" src="//ajax.microsoft.com/ajax/jquery.templates/beta1/jquery.tmpl.min.js"></script>
|
||||
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.timeago/1.4.1/jquery.timeago.js"></script>
|
||||
<script type="text/javascript" src="//cdnjs.cloudflare.com/ajax/libs/jquery.matchHeight/0.6.0/jquery.matchHeight-min.js"></script>
|
||||
|
||||
<script type="text/javascript" src="static/js/apps-catalog.js"></script>
|
||||
|
||||
<script type="text/javascript">
|
||||
$(function() { initMarketPlace (); });
|
||||
$(document).ready(function () { ; } );
|
||||
</script>
|
||||
|
||||
<script id="glance-images-info" type="text/x-jquery-tmpl">
|
||||
|
||||
<h2>${name} (${service['disk_format']})</h2>
|
||||
<div>
|
||||
<span class="label">Last modified: </span><span class="value">${last_modified}</span>
|
||||
</div>
|
||||
<div>
|
||||
{{if attributes['url']}}
|
||||
<span class="label">glance image-create:</span>
|
||||
<input type="text" value="glance --os-image-api-version 1 image-create --copy-from ${attributes['url']} --disk-format ${service['disk_format']} --container-format ${service['container_format']} --name '${name}'" onfocus="this.select();" onmouseup="return false;">
|
||||
{{else}}
|
||||
<span class="label">Website where the image can be downloaded:</span>
|
||||
<a href="${attributes['indirect_url']}">Link...</a>
|
||||
{{/if}}
|
||||
</div>
|
||||
{{if supported_by}}
|
||||
<div><span class="label">Supported by</span> <span class="value">${supported_by.name}</span></div>
|
||||
{{/if}}
|
||||
{{if license}}
|
||||
{{if license_url}}
|
||||
<div><span class="label">License</span> <a href="${license_url}"> <span class="value">${license}</span></a></div>
|
||||
{{else}}
|
||||
<div><span class="label">License</span> <span class="value">${license}</span></div>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
{{if cloud_user}}
|
||||
<div><span class="label">Cloud User</span> <span class="value">${cloud_user}</span></div>
|
||||
{{/if}}
|
||||
<div><span class="label">Description:</span> <span class="value">${description}</span></div>
|
||||
{{if hash }}
|
||||
<div><span class="label">Hash:</span> <span class="value">${hash}</span></div>
|
||||
{{/if}}
|
||||
|
||||
<h3>Author</h3>
|
||||
<div><span class="label">Contact:
|
||||
</span><a href="${provided_by.href}"> <span class="value">${provided_by.name}</span> </a></div>
|
||||
<div><span class="label">Company:</span> <span class="value">${provided_by.company}</span></div>
|
||||
|
||||
{{if attributes }}
|
||||
<h3>Attributes</h3>
|
||||
{{each( key, value ) attributes }}
|
||||
<div><span class="label">${key}:</span> <span class="value">${value}</span></div>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
</script>
|
||||
|
||||
<script id="heat-templates-info" type="text/x-jquery-tmpl">
|
||||
|
||||
<h2>${name} (${service['format']})</h2>
|
||||
<div>
|
||||
<span class="label">Last modified: </span><span class="value">${last_modified}</span>
|
||||
</div>
|
||||
{{if supported_by}}
|
||||
<div><span class="label">Supported by</span> <span class="value">${supported_by.name}</span></div>
|
||||
{{/if}}
|
||||
<div><span class="label">Description:</span> <span class="value">${description}</span></div>
|
||||
<div><span class="label">Available in Releases:</span> <span class="value">${release_html}</span></div>
|
||||
|
||||
<h3>Author</h3>
|
||||
<div><span class="label">Contact:
|
||||
</span><a href="${provided_by.href}"> <span class="value">${provided_by.name}</span> </a></div>
|
||||
<div><span class="label">Company:</span> <span class="value">${provided_by.company}</span></div>
|
||||
|
||||
{{if attributes }}
|
||||
<h3>Attributes</h3>
|
||||
{{each( key, value ) attributes }}
|
||||
<div><span class="label">${key}:</span> <span class="value">${value}</span></div>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
</script>
|
||||
|
||||
<script id="murano-apps-info" type="text/x-jquery-tmpl">
|
||||
|
||||
<h2>${name} ({{if service.type == "bundle"}}bundle{{else}}${service.format}{{/if}})</h2>
|
||||
<div>
|
||||
<span class="label">Last modified: </span><span class="value">${last_modified}</span>
|
||||
</div>
|
||||
<div>
|
||||
<span class="label">{{if service.format == 'package'}}Package{{else}}Bundle{{/if}} name:</span>
|
||||
{{if service.type == 'bundle'}}
|
||||
<input type="text" value="${service.murano_package_name}" onfocus="this.select();" onmouseup="return false;">
|
||||
{{else}}
|
||||
<input type="text" value="${service.package_name}" onfocus="this.select();" onmouseup="return false;">
|
||||
{{/if}}
|
||||
</div>
|
||||
|
||||
<h3>Description</h3>
|
||||
<div><span class="value">${description}</span></div>
|
||||
|
||||
<h3>Supported OpenStack Releases</h3>
|
||||
<div><span class="value">${release_html}</span></div>
|
||||
|
||||
<h3>Author</h3>
|
||||
<div><span class="label">Contact: </span><a href="${provided_by.href}"> <span class="value">${provided_by.name}</span> </a></div>
|
||||
<div><span class="label">Company:</span> <span class="value">${provided_by.company}</span></div>
|
||||
|
||||
{{if depends }}
|
||||
<h3>Depends On</h3>
|
||||
<p>Package may depend on image and on other packages, during import of
|
||||
this package to Murano following dependencies will be also downloaded
|
||||
and imported, but existing entries will not be overwritten.</p>
|
||||
{{if depends }}
|
||||
Dependencies:
|
||||
<ul>
|
||||
{{each depends }}
|
||||
<li>${depends[$index]['name']}</li>
|
||||
{{/each}}
|
||||
</ul>
|
||||
{{/if}}
|
||||
{{/if}}
|
||||
|
||||
{{if attributes }}
|
||||
<h3>Attributes</h3>
|
||||
{{each( key, value ) attributes }}
|
||||
<div><span class="label">${key}:</span> <span class="value">${value}</span></div>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
</script>
|
||||
|
||||
<script id="tosca-templates-info" type="text/x-jquery-tmpl">
|
||||
|
||||
<h2>${name} (${service['template_format']})</h2>
|
||||
<div>
|
||||
<span class="label">Last modified: </span><span class="value">${last_modified}</span>
|
||||
</div>
|
||||
{{if supported_by}}
|
||||
<div><span class="label">Supported by</span> <span class="value">${supported_by.name}</span></div>
|
||||
{{/if}}
|
||||
<div><span class="label">Description:</span> <span class="value">${description}</span></div>
|
||||
<div><span class="label">Available in Releases:</span> <span class="value">${release_html}</span></div>
|
||||
|
||||
<h3>Author</h3>
|
||||
<div><span class="label">Contact:
|
||||
</span><a href="${provided_by.href}"> <span class="value">${provided_by.name}</span> </a></div>
|
||||
<div><span class="label">Company:</span> <span class="value">${provided_by.company}</span></div>
|
||||
|
||||
{{if attributes }}
|
||||
<h3>Attributes</h3>
|
||||
{{each( key, value ) attributes }}
|
||||
<div><span class="label">${key}:</span> <span class="value">${value}</span></div>
|
||||
{{/each}}
|
||||
{{/if}}
|
||||
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
{% endverbatim %}
|
@ -1,61 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
"""
|
||||
test_openstack_catalog
|
||||
----------------------------------
|
||||
|
||||
Tests for `openstack_catalog` module.
|
||||
"""
|
||||
|
||||
import functools
|
||||
import jsonschema
|
||||
import six
|
||||
import testtools
|
||||
import yaml
|
||||
|
||||
|
||||
class TestOpenstack_catalog(testtools.TestCase):
|
||||
def setUp(self):
|
||||
super(TestOpenstack_catalog, self).setUp()
|
||||
|
||||
def _read_raw_file(self, file_name):
|
||||
if six.PY3:
|
||||
opener = functools.partial(open, encoding='utf8')
|
||||
else:
|
||||
opener = open
|
||||
with opener(file_name, 'r') as content_file:
|
||||
return content_file.read()
|
||||
|
||||
def _read_file(self, file_name):
|
||||
return yaml.safe_load(self._read_raw_file(file_name))
|
||||
|
||||
def _verify_by_schema(self, file_name, schema):
|
||||
data = self._read_file(file_name)
|
||||
schema = self._read_file(schema)
|
||||
names = {}
|
||||
for asset in data['assets']:
|
||||
name = asset['name']
|
||||
if name in names:
|
||||
self.fail("Duplicate asset name: %s" % name)
|
||||
names[name] = True
|
||||
try:
|
||||
jsonschema.validate(data, schema)
|
||||
except jsonschema.ValidationError as e:
|
||||
self.fail(e)
|
||||
|
||||
def test_asset_schema_conformance(self):
|
||||
self._verify_by_schema(
|
||||
'openstack_catalog/web/static/assets.yaml',
|
||||
'openstack_catalog/web/static/assets.schema.yaml')
|
@ -1,8 +0,0 @@
|
||||
from django.conf.urls import url
|
||||
from django.contrib.staticfiles.urls import staticfiles_urlpatterns
|
||||
|
||||
from openstack_catalog import views
|
||||
|
||||
urlpatterns = [url(r'^$', views.index)]
|
||||
|
||||
urlpatterns += staticfiles_urlpatterns()
|
@ -1,5 +0,0 @@
|
||||
from django.shortcuts import render
|
||||
|
||||
|
||||
def index(request):
|
||||
return render(request, 'index.html', {})
|
@ -1,274 +0,0 @@
|
||||
---
|
||||
$schema: http://json-schema.org/draft-04/schema#
|
||||
type: object
|
||||
required:
|
||||
- assets
|
||||
properties:
|
||||
assets:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- service
|
||||
- name
|
||||
- provided_by
|
||||
- description
|
||||
- license
|
||||
additionalProperties: false
|
||||
properties:
|
||||
active:
|
||||
type: boolean
|
||||
hash_url:
|
||||
type: string
|
||||
hash:
|
||||
type: string
|
||||
service:
|
||||
oneOf:
|
||||
- $ref: "#/definitions/glance"
|
||||
- $ref: "#/definitions/heat"
|
||||
- $ref: "#/definitions/murano"
|
||||
- $ref: "#/definitions/bundle"
|
||||
- $ref: "#/definitions/tosca"
|
||||
name:
|
||||
type: string
|
||||
tags:
|
||||
type: array
|
||||
items:
|
||||
enum:
|
||||
- app
|
||||
depends:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
release:
|
||||
type: array
|
||||
items:
|
||||
enum:
|
||||
- Austin
|
||||
- Bexar
|
||||
- Cactus
|
||||
- Diablo
|
||||
- Essex
|
||||
- Folsom
|
||||
- Grizzly
|
||||
- Havana
|
||||
- Icehouse
|
||||
- Juno
|
||||
- Kilo
|
||||
- Liberty
|
||||
- Mitaka
|
||||
- Newton
|
||||
- Ocata
|
||||
- Pike
|
||||
minItems: 1
|
||||
provided_by:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
- href
|
||||
- company
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
href:
|
||||
type: string
|
||||
pattern: "^((https?://)[a-z][a-z0-9_-]+(\\.[a-z][a-z0-9_-]+)+(/[a-z0-9\\._/~%\\-\\+&\\#\\?!=\\(\\)@]*)?)|(mailto:[a-z][a-z0-9._-]+@[a-z][a-z0-9_-]+(\\.[a-z][a-z0-9_-]+)+)$"
|
||||
company:
|
||||
type: string
|
||||
supported_by:
|
||||
type: object
|
||||
required:
|
||||
- name
|
||||
additionalProperties: false
|
||||
properties:
|
||||
name:
|
||||
type: string
|
||||
href:
|
||||
type: string
|
||||
pattern: "^((https?://)[a-z][a-z0-9_-]+(\\.[a-z][a-z0-9_-]+)+(/[a-z0-9\\._/~%\\-\\+&\\#\\?!=\\(\\)@]*)?)|(mailto:[a-z][a-z0-9._-]+@[a-z][a-z0-9_-]+(\\.[a-z][a-z0-9_-]+)+)$"
|
||||
company:
|
||||
type: string
|
||||
icon:
|
||||
type: object
|
||||
required:
|
||||
- top
|
||||
- left
|
||||
- height
|
||||
- url
|
||||
additionalProperties: false
|
||||
properties:
|
||||
top:
|
||||
type: number
|
||||
left:
|
||||
type: number
|
||||
height:
|
||||
type: number
|
||||
url:
|
||||
type: string
|
||||
pattern: "^((https?://)[a-z][a-z0-9_-]*(\\.[a-z][a-z0-9_-]*)+(/[a-z0-9\\._/~%\\-\\+&\\#\\?!=\\(\\)@]*)?)"
|
||||
description:
|
||||
type: string
|
||||
license:
|
||||
type: string
|
||||
pattern: "^(GPL .*)|(Apache .*)|(BSD .*)|(MIT)|(Free <= [0-9]+ (Users|Nodes))|(Multi-licensed OpenSource)|(Other)|(Unknown)$"
|
||||
license_url:
|
||||
type: string
|
||||
pattern: "^((https?://)[a-z][a-z0-9_-]+(\\.[a-z][a-z0-9_-]+)+(/[a-z0-9\\._/~%\\-\\+&\\#\\?!=\\(\\)@]*)?)$"
|
||||
cloud_user:
|
||||
type: string
|
||||
attributes:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
patternProperties:
|
||||
.*:
|
||||
type:
|
||||
- string
|
||||
- number
|
||||
definitions:
|
||||
glance:
|
||||
required:
|
||||
- type
|
||||
- container_format
|
||||
- disk_format
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- glance
|
||||
container_format:
|
||||
enum:
|
||||
- ami
|
||||
- ari
|
||||
- aki
|
||||
- bare
|
||||
- ovf
|
||||
disk_format:
|
||||
enum:
|
||||
- ami
|
||||
- ari
|
||||
- aki
|
||||
- vhd
|
||||
- vmdk
|
||||
- raw
|
||||
- qcow2
|
||||
- vdi
|
||||
- iso
|
||||
min_ram:
|
||||
type: number
|
||||
min_disk:
|
||||
type: number
|
||||
additionalProperties: false
|
||||
heat:
|
||||
required:
|
||||
- type
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- heat
|
||||
environment:
|
||||
type: object
|
||||
additionalProperties: true
|
||||
ever:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
min:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
max:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
murano:
|
||||
required:
|
||||
- type
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- murano
|
||||
format:
|
||||
type: string
|
||||
enum:
|
||||
- package
|
||||
package_name:
|
||||
type: string
|
||||
ever:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
min:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
max:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
bundle:
|
||||
required:
|
||||
- type
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- bundle
|
||||
murano_package_name:
|
||||
type: string
|
||||
|
||||
tosca:
|
||||
required:
|
||||
- type
|
||||
- template_format
|
||||
additionalProperties: false
|
||||
properties:
|
||||
type:
|
||||
type: string
|
||||
enum:
|
||||
- tosca
|
||||
template_format:
|
||||
type: string
|
||||
enum:
|
||||
- yaml
|
||||
- csar
|
||||
ever:
|
||||
type: array
|
||||
items:
|
||||
type: object
|
||||
additionalProperties: false
|
||||
properties:
|
||||
min:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
||||
max:
|
||||
type: array
|
||||
items:
|
||||
type: number
|
||||
minItems: 3
|
||||
maxItems: 3
|
@ -1,2 +0,0 @@
|
||||
assets:
|
||||
stackato-3.4.2-murano-agent: {active: false}
|
@ -1,225 +0,0 @@
|
||||
|
||||
h1, h2, h3, h4, h5, h6 {
|
||||
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
}
|
||||
body {
|
||||
padding-top: 133px;
|
||||
padding-bottom: 30px;
|
||||
}
|
||||
a {
|
||||
color: #30739c;
|
||||
}
|
||||
.masthead {
|
||||
background: #fff;
|
||||
}
|
||||
.masthead h1 {
|
||||
display: inline-block;
|
||||
border-left: 1px solid #ccc;
|
||||
padding-left: 20px;
|
||||
margin-left: 20px;
|
||||
height: 33px;
|
||||
line-height: 33px;
|
||||
font-size: 21px;
|
||||
color: #264d69;
|
||||
}
|
||||
.navbar {
|
||||
margin: 0;
|
||||
border-radius: 0;
|
||||
border: none;
|
||||
}
|
||||
.navbar-brand {
|
||||
width: 136px;
|
||||
height: 33px;
|
||||
background: url(../images/openstack-logo.png) no-repeat;
|
||||
display: block;
|
||||
padding: 0;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.navbar-inverse {
|
||||
background: #edf2f7;
|
||||
border: none;
|
||||
padding: 10px 0;
|
||||
}
|
||||
.navbar-inverse .navbar-nav>li>a {
|
||||
color: #486278;
|
||||
padding-top: 10px;
|
||||
padding-bottom: 10px;
|
||||
border-radius: 5px;
|
||||
margin-right: 10px;
|
||||
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
text-transform: uppercase;
|
||||
}
|
||||
.navbar-inverse .navbar-nav>.active>a, .navbar-inverse .navbar-nav>.open>a {
|
||||
background: #fff;
|
||||
box-shadow: none;
|
||||
color: #486278;
|
||||
}
|
||||
.navbar-inverse .navbar-nav>li>a:focus {
|
||||
color: #486278;
|
||||
}
|
||||
.navbar-inverse .navbar-nav>li>a:hover, .navbar-inverse .navbar-nav>.active>a:focus, .navbar-inverse .navbar-nav>.active>a:hover {
|
||||
background: #fff;
|
||||
color: #486278;
|
||||
}
|
||||
.filters #supported-by {
|
||||
margin-right: 20px;
|
||||
}
|
||||
.form-inline label {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.table th {
|
||||
font-weight: 400;
|
||||
color: #30739c;
|
||||
}
|
||||
.table tr td:first-child {
|
||||
font-weight: 700;
|
||||
}
|
||||
.table tr td:last-child {
|
||||
white-space: nowrap;
|
||||
}
|
||||
.content {
|
||||
font-family: "Open Sans","Helvetica Neue",Helvetica,Arial,sans-serif;
|
||||
padding: 25px 0;
|
||||
}
|
||||
.btn {
|
||||
border-radius: 0;
|
||||
}
|
||||
a.details {
|
||||
text-transform: uppercase;
|
||||
font-weight: 700;
|
||||
font-size: .9em;
|
||||
}
|
||||
a.details i {
|
||||
background: #30739c;
|
||||
color: #fff;
|
||||
display: inline-block;
|
||||
padding: 2px 3px;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.bluebox .inner {
|
||||
background-color: #edf2f7;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.bluebox h2 {
|
||||
margin-top: 0;
|
||||
color: #3597da;
|
||||
font-size: 24px;
|
||||
}
|
||||
.bluebox img {
|
||||
margin: 20px auto;
|
||||
text-align: center;
|
||||
}
|
||||
.featured {
|
||||
}
|
||||
.featured .inner {
|
||||
padding: 15px;
|
||||
border: 1px #ccc solid;
|
||||
border-radius: 4px;
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.featured img {
|
||||
max-width: 100%;
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
.featured .inner p {
|
||||
margin-bottom: 0;
|
||||
font-size: .9em;
|
||||
}
|
||||
.pluginbox {
|
||||
background-color: #edf2f7;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
.pluginbox .lbl {
|
||||
text-align: center;
|
||||
}
|
||||
.title div {
|
||||
font-size: 18px;
|
||||
text-transform: uppercase;
|
||||
color: #fff;
|
||||
text-align: left;
|
||||
font-weight: 700;
|
||||
}
|
||||
.title {
|
||||
text-align: left;
|
||||
color: #fff;
|
||||
background: #3597da;
|
||||
border: none;
|
||||
}
|
||||
h1 {
|
||||
color: #2A4E68;
|
||||
font-weight: 300;
|
||||
font-size: 28px;
|
||||
}
|
||||
.featured .glance {
|
||||
background: url(../images/featured-corner-glance.png) no-repeat;
|
||||
background-position: top right;
|
||||
}
|
||||
.featured .heat {
|
||||
background: url(../images/featured-corner-heat.png) no-repeat;
|
||||
background-position: top right;
|
||||
}
|
||||
.featured .murano {
|
||||
background: url(../images/featured-corner-murano.png) no-repeat;
|
||||
background-position: top right;
|
||||
}
|
||||
.filters {
|
||||
z-index: 1;
|
||||
position: relative;
|
||||
}
|
||||
.navbar-fixed-top {
|
||||
z-index: 2;
|
||||
}
|
||||
.dataTables_wrapper {
|
||||
z-index: 0;
|
||||
top: -27px;
|
||||
}
|
||||
.dataTables_length {
|
||||
float: right !important;
|
||||
}
|
||||
.dataTables_filter {
|
||||
margin: 0 20px 20px 0;
|
||||
}
|
||||
.dataTables_filter input {
|
||||
width: 70%;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 4px;
|
||||
}
|
||||
.ui-widget-overlay {
|
||||
background-image: none !important;
|
||||
background: #000 !important;
|
||||
opacity: 0.6 !important;
|
||||
}
|
||||
.ui-dialog-titlebar {
|
||||
display: none;
|
||||
}
|
||||
.ui-dialog h2 {
|
||||
margin-top: 0;
|
||||
color: #30739c;
|
||||
}
|
||||
.ui-dialog h3 {
|
||||
color: #2a4e68;
|
||||
}
|
||||
.ui-widget-content {
|
||||
background-image: none !important;
|
||||
}
|
||||
.ui-state-default {
|
||||
background: none !important;
|
||||
border: 1px solid #999 !important;
|
||||
color: #666 !important;
|
||||
}
|
||||
.label {
|
||||
font-size: 100% !important;
|
||||
color: #000 !important;
|
||||
}
|
||||
.masthead h1 a:active, .masthead h1 a:focus {
|
||||
text-decoration: none;
|
||||
}
|
||||
.form-group {
|
||||
margin-left: 15px;
|
||||
}
|
||||
input[type=text] {
|
||||
width: 250px;
|
||||
}
|
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 1.1 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.4 KiB |
Before Width: | Height: | Size: 1.7 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 20 KiB |
Before Width: | Height: | Size: 19 KiB |
Before Width: | Height: | Size: 3.3 KiB |
Before Width: | Height: | Size: 10 KiB |
Before Width: | Height: | Size: 18 KiB |
Before Width: | Height: | Size: 9.6 KiB |
Before Width: | Height: | Size: 8.5 KiB |
Before Width: | Height: | Size: 8.2 KiB |
Before Width: | Height: | Size: 4.2 KiB |
Before Width: | Height: | Size: 5.0 KiB |
Before Width: | Height: | Size: 12 KiB |
Before Width: | Height: | Size: 8.6 KiB |
Before Width: | Height: | Size: 7.8 KiB |
Before Width: | Height: | Size: 11 KiB |
Before Width: | Height: | Size: 6.6 KiB |
Before Width: | Height: | Size: 5.5 KiB |
Before Width: | Height: | Size: 3.4 KiB |
Before Width: | Height: | Size: 61 KiB |
@ -1,418 +0,0 @@
|
||||
function getUrlVars() {
|
||||
"use strict";
|
||||
var vars = {};
|
||||
window.location.href.replace(/[?&#]+([^=&]+)=([^&#]*)/gi, function (m, key, value) {
|
||||
vars[key] = decodeURIComponent(value);
|
||||
});
|
||||
return vars;
|
||||
}
|
||||
|
||||
function make_uri(uri, options) {
|
||||
"use strict";
|
||||
var ops = {};
|
||||
$.extend(ops, getUrlVars());
|
||||
if (options !== null) {
|
||||
$.extend(ops, options);
|
||||
}
|
||||
var str = $.map(ops, function (val, index) {
|
||||
return index + "=" + encodeURIComponent(val).toLowerCase();
|
||||
}).join("&");
|
||||
|
||||
return (str === "") ? uri : uri + "?" + str;
|
||||
}
|
||||
|
||||
function reload(extra) {
|
||||
"use strict";
|
||||
window.location.search = make_uri ("", extra);
|
||||
}
|
||||
|
||||
function update_url(extra) {
|
||||
var ops = {};
|
||||
$.extend(ops, getUrlVars ());
|
||||
if (extra !== null) {
|
||||
$.extend(ops, extra);
|
||||
}
|
||||
window.location.hash = $.map(ops, function (val, index) {
|
||||
return val ? (index + "=" + encodeURIComponent(val)) : null;
|
||||
}).join("&");
|
||||
}
|
||||
|
||||
function initSingleSelector(selector_id, property, dataSet, update_handler) {
|
||||
var values = {};
|
||||
var result = [];
|
||||
var value, key;
|
||||
|
||||
for (var i = 0; i < dataSet.length; i++) {
|
||||
var element = dataSet[i][property];
|
||||
if (element instanceof Array) {
|
||||
for (key in element)
|
||||
if (key) {
|
||||
values[element[key]] = element[key];
|
||||
}
|
||||
} else {
|
||||
values[element] = element;
|
||||
}
|
||||
}
|
||||
|
||||
for (value in values)
|
||||
if (value) {
|
||||
result.push({"id": value, "text": value});
|
||||
}
|
||||
|
||||
$("#" + selector_id).
|
||||
val (getUrlVars()[property]).
|
||||
on("select2-selecting", function (e) {
|
||||
var options = {};
|
||||
options[property] = e.val;
|
||||
update_url (options);
|
||||
update_handler ();
|
||||
}).
|
||||
on("select2-removed", function (e) {
|
||||
var options = {};
|
||||
options[property] = '';
|
||||
update_url (options);
|
||||
update_handler ();
|
||||
}).
|
||||
select2({data: result, allowClear: true});
|
||||
}
|
||||
|
||||
function filterData (tableData, filters) {
|
||||
var filteredData = [];
|
||||
var key, column;
|
||||
|
||||
for (var i = 0; i < tableData.length; i++) {
|
||||
var row = tableData[i];
|
||||
var filtered = true;
|
||||
|
||||
for (column in filters) {
|
||||
if (column in row) {
|
||||
if (row[column] instanceof Array) {
|
||||
filtered = false;
|
||||
for (key in row[column])
|
||||
if (filters[column] == row[column][key]) {
|
||||
filtered = true;
|
||||
}
|
||||
} else {
|
||||
if (filters[column] != row[column]) {
|
||||
filtered = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (filtered == false) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (filtered) {
|
||||
filteredData.push(row);
|
||||
}
|
||||
}
|
||||
|
||||
return filteredData;
|
||||
}
|
||||
|
||||
function populate_table (table_id, table_column_names, tableData)
|
||||
{
|
||||
var tableColumns = [];
|
||||
for (var i = 0; i < table_column_names.length; i++) {
|
||||
tableColumns.push({"mData": table_column_names[i]});
|
||||
for (var j = 0; j < tableData.length; j++) {
|
||||
if (!(table_column_names[i] in tableData[j])) {
|
||||
tableData[j][table_column_names[i]] = "";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (table_id) {
|
||||
$("#" + table_id).dataTable({
|
||||
"aLengthMenu": [
|
||||
[5, 10, 25, 50, -1],
|
||||
[5, 10, 25, 50, "All"]
|
||||
],
|
||||
"bDestroy": true,
|
||||
"iDisplayLength": -1,
|
||||
"bAutoWidth": false,
|
||||
"bPaginate": true,
|
||||
"pagingType": "full_numbers",
|
||||
"aaData": tableData,
|
||||
"aoColumns": tableColumns
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function showInfoDialog (tab, info) {
|
||||
$("#info-container").empty();
|
||||
$("#" + tab + "-info").tmpl(info).appendTo("#info-container");
|
||||
$("#info-dialog").dialog("open");
|
||||
$("button").focus ();
|
||||
}
|
||||
|
||||
function showInfoPage (tab, info)
|
||||
{
|
||||
$("#info-content").empty();
|
||||
$("#" + tab + "-info").tmpl(info).appendTo("#info-content");
|
||||
$( ".content" ).hide ();
|
||||
$( "#info-page" ).show ();
|
||||
update_url ({ tab : tab, asset : info.name});
|
||||
$(".value").replaceWith (function(idx, element) {
|
||||
return element.replace (/https?:\/\/[^ \t\n\r]+/gi, '<a target="_blank" href="$&">$&</a>');
|
||||
});
|
||||
}
|
||||
|
||||
function setupInfoHandler (tab, element_id, info) {
|
||||
info.name_html = "<a id=\"" + tab + "-" + element_id +
|
||||
"\" href=\"#\" title=\"Show details\">" + info.name + "</a>";
|
||||
|
||||
$("#" + tab + "-table").on("click", "#" + tab + "-" + element_id, function (event) {
|
||||
event.preventDefault();
|
||||
event.stopPropagation();
|
||||
|
||||
showInfoPage (tab, info);
|
||||
});
|
||||
}
|
||||
|
||||
var assets = { assets: [] };
|
||||
var glance_images = { assets: [] };
|
||||
|
||||
function show_glance_images ()
|
||||
{
|
||||
populate_table ("glance-images-table",
|
||||
["name_html", "description", "service.disk_format", "license"],
|
||||
filterData (glance_images.assets, getUrlVars ()));
|
||||
}
|
||||
|
||||
var heat_templates = { assets: [] };
|
||||
|
||||
function show_heat_templates ()
|
||||
{
|
||||
populate_table ("heat-templates-table",
|
||||
["name_html", "description", "release_html", "service.format"],
|
||||
filterData (heat_templates.assets, getUrlVars ()));
|
||||
}
|
||||
|
||||
var murano_apps = { assets: [] };
|
||||
|
||||
function show_murano_apps ()
|
||||
{
|
||||
populate_table ("murano-apps-table",
|
||||
["name_html", "description", "release_html", "service.format"],
|
||||
filterData (murano_apps.assets, getUrlVars ()));
|
||||
}
|
||||
|
||||
var tosca_templates = { assets: [] };
|
||||
|
||||
function show_tosca_templates ()
|
||||
{
|
||||
populate_table ("tosca-templates-table",
|
||||
["name_html", "description", "release_html", "service.template_format"],
|
||||
filterData (tosca_templates.assets, getUrlVars ()));
|
||||
}
|
||||
|
||||
function initTabs ()
|
||||
{
|
||||
$( "ul.nav > li > a" ).on("click", function (event) {
|
||||
event.preventDefault ();
|
||||
});
|
||||
$( "ul.nav > li" ).not(":last-child").on("click", function (event) {
|
||||
update_url ({ tab : this.children[0].hash.substring (1), asset: "" });
|
||||
});
|
||||
$( "ul.nav > li:last-child").on("click", function (event) {
|
||||
window.open('https://wiki.openstack.org/wiki/App-Catalog#How_to_contribute', '_blank');
|
||||
});
|
||||
}
|
||||
|
||||
function show_asset (tab, tableData)
|
||||
{
|
||||
var options = getUrlVars ();
|
||||
if ((tab == options.tab) && ("asset" in options)) {
|
||||
for (var i = 0; i < tableData.length; ++i) {
|
||||
if (tableData[i].name == options.asset) {
|
||||
showInfoPage (tab, tableData[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var recent_apps = [];
|
||||
|
||||
function build_recently_added ()
|
||||
{
|
||||
assets.assets.sort(function(a,b) {
|
||||
return new Date(b.last_modified) - new Date(a.last_modified);
|
||||
});
|
||||
sorted_assets = assets.assets.slice(0,15);
|
||||
sorted_assets.sort(
|
||||
function() {
|
||||
return 0.5 - Math.random();
|
||||
});
|
||||
for (var i = 0; i < 5; i++) {
|
||||
var iconurl,
|
||||
fittedname,
|
||||
divclass,
|
||||
hreftab;
|
||||
if (typeof (sorted_assets[i].icon) === 'undefined') {
|
||||
iconurl = "static/images/openstack-icon.png";
|
||||
} else {
|
||||
iconurl = sorted_assets[i].icon.url;
|
||||
}
|
||||
if (sorted_assets[i].name.length > 15) {
|
||||
fittedname = sorted_assets[i].name.slice(0,13) + "...";
|
||||
} else
|
||||
{ fittedname = sorted_assets[i].name; }
|
||||
if (sorted_assets[i].service.type == 'glance') {
|
||||
divclass = "glance";
|
||||
hreftab = "#tab=glance-images&asset=";
|
||||
} else if (sorted_assets[i].service.type == 'heat') {
|
||||
divclass = "heat";
|
||||
hreftab = "#tab=heat-templates&asset=";
|
||||
} else if ((sorted_assets[i].service.type == 'murano') ||
|
||||
(sorted_assets[i].service.type == 'bundle')) {
|
||||
divclass = "murano";
|
||||
hreftab = "#tab=murano-apps&asset=";
|
||||
}else if (sorted_assets[i].service.type == 'tosca') {
|
||||
divclass = "tosca";
|
||||
hreftab = "#tab=tosca-templates&asset=";
|
||||
}
|
||||
$('.featured').append(
|
||||
$('<div>', {class: "col-md-2 col-sm-6"})
|
||||
.append($('<div>', {class: "inner " + divclass})
|
||||
.append($("<a>", {href: hreftab + sorted_assets[i].name})
|
||||
.append($('<img>', {src: iconurl, height: 90}))
|
||||
.append($('<p>', {text: fittedname})))
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
function initMarketPlace ()
|
||||
{
|
||||
navigate ();
|
||||
initTabs ();
|
||||
$( ".inner" ).matchHeight ();
|
||||
|
||||
$("#info-dialog").dialog({
|
||||
autoOpen: false,
|
||||
width: "70%",
|
||||
modal: true,
|
||||
buttons: {
|
||||
Close: function () {
|
||||
$(this).dialog("close");
|
||||
}
|
||||
},
|
||||
close: function () { }
|
||||
});
|
||||
|
||||
$.ajax({ url: "api/v1/assets" }).
|
||||
done (function (data) {
|
||||
assets = data;
|
||||
build_recently_added ();
|
||||
for (var i = 0; i < assets.assets.length; i++) {
|
||||
var asset = assets.assets[i];
|
||||
if (asset.service.type == 'glance') {
|
||||
glance_images.assets.push(asset);
|
||||
} else if (asset.service.type == 'heat') {
|
||||
heat_templates.assets.push(asset);
|
||||
} else if (asset.service.type == 'murano') {
|
||||
murano_apps.assets.push(asset);
|
||||
if (asset.service.type === 'bundle') {
|
||||
asset.service.format = 'bundle';
|
||||
}
|
||||
} else if (asset.service.type == 'bundle') {
|
||||
if ('murano_package_name' in asset.service) {
|
||||
murano_apps.assets.push(asset);
|
||||
asset.service.format = 'bundle';
|
||||
}
|
||||
}else if (asset.service.type == 'tosca') {
|
||||
tosca_templates.assets.push(asset);
|
||||
}
|
||||
}
|
||||
|
||||
var tableData;
|
||||
|
||||
tableData = glance_images.assets;
|
||||
for (var i = 0; i < tableData.length; i++) {
|
||||
setupInfoHandler ("glance-images", i, tableData[i]);
|
||||
}
|
||||
|
||||
show_asset ("glance-images", tableData);
|
||||
show_glance_images ();
|
||||
|
||||
tableData = heat_templates.assets;
|
||||
for (var i = 0; i < tableData.length; i++) {
|
||||
tableData[i].release_html = "";
|
||||
if (tableData[i].release) {
|
||||
tableData[i].release_html = tableData[i].release.join(", ");
|
||||
}
|
||||
setupInfoHandler ("heat-templates", i, tableData[i]);
|
||||
}
|
||||
|
||||
show_asset ("heat-templates", tableData);
|
||||
show_heat_templates ();
|
||||
|
||||
initSingleSelector ("heat-release", "release", tableData, show_heat_templates);
|
||||
|
||||
tableData = murano_apps.assets;
|
||||
for (var i = 0; i < tableData.length; i++) {
|
||||
tableData[i].release_html = "";
|
||||
if (tableData[i].release) {
|
||||
tableData[i].release_html = tableData[i].release.join(", ");
|
||||
}
|
||||
setupInfoHandler ("murano-apps", i, tableData[i]);
|
||||
}
|
||||
|
||||
show_asset ("murano-apps", tableData);
|
||||
show_murano_apps ();
|
||||
|
||||
initSingleSelector ("murano-release", "release", tableData, show_murano_apps);
|
||||
|
||||
tableData = tosca_templates.assets;
|
||||
for (var i = 0; i < tableData.length; i++) {
|
||||
tableData[i].release_html = "";
|
||||
if (tableData[i].release) {
|
||||
tableData[i].release_html = tableData[i].release.join(", ");
|
||||
}
|
||||
setupInfoHandler ("tosca-templates", i, tableData[i]);
|
||||
}
|
||||
|
||||
show_asset ("tosca-templates", tableData);
|
||||
show_tosca_templates ();
|
||||
|
||||
initSingleSelector ("tosca-release", "release", tableData, show_tosca_templates);
|
||||
});
|
||||
}
|
||||
|
||||
function navigate ()
|
||||
{
|
||||
var tabs_list = $("#navbar")[0].children;
|
||||
var selected_tab_name = null;
|
||||
var options = getUrlVars ();
|
||||
|
||||
$( "ul.nav > li" ).removeClass ("active");
|
||||
if ("tab" in options) {
|
||||
for (var i = 0; i < tabs_list.length; ++i) {
|
||||
var tab_name = tabs_list[i].children[0].hash.substring (1);
|
||||
if (tab_name == options.tab) {
|
||||
selected_tab_name = tab_name;
|
||||
if (!("asset" in options)) {
|
||||
tabs_list[i].className = "active";
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$( ".content" ).hide ();
|
||||
|
||||
if (selected_tab_name === null) {
|
||||
$( "#landing-page" ).show ();
|
||||
} else if ("asset" in options) {
|
||||
show_asset ("murano-apps", murano_apps.assets);
|
||||
show_asset ("heat-templates", heat_templates.assets);
|
||||
show_asset ("glance-images", glance_images.assets);
|
||||
show_asset ("tosca-templates", tosca_templates.assets);
|
||||
} else {
|
||||
$( "#" + selected_tab_name ).show ();
|
||||
}
|
||||
}
|
||||
|
||||
window.onhashchange = navigate;
|
@ -1,116 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<script src= "http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
|
||||
<script>
|
||||
var app = angular.module('myApp', []);
|
||||
app.controller('myCtrl', function($scope, $http) {
|
||||
$http({url:'/api/v1/assets'}).success(function(data) {
|
||||
$scope.assets = [];
|
||||
for(i in data.assets) {
|
||||
var asset = data.assets[i];
|
||||
if('tags' in asset) {
|
||||
var found;
|
||||
for(j in asset['tags']) {
|
||||
if(asset['tags'][j] == 'app') {
|
||||
$scope.assets.push(asset);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
console.log($scope.assets);
|
||||
});
|
||||
});
|
||||
</script>
|
||||
<body>
|
||||
|
||||
<div style="margin-bottom: 4px;" ng-app="myApp" ng-controller="myCtrl">
|
||||
|
||||
<div style="
|
||||
background-color:#f9f9f9;
|
||||
overflow: auto;
|
||||
border-color:#cccccc; border-width:1px; border-style: solid;
|
||||
">
|
||||
<div ng-repeat="asset in assets | orderBy:'name':false" style="border:1px;
|
||||
margin: 10px;
|
||||
width: 200px; height: 180px; float: left;
|
||||
">
|
||||
<div style="
|
||||
margin:10px;
|
||||
border-color:#cccccc; border-width:1px;
|
||||
border-radius: 2px;
|
||||
box-shadow: 0 3px 5px rgba(0, 0, 0, 0.1);
|
||||
padding:8px;
|
||||
height: 170px;
|
||||
overflow: hidden;
|
||||
background-color:#ffffff;
|
||||
position: relative;
|
||||
">
|
||||
<div style="">
|
||||
<div style="
|
||||
width:128px;
|
||||
height:128px;
|
||||
overflow: hidden;
|
||||
margin-left: auto; margin-right:auto;
|
||||
">
|
||||
|
||||
<img style="
|
||||
margin: {{ asset.icon.top }}px 0px 0px {{ asset.icon.left }}px;
|
||||
height: {{ asset.icon.height }}px;
|
||||
" src="{{ asset.icon.url }}">
|
||||
|
||||
</div>
|
||||
|
||||
<span style="
|
||||
max-height: 100%;
|
||||
width: 23px;
|
||||
height: 23px;
|
||||
top: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, 0) url('http://apps.openstack.org/static/images/featured-corner-{{ asset.service.type }}.png') no-repeat scroll right top;
|
||||
">
|
||||
</span>
|
||||
</div>
|
||||
<div title="{{ asset.name }}" style="
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
line-height: 18px;
|
||||
font-size: 16px;
|
||||
"> {{ asset.name }}
|
||||
<span style="
|
||||
max-height: 100%;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, 0) linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1)) repeat scroll 0 0;
|
||||
">
|
||||
</span>
|
||||
</div>
|
||||
<div title="{{ asset.provided_by.name }}" style="
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
position: relative;
|
||||
line-height: 14px;
|
||||
font-size: 12px;
|
||||
"> {{ asset.provided_by.name }}
|
||||
<span style="
|
||||
max-height: 100%;
|
||||
width: 40px;
|
||||
height: 20px;
|
||||
bottom: 0;
|
||||
right: 0;
|
||||
position: absolute;
|
||||
background: rgba(0, 0, 0, 0) linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1)) repeat scroll 0 0;
|
||||
">
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</body>
|
||||
</html>
|
@ -1,7 +0,0 @@
|
||||
from openstack_catalog import wsgi_django
|
||||
|
||||
from openstack_catalog.api import api
|
||||
|
||||
from werkzeug.wsgi import DispatcherMiddleware
|
||||
|
||||
application = DispatcherMiddleware(wsgi_django.application, {'/api': api})
|
@ -1,28 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
# 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.
|
||||
|
||||
"""
|
||||
WSGI config for openstack_catalog project.
|
||||
|
||||
It exposes the WSGI callable as a module-level variable named ``application``.
|
||||
|
||||
For more information on this file, see
|
||||
https://docs.djangoproject.com/en/1.6/howto/deployment/wsgi/
|
||||
"""
|
||||
|
||||
import os
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "openstack_catalog.settings")
|
||||
|
||||
from django.core.wsgi import get_wsgi_application
|
||||
application = get_wsgi_application()
|
16
package.json
@ -1,16 +0,0 @@
|
||||
{
|
||||
"version": "0.0.0",
|
||||
"private": true,
|
||||
"name": "app-catalog",
|
||||
"description": "OpenStack App Catalog",
|
||||
"repository": "none",
|
||||
"license": "Apache 2.0",
|
||||
"devDependencies": {
|
||||
"eslint": "^0.23.0",
|
||||
"eslint-config-openstack": "1.2.0"
|
||||
},
|
||||
"scripts": {
|
||||
"lint": "eslint --no-color openstack_catalog/web/static/js/"
|
||||
},
|
||||
"dependencies": {}
|
||||
}
|
@ -1,13 +0,0 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
pbr>=1.3
|
||||
Babel>=1.3
|
||||
Django<1.9,>=1.8
|
||||
django-compressor>=1.4
|
||||
XStatic>=1.0.0 # MIT License
|
||||
XStatic-Angular>=1.3.7 # MIT License
|
||||
XStatic-Magic-Search>=0.2.5.1 # Apache 2.0 License
|
||||
werkzeug
|
||||
flask
|
70
run_tests.sh
@ -1,70 +0,0 @@
|
||||
#!/bin/bash
|
||||
|
||||
set -o errexit
|
||||
|
||||
function usage {
|
||||
echo "Usage: $0 [OPTION]..."
|
||||
echo "Run App Catalog's test suite(s)"
|
||||
echo ""
|
||||
echo " --runserver Run the development server for"
|
||||
echo " openstack_catalog in the virtual"
|
||||
echo " environment."
|
||||
echo " -h, --help Print this usage message"
|
||||
echo ""
|
||||
exit
|
||||
}
|
||||
|
||||
# DEFAULTS FOR RUN_TESTS.SH
|
||||
#
|
||||
root=`pushd $(dirname $0) > /dev/null; pwd; popd > /dev/null`
|
||||
venv=$root/.venv
|
||||
|
||||
runserver=0
|
||||
testopts=""
|
||||
testargs=""
|
||||
|
||||
# Jenkins sets a "JOB_NAME" variable, if it's not set, we'll make it "default"
|
||||
[ "$JOB_NAME" ] || JOB_NAME="default"
|
||||
|
||||
function process_option {
|
||||
case "$1" in
|
||||
-h|--help) usage;;
|
||||
--runserver) runserver=1;;
|
||||
-*) testopts="$testopts $1";;
|
||||
*) testargs="$testargs $1"
|
||||
esac
|
||||
}
|
||||
|
||||
# PROCESS ARGUMENTS, OVERRIDE DEFAULTS
|
||||
for arg in "$@"; do
|
||||
process_option $arg
|
||||
done
|
||||
|
||||
function run_server {
|
||||
echo "Starting development server..."
|
||||
$root/tools/update_assets.sh
|
||||
if [ ! -d $venv ]; then
|
||||
virtualenv $venv
|
||||
. $venv/bin/activate
|
||||
fi
|
||||
. $venv/bin/activate
|
||||
pip install -r $root/requirements.txt
|
||||
#FIXME make venv cleaner.
|
||||
|
||||
# FIXME remove when CORS works
|
||||
# pushd $root/openstack_catalog/web > /dev/null
|
||||
# ${command_wrapper} python $root/tools/testserver.py runserver $testopts $testargs
|
||||
${command_wrapper} python manage.py runserver $testopts $testargs
|
||||
# popd > /dev/null
|
||||
echo "Server stopped."
|
||||
}
|
||||
|
||||
# Development server
|
||||
if [ $runserver -eq 1 ]; then
|
||||
if [ "x$testargs" = "x" -o "$testargs x" = " x" ]; then
|
||||
testargs="127.0.0.1:18001"
|
||||
fi
|
||||
run_server
|
||||
exit $?
|
||||
fi
|
||||
|
45
setup.cfg
@ -1,45 +0,0 @@
|
||||
[metadata]
|
||||
name = openstack_catalog
|
||||
summary = Application catalog for OpenStack
|
||||
description-file =
|
||||
README.rst
|
||||
author = OpenStack
|
||||
author-email = openstack-dev@lists.openstack.org
|
||||
home-page = http://www.openstack.org/
|
||||
classifier =
|
||||
Environment :: OpenStack
|
||||
Intended Audience :: Information Technology
|
||||
Intended Audience :: System Administrators
|
||||
License :: OSI Approved :: Apache Software License
|
||||
Operating System :: POSIX :: Linux
|
||||
Programming Language :: Python
|
||||
Programming Language :: Python :: 2
|
||||
Programming Language :: Python :: 2.7
|
||||
Programming Language :: Python :: 3
|
||||
Programming Language :: Python :: 3.4
|
||||
|
||||
[files]
|
||||
packages =
|
||||
openstack_catalog
|
||||
|
||||
[build_sphinx]
|
||||
source-dir = doc/source
|
||||
build-dir = doc/build
|
||||
all_files = 1
|
||||
|
||||
[upload_sphinx]
|
||||
upload-dir = doc/build/html
|
||||
|
||||
[compile_catalog]
|
||||
directory = openstack_catalog/locale
|
||||
domain = catalog
|
||||
|
||||
[update_catalog]
|
||||
domain = catalog
|
||||
output_dir = openstack_catalog/locale
|
||||
input_file = openstack_catalog/locale/catalog.pot
|
||||
|
||||
[extract_messages]
|
||||
keywords = _ gettext ngettext l_ lazy_gettext
|
||||
mapping_file = babel.cfg
|
||||
output_file = openstack_catalog/locale/catalog.pot
|
30
setup.py
@ -1,30 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
# Copyright (c) 2013 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
# THIS FILE IS MANAGED BY THE GLOBAL REQUIREMENTS REPO - DO NOT EDIT
|
||||
import setuptools
|
||||
|
||||
# In python < 2.7.4, a lazy loading of package `pbr` will break
|
||||
# setuptools if some other modules registered functions in `atexit`.
|
||||
# solution from: http://bugs.python.org/issue15881#msg170215
|
||||
try:
|
||||
import multiprocessing # noqa
|
||||
except ImportError:
|
||||
pass
|
||||
|
||||
setuptools.setup(
|
||||
setup_requires=['pbr'],
|
||||
pbr=True)
|
@ -1,19 +0,0 @@
|
||||
# The order of packages is significant, because pip processes them in the order
|
||||
# of appearance. Changing the order has an impact on the overall integration
|
||||
# process, which may cause wedges in the gate later.
|
||||
|
||||
hacking<0.11,>=0.10.0
|
||||
|
||||
coverage>=3.6
|
||||
python-subunit>=0.0.18
|
||||
sphinx>=1.1.2,!=1.2.0,!=1.3b1,<1.3
|
||||
jsonschema>=2.0.0,<3.0.0
|
||||
oslosphinx>=2.2.0 # Apache-2.0
|
||||
oslotest>=1.2.0 # Apache-2.0
|
||||
testrepository>=0.0.18
|
||||
testscenarios>=0.4
|
||||
testtools>=0.9.36,!=1.2.0
|
||||
PyYAML>=3.1.0
|
||||
|
||||
# js lint tests
|
||||
nodeenv>=0.9.4 # BSD License
|
@ -1,10 +0,0 @@
|
||||
asset_file="$1"
|
||||
#Chunk the yaml assets into begin_line_number,end_line_number sections
|
||||
awk '{line+=1}/^ -/{end=line-1; if(start > 0){print start "," end}; count+=1;start=line;}END{print start "," line}' "$asset_file" | while read line; do
|
||||
size=`echo $line | awk -F, '{print $2-$1+1}'`
|
||||
end=`echo $line | awk -F, '{print $2}'`
|
||||
name=`head -n $end "$asset_file" | tail -n $size | python -c 'import yaml,sys; print yaml.safe_load(sys.stdin)[0]["name"]'`
|
||||
date=`git blame -w -L $line "$asset_file" | sed 's/^[^(]*(\([^)]*\)).*/\1/' | python -c 'import sys,dateutil.parser; print max([dateutil.parser.parse("%s %s%s"%(j[0], j[1], j[2])) for j in [i.split()[-4:] for i in sys.stdin.readlines()]])'`
|
||||
#Dump out the name of the asset, and the last modified date as a json doc to stdout to be reassembled outside the loop into one document
|
||||
(echo $name; echo $date) | python -c 'import sys,json; print json.dumps([i.strip() for i in sys.stdin.readlines()]),'
|
||||
done | python -c 'import sys,json,yaml; print yaml.safe_dump({"assets":dict([[j[0], {"last_modified":j[1]}] for j in [json.loads(i) for i in sys.stdin.readlines()]])}),' #Assemble the individual json documents from the loop into one big one.
|
@ -1,137 +0,0 @@
|
||||
#! /usr/bin/env python
|
||||
#
|
||||
# Copyright (c) 2015 Hewlett-Packard Development Company, L.P.
|
||||
#
|
||||
# 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.
|
||||
|
||||
import requests
|
||||
import requestsexceptions
|
||||
import yaml
|
||||
|
||||
|
||||
from collections import OrderedDict
|
||||
|
||||
|
||||
def project_representer(dumper, data):
|
||||
return dumper.represent_mapping('tag:yaml.org,2002:map',
|
||||
data.items())
|
||||
|
||||
|
||||
def construct_yaml_map(self, node):
|
||||
data = OrderedDict()
|
||||
yield data
|
||||
value = self.construct_mapping(node)
|
||||
|
||||
if isinstance(node, yaml.MappingNode):
|
||||
self.flatten_mapping(node)
|
||||
else:
|
||||
raise yaml.constructor.ConstructorError(
|
||||
None, None,
|
||||
'expected a mapping node, but found %s' % node.id,
|
||||
node.start_mark)
|
||||
|
||||
mapping = OrderedDict()
|
||||
for key_node, value_node in node.value:
|
||||
key = self.construct_object(key_node, deep=False)
|
||||
try:
|
||||
hash(key)
|
||||
except TypeError as exc:
|
||||
raise yaml.constructor.ConstructorError(
|
||||
'while constructing a mapping', node.start_mark,
|
||||
'found unacceptable key (%s)' % exc, key_node.start_mark)
|
||||
value = self.construct_object(value_node, deep=False)
|
||||
mapping[key] = value
|
||||
data.update(mapping)
|
||||
|
||||
|
||||
class IndentedEmitter(yaml.emitter.Emitter):
|
||||
def expect_block_sequence(self):
|
||||
self.increase_indent(flow=False, indentless=False)
|
||||
self.state = self.expect_first_block_sequence_item
|
||||
|
||||
|
||||
class IndentedDumper(IndentedEmitter, yaml.serializer.Serializer,
|
||||
yaml.representer.Representer, yaml.resolver.Resolver):
|
||||
def __init__(self, stream,
|
||||
default_style=None, default_flow_style=None,
|
||||
canonical=None, indent=None, width=None,
|
||||
allow_unicode=None, line_break=None,
|
||||
encoding=None, explicit_start=None, explicit_end=None,
|
||||
version=None, tags=None):
|
||||
IndentedEmitter.__init__(
|
||||
self, stream, canonical=canonical,
|
||||
indent=indent, width=width,
|
||||
allow_unicode=allow_unicode,
|
||||
line_break=line_break)
|
||||
yaml.serializer.Serializer.__init__(
|
||||
self, encoding=encoding,
|
||||
explicit_start=explicit_start,
|
||||
explicit_end=explicit_end,
|
||||
version=version, tags=tags)
|
||||
yaml.representer.Representer.__init__(
|
||||
self, default_style=default_style,
|
||||
default_flow_style=default_flow_style)
|
||||
yaml.resolver.Resolver.__init__(self)
|
||||
|
||||
|
||||
def get_hashes(hash_url):
|
||||
hashes = {}
|
||||
r = requests.get(hash_url, allow_redirects=True)
|
||||
if r.status_code == 200:
|
||||
for line in r.iter_lines():
|
||||
try:
|
||||
hash, file = line.split(" ")
|
||||
except ValueError:
|
||||
continue
|
||||
hashes[file] = hash
|
||||
return hashes
|
||||
|
||||
|
||||
def main():
|
||||
requestsexceptions.squelch_warnings()
|
||||
yaml.add_constructor(yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG,
|
||||
construct_yaml_map)
|
||||
|
||||
yaml.add_representer(OrderedDict, project_representer,
|
||||
Dumper=IndentedDumper)
|
||||
|
||||
data = yaml.safe_load(open('openstack_catalog/web/static/assets.yaml'))
|
||||
|
||||
assets = []
|
||||
for a in data['assets']:
|
||||
url = a.get('attributes', {}).get('url')
|
||||
if not a.get('active', True) or not url:
|
||||
assets.append(a)
|
||||
continue
|
||||
|
||||
r = requests.head(url, allow_redirects=True)
|
||||
if r.status_code != 200:
|
||||
a['active'] = False
|
||||
else:
|
||||
hash_url = a.get('hash_url')
|
||||
if hash_url:
|
||||
hashes = get_hashes(hash_url)
|
||||
filename = url.split("/")[-1]
|
||||
a['attributes']['hash'] = hashes.get(filename, 'unknown')
|
||||
|
||||
assets.append(a)
|
||||
|
||||
output = {'assets': assets}
|
||||
with open('openstack_catalog/web/static/assets.yaml', 'w') as out:
|
||||
out.write(yaml.dump(output, default_flow_style=False,
|
||||
Dumper=IndentedDumper, width=80,
|
||||
indent=2))
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
@ -1,41 +0,0 @@
|
||||
#!/bin/env python
|
||||
#
|
||||
# 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.
|
||||
|
||||
import SimpleHTTPServer
|
||||
import SocketServer
|
||||
|
||||
|
||||
class AllowOriginRequestHandler(SimpleHTTPServer.SimpleHTTPRequestHandler):
|
||||
def do_GET(self):
|
||||
print("App Catalog Versions:",
|
||||
self.headers.get('X-App-Catalog-Versions', ''))
|
||||
return SimpleHTTPServer.SimpleHTTPRequestHandler.do_GET(self)
|
||||
|
||||
def end_headers(self):
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
SimpleHTTPServer.SimpleHTTPRequestHandler.end_headers(self)
|
||||
|
||||
def do_OPTIONS(self):
|
||||
self.send_response(200)
|
||||
self.send_header("Access-Control-Allow-Origin", "*")
|
||||
self.send_header("Access-Control-Allow-Headers",
|
||||
"X-App-Catalog-Versions")
|
||||
self.send_header("Allow", "GET")
|
||||
|
||||
if __name__ == '__main__':
|
||||
PORT = 18001
|
||||
httpd = SocketServer.TCPServer(("", PORT), AllowOriginRequestHandler)
|
||||
print("serving at port", PORT)
|
||||
httpd.serve_forever()
|
@ -1,19 +0,0 @@
|
||||
#!/bin/bash
|
||||
ROOTDIR=`pushd $(dirname $0)/.. > /dev/null /dev/null; pwd; popd > /dev/null`
|
||||
echo $ROOTDIR
|
||||
pushd $ROOTDIR/openstack_catalog/web > /dev/null
|
||||
mkdir -p api/v1/
|
||||
if [ ! -f static/assets_dead.yaml ];
|
||||
then
|
||||
echo 'assets: {}' > static/assets_dead.yaml
|
||||
fi
|
||||
if [ ! -f api/v1/assets ] || [ static/assets.yaml -nt api/v1/assets ] || [ static/assets_dead.yaml -nt api/v1/assets ];
|
||||
then
|
||||
$ROOTDIR/tools/asset_history.sh static/assets.yaml > static/assets_merge.yaml
|
||||
python $ROOTDIR/tools/yaml2json.py static/assets_merge.yaml static/assets_dead.yaml < static/assets.yaml > /tmp/assets.$$
|
||||
zopfli --i150 -c /tmp/assets.$$ > /tmp/assets.$$.gz || gzip -c /tmp/assets.$$ > /tmp/assets.$$.gz
|
||||
mv /tmp/assets.$$.gz api/v1/assets.gz
|
||||
mv /tmp/assets.$$ api/v1/assets
|
||||
rm -f static/assets_merge.yaml
|
||||
fi
|
||||
popd > /dev/null
|
@ -1,51 +0,0 @@
|
||||
#!/usr/bin/env python
|
||||
#
|
||||
# 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.
|
||||
|
||||
import argparse
|
||||
import json
|
||||
import sys
|
||||
import yaml
|
||||
|
||||
parser = argparse.ArgumentParser(description='Merge and convert yaml to json.')
|
||||
parser.add_argument('files', metavar='F', type=str, nargs='+',
|
||||
help='file to process')
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
||||
def dict_merge(a, b):
|
||||
for k, v in b.items():
|
||||
if isinstance(v, dict):
|
||||
n = a.setdefault(k, {})
|
||||
dict_merge(n, v)
|
||||
else:
|
||||
a[k] = v
|
||||
return a
|
||||
|
||||
merge = {}
|
||||
for f in args.files:
|
||||
merge = dict_merge(merge, yaml.safe_load(open(f))['assets'])
|
||||
|
||||
y = yaml.safe_load(sys.stdin)
|
||||
for a in y['assets']:
|
||||
s = a['service']
|
||||
if s['type'] == 'heat':
|
||||
if 'environment' in s:
|
||||
s['environment'] = yaml.dump(s['environment'])
|
||||
if a['name'] in merge:
|
||||
dict_merge(a, merge[a['name']])
|
||||
y = [a for a in y['assets'] if a.get('active', True)]
|
||||
y = {'assets': y}
|
||||
json.dump(y, sys.stdout)
|
50
tox.ini
@ -1,50 +0,0 @@
|
||||
[tox]
|
||||
minversion = 1.6
|
||||
envlist = py34,py27,pep8
|
||||
skipsdist = True
|
||||
|
||||
[testenv]
|
||||
usedevelop = True
|
||||
install_command = pip install -U {opts} {packages}
|
||||
setenv =
|
||||
VIRTUAL_ENV={envdir}
|
||||
deps = -r{toxinidir}/requirements.txt
|
||||
-r{toxinidir}/test-requirements.txt
|
||||
commands = python setup.py testr --slowest --testr-args='{posargs}'
|
||||
|
||||
[testenv:pep8]
|
||||
commands = flake8
|
||||
|
||||
[testenv:venv]
|
||||
commands = {posargs}
|
||||
|
||||
[testenv:eslint]
|
||||
deps = -r{toxinidir}/test-requirements.txt
|
||||
passenv = *
|
||||
commands = nodeenv -p
|
||||
npm install
|
||||
npm run lint
|
||||
|
||||
[testenv:cover]
|
||||
commands = python setup.py testr --coverage --testr-args='{posargs}'
|
||||
|
||||
[testenv:docs]
|
||||
commands = python setup.py build_sphinx
|
||||
|
||||
[testenv:debug]
|
||||
commands = oslo_debug_helper {posargs}
|
||||
|
||||
[flake8]
|
||||
# E123, E125 skipped as they are invalid PEP-8.
|
||||
|
||||
show-source = True
|
||||
builtins = _
|
||||
exclude=.venv,.git,.tox,dist,doc,*lib/python*,*egg,build
|
||||
|
||||
[testenv:bindep]
|
||||
# Do not install any requirements. We want this to be fast and work even if
|
||||
# system dependencies are missing, since it's used to tell you what system
|
||||
# dependencies are missing! This also means that bindep must be installed
|
||||
# separately, outside of the requirements files.
|
||||
deps = bindep
|
||||
commands = bindep test
|