{"action":"created","comment":{"url":"https://api.github.com/repos/juju/juju-gui/pulls/comments/47716241","id":47716241,"diff_hunk":"@@ -2442,6 +2443,155 @@ YUI.add('juju-env-go', function(Y) {\n     },\n \n     /**\n+      Make service endpoints available for consumption.\n+\n+      @method offer\n+      @param {String} service The name of the service being offered.\n+      @param {Array of strings} endpoints The offered endpoint names.\n+      @param {String} url The URL to use to reference the resulting remote\n+        service. For instance \"local:/u/admin/ec2/django\".\n+        If empty, a URL is automatically generated using the\n+        \"local:/u/$user/$env-name/$service\" pattern.\n+      @param {Array of strings} users Users that these endpoints are offered\n+        to. If left empty, the offer is considered public.\n+      @param {String} description Description for the offered service. It\n+        defaults to the description provided in the charm.\n+      @param {Function} callback A callable that must be called once the\n+        operation is performed. It will receive an object with the following\n+        attributes:\n+        - err: optional error, only defined if something went wrong;\n+        - service: the provided name of the offered service;\n+        - endpoints: the provided offered endpoints;\n+        - url: the offered service URL.\n+    */\n+    offer: function(service, endpoints, url, users, description, callback) {\n+      // Generate the URL if an empty one has been provided.\n+      // XXX frankban 2015/12/15: this will be done automatically by the\n+      // server, and the URL will be returned as part of the API response.\n+      if (!url) {\n+        var user = this.getCredentials().user.replace(/^user-/, '');\n+        var envName = this.get('environmentName');\n+        url = 'local:/u/' + user + '/' + envName + '/' + service;\n+      }\n+\n+      // Define the API callback.\n+      var handleOffer = function(userCallback, service, endpoints, url, data) {\n+        if (!userCallback) {\n+          console.log('data returned by offer API call:', data);\n+          return;\n+        }\n+        var err = data.Error;\n+        if (!err) {\n+          var errResponse = data.Response.Results[0].Error;\n+          err = errResponse && errResponse.Message;\n+        }\n+        userCallback({\n+          err: err,\n+          service: service,\n+          endpoints: endpoints,\n+          url: url\n+        });\n+      }.bind(this, callback, service, endpoints, url);\n+\n+      // Build the API call parameters.\n+      if (users && users.length) {\n+        users = users.map(function(user) {\n+          return 'user-' + user;\n+        });\n+      } else {\n+        users = ['user-public'];\n+      }\n+      var offer = {\n+        servicename: service,\n+        endpoints: endpoints,\n+        serviceurl: url,\n+        allowedusers: users,\n+        servicedescription: description\n+      };\n+\n+      // Perform the API call.\n+      this._send_rpc({\n+        Type: 'CrossModelRelations',\n+        Request: 'Offer',\n+        Params: {Offers: [offer]}\n+      }, handleOffer);\n+    },\n+\n+    /**\n+      Get all remote services that have been offered from this Juju model.\n+      Each returned service satisfies at least one of the the specified\n+      filters.\n+\n+      @method listOffers\n+      @param {Object} filters Not implemented.\n+      @param {Function} callback A callable that must be called once the\n+        operation is performed. It will receive an object with the following\n+        attributes:\n+        - err: optional error, only defined if something went wrong;\n+        - results: an array of objects representing a remote service, only\n+          present if the request succeeded.\n+          Each result has the following attributes:\n+          - err: possible error occurred while retrieving offer;\n+          - service: the offered service name;\n+          - url: the URL used to reference the remote service;\n+          - charm: the charm name;\n+          - endpoints: the list of offered endpoints.\n+          Each endpoint has the following attributes:\n+          - name: the endpoint name (e.g. \"db\" or \"website\");\n+          - interface: the endpoint inteface (e.g. \"http\" or \"mysql\");\n+          - role: the role for the endpoint (\"requirer\" or \"provider\").\n+    */\n+    listOffers: function(filters, callback) {\n+      // Define the API callback.\n+      var handleListOffers = function(userCallback, data) {\n+        if (!userCallback) {","path":"jujugui/static/gui/src/app/store/env/go.js","position":116,"original_position":116,"commit_id":"ad30f986539ec22e01e448581a74b90397b24290","original_commit_id":"ad30f986539ec22e01e448581a74b90397b24290","user":{"login":"hatched","id":532033,"avatar_url":"https://avatars.githubusercontent.com/u/532033?v=3","gravatar_id":"","url":"https://api.github.com/users/hatched","html_url":"https://github.com/hatched","followers_url":"https://api.github.com/users/hatched/followers","following_url":"https://api.github.com/users/hatched/following{/other_user}","gists_url":"https://api.github.com/users/hatched/gists{/gist_id}","starred_url":"https://api.github.com/users/hatched/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/hatched/subscriptions","organizations_url":"https://api.github.com/users/hatched/orgs","repos_url":"https://api.github.com/users/hatched/repos","events_url":"https://api.github.com/users/hatched/events{/privacy}","received_events_url":"https://api.github.com/users/hatched/received_events","type":"User","site_admin":false},"body":"same as above.","created_at":"2015-12-15T23:37:14Z","updated_at":"2015-12-15T23:37:14Z","html_url":"https://github.com/juju/juju-gui/pull/1083#discussion_r47716241","pull_request_url":"https://api.github.com/repos/juju/juju-gui/pulls/1083","_links":{"self":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/comments/47716241"},"html":{"href":"https://github.com/juju/juju-gui/pull/1083#discussion_r47716241"},"pull_request":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/1083"}}},"pull_request":{"url":"https://api.github.com/repos/juju/juju-gui/pulls/1083","id":53721584,"html_url":"https://github.com/juju/juju-gui/pull/1083","diff_url":"https://github.com/juju/juju-gui/pull/1083.diff","patch_url":"https://github.com/juju/juju-gui/pull/1083.patch","issue_url":"https://api.github.com/repos/juju/juju-gui/issues/1083","number":1083,"state":"open","locked":false,"title":"Implement the initial cross model relation endpoints.","user":{"login":"frankban","id":1408172,"avatar_url":"https://avatars.githubusercontent.com/u/1408172?v=3","gravatar_id":"","url":"https://api.github.com/users/frankban","html_url":"https://github.com/frankban","followers_url":"https://api.github.com/users/frankban/followers","following_url":"https://api.github.com/users/frankban/following{/other_user}","gists_url":"https://api.github.com/users/frankban/gists{/gist_id}","starred_url":"https://api.github.com/users/frankban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/frankban/subscriptions","organizations_url":"https://api.github.com/users/frankban/orgs","repos_url":"https://api.github.com/users/frankban/repos","events_url":"https://api.github.com/users/frankban/events{/privacy}","received_events_url":"https://api.github.com/users/frankban/received_events","type":"User","site_admin":false},"body":"Implement offer and listOffers, used for offering\r\nendpoints and retrieving a list of remote services.\r\n\r\nI presume QA for this would be done in the cmr sprint,\r\nas these API calls should be used to create and list offers.\r\n\r\nNote that sandbox mode is not implemented yet, and will be\r\nlater.","created_at":"2015-12-15T15:54:35Z","updated_at":"2015-12-15T23:37:14Z","closed_at":null,"merged_at":null,"merge_commit_sha":"38913d3878e1a184cd4103baa0f02ff6797837f8","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/juju/juju-gui/pulls/1083/commits","review_comments_url":"https://api.github.com/repos/juju/juju-gui/pulls/1083/comments","review_comment_url":"https://api.github.com/repos/juju/juju-gui/pulls/comments{/number}","comments_url":"https://api.github.com/repos/juju/juju-gui/issues/1083/comments","statuses_url":"https://api.github.com/repos/juju/juju-gui/statuses/ad30f986539ec22e01e448581a74b90397b24290","head":{"label":"frankban:initial-cmr-endpoints","ref":"initial-cmr-endpoints","sha":"ad30f986539ec22e01e448581a74b90397b24290","user":{"login":"frankban","id":1408172,"avatar_url":"https://avatars.githubusercontent.com/u/1408172?v=3","gravatar_id":"","url":"https://api.github.com/users/frankban","html_url":"https://github.com/frankban","followers_url":"https://api.github.com/users/frankban/followers","following_url":"https://api.github.com/users/frankban/following{/other_user}","gists_url":"https://api.github.com/users/frankban/gists{/gist_id}","starred_url":"https://api.github.com/users/frankban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/frankban/subscriptions","organizations_url":"https://api.github.com/users/frankban/orgs","repos_url":"https://api.github.com/users/frankban/repos","events_url":"https://api.github.com/users/frankban/events{/privacy}","received_events_url":"https://api.github.com/users/frankban/received_events","type":"User","site_admin":false},"repo":{"id":15930273,"name":"juju-gui","full_name":"frankban/juju-gui","owner":{"login":"frankban","id":1408172,"avatar_url":"https://avatars.githubusercontent.com/u/1408172?v=3","gravatar_id":"","url":"https://api.github.com/users/frankban","html_url":"https://github.com/frankban","followers_url":"https://api.github.com/users/frankban/followers","following_url":"https://api.github.com/users/frankban/following{/other_user}","gists_url":"https://api.github.com/users/frankban/gists{/gist_id}","starred_url":"https://api.github.com/users/frankban/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/frankban/subscriptions","organizations_url":"https://api.github.com/users/frankban/orgs","repos_url":"https://api.github.com/users/frankban/repos","events_url":"https://api.github.com/users/frankban/events{/privacy}","received_events_url":"https://api.github.com/users/frankban/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/frankban/juju-gui","description":"Juju-GUI is a web-based GUI for Juju <https://juju.ubuntu.com/>.","fork":true,"url":"https://api.github.com/repos/frankban/juju-gui","forks_url":"https://api.github.com/repos/frankban/juju-gui/forks","keys_url":"https://api.github.com/repos/frankban/juju-gui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/frankban/juju-gui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/frankban/juju-gui/teams","hooks_url":"https://api.github.com/repos/frankban/juju-gui/hooks","issue_events_url":"https://api.github.com/repos/frankban/juju-gui/issues/events{/number}","events_url":"https://api.github.com/repos/frankban/juju-gui/events","assignees_url":"https://api.github.com/repos/frankban/juju-gui/assignees{/user}","branches_url":"https://api.github.com/repos/frankban/juju-gui/branches{/branch}","tags_url":"https://api.github.com/repos/frankban/juju-gui/tags","blobs_url":"https://api.github.com/repos/frankban/juju-gui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/frankban/juju-gui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/frankban/juju-gui/git/refs{/sha}","trees_url":"https://api.github.com/repos/frankban/juju-gui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/frankban/juju-gui/statuses/{sha}","languages_url":"https://api.github.com/repos/frankban/juju-gui/languages","stargazers_url":"https://api.github.com/repos/frankban/juju-gui/stargazers","contributors_url":"https://api.github.com/repos/frankban/juju-gui/contributors","subscribers_url":"https://api.github.com/repos/frankban/juju-gui/subscribers","subscription_url":"https://api.github.com/repos/frankban/juju-gui/subscription","commits_url":"https://api.github.com/repos/frankban/juju-gui/commits{/sha}","git_commits_url":"https://api.github.com/repos/frankban/juju-gui/git/commits{/sha}","comments_url":"https://api.github.com/repos/frankban/juju-gui/comments{/number}","issue_comment_url":"https://api.github.com/repos/frankban/juju-gui/issues/comments{/number}","contents_url":"https://api.github.com/repos/frankban/juju-gui/contents/{+path}","compare_url":"https://api.github.com/repos/frankban/juju-gui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/frankban/juju-gui/merges","archive_url":"https://api.github.com/repos/frankban/juju-gui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/frankban/juju-gui/downloads","issues_url":"https://api.github.com/repos/frankban/juju-gui/issues{/number}","pulls_url":"https://api.github.com/repos/frankban/juju-gui/pulls{/number}","milestones_url":"https://api.github.com/repos/frankban/juju-gui/milestones{/number}","notifications_url":"https://api.github.com/repos/frankban/juju-gui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/frankban/juju-gui/labels{/name}","releases_url":"https://api.github.com/repos/frankban/juju-gui/releases{/id}","created_at":"2014-01-15T09:15:06Z","updated_at":"2015-04-29T09:56:41Z","pushed_at":"2015-12-15T15:51:30Z","git_url":"git://github.com/frankban/juju-gui.git","ssh_url":"git@github.com:frankban/juju-gui.git","clone_url":"https://github.com/frankban/juju-gui.git","svn_url":"https://github.com/frankban/juju-gui","homepage":null,"size":112203,"stargazers_count":0,"watchers_count":0,"language":"JavaScript","has_issues":false,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"develop"}},"base":{"label":"juju:develop","ref":"develop","sha":"94da299025d9e4aaab5f92ac24c070f79fb931cb","user":{"login":"juju","id":4604548,"avatar_url":"https://avatars.githubusercontent.com/u/4604548?v=3","gravatar_id":"","url":"https://api.github.com/users/juju","html_url":"https://github.com/juju","followers_url":"https://api.github.com/users/juju/followers","following_url":"https://api.github.com/users/juju/following{/other_user}","gists_url":"https://api.github.com/users/juju/gists{/gist_id}","starred_url":"https://api.github.com/users/juju/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juju/subscriptions","organizations_url":"https://api.github.com/users/juju/orgs","repos_url":"https://api.github.com/users/juju/repos","events_url":"https://api.github.com/users/juju/events{/privacy}","received_events_url":"https://api.github.com/users/juju/received_events","type":"Organization","site_admin":false},"repo":{"id":14960387,"name":"juju-gui","full_name":"juju/juju-gui","owner":{"login":"juju","id":4604548,"avatar_url":"https://avatars.githubusercontent.com/u/4604548?v=3","gravatar_id":"","url":"https://api.github.com/users/juju","html_url":"https://github.com/juju","followers_url":"https://api.github.com/users/juju/followers","following_url":"https://api.github.com/users/juju/following{/other_user}","gists_url":"https://api.github.com/users/juju/gists{/gist_id}","starred_url":"https://api.github.com/users/juju/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/juju/subscriptions","organizations_url":"https://api.github.com/users/juju/orgs","repos_url":"https://api.github.com/users/juju/repos","events_url":"https://api.github.com/users/juju/events{/privacy}","received_events_url":"https://api.github.com/users/juju/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/juju/juju-gui","description":"Juju-GUI is a web-based GUI for Juju <https://juju.ubuntu.com/>.","fork":false,"url":"https://api.github.com/repos/juju/juju-gui","forks_url":"https://api.github.com/repos/juju/juju-gui/forks","keys_url":"https://api.github.com/repos/juju/juju-gui/keys{/key_id}","collaborators_url":"https://api.github.com/repos/juju/juju-gui/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/juju/juju-gui/teams","hooks_url":"https://api.github.com/repos/juju/juju-gui/hooks","issue_events_url":"https://api.github.com/repos/juju/juju-gui/issues/events{/number}","events_url":"https://api.github.com/repos/juju/juju-gui/events","assignees_url":"https://api.github.com/repos/juju/juju-gui/assignees{/user}","branches_url":"https://api.github.com/repos/juju/juju-gui/branches{/branch}","tags_url":"https://api.github.com/repos/juju/juju-gui/tags","blobs_url":"https://api.github.com/repos/juju/juju-gui/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/juju/juju-gui/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/juju/juju-gui/git/refs{/sha}","trees_url":"https://api.github.com/repos/juju/juju-gui/git/trees{/sha}","statuses_url":"https://api.github.com/repos/juju/juju-gui/statuses/{sha}","languages_url":"https://api.github.com/repos/juju/juju-gui/languages","stargazers_url":"https://api.github.com/repos/juju/juju-gui/stargazers","contributors_url":"https://api.github.com/repos/juju/juju-gui/contributors","subscribers_url":"https://api.github.com/repos/juju/juju-gui/subscribers","subscription_url":"https://api.github.com/repos/juju/juju-gui/subscription","commits_url":"https://api.github.com/repos/juju/juju-gui/commits{/sha}","git_commits_url":"https://api.github.com/repos/juju/juju-gui/git/commits{/sha}","comments_url":"https://api.github.com/repos/juju/juju-gui/comments{/number}","issue_comment_url":"https://api.github.com/repos/juju/juju-gui/issues/comments{/number}","contents_url":"https://api.github.com/repos/juju/juju-gui/contents/{+path}","compare_url":"https://api.github.com/repos/juju/juju-gui/compare/{base}...{head}","merges_url":"https://api.github.com/repos/juju/juju-gui/merges","archive_url":"https://api.github.com/repos/juju/juju-gui/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/juju/juju-gui/downloads","issues_url":"https://api.github.com/repos/juju/juju-gui/issues{/number}","pulls_url":"https://api.github.com/repos/juju/juju-gui/pulls{/number}","milestones_url":"https://api.github.com/repos/juju/juju-gui/milestones{/number}","notifications_url":"https://api.github.com/repos/juju/juju-gui/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/juju/juju-gui/labels{/name}","releases_url":"https://api.github.com/repos/juju/juju-gui/releases{/id}","created_at":"2013-12-05T17:15:48Z","updated_at":"2015-11-24T15:41:39Z","pushed_at":"2015-12-15T23:31:47Z","git_url":"git://github.com/juju/juju-gui.git","ssh_url":"git@github.com:juju/juju-gui.git","clone_url":"https://github.com/juju/juju-gui.git","svn_url":"https://github.com/juju/juju-gui","homepage":null,"size":113137,"stargazers_count":57,"watchers_count":57,"language":"JavaScript","has_issues":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":45,"mirror_url":null,"open_issues_count":15,"forks":45,"open_issues":15,"watchers":57,"default_branch":"develop"}},"_links":{"self":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/1083"},"html":{"href":"https://github.com/juju/juju-gui/pull/1083"},"issue":{"href":"https://api.github.com/repos/juju/juju-gui/issues/1083"},"comments":{"href":"https://api.github.com/repos/juju/juju-gui/issues/1083/comments"},"review_comments":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/1083/comments"},"review_comment":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/juju/juju-gui/pulls/1083/commits"},"statuses":{"href":"https://api.github.com/repos/juju/juju-gui/statuses/ad30f986539ec22e01e448581a74b90397b24290"}}}}