{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/34254139","id":34254139,"diff_hunk":"@@ -40,64 +41,117 @@ func ValidateOAuthConfig(config *api.OAuthConfig) fielderrors.ValidationErrorLis\n \n \t\t\tif api.IsPasswordAuthenticator(identityProvider) {\n \t\t\t\tif config.SessionConfig == nil {\n-\t\t\t\t\tallErrs = append(allErrs, fielderrors.NewFieldInvalid(\"sessionConfig\", config, \"sessionConfig is required if a password identity provider is used for browser based login\"))\n+\t\t\t\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"sessionConfig\", config, \"sessionConfig is required if a password identity provider is used for browser based login\"))\n \t\t\t\t}\n \t\t\t}\n \t\t}\n \n-\t\tallErrs = append(allErrs, ValidateIdentityProvider(identityProvider).Prefix(fmt.Sprintf(\"identityProvider[%d]\", i))...)\n+\t\tvalidationResults.Append(ValidateIdentityProvider(identityProvider).Prefix(fmt.Sprintf(\"identityProvider[%d]\", i)))\n \n \t\tif len(identityProvider.Name) > 0 {\n \t\t\tif providerNames.Has(identityProvider.Name) {\n-\t\t\t\tallErrs = append(allErrs, fielderrors.NewFieldInvalid(fmt.Sprintf(\"identityProvider[%d].name\", i), identityProvider.Name, \"must have a unique name\"))\n+\t\t\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(fmt.Sprintf(\"identityProvider[%d].name\", i), identityProvider.Name, \"must have a unique name\"))\n \t\t\t}\n \t\t\tproviderNames.Insert(identityProvider.Name)\n \t\t}\n \t}\n \n \tif len(redirectingIdentityProviders) > 1 {\n-\t\tallErrs = append(allErrs, fielderrors.NewFieldInvalid(\"identityProviders\", config.IdentityProviders, fmt.Sprintf(\"only one identity provider can support login for a browser, found: %v\", redirectingIdentityProviders)))\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"identityProviders\", config.IdentityProviders, fmt.Sprintf(\"only one identity provider can support login for a browser, found: %v\", redirectingIdentityProviders)))\n \t}\n \n-\treturn allErrs\n+\treturn validationResults\n }\n \n-func ValidateIdentityProvider(identityProvider api.IdentityProvider) fielderrors.ValidationErrorList {\n-\tallErrs := fielderrors.ValidationErrorList{}\n+func ValidateIdentityProvider(identityProvider api.IdentityProvider) ValidationResults {\n+\tvalidationResults := ValidationResults{}\n \n \tif len(identityProvider.Name) == 0 {\n-\t\tallErrs = append(allErrs, fielderrors.NewFieldRequired(\"name\"))\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldRequired(\"name\"))\n \t}\n \tif ok, err := validation.ValidateIdentityProviderName(identityProvider.Name); !ok {\n-\t\tallErrs = append(allErrs, fielderrors.NewFieldInvalid(\"name\", identityProvider.Name, err))\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"name\", identityProvider.Name, err))\n \t}\n \n \tif !api.IsIdentityProviderType(identityProvider.Provider) {\n-\t\tallErrs = append(allErrs, fielderrors.NewFieldInvalid(\"provider\", identityProvider.Provider, fmt.Sprintf(\"%v is invalid in this context\", identityProvider.Provider)))\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"provider\", identityProvider.Provider, fmt.Sprintf(\"%v is invalid in this context\", identityProvider.Provider)))\n \t} else {\n \t\tswitch provider := identityProvider.Provider.Object.(type) {\n \t\tcase (*api.RequestHeaderIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateRequestHeaderIdentityProvider(provider, identityProvider)...)\n+\t\t\tvalidationResults.AddErrors(ValidateRequestHeaderIdentityProvider(provider, identityProvider)...)\n \n \t\tcase (*api.BasicAuthPasswordIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateRemoteConnectionInfo(provider.RemoteConnectionInfo).Prefix(\"provider\")...)\n+\t\t\tvalidationResults.AddErrors(ValidateRemoteConnectionInfo(provider.RemoteConnectionInfo).Prefix(\"provider\")...)\n \n \t\tcase (*api.HTPasswdPasswordIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateFile(provider.File, \"provider.file\")...)\n+\t\t\tvalidationResults.AddErrors(ValidateFile(provider.File, \"provider.file\")...)\n+\n+\t\tcase (*api.LDAPPasswordIdentityProvider):\n+\t\t\tvalidationResults.Append(ValidateLDAPIdentityProvider(provider, identityProvider))\n \n \t\tcase (*api.GitHubIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...)\n+\t\t\tvalidationResults.AddErrors(ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...)\n \n \t\tcase (*api.GoogleIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...)\n+\t\t\tvalidationResults.AddErrors(ValidateOAuthIdentityProvider(provider.ClientID, provider.ClientSecret, identityProvider.UseAsChallenger)...)\n \n \t\tcase (*api.OpenIDIdentityProvider):\n-\t\t\tallErrs = append(allErrs, ValidateOpenIDIdentityProvider(provider, identityProvider)...)\n+\t\t\tvalidationResults.AddErrors(ValidateOpenIDIdentityProvider(provider, identityProvider)...)\n \n \t\t}\n \t}\n \n-\treturn allErrs\n+\treturn validationResults\n+}\n+\n+func ValidateLDAPIdentityProvider(provider *api.LDAPPasswordIdentityProvider, identityProvider api.IdentityProvider) ValidationResults {\n+\tvalidationResults := ValidationResults{}\n+\n+\tif len(provider.URL) == 0 {\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldRequired(\"provider.url\"))\n+\t\treturn validationResults\n+\t}\n+\n+\tu, err := ldappassword.ParseURL(provider.URL)\n+\tif err != nil {\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"provider.url\", provider.URL, err.Error()))\n+\t\treturn validationResults\n+\t}\n+\n+\t// Make sure bindDN and bindPassword are both set, or both unset\n+\t// Both unset means an anonymous bind is used for search (https://tools.ietf.org/html/rfc4513#section-5.1.1)\n+\t// Both set means the name/password simple bind is used for search (https://tools.ietf.org/html/rfc4513#section-5.1.3)\n+\tif len(provider.BindDN) > 0 && len(provider.BindPassword) == 0 {\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"provider.bindDN\", provider.BindDN, \"Cannot specify bindDN without bindPassword\"))\n+\t}\n+\tif len(provider.BindPassword) > 0 && len(provider.BindDN) == 0 {\n+\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"provider.bindPassword\", \"<masked>\", \"Cannot specify bindPassword without bindDN\"))\n+\t}\n+\n+\tif provider.Insecure {\n+\t\tif u.Scheme == ldappassword.ProtocolLDAPS {\n+\t\t\tvalidationResults.AddErrors(fielderrors.NewFieldInvalid(\"provider.url\", provider.URL, fmt.Sprintf(\"Cannot use %s scheme with insecure=true\", u.Scheme)))\n+\t\t}\n+\t\tif len(provider.CA) > 0 {","path":"pkg/cmd/server/api/validation/oauth.go","position":152,"original_position":152,"commit_id":"725e763d1c5f8fb0cb5af81312cc83eeb7e899d2","original_commit_id":"725e763d1c5f8fb0cb5af81312cc83eeb7e899d2","user":{"login":"liggitt","id":980082,"avatar_url":"https://avatars.githubusercontent.com/u/980082?v=3","gravatar_id":"","url":"https://api.github.com/users/liggitt","html_url":"https://github.com/liggitt","followers_url":"https://api.github.com/users/liggitt/followers","following_url":"https://api.github.com/users/liggitt/following{/other_user}","gists_url":"https://api.github.com/users/liggitt/gists{/gist_id}","starred_url":"https://api.github.com/users/liggitt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liggitt/subscriptions","organizations_url":"https://api.github.com/users/liggitt/orgs","repos_url":"https://api.github.com/users/liggitt/repos","events_url":"https://api.github.com/users/liggitt/events{/privacy}","received_events_url":"https://api.github.com/users/liggitt/received_events","type":"User","site_admin":false},"body":"roots are part of the tlsConfig which is used during connect or during upgrade","created_at":"2015-07-09T13:26:21Z","updated_at":"2015-07-09T13:26:21Z","html_url":"https://github.com/openshift/origin/pull/3558#discussion_r34254139","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/3558","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/34254139"},"html":{"href":"https://github.com/openshift/origin/pull/3558#discussion_r34254139"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/3558"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/3558","id":39143184,"html_url":"https://github.com/openshift/origin/pull/3558","diff_url":"https://github.com/openshift/origin/pull/3558.diff","patch_url":"https://github.com/openshift/origin/pull/3558.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/3558","number":3558,"state":"open","locked":false,"title":"LDAP password authentication","user":{"login":"liggitt","id":980082,"avatar_url":"https://avatars.githubusercontent.com/u/980082?v=3","gravatar_id":"","url":"https://api.github.com/users/liggitt","html_url":"https://github.com/liggitt","followers_url":"https://api.github.com/users/liggitt/followers","following_url":"https://api.github.com/users/liggitt/following{/other_user}","gists_url":"https://api.github.com/users/liggitt/gists{/gist_id}","starred_url":"https://api.github.com/users/liggitt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liggitt/subscriptions","organizations_url":"https://api.github.com/users/liggitt/orgs","repos_url":"https://api.github.com/users/liggitt/repos","events_url":"https://api.github.com/users/liggitt/events{/privacy}","received_events_url":"https://api.github.com/users/liggitt/received_events","type":"User","site_admin":false},"body":"- [x] Add LDAP password authenticator\r\n- [x] Godoc\r\n- [x] Unit tests\r\n- [ ] Integration tests\r\n- [ ] open ansible issue\r\n- [ ] open doc issue\r\n- [x] create story for QE - https://trello.com/c/UC2rGgJ2/\r\n\r\nSample configuration to test TLS/StartTLS (`ldap.ca.crt` is the Red Hat CA - https://password.corp.redhat.com/newca.crt):\r\n```\r\n  identityProviders:\r\n  - challenge: true\r\n    login: true\r\n    name: \"secureldap\"\r\n    provider:\r\n      apiVersion: v1\r\n      attributes:\r\n        email:\r\n        - mail\r\n        id:\r\n        - dn\r\n        name:\r\n        - cn\r\n        preferredUsername:\r\n        - uid\r\n      bindDN: \"\"\r\n      bindPassword: \"\"\r\n      ca: ldap.ca.crt\r\n      kind: LDAPPasswordIdentityProvider\r\n      insecure: false\r\n      url: \"ldap://ldap.rdu.redhat.com/ou=users,dc=redhat,dc=com?uid\"\r\n```\r\n\r\n\r\nSample configuration to test `insecure: true` (login with \"newton\" / \"password\"):\r\n```\r\n  identityProviders:\r\n  - challenge: true\r\n    login: true\r\n    name: \"insecureldap\"\r\n    provider:\r\n      apiVersion: v1\r\n      attributes:\r\n        id:\r\n        - dn\r\n        name:\r\n        - cn\r\n        preferredUsername:\r\n        - uid\r\n      bindDN: \"cn=read-only-admin,dc=example,dc=com\"\r\n      bindPassword: \"password\"\r\n      ca: \"\"\r\n      kind: LDAPPasswordIdentityProvider\r\n      insecure: true\r\n      url: \"ldap://ldap.forumsys.com/dc=example,dc=com?uid\"\r\n```","created_at":"2015-07-03T03:16:35Z","updated_at":"2015-07-09T13:26:21Z","closed_at":null,"merged_at":null,"merge_commit_sha":"5704b7bdf008325e0ca62461e47ee5534463b78d","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/3558/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/3558/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/3558/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/725e763d1c5f8fb0cb5af81312cc83eeb7e899d2","head":{"label":"liggitt:ldap","ref":"ldap","sha":"725e763d1c5f8fb0cb5af81312cc83eeb7e899d2","user":{"login":"liggitt","id":980082,"avatar_url":"https://avatars.githubusercontent.com/u/980082?v=3","gravatar_id":"","url":"https://api.github.com/users/liggitt","html_url":"https://github.com/liggitt","followers_url":"https://api.github.com/users/liggitt/followers","following_url":"https://api.github.com/users/liggitt/following{/other_user}","gists_url":"https://api.github.com/users/liggitt/gists{/gist_id}","starred_url":"https://api.github.com/users/liggitt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liggitt/subscriptions","organizations_url":"https://api.github.com/users/liggitt/orgs","repos_url":"https://api.github.com/users/liggitt/repos","events_url":"https://api.github.com/users/liggitt/events{/privacy}","received_events_url":"https://api.github.com/users/liggitt/received_events","type":"User","site_admin":false},"repo":{"id":23198153,"name":"origin","full_name":"liggitt/origin","owner":{"login":"liggitt","id":980082,"avatar_url":"https://avatars.githubusercontent.com/u/980082?v=3","gravatar_id":"","url":"https://api.github.com/users/liggitt","html_url":"https://github.com/liggitt","followers_url":"https://api.github.com/users/liggitt/followers","following_url":"https://api.github.com/users/liggitt/following{/other_user}","gists_url":"https://api.github.com/users/liggitt/gists{/gist_id}","starred_url":"https://api.github.com/users/liggitt/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/liggitt/subscriptions","organizations_url":"https://api.github.com/users/liggitt/orgs","repos_url":"https://api.github.com/users/liggitt/repos","events_url":"https://api.github.com/users/liggitt/events{/privacy}","received_events_url":"https://api.github.com/users/liggitt/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/liggitt/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/liggitt/origin","forks_url":"https://api.github.com/repos/liggitt/origin/forks","keys_url":"https://api.github.com/repos/liggitt/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/liggitt/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/liggitt/origin/teams","hooks_url":"https://api.github.com/repos/liggitt/origin/hooks","issue_events_url":"https://api.github.com/repos/liggitt/origin/issues/events{/number}","events_url":"https://api.github.com/repos/liggitt/origin/events","assignees_url":"https://api.github.com/repos/liggitt/origin/assignees{/user}","branches_url":"https://api.github.com/repos/liggitt/origin/branches{/branch}","tags_url":"https://api.github.com/repos/liggitt/origin/tags","blobs_url":"https://api.github.com/repos/liggitt/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/liggitt/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/liggitt/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/liggitt/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/liggitt/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/liggitt/origin/languages","stargazers_url":"https://api.github.com/repos/liggitt/origin/stargazers","contributors_url":"https://api.github.com/repos/liggitt/origin/contributors","subscribers_url":"https://api.github.com/repos/liggitt/origin/subscribers","subscription_url":"https://api.github.com/repos/liggitt/origin/subscription","commits_url":"https://api.github.com/repos/liggitt/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/liggitt/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/liggitt/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/liggitt/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/liggitt/origin/contents/{+path}","compare_url":"https://api.github.com/repos/liggitt/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/liggitt/origin/merges","archive_url":"https://api.github.com/repos/liggitt/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/liggitt/origin/downloads","issues_url":"https://api.github.com/repos/liggitt/origin/issues{/number}","pulls_url":"https://api.github.com/repos/liggitt/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/liggitt/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/liggitt/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/liggitt/origin/labels{/name}","releases_url":"https://api.github.com/repos/liggitt/origin/releases{/id}","created_at":"2014-08-21T18:23:05Z","updated_at":"2015-05-08T13:01:51Z","pushed_at":"2015-07-08T21:03:09Z","git_url":"git://github.com/liggitt/origin.git","ssh_url":"git@github.com:liggitt/origin.git","clone_url":"https://github.com/liggitt/origin.git","svn_url":"https://github.com/liggitt/origin","homepage":"https://openshift.github.io","size":125237,"stargazers_count":0,"watchers_count":0,"language":"Go","has_issues":false,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":0,"mirror_url":null,"open_issues_count":0,"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"dc931edff5f6cc8df34c70499a67b53294bae97e","user":{"login":"openshift","id":792337,"avatar_url":"https://avatars.githubusercontent.com/u/792337?v=3","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"repo":{"id":22442668,"name":"origin","full_name":"openshift/origin","owner":{"login":"openshift","id":792337,"avatar_url":"https://avatars.githubusercontent.com/u/792337?v=3","gravatar_id":"","url":"https://api.github.com/users/openshift","html_url":"https://github.com/openshift","followers_url":"https://api.github.com/users/openshift/followers","following_url":"https://api.github.com/users/openshift/following{/other_user}","gists_url":"https://api.github.com/users/openshift/gists{/gist_id}","starred_url":"https://api.github.com/users/openshift/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/openshift/subscriptions","organizations_url":"https://api.github.com/users/openshift/orgs","repos_url":"https://api.github.com/users/openshift/repos","events_url":"https://api.github.com/users/openshift/events{/privacy}","received_events_url":"https://api.github.com/users/openshift/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/openshift/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":false,"url":"https://api.github.com/repos/openshift/origin","forks_url":"https://api.github.com/repos/openshift/origin/forks","keys_url":"https://api.github.com/repos/openshift/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/openshift/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/openshift/origin/teams","hooks_url":"https://api.github.com/repos/openshift/origin/hooks","issue_events_url":"https://api.github.com/repos/openshift/origin/issues/events{/number}","events_url":"https://api.github.com/repos/openshift/origin/events","assignees_url":"https://api.github.com/repos/openshift/origin/assignees{/user}","branches_url":"https://api.github.com/repos/openshift/origin/branches{/branch}","tags_url":"https://api.github.com/repos/openshift/origin/tags","blobs_url":"https://api.github.com/repos/openshift/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/openshift/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/openshift/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/openshift/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/openshift/origin/languages","stargazers_url":"https://api.github.com/repos/openshift/origin/stargazers","contributors_url":"https://api.github.com/repos/openshift/origin/contributors","subscribers_url":"https://api.github.com/repos/openshift/origin/subscribers","subscription_url":"https://api.github.com/repos/openshift/origin/subscription","commits_url":"https://api.github.com/repos/openshift/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/openshift/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/openshift/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/openshift/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/openshift/origin/contents/{+path}","compare_url":"https://api.github.com/repos/openshift/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/openshift/origin/merges","archive_url":"https://api.github.com/repos/openshift/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/openshift/origin/downloads","issues_url":"https://api.github.com/repos/openshift/origin/issues{/number}","pulls_url":"https://api.github.com/repos/openshift/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/openshift/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/openshift/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/openshift/origin/labels{/name}","releases_url":"https://api.github.com/repos/openshift/origin/releases{/id}","created_at":"2014-07-30T20:04:05Z","updated_at":"2015-07-09T08:29:05Z","pushed_at":"2015-07-09T13:18:37Z","git_url":"git://github.com/openshift/origin.git","ssh_url":"git@github.com:openshift/origin.git","clone_url":"https://github.com/openshift/origin.git","svn_url":"https://github.com/openshift/origin","homepage":"http://www.openshift.org","size":192120,"stargazers_count":536,"watchers_count":536,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":286,"mirror_url":null,"open_issues_count":403,"forks":286,"open_issues":403,"watchers":536,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/3558"},"html":{"href":"https://github.com/openshift/origin/pull/3558"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/3558"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/3558/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/3558/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/3558/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/725e763d1c5f8fb0cb5af81312cc83eeb7e899d2"}}}}