├── api-client-py ├── Makefile ├── .gitignore ├── requirements.txt ├── cumulus_api │ ├── __init__.py │ └── cumulus_api.py ├── setup.py └── LICENSE ├── examples ├── node │ ├── logs.js │ ├── pdrs.js │ ├── rules.js │ ├── stats.js │ ├── executions.js │ ├── providers.js │ ├── resources.js │ ├── schemas.js │ ├── workflows.js │ ├── README.md │ ├── auth.js │ ├── granules.js │ ├── collections.js │ ├── distribution.js │ └── execution-status.js ├── python │ ├── logs.py │ ├── pdrs.py │ ├── granules.py │ ├── providers.py │ ├── resources.py │ ├── schemas.py │ ├── stats.py │ ├── collections.py │ ├── README.md │ ├── collections.pyc │ └── auth.py ├── curl │ ├── distribution.sh │ ├── README.md │ ├── logs.sh │ ├── pdrs.sh │ ├── rules.sh │ ├── granules.sh │ ├── workflows.sh │ ├── executions.sh │ ├── providers.sh │ ├── collections.sh │ ├── schemas.sh │ ├── reconciliation-reports.sh │ ├── execution-status.sh │ ├── stats.sh │ └── auth.sh └── README.md ├── website ├── v11.0.0 │ ├── bundle.js │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── v13.0.0 │ ├── bundle.js │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── v13.3.0 │ ├── bundle.js │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── v13.4.0 │ ├── bundle.js │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── favicon.ico ├── v14.0.0 │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── v14.1.0 │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── favicon.ico ├── v16.1.1 │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v18.1.0 │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v18.4.0 │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v18.5.3 │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v20.0.0 │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v20.1.2 │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── build │ │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── v21.0.0 │ ├── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css │ └── build │ │ └── css │ │ ├── icon.eot │ │ ├── icon.woff │ │ ├── railscasts.css │ │ └── style.css ├── img │ ├── ic_cumulus_logo_blue.svg │ └── ic_cumulus_logo_white.svg └── input.css ├── .prettierignore ├── .eslintignore ├── prettier.config.js ├── postcss.config.js ├── .gitignore ├── api-client-js ├── endpoints │ ├── distribution.js │ ├── logs.js │ ├── schemas.js │ ├── execution-status.js │ ├── workflows.js │ ├── executions.js │ ├── pdrs.js │ ├── granules.js │ ├── stats.js │ ├── reconciliation-reports.js │ ├── rules.js │ ├── providers.js │ └── collections.js ├── tests │ ├── README.md │ └── index.js ├── package.json └── index.js ├── content ├── version.md ├── orca.md ├── instance-meta.md ├── dashboard.md ├── granule-csv.md ├── replays-sqs-messages.md ├── replays.md ├── async-operations.md ├── dead-letter-archive.md ├── stats.md ├── pdrs.md ├── schemas.md ├── intro.md ├── auth.md ├── workflows.md ├── providers.md ├── rules.md └── logs.md ├── template ├── defaults │ └── index.html └── src │ ├── custom │ ├── index.js │ └── content.js │ └── components │ └── app.js ├── tailwind.config.js ├── README.md ├── .circleci └── config.yml ├── package.json ├── bin └── docs ├── release.md ├── CONTRIBUTING.md └── LICENSE /api-client-py/Makefile: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/logs.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/pdrs.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/rules.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/stats.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/logs.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/pdrs.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/executions.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/providers.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/resources.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/schemas.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/node/workflows.js: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/granules.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/providers.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/resources.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/schemas.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/stats.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/python/collections.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/v11.0.0/bundle.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /website/v13.0.0/bundle.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /website/v13.3.0/bundle.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /website/v13.4.0/bundle.js: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /examples/curl/distribution.sh: -------------------------------------------------------------------------------- 1 | # TODO -------------------------------------------------------------------------------- /examples/curl/README.md: -------------------------------------------------------------------------------- 1 | # Curl examples 2 | -------------------------------------------------------------------------------- /api-client-py/.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | -------------------------------------------------------------------------------- /examples/node/README.md: -------------------------------------------------------------------------------- 1 | # Node.js examples 2 | -------------------------------------------------------------------------------- /examples/python/README.md: -------------------------------------------------------------------------------- 1 | # Python examples 2 | -------------------------------------------------------------------------------- /.prettierignore: -------------------------------------------------------------------------------- 1 | # Ignore artifacts: 2 | build 3 | coverage -------------------------------------------------------------------------------- /api-client-py/requirements.txt: -------------------------------------------------------------------------------- 1 | future 2 | requests==2.32.5 3 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | /build 3 | /dist 4 | test 5 | tmp 6 | public 7 | -------------------------------------------------------------------------------- /website/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/favicon.ico -------------------------------------------------------------------------------- /prettier.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: [require("prettier-plugin-tailwindcss")], 3 | }; 4 | -------------------------------------------------------------------------------- /website/v11.0.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v11.0.0/css/icon.eot -------------------------------------------------------------------------------- /website/v11.0.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v11.0.0/favicon.ico -------------------------------------------------------------------------------- /website/v13.0.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.0.0/css/icon.eot -------------------------------------------------------------------------------- /website/v13.0.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.0.0/favicon.ico -------------------------------------------------------------------------------- /website/v13.3.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.3.0/css/icon.eot -------------------------------------------------------------------------------- /website/v13.3.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.3.0/favicon.ico -------------------------------------------------------------------------------- /website/v13.4.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.4.0/css/icon.eot -------------------------------------------------------------------------------- /website/v13.4.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.4.0/favicon.ico -------------------------------------------------------------------------------- /website/v14.0.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.0.0/css/icon.eot -------------------------------------------------------------------------------- /website/v14.0.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.0.0/favicon.ico -------------------------------------------------------------------------------- /website/v14.1.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.1.0/css/icon.eot -------------------------------------------------------------------------------- /website/v14.1.0/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.1.0/favicon.ico -------------------------------------------------------------------------------- /website/v16.1.1/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v16.1.1/css/icon.eot -------------------------------------------------------------------------------- /website/v18.1.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.1.0/css/icon.eot -------------------------------------------------------------------------------- /website/v18.4.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.4.0/css/icon.eot -------------------------------------------------------------------------------- /website/v18.5.3/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.5.3/css/icon.eot -------------------------------------------------------------------------------- /website/v20.0.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.0.0/css/icon.eot -------------------------------------------------------------------------------- /website/v20.1.2/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.1.2/css/icon.eot -------------------------------------------------------------------------------- /website/v21.0.0/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v21.0.0/css/icon.eot -------------------------------------------------------------------------------- /website/v11.0.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v11.0.0/css/icon.woff -------------------------------------------------------------------------------- /website/v13.0.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.0.0/css/icon.woff -------------------------------------------------------------------------------- /website/v13.3.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.3.0/css/icon.woff -------------------------------------------------------------------------------- /website/v13.4.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v13.4.0/css/icon.woff -------------------------------------------------------------------------------- /website/v14.0.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.0.0/css/icon.woff -------------------------------------------------------------------------------- /website/v14.1.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v14.1.0/css/icon.woff -------------------------------------------------------------------------------- /website/v16.1.1/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v16.1.1/css/icon.woff -------------------------------------------------------------------------------- /website/v18.1.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.1.0/css/icon.woff -------------------------------------------------------------------------------- /website/v18.4.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.4.0/css/icon.woff -------------------------------------------------------------------------------- /website/v18.5.3/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v18.5.3/css/icon.woff -------------------------------------------------------------------------------- /website/v20.0.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.0.0/css/icon.woff -------------------------------------------------------------------------------- /website/v20.1.2/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.1.2/css/icon.woff -------------------------------------------------------------------------------- /website/v21.0.0/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v21.0.0/css/icon.woff -------------------------------------------------------------------------------- /examples/python/collections.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/examples/python/collections.pyc -------------------------------------------------------------------------------- /website/v20.1.2/build/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.1.2/build/css/icon.eot -------------------------------------------------------------------------------- /website/v20.1.2/build/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v20.1.2/build/css/icon.woff -------------------------------------------------------------------------------- /website/v21.0.0/build/css/icon.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v21.0.0/build/css/icon.eot -------------------------------------------------------------------------------- /website/v21.0.0/build/css/icon.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/nasa/cumulus-api/HEAD/website/v21.0.0/build/css/icon.woff -------------------------------------------------------------------------------- /postcss.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | plugins: { 3 | tailwindcss: {}, 4 | autoprefixer: {}, 5 | } 6 | } -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Cumulus API Examples 2 | 3 | - [curl](./curl/README.md) 4 | - [node](./node/README.md) 5 | - [python](./python/README.md) 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | .tmp 3 | npm-debug.log 4 | .DS_Store 5 | .swo 6 | package-lock.json 7 | .idea/ 8 | website/unreleased/ 9 | website/output.css -------------------------------------------------------------------------------- /api-client-py/cumulus_api/__init__.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # coding: utf8 3 | 4 | from __future__ import absolute_import 5 | from .cumulus_api import CumulusApi 6 | -------------------------------------------------------------------------------- /examples/curl/logs.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | 6 | # Get logs 7 | URL="$CUMULUS_BASEURL/logs" 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/pdrs.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/pdrs" 6 | 7 | # Get list of pdrs 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/rules.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/rules" 6 | 7 | # Get list of rules 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/granules.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/granules" 6 | 7 | # Get list of granules 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/workflows.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/workflows" 6 | 7 | # Get list of workflows 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/executions.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/executions" 6 | 7 | # Get list of executions 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/providers.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/providers" 6 | 7 | # Get list of providers 8 | curl -i $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/collections.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/collections" 6 | 7 | # Get list of collections 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/curl/schemas.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | SCHEMA="" # TODO 6 | URL="$CUMULUS_BASEURL/schemas/$SCHEMA" 7 | 8 | # Get list of schemas 9 | curl $URL \ 10 | -H "Authorization: Bearer ${TOKEN}" 11 | -------------------------------------------------------------------------------- /api-client-js/endpoints/distribution.js: -------------------------------------------------------------------------------- 1 | 2 | module.exports = class Pdrs { 3 | constructor (client) { 4 | this.client = client 5 | } 6 | 7 | get (granuleId, options, callback) { 8 | return this.client._req('get', granuleId, options, callback) 9 | } 10 | } 11 | -------------------------------------------------------------------------------- /examples/curl/reconciliation-reports.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/reconciliationReports" 6 | 7 | # Get list of reconciliation reports 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /api-client-js/endpoints/logs.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Logs { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'logs' 7 | } 8 | 9 | list (options, callback) { 10 | return this.client._req('get', this.endpoint, options, callback) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /api-client-js/endpoints/schemas.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Schemas { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'schemas' 7 | } 8 | 9 | get (name, options, callback) { 10 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/node/auth.js: -------------------------------------------------------------------------------- 1 | var Cumulus = require('../../api-client-js') 2 | 3 | var api = new Cumulus({ 4 | baseUrl: process.env.CUMULUS_BASEURL 5 | }) 6 | 7 | var options = { 8 | username: process.env.EARTHDATA_USERNAME, 9 | password: process.env.EARTHDATA_PASSWORD 10 | } 11 | 12 | api.login(options, function (err, token) { 13 | console.log('token', token) 14 | }) 15 | -------------------------------------------------------------------------------- /api-client-js/endpoints/execution-status.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class ExecutionStatus { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'executions/status' 7 | } 8 | 9 | get (name, options, callback) { 10 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /examples/curl/execution-status.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | EXECUTION_ARN="arn:aws:states:us-east-1:ACCOUNT:execution:LpdaacCumulusDiscoverPdrsStateMachine-TOSDNMC55QUA:7b242f9bab4628d49bc9f8d3a" 6 | URL="$CUMULUS_BASEURL/executions/status/$EXECUTION_ARN" 7 | 8 | curl $URL \ 9 | -H "Authorization: Bearer ${TOKEN}" 10 | -------------------------------------------------------------------------------- /examples/node/granules.js: -------------------------------------------------------------------------------- 1 | var Cumulus = require('../../api-client-js') 2 | 3 | var api = new Cumulus({ 4 | baseUrl: process.env.CUMULUS_BASEURL 5 | }) 6 | 7 | var options = { 8 | username: process.env.EARTHDATA_USERNAME, 9 | password: process.env.EARTHDATA_PASSWORD 10 | } 11 | 12 | api.login(options, function (err, token) { 13 | api.granules.list(function (err, response) { 14 | 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /api-client-py/setup.py: -------------------------------------------------------------------------------- 1 | from distutils.core import setup 2 | 3 | setup( 4 | name='cumulus_api', 5 | version='1.0.0', 6 | url='https://github.com/nasa/cumulus_api.py', 7 | author='', 8 | author_email='', 9 | description='', 10 | license='Apache-2.0', 11 | packages=[''], 12 | install_requires=['future', 'requests'], 13 | tests_require=['pytest'], 14 | classifiers=[] 15 | ) 16 | -------------------------------------------------------------------------------- /examples/node/collections.js: -------------------------------------------------------------------------------- 1 | var Cumulus = require('../../api-client-js') 2 | 3 | var api = new Cumulus({ 4 | baseUrl: process.env.CUMULUS_BASEURL 5 | }) 6 | 7 | var options = { 8 | username: process.env.EARTHDATA_USERNAME, 9 | password: process.env.EARTHDATA_PASSWORD 10 | } 11 | 12 | api.login(options, function (err, token) { 13 | api.collections.list(function (err, response) { 14 | console.log(response) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /examples/node/distribution.js: -------------------------------------------------------------------------------- 1 | var Cumulus = require('../../api-client-js') 2 | 3 | var api = new Cumulus({ 4 | baseUrl: process.env.CUMULUS_BASEURL 5 | }) 6 | 7 | var options = { 8 | username: process.env.EARTHDATA_USERNAME, 9 | password: process.env.EARTHDATA_PASSWORD 10 | } 11 | 12 | api.login(options, function (err, token) { 13 | api.distribution.get(function (err, response) { 14 | console.log(response) 15 | }) 16 | }) 17 | -------------------------------------------------------------------------------- /api-client-js/endpoints/workflows.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Workflows { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'workflows' 7 | } 8 | 9 | get (name, options, callback) { 10 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | list (options, callback) { 14 | return this.client._req('get', this.endpoint, options, callback) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /api-client-js/endpoints/executions.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Executions { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'executions' 7 | } 8 | 9 | get (name, options, callback) { 10 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | list (options, callback) { 14 | return this.client._req('get', this.endpoint, options, callback) 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /examples/python/auth.py: -------------------------------------------------------------------------------- 1 | import os 2 | import sys 3 | 4 | sys.path.append(os.path.dirname(os.path.abspath(__file__)) + '/../../api-client-py') 5 | 6 | from cumulus_api import CumulusApi 7 | 8 | CUMULUS_BASEURL = os.environ["CUMULUS_BASEURL"] 9 | EARTHDATA_USERNAME = os.environ["EARTHDATA_USERNAME"] 10 | EARTHDATA_PASSWORD = os.environ["EARTHDATA_PASSWORD"] 11 | 12 | api = CumulusApi(CUMULUS_BASEURL) 13 | 14 | token = api.login(EARTHDATA_USERNAME, EARTHDATA_PASSWORD) 15 | print token 16 | -------------------------------------------------------------------------------- /api-client-js/tests/README.md: -------------------------------------------------------------------------------- 1 | # Tests 2 | 3 | Tests are run using [tape](https://npmjs.com/tape). 4 | 5 | Linting is performed using [standard](https://npmjs.com/standard) 6 | 7 | ## Running tests 8 | 9 | ```sh 10 | git clone {this repo} 11 | cd {this repo} 12 | npm install 13 | npm test 14 | ``` 15 | 16 | `npm test` runs both the linter and the tests. 17 | 18 | ### Just run the linter 19 | 20 | ```sh 21 | npm run lint 22 | ``` 23 | 24 | ### Only run the tests 25 | 26 | ```sh 27 | npm run test:no-lint 28 | ``` 29 | -------------------------------------------------------------------------------- /api-client-js/tests/index.js: -------------------------------------------------------------------------------- 1 | var test = require('tape') 2 | 3 | var CumulusApiClient = require('../index') 4 | 5 | var api = new CumulusApiClient({ 6 | baseUrl: process.env.CUMULUS_BASEURL 7 | }) 8 | 9 | test('login', function (t) { 10 | var options = { 11 | username: process.env.EARTHDATA_USERNAME, 12 | password: process.env.EARTHDATA_PASSWORD 13 | } 14 | 15 | api.login(options, function (err, token) { 16 | t.notOk(err) 17 | t.ok(token && typeof token === 'string') 18 | t.end() 19 | }) 20 | }) 21 | -------------------------------------------------------------------------------- /content/version.md: -------------------------------------------------------------------------------- 1 | ## Versioning 2 | 3 | The Cumulus API is versioned and the current version is v2. Retrieve the latest API version from Cumulus. 4 | 5 | ```endpoint 6 | GET /version 7 | ``` 8 | 9 | To use any version, include the version number in the path before the query endpoint. `{API_URL}/{version}/{query}` 10 | 11 | #### Example Request 12 | ```curl 13 | $ curl https://example.com/version 14 | ``` 15 | 16 | #### Example Response 17 | ```json 18 | { 19 | "response_version": "v2", 20 | "api_version": "15.0.0" 21 | } 22 | ``` 23 | 24 | -------------------------------------------------------------------------------- /api-client-js/endpoints/pdrs.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Pdrs { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'pdrs' 7 | } 8 | 9 | get (name, options, callback) { 10 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | list (options, callback) { 14 | return this.client._req('get', this.endpoint, options, callback) 15 | } 16 | 17 | del (name, callback) { 18 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /template/defaults/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Cumulus API 7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /content/orca.md: -------------------------------------------------------------------------------- 1 | ## ORCA 2 | 3 | This endpoint authenticates and forwards requests to the ORCA private API, and returns the response from the ORCA API. Please refer to [ORCA API reference](https://nasa.github.io/cumulus-orca/docs/developer/api/orca-api) on how to use ORCA API. 4 | 5 | ```endpoint 6 | POST /orca 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl --request POST https://example.com/orca/recovery/granules --header 'Authorization: Bearer ReplaceWithTheToken' --header 'Content-Type: application/json' --data '{ 13 | "granuleId": "MOD14A1.061.H5V12.2020312.141531789" 14 | }' 15 | ``` 16 | -------------------------------------------------------------------------------- /tailwind.config.js: -------------------------------------------------------------------------------- 1 | /** @type {import('tailwindcss').Config} */ 2 | module.exports = { 3 | content: ['./website/index.html'], 4 | theme: { 5 | screens: { 6 | sm: '480px', 7 | md: '768px', 8 | lg: '976px', 9 | xl: '1440px', 10 | }, 11 | fontFamily: { 12 | sans: ['Open Sans', 'sans-serif'], 13 | }, 14 | extend: { 15 | colors: { 16 | 'blue': '#2276AC', 17 | 'gray-light': '#F5F6F7', 18 | 'dark-surface': '#121212', 19 | 'dark-blue': '#52BDFF', 20 | 'dark-highlight': '#EBF7FF' 21 | }, 22 | }, 23 | }, 24 | plugins: [], 25 | }; 26 | -------------------------------------------------------------------------------- /api-client-js/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cumulus/cumulus-api-client", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "index.js", 6 | "scripts": { 7 | "lint": "standard", 8 | "test": "CUMULUS_BASEURL=https://wjdkfyb6t6.execute-api.us-east-1.amazonaws.com/dev/ node tests/index.js" 9 | }, 10 | "dependencies": { 11 | "base-64": "^0.1.0", 12 | "call-me-maybe": "^1.0.1", 13 | "got": "^7.1.0", 14 | "nanoassert": "^1.1.0", 15 | "url-join": "^2.0.2" 16 | }, 17 | "devDependencies": { 18 | "documentation": "^5.3.3", 19 | "standard": "^10.0.3", 20 | "tap-spec": "^5.0.0", 21 | "tape": "^4.8.0" 22 | }, 23 | "author": "", 24 | "license": "Apache-2.0" 25 | } 26 | -------------------------------------------------------------------------------- /examples/curl/stats.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | # Get the access token using the auth example 4 | TOKEN=`"./auth.sh"` 5 | URL="$CUMULUS_BASEURL/stats" 6 | 7 | # Get stats summary 8 | printf "\nsummary\n" 9 | curl -i $URL \ 10 | -H "Authorization: Bearer ${TOKEN}" 11 | 12 | # Get histogram 13 | printf "\nhistogram\n" 14 | URL="$CUMULUS_BASEURL/stats/histogram" 15 | curl -i $URL \ 16 | -H "Authorization: Bearer ${TOKEN}" 17 | 18 | # Get aggregate 19 | printf "\naggregate\n" 20 | URL="$CUMULUS_BASEURL/stats/aggregate" 21 | curl -i $URL \ 22 | -H "Authorization: Bearer ${TOKEN}" 23 | 24 | # Get average 25 | printf "\naverage\n" 26 | URL="$CUMULUS_BASEURL/stats/average?field=grade" 27 | curl -i $URL \ 28 | -H "Authorization: Bearer ${TOKEN}" 29 | -------------------------------------------------------------------------------- /api-client-js/endpoints/granules.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Granules { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'granules' 7 | } 8 | 9 | put (name, options, callback) { 10 | return this.client._req('put', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | get (name, options, callback) { 14 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 15 | } 16 | 17 | list (options, callback) { 18 | return this.client._req('get', this.endpoint, options, callback) 19 | } 20 | 21 | del (name, callback) { 22 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /examples/node/execution-status.js: -------------------------------------------------------------------------------- 1 | var Cumulus = require('../../api-client-js') 2 | 3 | var api = new Cumulus({ 4 | baseUrl: process.env.CUMULUS_BASEURL 5 | }) 6 | 7 | var options = { 8 | username: process.env.EARTHDATA_USERNAME, 9 | password: process.env.EARTHDATA_PASSWORD 10 | } 11 | 12 | api.login(options, function (err, token) { 13 | getExecutionsList(function (err, list) { 14 | var execution = list[0] 15 | api.executionStatus.get(execution.arn, function (err, response) { 16 | console.log(response) 17 | }) 18 | }) 19 | }) 20 | 21 | function getExecutionsList (callback) { 22 | api.executions.list(function (err, res) { 23 | if (err) return callback(err) 24 | return callback(null, res.results) 25 | }) 26 | } 27 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## Cumulus API Docs 2 | 3 | [![CircleCI](https://circleci.com/gh/nasa/cumulus-api.svg?style=svg)](https://circleci.com/gh/nasa/cumulus-api) 4 | 5 | Cumulus API documentation: https://nasa.github.io/cumulus-api 6 | 7 | ### Installation 8 | 9 | $ npm install 10 | 11 | ### Build CSS (Styling) 12 | 13 | $ npm run build-css 14 | 15 | ### Build Site 16 | 17 | $ npm run build 18 | 19 | ### Serve 20 | 21 | #### Serve current(unreleased) document 22 | 23 | $ npm run serve 24 | 25 | #### Serve current and released document 26 | 27 | $ npm run serve-all 28 | 29 | ### Deploy 30 | 31 | $ npm run deploy 32 | 33 | ### 🛒 Release 34 | 35 | To release a new version of Cumulus API document [read this](release.md). 36 | -------------------------------------------------------------------------------- /content/instance-meta.md: -------------------------------------------------------------------------------- 1 | ## Instance Metadata 2 | 3 | The Cumulus API can provide information about its configuration. 4 | 5 | GET requests to the instance metadata endpoint return a json object with information about how the Cumulus stack is configured. It returns the CMR provider and environment as well as the stackName (prefix). 6 | 7 | ```endpoint 8 | GET /instanceMeta 9 | ``` 10 | 11 | #### Example Request 12 | ```curl 13 | $ curl https://example.com/instanceMeta --header 'Authorization: Bearer ReplaceWithTheToken' 14 | ``` 15 | 16 | #### Example Response 17 | ```json 18 | { 19 | "cmr": { 20 | "provider": "CUMULUS", 21 | "environment": "UAT" 22 | }, 23 | "cumulus": { 24 | "stackName": "cumulus-stack-prefix" 25 | } 26 | } 27 | ``` 28 | -------------------------------------------------------------------------------- /api-client-js/endpoints/stats.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Stats { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'stats' 7 | } 8 | 9 | get (options, callback) { 10 | return this.client._req('get', this.endpoint, options, callback) 11 | } 12 | 13 | aggregate (options, callback) { 14 | return this.client._req('get', joinUrl('aggregate', this.endpoint), options, callback) 15 | } 16 | 17 | average (options, callback) { 18 | return this.client._req('get', joinUrl('average', this.endpoint), options, callback) 19 | } 20 | 21 | histogram (options, callback) { 22 | return this.client._req('get', joinUrl('histogram', this.endpoint), options, callback) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /api-client-js/endpoints/reconciliation-reports.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class ReconciliationReports { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'reconciliationReports' 7 | } 8 | 9 | post (name, options, callback) { 10 | return this.client._req('post', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | get (name, options, callback) { 14 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 15 | } 16 | 17 | list (options, callback) { 18 | return this.client._req('get', this.endpoint, options, callback) 19 | } 20 | 21 | del (name, callback) { 22 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /content/dashboard.md: -------------------------------------------------------------------------------- 1 | ## Serve the dashboard from a bucket 2 | 3 | Serve the dashboard from an S3 bucket. 4 | 5 | ```endpoint 6 | GET /dashboard/{bucket}/{key} 7 | ``` 8 | 9 | This is a way to serve the Cumulus dashboard in a browser from an S3 bucket without making the bucket or files public. 10 | 11 | To use this: 12 | - Your dashboard bucket must be in the bucket definitions in your Cumulus `terraform.tfvars`, otherwise you will not be able to access the bucket. 13 | - Deploy the dashboard to your bucket using the instructions in the Cumulus dashboard README. 14 | - In a browser, use the example request below, but replace `example.com` with your Cumulus backend API and `dashboard-bucket` with your bucket name. 15 | 16 | #### Example request 17 | 18 | ``` 19 | https://example.com/dashboard/dashboard-bucket/index.html 20 | ``` 21 | -------------------------------------------------------------------------------- /content/granule-csv.md: -------------------------------------------------------------------------------- 1 | ## Get Granule CSV file 2 | 3 | Get a CSV file of all the granule in the Cumulus database. 4 | 5 | ```endpoint 6 | GET /granule-csv 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl https://example.com/granule-csv --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example response 16 | 17 | ``` json 18 | "granuleUr","collectionId","createdAt","startDateTime","endDateTime","status","updatedAt","published" 19 | "MOD14A1.A9506271.IvEJsu.006.8359924290786","MOD14A1___006","2020-05-18T20:15:54.525Z","2017-10-24T00:00:00Z","2017-11-08T23:59:59Z","completed","2020-05-18T20:16:02.473Z",false 20 | "MYD13Q1.A9663671.0zkwKH.006.9812354158395","MYD13Q1___006","2020-07-06T19:46:19.957Z","2017-10-24T00:00:00Z","2017-11-08T23:59:59Z","completed","2020-07-06T19:46:57.054Z",true 21 | ``` 22 | -------------------------------------------------------------------------------- /api-client-js/endpoints/rules.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Rules { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'rules' 7 | } 8 | 9 | post (name, options, callback) { 10 | return this.client._req('post', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | put (name, options, callback) { 14 | return this.client._req('put', joinUrl(this.endpoint, name), options, callback) 15 | } 16 | 17 | get (name, options, callback) { 18 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 19 | } 20 | 21 | list (options, callback) { 22 | return this.client._req('get', this.endpoint, options, callback) 23 | } 24 | 25 | del (name, callback) { 26 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /api-client-js/endpoints/providers.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | module.exports = class Providers { 4 | constructor (client) { 5 | this.client = client 6 | this.endpoint = 'providers' 7 | } 8 | 9 | post (name, options, callback) { 10 | return this.client._req('post', joinUrl(this.endpoint, name), options, callback) 11 | } 12 | 13 | put (name, options, callback) { 14 | return this.client._req('put', joinUrl(this.endpoint, name), options, callback) 15 | } 16 | 17 | get (name, options, callback) { 18 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 19 | } 20 | 21 | list (options, callback) { 22 | return this.client._req('get', this.endpoint, options, callback) 23 | } 24 | 25 | del (name, callback) { 26 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /content/replays-sqs-messages.md: -------------------------------------------------------------------------------- 1 | ## SQS Messages Replays 2 | Cumulus archives all incoming SQS messages to S3 and removes messages once they have been processed. Unprocessed messages are archived at the path: `${stackName}/archived-incoming-messages/${queueName}/${messageId}`. 3 | 4 | The Cumulus API supports requests to replay archived SQS messages by queue name. 5 | The schema below describes the expected fields in a replay request 6 | 7 | | Field | Type | Description | 8 | | ------ | ------ | ------ | 9 | | `queueName` | string | Any valid SQS queue name (*not* ARN) | | 10 | 11 | #### Example Request 12 | 13 | ```curl 14 | $ curl -X POST https://example.com/replays/sqs --header 'Authorization: Bearer ReplaceWithTheToken' --data '{ "queueName": "my-queue" }' 15 | ``` 16 | 17 | #### Example Response 18 | 19 | ```json 20 | { 21 | "asyncOperationId": "208a463a-e096-4dd9-b006-e09345319ae6" 22 | } 23 | ``` 24 | -------------------------------------------------------------------------------- /examples/curl/auth.sh: -------------------------------------------------------------------------------- 1 | #! /bin/sh 2 | 3 | ORIGIN=$(dirname $CUMULUS_BASEURL) 4 | LOGIN_URL="$CUMULUS_BASEURL/token" 5 | 6 | # create a base64 hash of your login credentials 7 | AUTH=$(printf "$EARTHDATA_USERNAME:$EARTHDATA_PASSWORD" | base64) 8 | 9 | # Request the Earthdata url with client id and redirect uri to use with Cumulus 10 | AUTHORIZE_URL=$(curl -s -i ${LOGIN_URL} | grep location | sed -e "s/^location: //"); 11 | 12 | # Request an authorization grant code 13 | TOKEN_URL=$(curl -s -i -X POST \ 14 | -F "credentials=${AUTH}" \ 15 | -H "Origin: ${ORIGIN}" \ 16 | ${AUTHORIZE_URL%$'\r'} | grep Location | sed -e "s/^Location: //") 17 | 18 | # Request the token through the CUMULUS API url that's returned from Earthdata 19 | # Response is a JSON object of the form { token: String } 20 | # This uses the cli tool jq to parse the JSON and get the token string 21 | # More info on jq: https://stedolan.github.io/jq/ 22 | TOKEN=$(curl -s ${TOKEN_URL%$'\r'} | jq -r '.token') 23 | 24 | echo $TOKEN 25 | -------------------------------------------------------------------------------- /.circleci/config.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | jobs: 3 | build: 4 | docker: 5 | - image: circleci/node:14.18.2 6 | working_directory: ~/cumulus-api 7 | steps: 8 | - checkout 9 | 10 | # restore cache 11 | - restore_cache: 12 | keys: 13 | - cumulus-api-{{ .Branch }}-{{ checksum "package.json" }} 14 | 15 | - run: 16 | name: Installing Dependencies 17 | command: sudo npm install -g npm@8.6.0 && npm install 18 | 19 | # save node_module and yarn-cache folders 20 | - save_cache: 21 | key: cumulus-api-{{ .Branch }}-{{ checksum "package.json" }} 22 | paths: 23 | - ~/cumulus-api/node_modules 24 | 25 | 26 | - add_ssh_keys: 27 | fingerprints: 28 | - "e3:e2:f2:ad:45:cc:79:08:79:ad:b3:3f:16:a3:fd:10" 29 | 30 | - deploy: 31 | name: deploy documentation to gh-pages 32 | command: | 33 | if [ "${CIRCLE_BRANCH}" == "master" ]; then 34 | npm run build 35 | npm run deploy 36 | fi 37 | -------------------------------------------------------------------------------- /website/img/ic_cumulus_logo_blue.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /website/img/ic_cumulus_logo_white.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "@cumulus/cumulus-api", 3 | "version": "0.1.0", 4 | "description": "Cumulus API Docs", 5 | "main": "handler.js", 6 | "scripts": { 7 | "bootstrap": "./bin/docs install", 8 | "serve": "./bin/docs serve", 9 | "serve-all": "budo --dir website --live", 10 | "build": "./bin/docs build", 11 | "build-css": "tailwindcss -i ./website/input.css -o ./website/output.css --minify", 12 | "deploy": "./bin/docs deploy" 13 | }, 14 | "repository": { 15 | "type": "git", 16 | "url": "git+https://github.com/nasa/cumulus-api.git" 17 | }, 18 | "author": "https://nasa.github.io/cumulus/docs/team", 19 | "license": "Apache-2.0", 20 | "bugs": { 21 | "url": "https://github.com/nasa/cumulus-api/issues" 22 | }, 23 | "homepage": "https://github.com/nasa/cumulus-api#readme", 24 | "dependencies": { 25 | "autoprefixer": "^10.4.14", 26 | "docbox": "^1.0.11", 27 | "postcss": "^8.4.23" 28 | }, 29 | "devDependencies": { 30 | "babel-register": "^6.3.13", 31 | "budo": "^11.6.3", 32 | "cross-env": "7.0.3", 33 | "cz-conventional-changelog": "2.0.0", 34 | "expect": "^25.0.0", 35 | "prettier": "^2.8.7", 36 | "prettier-plugin-tailwindcss": "^0.2.7", 37 | "tailwindcss": "^3.3.1", 38 | "to-vfile": "^2.0.0", 39 | "uglify-js": "^3.0.27" 40 | }, 41 | "engines": { 42 | "node": ">=14.18.2", 43 | "npm": "8.6.0" 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /api-client-js/endpoints/collections.js: -------------------------------------------------------------------------------- 1 | var joinUrl = require('url-join') 2 | 3 | /** 4 | * Request collections 5 | * @name collections 6 | * @example 7 | * 8 | * const api = new CumulusApi({ baseUrl: 'baseurl' }) 9 | * const listPromise = api.collections.list() 10 | **/ 11 | module.exports = class Collections { 12 | constructor (client) { 13 | this.client = client 14 | this.endpoint = 'collections' 15 | } 16 | 17 | /** 18 | * @name post 19 | * @memberof collections 20 | **/ 21 | post (name, options, callback) { 22 | return this.client._req('post', joinUrl(this.endpoint, name), options, callback) 23 | } 24 | 25 | /** 26 | * @name put 27 | * @memberof collections 28 | **/ 29 | put (name, options, callback) { 30 | return this.client._req('put', joinUrl(this.endpoint, name), options, callback) 31 | } 32 | 33 | /** 34 | * @name get 35 | * @memberof collections 36 | **/ 37 | get (name, options, callback) { 38 | return this.client._req('get', joinUrl(this.endpoint, name), options, callback) 39 | } 40 | 41 | /** 42 | * @name list 43 | * @memberof collections 44 | **/ 45 | list (options, callback) { 46 | return this.client._req('get', this.endpoint, options, callback) 47 | } 48 | 49 | /** 50 | * @name del 51 | * @memberof collections 52 | **/ 53 | del (name, callback) { 54 | return this.client._req('delete', joinUrl(this.endpoint, name), callback) 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /content/replays.md: -------------------------------------------------------------------------------- 1 | ## Ingest Replays 2 | 3 | The Cumulus API supports requests to replay ingest notifications. 4 | The schema below describes the expected fields in a replay request 5 | 6 | | Field | Type | Required | Description | 7 | | ------ | ------ | ------ | ------ | 8 | | `type` | string | required | Currently only accepts `kinesis`. | 9 | | `kinesisStream` | string | for type `kinesis` | Any valid kinesis stream name (*not* ARN) | 10 | | `kinesisStreamCreationTimestamp` | * | optional | Any input valid for a JS Date constructor. For reasons to use this field see [AWS documentation on StreamCreationTimestamp](https://docs.aws.amazon.com/kinesis/latest/APIReference/API_ListShards.html#API_ListShards_RequestSyntax). | 11 | | `endTimestamp` | * | optional | Any input valid for a JS Date constructor. Messages newer than this timestamp will be skipped. 12 | | `startTimestamp` | * | optional | Any input valid for a JS Date constructor. Messages will be fetched from the Kinesis stream starting at this timestamp. Ignored if it is further in the past than the stream's retention period. | 13 | 14 | #### Example Request 15 | 16 | ```curl 17 | $ curl -X POST https://example.com/replays --header 'Authorization: Bearer ReplaceWithTheToken' --data '{ "type: "kinesis", "kinesisStream": "my-stream", "endTimestamp": 1567890123456, "startTimestamp": "2019-08-31T22:22:03.456Z"}' 18 | ``` 19 | 20 | #### Example Response 21 | 22 | ```json 23 | { 24 | "asyncOperationId": "208a463a-e096-4dd9-b006-e09345319ae6" 25 | } 26 | ``` 27 | -------------------------------------------------------------------------------- /website/input.css: -------------------------------------------------------------------------------- 1 | /** 2 | * This injects Tailwind's base styles and any base styles registered by 3 | * plugins. 4 | */ 5 | @tailwind base; 6 | 7 | /** 8 | * This injects Tailwind's component classes and any component classes 9 | * registered by plugins. 10 | */ 11 | @tailwind components; 12 | 13 | /** 14 | * This injects Tailwind's utility classes and any utility classes registered 15 | * by plugins. 16 | */ 17 | @tailwind utilities; 18 | 19 | /** 20 | * Use this directive to control where Tailwind injects the hover, focus, 21 | * responsive, dark mode, and other variants of each class. 22 | * 23 | * If omitted, Tailwind will append these classes to the very end of 24 | * your stylesheet by default. 25 | */ 26 | @tailwind variants; 27 | 28 | @layer components { 29 | .version { 30 | @apply text-lg text-blue hover:underline dark:text-dark-blue; 31 | } 32 | 33 | .row-release { 34 | @apply border-b hover:bg-gray-50 dark:border-gray-600 dark:hover:bg-dark-highlight/10; 35 | } 36 | 37 | .latest-badge { 38 | @apply ml-2 mr-2 rounded border border-green-400 bg-green-100 px-2.5 py-0.5 text-xs font-medium text-green-800 dark:bg-gray-700 dark:text-green-400; 39 | } 40 | } 41 | 42 | tr { 43 | height: 50px; 44 | } 45 | 46 | td { 47 | padding: 0 20px; 48 | } 49 | 50 | #mobile-menu { 51 | visibility: hidden; 52 | opacity: 0; 53 | transition: opacity 2s 0 ease; 54 | } 55 | 56 | .overlay { 57 | background-color: rgba(0,0,0,.50); 58 | cursor: pointer; 59 | } -------------------------------------------------------------------------------- /website/v11.0.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v13.0.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v13.3.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v13.4.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v14.0.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v14.1.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v16.1.1/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v18.1.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v18.4.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v18.5.3/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v20.0.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v20.1.2/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v21.0.0/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v20.1.2/build/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /website/v21.0.0/build/css/railscasts.css: -------------------------------------------------------------------------------- 1 | .hljs { 2 | display: block; 3 | overflow-x: auto; 4 | padding: 0.5em; 5 | background: #232323; 6 | color: #e6e1dc; 7 | } 8 | 9 | .hljs-comment, 10 | .hljs-quote { 11 | color: #bc9458; 12 | font-style: italic; 13 | } 14 | 15 | .hljs-keyword, 16 | .hljs-selector-tag { 17 | color: #c26230; 18 | } 19 | 20 | .hljs-string, 21 | .hljs-number, 22 | .hljs-regexp, 23 | .hljs-variable, 24 | .hljs-template-variable { 25 | color: #a5c261; 26 | } 27 | 28 | .hljs-subst { 29 | color: #519f50; 30 | } 31 | 32 | .hljs-tag, 33 | .hljs-name { 34 | color: #e8bf6a; 35 | } 36 | 37 | .hljs-type { 38 | color: #da4939; 39 | } 40 | 41 | 42 | .hljs-symbol, 43 | .hljs-bullet, 44 | .hljs-built_in, 45 | .hljs-builtin-name, 46 | .hljs-attr, 47 | .hljs-link { 48 | color: #6d9cbe; 49 | } 50 | 51 | .hljs-params { 52 | color: #d0d0ff; 53 | } 54 | 55 | .hljs-attribute { 56 | color: #cda869; 57 | } 58 | 59 | .hljs-meta { 60 | color: #9b859d; 61 | } 62 | 63 | .hljs-title, 64 | .hljs-section { 65 | color: #ffc66d; 66 | } 67 | 68 | .hljs-addition { 69 | background-color: #144212; 70 | color: #e6e1dc; 71 | display: inline-block; 72 | width: 100%; 73 | } 74 | 75 | .hljs-deletion { 76 | background-color: #600; 77 | color: #e6e1dc; 78 | display: inline-block; 79 | width: 100%; 80 | } 81 | 82 | .hljs-selector-class { 83 | color: #9b703f; 84 | } 85 | 86 | .hljs-selector-id { 87 | color: #8b98ab; 88 | } 89 | 90 | .hljs-emphasis { 91 | font-style: italic; 92 | } 93 | 94 | .hljs-strong { 95 | font-weight: bold; 96 | } 97 | 98 | .hljs-link { 99 | text-decoration: underline; 100 | } 101 | -------------------------------------------------------------------------------- /template/src/custom/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | /** 4 | * Brand names, in order to decreasing length, for different 5 | * media queries. 6 | */ 7 | module.exports.brandNames = { 8 | desktop: 'Cumulus API', 9 | tablet: 'Cumulus API', 10 | mobile: 'API Docs' 11 | }; 12 | 13 | /** 14 | * Classes that define the top-left brand box. 15 | */ 16 | module.exports.brandClasses = 'fill-blue'; 17 | 18 | 19 | /** 20 | * Text for the link back to the linking website. 21 | */ 22 | module.exports.backLink = 'Back to Cumulus Docs'; 23 | 24 | /** 25 | * Runs after highlighting code samples. You can use this 26 | * hook to, for instance, highlight a token and link it 27 | * to some canonical part of documentation. 28 | */ 29 | module.exports.postHighlight = function(html) { 30 | return html; 31 | }; 32 | 33 | /** 34 | * Highlight tokens in endpoint URLs, optionally linking to documentation 35 | * or adding detail. This is the equivalent of postHighlight but it 36 | * operates on endpoint URLs only. 37 | */ 38 | function highlightTokens(str) { 39 | return str.replace(/{[\w_]+}/g, 40 | (str) => '' + str + ''); 41 | } 42 | 43 | /** 44 | * Transform endpoints given as strings in a highlighted block like 45 | * 46 | * ```endpoint 47 | * GET /foo/bar 48 | * ``` 49 | * 50 | * Into HTML nodes that format those endpoints in nice ways. 51 | */ 52 | module.exports.transformURL = function(value) { 53 | let parts = value.split(/\s+/); 54 | return { 55 | type: 'html', 56 | value: `
57 |
${parts[0]}
58 |
${highlightTokens(parts[1])}
59 |
` 60 | }; 61 | }; 62 | 63 | module.exports.remarkPlugins = []; 64 | -------------------------------------------------------------------------------- /api-client-py/cumulus_api/cumulus_api.py: -------------------------------------------------------------------------------- 1 | # stdlib 2 | import json 3 | import base64 4 | from urlparse import urlparse 5 | 6 | # requests 7 | import requests 8 | 9 | class CumulusApi(object): 10 | """An API client for Cumulus 11 | Example usage: 12 | >>> import os 13 | >>> from cumulus_api import CumulusApi 14 | >>> 15 | >>> BASEURL = os.environ["CUMULUS_BASEURL"] 16 | >>> USERNAME = os.environ["EARTHDATA_USERNAME"] 17 | >>> PASSWORD = os.environ["EARTHDATA_PASSWORD"] 18 | >>> 19 | >>> api = CumulusAPI(BASEURL) 20 | >>> api.login(USERNAME, PASSWORD) 21 | """ 22 | 23 | def __init__(self, base_url, access_token=None): 24 | # TODO: validate base_url 25 | self.base_url = base_url 26 | self.access_token = access_token 27 | 28 | def login(self, username, password): 29 | # send a request to cumulus to get the Earthdata authorization url 30 | authorize_response = requests.get(self.base_url + '/token', allow_redirects=False) 31 | authorize_url = authorize_response.headers['location'] 32 | 33 | # send username & password to Earthdata to request a code to use to get an access token 34 | credentials = base64.b64encode('{}:{}'.format(username, password)) 35 | payload = { 'credentials': credentials } 36 | parsed_url = urlparse(self.base_url) 37 | headers = {'origin': parsed_url.scheme + '://' + parsed_url.hostname } 38 | grant_code_response = requests.post(authorize_url, data=payload, headers=headers, allow_redirects=False) 39 | grant_code_url = grant_code_response.headers['Location'] 40 | 41 | # get the access token for use in future requests 42 | token_response = requests.get(grant_code_url) 43 | self.access_token = token_response.json()['message']['token'] 44 | return self.access_token 45 | -------------------------------------------------------------------------------- /bin/docs: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | copy_docs() { 4 | echo 'Copying API content and custom template to DocBox' 5 | rm -rf node_modules/docbox/content 6 | ln -s $(pwd)/content $(pwd)/node_modules/docbox/content 7 | cp template/src/components/app.js node_modules/docbox/src/components/app.js 8 | cp template/src/custom/* node_modules/docbox/src/custom/ 9 | cp template/defaults/* node_modules/docbox/ 10 | } 11 | 12 | # Serves docbox 13 | serve() { 14 | cd node_modules/docbox || exit 15 | npm start 16 | } 17 | 18 | build() { 19 | RELEASE=$1 20 | rm -rf website/unreleased 21 | npm run build-css 22 | pushd node_modules/docbox || exit 23 | rm -rf build 24 | mkdir -p build 25 | npm run build 26 | cp -r css build/ 27 | cp index.html build/ 28 | cp bundle.js build/ 29 | popd 30 | cp -r node_modules/docbox/build website/unreleased 31 | if [ "$RELEASE" ] 32 | then 33 | cp -r node_modules/docbox/build "website/$RELEASE" 34 | fi 35 | } 36 | 37 | deploy() { 38 | cd website || exit 39 | git init 40 | git config user.name "Dvseed" 41 | git config user.email "info@developmentseed.org" 42 | git config commit.gpgsign "false" 43 | git add . 44 | git commit -m "Automated to gh-pages [skip ci]" 45 | git push --force --quiet git@github.com:nasa/cumulus-api.git master:gh-pages 46 | rm -rf .git/ 47 | } 48 | 49 | while [[ $1 ]] 50 | do 51 | case "$1" in 52 | serve) 53 | copy_docs 54 | serve 55 | exit 0 56 | ;; 57 | copy) 58 | copy_docs 59 | exit 0 60 | ;; 61 | build) 62 | copy_docs 63 | build $2 64 | exit 0 65 | ;; 66 | deploy) 67 | deploy 68 | exit 0 69 | ;; 70 | *) 71 | echo 'Argument(s) not supported' 72 | exit 0 73 | ;; 74 | esac 75 | done 76 | -------------------------------------------------------------------------------- /release.md: -------------------------------------------------------------------------------- 1 | # Releasing a new Cumulus API version 2 | 3 | ## Releasing a version 4 | 5 | ### 1. Create a branch for the new release 6 | 7 | #### From Master 8 | 9 | Create a branch titled `release-MAJOR.MINOR.x` for the release (use a literal x 10 | for the patch version). 11 | 12 | ```shell 13 | git checkout -b release-MAJOR.MINOR.x 14 | ``` 15 | e.g.: 16 | ```shell 17 | git checkout -b release-9.1.x 18 | ``` 19 | 20 | If creating a new major version release from master, say `5.0.0`, then the 21 | branch would be named `release-5.0.x`. If creating a new minor version release 22 | from master, say `1.14.0` then the branch would be named `release-1.14.x`. 23 | 24 | Push the `release-MAJOR.MINOR.x` branch to GitHub if it was created locally. 25 | (Commits should be even with master at this point.) 26 | 27 | If creating a patch release, you can check out the existing base branch. NOTE: 28 | We **should not** create a patch release if there is no API update. 29 | 30 | ### 2. Create a git tag for the release 31 | 32 | From the minor version base branch (`release-1.2.x`), create and push a new git 33 | tag: 34 | 35 | ```bash 36 | git tag -a vMAJOR.MINOR.PATCH -m "Release MAJOR.MINOR.PATCH" 37 | git push origin vMAJOR.MINOR.PATCH 38 | ``` 39 | e.g.: 40 | ```shell 41 | git tag -a v9.1.0 -m "Release 9.1.0" 42 | git push origin v9.1.0 43 | ``` 44 | 45 | ### 3. Generate the API document 46 | 47 | ```bash 48 | npm install 49 | ``` 50 | ```bash 51 | npm run build vMAJOR.MINOR.PATCH 52 | ``` 53 | e.g.: 54 | ```shell 55 | npm run build v9.1.0 56 | ``` 57 | 58 | You can view the generated API document with `npm run serve-all`. 59 | 60 | ### 4. Add the new API document 61 | 62 | Add the new API document link to `website/index.html`. Then add it to the 63 | commit along with the new API document with `git add website/index.html`. 64 | 65 | ```bash 66 | git add website/vMAJOR.MINOR.PATCH 67 | git commit -m "Release MAJOR.MINOR.PATCH" 68 | ``` 69 | e.g.: 70 | ```shell 71 | git add website/v9.1.0 website/index.html 72 | git commit -m "Release 9.1.0" 73 | ``` 74 | 75 | ### 5: Create a PR against master 76 | -------------------------------------------------------------------------------- /content/async-operations.md: -------------------------------------------------------------------------------- 1 | ## List async operations 2 | 3 | Async operations are long-running requests serviced by the Cumulus API. 4 | 5 | These tend to be bulk operations. Examples include bulk granule operations and replaying ingest notifications. 6 | 7 | This endpoint lists async operations in the Cumulus system. 8 | 9 | ```endpoint 10 | GET /asyncOperations 11 | ``` 12 | 13 | #### Example request 14 | 15 | ```curl 16 | $ curl https://example.com/asyncOperations --header 'Authorization: Bearer ReplaceWithTheToken' 17 | ``` 18 | 19 | #### Example response 20 | 21 | ```json 22 | { 23 | "meta": { 24 | "name": "cumulus-api", 25 | "stack": "lpdaac-cumulus", 26 | "table": "async_operations", 27 | "limit": 1, 28 | "page": 1, 29 | "count": 8 30 | }, 31 | "results": [ 32 | { 33 | "output": "{\"deletedGranules\":[\"granule-id-f02a53418f\"]}", 34 | "createdAt": 1591384094512, 35 | "taskArn": "arn:aws:ecs:us-east-1:111111111111:task/d481e76e-f5fc-9c1c-2411-fa13779b111a", 36 | "description": "Bulk granule deletion", 37 | "operationType": "Bulk Granule Delete", 38 | "id": "0eb8e809-8790-5409-1239-bcd9e8d28b8e", 39 | "status": "SUCCEEDED", 40 | "updatedAt": 1591384094512, 41 | "timestamp": 1591384095235 42 | } 43 | ] 44 | } 45 | ``` 46 | 47 | ## Retrieve async operation 48 | 49 | Retrieve information about a single async operation. Useful for determining the status of an async operation. 50 | 51 | ```endpoint 52 | GET /asyncOperations/{id} 53 | ``` 54 | 55 | #### Example request 56 | 57 | ```curl 58 | $ curl https://example.com/asyncOperations/0eb8e809-8790-5409-1239-bcd9e8d28b8e --header 'Authorization: Bearer ReplaceWithTheToken' 59 | ``` 60 | 61 | #### Example response 62 | 63 | ```json 64 | { 65 | "id": "0eb8e809-8790-5409-1239-bcd9e8d28b8e", 66 | "updatedAt": 1574730504762, 67 | "status": "RUNNING", 68 | "taskArn": "arn:aws:ecs:us-east-1:111111111111:task/d481e76e-f5fc-9c1c-2411-fa13779b111a", 69 | "description": "Bulk granule deletion", 70 | "operationType": "Bulk Granule Delete" 71 | } 72 | ``` 73 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing 2 | 3 | Thanks for considering contributing and making our planet easier to explore! 4 | 5 | We're excited you would like to contribute to Cumulus! Whether you're finding bugs, adding new features, fixing anything broken, or improving documentation, get started by submitting an issue or pull request! 6 | 7 | ## Submitting an Issue 8 | 9 | If you have any questions or ideas, or notice any problems or bugs, first [search open issues](https://github.com/nasa/cumulus-api/issues) to see if the issue has already been submitted. We may already be working on the issue. If you think your issue is new, you're welcome to [create a new issue](https://github.com/nasa/cumulus-api/issues/new). 10 | 11 | ## Pull Requests 12 | 13 | If you want to submit your own contributions, follow these steps: 14 | 15 | * Fork the Cumulus API repo 16 | * Create a new branch from the branch you'd like to contribute to 17 | * If an issue doesn't already exist, submit one (see above) 18 | * [Create a pull request](https://help.github.com/articles/creating-a-pull-request/) from your fork into the target branch of the nasa/cumulus-api repo 19 | * Be sure to [mention the corresponding issue number](https://help.github.com/articles/closing-issues-using-keywords/) in the PR description, i.e. "Fixes Issue #10" 20 | * Upon submission of a pull request, the Cumulus development team will review the code 21 | * The request will then either be merged, declined, or an adjustment to the code will be requested 22 | 23 | ## Guidelines 24 | 25 | We ask that you follow these guidelines with your contributions: 26 | 27 | ### Commits 28 | 29 | * Make small commits that show the individual changes you are making 30 | * Write descriptive commit messages that explain your changes 31 | 32 | Example of a good commit message: 33 | 34 | ``` 35 | Improve contributing guidelines. Fixes #10 36 | 37 | Improve contributing docs and consolidate them in the standard location https://help.github.com/articles/setting-guidelines-for-repository-contributors/ 38 | ``` 39 | 40 | ### For more information on Cumulus governance, see the [Cumulus Code Contribution Guidelines](https://docs.google.com/document/d/14J_DS6nyQ32BpeVjdR-YKfzHAzFB299tKghPGshXUTU/edit) and [the Cumulus Wiki](https://wiki.earthdata.nasa.gov/display/CUMULUS/Cumulus). 41 | -------------------------------------------------------------------------------- /content/dead-letter-archive.md: -------------------------------------------------------------------------------- 1 | ## Recover cumulus messages 2 | 3 | Endpoint provides a mechanism for recovery of S3 sfEventSqsToDbRecords dead letter objects (created as described in the [Core Documentation](https://nasa.github.io/cumulus/docs/features/dead_letter_archive)). The endpoint will invoke an async operation that will attempt to process all of the objects in the specified location. 4 | 5 | The endpoint by default will process all records contained in the S3 objects from the default storage location on the S3 system bucket under the prefix of `/dead-letter-archive/sqs/`. However, it is likely useful to process a subset of those objects, which you can do by moving the desired subset of objects to a new path on S3 and then specifying that new path using the `path` parameter to the endpoint request. 6 | 7 | The query uses the following optional parameters: 8 | 9 | | parameter | description | 10 | | --- | --- | 11 | | bucket | The bucket to read records from. Defaults to the Core system bucket| 12 | | path | The S3 prefix (path) to read DLQ records from. Defaults to `/dead-letter-archive/sqs/`| 13 | | batchSize | Specifies how many DLA objects to read from S3 and hold in memory. Defaults to 1000| 14 | | concurrency | Specifies how many messages to process at the same time. Defaults to 30| 15 | | dbMaxPool | Specifies how many database connections to allow the process to utilize. Defaults to 30. Process should at minimum the value set for `concurrency`| 16 | 17 | ```endpoint 18 | POST /deadLetterArchive/recoverCumulusMessages 19 | ``` 20 | 21 | #### Example request 22 | 23 | ```curl 24 | curl -X POST https://cumulus.podaac.sit.earthdata.nasa.gov/deadLetterArchive/recoverCumulusMessages --header "Authorization: Bearer $TOKEN" --header 'Content-Type: application/json' --data '{ 25 | "bucket": "some-cumulus-bucket", 26 | "path": "some/path/to/records/" 27 | }' 28 | ``` 29 | 30 | #### Example response 31 | 32 | ```json 33 | { 34 | "createdAt":1646861517957, 35 | "updatedAt":1646861517957, 36 | "id":"a0cd2cf0-a677-e82a-27d1-0a09271aa37d", 37 | "status":"RUNNING", 38 | "taskArn":"arn:aws:ecs:us-west-2:xxxxxxxxxx:task/stack-CumulusECSCluster/{SHA}", 39 | "description":"Dead-Letter Processor ECS Run", 40 | "operationType":"Dead-Letter Processing" 41 | } 42 | ``` 43 | -------------------------------------------------------------------------------- /template/src/custom/content.js: -------------------------------------------------------------------------------- 1 | const fs = require('fs'); 2 | 3 | /** 4 | * This file exports the content of your website, as a bunch of concatenated 5 | * Markdown files. By doing this explicitly, you can control the order 6 | * of content without any level of abstraction. 7 | * 8 | * Using the brfs module, fs.readFileSync calls in this file are translated 9 | * into strings of those files' content before the file is delivered to a 10 | * browser: the content is read ahead-of-time and included in bundle.js. 11 | */ 12 | module.exports = 13 | '# Introduction\n' + 14 | fs.readFileSync('./content/intro.md', 'utf8') + '\n' + 15 | 16 | '# Versioning\n' + 17 | fs.readFileSync('./content/version.md', 'utf8') + '\n' + 18 | 19 | '# Authentication\n' + 20 | fs.readFileSync('./content/auth.md', 'utf8') + '\n' + 21 | 22 | '# Providers\n' + 23 | fs.readFileSync('./content/providers.md', 'utf8') + '\n' + 24 | 25 | '# Collections\n' + 26 | fs.readFileSync('./content/collections.md', 'utf8') + '\n' + 27 | 28 | '# Granules\n' + 29 | fs.readFileSync('./content/granules.md', 'utf8') + '\n' + 30 | 31 | '# PDRs\n' + 32 | fs.readFileSync('./content/pdrs.md', 'utf8') + '\n' + 33 | 34 | '# Rules\n' + 35 | fs.readFileSync('./content/rules.md', 'utf8') + '\n' + 36 | 37 | '# Stats\n' + 38 | fs.readFileSync('./content/stats.md', 'utf8') + '\n' + 39 | 40 | '# Logs\n' + 41 | fs.readFileSync('./content/logs.md', 'utf8') + '\n' + 42 | 43 | '# Granule CSV\n' + 44 | fs.readFileSync('./content/granule-csv.md', 'utf8') + '\n' + 45 | 46 | '# Executions\n' + 47 | fs.readFileSync('./content/executions.md', 'utf8') + '\n' + 48 | 49 | '# Workflows\n' + 50 | fs.readFileSync('./content/workflows.md', 'utf8') + '\n' + 51 | 52 | '# Async Operations\n' + 53 | fs.readFileSync('./content/async-operations.md', 'utf8') + '\n' + 54 | 55 | '# Replays\n' + 56 | fs.readFileSync('./content/replays.md', 'utf8') + '\n' + 57 | 58 | '# Schemas\n' + 59 | fs.readFileSync('./content/schemas.md', 'utf8') + '\n' + 60 | 61 | '# Reconciliation Reports\n' + 62 | fs.readFileSync('./content/reconciliation-reports.md', 'utf8') + '\n' + 63 | 64 | '# Instance Metadata\n' + 65 | fs.readFileSync('./content/instance-meta.md') + '\n' + 66 | 67 | '# Dashboard\n' + 68 | fs.readFileSync('./content/dashboard.md') + '\n' + 69 | 70 | '# ORCA\n' + 71 | fs.readFileSync('./content/orca.md', 'utf8') + '\n' + 72 | 73 | '# Dead Letter Archive\n' + 74 | fs.readFileSync('./content/dead-letter-archive.md') + '\n' 75 | ; 76 | -------------------------------------------------------------------------------- /content/stats.md: -------------------------------------------------------------------------------- 1 | ## Summary 2 | 3 | Retrieve a summary of statistics around the granules in the system. The `collections` returned are the number of distinct collections for the granules active during the given time period, defaulted to the last day if none is specified. 4 | 5 | ```endpoint 6 | GET /stats 7 | ``` 8 | 9 | #### Example Request 10 | 11 | ```curl 12 | $ curl https://example.com/stats --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example success response 16 | 17 | ```json 18 | { 19 | "errors": { 20 | "dateFrom": "1970-01-18T12:36:59+00:00", 21 | "dateTo": "2017-12-26T04:38:15+00:00", 22 | "value": 2, 23 | "aggregation": "count", 24 | "unit": "error" 25 | }, 26 | "collections": { 27 | "dateFrom": "1970-01-01T12:00:00+00:00", 28 | "dateTo": "2017-12-26T04:38:15+00:00", 29 | "value": 3, 30 | "aggregation": "count", 31 | "unit": "collection" 32 | }, 33 | "processingTime": { 34 | "dateFrom": "1970-01-18T12:36:59+00:00", 35 | "dateTo": "2017-12-26T04:38:15+00:00", 36 | "value": null, 37 | "aggregation": "average", 38 | "unit": "second" 39 | }, 40 | "granules": { 41 | "dateFrom": "1970-01-18T12:36:59+00:00", 42 | "dateTo": "2017-12-26T04:38:15+00:00", 43 | "value": 8, 44 | "aggregation": "count", 45 | "unit": "granule" 46 | } 47 | } 48 | ``` 49 | 50 | ## Count 51 | 52 | Count the value frequencies for a given field, for a given type of record in Cumulus. Requires the following query parameters, and may include the regular filter parameters: 53 | 54 | | query string parameter | description | 55 | | --- | --- | 56 | | `type={providers|collections|granules|pdrs|logs}` | type of Cumulus record to query | 57 | | `field={fieldName}` | which field to count frequencies for; no default | 58 | 59 | ```endpoint 60 | GET /stats/aggregate 61 | ``` 62 | 63 | #### Example request 64 | 65 | ```curl 66 | curl 'https://example.com/stats/aggregate?field=status&type=pdrs' --header 'Authorization: Bearer ReplaceWithTheToken' 67 | ``` 68 | 69 | #### Example response 70 | 71 | ```json 72 | { 73 | "meta": { 74 | "name": "cumulus-api", 75 | "count": 52, 76 | "field": "status.keyword" 77 | }, 78 | "count": [ 79 | { 80 | "key": "failed", 81 | "count": 43 82 | }, 83 | { 84 | "key": "completed", 85 | "count": 5 86 | }, 87 | { 88 | "key": "parsed", 89 | "count": 3 90 | } 91 | ] 92 | } 93 | ``` -------------------------------------------------------------------------------- /website/v11.0.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v13.0.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v13.3.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v13.4.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v14.0.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v14.1.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v16.1.1/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v18.1.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v18.4.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v18.5.3/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v20.0.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v20.1.2/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v21.0.0/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v20.1.2/build/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /website/v21.0.0/build/css/style.css: -------------------------------------------------------------------------------- 1 | /* BASE OVERRIDES */ 2 | 3 | /* Add buffer for nicer anchor links */ 4 | .prose h2:first-child { 5 | padding-top: 20px; 6 | } 7 | 8 | .prose h3:first-child { 9 | padding-top: 20px; 10 | } 11 | 12 | /* Header gets big */ 13 | @media only screen and (max-width:960px) { 14 | .prose h2:first-child { 15 | padding-top: 60px; 16 | } 17 | 18 | .prose h3:first-child { 19 | padding-top: 60px; 20 | } 21 | } 22 | 23 | /* Header gets bigger */ 24 | @media only screen and (max-width:640px) { 25 | .prose h2:first-child { 26 | padding-top: 100px; 27 | } 28 | 29 | .prose h3:first-child { 30 | padding-top: 100px; 31 | } 32 | } 33 | 34 | 35 | /* tables are too giant */ 36 | .prose table, 37 | .prose table code { 38 | margin-bottom: 20px; 39 | font-size: 12px; 40 | line-height: 1.5; 41 | } 42 | 43 | .prose table th, .prose table td { 44 | padding: 5px; 45 | } 46 | 47 | .dark.keyline-top, 48 | .dark.keyline-bottom { 49 | border-color: #313131; 50 | } 51 | 52 | html, body, #app, .container { 53 | height: 100%; 54 | } 55 | 56 | body pre { 57 | padding: 0; 58 | } 59 | 60 | /* BASE ADDONS */ 61 | .fill-dark2 { background-color: #313131; } 62 | .fill-dark2 .rounded-toggle input[type=radio]:checked + label, 63 | .fill-dark2 .rounded-toggle .active { background-color: #313131; } 64 | .space-top3 { margin-top: 30px;} 65 | .space-top5 { margin-top: 50px;} 66 | .line-height15 { line-height: 15px; } 67 | .pad00y { padding-top: 2px; padding-bottom: 2px; } 68 | .space-bottom00 { margin-bottom: 3px;} 69 | 70 | .endpoint { 71 | width: 100%; 72 | display: flex; 73 | } 74 | 75 | .endpoint-method { 76 | } 77 | 78 | .endpoint-url { 79 | flex-grow: 1; 80 | word-wrap: break-word; 81 | } 82 | 83 | .endpoint-url a { 84 | background-color: rgba(255, 255, 255, 0.1); 85 | border-radius: 2px; 86 | font-weight:bold; 87 | padding: 2px; 88 | color: #fff; 89 | } 90 | 91 | .endpoint-url a:hover { 92 | background-color: rgba(255, 255, 255, 0.15); 93 | } 94 | 95 | .endpoint-token { 96 | } 97 | 98 | a.hljs-linked { 99 | border-radius: 2px; 100 | color: #a5c261; 101 | background: #383C2F; 102 | padding: 2px; 103 | } 104 | 105 | body .prose blockquote { 106 | padding: 5px 10px; 107 | background: #232323; 108 | } 109 | 110 | .preview { 111 | background-image: -webkit-linear-gradient(#F1F075, #F1F075); 112 | background-size: 10px 10px; 113 | background-repeat: repeat-y; 114 | } 115 | 116 | .preview h2::after, 117 | .preview h3::after { 118 | content: 'PREVIEW'; 119 | background-color: #F1F075; 120 | border-radius: 2px; 121 | font-size: 9px; 122 | font-weight: normal; 123 | padding: 2px 5px; 124 | color: rgba(0, 0, 0, 0.5); 125 | margin-left: 10px; 126 | vertical-align: middle; 127 | } 128 | -------------------------------------------------------------------------------- /content/pdrs.md: -------------------------------------------------------------------------------- 1 | ## List PDRs 2 | 3 | List PDRs in the Cumulus system. 4 | 5 | ```endpoint 6 | GET /pdrs 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl https://example.com/pdrs --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example response 16 | 17 | ```json 18 | { 19 | "meta": { 20 | "name": "cumulus-api", 21 | "stack": "lpdaac-cumulus", 22 | "table": "pdrs", 23 | "limit": 1, 24 | "page": 1, 25 | "count": 8 26 | }, 27 | "results": [ 28 | { 29 | "pdrName": "7970bff5-128a-489f-b43c-de4ad7834ce5.PDR", 30 | "collectionId": "MOD11A1___006", 31 | "status": "failed", 32 | "provider": "LP_TS2_DataPool", 33 | "progress": 0, 34 | "execution": "https://console.aws.amazon.com/states/home?region=us-east-1#/executions/details/arn:aws:states:us-east-1:ACCOUNT:execution:LpdaacCumulusIngestGranuleStateMachine-N3CLGBXRPAT9:6ef0c52f83c549db58b3a1e50", 35 | "PANSent": false, 36 | "PANmessage": "N/A", 37 | "stats": { 38 | "processing": 0, 39 | "completed": 0, 40 | "failed": 0, 41 | "total": 0 42 | }, 43 | "createdAt": 1514305411204, 44 | "timestamp": 1514305424036, 45 | "duration": 12.832 46 | } 47 | ] 48 | } 49 | ``` 50 | 51 | ## Retrieve PDR 52 | 53 | Retrieve a single PDR. 54 | 55 | ```endpoint 56 | GET /pdrs/{pdrName} 57 | ``` 58 | 59 | #### Example request 60 | 61 | ```curl 62 | $ curl https://example.com/pdrs/7970bff5-128a-489f-b43c-de4ad7834ce5.PDR --header 'Authorization: Bearer ReplaceWithTheToken' 63 | ``` 64 | 65 | #### Example response 66 | 67 | ```json 68 | { 69 | "pdrName": "7970bff5-128a-489f-b43c-de4ad7834ce5.PDR", 70 | "collectionId": "MOD11A1___006", 71 | "status": "failed", 72 | "provider": "LP_TS2_DataPool", 73 | "progress": 0, 74 | "execution": "https://console.aws.amazon.com/states/home?region=us-east-1#/executions/details/arn:aws:states:us-east-1:ACCOUNT:execution:LpdaacCumulusIngestGranuleStateMachine-N3CLGBXRPAT9:6ef0c52f83c549db58b3a1e50", 75 | "PANSent": false, 76 | "PANmessage": "N/A", 77 | "stats": { 78 | "processing": 0, 79 | "completed": 0, 80 | "failed": 0, 81 | "total": 0 82 | }, 83 | "createdAt": 1514305411204, 84 | "timestamp": 1514305424036, 85 | "duration": 12.832, 86 | "_id": "7970bff5-128a-489f-b43c-de4ad7834ce5.PDR" 87 | } 88 | ``` 89 | 90 | ## Delete PDR 91 | 92 | Delete a PDR from Cumulus. Its granules will remain, and the PDR may be re-discovered and re-ingested/re-processed from scratch in the future. 93 | 94 | ```endpoint 95 | DELETE /pdrs/{pdrName} 96 | ``` 97 | 98 | #### Example request 99 | 100 | ```curl 101 | $ curl --request DELETE https://example.com/pdrs/good_25grans.PDR --header 'Authorization: Bearer ReplaceWithTheToken' 102 | 103 | ``` 104 | 105 | #### Example response 106 | 107 | ```json 108 | { 109 | "message": "Record deleted" 110 | } 111 | ``` 112 | -------------------------------------------------------------------------------- /content/schemas.md: -------------------------------------------------------------------------------- 1 | ## Retrieve schema 2 | 3 | Retrieve the data schema for a particular type of Cumulus record. 4 | 5 | This schema describes the expected format of a record's JSON object when retrieving from Cumulus, as well as a summary of what each field may contain. The schema response can also be used to determine which fields are required when creating a new record using the API. 6 | 7 | Supported `type` values are `provider`, `collection`, `granule`, and `pdr`. 8 | 9 | ```endpoint 10 | GET /schemas/{type} 11 | ``` 12 | 13 | #### Example request 14 | 15 | ```curl 16 | $ curl https://example.com/schemas/provider --header 'Authorization: Bearer ReplceWithTheToken' 17 | ``` 18 | 19 | #### Example response 20 | 21 | ```json 22 | { 23 | "$schema": "http://json-schema.org/draft-04/schema#", 24 | "title": "Provider Object", 25 | "description": "Keep the information about each ingest endpoint", 26 | "type": "object", 27 | "properties": { 28 | "name": { 29 | "title": "Title", 30 | "description": "A title for the provider record", 31 | "type": "string", 32 | "pattern": "^([\\w\\d_\\-]*)$" 33 | }, 34 | "providerName": { 35 | "title": "Provider, e.g. MODAPS", 36 | "description": "Name of the SIP", 37 | "type": "string" 38 | }, 39 | "protocol": { 40 | "title": "Protocol", 41 | "type": "string", 42 | "enum": [ 43 | "http", 44 | "ftp" 45 | ], 46 | "default": "http" 47 | }, 48 | "host": { 49 | "title": "Host", 50 | "type": "string" 51 | }, 52 | "path": { 53 | "title": "Path to the PDR/files folder", 54 | "type": "string" 55 | }, 56 | "config": { 57 | "title": "Configuration", 58 | "type": "object", 59 | "properties": { 60 | "username": { 61 | "type": "string" 62 | }, 63 | "password": { 64 | "type": "string" 65 | }, 66 | "port": { 67 | "type": "string" 68 | } 69 | } 70 | }, 71 | "status": { 72 | "title": "Status", 73 | "type": "string", 74 | "enum": [ 75 | "ingesting", 76 | "stopped", 77 | "failed" 78 | ], 79 | "default": "stopped", 80 | "readonly": true 81 | }, 82 | "isActive": { 83 | "title": "Is Active?", 84 | "type": "boolean", 85 | "default": false, 86 | "readonly": true 87 | }, 88 | "regex": { 89 | "type": "object", 90 | "patternProperties": { 91 | "^([\\S]*)$": { 92 | "type": "string" 93 | } 94 | }, 95 | "readonly": true 96 | }, 97 | "lastTimeIngestedAt": { 98 | "title": "Last Time Ingest from the Provider", 99 | "type": "number", 100 | "readonly": true 101 | }, 102 | "createdAt": { 103 | "type": "number", 104 | "readonly": true 105 | }, 106 | "updatedAt": { 107 | "type": "number", 108 | "readonly": true 109 | } 110 | }, 111 | "required": [ 112 | "name", 113 | "providerName", 114 | "protocol", 115 | "host", 116 | "path", 117 | "isActive", 118 | "status", 119 | "createdAt", 120 | "updatedAt" 121 | ] 122 | } 123 | ``` 124 | -------------------------------------------------------------------------------- /content/intro.md: -------------------------------------------------------------------------------- 1 | ## Cumulus API 2 | 3 | The Cumulus API allows developers to interact with the [Cumulus Framework](https://github.com/nasa/cumulus), such as monitoring status or creating, editing, and deleting records. This is the same API that powers the [Cumulus dashboard](https://github.com/nasa/cumulus-dashboard). 4 | 5 | By utilizing this API, a developer can integrate with the Cumulus framework in any language or environment; although interacting with Cumulus through the Cumulus dashboard may be appropriate for many end users, for some use cases it's best to have the flexibility of a web-accessible API. 6 | 7 | The API accepts and responds with JSON payloads at various HTTPS endpoints. 8 | 9 | In order to use these endpoints, you must include authentication information in your HTTPS request; authentication is explained in the following section. 10 | 11 | The following table lists the [query string](https://en.wikipedia.org/wiki/Query_string) parameters that can be used with most of the Cumulus API endpoints. `{fieldName}` is a stand-in for any of the fields in the record, and for nested objects dot notation can be used; for example, valid `fieldName`s include: `pdrName`, `status`, and `recipe.processStep.description`. 12 | 13 | | query string parameter | description | 14 | | ----- | ----------- | 15 | | `countOnly={boolean}` | For search/list endpoints ONLY, if set to `true`, return only count/meta information but an empty array of results. Used for cases where returning results is undesirable for performance reasons. Defaults to `false` | 16 | | `limit={number}` | Number of records to be returned by the API call; default is `10`. A value of `null` will return all records. | 17 | | `page={number}` | page number, 1-indexed; default is `1` | 18 | | `sort_by={fieldName}` | which field to sort by; default is `timestamp` | 19 | | `order={asc|desc}` | whether to sort in `asc` or `desc` order | 20 | | `sort_key[]={-fieldName1}&sort_key[]={fieldName2}` | One or more sort keys can be specified using the sort_key[] parameter. The order used impacts searching. Fields can be prepended with a `-` to sort in descending order or a `+` to sort in ascending. Ascending order is the default. The + must be escaped with %2B| 21 | | `prefix={value}` | `startsWith` search of the Providers by `name`, Collections by `name`, Granules by `granuleId`, PDRs by `pdrName`, Rules by `name`, Executions by `arn`, Async Operations by `id`, Reconciliation Reports by `name` | 22 | | `infix={value}` | `includes` search of the Providers by `name`, Collections by `name`, Granules by `granuleId`, PDRs by `pdrName`, Rules by `name`, Executions by `arn`, Async Operations by `id`, Reconciliation Reports by `name` | 23 | | `fields={fieldName1, fieldName2}` | which fields to return, separated by a comma | 24 | | `{fieldName}={value}` | exact value match for the given field | 25 | | `{fieldName}__from={number}` | for numeric fields, field value must be greater than the given number | 26 | | `{fieldName}__to={number}` | for numeric fields, field value must be less than the given number | 27 | | `{fieldName}__not={value}` | field does not match the given value | 28 | | `{fieldName}__in={value1, value2}` | field matches _one of_ the values in the comma-separated list | 29 | | `{fieldName}__exists={true|false}` | field exists or doesn't exist in the record | 30 | | `q="fieldName:[1 TO 2] AND fieldName2:[3 TO 4]"` | arbitrary Apache [Lucene query syntax], _not needed for most uses of the API_; if the `q` parameter is used, all other query parameters will be ignored, besides `limit`, `page`, and `fields` | 31 | 32 | [Lucene query syntax]: 33 | https://www.elastic.co/guide/en/kibana/current/lucene-query.html 34 | -------------------------------------------------------------------------------- /content/auth.md: -------------------------------------------------------------------------------- 1 | ## Token 2 | 3 | Returns a bearer token using oAuth with [Earthdata Login](https://urs.earthdata.nasa.gov) service. The token will be returned as a [JWT (JSON Web Token)](https://jwt.io/introduction/). 4 | 5 | ```endpoint 6 | GET /token 7 | ``` 8 | 9 | ### Query Parameters 10 | 11 | | query string parameter | description | 12 | | ----- | ----------- | 13 | | `state={string}` | The URI to redirect to after if oAuth was successful | 14 | 15 | 16 | #### Example request 17 | 18 | ```curl 19 | $ curl https://example.com/token 20 | ``` 21 | 22 | #### Example response 23 | 24 | ```json 25 | {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NUb2tlbiI6IjIyMzc0YWE4MDM1M2E3ODFkYWJjYmFhZGJhOGE3ZmMwZmE1MWYzYjQzNWYxNTc4MjU2NjA0ZjFiNGQ0NTE2ODYiLCJleHAiOiIxNTQ0NDY1MDk3ODczIn0.SxFtZ7dqp9KsUSn1uTXhWis8Il8Hig8mwLANGU3cXhY"} 26 | ``` 27 | 28 | ## Refresh token 29 | 30 | Refreshes a bearer token received from oAuth with [Earthdata Login](https://urs.earthdata.nasa.gov) service. The token will be returned as a [JWT (JSON Web Token)](https://jwt.io/introduction/). 31 | 32 | ```endpoint 33 | POST /refresh 34 | ``` 35 | 36 | ### Request body 37 | 38 | | parameter | type | required | description | 39 | | ----- | --- | -- | ----------- | 40 | | `token` | string | `true` | The JWT received from the `/token` endpoint to refresh | 41 | 42 | 43 | #### Example request 44 | 45 | ```curl 46 | $ curl --request POST https://example.com/refresh --header 'Content-Type: application/json' --data '{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NUb2tlbiI6IjIyMzc0YWE4MDM1M2E3ODFkYWJjYmFhZGJhOGE3ZmMwZmE1MWYzYjQzNWYxNTc4MjU2NjA0ZjFiNGQ0NTE2ODYiLCJleHAiOiIxNTQ0NDY1MDk3ODczIn0.SxFtZ7dqp9KsUSn1uTXhWis8Il8Hig8mwLANGU3cXhY"}' 47 | ``` 48 | 49 | #### Example response 50 | 51 | ```json 52 | {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NUb2tlbiI6IjIyMzc0YWE4MDM1M2E3ODFkYWJjYmFhZGJhOGE3ZmMwZmE1MWYzYjQzNWYxNTc4MjU2NjA0ZjFiNGQ0NTE2ODYiLCJleHAiOiIxNTQ0NDcxMjk4ODEzIn0.vO6RlSRo47kkH15_muoUYNvv74fRzFxs7FlmVaarHlc"} 53 | ``` 54 | 55 | ## Delete token 56 | 57 | Delete the record for an access token received from oAuth with [Earthdata Login](https://urs.earthdata.nasa.gov) service. 58 | 59 | ```endpoint 60 | DELETE /tokenDelete/{token} 61 | ``` 62 | 63 | `token` is the JWT containing access token information to delete 64 | 65 | #### Example request 66 | 67 | ```curl 68 | $ curl --request DELETE https://example.com/tokenDelete/eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJhY2Nlc3NUb2tlbiI6IjIyMzc0YWE4MDM1M2E3ODFkYWJjYmFhZGJhOGE3ZmMwZmE1MWYzYjQzNWYxNTc4MjU2NjA0ZjFiNGQ0NTE2ODYiLCJleHAiOiIxNTQ0NDY1MDk3ODczIn0.SxFtZ7dqp9KsUSn1uTXhWis8Il8Hig8mwLANGU3cXhY 69 | ``` 70 | 71 | #### Example response 72 | 73 | ```json 74 | {"message": "Token record was deleted"} 75 | ``` 76 | 77 | ## Authorization header 78 | 79 | When a request is made to the Cumulus API, it must contain a bearer token generated by the API. 80 | 81 | The token is generated after the user login with [Earthdata Login](https://urs.earthdata.nasa.gov) service. 82 | 83 | The token is included in requests using the `Authorization` header. 84 | 85 | If no token is provided, the Cumulus API server will respond with an error, requesting credentials. If an incorrect token is provided, the server will respond with a separate error noting this. 86 | 87 | #### Authentication example 88 | 89 | ```curl 90 | #! /bin/sh 91 | 92 | ORIGIN=$(dirname $CUMULUS_BASEURL) 93 | LOGIN_URL="$CUMULUS_BASEURL/token" 94 | 95 | # create a base64 hash of your login credentials 96 | AUTH=$(printf "$EARTHDATA_USERNAME:$EARTHDATA_PASSWORD" | base64) 97 | 98 | # Request the Earthdata url with client id and redirect uri to use with Cumulus 99 | AUTHORIZE_URL=$(curl -s -i ${LOGIN_URL} | grep location | sed -e "s/^location: //"); 100 | 101 | # Request an authorization grant code 102 | TOKEN_URL=$(curl -s -i -X POST \ 103 | -F "credentials=${AUTH}" \ 104 | -H "Origin: ${ORIGIN}" \ 105 | ${AUTHORIZE_URL%$'\r'} | grep Location | sed -e "s/^Location: //") 106 | 107 | # Request the token through the CUMULUS API url that's returned from Earthdata 108 | # Response is a JSON object of the form { token: String } 109 | # This uses the cli tool jq to parse the JSON and get the token string 110 | # More info on jq: https://stedolan.github.io/jq/ 111 | TOKEN=$(curl -s ${TOKEN_URL%$'\r'} | jq -r '.message.token') 112 | 113 | echo $TOKEN 114 | ``` 115 | 116 | ```python 117 | import os 118 | 119 | from cumulus_api import CumulusApi 120 | 121 | CUMULUS_BASEURL = os.environ["CUMULUS_BASEURL"] 122 | EARTHDATA_USERNAME = os.environ["EARTHDATA_USERNAME"] 123 | EARTHDATA_PASSWORD = os.environ["EARTHDATA_PASSWORD"] 124 | 125 | api = CumulusApi(CUMULUS_BASEURL) 126 | 127 | token = api.login(EARTHDATA_USERNAME, EARTHDATA_PASSWORD) 128 | print token 129 | ``` 130 | 131 | ```javascript 132 | var Cumulus = require('../../api-client-js') 133 | 134 | var api = new Cumulus({ 135 | baseUrl: process.env.CUMULUS_BASEURL 136 | }) 137 | 138 | var options = { 139 | username: process.env.EARTHDATA_USERNAME, 140 | password: process.env.EARTHDATA_PASSWORD 141 | } 142 | 143 | api.login(options, function (err, token) { 144 | console.log('token', token) 145 | }) 146 | ``` 147 | -------------------------------------------------------------------------------- /content/workflows.md: -------------------------------------------------------------------------------- 1 | ## List workflows 2 | 3 | List workflows in the Cumulus system. 4 | 5 | ```endpoint 6 | GET /workflows 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl https://example.com/workflows --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example response 16 | 17 | ```json 18 | [ 19 | { 20 | "name": "TestLambdaVersionWorkflow", 21 | "template": "s3://cumulus-test-sandbox-internal/cumulus/workflows/TestLambdaVersionWorkflow.json", 22 | "definition": { 23 | "Comment": "Tests Lambda update after redeploy", 24 | "StartAt": "StartStatus", 25 | "States": { 26 | "StartStatus": { 27 | "Type": "Task", 28 | "Resource": "${SfSnsReportLambdaAliasOutput}", 29 | "Next": "WaitForDeployment" 30 | }, 31 | "WaitForDeployment": { 32 | "Type": "Task", 33 | "Resource": "${WaitForDeploymentLambdaAliasOutput}", 34 | "Next": "VersionUpTest" 35 | }, 36 | "VersionUpTest": { 37 | "Type": "Task", 38 | "Resource": "${VersionUpTestLambdaAliasOutput}", 39 | "Next": "StopStatus" 40 | }, 41 | "StopStatus": { 42 | "Type": "Task", 43 | "Resource": "${SfSnsReportLambdaAliasOutput}", 44 | "Catch": [ 45 | { 46 | "ErrorEquals": [ 47 | "States.ALL" 48 | ], 49 | "Next": "WorkflowFailed" 50 | } 51 | ], 52 | "End": true 53 | }, 54 | "WorkflowFailed": { 55 | "Type": "Fail", 56 | "Cause": "Workflow failed" 57 | } 58 | } 59 | } 60 | }, 61 | { 62 | "name": "HelloWorldWorkflow", 63 | "template": "s3://cumulus-test-sandbox-internal/cumulus/workflows/HelloWorldWorkflow.json", 64 | "definition": { 65 | "Comment": "Returns Hello World", 66 | "StartAt": "StartStatus", 67 | "States": { 68 | "StartStatus": { 69 | "Type": "Task", 70 | "Resource": "${SfSnsReportLambdaAliasOutput}", 71 | "Next": "HelloWorld" 72 | }, 73 | "HelloWorld": { 74 | "Type": "Task", 75 | "Resource": "${HelloWorldLambdaAliasOutput}", 76 | "Next": "StopStatus" 77 | }, 78 | "StopStatus": { 79 | "Type": "Task", 80 | "Resource": "${SfSnsReportLambdaAliasOutput}", 81 | "Catch": [ 82 | { 83 | "ErrorEquals": [ 84 | "States.ALL" 85 | ], 86 | "Next": "WorkflowFailed" 87 | } 88 | ], 89 | "End": true 90 | }, 91 | "WorkflowFailed": { 92 | "Type": "Fail", 93 | "Cause": "Workflow failed" 94 | } 95 | } 96 | } 97 | } 98 | ] 99 | ``` 100 | 101 | ## Retrieve workflow 102 | 103 | Retrieve a single workflow. 104 | 105 | ```endpoint 106 | GET /workflow/{name} 107 | ``` 108 | 109 | #### Example request 110 | 111 | ```curl 112 | $ curl https://example.com/workflows/HelloWorldWorkflow --header 'Authorization: Bearer ReplaceWithTheToken' 113 | ``` 114 | 115 | #### Example response 116 | 117 | ```json 118 | { 119 | "name": "HelloWorldWorkflow", 120 | "template": "s3://cumulus-test-sandbox-internal/cumulus/workflows/HelloWorldWorkflow.json", 121 | "definition": { 122 | "Comment": "Returns Hello World", 123 | "StartAt": "StartStatus", 124 | "States": { 125 | "StartStatus": { 126 | "Type": "Task", 127 | "Resource": "${SfSnsReportLambdaAliasOutput}", 128 | "Next": "HelloWorld" 129 | }, 130 | "HelloWorld": { 131 | "Type": "Task", 132 | "Resource": "${HelloWorldLambdaAliasOutput}", 133 | "Next": "StopStatus" 134 | }, 135 | "StopStatus": { 136 | "Type": "Task", 137 | "Resource": "${SfSnsReportLambdaAliasOutput}", 138 | "Catch": [ 139 | { 140 | "ErrorEquals": [ 141 | "States.ALL" 142 | ], 143 | "Next": "WorkflowFailed" 144 | } 145 | ], 146 | "End": true 147 | }, 148 | "WorkflowFailed": { 149 | "Type": "Fail", 150 | "Cause": "Workflow failed" 151 | } 152 | } 153 | } 154 | } 155 | ``` 156 | -------------------------------------------------------------------------------- /api-client-js/index.js: -------------------------------------------------------------------------------- 1 | var parseUrl = require('url').parse 2 | 3 | const maybe = require('call-me-maybe') 4 | const joinUrl = require('url-join') 5 | const assert = require('nanoassert') 6 | const base64 = require('base-64') 7 | const request = require('got') 8 | 9 | const Collections = require('./endpoints/collections') 10 | const Distribution = require('./endpoints/distribution') 11 | const ExecutionStatus = require('./endpoints/execution-status') 12 | const Executions = require('./endpoints/executions') 13 | const Granules = require('./endpoints/granules') 14 | const Logs = require('./endpoints/logs') 15 | const Pdrs = require('./endpoints/pdrs') 16 | const Providers = require('./endpoints/providers') 17 | const Rules = require('./endpoints/rules') 18 | const Schemas = require('./endpoints/schemas') 19 | const Stats = require('./endpoints/stats') 20 | const Workflows = require('./endpoints/workflows') 21 | 22 | /** 23 | * 24 | * @name CumulusApi 25 | **/ 26 | class CumulusApi { 27 | constructor (baseUrl, options) { 28 | if (typeof baseUrl === 'object') { 29 | options = baseUrl 30 | baseUrl = options.baseUrl 31 | } 32 | 33 | assert(options && typeof options === 'object', 'options object is required') 34 | assert(baseUrl && typeof baseUrl === 'string', 'baseUrl string is required') 35 | 36 | this.baseUrl = baseUrl 37 | this.token = options.token || null 38 | 39 | this.collections = new Collections(this) 40 | this.distribution = new Distribution(this) 41 | this.executionStatus = new ExecutionStatus(this) 42 | this.executions = new Executions(this) 43 | this.granules = new Granules(this) 44 | this.logs = new Logs(this) 45 | this.pdrs = new Pdrs(this) 46 | this.providers = new Providers(this) 47 | this.rules = new Rules(this) 48 | this.schemas = new Schemas(this) 49 | this.stats = new Stats(this) 50 | this.workflows = new Workflows(this) 51 | } 52 | 53 | /** 54 | * 55 | * @name 56 | **/ 57 | login (options, callback) { 58 | assert(options && typeof options === 'object', 'options object is required') 59 | assert(options.username && typeof options.username === 'string', 'options.username string is required') 60 | assert(options.password && typeof options.password === 'string', 'options.password string is required') 61 | 62 | var url = joinUrl(this.baseUrl, '/token') 63 | 64 | return maybe(callback, new Promise((resolve, reject) => { 65 | return request(url, { followRedirect: false }) 66 | .catch(reject) 67 | .then((res) => { 68 | if (res.statusCode && res.headers.location) { 69 | resolve(this._authorize(res.headers.location, options)) 70 | } else { 71 | reject(new Error('Error authenticating with EarthData login. Check that your baseUrl, username, and password are correct, and the app client_id and redirect_uri are correctly set up')) 72 | } 73 | }) 74 | })) 75 | } 76 | 77 | /** 78 | * 79 | * @private 80 | **/ 81 | _authorize (url, options) { 82 | assert(url && typeof url === 'string', 'url string is required') 83 | 84 | var urlObj = parseUrl(url) 85 | var auth = base64.encode(options.username + ':' + options.password) 86 | 87 | var requestOptions = { 88 | method: 'POST', 89 | form: true, 90 | body: { credentials: auth }, 91 | headers: { 92 | origin: urlObj.protocol + '//' + urlObj.host 93 | } 94 | } 95 | 96 | return new Promise((resolve, reject) => { 97 | return request(url, requestOptions) 98 | .catch((err) => { 99 | if (err.statusCode === 302 && err.headers.location) { 100 | return resolve(this._getToken(err.headers.location)) 101 | } 102 | 103 | reject(err) 104 | }) 105 | .then((res) => { 106 | reject(new Error('Error authenticating with EarthData login. Check that your baseUrl, username, and password are correct, and the app client_id and redirect_uri are correctly set up')) 107 | }) 108 | }) 109 | } 110 | 111 | /** 112 | * 113 | * @private 114 | **/ 115 | _getToken (url) { 116 | return new Promise((resolve, reject) => { 117 | request(url) 118 | .catch(reject) 119 | .then((res) => { 120 | var body = JSON.parse(res.body) 121 | this.token = body.message.token 122 | resolve(body.message.token) 123 | }) 124 | }) 125 | } 126 | 127 | _req (method, url, options, callback) { 128 | if (typeof options === 'function') { 129 | callback = options 130 | options = {} 131 | } 132 | 133 | if (!options) options = {} 134 | options.headers = { authorization: `Bearer ${this.token}` } 135 | options.method = method 136 | 137 | const requestPromise = new Promise((resolve, reject) => { 138 | return request(joinUrl(this.baseUrl, url), options) 139 | .catch(reject) 140 | .then((res) => { 141 | console.log('res.statusCode', res.statusCode) 142 | console.log(res) 143 | resolve(JSON.parse(res.body)) 144 | }) 145 | }) 146 | 147 | return maybe(callback, requestPromise) 148 | } 149 | } 150 | 151 | module.exports = CumulusApi 152 | -------------------------------------------------------------------------------- /content/providers.md: -------------------------------------------------------------------------------- 1 | ## List providers 2 | 3 | List providers in the Cumulus system. 4 | 5 | ```endpoint 6 | GET /providers 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl https://example.com/providers --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example response 16 | 17 | ```json 18 | { 19 | "meta": { 20 | "name": "cumulus-api", 21 | "stack": "daac-cumulus", 22 | "table": "providers", 23 | "limit": 1, 24 | "page": 1, 25 | "count": 2 26 | }, 27 | "results": [ 28 | { 29 | "id": "HTTP_MODIS", 30 | "globalConnectionLimit": 10, 31 | "maxDownloadTime": 300, 32 | "protocol": "http", 33 | "host": "https://data.modis.gov/", 34 | "timestamp": 1508861082226 35 | } 36 | ] 37 | } 38 | ``` 39 | 40 | ## Retrieve provider 41 | 42 | Retrieve a single provider. 43 | 44 | ```endpoint 45 | GET /providers/{id} 46 | ``` 47 | 48 | #### Example request 49 | 50 | ```curl 51 | $ curl https://example.com/providers/HTTP_MODIS --header 'Authorization: Bearer ReplaceWithTheToken' 52 | ``` 53 | 54 | #### Example response 55 | 56 | ```json 57 | { 58 | "createdAt": 1508861081785, 59 | "id": "HTTP_MODIS", 60 | "host": "https://data.modis.gov/", 61 | "globalConnectionLimit": 10, 62 | "maxDownloadTime": 300, 63 | "updatedAt": 1508861081785, 64 | "protocol": "http" 65 | } 66 | ``` 67 | 68 | ## Create provider 69 | 70 | Create a provider. For more information on creating providers and the contents of a request see [the Cumulus setup documentation](https://nasa.github.io/cumulus/docs/data-cookbooks/setup#providers). 71 | 72 | Overview of the schema fields: 73 | 74 | | Field | Value | Description | 75 | | --- | --- | --- | 76 | | `id` | `string` | provider id/name | 77 | | `protocol` | `"s3"`|`"http"`|`"https"`|`"ftp"` | file transfer (sync) protocol | 78 | | `host` | `string` | provider host endpoint | 79 | | `port` | `number` | provider host port | 80 | | `globalConnectionLimit` | `number` | limit to number of concurrent connections. This is the maximum number of connections Cumulus compatible ingest lambdas are expected to make to a provider. Defaults to unlimited | 81 | | `maxDownloadTime` | `number` | Maximum download time in seconds for all granule files on a sync granule task. The timeout is used together with globalConnectionLimit to limit concurrent downloads. | 82 | | `username` | `string` | provider connection username | 83 | | `password` | `string` | provider connection password | 84 | | `privateKey` | `string` | filename assumed to be in s3://bucketInternal/stackName/crypto | 85 | | `cmKeyId` | `string` | AWS KMS Customer Master Key arn or alias | 86 | | `allowedRedirects` | `Array` | Only hosts in this list will have the provider username/password forwarded for authentication. Entries should be specified as host.com or host.com:7000 if redirect port is different than the provider port. | 87 | | `certificateUri` | `string` | Optional SSL Certificate S3 URI for custom or self-signed SSL (TLS) certificate | 88 | 89 | ```endpoint 90 | POST /providers 91 | ``` 92 | 93 | #### Example request 94 | 95 | ```curl 96 | $ curl --request POST https://example.com/providers --header 'Authorization: Bearer ReplaceWithTheToken' --header 'Content-Type: application/json' --data '{ 97 | "host": "https://www.example.gov", 98 | "id": "MY_DAAC_SATELLITE", 99 | "protocol": "http", 100 | "globalConnectionLimit": 10, 101 | "maxDownloadTime": 300 102 | }' 103 | ``` 104 | 105 | #### Example response 106 | 107 | ```json 108 | { 109 | "message": "Record saved", 110 | "record": { 111 | "createdAt": 1491941727851, 112 | "host": "https://www.example.gov", 113 | "id": "MY_DAAC_SATELLITE", 114 | "protocol": "http", 115 | "globalConnectionLimit": 10, 116 | "maxDownloadTime": 300, 117 | "timestamp": 1513956151186 118 | } 119 | } 120 | ``` 121 | 122 | ## Update/replace provider 123 | 124 | Update/replace an existing provider. Expects payload to specify the entire 125 | provider object, and will completely replace the existing provider with the 126 | specified payload. For a field reference see 127 | ["Create provider"](#create-provider). 128 | 129 | Returns status 200 on successful replacement, 400 if the `id` property in the 130 | payload does not match the corresponding value in the resource URI, or 404 if 131 | there is no provider with the specified ID. 132 | 133 | ```endpoint 134 | PUT /providers/{id} 135 | ``` 136 | 137 | #### Example request 138 | 139 | ```curl 140 | $ curl --request PUT https://example.com/providers/MY_DAAC_SATELLITE --header 'Authorization: Bearer ReplaceWithTheToken' --header 'Content-Type: application/json' --data '{ 141 | "id": "MY_DAAC_SATELLITE", 142 | "host": "https://www.example.co.uk", 143 | "globalConnectionLimit": 10, 144 | "maxDownloadTime": 300, 145 | "protocol": "http" 146 | }' 147 | ``` 148 | 149 | #### Example successful response 150 | 151 | ```json 152 | { 153 | "createdAt": 1491941727851, 154 | "id": "MY_DAAC_SATELLITE", 155 | "host": "https://www.example.co.uk", 156 | "globalConnectionLimit": 10, 157 | "maxDownloadTime": 300, 158 | "updatedAt": 1513956150733, 159 | "protocol": "http", 160 | "timestamp": 1513956555713 161 | } 162 | ``` 163 | 164 | ## Delete provider 165 | 166 | Delete a provider from Cumulus. The related PDRs and granules remain in the Cumulus and CMR systems. 167 | 168 | ```endpoint 169 | DELETE /providers/{id} 170 | ``` 171 | 172 | #### Example request 173 | 174 | ```curl 175 | $ curl --request DELETE https://example.com/providers/MY_DAAC_SATELLITE --header 'Authorization: Bearer ReplaceWithTheToken' 176 | 177 | ``` 178 | 179 | #### Example response 180 | 181 | ```json 182 | { 183 | "message": "Record deleted" 184 | } 185 | ``` 186 | -------------------------------------------------------------------------------- /template/src/components/app.js: -------------------------------------------------------------------------------- 1 | import React from 'react'; 2 | import Navigation from './navigation'; 3 | import PropTypes from 'prop-types'; 4 | import Content from './content'; 5 | import RoundedToggle from './rounded_toggle'; 6 | import GithubSlugger from 'github-slugger'; 7 | import debounce from 'lodash.debounce'; 8 | import { brandNames, brandClasses } from '../custom'; 9 | import qs from 'querystring'; 10 | 11 | let slugger = new GithubSlugger(); 12 | let slug = title => { slugger.reset(); return slugger.slug(title); }; 13 | 14 | let languageOptions = [ 15 | { title: 'cURL', 16 | short: 'cURL', 17 | value: 'curl' }, 18 | { title: 'Python', 19 | short: 'Python', 20 | value: 'python' }, 21 | { title: 'JavaScript', 22 | short: 'JS', 23 | value: 'javascript' } 24 | ]; 25 | 26 | let defaultLanguage = languageOptions[0]; 27 | 28 | let debouncedReplaceState = debounce(hash => { 29 | window.history.replaceState('', '', hash); 30 | }, 100); 31 | 32 | export default class App extends React.PureComponent { 33 | static propTypes = { 34 | content: PropTypes.string.isRequired, 35 | ast: PropTypes.object.isRequired 36 | } 37 | constructor(props) { 38 | super(props); 39 | var active = 'Introduction'; 40 | 41 | if (process.browser) { 42 | let hash = window.location.hash.split('#').pop(); 43 | let languageFromURL = qs.parse(window.location.search.substring(1)).language; 44 | let language = languageOptions.find(option => option.title === languageFromURL) || 45 | defaultLanguage; 46 | let mqls = [ 47 | { name: 'widescreen', query: window.matchMedia('(min-width: 1200px)') }, 48 | { name: 'desktop', query: window.matchMedia('(min-width: 961px)') }, 49 | { name: 'tablet', query: window.matchMedia('(max-width: 960px)') }, 50 | { name: 'mobile', query: window.matchMedia('(max-width: 640px)') } 51 | ]; 52 | mqls.forEach(q => q.query.addListener(this.mediaQueryChanged)); 53 | if (hash) { 54 | let headingForHash = this.props.ast.children 55 | .filter(child => child.type === 'heading') 56 | .find(heading => heading.data.id === hash); 57 | if (headingForHash) { 58 | active = headingForHash.children[0].value; 59 | } 60 | } 61 | this.state = { 62 | // media queryMatches 63 | mqls: mqls, 64 | // object of currently matched queries, like { desktop: true } 65 | queryMatches: {}, 66 | language: language, 67 | columnMode: 2, 68 | activeSection: active, 69 | // for the toggle-able navigation on mobile 70 | showNav: false 71 | }; 72 | } else { 73 | this.state = { 74 | mqls: { }, 75 | queryMatches: { 76 | desktop: true 77 | }, 78 | language: defaultLanguage, 79 | activeSection: '', 80 | showNav: false 81 | }; 82 | } 83 | } 84 | toggleNav() { 85 | this.setState({ showNav: !this.state.showNav }); 86 | } 87 | componentDidMount() { 88 | this.mediaQueryChanged(); 89 | this.onScroll = debounce(this.onScrollImmediate, 100); 90 | document.addEventListener('scroll', this.onScroll); 91 | this.onScrollImmediate(); 92 | } 93 | onScrollImmediate = () => { 94 | var sections = document.querySelectorAll('div.section'); 95 | if (!sections.length) return; 96 | for (var i = 0; i < sections.length; i++) { 97 | var rect = sections[i].getBoundingClientRect(); 98 | if (rect.bottom > 0) { 99 | this.setState({ 100 | activeSection: sections[i].getAttribute('data-title') 101 | }); 102 | return; 103 | } 104 | } 105 | } 106 | mediaQueryChanged() { 107 | this.setState({ 108 | queryMatches: this.state.mqls.reduce((memo, q) => { 109 | memo[q.name] = q.query.matches; 110 | return memo; 111 | }, {}) 112 | }); 113 | } 114 | componentWillUnmount() { 115 | this.state.mqls.forEach(q => q.removeListener(this.mediaQueryChanged)); 116 | document.body.removeEventListener('scroll', this.onScroll); 117 | } 118 | onChangeLanguage = (language) => { 119 | this.setState({ language }, () => { 120 | if (window.history) { 121 | window.history.pushState(null, null, 122 | `?${qs.stringify({ language: language.title })}${window.location.hash}`); 123 | } 124 | }); 125 | } 126 | componentDidUpdate(_, prevState) { 127 | if (prevState.activeSection !== this.state.activeSection) { 128 | // when the section changes, replace the hash 129 | debouncedReplaceState(`#${slug(this.state.activeSection)}`); 130 | } else if (prevState.language.title !== this.state.language.title || 131 | prevState.columnMode !== this.state.columnMode) { 132 | // when the language changes, use the hash to set scroll 133 | window.location.hash = window.location.hash; 134 | } 135 | } 136 | navigationItemClicked = activeSection => { 137 | setTimeout(() => { 138 | this.setState({ activeSection }); 139 | }, 10); 140 | if (!this.state.queryMatches.desktop) { 141 | this.toggleNav(); 142 | } 143 | } 144 | toggleColumnMode() { 145 | this.setState({ 146 | columnMode: this.state.columnMode === 1 ? 2 : 1 147 | }); 148 | } 149 | render() { 150 | let ast = JSON.parse(JSON.stringify(this.props.ast)); 151 | let { activeSection, queryMatches, showNav, columnMode } = this.state; 152 | let col1 = columnMode === 1 && queryMatches.desktop; 153 | return (
154 | 155 | {/* Content background */ } 156 | {(!col1 && !queryMatches.mobile) &&
157 |
158 |
} 159 | 160 | {/* Desktop nav */ } 161 | {queryMatches.desktop &&
162 | 166 |
} 167 | 168 | {/* Content */ } 169 |
170 |
171 | 176 |
177 |
178 | 179 | {/* Language toggle */ } 180 |
181 |
182 |
183 | Show examples in: 184 |
185 | 190 |
191 | {queryMatches.desktop ? 192 | : null} 197 |
198 |
199 |
200 | 201 | {/* Header */ } 202 | 225 | 226 |
); 227 | } 228 | } 229 | 230 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright © 2017 United States Government as represented by the Administrator of the National Aeronautics and Space Administration. All Rights Reserved. 2 | 3 | Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 4 | You may obtain a copy of the License at 5 | 6 | http://www.apache.org/licenses/LICENSE-2.0 7 | 8 | Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, 9 | 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. 10 | 11 | --- 12 | 13 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 14 | 15 | 1. Definitions. 16 | 17 | "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. 18 | 19 | "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. 20 | 21 | "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. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. 24 | 25 | "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. 26 | 27 | "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. 28 | 29 | "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). 30 | 31 | "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. 32 | 33 | "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." 34 | 35 | "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. 36 | 37 | 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. 38 | 39 | 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. 40 | 41 | 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: 42 | 43 | You must give any other recipients of the Work or Derivative Works a copy of this License; and 44 | You must cause any modified files to carry prominent notices stating that You changed the files; and 45 | 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 46 | 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. 47 | 48 | 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. 49 | 50 | 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. 51 | 52 | 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. 53 | 54 | 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. 55 | 56 | 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. 57 | 58 | 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. 59 | 60 | END OF TERMS AND CONDITIONS 61 | -------------------------------------------------------------------------------- /content/rules.md: -------------------------------------------------------------------------------- 1 | ## List rules 2 | 3 | List rules in the Cumulus system. 4 | 5 | ```endpoint 6 | GET /rules 7 | ``` 8 | 9 | #### Example request 10 | 11 | ```curl 12 | $ curl https://example.com/rules --header 'Authorization: Bearer ReplaceWithTheToken' 13 | ``` 14 | 15 | #### Example response 16 | 17 | ```json 18 | { 19 | "meta": { 20 | "name": "cumulus-api", 21 | "stack": "lpdaac-cumulus", 22 | "table": "rules", 23 | "limit": 1, 24 | "page": 1, 25 | "count": 7 26 | }, 27 | "results": [ 28 | { 29 | "name": "repeat", 30 | "workflow": "DiscoverPdrs", 31 | "provider": "local", 32 | "collection": { 33 | "name": "AST_L1A", 34 | "version": "003" 35 | }, 36 | "rule": { 37 | "type": "scheduled", 38 | "value": "rate(5 minutes)" 39 | }, 40 | "timestamp": 1511232462534, 41 | "state": "DISABLED" 42 | } 43 | ] 44 | } 45 | ``` 46 | 47 | ## Retrieve rule 48 | 49 | Retrieve a single rule. 50 | 51 | ```endpoint 52 | GET /rules/{name} 53 | ``` 54 | 55 | #### Example request 56 | 57 | ```curl 58 | $ curl https://example.com/rules/repeat --header 'Authorization: Bearer ReplaceWithTheToken' 59 | ``` 60 | 61 | #### Example response 62 | 63 | ```json 64 | { 65 | "workflow": "DiscoverPdrs", 66 | "collection": { 67 | "name": "AST_L1A", 68 | "version": "003" 69 | }, 70 | "updatedAt": 1511232462507, 71 | "createdAt": 1510903518741, 72 | "provider": "local", 73 | "name": "repeat", 74 | "rule": { 75 | "type": "scheduled", 76 | "value": "rate(5 minutes)" 77 | }, 78 | "state": "DISABLED" 79 | } 80 | ``` 81 | 82 | ## Create rule 83 | 84 | Create a rule. For more information on creating rules and the contents of a request see [the Cumulus setup documentation](https://nasa.github.io/cumulus/docs/data-cookbooks/setup#rules). 85 | 86 | Overview of the schema fields: 87 | 88 | | Field | Value | Required | Description | 89 | | --- | --- | --- | --- | 90 | | `name` | `string` | `yes` | rule name (letters, numbers, underscores only) | 91 | | `state` | `"DISABLED"`|`"ENABLED"` | `yes` | rule state (default: ENABLED) | 92 | | `workflow` | `string` | `yes` | name of workflow started by the rule | 93 | | `rule` | `Object` | `yes` | rule object | 94 | | `-- rule.type` | `"onetime"`|`"scheduled"`|`"kinesis"`|
`"sns"`|`"sqs"` | `yes` | rule trigger type | 95 | | `-- rule.value` | `onetime`: N/A
`scheduled`: cron-type or rate expression
`kinesis`: Kinesis stream ARN
`sns`: SNS topic ARN
`sqs`: SQS queue URL | `no` | required value differs by type | 96 | | `-- rule.arn` | `string` | `no` | `kinesis` scheduled event arn | 97 | | `-- rule.logEventArn` | `string` | `no` | `kinesis` scheduled log event arn | 98 | | `collection` | `Object` | `no` | collection record provided to workflow | 99 | | `-- collection.name` | `string` | `yes` | collection name | 100 | | `-- collection.version` | `string` | `yes` | collection version | 101 | | `executionNamePrefix` | `string` | `no` | Execution Name Prefix | 102 | | `meta` | `Object` | `no` | contents to add to workflow input's `meta` field | 103 | | `payload` | `string` | `no` | input payload to be used in onetime and scheduled rules| 104 | | `provider` | `string` | `no` | provider record provided to workflow | 105 | | `queueUrl` | `string` | `no` | queue URL for Scheduled Executions | 106 | | `tags` | `array` | `no` | tags (for search) | 107 | 108 | ```endpoint 109 | POST /rules 110 | ``` 111 | 112 | #### Example request 113 | 114 | ```curl 115 | $ curl --request POST https://example.com/rules --header 'Authorization: Bearer ReplaceWithToken' --header 'Content-Type: application/json' --data '{ 116 | "workflow": "DiscoverPdrs", 117 | "collection": { 118 | "name": "AST_L1A", 119 | "version": "003" 120 | }, 121 | "provider": "local", 122 | "name": "repeat_test", 123 | "rule": { 124 | "type": "scheduled", 125 | "value": "rate(5 minutes)" 126 | }, 127 | "meta": { "publish": false }, 128 | "state": "DISABLED" 129 | }' 130 | ``` 131 | 132 | #### Example response 133 | 134 | ```json 135 | { 136 | "message": "Record saved", 137 | "record": { 138 | "workflow": "DiscoverPdrs", 139 | "collection": { 140 | "name": "AST_L1A", 141 | "version": "003" 142 | }, 143 | "createdAt": 1510903518741, 144 | "provider": "local", 145 | "name": "repeat_test", 146 | "rule": { 147 | "type": "scheduled", 148 | "value": "rate(5 minutes)" 149 | }, 150 | "meta": { "publish": false }, 151 | "state": "DISABLED" 152 | } 153 | } 154 | ``` 155 | 156 | ## Replace rule 157 | 158 | Replace an existing rule. Expects payload to specify the entire 159 | rule object, and will completely replace the existing rule with the 160 | specified payload. For a field reference see ["Create rule"](#create-rule). 161 | 162 | Returns status 200 on successful replacement, 400 if the `name` property in the 163 | payload does not match the corresponding value in the resource URI, or 404 if 164 | there is no rule with the specified name. 165 | 166 | Special case: 167 | 168 | | Field | Value | Description | 169 | | --- | --- | --- | 170 | | `action` | `"rerun"` | rerun rule (`onetime` rule only), and rule record is not replaced | 171 | 172 | ```endpoint 173 | PUT /rules/{name} 174 | ``` 175 | 176 | #### Example request 177 | 178 | ```curl 179 | $ curl --request PUT https://example.com/rules/repeat_test \ 180 | --header 'Authorization: Bearer ReplaceWithToken' \ 181 | --header 'Content-Type: application/json' \ 182 | --header 'Cumulus-API-Version: 2' \ 183 | --data '{ 184 | "name": "repeat_test", 185 | "workflow": "DiscoverPdrs", 186 | "collection": { 187 | "name": "AST_L1A", 188 | "version": "003" 189 | }, 190 | "provider": "local", 191 | "rule": { 192 | "type": "scheduled", 193 | "value": "rate(5 minutes)" 194 | }, 195 | "state": "ENABLED" 196 | }' 197 | ``` 198 | 199 | #### Example successful response 200 | 201 | ```json 202 | { 203 | "name": "repeat_test", 204 | "workflow": "DiscoverPdrs", 205 | "collection": { 206 | "name": "AST_L1A", 207 | "version": "003" 208 | }, 209 | "updatedAt": 1521755265130, 210 | "createdAt": 1510903518741, 211 | "provider": "local", 212 | "rule": { 213 | "type": "scheduled", 214 | "value": "rate(5 minutes)" 215 | }, 216 | "state": "ENABLED" 217 | } 218 | ``` 219 | 220 | #### Rerun request (`onetime`-rule special case) 221 | 222 | ```curl 223 | $ curl --request PUT https://example.com/rules/my_onetime_rule \ 224 | --header 'Authorization: Bearer ReplaceWithToken' \ 225 | --header 'Content-Type: application/json' \ 226 | --header 'Cumulus-API-Version: 2' \ 227 | --data '{ 228 | "name": "repeat_test", 229 | "workflow": "DiscoverPdrs", 230 | "collection": { 231 | "name": "AST_L1A", 232 | "version": "003" 233 | }, 234 | "provider": "local", 235 | "rule": { 236 | "type": "scheduled", 237 | "value": "rate(5 minutes)" 238 | }, 239 | "state": "ENABLED", 240 | "action": "rerun" 241 | }' 242 | ``` 243 | 244 | ## Update rule 245 | 246 | Update an existing rule. Expects payload to contain the modified and/or additional 247 | fields of the rule and the existing rule values will be overwritten by the 248 | modified portions. Unspecified keys will be retained. Keys set to `null` 249 | will be removed. For a field reference see ["Create rule"](#create-rule). 250 | 251 | Returns status 200 on successful update, 400 if the `name` property in the 252 | payload does not match the corresponding value in the resource URI, or 404 if 253 | there is no rule with the specified name. 254 | 255 | Special case: 256 | 257 | | Field | Value | Description | 258 | | --- | --- | --- | 259 | | `action` | `"rerun"` | rerun rule (`onetime` rule only), and rule record is not updated | 260 | 261 | ```endpoint 262 | PATCH /rules/{name} 263 | ``` 264 | 265 | #### Example request 266 | 267 | ```curl 268 | $ curl --request PATCH https://example.com/rules/repeat_test \ 269 | --header 'Authorization: Bearer ReplaceWithToken' \ 270 | --header 'Content-Type: application/json' \ 271 | --header 'Cumulus-API-Version: 2' \ 272 | --data '{ 273 | "name": "repeat_test", 274 | "workflow": "NewDiscoverPdrs", 275 | "meta": { 276 | "additionalKey": "additionalKeyValue" 277 | }, 278 | "state": "ENABLED" 279 | }' 280 | ``` 281 | 282 | #### Example successful response 283 | 284 | ```json 285 | { 286 | "name": "repeat_test", 287 | "workflow": "NewDiscoverPdrs", 288 | "collection": { 289 | "name": "AST_L1A", 290 | "version": "003" 291 | }, 292 | "updatedAt": 1521755265130, 293 | "createdAt": 1510903518741, 294 | "provider": "local", 295 | "rule": { 296 | "type": "scheduled", 297 | "value": "rate(5 minutes)" 298 | }, 299 | "meta": { 300 | "publish": false, 301 | "additionalKey": "additionalKeyValue" 302 | }, 303 | "state": "ENABLED" 304 | } 305 | ``` 306 | 307 | #### Rerun request (`onetime`-rule special case) 308 | 309 | ```curl 310 | $ curl --request PATCH https://example.com/rules/my_onetime_rule \ 311 | --header 'Authorization: Bearer ReplaceWithToken' \ 312 | --header 'Content-Type: application/json' \ 313 | --header 'Cumulus-API-Version: 2' \ 314 | --data '{"action": "rerun"}' 315 | ``` 316 | 317 | ## Delete rule 318 | 319 | Delete a rule from Cumulus. 320 | 321 | ```endpoint 322 | DELETE /rules/{name} 323 | ``` 324 | 325 | #### Example request 326 | 327 | ```curl 328 | $ curl --request DELETE https://example.com/rules/repeat_test --header 'Authorization: Bearer ReplaceWithTheToken' 329 | 330 | ``` 331 | 332 | #### Example response 333 | 334 | ```json 335 | { 336 | "message": "Record deleted" 337 | } 338 | ``` 339 | -------------------------------------------------------------------------------- /content/logs.md: -------------------------------------------------------------------------------- 1 | ## List logs 2 | 3 | **Note:** This endpoint will only work if logs are being delivered to the Metrics system. Otherwise it will 4 | return a 400 Error. 5 | 6 | List processing logs from the Cumulus engine. A log's `level` field should be specified by their string value and be one of: 7 | * fatal (60) 8 | * error (50) 9 | * warn (40) 10 | * info (30) 11 | * debug (20) 12 | * trace (10) 13 | 14 | ```endpoint 15 | GET /logs 16 | ``` 17 | 18 | #### Example request 19 | 20 | ```curl 21 | $ curl https://example.com/logs?limit=5 --header 'Authorization: Bearer ReplaceWithTheToken' 22 | ``` 23 | 24 | #### Example response 25 | 26 | ```json 27 | { 28 | "meta": { 29 | "name": "cumulus-api", 30 | "stack": "lpdaac-cumulus", 31 | "table": "logs", 32 | "limit": 5, 33 | "page": 1, 34 | "count": 750 35 | }, 36 | "results": [ 37 | { 38 | "pid": 1, 39 | "hostname": "ip-10-29-4-186", 40 | "name": "cumulus", 41 | "level": 50, 42 | "msg": "https://ba008ffc.ngrok.io/ not found", 43 | "file": "discover-pdrs/index.js", 44 | "type": "Error", 45 | "stack": "HostNotFound: https://ba008ffc.ngrok.io/ not found\n at discover.discover.then.catch.e (/var/task/index.js:9006:22)\n at process._tickDomainCallback (internal/process/next_tick.js:135:7)", 46 | "message": "https://ba008ffc.ngrok.io/ not found", 47 | "v": 1, 48 | "timestamp": 1513881407867 49 | }, 50 | { 51 | "pid": 1, 52 | "hostname": "ip-10-29-4-186", 53 | "name": "cumulus", 54 | "level": 50, 55 | "file": "discover-pdrs/index.js", 56 | "message": "Received a 404 error from undefined. Check your endpoint!", 57 | "details": { 58 | "host": "ba008ffc.ngrok.io", 59 | "path": "/", 60 | "port": "", 61 | "protocol": "https", 62 | "uriPath": "/", 63 | "url": "https://ba008ffc.ngrok.io/", 64 | "depth": 1, 65 | "fetched": true, 66 | "status": "notfound", 67 | "stateData": { 68 | "requestLatency": 66, 69 | "requestTime": 66, 70 | "contentLength": 34, 71 | "contentType": "text/plain", 72 | "code": 404, 73 | "headers": { 74 | "content-length": "34", 75 | "connection": "close", 76 | "content-type": "text/plain" 77 | } 78 | }, 79 | "id": 0 80 | }, 81 | "v": 1, 82 | "timestamp": 1513881407867 83 | }, 84 | { 85 | "pid": 1, 86 | "hostname": "ip-10-29-4-186", 87 | "name": "cumulus", 88 | "level": 50, 89 | "msg": "Cannot read property 'provider_path' of undefined", 90 | "file": "discover-pdrs/index.js", 91 | "type": "Error", 92 | "stack": "TypeError: Cannot read property 'provider_path' of undefined\n at HttpDiscover.Discover (/var/task/index.js:10098:33)\n at HttpDiscover._class (/var/task/index.js:96368:255)\n at new HttpDiscover (/var/task/index.js:10342:241)\n at handler (/var/task/index.js:8968:23)\n at Promise (/var/task/cumulus-sled/index.js:82:5)\n at invokeHandler (/var/task/cumulus-sled/index.js:72:10)\n at then.then.then (/var/task/cumulus-sled/index.js:112:14)\n at process._tickDomainCallback (internal/process/next_tick.js:135:7)", 93 | "v": 1, 94 | "timestamp": 1513881031694 95 | }, 96 | { 97 | "pid": 1, 98 | "hostname": "ip-10-29-4-186", 99 | "name": "cumulus", 100 | "level": 50, 101 | "msg": "Provider info not provided", 102 | "file": "discover-pdrs/index.js", 103 | "type": "Error", 104 | "stack": "ProviderNotFound: Provider info not provided\n at handler (/var/task/index.js:8962:20)\n at Promise (/var/task/cumulus-sled/index.js:82:5)\n at invokeHandler (/var/task/cumulus-sled/index.js:72:10)\n at then.then.then (/var/task/cumulus-sled/index.js:112:14)\n at process._tickDomainCallback (internal/process/next_tick.js:135:7)", 105 | "message": "Provider info not provided", 106 | "v": 1, 107 | "timestamp": 1513879654040 108 | }, 109 | { 110 | "pid": 1, 111 | "hostname": "ip-10-29-4-186", 112 | "name": "cumulus", 113 | "level": 50, 114 | "msg": "Provider info not provided", 115 | "file": "discover-pdrs/index.js", 116 | "type": "Error", 117 | "stack": "ProviderNotFound: Provider info not provided\n at handler (/var/task/index.js:8962:20)\n at Promise (/var/task/cumulus-sled/index.js:82:5)\n at invokeHandler (/var/task/cumulus-sled/index.js:72:10)\n at then.then.then (/var/task/cumulus-sled/index.js:112:14)\n at process._tickDomainCallback (internal/process/next_tick.js:135:7)", 118 | "message": "Provider info not provided", 119 | "v": 1, 120 | "timestamp": 1513879435010 121 | } 122 | ] 123 | } 124 | ``` 125 | 126 | #### Example request for errors 127 | 128 | ```curl 129 | $ curl https://example.com/logs?level=error --header 'Authorization: Bearer ReplaceWithTheToken' 130 | ``` 131 | 132 | #### Example response for errors 133 | 134 | ```json 135 | { 136 | "meta": { 137 | "name": "cumulus-api", 138 | "stack": "lpdaac-cumulus", 139 | "table": "logs", 140 | "limit": 1, 141 | "page": 1, 142 | "count": 181 143 | }, 144 | "results": [ 145 | { 146 | "level": 50, 147 | "msg": "Unexpected HTTP status code: 404", 148 | "pid": 1, 149 | "hostname": "ip-10-26-125-174", 150 | "name": "cumulus", 151 | "file": "sync-granule/index.js", 152 | "type": "Error", 153 | "stack": "Error: Unexpected HTTP status code: 404\n at ClientRequest. (/var/task/sync-granule/index.js:125136:29)\n at ClientRequest.g (events.js:292:16)\n at emitOne (events.js:96:13)\n at ClientRequest.emit (events.js:188:7)\n at HTTPParser.parserOnIncomingClient (_http_client.js:473:21)\n at HTTPParser.parserOnHeadersComplete (_http_common.js:99:23)\n at TLSSocket.socketOnData (_http_client.js:362:20)\n at emitOne (events.js:96:13)\n at TLSSocket.emit (events.js:188:7)\n at readableAddChunk (_stream_readable.js:176:18)", 154 | "code": 404, 155 | "v": 1, 156 | "timestamp": 1515446810226 157 | } 158 | ] 159 | } 160 | ``` 161 | 162 | ## Retrieve Logs 163 | 164 | **Note:** This endpoint will only work if logs are being delivered to the Metrics system. Otherwise it will 165 | return a 400 Error. 166 | 167 | Retrieve all logs from a specific execution. 168 | 169 | ```endpoint 170 | GET /logs/{executionName} 171 | ``` 172 | 173 | #### Example request 174 | 175 | ```curl 176 | $ curl https://example.com/logs/93e5e049-89aa-47e5-900d-0eec87327260?limit=5 --header 'Authorization: Bearer ReplaceWithTheToken' 177 | ``` 178 | 179 | #### Example response 180 | 181 | ```json 182 | { 183 | "meta": { 184 | "name": "cumulus-api", 185 | "stack": "test-src-integration", 186 | "table": "logs", 187 | "limit": 5, 188 | "page": 1, 189 | "count": 10 190 | }, 191 | "results": [ 192 | { 193 | "level": 30, 194 | "executions": "93e5e049-89aa-47e5-900d-0eec87327260", 195 | "timestamp": "2018-08-15T19:23:57.752Z", 196 | "sender": "test-src-integration-PostToCmr", 197 | "version": "$LATEST", 198 | "message": "Published MOD09GQ.A8009365.7JQhni.006.6594428626875 to the CMR. conceptId: G1223210348-CUMULUS", 199 | "RequestId": "05712fb1-5593-4640-b5a3-a99db41d8003" 200 | }, 201 | { 202 | "level": 30, 203 | "executions": "93e5e049-89aa-47e5-900d-0eec87327260", 204 | "timestamp": "2018-08-15T19:23:42.054Z", 205 | "sender": "test-src-integration-SyncGranuleNoVpc", 206 | "version": "$LATEST", 207 | "message": "uploaded s3://cumulus-test-sandbox-internal/file-staging/test-src-integration/MOD09GQ___006/MOD09GQ.A8009365.7JQhni.006.6594428626875.hdf", 208 | "RequestId": "a20698f3-a9a1-4e64-acbf-09ef77827fbc" 209 | }, 210 | { 211 | "level": 30, 212 | "executions": "93e5e049-89aa-47e5-900d-0eec87327260", 213 | "timestamp": "2018-08-15T19:23:41.913Z", 214 | "sender": "test-src-integration-SyncGranuleNoVpc", 215 | "version": "$LATEST", 216 | "message": "Finishing downloading s3://cumulus-test-sandbox-internal/cumulus-test-data/pdrs/MOD09GQ.A8009365.7JQhni.006.6594428626875.hdf", 217 | "RequestId": "a20698f3-a9a1-4e64-acbf-09ef77827fbc" 218 | }, 219 | { 220 | "level": 30, 221 | "executions": "93e5e049-89aa-47e5-900d-0eec87327260", 222 | "timestamp": "2018-08-15T19:23:41.888Z", 223 | "sender": "test-src-integration-SyncGranuleNoVpc", 224 | "version": "$LATEST", 225 | "message": "uploaded s3://cumulus-test-sandbox-internal/file-staging/test-src-integration/MOD09GQ___006/MOD09GQ.A8009365.7JQhni.006.6594428626875_ndvi.jpg", 226 | "RequestId": "a20698f3-a9a1-4e64-acbf-09ef77827fbc" 227 | }, 228 | { 229 | "level": 30, 230 | "executions": "93e5e049-89aa-47e5-900d-0eec87327260", 231 | "timestamp": "2018-08-15T19:23:41.886Z", 232 | "sender": "test-src-integration-SyncGranuleNoVpc", 233 | "version": "$LATEST", 234 | "message": "uploaded s3://cumulus-test-sandbox-internal/file-staging/test-src-integration/MOD09GQ___006/MOD09GQ.A8009365.7JQhni.006.6594428626875.hdf.met", 235 | "RequestId": "a20698f3-a9a1-4e64-acbf-09ef77827fbc" 236 | } 237 | ] 238 | } 239 | ``` 240 | -------------------------------------------------------------------------------- /api-client-py/LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | --------------------------------------------------------------------------------