{"action":"created","comment":{"url":"https://api.github.com/repos/openshift/origin/pulls/comments/51625241","id":51625241,"diff_hunk":"@@ -0,0 +1,125 @@\n+package podlimitrequest\n+\n+import (\n+\t\"bytes\"\n+\t\"fmt\"\n+\t\"io\"\n+\n+\t\"github.com/openshift/origin/pkg/cmd/server/api\"\n+\t\"k8s.io/kubernetes/pkg/admission\"\n+\tkapi \"k8s.io/kubernetes/pkg/api\"\n+\t\"k8s.io/kubernetes/pkg/api/resource\"\n+\tkclient \"k8s.io/kubernetes/pkg/client/unversioned\"\n+\n+\t\"github.com/ghodss/yaml\"\n+\t\"github.com/golang/glog\"\n+\t\"speter.net/go/exp/math/dec/inf\"\n+)\n+\n+const (\n+\tannEnabled         = \"openshift.io/PodLimitRequestEnabled\"\n+\tcpuBaseScaleFactor = 1000.0 / (1024.0 * 1024.0 * 1024.0) // 1000 milliCores per 1GiB\n+)\n+\n+func init() {\n+\tadmission.RegisterPlugin(\"PodLimitRequest\", func(client kclient.Interface, config io.Reader) (admission.Interface, error) {\n+\t\treturn newPodLimitRequest(client, config)\n+\t})\n+}\n+\n+type podLimitRequest struct {\n+\t*admission.Handler\n+\tConfig     api.PodLimitRequestConfig\n+\tKubeClient kclient.Interface\n+}\n+\n+// newPodLimitRequest returns an admission controller for containers that\n+// configurably overrides container resource request/limits\n+func newPodLimitRequest(client kclient.Interface, config io.Reader) (admission.Interface, error) {\n+\tglog.V(5).Infof(\"PodLimitRequest admission controller is loaded\")\n+\tparsed, err := ReadConfig(config)\n+\tglog.V(5).Infof(\"PodLimitRequest admission controller got config: %v\\nerror: %v\", parsed, err)\n+\treturn &podLimitRequest{\n+\t\tHandler:    admission.NewHandler(admission.Create),\n+\t\tConfig:     parsed,\n+\t\tKubeClient: client,\n+\t}, err\n+}\n+\n+func ReadConfig(configFile io.Reader) (api.PodLimitRequestConfig, error) {\n+\tglog.V(5).Infof(\"PodLimitRequest about to read config:\\n%v\", configFile)\n+\tconfig := api.PodLimitRequestConfig{}\n+\tbuffer := new(bytes.Buffer)\n+\tbuffer.ReadFrom(configFile)\n+\tglog.V(5).Infof(\"PodLimitRequest read config:\\n%v\", buffer.Bytes())\n+\terr := yaml.Unmarshal(buffer.Bytes(), &config)\n+\tif err == nil && config.Enabled {\n+\t\tif config.LimitCPUToMemoryRatio == 0.0 && config.CPURequestToLimitRatio == 0.0 && config.MemoryRequestToLimitRatio == 0.0 {\n+\t\t\treturn config, fmt.Errorf(\"PodLimitRequest plugin enabled but no ratios specified\")\n+\t\t}\n+\t\tif config.LimitCPUToMemoryRatio < 0.0 {\n+\t\t\treturn config, fmt.Errorf(\"LimitCPUToMemoryRatio must be positive\")\n+\t\t}\n+\t\tif config.CPURequestToLimitRatio < 0.0 || config.CPURequestToLimitRatio > 1.0 {\n+\t\t\treturn config, fmt.Errorf(\"CPURequestToLimitRatio must be between 0.0 and 1.0\")\n+\t\t}\n+\t\tif config.MemoryRequestToLimitRatio < 0.0 || config.MemoryRequestToLimitRatio > 1.0 {\n+\t\t\treturn config, fmt.Errorf(\"MemoryRequestToLimitRatio must be between 0.0 and 1.0\")\n+\t\t}\n+\t}\n+\treturn config, err\n+}\n+\n+func (a *podLimitRequest) Admit(attr admission.Attributes) error {\n+\tglog.V(8).Infof(\"PodLimitRequest admission controller is invoked\")\n+\tif !a.Config.Enabled {\n+\t\treturn nil\n+\t}\n+\tif pod, isPod := attr.GetObject().(*kapi.Pod); isPod && attr.GetSubresource() == \"\" {\n+\t\tglog.V(8).Infof(\"PodLimitRequest is looking at creating a pod\")\n+\n+\t\t// allow annotations on project to override\n+\t\tif ns, err := a.KubeClient.Namespaces().Get(attr.GetNamespace()); err != nil {","path":"pkg/quota/admission/podlimitrequest/admission.go","position":82,"original_position":82,"commit_id":"ac796ef7c847db45c4ee85e2963e53704bacab8b","original_commit_id":"ac796ef7c847db45c4ee85e2963e53704bacab8b","user":{"login":"csrwng","id":5834976,"avatar_url":"https://avatars.githubusercontent.com/u/5834976?v=3","gravatar_id":"","url":"https://api.github.com/users/csrwng","html_url":"https://github.com/csrwng","followers_url":"https://api.github.com/users/csrwng/followers","following_url":"https://api.github.com/users/csrwng/following{/other_user}","gists_url":"https://api.github.com/users/csrwng/gists{/gist_id}","starred_url":"https://api.github.com/users/csrwng/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/csrwng/subscriptions","organizations_url":"https://api.github.com/users/csrwng/orgs","repos_url":"https://api.github.com/users/csrwng/repos","events_url":"https://api.github.com/users/csrwng/events{/privacy}","received_events_url":"https://api.github.com/users/csrwng/received_events","type":"User","site_admin":false},"body":"https://github.com/openshift/origin/blob/master/pkg/project/admission/requestlimit/admission.go \r\n\r\nYour plugin should implement the WantsProjectCache and Validator interfaces:\r\nhttps://github.com/openshift/origin/blob/master/pkg/project/admission/requestlimit/admission.go#L60-L62\r\nThe code in master_config.go will call SetProjectCache on your plugin for you.","created_at":"2016-02-02T19:55:30Z","updated_at":"2016-02-02T19:55:30Z","html_url":"https://github.com/openshift/origin/pull/6901#discussion_r51625241","pull_request_url":"https://api.github.com/repos/openshift/origin/pulls/6901","_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments/51625241"},"html":{"href":"https://github.com/openshift/origin/pull/6901#discussion_r51625241"},"pull_request":{"href":"https://api.github.com/repos/openshift/origin/pulls/6901"}}},"pull_request":{"url":"https://api.github.com/repos/openshift/origin/pulls/6901","id":57657590,"html_url":"https://github.com/openshift/origin/pull/6901","diff_url":"https://github.com/openshift/origin/pull/6901.diff","patch_url":"https://github.com/openshift/origin/pull/6901.patch","issue_url":"https://api.github.com/repos/openshift/origin/issues/6901","number":6901,"state":"open","locked":false,"title":"PodRequestLimit: overcommit admission controller","user":{"login":"sosiouxme","id":29690,"avatar_url":"https://avatars.githubusercontent.com/u/29690?v=3","gravatar_id":"","url":"https://api.github.com/users/sosiouxme","html_url":"https://github.com/sosiouxme","followers_url":"https://api.github.com/users/sosiouxme/followers","following_url":"https://api.github.com/users/sosiouxme/following{/other_user}","gists_url":"https://api.github.com/users/sosiouxme/gists{/gist_id}","starred_url":"https://api.github.com/users/sosiouxme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sosiouxme/subscriptions","organizations_url":"https://api.github.com/users/sosiouxme/orgs","repos_url":"https://api.github.com/users/sosiouxme/repos","events_url":"https://api.github.com/users/sosiouxme/events{/privacy}","received_events_url":"https://api.github.com/users/sosiouxme/received_events","type":"User","site_admin":false},"body":"Allows master config to override request and limit on submitted pods in order to control \"request\" overcommit and peg cpu limit to memory limit.\r\n\r\nhttps://trello.com/c/rRN7m0zv/546-5-override-container-resource-request-based-on-limit\r\n\r\n","created_at":"2016-01-29T15:00:50Z","updated_at":"2016-02-02T19:55:30Z","closed_at":null,"merged_at":null,"merge_commit_sha":"f6ba7f24d9d876969cc0f6339f482ad9d30887a4","assignee":null,"milestone":null,"commits_url":"https://api.github.com/repos/openshift/origin/pulls/6901/commits","review_comments_url":"https://api.github.com/repos/openshift/origin/pulls/6901/comments","review_comment_url":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}","comments_url":"https://api.github.com/repos/openshift/origin/issues/6901/comments","statuses_url":"https://api.github.com/repos/openshift/origin/statuses/ac796ef7c847db45c4ee85e2963e53704bacab8b","head":{"label":"sosiouxme:20160125-overcommit-admission","ref":"20160125-overcommit-admission","sha":"ac796ef7c847db45c4ee85e2963e53704bacab8b","user":{"login":"sosiouxme","id":29690,"avatar_url":"https://avatars.githubusercontent.com/u/29690?v=3","gravatar_id":"","url":"https://api.github.com/users/sosiouxme","html_url":"https://github.com/sosiouxme","followers_url":"https://api.github.com/users/sosiouxme/followers","following_url":"https://api.github.com/users/sosiouxme/following{/other_user}","gists_url":"https://api.github.com/users/sosiouxme/gists{/gist_id}","starred_url":"https://api.github.com/users/sosiouxme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sosiouxme/subscriptions","organizations_url":"https://api.github.com/users/sosiouxme/orgs","repos_url":"https://api.github.com/users/sosiouxme/repos","events_url":"https://api.github.com/users/sosiouxme/events{/privacy}","received_events_url":"https://api.github.com/users/sosiouxme/received_events","type":"User","site_admin":false},"repo":{"id":26488206,"name":"origin","full_name":"sosiouxme/origin","owner":{"login":"sosiouxme","id":29690,"avatar_url":"https://avatars.githubusercontent.com/u/29690?v=3","gravatar_id":"","url":"https://api.github.com/users/sosiouxme","html_url":"https://github.com/sosiouxme","followers_url":"https://api.github.com/users/sosiouxme/followers","following_url":"https://api.github.com/users/sosiouxme/following{/other_user}","gists_url":"https://api.github.com/users/sosiouxme/gists{/gist_id}","starred_url":"https://api.github.com/users/sosiouxme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sosiouxme/subscriptions","organizations_url":"https://api.github.com/users/sosiouxme/orgs","repos_url":"https://api.github.com/users/sosiouxme/repos","events_url":"https://api.github.com/users/sosiouxme/events{/privacy}","received_events_url":"https://api.github.com/users/sosiouxme/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/sosiouxme/origin","description":"OpenShift 3 - build, deploy, and manage your applications with Docker and Kubernetes","fork":true,"url":"https://api.github.com/repos/sosiouxme/origin","forks_url":"https://api.github.com/repos/sosiouxme/origin/forks","keys_url":"https://api.github.com/repos/sosiouxme/origin/keys{/key_id}","collaborators_url":"https://api.github.com/repos/sosiouxme/origin/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/sosiouxme/origin/teams","hooks_url":"https://api.github.com/repos/sosiouxme/origin/hooks","issue_events_url":"https://api.github.com/repos/sosiouxme/origin/issues/events{/number}","events_url":"https://api.github.com/repos/sosiouxme/origin/events","assignees_url":"https://api.github.com/repos/sosiouxme/origin/assignees{/user}","branches_url":"https://api.github.com/repos/sosiouxme/origin/branches{/branch}","tags_url":"https://api.github.com/repos/sosiouxme/origin/tags","blobs_url":"https://api.github.com/repos/sosiouxme/origin/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/sosiouxme/origin/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/sosiouxme/origin/git/refs{/sha}","trees_url":"https://api.github.com/repos/sosiouxme/origin/git/trees{/sha}","statuses_url":"https://api.github.com/repos/sosiouxme/origin/statuses/{sha}","languages_url":"https://api.github.com/repos/sosiouxme/origin/languages","stargazers_url":"https://api.github.com/repos/sosiouxme/origin/stargazers","contributors_url":"https://api.github.com/repos/sosiouxme/origin/contributors","subscribers_url":"https://api.github.com/repos/sosiouxme/origin/subscribers","subscription_url":"https://api.github.com/repos/sosiouxme/origin/subscription","commits_url":"https://api.github.com/repos/sosiouxme/origin/commits{/sha}","git_commits_url":"https://api.github.com/repos/sosiouxme/origin/git/commits{/sha}","comments_url":"https://api.github.com/repos/sosiouxme/origin/comments{/number}","issue_comment_url":"https://api.github.com/repos/sosiouxme/origin/issues/comments{/number}","contents_url":"https://api.github.com/repos/sosiouxme/origin/contents/{+path}","compare_url":"https://api.github.com/repos/sosiouxme/origin/compare/{base}...{head}","merges_url":"https://api.github.com/repos/sosiouxme/origin/merges","archive_url":"https://api.github.com/repos/sosiouxme/origin/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/sosiouxme/origin/downloads","issues_url":"https://api.github.com/repos/sosiouxme/origin/issues{/number}","pulls_url":"https://api.github.com/repos/sosiouxme/origin/pulls{/number}","milestones_url":"https://api.github.com/repos/sosiouxme/origin/milestones{/number}","notifications_url":"https://api.github.com/repos/sosiouxme/origin/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/sosiouxme/origin/labels{/name}","releases_url":"https://api.github.com/repos/sosiouxme/origin/releases{/id}","deployments_url":"https://api.github.com/repos/sosiouxme/origin/deployments","created_at":"2014-11-11T14:22:34Z","updated_at":"2015-05-07T14:35:38Z","pushed_at":"2016-02-02T18:01:19Z","git_url":"git://github.com/sosiouxme/origin.git","ssh_url":"git@github.com:sosiouxme/origin.git","clone_url":"https://github.com/sosiouxme/origin.git","svn_url":"https://github.com/sosiouxme/origin","homepage":"https://openshift.github.io","size":193437,"stargazers_count":1,"watchers_count":1,"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":1,"default_branch":"master"}},"base":{"label":"openshift:master","ref":"master","sha":"1647ee4d2074accb627e51e1fa298cb522b1fa91","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}","deployments_url":"https://api.github.com/repos/openshift/origin/deployments","created_at":"2014-07-30T20:04:05Z","updated_at":"2016-02-02T05:20:10Z","pushed_at":"2016-02-02T19:36:49Z","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":255368,"stargazers_count":960,"watchers_count":960,"language":"Go","has_issues":true,"has_downloads":true,"has_wiki":false,"has_pages":false,"forks_count":608,"mirror_url":null,"open_issues_count":793,"forks":608,"open_issues":793,"watchers":960,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/openshift/origin/pulls/6901"},"html":{"href":"https://github.com/openshift/origin/pull/6901"},"issue":{"href":"https://api.github.com/repos/openshift/origin/issues/6901"},"comments":{"href":"https://api.github.com/repos/openshift/origin/issues/6901/comments"},"review_comments":{"href":"https://api.github.com/repos/openshift/origin/pulls/6901/comments"},"review_comment":{"href":"https://api.github.com/repos/openshift/origin/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/openshift/origin/pulls/6901/commits"},"statuses":{"href":"https://api.github.com/repos/openshift/origin/statuses/ac796ef7c847db45c4ee85e2963e53704bacab8b"}}}}