{"action":"created","comment":{"url":"https://api.github.com/repos/mesosphere/marathon/pulls/comments/41162728","id":41162728,"diff_hunk":"@@ -0,0 +1,169 @@\n+---\n+title: Extend Marathon with Plugins\n+---\n+\n+\n+# Extend Marathon with Plugins\n+\n+<div class=\"alert alert-danger\" role=\"alert\">\n+  <span class=\"glyphicon glyphicon-exclamation-sign\" aria-hidden=\"true\"></span> Available in Marathon Version 0.12+ <br/>\n+  The Marathon plugin functionality is considered Alpha! <br/>\n+  You can use this feature at you own risk. <br/>\n+  We might want to add, change or delete any functionality described in this document. \n+</div>\n+\n+## Overview\n+\n+<p class=\"text-center\">\n+  <img src=\"{{ site.baseurl}}/img/plugin-mechanism.png\" width=\"552\" height=\"417\" alt=\"\">\n+</p>\n+\n+\n+Starting with Marathon 0.12 we provide the ability to extend functionality in Marathon with plugins.\n+Every extension comprises this functionality:\n+\n+- __Extension Aware Functionality:__ Marathon makes specific functionality available for customization. There are hooks implemented into the main system, that can be refined and extended with external plugins.\n+- __Extension Interface:__ The extended functionality is defined as scala trait (java interface). In order to extend this functionality, the plugin writer has to implement that interface.\n+- __Plugin Extension:__ This is the implementation of a defined Extension Interface. The implementation needs to be compiled and packaged into one or more separate jar files. \n+- __Plugin Descriptor:__ The descriptor defines, which set of plugins should be enabled in one instance of Marathon.\n+  \n+\n+\n+## Plugin Interface\n+\n+A separate Marathon Plugin interface jar is published with every Marathon Release on that maven repository:\n+\n+```\n+http://downloads.mesosphere.io/marathon\n+```\n+\n+with following dependency:\n+\n+SBT:\n+\n+```\n+\"mesosphere.marathon\" %% \"plugin-interface\" % \"x.x.x\" % \"provided\"\n+\n+```\n+\n+Maven:\n+\n+```\n+<dependency>\n+    <groupId>mesosphere.marathon</groupId>\n+    <artifactId>plugin-interface_2.11</artifactId>\n+    <version>x.x.x</version>\n+</dependency>\n+```\n+\n+Please make sure, that you always use the same version of the plugin interface as the Marathon version in production.\n+\n+\n+\n+## Extension Functionality\n+\n+To create an extension, you have to implement an extension interface from the plugin interface method, that can be loaded by the ServiceLoader.\n+\n+### Service Loader\n+\n+Marathon makes use of the [ServiceLoader](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) \n+to make service provider available to a running Marathon instance. For background information on that topic, please see [Creating Extensible Applications](https://docs.oracle.com/javase/tutorial/ext/basics/spi.html).\n+\n+### Dependencies to other libraries\n+\n+The plugin writer can define dependencies to other libraries and use those dependencies, if following requirements are met:\n+\n+- Marathon already has a dependency to that library. You can see all Marathon dependencies by checking out Marathon and running `sbt dependencyTree`. \n+  Such a dependency can be defined as `provided` in your build tool of choice.\n+  _Please make sure, you use the exact same version of that library!_\n+- A library that does not conflict with any library bundled with Marathon (e.g. different byte code manipulation libraries are known to interfere). \n+  Such a dependency should be defined as `compile` dependency in your build tool of choice.\n+  \n+Dependant libraries that are not already provided by Marathon have to be shipped along with the plugin itself.\n+ \n+### Packaging\n+\n+The plugin has to be compiled and packaged as `jar` file.\n+Inside that jar file the [ServiceLoader](https://docs.oracle.com/javase/8/docs/api/java/util/ServiceLoader.html) specific provider-configuration file needs to be included.\n+ \n+\n+### Logging\n+\n+Marathon uses `slf4j` for logging. The dependency to this library is already available with the plugin interface package.\n+If you use this logger classes, all log statement will be available in Marathon.\n+\n+### Configuration\n+\n+Since the plugin mechanism in Marathon relies on the ServiceLoader, the plugin class has to implement a default constructor.\n+To pass a certain configuration to the plugin, you can use whatever functionality you like.\n+\n+We build one optional way, that can be used by your plugin: If you implement the interface [PluginConfiguration](https://github.com/mesosphere/marathon/blob/master/plugin-interface/src/main/scala/mesosphere/marathon/plugin/plugin/PluginConfiguration.scala)","path":"docs/docs/plugin.md","position":100,"original_position":100,"commit_id":"a1bb1e3da7f5e802bdf60e1d892287ed310af614","original_commit_id":"02a9df73b8ac05fdfb4f91ebbc2760cf799e8f9d","user":{"login":"gkleiman","id":146374,"avatar_url":"https://avatars.githubusercontent.com/u/146374?v=3","gravatar_id":"","url":"https://api.github.com/users/gkleiman","html_url":"https://github.com/gkleiman","followers_url":"https://api.github.com/users/gkleiman/followers","following_url":"https://api.github.com/users/gkleiman/following{/other_user}","gists_url":"https://api.github.com/users/gkleiman/gists{/gist_id}","starred_url":"https://api.github.com/users/gkleiman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gkleiman/subscriptions","organizations_url":"https://api.github.com/users/gkleiman/orgs","repos_url":"https://api.github.com/users/gkleiman/repos","events_url":"https://api.github.com/users/gkleiman/events{/privacy}","received_events_url":"https://api.github.com/users/gkleiman/received_events","type":"User","site_admin":false},"body":"s/build/built/","created_at":"2015-10-05T16:08:45Z","updated_at":"2015-10-05T16:08:45Z","html_url":"https://github.com/mesosphere/marathon/pull/2355#discussion_r41162728","pull_request_url":"https://api.github.com/repos/mesosphere/marathon/pulls/2355","_links":{"self":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/comments/41162728"},"html":{"href":"https://github.com/mesosphere/marathon/pull/2355#discussion_r41162728"},"pull_request":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/2355"}}},"pull_request":{"url":"https://api.github.com/repos/mesosphere/marathon/pulls/2355","id":46788606,"html_url":"https://github.com/mesosphere/marathon/pull/2355","diff_url":"https://github.com/mesosphere/marathon/pull/2355.diff","patch_url":"https://github.com/mesosphere/marathon/pull/2355.patch","issue_url":"https://api.github.com/repos/mesosphere/marathon/issues/2355","number":2355,"state":"open","locked":false,"title":"Add plugin management documentation.","user":{"login":"aquamatthias","id":330485,"avatar_url":"https://avatars.githubusercontent.com/u/330485?v=3","gravatar_id":"","url":"https://api.github.com/users/aquamatthias","html_url":"https://github.com/aquamatthias","followers_url":"https://api.github.com/users/aquamatthias/followers","following_url":"https://api.github.com/users/aquamatthias/following{/other_user}","gists_url":"https://api.github.com/users/aquamatthias/gists{/gist_id}","starred_url":"https://api.github.com/users/aquamatthias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aquamatthias/subscriptions","organizations_url":"https://api.github.com/users/aquamatthias/orgs","repos_url":"https://api.github.com/users/aquamatthias/repos","events_url":"https://api.github.com/users/aquamatthias/events{/privacy}","received_events_url":"https://api.github.com/users/aquamatthias/received_events","type":"User","site_admin":false},"body":"","created_at":"2015-10-05T14:38:44Z","updated_at":"2015-10-05T16:08:45Z","closed_at":null,"merged_at":null,"merge_commit_sha":"b4575acaa5ed008cb0aaaff52ad812e92b856e80","assignee":{"login":"gkleiman","id":146374,"avatar_url":"https://avatars.githubusercontent.com/u/146374?v=3","gravatar_id":"","url":"https://api.github.com/users/gkleiman","html_url":"https://github.com/gkleiman","followers_url":"https://api.github.com/users/gkleiman/followers","following_url":"https://api.github.com/users/gkleiman/following{/other_user}","gists_url":"https://api.github.com/users/gkleiman/gists{/gist_id}","starred_url":"https://api.github.com/users/gkleiman/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/gkleiman/subscriptions","organizations_url":"https://api.github.com/users/gkleiman/orgs","repos_url":"https://api.github.com/users/gkleiman/repos","events_url":"https://api.github.com/users/gkleiman/events{/privacy}","received_events_url":"https://api.github.com/users/gkleiman/received_events","type":"User","site_admin":false},"milestone":{"url":"https://api.github.com/repos/mesosphere/marathon/milestones/20","html_url":"https://github.com/mesosphere/marathon/milestones/0.12.0","labels_url":"https://api.github.com/repos/mesosphere/marathon/milestones/20/labels","id":1231438,"number":20,"title":"0.12.0","description":"RC-1 will be released on 2015-09-28","creator":{"login":"aquamatthias","id":330485,"avatar_url":"https://avatars.githubusercontent.com/u/330485?v=3","gravatar_id":"","url":"https://api.github.com/users/aquamatthias","html_url":"https://github.com/aquamatthias","followers_url":"https://api.github.com/users/aquamatthias/followers","following_url":"https://api.github.com/users/aquamatthias/following{/other_user}","gists_url":"https://api.github.com/users/aquamatthias/gists{/gist_id}","starred_url":"https://api.github.com/users/aquamatthias/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/aquamatthias/subscriptions","organizations_url":"https://api.github.com/users/aquamatthias/orgs","repos_url":"https://api.github.com/users/aquamatthias/repos","events_url":"https://api.github.com/users/aquamatthias/events{/privacy}","received_events_url":"https://api.github.com/users/aquamatthias/received_events","type":"User","site_admin":false},"open_issues":4,"closed_issues":69,"state":"open","created_at":"2015-07-29T12:23:28Z","updated_at":"2015-10-05T15:46:16Z","due_on":"2015-10-14T22:00:00Z","closed_at":null},"commits_url":"https://api.github.com/repos/mesosphere/marathon/pulls/2355/commits","review_comments_url":"https://api.github.com/repos/mesosphere/marathon/pulls/2355/comments","review_comment_url":"https://api.github.com/repos/mesosphere/marathon/pulls/comments{/number}","comments_url":"https://api.github.com/repos/mesosphere/marathon/issues/2355/comments","statuses_url":"https://api.github.com/repos/mesosphere/marathon/statuses/a1bb1e3da7f5e802bdf60e1d892287ed310af614","head":{"label":"mesosphere:mv/plugin_docs","ref":"mv/plugin_docs","sha":"a1bb1e3da7f5e802bdf60e1d892287ed310af614","user":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":10941409,"name":"marathon","full_name":"mesosphere/marathon","owner":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mesosphere/marathon","description":"Deploy and manage containers (including Docker) on top of Apache Mesos at scale.","fork":false,"url":"https://api.github.com/repos/mesosphere/marathon","forks_url":"https://api.github.com/repos/mesosphere/marathon/forks","keys_url":"https://api.github.com/repos/mesosphere/marathon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mesosphere/marathon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mesosphere/marathon/teams","hooks_url":"https://api.github.com/repos/mesosphere/marathon/hooks","issue_events_url":"https://api.github.com/repos/mesosphere/marathon/issues/events{/number}","events_url":"https://api.github.com/repos/mesosphere/marathon/events","assignees_url":"https://api.github.com/repos/mesosphere/marathon/assignees{/user}","branches_url":"https://api.github.com/repos/mesosphere/marathon/branches{/branch}","tags_url":"https://api.github.com/repos/mesosphere/marathon/tags","blobs_url":"https://api.github.com/repos/mesosphere/marathon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mesosphere/marathon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mesosphere/marathon/git/refs{/sha}","trees_url":"https://api.github.com/repos/mesosphere/marathon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mesosphere/marathon/statuses/{sha}","languages_url":"https://api.github.com/repos/mesosphere/marathon/languages","stargazers_url":"https://api.github.com/repos/mesosphere/marathon/stargazers","contributors_url":"https://api.github.com/repos/mesosphere/marathon/contributors","subscribers_url":"https://api.github.com/repos/mesosphere/marathon/subscribers","subscription_url":"https://api.github.com/repos/mesosphere/marathon/subscription","commits_url":"https://api.github.com/repos/mesosphere/marathon/commits{/sha}","git_commits_url":"https://api.github.com/repos/mesosphere/marathon/git/commits{/sha}","comments_url":"https://api.github.com/repos/mesosphere/marathon/comments{/number}","issue_comment_url":"https://api.github.com/repos/mesosphere/marathon/issues/comments{/number}","contents_url":"https://api.github.com/repos/mesosphere/marathon/contents/{+path}","compare_url":"https://api.github.com/repos/mesosphere/marathon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mesosphere/marathon/merges","archive_url":"https://api.github.com/repos/mesosphere/marathon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mesosphere/marathon/downloads","issues_url":"https://api.github.com/repos/mesosphere/marathon/issues{/number}","pulls_url":"https://api.github.com/repos/mesosphere/marathon/pulls{/number}","milestones_url":"https://api.github.com/repos/mesosphere/marathon/milestones{/number}","notifications_url":"https://api.github.com/repos/mesosphere/marathon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mesosphere/marathon/labels{/name}","releases_url":"https://api.github.com/repos/mesosphere/marathon/releases{/id}","created_at":"2013-06-25T14:56:34Z","updated_at":"2015-10-04T19:57:14Z","pushed_at":"2015-10-05T16:02:44Z","git_url":"git://github.com/mesosphere/marathon.git","ssh_url":"git@github.com:mesosphere/marathon.git","clone_url":"https://github.com/mesosphere/marathon.git","svn_url":"https://github.com/mesosphere/marathon","homepage":"https://mesosphere.github.io/marathon/","size":29817,"stargazers_count":1846,"watchers_count":1846,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":390,"mirror_url":null,"open_issues_count":325,"forks":390,"open_issues":325,"watchers":1846,"default_branch":"master"}},"base":{"label":"mesosphere:master","ref":"master","sha":"d97b21af167433be683af7fbb18d84f02efef6ef","user":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"repo":{"id":10941409,"name":"marathon","full_name":"mesosphere/marathon","owner":{"login":"mesosphere","id":3458585,"avatar_url":"https://avatars.githubusercontent.com/u/3458585?v=3","gravatar_id":"","url":"https://api.github.com/users/mesosphere","html_url":"https://github.com/mesosphere","followers_url":"https://api.github.com/users/mesosphere/followers","following_url":"https://api.github.com/users/mesosphere/following{/other_user}","gists_url":"https://api.github.com/users/mesosphere/gists{/gist_id}","starred_url":"https://api.github.com/users/mesosphere/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mesosphere/subscriptions","organizations_url":"https://api.github.com/users/mesosphere/orgs","repos_url":"https://api.github.com/users/mesosphere/repos","events_url":"https://api.github.com/users/mesosphere/events{/privacy}","received_events_url":"https://api.github.com/users/mesosphere/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/mesosphere/marathon","description":"Deploy and manage containers (including Docker) on top of Apache Mesos at scale.","fork":false,"url":"https://api.github.com/repos/mesosphere/marathon","forks_url":"https://api.github.com/repos/mesosphere/marathon/forks","keys_url":"https://api.github.com/repos/mesosphere/marathon/keys{/key_id}","collaborators_url":"https://api.github.com/repos/mesosphere/marathon/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/mesosphere/marathon/teams","hooks_url":"https://api.github.com/repos/mesosphere/marathon/hooks","issue_events_url":"https://api.github.com/repos/mesosphere/marathon/issues/events{/number}","events_url":"https://api.github.com/repos/mesosphere/marathon/events","assignees_url":"https://api.github.com/repos/mesosphere/marathon/assignees{/user}","branches_url":"https://api.github.com/repos/mesosphere/marathon/branches{/branch}","tags_url":"https://api.github.com/repos/mesosphere/marathon/tags","blobs_url":"https://api.github.com/repos/mesosphere/marathon/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/mesosphere/marathon/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/mesosphere/marathon/git/refs{/sha}","trees_url":"https://api.github.com/repos/mesosphere/marathon/git/trees{/sha}","statuses_url":"https://api.github.com/repos/mesosphere/marathon/statuses/{sha}","languages_url":"https://api.github.com/repos/mesosphere/marathon/languages","stargazers_url":"https://api.github.com/repos/mesosphere/marathon/stargazers","contributors_url":"https://api.github.com/repos/mesosphere/marathon/contributors","subscribers_url":"https://api.github.com/repos/mesosphere/marathon/subscribers","subscription_url":"https://api.github.com/repos/mesosphere/marathon/subscription","commits_url":"https://api.github.com/repos/mesosphere/marathon/commits{/sha}","git_commits_url":"https://api.github.com/repos/mesosphere/marathon/git/commits{/sha}","comments_url":"https://api.github.com/repos/mesosphere/marathon/comments{/number}","issue_comment_url":"https://api.github.com/repos/mesosphere/marathon/issues/comments{/number}","contents_url":"https://api.github.com/repos/mesosphere/marathon/contents/{+path}","compare_url":"https://api.github.com/repos/mesosphere/marathon/compare/{base}...{head}","merges_url":"https://api.github.com/repos/mesosphere/marathon/merges","archive_url":"https://api.github.com/repos/mesosphere/marathon/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/mesosphere/marathon/downloads","issues_url":"https://api.github.com/repos/mesosphere/marathon/issues{/number}","pulls_url":"https://api.github.com/repos/mesosphere/marathon/pulls{/number}","milestones_url":"https://api.github.com/repos/mesosphere/marathon/milestones{/number}","notifications_url":"https://api.github.com/repos/mesosphere/marathon/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/mesosphere/marathon/labels{/name}","releases_url":"https://api.github.com/repos/mesosphere/marathon/releases{/id}","created_at":"2013-06-25T14:56:34Z","updated_at":"2015-10-04T19:57:14Z","pushed_at":"2015-10-05T16:02:44Z","git_url":"git://github.com/mesosphere/marathon.git","ssh_url":"git@github.com:mesosphere/marathon.git","clone_url":"https://github.com/mesosphere/marathon.git","svn_url":"https://github.com/mesosphere/marathon","homepage":"https://mesosphere.github.io/marathon/","size":29817,"stargazers_count":1846,"watchers_count":1846,"language":"Scala","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":true,"forks_count":390,"mirror_url":null,"open_issues_count":325,"forks":390,"open_issues":325,"watchers":1846,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/2355"},"html":{"href":"https://github.com/mesosphere/marathon/pull/2355"},"issue":{"href":"https://api.github.com/repos/mesosphere/marathon/issues/2355"},"comments":{"href":"https://api.github.com/repos/mesosphere/marathon/issues/2355/comments"},"review_comments":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/2355/comments"},"review_comment":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/mesosphere/marathon/pulls/2355/commits"},"statuses":{"href":"https://api.github.com/repos/mesosphere/marathon/statuses/a1bb1e3da7f5e802bdf60e1d892287ed310af614"}}}}