{"id":18542192,"url":"https://github.com/heremaps/deployment-api","last_synced_at":"2025-10-05T00:07:06.969Z","repository":{"id":71903193,"uuid":"103288819","full_name":"heremaps/deployment-api","owner":"heremaps","description":"A front-end for DC/OS service creation","archived":false,"fork":false,"pushed_at":"2017-10-26T17:15:43.000Z","size":295,"stargazers_count":4,"open_issues_count":0,"forks_count":3,"subscribers_count":5,"default_branch":"master","last_synced_at":"2025-04-10T11:52:39.881Z","etag":null,"topics":["dcos","deployment"],"latest_commit_sha":null,"homepage":"","language":"Java","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/heremaps.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-09-12T15:32:28.000Z","updated_at":"2019-03-04T14:44:43.000Z","dependencies_parsed_at":null,"dependency_job_id":"6ee51e3e-082b-413e-a1bd-0185c6c7a1e7","html_url":"https://github.com/heremaps/deployment-api","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/heremaps/deployment-api","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heremaps%2Fdeployment-api","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heremaps%2Fdeployment-api/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heremaps%2Fdeployment-api/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heremaps%2Fdeployment-api/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/heremaps","download_url":"https://codeload.github.com/heremaps/deployment-api/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/heremaps%2Fdeployment-api/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":278391220,"owners_count":25978947,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-10-04T02:00:05.491Z","response_time":63,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dcos","deployment"],"created_at":"2024-11-06T20:07:42.213Z","updated_at":"2025-10-05T00:07:06.958Z","avatar_url":"https://github.com/heremaps.png","language":"Java","funding_links":[],"categories":[],"sub_categories":[],"readme":"# DC/OS Deployment API Service\n\nCopyright (c) 2017 HERE Europe B.V\n\nA REST service which integrates with Git to provide a hierarchical, source control-backed YAML model for managing deployment configuration for [DC/OS](https://docs.mesosphere.com/1.10/overview/what-is-dcos). DevOps engineers within HERE use this service to configure global, application, and environmental settings for \"bundles\" of an application and its environments, e.g. *MyService-dev*, *MyService-uat*, *MyService-prod*.\n\n# Table of contents\n1. [Introduction](#introduction)\n1. [Setup](#setup)\n1. [Concepts](#concepts)\n1. [Inheritance Hierarchy](#inheritance-hierarchy)\n1. [Secrets](#secrets)\n1. [Label Templates](#label-templates)\n1. [Service Deployments](#service-deployments)\n1. [Swagger UI](#swagger-ui)\n1. [Jenkins Pipeline Integration](#jenkins-pipeline-integration)\n1. [Troubleshooting](#troubleshooting)\n1. [YAML Model](#yaml-model)\n1. [Plugins](#plugins)\n\nIntroduction\n---\n\nDeployment API is a front-end for DC/OS service creation. It allows Ops to control all deployment properties while allowing for self-service deployments from CI tools like Jenkins without exposing credential configuration or the heavy lifting required to correctly deploy DC/OS services. The configuration files are stored in Git in YAML format, so all deployment configuration changes are appropriately tracked in source control and can be easily reviewed. Deployment configuration is transformed from the YAML model to the [Marathon API format](https://dcos.io/docs/1.9/deploying-services/marathon-api/) and sent to DC/OS automatically.\n\nSetup\n---\n \t\n*Full deployment/setup instructions are currently pending legal approval of the release on hub.docker.com.* \n\nConcepts\n---\n\nThe core concept is best demonstrated using an example. All deployment configuration lives inside YAML files stored in a Git repo. For an application called \"MyService\" with 2 environments (`dev`, `prod`), you'd create a bundle of deployment configuration YAML files inside your backing Git repo. At deployment time, these files are merged into a single YAML model, transformed into the [Marathon API format](https://dcos.io/docs/1.9/deploying-services/marathon-api/), and then sent to DC/OS.\n\n```\n\u003crepo_root\u003e/application-global.yml\t\t# global settings, applies to all deployments\n\u003crepo_root\u003e/MyService/MyService-deploy.yml\t# application settings, applies to all MyService deployments (dev, prod)\n\u003crepo_root\u003e/MyService/MyService-deploy-dev.yml\t# environment settings, applies only to MyService dev deployments\n\u003crepo_root\u003e/MyService/MyService-deploy-prod.yml\t# environment settings, applies only to MyService prod deployments\n```\n\nThe Deployment API model requires an `appName` and `appEnv` to arrange deployment properties by application and environment. In the above example, the `appName` is *MyService* and the `appEnv` could be `dev` or `prod`.\n\n*application-global.yml* contains global settings for all applications. These will be inherited by every deployment unless overridden:\n\n```yaml\nmarathon:\n  url: https://dcos-internal.mycompany.com\n  container:\n    type: DOCKER\n    docker:\n      forcePullImage: true\n      network: BRIDGE\n\nglobal:\n  docker:\n    parameters:\n      -\n        key: log-driver\n        value: syslog\n      -\n        key: log-opt\n        value: syslog-address=tcp://logstash-shipper.mycompany.com:514\n      -\n        key: log-opt\n        value: syslog-format=rfc3164       \n```\n\n*MyService-deploy.yml* contains settings for all *MyService* environments:\n\n```yaml\nmarathon:\n  mem: 512.0\n  upgradeStrategy:\n    minimumHealthCapacity: 0.5\n    maximumOverCapacity: 0.2\n  healthChecks:\n    -\n      protocol: MESOS_HTTP\n      path: /\n      portIndex: 0\n      gracePeriodSeconds: 300\n      intervalSeconds: 30\n      timeoutSeconds: 20\n      maxConsecutiveFailures: 3\n  secrets:\n    -\n      name: DCOS_SECRET\t\t# local secret name reference\n      source: my-dcos-secret\t# name of DC/OS Secret\napplication:\n  env:\n    -\n      key: JAVA_OPTS\n      value: -Xmx512m\n    -\n      key: DEPLOYMENT_SECRET\t# environment variable name/key\n      secret: DCOS_SECRET\t# local secret name reference\n  labels:\n    -\n      key: HAPROXY_GROUP\n      value: external\n    -\n      key: HAPROXY_0_REDIRECT_TO_HTTPS\n      value: 'true'\n    -\n      key: HAPROXY_0_STICKY\n      value: 'true'                         \n```\n\n*MyService-deploy-dev.yml* contains settings for only *MyService-dev* environments:\n\n```yaml\nmarathon:\n  appId: /myservice-dev\n  instances: 1\n  cpus: 0.25      \n  container:\n    docker:\n      portMappings:\n        -\n          containerPort: 8080\n          hostPort: 0\n          protocol: tcp\n          labels:\n            -\n              key: VIP_0\n              value: /myservice-dev:8080\n        -\n          containerPort: 9096\n          hostPort: 9096\n          protocol: tcp          \n          labels:\n            -\n              key: VIP_1\n              value: /myservice-dev:9096\nenvironment:\n  env:\n    - \n      key: DEPLOYMENT_ENV\n      value: development \n  docker:\n    parameters:\n      -\n        key: log-opt\n        value: tag=myservice-dev/{{.ID}}\n  labels:\n    -\n      key: HAPROXY_0_VHOST\n      value: myservice-dev.mycompany.com        \n```\n\nWhen a deployment to the `dev` environment is initiated, Deployment API merges the 3 YAML configuration files and transforms the merged configuration into the familiar [Marathon API format](https://dcos.io/docs/1.9/deploying-services/marathon-api/):\n\n```json\n{\n  \"id\": \"/myservice-dev\",\n  \"instances\": 1,\n  \"cpus\": 0.25,\n  \"mem\": 512.0,\n  \"container\": {\n    \"type\": \"DOCKER\",\n    \"docker\": {\n      \"network\": \"BRIDGE\",\n      \"forcePullImage\": true,\n      \"portMappings\": [\n        {\n          \"containerPort\": 8080,\n          \"hostPort\": 0,\n          \"protocol\": \"tcp\",\n          \"labels\": {\n            \"VIP_0\": \"/myservice-dev:8080\"\n          }\n        },\n        {\n          \"containerPort\": 9096,\n          \"hostPort\": 9096,\n          \"protocol\": \"tcp\",\n          \"labels\": {\n            \"VIP_1\": \"/myservice-dev:9096\"\n          }\n        }\n      ],\n      \"parameters\": [\n        {\n          \"key\": \"log-driver\",\n          \"value\": \"syslog\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"syslog-address=tcp://logstash-shipper.mycompany.com:514\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"syslog-format=rfc3164\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"tag=myservice-dev/{{.ID}}\"\n        }\n      ]\n    }\n  },\n  \"env\": {\n    \"DEPLOYMENT_SECRET\": {\n      \"secret\": \"DCOS_SECRET\"\n    },\n    \"DEPLOYMENT_ENV\": \"development\",    \n    \"JAVA_OPTS\": \"-Xmx512m\"\n  },\n  \"secrets\": {\n    \"DCOS_SECRET\": {\n      \"source\": \"my-dcos-secret\"\n    }\n  },\n  \"labels\": {\n    \"HAPROXY_0_VHOST\": \"myservice-dev.mycompany.com\",\n    \"HAPROXY_0_REDIRECT_TO_HTTPS\": \"true\",\n    \"HAPROXY_GROUP\": \"external\",\n    \"HAPROXY_0_STICKY\": \"true\"\n  },\n  \"healthChecks\": [\n    {\n      \"gracePeriodSeconds\": 300,\n      \"intervalSeconds\": 30,\n      \"maxConsecutiveFailures\": 3,\n      \"portIndex\": 0,\n      \"timeoutSeconds\": 20,\n      \"ignoreHttp1xx\": false,\n      \"path\": \"/\",\n      \"protocol\": \"MESOS_HTTP\"\n    }\n  ],\n  \"upgradeStrategy\": {\n    \"minimumHealthCapacity\": 0.5,\n    \"maximumOverCapacity\": 0.2\n  }\n}\n```\n\n*MyService-deploy-prod.yml* and its corresponding transformation follow the same ideas:\n\n```yaml\nmarathon:\n  appId: /myservice-prod\n  instances: 5\n  cpus: 1  \n  container:\n    docker:\n      portMappings:\n        -\n          containerPort: 8080\n          hostPort: 0\n          protocol: tcp\n          labels:\n            -\n              key: VIP_0\n              value: /myservice-prod:8080\n        -\n          containerPort: 9096\n          hostPort: 9096\n          protocol: tcp          \n          labels:\n            -\n              key: VIP_1\n              value: /myservice-prod:9096\nenvironment:\n  env:\n    - \n      key: DEPLOYMENT_ENV\n      value: production \n  docker:\n    parameters:\n      -\n        key: log-opt\n        value: tag=myservice-prod/{{.ID}}\n  labels:\n    -\n      key: HAPROXY_0_VHOST\n      value: myservice-prod.mycompany.com         \n```\n\n\n```json\n{\n  \"id\": \"/myservice-prod\",\n  \"instances\": 5,\n  \"cpus\": 1,\n  \"mem\": 512.0,\n  \"container\": {\n    \"type\": \"DOCKER\",\n    \"docker\": {\n      \"network\": \"BRIDGE\",\n      \"forcePullImage\": true,\n      \"portMappings\": [\n        {\n          \"containerPort\": 8080,\n          \"hostPort\": 0,\n          \"protocol\": \"tcp\",\n          \"labels\": {\n            \"VIP_0\": \"/myservice-prod:8080\"\n          }\n        },\n        {\n          \"containerPort\": 9096,\n          \"hostPort\": 9096,\n          \"protocol\": \"tcp\",\n          \"labels\": {\n            \"VIP_1\": \"/myservice-prod:9096\"\n          }\n        }\n      ],\n      \"parameters\": [\n        {\n          \"key\": \"log-driver\",\n          \"value\": \"syslog\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"syslog-address=tcp://logstash-shipper.mycompany.com:514\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"syslog-format=rfc3164\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"tag=myservice-prod/{{.ID}}\"\n        }\n      ]\n    }\n  },\n  \"env\": {\n    \"DEPLOYMENT_SECRET\": {\n      \"secret\": \"DCOS_SECRET\"\n    },\n    \"DEPLOYMENT_ENV\": \"production\",    \n    \"JAVA_OPTS\": \"-Xmx512m\"\n  },\n  \"secrets\": {\n    \"DCOS_SECRET\": {\n      \"source\": \"my-dcos-secret\"\n    }\n  },\n  \"labels\": {\n    \"HAPROXY_0_VHOST\": \"myservice-prod.mycompany.com\",\n    \"HAPROXY_0_REDIRECT_TO_HTTPS\": \"true\",\n    \"HAPROXY_GROUP\": \"external\",\n    \"HAPROXY_0_STICKY\": \"true\"\n  },\n  \"healthChecks\": [\n    {\n      \"gracePeriodSeconds\": 300,\n      \"intervalSeconds\": 30,\n      \"maxConsecutiveFailures\": 3,\n      \"portIndex\": 0,\n      \"timeoutSeconds\": 20,\n      \"ignoreHttp1xx\": false,\n      \"path\": \"/\",\n      \"protocol\": \"MESOS_HTTP\"\n    }\n  ],\n  \"upgradeStrategy\": {\n    \"minimumHealthCapacity\": 0.5,\n    \"maximumOverCapacity\": 0.2\n  }\n}\n```\n\nInheritance Hierarchy\n---\n\nProperties underneath the `marathon.*` namespace can be overridden by hierarchy: `environment` overrides `application` overrides `global`. For example:\n\n*application-global.yml* (global):\n\n```yaml\nmarathon:\n  instances: 1\n  cpus: 0.25\n  ...  \n```\n\n*MyService-deploy.yml* (application):\n\n```yaml\nmarathon:\n  instances: 3\n  cpus: 0.5\n  mem: 512.0\n  ...  \n```\n\n*MyService-deploy-dev.yml* (environment):\n\n```yaml\nmarathon:\n  appId: /myservice-dev\n  instances: 5\n  cpus: 1\n  ...  \n```\n\nWhen these are merged at deployment time, the `instances` and `cpus` settings defined by *MyService-deploy-dev.yml* would override both the application and global settings, and the service would deploy with `instances: 5` , `cpus: 1` , `mem: 512.0`. If *MyService-deploy-dev.yml* didn't define anything for these settings:\n\n```yaml\nmarathon:\n  appId: /myservice-dev\n  ...  \n```\n\nThe deployment would inherit from *MyService-deploy.yml* `instances: 3` , `cpus: 0.5` , `mem: 512.0`\n\n#### Merging Lists\n\n**Lists underneath the marathon.* namespace are not merged.** For example:\n\n*MyService-deploy.yml* (application):\n\n```yaml\nmarathon:   \n  container:\n    docker:\n      portMappings:\n        -\n          containerPort: 8080\n          hostPort: 0\n          protocol: tcp\n          labels:\n            -\n              key: VIP_0\n              value: /myservice-dev:8080\n```\n\n*MyService-deploy-dev.yml* (environment):\n\n```yaml\nmarathon:   \n  container:\n    docker:\n      portMappings:              \n        -\n          containerPort: 9096\n          hostPort: 9096\n          protocol: tcp          \n          labels:\n            -\n              key: VIP_1\n              value: /myservice-dev:9096\n```\n\nThe merged deployment would **only** contain the `portMapping` labeled `VIP_1`, the the portMapping from *MyService-deploy.yml* would not be included.\n\nIf the `marathon.*` namespace lists were allowed to be merged, there would be no way to exclude list items from another file. Thus, Deployment API provides a structure for defining merged lists of the three most common merged list items: environment variables, docker parameters and labels. For example:\n\n*application-global.yml* (global):\n\n```yaml\nglobal:\n  env:\n    - \n      key: GLOBAL_ENV_VAR\n      value: global-var\n  docker:\n    parameters:\n      -\n        key: log-driver\n        value: tag=syslog\n  labels:\n    - \n      key: GLOBAL_LABEL\n      value: global-label\n```\n\n*MyService-deploy.yml* (application):\n\n```yaml\napplication:\n  env:\n    - \n      key: APPLICATION_ENV_VAR\n      value: application-var\n  docker:\n    parameters:\n      -\n        key: log-opt\n        value: syslog-format=rfc3164  \n  labels:\n    - \n      key: APPLICATION_LABEL\n      value: application-label\n```\n\n*MyService-deploy-dev.yml* (environment):\n\n```yaml   \nenvironment:\n  env:\n    - \n      key: ENVIRONMENT_ENV_VAR\n      value: environment-var\n  docker:\n    parameters:\n      -\n        key: log-opt\n        value: tag=mytag\n  labels:\n    - \n      key: ENVIRONMENT_LABEL\n      value: environment-label\n```\n\nWould produce the following merged JSON:\n\n```json\n{\n  ...\n  \"container\": {\n    \"docker\": {\n      \"parameters\": [\n        {\n          \"key\": \"log-driver\",\n          \"value\": \"syslog\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"syslog-format=rfc3164\"\n        },\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"tag=mytag\"\n        }\n      ]\n    }\n  },\n  \"env\": {\n    \"GLOBAL_ENV_VAR\": \"global-var\",    \n    \"APPLICATION_ENV_VAR\": \"application-var\",\n    \"ENVIRONMENT_ENV_VAR\": \"environment-var\"\n  },\n  \"labels\": {\n    \"GLOBAL_LABEL\": \"global-label\",\n    \"APPLICATION_LABEL\": \"application-label\",\n    \"ENVIRONMENT_LABEL\": \"environment-label\"\n  },\n  ...\n}\n```\n\n#### Excluding List Values\n\nTo exclude the values from another file from being merged, we just define the list with no values. For example, if using the same example as above except with *MyService-deploy-dev.yml* (environment) defined like:\n\n```yaml   \nenvironment:\n  env:\n    - \n      key: ENVIRONMENT_ENV_VAR\n      value: environment-var\n  docker:\n    parameters:\n      -\n        key: log-opt\n        value: tag=mytag\n  labels:\n    - \n      key: ENVIRONMENT_LABEL\n      value: environment-label\nglobal:\n  env:\n  docker:\n    parameters:\n  labels:\napplication:\n  env:\n  docker:\n    parameters:\n  labels:          \n```\n\nThe merged JSON would not include anything from *application-global.yml* or *MyService-deploy.yml*:\n\n```json\n{\n  ...\n  \"container\": {\n    \"docker\": {\n      \"parameters\": [\n        {\n          \"key\": \"log-opt\",\n          \"value\": \"tag=mytag\"\n        }\n      ]\n    }\n  },\n  \"env\": {\n    \"ENVIRONMENT_ENV_VAR\": \"environment-var\"\n  },\n  \"labels\": {\n    \"ENVIRONMENT_LABEL\": \"environment-label\"\n  },\n  ...\n}\n```\n \nSecrets\n---\n\nSecrets are supported using a similar model to the native JSON. First, define the secret with a name and source. \"Source\" refers to the DC/OS secret key, \"name\" is the local reference to the secret.\n\n```yaml  \nmarathon:\n  secrets:\n    -\n      name: DCOS_SECRET\t\t# local secret name reference\n      source: my-dcos-secret\t# name of DC/OS Secret\n```\n\nThen add the secret to the environment:\n      \n```yaml    \napplication:\n  env:\n    -\n      key: DEPLOYMENT_SECRET\t# environment variable name/key\n      secret: DCOS_SECRET\t# local secret name reference\n```\n\nProduces:\n\n```json\n{\n  ...\n  \"env\": {\n    \"DEPLOYMENT_SECRET\": {\n      \"secret\": \"DCOS_SECRET\"\n    }\n  },\n  \"secrets\": {\n    \"DCOS_SECRET\": {\n      \"source\": \"my-dcos-secret\"\n    }\n  },\n  ...\n}\n```\n\n\nLabel Templates\n---\nDeployment API provides functionality to template difficult to manage strings in labels. There are two built-in label templates to facilitate integration with HAProxy, and it is simple to add custom templates.\n\n#### `haproxy_backend_health`\n\n```yaml\nenvironment:\n  labels:\n    -\n      key: HAPROXY_0_BACKEND_HTTP_HEALTHCHECK_OPTIONS\n      template: haproxy_backend_health\n      args:\n        - myhost.com           \n```\n\n```json\n}\n  ...\n  \"labels\": {\n    \"HAPROXY_0_BACKEND_HTTP_HEALTHCHECK_OPTIONS\": \"option httpchk GET {healthCheckPath} HTTP/1.1\\\\\\\\r\\\\\\\\nHost:\\\\\\\\ myhost.com\\\\n\",\n  } \n  ...\n}  \n```\n\n#### `haproxy_backend_head`\n\n```yaml\nenvironment:\n  labels:\n    -\n      key: HAPROXY_0_BACKEND_HEAD\n      template: haproxy_backend_head\n      args:\n        - 300s         \n```\n\n```json\n}\n  ...\n  \"labels\": {\n    \"HAPROXY_0_BACKEND_HEAD\": \"backend {backend}\\\\r\\\\n balance {balance}\\\\r\\\\n mode {mode}\\\\r\\\\n timeout server 300s\\\\r\\\\n timeout client 300s\\\\r\\\\n\",\n  } \n  ...\n}  \n```\n\n### Custom Label Templates\nTo define custom label templates, add *DeploymentApiService.yml* to your backing Git repo in the following location:\n\n```\n\u003crepo_root\u003e/DeploymentApiService/DeploymentApiService.yml\n```\n\nWith the definition of your template as `my_label_template_name`:\n\n```yaml\ndeployment:  \n  label:\n    template:\n      user:\n        my_label_template_name: my template {0}\n```\n\nThen restart Deployment API service and refer to your new template:\n\n```yaml\nenvironment:\n  labels:\n    -\n      key: LABEL_NAME\n      template: my_label_template_name\n      args:\n        - myArg         \n```\n\nAnd this will produce:\n\n```json\n}\n  ...\n  \"labels\": {\n    \"LABEL_NAME\": \"my template myArg\",\n  } \n  ...\n}  \n```\n\nService Deployments\n---\n\nService deployment requires 5 arguments:\n* username: Username for DC/OS. This user must have the appropriate permissions set up to create services via the API. Typically a service account user.\n* password: Password for DC/OS user.\n* appName: The application name referenced in the YAML files (see [Concepts](#concepts))\n* appEnv: The application environment referenced in the YAML files (see [Concepts](#concepts))\n* image: Docker image being deployed.\n\nSimply POST to the service created in [Setup](#setup):\n\n```\ncurl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \\ \n   \"username\": \"MyDcosUsername\", \\ \n   \"password\": \"myDcosPassword1234!\", \\ \n   \"appName\": \"MyService\", \\ \n   \"appEnv\": \"dev\", \\ \n   \"image\": \"docker.mycompany.com/my-service:latest\" \\ \n }' 'https://deploymentapi.mycompany.com/v1/dcos/deploy'\n```\n\nIf successful, returns `201 Created` with the appId:\n\n```json\n{\n  \"appId\": \"/myservice-dev\"\n}\n```\n\nOne can then poll for the status until `state: deployed`\n\n```\ncurl -X POST --header 'Content-Type: application/json' --header 'Accept: application/json' -d '{ \\ \n   \"username\": \"MyDcosUsername\", \\ \n   \"password\": \"myDcosPassword1234!\", \\ \n   \"appName\": \"MyService\", \\ \n   \"appEnv\": \"dev\" \\ \n }' 'https://deploymentapi.mycompany.com/v1/dcos/status\n```\n\n```json\n{\n  \"appId\": \"/myservice-dev\",\n  \"tasksStaged\": 1,\n  \"tasksRunning\": 0,\n  \"tasksHealthy\": 0,\n  \"tasksUnhealthy\": 0,\n  \"deployments\": [\n    {\n      \"id\": \"a5d121b4-7885-4941-badf-846a0b2df995\"\n    }\n  ],  \n  \"state\": \"deploying\"\n}\n```\n\n...and then once the app is finally deployed...\n\n```json\n{\n  \"appId\": \"/myservice-dev\",\n  \"tasksStaged\": 0,\n  \"tasksRunning\": 1,\n  \"tasksHealthy\": 1,\n  \"tasksUnhealthy\": 0,\n  \"deployments\": [],\n  \"state\": \"deployed\"\n}\n```\n\nSwagger UI\n---\n\nPointing your web browser at the service created in [Setup](#setup) will display a Swagger UI page for interacting with the three functions Deployment API provides.\n\n---\n\n#### GET - /v1/dcos/config\n\nReturns the YAML model transformed to [Marathon API format](https://dcos.io/docs/1.9/deploying-services/marathon-api/) for the given appName and appEnv. Useful for debugging.\n\n![swagger-1](docs/images/swagger-1.png)\n\n---\n\n#### POST - /v1/dcos/deploy\n\nDeploy the provided Docker image to DC/OS using configuration provided by appName and appEnv.\n\n![swagger-2](docs/images/swagger-2.png)\n\n----\n\n#### POST - /v1/dcos/status\n\nRetrieve deployment status for provided appName and appEnv from DC/OS.\n\n![swagger-3](docs/images/swagger-3.png)\n\n---\n\nJenkins Pipeline Integration\n---\n\n[Jenkins Pipelines](https://jenkins.io/doc/book/pipeline/syntax/) are supported with a [shared library](https://jenkins.io/doc/book/pipeline/shared-libraries/) (requires [Credentials Plugin](https://wiki.jenkins.io/display/JENKINS/Credentials+Plugin))\n\nFirst, create a new Credential with the ID 'deployment-api'. This is your DC/OS user which has the appropriate permissions to create services.\n\n![credentials](docs/images/credentials.png)\n\nCopy the example jenkins-pipeline from the [deployment-api examples](https://github.com/heremaps/deployment-api/tree/master/examples/jenkins-pipeline) to a repository of your choice. For example: [https://github.com/micahnoland/deployment-api-jenkins](https://github.com/micahnoland/deployment-api-jenkins)\n\nAnd then add the following to the top of your Jenkinsfile:\n\n```groovy\n@Library('github.com/micahnoland/deployment-api-jenkins@master') _\n```\n\nYour Jenkins Pipeline can then call the `deploymentApi(appName, appEnv, image)` method to initiate the deployment. `deploymentApi()` will attempt to deploy the application, and then block for up to 10 minutes while polling for deployment status. Once the deployment status is 'deployed', the method exits successfully. If 10 minutes of status polling elapse without receiving a 'deployed' status, the method throws an exception.\n\nHere is a sample Jenkinsfile for reference:\n\n```groovy\n#!/usr/bin/env groovy\n@Library('github.com/micahnoland/deployment-api-jenkins@master') _\n\npipeline {\n  environment {\n  \tDEPLOYMENT_API_APP_NAME = 'CoolService'\n  \tDEPLOYMENT_API_URL = 'https://deploymentapi.mycompany.com' \n  }\n  stages {\n    stage ('Build') {\n  \t// run build, create Docker image, etc.\n  \tenv.DOCKER_IMAGE = ...\n    }      \n    stage ('Deploy to Dev') {\n      steps {\n      \tscript {\n      \t  deploymentApi(env.DEPLOYMENT_API_APP_NAME, 'dev', \"${DOCKER_IMAGE}\") )\n      \t}\n      }\n    }\n  }    \n}\n```\n\nTroubleshooting\n---\n\n#### HTTP Status 409\n\n`409 - Conflict` is returned if Marathon already has an App running with the same id and Docker image. For example, if [Marathon already has an App](https://mesosphere.github.io/marathon/docs/rest-api.html#user-content-get-v2apps) with id `/myservice-dev` running `docker.mycompany.com/docker/my-service:latest` as in:\n\n```json\n{\n\t\"apps\": [\n\t\t{\n\t\t    \"id\": \"/myservice-dev\",\n\t\t    \"container\": {\n\t\t        \"docker\": {\n\t\t            \"image\": \"docker.mycompany.com/docker/my-service:latest\",\n\t\t            ... \n\t\t        }\n\t\t        ...\n\t\t    }\n\t\t    ...\n\t\t}\n\t]\n}\t\t\n```\n\nThen trying to deploy `docker.mycompany.com/docker/my-service:latest` to `/myservice-dev` again will return `409 - Conflict`. To work around this, in the short term, destroy the service manually in DC/OS and then re-deploy. In the long-term, configure your deployment pipeline to give a unique tag to your Docker image for each build, as in `docker.mycompany.com/docker/my-service:1.0.67`.\n\n#### HTTP Status 403\n\n`403 - Forbidden` is returned if the credentials provided by `\"username\"` and `\"password\"` does not have access to deploy to the given id. \n\n\nYAML Model\n---\n\n```yaml\nmarathon:\n  url: \n  appId:  \n  instances:\n  cpus: \n  mem:\n  container:\n    type: \n    docker:\n      forcePullImage: \n      network: \n      portMappings:\n        -\n          containerPort:\n          hostPort:\n          servicePort:\n          protocol:     \n          labels:\n            -\n              key:\n              value:\n    volumes:\n      -\n        containerPath: \n        hostPath: \n        mode:            \n        id:\n        status:\n        type:\n        name:\n        provider:\n        options:\n          -\n            key:\n            value: \n  upgradeStrategy:\n    minimumHealthCapacity:\n    maximumOverCapacity:\n  healthChecks:\n    -\n      protocol: \n      portIndex: \n      gracePeriodSeconds: \n      path: \n      intervalSeconds: \n      timeoutSeconds:\n      maxConsecutiveFailures:\n      ignoreHttp1xx: \n  secrets:\n    -\n      name: \n      source:  \n  fetch:\n    -\n      uri:       \n  constraints: \n    -\n      attribute: \n      operator: \n      value:       \n          \n# parameters which will apply to all deployments. Should live in application-global.yml          \nglobal:\n  docker:\n    parameters:\n      -\n        key: \n        value:\n  env:\n    - \n      key: \n      value: \n    -\n      key: \n      secret: \n  labels:\n    -\n      key: \n      value: \n    -\n      key:\n      template: \n      args:\n        -       \n         \n# parameters which will apply to all deployments for this appName. Should live in {appName}/{appName}-deploy.yml      \napplication:\n  docker:\n    parameters:\n      -\n        key:\n        value:\n  env:\n    - \n      key: \n      value: \n    -\n      key: \n      secret: \n  labels:\n    -\n      key: \n      value: \n    -\n      key:\n      template: \n      args:\n        -       \n\n# parameters which will apply to deployments for this appName and appEnv. Should live in {appName}/{appName}-deploy-{appEnv}.yml         \nenvironment:        \n  docker:\n    parameters:\n      -\n        key:\n        value:\n  env:\n    - \n      key: \n      value: \n    -\n      key: \n      secret:\n       environment:\n  labels:\n    -\n      key: \n      value: \n    -\n      key:\n      template: \n      args:\n        - \n```\n\nPlugins\n---\n\n\nIt is possible to create custom plugins which can send arbitrary payloads to various services at deployment time, to facilitate deployment orchestration. For example, when an application is deployed, some HERE Technologies users require a JSON payload to be sent to an external [Etcd](https://github.com/coreos/etcd) service to enable [DataDog](https://github.com/DataDog) monitoring of the Docker containers. These payloads live inside the same Git repo as deployment configuration for maximum convenience:\n\n```\n\u003crepo_root\u003e/application-global.yml\t\n\u003crepo_root\u003e/MyService/MyService-deploy.yml\n\u003crepo_root\u003e/MyService/MyService-deploy-dev.yml\t\n\u003crepo_root\u003e/MyService/MyService-deploy-prod.yml\n\u003crepo_root\u003e/MyService/MyService-etcd-dev.yml\n\u003crepo_root\u003e/MyService/MyService-etcd-prod.yml\n```\n\nThe deployment-api-datadog-plugin project is provided as an example. Familiarity with [Spring Boot](https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-auto-configuration.html) is required.","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheremaps%2Fdeployment-api","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fheremaps%2Fdeployment-api","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fheremaps%2Fdeployment-api/lists"}