{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/42499919","id":42499919,"diff_hunk":"@@ -0,0 +1,276 @@\n+package cli\n+\n+import (\n+\t\"fmt\"\n+\t\"io\"\n+\t\"io/ioutil\"\n+\t\"os\"\n+\n+\t\"github.com/spf13/cobra\"\n+\n+\tconfigapilatest \"github.com/openshift/origin/pkg/cmd/server/api/latest\"\n+\tkapi \"k8s.io/kubernetes/pkg/api\"\n+\tcmdutil \"k8s.io/kubernetes/pkg/kubectl/cmd/util\"\n+\tkerrs \"k8s.io/kubernetes/pkg/util/errors\"\n+\tkyaml \"k8s.io/kubernetes/pkg/util/yaml\"\n+\n+\t\"github.com/openshift/origin/pkg/auth/ldaputil\"\n+\tosclient \"github.com/openshift/origin/pkg/client\"\n+\t\"github.com/openshift/origin/pkg/cmd/experimental/syncgroups\"\n+\t\"github.com/openshift/origin/pkg/cmd/experimental/syncgroups/interfaces\"\n+\t\"github.com/openshift/origin/pkg/cmd/server/api\"\n+\t\"github.com/openshift/origin/pkg/cmd/server/api/validation\"\n+\t\"github.com/openshift/origin/pkg/cmd/util/clientcmd\"\n+)\n+\n+const (\n+\tPruneGroupsRecommendedName = \"prune-groups\"\n+\n+\tpruneGroupsLong = `\n+Prune OpenShift Groups referencing records from an external provider.\n+\n+In order to prune OpenShift Group records using those from an external provider, determine which Groups you wish\n+to prune. For instance, all or some groups may be selected from the current Groups stored in OpenShift that have\n+been synced previously. Any combination of a literal whitelist, a whitelist file and a blacklist file is supported.\n+The path to a sync configuration file that was used for syncing the groups in question is required in order to \n+describe how data is requested from the external record store. Default behavior is to prune all OpenShift groups \n+for which the LDAP record does not exist.\n+`\n+\tpruneGroupsExamples = `  # Prune all orphaned groups \n+  $ %[1]s --sync-config=/path/to/ldap-sync-config.yaml\n+\n+  # Prune all orphaned groups except the ones from the blacklist file\n+  $ %[1]s --blacklist=/path/to/blacklist.txt --sync-config=/path/to/ldap-sync-config.yaml\n+\n+  # Prune all orphaned groups from a list of specific groups specified in a whitelist file\n+  $ %[1]s --whitelist=/path/to/whitelist.txt --sync-config=/path/to/ldap-sync-config.yaml\n+\n+  # Prune all orphaned groups from a list of specific groups specified in a whitelist\n+  $ %[1]s groups/group_name groups/other_name --sync-config=/path/to/ldap-sync-config.yaml\n+`\n+)\n+\n+type PruneGroupsOptions struct {\n+\t// Config is the LDAP sync config read from file\n+\tConfig api.LDAPSyncConfig\n+\n+\t// Whitelist are the names of OpenShift group or LDAP group UIDs to use for syncing\n+\tWhitelist []string\n+\n+\t// Blacklist are the names of OpenShift group or LDAP group UIDs to exclude\n+\tBlacklist []string\n+\n+\t// Confirm determines whether or not to write to OpenShift\n+\tConfirm bool\n+\n+\t// GroupsInterface is the interface used to interact with OpenShift Group objects\n+\tGroupInterface osclient.GroupInterface\n+\n+\t// Stderr is the writer to write warnings and errors to\n+\tStderr io.Writer\n+\n+\t// Out is the writer to write output to\n+\tOut io.Writer\n+}\n+\n+func NewPruneGroupsOptions() *PruneGroupsOptions {\n+\treturn &PruneGroupsOptions{\n+\t\tStderr:    os.Stderr,\n+\t\tWhitelist: []string{},\n+\t}\n+}\n+\n+func NewCmdPruneGroups(name, fullName string, f *clientcmd.Factory, out io.Writer) *cobra.Command {\n+\toptions := NewPruneGroupsOptions()\n+\toptions.Out = out\n+\n+\twhitelistFile := \"\"\n+\tblacklistFile := \"\"\n+\tconfigFile := \"\"\n+\n+\tcmd := &cobra.Command{\n+\t\tUse:     fmt.Sprintf(\"%s [WHITELIST] [--whitelist=WHITELIST-FILE] [--blacklist=BLACKLIST-FILE] --sync-config=CONFIG-SOURCE\", name),\n+\t\tShort:   \"Prune OpenShift groups referencing records from an external provider.\",\n+\t\tLong:    pruneGroupsLong,\n+\t\tExample: fmt.Sprintf(pruneGroupsExamples, fullName),\n+\t\tRun: func(c *cobra.Command, args []string) {\n+\t\t\tif err := options.Complete(whitelistFile, blacklistFile, configFile, args, f); err != nil {\n+\t\t\t\tcmdutil.CheckErr(cmdutil.UsageError(c, err.Error()))\n+\t\t\t}\n+\n+\t\t\tif err := options.Validate(); err != nil {\n+\t\t\t\tcmdutil.CheckErr(cmdutil.UsageError(c, err.Error()))\n+\t\t\t}\n+\n+\t\t\terr := options.Run(c, f)\n+\t\t\tif err != nil {\n+\t\t\t\tif aggregate, ok := err.(kerrs.Aggregate); ok {\n+\t\t\t\t\tfor _, err := range aggregate.Errors() {\n+\t\t\t\t\t\tfmt.Printf(\"%s\\n\", err)\n+\t\t\t\t\t}\n+\t\t\t\t\tos.Exit(1)\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\tcmdutil.CheckErr(err)\n+\t\t},\n+\t}\n+\n+\tcmd.Flags().StringVar(&whitelistFile, \"whitelist\", whitelistFile, \"path to the group whitelist file\")\n+\tcmd.Flags().StringVar(&blacklistFile, \"blacklist\", whitelistFile, \"path to the group blacklist file\")\n+\t// TODO enable this we're able to support string slice elements that have commas\n+\t// cmd.Flags().StringSliceVar(&options.Blacklist, \"blacklist-group\", options.Blacklist, \"group to blacklist\")\n+\tcmd.Flags().StringVar(&configFile, \"sync-config\", configFile, \"path to the sync config\")\n+\tcmd.Flags().BoolVar(&options.Confirm, \"confirm\", false, \"if true, modify OpenShift groups; if false, display groups\")\n+\tcmdutil.AddPrinterFlags(cmd)\n+\tcmd.Flags().Lookup(\"output\").DefValue = \"yaml\"\n+\tcmd.Flags().Lookup(\"output\").Value.Set(\"yaml\")\n+\n+\treturn cmd\n+}\n+\n+func (o *PruneGroupsOptions) Complete(whitelistFile, blacklistFile, configFile string, args []string, f *clientcmd.Factory) error {\n+\t// if args are given, they are OpenShift Group names forming a whitelist\n+\tif len(args) > 0 {\n+\t\to.Whitelist = append(o.Whitelist, args...)\n+\t}\n+\n+\t// unpack whitelist file from source\n+\tif len(whitelistFile) != 0 {\n+\t\twhitelistData, err := readLines(whitelistFile)\n+\t\tif err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\to.Whitelist = append(o.Whitelist, whitelistData...)\n+\t}\n+\n+\t// unpack blacklist file from source\n+\tif len(blacklistFile) != 0 {\n+\t\tblacklistData, err := readLines(blacklistFile)\n+\t\tif err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\to.Blacklist = append(o.Blacklist, blacklistData...)\n+\t}\n+\n+\tyamlConfig, err := ioutil.ReadFile(configFile)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"could not read file %s: %v\", configFile, err)\n+\t}\n+\tjsonConfig, err := kyaml.ToJSON(yamlConfig)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"could not parse file %s: %v\", configFile, err)\n+\t}\n+\tif err := configapilatest.Codec.DecodeInto(jsonConfig, &o.Config); err != nil {\n+\t\treturn err\n+\t}\n+\n+\tif f != nil {\n+\t\tosClient, _, err := f.Clients()\n+\t\tif err != nil {\n+\t\t\treturn err\n+\t\t}\n+\t\to.GroupInterface = osClient.Groups()\n+\t}\n+\n+\treturn nil\n+}\n+\n+func (o *PruneGroupsOptions) Validate() error {\n+\tresults := validation.ValidateLDAPSyncConfig(o.Config)\n+\t// TODO(skuznets): pretty-print validation results\n+\tif len(results.Errors) > 0 {\n+\t\treturn fmt.Errorf(\"validation of LDAP sync config failed: %v\", kerrs.NewAggregate([]error(results.Errors)))\n+\t}\n+\treturn nil\n+}\n+\n+// Run creates the GroupSyncer specified and runs it to sync groups\n+// the arguments are only here because its the only way to get the printer we need\n+func (o *PruneGroupsOptions) Run(cmd *cobra.Command, f *clientcmd.Factory) error {\n+\tclientConfig, err := ldaputil.NewLDAPClientConfig(o.Config.URL, o.Config.BindDN, o.Config.BindPassword, o.Config.CA, o.Config.Insecure)\n+\tif err != nil {\n+\t\treturn fmt.Errorf(\"could not determine LDAP client configuration: %v\", err)\n+\t}\n+\n+\tvar syncBuilder SyncBuilder\n+\tswitch {\n+\tcase o.Config.RFC2307Config != nil:\n+\t\tsyncBuilder = &RFC2307SyncBuilder{ClientConfig: clientConfig, Config: o.Config.RFC2307Config}\n+\n+\tcase o.Config.ActiveDirectoryConfig != nil:\n+\t\tsyncBuilder = &ADSyncBuilder{ClientConfig: clientConfig, Config: o.Config.ActiveDirectoryConfig}\n+\n+\tcase o.Config.AugmentedActiveDirectoryConfig != nil:\n+\t\tsyncBuilder = &AugmentedADSyncBuilder{ClientConfig: clientConfig, Config: o.Config.AugmentedActiveDirectoryConfig}\n+\n+\tdefault:\n+\t\treturn fmt.Errorf(\"invalid sync config type: %v\", o.Config)\n+\t}\n+\n+\t// populate schema-independent pruner fields\n+\tpruner := &syncgroups.LDAPGroupSyncer{\n+\t\tHost:        clientConfig.Host,\n+\t\tGroupClient: o.GroupInterface,\n+\t\tDryRun:      !o.Confirm,\n+\n+\t\tOut: o.Out,\n+\t\tErr: os.Stderr,\n+\t}\n+\n+\tlisterMapper, err := o.GetOpenShiftGroupListerMapper(syncBuilder, clientConfig)\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\tpruner.GroupLister = listerMapper\n+\tpruner.GroupNameMapper = listerMapper\n+\n+\tpruner.GroupMemberExtractor, err = syncBuilder.GetGroupMemberExtractor()\n+\tif err != nil {\n+\t\treturn err\n+\t}\n+\n+\t// Now we run the pruner and report any errors\n+\tgroupsToPrune, pruneErrors := pruner.Prune()\n+\tif o.Confirm {\n+\t\treturn kerrs.NewAggregate(pruneErrors)\n+\t}\n+\n+\tlist := &kapi.List{}\n+\tfor _, item := range groupsToPrune {\n+\t\tlist.Items = append(list.Items, item)\n+\t}\n+\tif err := f.Factory.PrintObject(cmd, list, o.Out); err != nil {\n+\t\treturn err\n+\t}\n+\n+\treturn kerrs.NewAggregate(pruneErrors)\n+\n+}\n+\n+func (o *PruneGroupsOptions) GetOpenShiftGroupListerMapper(syncBuilder SyncBuilder, clientConfig *ldaputil.LDAPClientConfig) (interfaces.LDAPGroupListerNameMapper, error) {","path":"pkg/cmd/experimental/syncgroups/cli/prunegroups.go","position":250,"original_position":250,"commit_id":"eea9a86f985f038311ca7171699d71c5d8962100","original_commit_id":"eea9a86f985f038311ca7171699d71c5d8962100","user":{"login":"deads2k","id":8225098,"avatar_url":"https://avatars.githubusercontent.com/u/8225098?v=3","gravatar_id":"","url":"https://api.github.com/users/deads2k","html_url":"https://github.com/deads2k","followers_url":"https://api.github.com/users/deads2k/followers","following_url":"https://api.github.com/users/deads2k/following{/other_user}","gists_url":"https://api.github.com/users/deads2k/gists{/gist_id}","starred_url":"https://api.github.com/users/deads2k/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/deads2k/subscriptions","organizations_url":"https://api.github.com/users/deads2k/orgs","repos_url":"https://api.github.com/users/deads2k/repos","events_url":"https://api.github.com/users/deads2k/events{/privacy}","received_events_url":"https://api.github.com/users/deads2k/received_events","type":"User","site_admin":false},"body":"Fix these like we discussed in person.","created_at":"2015-10-20T14:12:28Z","updated_at":"2015-10-20T14:12:28Z","html_url":"https://github.com/openshift/origin/pull/5145#discussion_r42499919","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/5145","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/42499919"},"html":{"href":"https://github.com/openshift/origin/pull/5145#discussion_r42499919"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/5145"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/5145","id":47819454,"html_url":"https://github.com/openshift/origin/pull/5145","diff_url":"https://github.com/openshift/origin/pull/5145.diff","patch_url":"https://github.com/openshift/origin/pull/5145.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/5145","number":5145,"state":"open","locked":false,"title":"implemented LDAP group pruning","user":{"login":"stevekuznetsov","id":7328370,"avatar_url":"https://avatars.githubusercontent.com/u/7328370?v=3","gravatar_id":"","url":"https://api.github.com/users/stevekuznetsov","html_url":"https://github.com/stevekuznetsov","followers_url":"https://api.github.com/users/stevekuznetsov/followers","following_url":"https://api.github.com/users/stevekuznetsov/following{/other_user}","gists_url":"https://api.github.com/users/stevekuznetsov/gists{/gist_id}","starred_url":"https://api.github.com/users/stevekuznetsov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stevekuznetsov/subscriptions","organizations_url":"https://api.github.com/users/stevekuznetsov/orgs","repos_url":"https://api.github.com/users/stevekuznetsov/repos","events_url":"https://api.github.com/users/stevekuznetsov/events{/privacy}","received_events_url":"https://api.github.com/users/stevekuznetsov/received_events","type":"User","site_admin":false},"body":"Adds `openshift ex prune-groups`.\r\n\r\ncc/ @deads2k @liggitt ","created_at":"2015-10-15T17:53:24Z","updated_at":"2015-10-20T14:12:28Z","closed_at":null,"merged_at":null,"merge_commit_sha":"be0a449de40f77d506657c62f7f45743563c7485","assignee":{"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},"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/5145/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/5145/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/5145/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/eea9a86f985f038311ca7171699d71c5d8962100","head":{"label":"stevekuznetsov:skuznets/prune-groups","ref":"skuznets/prune-groups","sha":"eea9a86f985f038311ca7171699d71c5d8962100","user":{"login":"stevekuznetsov","id":7328370,"avatar_url":"https://avatars.githubusercontent.com/u/7328370?v=3","gravatar_id":"","url":"https://api.github.com/users/stevekuznetsov","html_url":"https://github.com/stevekuznetsov","followers_url":"https://api.github.com/users/stevekuznetsov/followers","following_url":"https://api.github.com/users/stevekuznetsov/following{/other_user}","gists_url":"https://api.github.com/users/stevekuznetsov/gists{/gist_id}","starred_url":"https://api.github.com/users/stevekuznetsov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stevekuznetsov/subscriptions","organizations_url":"https://api.github.com/users/stevekuznetsov/orgs","repos_url":"https://api.github.com/users/stevekuznetsov/repos","events_url":"https://api.github.com/users/stevekuznetsov/events{/privacy}","received_events_url":"https://api.github.com/users/stevekuznetsov/received_events","type":"User","site_admin":false},"repo":{"id":35963136,"name":"origin","full_name":"stevekuznetsov/origin","owner":{"login":"stevekuznetsov","id":7328370,"avatar_url":"https://avatars.githubusercontent.com/u/7328370?v=3","gravatar_id":"","url":"https://api.github.com/users/stevekuznetsov","html_url":"https://github.com/stevekuznetsov","followers_url":"https://api.github.com/users/stevekuznetsov/followers","following_url":"https://api.github.com/users/stevekuznetsov/following{/other_user}","gists_url":"https://api.github.com/users/stevekuznetsov/gists{/gist_id}","starred_url":"https://api.github.com/users/stevekuznetsov/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/stevekuznetsov/subscriptions","organizations_url":"https://api.github.com/users/stevekuznetsov/orgs","repos_url":"https://api.github.com/users/stevekuznetsov/repos","events_url":"https://api.github.com/users/stevekuznetsov/events{/privacy}","received_events_url":"https://api.github.com/users/stevekuznetsov/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/stevekuznetsov/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/stevekuznetsov/origin","forks_url":"https://api.github.com/repos/stevekuznetsov/origin/forks","keys_url":"https://api.github.com/repos/stevekuznetsov/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/stevekuznetsov/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/stevekuznetsov/origin/teams","hooks_url":"https://api.github.com/repos/stevekuznetsov/origin/hooks","issue_events_url":"https://api.github.com/repos/stevekuznetsov/origin/issues/events{/number}","events_url":"https://api.github.com/repos/stevekuznetsov/origin/events","assignees_url":"https://api.github.com/repos/stevekuznetsov/origin/assignees{/user}","branches_url":"https://api.github.com/repos/stevekuznetsov/origin/branches{/branch}","tags_url":"https://api.github.com/repos/stevekuznetsov/origin/tags","blobs_url":"https://api.github.com/repos/stevekuznetsov/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/stevekuznetsov/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/stevekuznetsov/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/stevekuznetsov/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/stevekuznetsov/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/stevekuznetsov/origin/languages","stargazers_url":"https://api.github.com/repos/stevekuznetsov/origin/stargazers","contributors_url":"https://api.github.com/repos/stevekuznetsov/origin/contributors","subscribers_url":"https://api.github.com/repos/stevekuznetsov/origin/subscribers","subscription_url":"https://api.github.com/repos/stevekuznetsov/origin/subscription","commits_url":"https://api.github.com/repos/stevekuznetsov/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/stevekuznetsov/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/stevekuznetsov/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/stevekuznetsov/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/stevekuznetsov/origin/contents/{+path}","compare_url":"https://api.github.com/repos/stevekuznetsov/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/stevekuznetsov/origin/merges","archive_url":"https://api.github.com/repos/stevekuznetsov/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/stevekuznetsov/origin/downloads","issues_url":"https://api.github.com/repos/stevekuznetsov/origin/issues{/number}","pulls_url":"https://api.github.com/repos/stevekuznetsov/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/stevekuznetsov/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/stevekuznetsov/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/stevekuznetsov/origin/labels{/name}","releases_url":"https://api.github.com/repos/stevekuznetsov/origin/releases{/id}","created_at":"2015-05-20T17:28:25Z","updated_at":"2015-05-20T17:28:28Z","pushed_at":"2015-10-20T14:11:18Z","git_url":"git://github.com/stevekuznetsov/origin.git","ssh_url":"git@github.com:stevekuznetsov/origin.git","clone_url":"https://github.com/stevekuznetsov/origin.git","svn_url":"https://github.com/stevekuznetsov/origin","homepage":"http://www.openshift.org","size":154267,"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":"a5f3dc21b28f375b7db6719cb731c6ded796ac7a","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-10-20T09:29:19Z","pushed_at":"2015-10-20T14:11:18Z","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":273850,"stargazers_count":753,"watchers_count":753,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":458,"mirror_url":null,"open_issues_count":587,"forks":458,"open_issues":587,"watchers":753,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/5145"},"html":{"href":"https://github.com/openshift/origin/pull/5145"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/5145"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/5145/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/5145/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/5145/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/eea9a86f985f038311ca7171699d71c5d8962100"}}}}