From 7b25a6fe5ce904f2ca2320090bd8eac50e6101f1 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sat, 25 Mar 2023 21:40:51 +0300 Subject: [PATCH 01/18] :heavy_plus_sign: add main function modified: go.mod; modified: go.sum; new file: pkg/git/api/functions.go --- go.mod | 21 +++++++--- go.sum | 28 +++++++++++++ pkg/git/api/functions.go | 91 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 134 insertions(+), 6 deletions(-) create mode 100644 pkg/git/api/functions.go diff --git a/go.mod b/go.mod index 8a07e15..7e532b3 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,13 @@ require ( sigs.k8s.io/controller-runtime v0.13.1 ) +require ( + github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/cloudflare/circl v1.1.0 // indirect + github.com/google/go-github/v50 v50.2.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect +) + require ( cloud.google.com/go v0.97.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -39,6 +46,8 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-github/v33 v33.0.0 + github.com/google/go-github/v39 v39.2.0 github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.1.2 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -62,12 +71,12 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect diff --git a/go.sum b/go.sum index 0a7d1ef..14361b7 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= @@ -79,6 +81,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -88,6 +91,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= +github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -199,6 +204,15 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= +github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= +github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ= +github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= +github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk= +github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= +github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -366,10 +380,13 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= +golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -447,6 +464,8 @@ golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qx golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -464,6 +483,8 @@ golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -530,14 +551,19 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -548,6 +574,8 @@ golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/pkg/git/api/functions.go b/pkg/git/api/functions.go new file mode 100644 index 0000000..1d17b42 --- /dev/null +++ b/pkg/git/api/functions.go @@ -0,0 +1,91 @@ +package kubegit + +import ( + "context" + "fmt" + "net/http" + "os" + "path/filepath" + + "github.com/google/go-github/v50/github" + "github.com/jatalocks/kube-reqsizer/types" + "gopkg.in/yaml.v3" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func UpdateContainerRequestsInFile(filePath string, containerReqs []types.NewContainerRequests, ghToken, owner, repo string) error { + // Read the YAML file and unmarshal it into an unstructured object + file, err := os.ReadFile(filePath) + if err != nil { + return fmt.Errorf("failed to read file: %v", err) + } + var obj unstructured.Unstructured + if err := yaml.Unmarshal(file, &obj); err != nil { + return fmt.Errorf("failed to unmarshal YAML: %v", err) + } + + // Find the containers in the YAML that match the container names in the requests and update their requests + containers, _, err := unstructured.NestedSlice(obj.Object, "spec", "containers") + if err != nil { + return fmt.Errorf("failed to get containers from YAML: %v", err) + } + for i, container := range containers { + name, _, err := unstructured.NestedString(container.(map[string]interface{}), "name") + if err != nil { + continue + } + for _, req := range containerReqs { + if name == req.Name { + reqMap := map[string]interface{}{ + "resources": map[string]interface{}{ + "requests": req.Requests.Requests, + }, + } + if err := unstructured.SetNestedMap(containers[i].(map[string]interface{}), reqMap, "resources"); err != nil { + return fmt.Errorf("failed to set resource requests for container %q: %v", req.Name, err) + } + } + } + } + + // Marshal the updated YAML back to a string and write it to the file + newFile, err := yaml.Marshal(obj) + if err != nil { + return fmt.Errorf("failed to marshal updated YAML: %v", err) + } + if err := os.WriteFile(filePath, newFile, 0644); err != nil { + return fmt.Errorf("failed to write updated file: %v", err) + } + + // Create a pull request for the updated file, if one doesn't already exist + prTitle := "Update resource requests for containers" + prBody := fmt.Sprintf("Update resource requests for %d containers in file %q", len(containerReqs), filePath) + head := fmt.Sprintf("%s:%s", owner, filepath.Base(filePath)) + base := "main" + client := github.NewClient(&http.Client{}) + ctx := context.Background() + pullRequests, _, err := client.PullRequests.List(ctx, owner, repo, nil) + if err != nil { + return fmt.Errorf("failed to list pull requests: %v", err) + } + var existingPullRequest *github.PullRequest + for _, pr := range pullRequests { + if pr.Head.GetRef() == head && pr.Base.GetRef() == base { + existingPullRequest = pr + break + } + } + if existingPullRequest == nil { + newPR := &github.NewPullRequest{ + Title: &prTitle, + Head: &head, + Base: &base, + Body: &prBody, + } + if _, _, err := client.PullRequests.Create(ctx, owner, repo, newPR); err != nil { + return fmt.Errorf("failed to create pull request: %v", err) + } + } + + return nil +} From 53df0d5463aba8e8e45d0b835300d29893b62957 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 19:14:25 +0300 Subject: [PATCH 02/18] :pencil2: f modified: controllers/pod_controller.go; modified: main.go --- controllers/pod_controller.go | 14 ++++++++++---- main.go | 8 ++++++++ pkg/git/{api/functions.go => kubegit.go} | 0 3 files changed, 18 insertions(+), 4 deletions(-) rename pkg/git/{api/functions.go => kubegit.go} (100%) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 5a4f0a6..3b189fc 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -25,6 +25,7 @@ import ( "github.com/go-logr/logr" "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache" "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache" + "github.com/jatalocks/kube-reqsizer/pkg/git/kubegit" "github.com/jatalocks/kube-reqsizer/types" "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" @@ -65,6 +66,8 @@ type PodReconciler struct { MemoryFactor float64 RedisClient rediscache.RedisClient EnablePersistence bool + GithubMode bool + VerboseMode bool } const ( @@ -313,10 +316,13 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R if err != nil { return ctrl.Result{}, err } - - UpdatePodController(podSpec, Requests, ctx) - - return r.UpdateKubeObject(deployment.(client.Object), ctx) + if !r.VerboseMode { + UpdatePodController(podSpec, Requests, ctx) + return r.UpdateKubeObject(deployment.(client.Object), ctx) + } + if r.GithubMode { + kubegit.UpdateContainerRequestsInFile() + } } } } diff --git a/main.go b/main.go index e410760..27b5b03 100644 --- a/main.go +++ b/main.go @@ -80,7 +80,13 @@ func main() { var redisPort string var redisDB uint + var githubMode bool + var verboseMode bool + flag.BoolVar(&enablePersistence, "enable-persistence", false, "Uses Redis as a persistent cache") + flag.BoolVar(&enablePersistence, "github-mode", false, "Creates pull requests for resource changes using annotations") + flag.BoolVar(&enablePersistence, "verbose-mode", false, "Disable real-time resource applies. Logs only.") + flag.StringVar(&redisHost, "redis-host", "localhost", "Redis host address") flag.StringVar(&redisPort, "redis-port", "6379", "Redis port") flag.StringVar(&redisPassword, "redis-password", "", "Redis password") @@ -175,6 +181,8 @@ func main() { MinMemoryDecreasePercentage: minMemoryDecreasePercentage, CPUFactor: cpuFactor, MemoryFactor: memoryFactor, + GithubMode: githubMode, + VerboseMode: verboseMode, RedisClient: rediscache.RedisClient{Client: redisClient}, EnablePersistence: enablePersistence, }).SetupWithManager(mgr, concurrentWorkers); err != nil { diff --git a/pkg/git/api/functions.go b/pkg/git/kubegit.go similarity index 100% rename from pkg/git/api/functions.go rename to pkg/git/kubegit.go From 42ac465ff79e6cbc7f45faca429674c82c200a88 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 19:33:08 +0300 Subject: [PATCH 03/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 2 +- pkg/git/{kubegit.go => client.go} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename pkg/git/{kubegit.go => client.go} (100%) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 3b189fc..699378d 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -25,7 +25,7 @@ import ( "github.com/go-logr/logr" "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache" "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache" - "github.com/jatalocks/kube-reqsizer/pkg/git/kubegit" + kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" "github.com/jatalocks/kube-reqsizer/types" "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" diff --git a/pkg/git/kubegit.go b/pkg/git/client.go similarity index 100% rename from pkg/git/kubegit.go rename to pkg/git/client.go From eb4e36a8d4d037e4bef7447fea1857135b5041fd Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 19:39:43 +0300 Subject: [PATCH 04/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 699378d..565ca30 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -25,7 +25,8 @@ import ( "github.com/go-logr/logr" "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache" "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache" - kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" + + // kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" "github.com/jatalocks/kube-reqsizer/types" "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" @@ -320,9 +321,9 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R UpdatePodController(podSpec, Requests, ctx) return r.UpdateKubeObject(deployment.(client.Object), ctx) } - if r.GithubMode { - kubegit.UpdateContainerRequestsInFile() - } + // if r.GithubMode { + // kubegit.UpdateContainerRequestsInFile() + // } } } } From 14b1b31b1d0d5125ed44234d1d719d527158c0eb Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 19:42:13 +0300 Subject: [PATCH 05/18] :heavy_plus_sign: add git client modified: go.mod; modified: go.sum; new file: pkg/git/client.go --- go.mod | 23 +++++++----- go.sum | 34 +++++++++++------- pkg/git/client.go | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 128 insertions(+), 20 deletions(-) create mode 100644 pkg/git/client.go diff --git a/go.mod b/go.mod index 8a07e15..9b92373 100644 --- a/go.mod +++ b/go.mod @@ -13,6 +13,12 @@ require ( sigs.k8s.io/controller-runtime v0.13.1 ) +require ( + github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect + github.com/cloudflare/circl v1.1.0 // indirect + github.com/google/go-querystring v1.1.0 // indirect +) + require ( cloud.google.com/go v0.97.0 // indirect github.com/Azure/go-autorest v14.2.0+incompatible // indirect @@ -39,6 +45,7 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect + github.com/google/go-github/v50 v50.2.0 github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.1.2 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -52,7 +59,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect + github.com/prometheus/client_golang v1.12.2 github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect @@ -62,19 +69,19 @@ require ( go.uber.org/atomic v1.7.0 // indirect go.uber.org/multierr v1.6.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd // indirect - golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 // indirect - golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 // indirect - golang.org/x/sys v0.3.0 // indirect - golang.org/x/term v0.3.0 // indirect - golang.org/x/text v0.5.0 // indirect + golang.org/x/crypto v0.7.0 // indirect + golang.org/x/net v0.8.0 // indirect + golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/sys v0.6.0 // indirect + golang.org/x/term v0.6.0 // indirect + golang.org/x/text v0.8.0 // indirect golang.org/x/time v0.0.0-20220609170525-579cf78fd858 // indirect gomodules.xyz/jsonpatch/v2 v2.2.0 // indirect google.golang.org/appengine v1.6.7 // indirect google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 k8s.io/apiextensions-apiserver v0.25.0 // indirect k8s.io/component-base v0.25.0 // indirect k8s.io/klog/v2 v2.80.1 // indirect diff --git a/go.sum b/go.sum index 0a7d1ef..59db8f8 100644 --- a/go.sum +++ b/go.sum @@ -63,6 +63,8 @@ github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBp github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 h1:wPbRQzjjwFc0ih8puEVAOFGELsn1zoIIYdxvML7mDxA= +github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8/go.mod h1:I0gYDMZ6Z5GRU7l58bNFSkPTFN6Yl12dsUlAZ8xy98g= github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M= @@ -79,6 +81,7 @@ github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24 github.com/beorn7/perks v1.0.0/go.mod h1:KWe93zE9D1o94FZ5RNwFwVgaQK1VOXiVxmqh+CedLV8= github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= +github.com/bwesterb/go-ristretto v1.2.0/go.mod h1:fUIoIZaG73pV5biE2Blr2xEzDoMj7NFEuV9ekS419A0= github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU= github.com/cespare/xxhash v1.1.0/go.mod h1:XrSqR1VqqWfGrhpAt58auRo0WTKS1nRRg3ghfAqPWnc= github.com/cespare/xxhash/v2 v2.1.1/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= @@ -88,6 +91,8 @@ github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWR github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI= github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= +github.com/cloudflare/circl v1.1.0 h1:bZgT/A+cikZnKIwn7xL2OBj012Bmvho/o6RpRvv3GKY= +github.com/cloudflare/circl v1.1.0/go.mod h1:prBCrKB9DV4poKZY1l9zBXg2QJY7mvgRvtMxxK7fi4I= github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc= github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= @@ -199,6 +204,10 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk= +github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= +github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= +github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.1.0 h1:Hsa8mG0dQ46ij8Sl2AYJDUv1oA9/d6Vk+3LG99Oe02g= github.com/google/gofuzz v1.1.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -368,8 +377,8 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= +golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= @@ -445,8 +454,8 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= +golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= +golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw= @@ -462,8 +471,8 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= +golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= +golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181221193216-37e7f081c4d4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -530,14 +539,15 @@ golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210823070655-63515b42dcdf/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210908233432-aa78b53d3365/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= +golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= +golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= +golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -546,8 +556,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= +golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= +golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20190308202827-9d24e82272b4/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.0.0-20191024005414-555d28b269f0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/pkg/git/client.go b/pkg/git/client.go new file mode 100644 index 0000000..1d17b42 --- /dev/null +++ b/pkg/git/client.go @@ -0,0 +1,91 @@ +package kubegit + +import ( + "context" + "fmt" + "net/http" + "os" + "path/filepath" + + "github.com/google/go-github/v50/github" + "github.com/jatalocks/kube-reqsizer/types" + "gopkg.in/yaml.v3" + "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" +) + +func UpdateContainerRequestsInFile(filePath string, containerReqs []types.NewContainerRequests, ghToken, owner, repo string) error { + // Read the YAML file and unmarshal it into an unstructured object + file, err := os.ReadFile(filePath) + if err != nil { + return fmt.Errorf("failed to read file: %v", err) + } + var obj unstructured.Unstructured + if err := yaml.Unmarshal(file, &obj); err != nil { + return fmt.Errorf("failed to unmarshal YAML: %v", err) + } + + // Find the containers in the YAML that match the container names in the requests and update their requests + containers, _, err := unstructured.NestedSlice(obj.Object, "spec", "containers") + if err != nil { + return fmt.Errorf("failed to get containers from YAML: %v", err) + } + for i, container := range containers { + name, _, err := unstructured.NestedString(container.(map[string]interface{}), "name") + if err != nil { + continue + } + for _, req := range containerReqs { + if name == req.Name { + reqMap := map[string]interface{}{ + "resources": map[string]interface{}{ + "requests": req.Requests.Requests, + }, + } + if err := unstructured.SetNestedMap(containers[i].(map[string]interface{}), reqMap, "resources"); err != nil { + return fmt.Errorf("failed to set resource requests for container %q: %v", req.Name, err) + } + } + } + } + + // Marshal the updated YAML back to a string and write it to the file + newFile, err := yaml.Marshal(obj) + if err != nil { + return fmt.Errorf("failed to marshal updated YAML: %v", err) + } + if err := os.WriteFile(filePath, newFile, 0644); err != nil { + return fmt.Errorf("failed to write updated file: %v", err) + } + + // Create a pull request for the updated file, if one doesn't already exist + prTitle := "Update resource requests for containers" + prBody := fmt.Sprintf("Update resource requests for %d containers in file %q", len(containerReqs), filePath) + head := fmt.Sprintf("%s:%s", owner, filepath.Base(filePath)) + base := "main" + client := github.NewClient(&http.Client{}) + ctx := context.Background() + pullRequests, _, err := client.PullRequests.List(ctx, owner, repo, nil) + if err != nil { + return fmt.Errorf("failed to list pull requests: %v", err) + } + var existingPullRequest *github.PullRequest + for _, pr := range pullRequests { + if pr.Head.GetRef() == head && pr.Base.GetRef() == base { + existingPullRequest = pr + break + } + } + if existingPullRequest == nil { + newPR := &github.NewPullRequest{ + Title: &prTitle, + Head: &head, + Base: &base, + Body: &prBody, + } + if _, _, err := client.PullRequests.Create(ctx, owner, repo, newPR); err != nil { + return fmt.Errorf("failed to create pull request: %v", err) + } + } + + return nil +} From b14156e1e38dbe5c514365336639c5fd89071363 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 19:49:40 +0300 Subject: [PATCH 06/18] :pencil2: f modified: controllers/pod_controller.go; modified: go.mod --- controllers/pod_controller.go | 8 ++++---- go.mod | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 565ca30..609a9d7 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -26,7 +26,7 @@ import ( "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache" "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache" - // kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" + kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" "github.com/jatalocks/kube-reqsizer/types" "github.com/prometheus/client_golang/prometheus" corev1 "k8s.io/api/core/v1" @@ -321,9 +321,9 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R UpdatePodController(podSpec, Requests, ctx) return r.UpdateKubeObject(deployment.(client.Object), ctx) } - // if r.GithubMode { - // kubegit.UpdateContainerRequestsInFile() - // } + if r.GithubMode { + kubegit.UpdateContainerRequestsInFile() + } } } } diff --git a/go.mod b/go.mod index 7e532b3..8452e4a 100644 --- a/go.mod +++ b/go.mod @@ -61,7 +61,7 @@ require ( github.com/modern-go/reflect2 v1.0.2 // indirect github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect github.com/pkg/errors v0.9.1 // indirect - github.com/prometheus/client_golang v1.12.2 // indirect + github.com/prometheus/client_golang v1.12.2 github.com/prometheus/client_model v0.2.0 // indirect github.com/prometheus/common v0.32.1 // indirect github.com/prometheus/procfs v0.7.3 // indirect From bbe593f58c62e3c9303cc7cfafc711caece5c9fb Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 22:54:08 +0300 Subject: [PATCH 07/18] :art: ad modified: controllers/pod_controller.go; modified: controllers/pod_controller_functions.go; modified: go.mod; modified: go.sum; modified: pkg/git/client.go --- controllers/pod_controller.go | 8 ++++---- controllers/pod_controller_functions.go | 25 +++++++++++++------------ go.mod | 8 +++----- go.sum | 18 ------------------ pkg/git/client.go | 14 +++++++++----- 5 files changed, 29 insertions(+), 44 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 609a9d7..a84454c 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -26,10 +26,10 @@ import ( "github.com/jatalocks/kube-reqsizer/pkg/cache/localcache" "github.com/jatalocks/kube-reqsizer/pkg/cache/rediscache" - kubegit "github.com/jatalocks/kube-reqsizer/pkg/git/client" + "github.com/jatalocks/kube-reqsizer/pkg/git" "github.com/jatalocks/kube-reqsizer/types" "github.com/prometheus/client_golang/prometheus" - corev1 "k8s.io/api/core/v1" + corev1 "k8s.io/api/core/v1" // nolint:all v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/api/resource" @@ -313,7 +313,7 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return r.UpdateKubeObject(&pod, ctx) } - err, podSpec, deployment, _ := r.GetPodParentKind(pod, ctx) + podSpec, deployment, _, err := r.GetPodParentKind(pod, ctx) if err != nil { return ctrl.Result{}, err } @@ -322,7 +322,7 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return r.UpdateKubeObject(deployment.(client.Object), ctx) } if r.GithubMode { - kubegit.UpdateContainerRequestsInFile() + git.UpdateContainerRequestsInFile(pod.Annotations["reqsizer.jatalocks.github.io/github/path"], Requests, pod.Annotations["reqsizer.jatalocks.github.io/github/repo"], pod.Annotations["reqsizer.jatalocks.github.io/github/owner"]) } } } diff --git a/controllers/pod_controller_functions.go b/controllers/pod_controller_functions.go index 3437090..4021da4 100644 --- a/controllers/pod_controller_functions.go +++ b/controllers/pod_controller_functions.go @@ -11,7 +11,8 @@ import ( "github.com/jatalocks/kube-reqsizer/types" "github.com/labstack/gommon/log" - corev1 "k8s.io/api/core/v1" + + corev1 "k8s.io/api/core/v1" // nolint:all v1 "k8s.io/api/core/v1" apierrors "k8s.io/apimachinery/pkg/api/errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" @@ -171,7 +172,7 @@ func GetPodRequests(pod corev1.Pod) types.PodRequests { } containerData = append(containerData, types.ContainerRequests{Name: c.Name, CPU: int64(nanoCores), Memory: int64(miMemory)}) } - return types.PodRequests{pod.Name, pod.Namespace, containerData, 0} + return types.PodRequests{Name: pod.Name, Namespace: pod.Namespace, ContainerRequests: containerData, Sample: 0} } func GeneratePodRequestsObjectFromRestData(restData []byte) types.PodRequests { @@ -184,7 +185,7 @@ func GeneratePodRequestsObjectFromRestData(restData []byte) types.PodRequests { kiMemory, _ := strconv.Atoi(strings.ReplaceAll(c.Usage.Memory, "Ki", "")) containerData = append(containerData, types.ContainerRequests{Name: c.Name, CPU: int64(nanoCores / 1000000), Memory: int64(kiMemory / 1000)}) } - return types.PodRequests{data.Metadata.Name, data.Metadata.Namespace, containerData, 0} + return types.PodRequests{Name: data.Metadata.Name, Namespace: data.Metadata.Namespace, ContainerRequests: containerData, Sample: 0} } func (r *PodReconciler) MinimumUptimeOfPodInParent(pod corev1.Pod, ctx context.Context) bool { @@ -192,7 +193,7 @@ func (r *PodReconciler) MinimumUptimeOfPodInParent(pod corev1.Pod, ctx context.C if len(pod.OwnerReferences) == 0 { return time.Since(pod.CreationTimestamp.Time).Seconds() >= r.MinSecondsBetweenPodRestart } - err, _, _, deploymentName := r.GetPodParentKind(pod, ctx) + _, _, deploymentName, err := r.GetPodParentKind(pod, ctx) if err != nil { log.Error(err) return false @@ -216,32 +217,32 @@ func (r *PodReconciler) MinimumUptimeOfPodInParent(pod corev1.Pod, ctx context.C return overAllLength != 0 } -func (r *PodReconciler) GetPodParentKind(pod corev1.Pod, ctx context.Context) (error, *v1.PodSpec, interface{}, string) { +func (r *PodReconciler) GetPodParentKind(pod corev1.Pod, ctx context.Context) (*v1.PodSpec, interface{}, string, error) { if len(pod.OwnerReferences) > 0 { switch pod.OwnerReferences[0].Kind { case "ReplicaSet": replica, err := r.ClientSet.AppsV1().ReplicaSets(pod.Namespace).Get(ctx, pod.OwnerReferences[0].Name, metav1.GetOptions{}) if err != nil { log.Error(err, err.Error()) - return err, nil, nil, "" + return nil, nil, "", err } deployment, err := r.ClientSet.AppsV1().Deployments(pod.Namespace).Get(ctx, replica.OwnerReferences[0].Name, metav1.GetOptions{}) if replica.OwnerReferences[0].Kind == "Deployment" { - return err, &deployment.Spec.Template.Spec, deployment, deployment.Name + return &deployment.Spec.Template.Spec, deployment, deployment.Name, err } else { - return errors.New("Is Owned by Unknown CRD"), nil, nil, "" + return nil, nil, "", errors.New("is Owned by Unknown CRD") } case "DaemonSet": deployment, err := r.ClientSet.AppsV1().DaemonSets(pod.Namespace).Get(ctx, pod.OwnerReferences[0].Name, metav1.GetOptions{}) - return err, &deployment.Spec.Template.Spec, deployment, deployment.Name + return &deployment.Spec.Template.Spec, deployment, deployment.Name, err case "StatefulSet": deployment, err := r.ClientSet.AppsV1().StatefulSets(pod.Namespace).Get(ctx, pod.OwnerReferences[0].Name, metav1.GetOptions{}) - return err, &deployment.Spec.Template.Spec, deployment, deployment.Name + return &deployment.Spec.Template.Spec, deployment, deployment.Name, err default: - return errors.New("Is Owned by Unknown CRD"), nil, nil, "" + return nil, nil, "", errors.New("is Owned by Unknown CRD") } } else { - return errors.New("Pod Has No Owner"), nil, nil, "" + return nil, nil, "", errors.New("pod Has No Owner") } } diff --git a/go.mod b/go.mod index 8452e4a..08e4ee7 100644 --- a/go.mod +++ b/go.mod @@ -5,6 +5,7 @@ go 1.19 require ( github.com/go-logr/logr v1.2.3 github.com/go-redis/redis v6.15.9+incompatible + github.com/google/go-github/v50 v50.2.0 github.com/labstack/gommon v0.4.0 k8s.io/api v0.25.0 k8s.io/apimachinery v0.26.0 @@ -16,7 +17,6 @@ require ( require ( github.com/ProtonMail/go-crypto v0.0.0-20230217124315-7d5c6f04bbb8 // indirect github.com/cloudflare/circl v1.1.0 // indirect - github.com/google/go-github/v50 v50.2.0 // indirect github.com/google/go-querystring v1.1.0 // indirect ) @@ -46,8 +46,6 @@ require ( github.com/golang/protobuf v1.5.2 // indirect github.com/google/gnostic v0.5.7-v3refs // indirect github.com/google/go-cmp v0.5.9 // indirect - github.com/google/go-github/v33 v33.0.0 - github.com/google/go-github/v39 v39.2.0 github.com/google/gofuzz v1.1.0 // indirect github.com/google/uuid v1.1.2 // indirect github.com/imdario/mergo v0.3.12 // indirect @@ -73,7 +71,7 @@ require ( go.uber.org/zap v1.21.0 // indirect golang.org/x/crypto v0.7.0 // indirect golang.org/x/net v0.8.0 // indirect - golang.org/x/oauth2 v0.6.0 // indirect + golang.org/x/oauth2 v0.6.0 golang.org/x/sys v0.6.0 // indirect golang.org/x/term v0.6.0 // indirect golang.org/x/text v0.8.0 // indirect @@ -83,7 +81,7 @@ require ( google.golang.org/protobuf v1.28.1 // indirect gopkg.in/inf.v0 v0.9.1 // indirect gopkg.in/yaml.v2 v2.4.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + gopkg.in/yaml.v3 v3.0.1 k8s.io/apiextensions-apiserver v0.25.0 // indirect k8s.io/component-base v0.25.0 // indirect k8s.io/klog/v2 v2.80.1 // indirect diff --git a/go.sum b/go.sum index 14361b7..59db8f8 100644 --- a/go.sum +++ b/go.sum @@ -204,13 +204,8 @@ github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/ github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= -github.com/google/go-github/v33 v33.0.0 h1:qAf9yP0qc54ufQxzwv+u9H0tiVOnPJxo0lI/JXqw3ZM= -github.com/google/go-github/v33 v33.0.0/go.mod h1:GMdDnVZY/2TsWgp/lkYnpSAh6TrzhANBBwm6k6TTEXg= -github.com/google/go-github/v39 v39.2.0 h1:rNNM311XtPOz5rDdsJXAp2o8F67X9FnROXTvto3aSnQ= -github.com/google/go-github/v39 v39.2.0/go.mod h1:C1s8C5aCC9L+JXIYpJM5GYytdX52vC1bLvHEF1IhBrE= github.com/google/go-github/v50 v50.2.0 h1:j2FyongEHlO9nxXLc+LP3wuBSVU9mVxfpdYUexMpIfk= github.com/google/go-github/v50 v50.2.0/go.mod h1:VBY8FB6yPIjrtKhozXv4FQupxKLS6H4m6xFZlT43q8Q= -github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck= github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= @@ -380,11 +375,8 @@ golang.org/x/crypto v0.0.0-20190510104115-cbcb75029529/go.mod h1:yigFU9vqHzYiE8U golang.org/x/crypto v0.0.0-20190605123033-f99c8df09eb5/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= -golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38= -golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= @@ -462,8 +454,6 @@ golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96b golang.org/x/net v0.0.0-20210503060351-7fd8e65b6420/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10 h1:Frnccbp+ok2GkUS2tC84yAq/U9Vg+0sIO7aRL3T4Xnc= -golang.org/x/net v0.3.1-0.20221206200815-1e63c2f08a10/go.mod h1:MBQ8lrhLObU/6UmLb4fmbmk5OcyYmqtbGd/9yIeKjEE= golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= @@ -481,8 +471,6 @@ golang.org/x/oauth2 v0.0.0-20210514164344-f6687ab2804c/go.mod h1:KelEdhl1UZF7XfJ golang.org/x/oauth2 v0.0.0-20210628180205-a41e5a781914/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210805134026-6f1e6394065a/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8 h1:RerP+noqYHUQ8CMRcPlC2nvTa4dcBIjegkuWdcUDuqg= -golang.org/x/oauth2 v0.0.0-20211104180415-d3ed0bb246c8/go.mod h1:KelEdhl1UZF7XfJ4dDtk6s++YSgaE7mD/BuKKDLBl4A= golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw= golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -555,13 +543,9 @@ golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220114195835-da31bd327af9/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.3.0 h1:w8ZOecv6NaNa/zC8944JTU3vz4u6Lagfk4RPQxv92NQ= -golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= -golang.org/x/term v0.3.0 h1:qoo4akIqOcDME5bhc/NgxUdovd6BSS2uMsVjB56q1xI= -golang.org/x/term v0.3.0/go.mod h1:q750SLmJuPmVoN1blW3UFBPREJfb1KmY3vwxfr+nFDA= golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw= golang.org/x/term v0.6.0/go.mod h1:m6U89DPEgQRMq3DNkDClhWw02AUbt2daBVO4cn4Hv9U= golang.org/x/text v0.0.0-20170915032832-14c0d48ead0c/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -572,8 +556,6 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= -golang.org/x/text v0.5.0 h1:OLmvp0KP+FVG99Ct/qFiL/Fhk4zp4QQnZ7b2U+5piUM= -golang.org/x/text v0.5.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/time v0.0.0-20181108054448-85acf8d2951c/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= diff --git a/pkg/git/client.go b/pkg/git/client.go index 1d17b42..5a3b6e0 100644 --- a/pkg/git/client.go +++ b/pkg/git/client.go @@ -1,20 +1,21 @@ -package kubegit +package git import ( "context" "fmt" - "net/http" "os" "path/filepath" "github.com/google/go-github/v50/github" "github.com/jatalocks/kube-reqsizer/types" + "golang.org/x/oauth2" "gopkg.in/yaml.v3" "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" ) -func UpdateContainerRequestsInFile(filePath string, containerReqs []types.NewContainerRequests, ghToken, owner, repo string) error { +func UpdateContainerRequestsInFile(filePath string, containerReqs []types.NewContainerRequests, owner, repo string) error { // Read the YAML file and unmarshal it into an unstructured object + ctx := context.Background() file, err := os.ReadFile(filePath) if err != nil { return fmt.Errorf("failed to read file: %v", err) @@ -62,8 +63,11 @@ func UpdateContainerRequestsInFile(filePath string, containerReqs []types.NewCon prBody := fmt.Sprintf("Update resource requests for %d containers in file %q", len(containerReqs), filePath) head := fmt.Sprintf("%s:%s", owner, filepath.Base(filePath)) base := "main" - client := github.NewClient(&http.Client{}) - ctx := context.Background() + ts := oauth2.StaticTokenSource( + &oauth2.Token{AccessToken: os.Getenv("GITHUB_TOKEN")}, + ) + tc := oauth2.NewClient(ctx, ts) + client := github.NewClient(tc) pullRequests, _, err := client.PullRequests.List(ctx, owner, repo, nil) if err != nil { return fmt.Errorf("failed to list pull requests: %v", err) From 16adabef3244e051e29236f92ec3658c40fc833e Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:08:42 +0300 Subject: [PATCH 08/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 114 ++++++++++++---------------------- 1 file changed, 38 insertions(+), 76 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index a84454c..24a172c 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -224,95 +224,51 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } } } - if (SumPodRequest.Sample >= r.SampleSize) && r.MinimumUptimeOfPodInParent(pod, ctx) { - log.Info("Sample Size and Minimum Time have been reached") - PodChange := false - Requests := []types.NewContainerRequests{} + if SumPodRequest.Sample >= r.SampleSize && r.MinimumUptimeOfPodInParent(pod, ctx) { + PodChange, Requests := false, []types.NewContainerRequests{} for _, c := range SumPodRequest.ContainerRequests { - AverageUsageCPU := c.CPU / int64(SumPodRequest.Sample) - AverageUsageMemory := c.Memory / int64(SumPodRequest.Sample) - PodRequestsData := GetPodRequests(pod) - for _, currentC := range PodRequestsData.ContainerRequests { - if currentC.Name == c.Name { - for i, v := range pod.Spec.Containers { - if v.Name == c.Name { - if AverageUsageCPU < r.MinCPU && (r.MinCPU > 0) { - AverageUsageCPU = r.MinCPU - } - if AverageUsageCPU > r.MaxCPU && (r.MaxCPU > 0) { - AverageUsageCPU = r.MaxCPU - } - if AverageUsageMemory < r.MinMemory && (r.MinMemory > 0) { - AverageUsageMemory = r.MinMemory - } - if AverageUsageMemory > r.MaxMemory && (r.MaxMemory > 0) { - AverageUsageMemory = r.MaxMemory - } - log.Info(fmt.Sprint(c.Name, " Comparing CPU: ", fmt.Sprintf("%dm", AverageUsageCPU), " <> ", fmt.Sprintf("%dm", currentC.CPU))) - log.Info(fmt.Sprint(c.Name, " Comparing Memory: ", fmt.Sprintf("%dMi", AverageUsageMemory), " <> ", fmt.Sprintf("%dMi", currentC.Memory))) - if pod.Spec.Containers[i].Resources.Requests != nil { - switch r.GetPodMode(pod, ctx) { - case "average": - if r.ValidateCPU(currentC.CPU, AverageUsageCPU) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(AverageUsageCPU)*r.CPUFactor))) - cpuOffset.Add(float64(int(float64(AverageUsageCPU)*r.CPUFactor) - int(currentC.CPU))) - PodChange = true - } - if r.ValidateMemory(currentC.Memory, AverageUsageMemory) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(AverageUsageMemory)*r.MemoryFactor))) - memoryOffset.Add(float64(int(float64(AverageUsageMemory)*r.MemoryFactor) - int(currentC.Memory))) - PodChange = true - } - case "min": - if r.ValidateCPU(currentC.CPU, c.MinCPU) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinCPU)*r.CPUFactor))) - cpuOffset.Add(float64(int(float64(c.MinCPU)*r.CPUFactor) - int(currentC.CPU))) - PodChange = true - } - if r.ValidateMemory(currentC.Memory, c.MinMemory) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MinMemory)*r.MemoryFactor))) - memoryOffset.Add(float64(int(float64(c.MinMemory)*r.MemoryFactor) - int(currentC.Memory))) - PodChange = true - } - case "max": - if r.ValidateCPU(currentC.CPU, c.MaxCPU) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxCPU)*r.CPUFactor))) - cpuOffset.Add(float64(int(float64(c.MaxCPU)*r.CPUFactor) - int(currentC.CPU))) - PodChange = true - } - if r.ValidateMemory(currentC.Memory, c.MaxMemory) { - pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MaxMemory)*r.MemoryFactor))) - memoryOffset.Add(float64(int(float64(c.MaxMemory)*r.MemoryFactor) - int(currentC.Memory))) - PodChange = true - } - } - } - - Requests = append(Requests, types.NewContainerRequests{Name: c.Name, Requests: pod.Spec.Containers[i].Resources}) + AvgCPU, AvgMem := c.CPU/int64(SumPodRequest.Sample), c.Memory/int64(SumPodRequest.Sample) + for _, currentC := range GetPodRequests(pod).ContainerRequests { + if currentC.Name != c.Name { + continue + } + for i, v := range pod.Spec.Containers { + if v.Name != c.Name || pod.Spec.Containers[i].Resources.Requests == nil { + continue + } + var cpuReq, memReq resource.Quantity + switch r.GetPodMode(pod, ctx) { + case "average": + if !r.ValidateCPU(currentC.CPU, AvgCPU) || !r.ValidateMemory(currentC.Memory, AvgMem) { + continue + } + cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(AvgCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(AvgMem)*r.MemoryFactor))) + case "min": + if !r.ValidateCPU(currentC.CPU, c.MinCPU) || !r.ValidateMemory(currentC.Memory, c.MinMemory) { + continue } + cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MinMemory)*r.MemoryFactor))) + case "max": + if !r.ValidateCPU(currentC.CPU, c.MaxCPU) || !r.ValidateMemory(currentC.Memory, c.MaxMemory) { + continue + } + cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MaxMemory)*r.MemoryFactor))) } + pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU], pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = cpuReq, memReq + Requests, PodChange = append(Requests, types.NewContainerRequests{Name: c.Name, Requests: pod.Spec.Containers[i].Resources}), true } } } if r.EnablePersistence { - if err := r.RedisClient.DeleteFromCache(SumPodRequest); err != nil { - log.Error(err, err.Error()) - } + r.RedisClient.DeleteFromCache(SumPodRequest) } else { - if err := localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { - log.Error(err, err.Error()) - } + localcache.DeleteFromCache(cacheStore, LatestPodRequest) } if PodChange { pod.Annotations["reqsizer.jatalocks.github.io/changed"] = "true" - - log.Info("Pod Requests Will Change") - if len(pod.OwnerReferences) == 0 { - log.Info("Pod has no owner") return r.UpdateKubeObject(&pod, ctx) } - podSpec, deployment, _, err := r.GetPodParentKind(pod, ctx) if err != nil { return ctrl.Result{}, err @@ -322,10 +278,16 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return r.UpdateKubeObject(deployment.(client.Object), ctx) } if r.GithubMode { - git.UpdateContainerRequestsInFile(pod.Annotations["reqsizer.jatalocks.github.io/github/path"], Requests, pod.Annotations["reqsizer.jatalocks.github.io/github/repo"], pod.Annotations["reqsizer.jatalocks.github.io/github/owner"]) + path, pathExists := pod.Annotations["reqsizer.jatalocks.github.io/github/path"] + repo, repoExists := pod.Annotations["reqsizer.jatalocks.github.io/github/repo"] + owner, ownerExists := pod.Annotations["reqsizer.jatalocks.github.io/github/owner"] + if pathExists && repoExists && ownerExists { + git.UpdateContainerRequestsInFile(path, Requests, repo, owner) + } } } } + } return ctrl.Result{RequeueAfter: 5 * time.Second}, nil From 770a4e191369a49b32d02d90471156bf4b797cb1 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:18:14 +0300 Subject: [PATCH 09/18] :pencil2: f modified: .github/workflows/lint.yml --- .github/workflows/lint.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index c2aba58..0da42df 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,6 +23,7 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: v1.50.0 - args: -c .golang-ci.yml -v --timeout=5m + # args: -c .golang-ci.yml -v --timeout=5m + args: -v --timeout=5m env: GO111MODULES: off \ No newline at end of file From 766da6545ff2e48520f09f75b3d9dc7fd4cfbefb Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:29:21 +0300 Subject: [PATCH 10/18] :pencil2: f modified: .github/workflows/lint.yml; modified: .github/workflows/test.yml; modified: controllers/pod_controller.go; modified: pkg/cache/localcache/localcache.go; modified: pkg/cache/rediscache/rediscache.go --- .github/workflows/lint.yml | 2 +- .github/workflows/test.yml | 50 ++++++------ controllers/pod_controller.go | 119 ++++++++++++++++++++--------- pkg/cache/localcache/localcache.go | 5 +- pkg/cache/rediscache/rediscache.go | 8 +- 5 files changed, 114 insertions(+), 70 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 0da42df..57822f1 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -1,6 +1,6 @@ name: golangci-lint -on: [push, pull_request] +on: [pull_request] jobs: golangci: diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index addb075..850e3ee 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -1,34 +1,34 @@ -name: Test and coverage +# name: Test and coverage -on: [push, pull_request] +# on: [pull_request] -jobs: - test: - strategy: - matrix: - go-version: [1.19.x] - os: [ubuntu-latest, macos-latest] +# jobs: +# test: +# strategy: +# matrix: +# go-version: [1.19.x] +# os: [ubuntu-latest, macos-latest] - runs-on: ${{ matrix.os }} +# runs-on: ${{ matrix.os }} - steps: - - uses: actions/checkout@v3 - with: - fetch-depth: 2 +# steps: +# - uses: actions/checkout@v3 +# with: +# fetch-depth: 2 - - uses: actions/setup-go@v2 - with: - go-version: ${{ matrix.go-version }} +# - uses: actions/setup-go@v2 +# with: +# go-version: ${{ matrix.go-version }} - - name: go get - run: go get ./... +# - name: go get +# run: go get ./... - - name: go mod tidy - run: go mod tidy +# - name: go mod tidy +# run: go mod tidy - - name: Run coverage - run: go test -race -coverprofile=coverage.out -covermode=atomic ./... +# - name: Run coverage +# run: go test -race -coverprofile=coverage.out -covermode=atomic ./... - - name: Upload coverage to Codecov - if: matrix.os == 'ubuntu-latest' - run: bash <(curl -s https://codecov.io/bash) \ No newline at end of file +# - name: Upload coverage to Codecov +# if: matrix.os == 'ubuntu-latest' +# run: bash <(curl -s https://codecov.io/bash) \ No newline at end of file diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 24a172c..53f6cd0 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -224,51 +224,95 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } } } - if SumPodRequest.Sample >= r.SampleSize && r.MinimumUptimeOfPodInParent(pod, ctx) { - PodChange, Requests := false, []types.NewContainerRequests{} + if (SumPodRequest.Sample >= r.SampleSize) && r.MinimumUptimeOfPodInParent(pod, ctx) { + log.Info("Sample Size and Minimum Time have been reached") + PodChange := false + Requests := []types.NewContainerRequests{} for _, c := range SumPodRequest.ContainerRequests { - AvgCPU, AvgMem := c.CPU/int64(SumPodRequest.Sample), c.Memory/int64(SumPodRequest.Sample) - for _, currentC := range GetPodRequests(pod).ContainerRequests { - if currentC.Name != c.Name { - continue - } - for i, v := range pod.Spec.Containers { - if v.Name != c.Name || pod.Spec.Containers[i].Resources.Requests == nil { - continue - } - var cpuReq, memReq resource.Quantity - switch r.GetPodMode(pod, ctx) { - case "average": - if !r.ValidateCPU(currentC.CPU, AvgCPU) || !r.ValidateMemory(currentC.Memory, AvgMem) { - continue - } - cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(AvgCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(AvgMem)*r.MemoryFactor))) - case "min": - if !r.ValidateCPU(currentC.CPU, c.MinCPU) || !r.ValidateMemory(currentC.Memory, c.MinMemory) { - continue - } - cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MinMemory)*r.MemoryFactor))) - case "max": - if !r.ValidateCPU(currentC.CPU, c.MaxCPU) || !r.ValidateMemory(currentC.Memory, c.MaxMemory) { - continue + AverageUsageCPU := c.CPU / int64(SumPodRequest.Sample) + AverageUsageMemory := c.Memory / int64(SumPodRequest.Sample) + PodRequestsData := GetPodRequests(pod) + for _, currentC := range PodRequestsData.ContainerRequests { + if currentC.Name == c.Name { + for i, v := range pod.Spec.Containers { + if v.Name == c.Name { + if AverageUsageCPU < r.MinCPU && (r.MinCPU > 0) { + AverageUsageCPU = r.MinCPU + } + if AverageUsageCPU > r.MaxCPU && (r.MaxCPU > 0) { + AverageUsageCPU = r.MaxCPU + } + if AverageUsageMemory < r.MinMemory && (r.MinMemory > 0) { + AverageUsageMemory = r.MinMemory + } + if AverageUsageMemory > r.MaxMemory && (r.MaxMemory > 0) { + AverageUsageMemory = r.MaxMemory + } + log.Info(fmt.Sprint(c.Name, " Comparing CPU: ", fmt.Sprintf("%dm", AverageUsageCPU), " <> ", fmt.Sprintf("%dm", currentC.CPU))) + log.Info(fmt.Sprint(c.Name, " Comparing Memory: ", fmt.Sprintf("%dMi", AverageUsageMemory), " <> ", fmt.Sprintf("%dMi", currentC.Memory))) + if pod.Spec.Containers[i].Resources.Requests != nil { + switch r.GetPodMode(pod, ctx) { + case "average": + if r.ValidateCPU(currentC.CPU, AverageUsageCPU) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(AverageUsageCPU)*r.CPUFactor))) + cpuOffset.Add(float64(int(float64(AverageUsageCPU)*r.CPUFactor) - int(currentC.CPU))) + PodChange = true + } + if r.ValidateMemory(currentC.Memory, AverageUsageMemory) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(AverageUsageMemory)*r.MemoryFactor))) + memoryOffset.Add(float64(int(float64(AverageUsageMemory)*r.MemoryFactor) - int(currentC.Memory))) + PodChange = true + } + case "min": + if r.ValidateCPU(currentC.CPU, c.MinCPU) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MinCPU)*r.CPUFactor))) + cpuOffset.Add(float64(int(float64(c.MinCPU)*r.CPUFactor) - int(currentC.CPU))) + PodChange = true + } + if r.ValidateMemory(currentC.Memory, c.MinMemory) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MinMemory)*r.MemoryFactor))) + memoryOffset.Add(float64(int(float64(c.MinMemory)*r.MemoryFactor) - int(currentC.Memory))) + PodChange = true + } + case "max": + if r.ValidateCPU(currentC.CPU, c.MaxCPU) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU] = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxCPU)*r.CPUFactor))) + cpuOffset.Add(float64(int(float64(c.MaxCPU)*r.CPUFactor) - int(currentC.CPU))) + PodChange = true + } + if r.ValidateMemory(currentC.Memory, c.MaxMemory) { + pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MaxMemory)*r.MemoryFactor))) + memoryOffset.Add(float64(int(float64(c.MaxMemory)*r.MemoryFactor) - int(currentC.Memory))) + PodChange = true + } + } + } + + Requests = append(Requests, types.NewContainerRequests{Name: c.Name, Requests: pod.Spec.Containers[i].Resources}) } - cpuReq, memReq = resource.MustParse(fmt.Sprintf("%dm", int(float64(c.MaxCPU)*r.CPUFactor))), resource.MustParse(fmt.Sprintf("%dMi", int(float64(c.MaxMemory)*r.MemoryFactor))) } - pod.Spec.Containers[i].Resources.Requests[v1.ResourceCPU], pod.Spec.Containers[i].Resources.Requests[v1.ResourceMemory] = cpuReq, memReq - Requests, PodChange = append(Requests, types.NewContainerRequests{Name: c.Name, Requests: pod.Spec.Containers[i].Resources}), true } } } if r.EnablePersistence { - r.RedisClient.DeleteFromCache(SumPodRequest) + if err := r.RedisClient.DeleteFromCache(SumPodRequest); err != nil { + log.Error(err, err.Error()) + } } else { - localcache.DeleteFromCache(cacheStore, LatestPodRequest) + if err := localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { + log.Error(err, err.Error()) + } } if PodChange { pod.Annotations["reqsizer.jatalocks.github.io/changed"] = "true" + + log.Info("Pod Requests Will Change") + if len(pod.OwnerReferences) == 0 { + log.Info("Pod has no owner") return r.UpdateKubeObject(&pod, ctx) } + podSpec, deployment, _, err := r.GetPodParentKind(pod, ctx) if err != nil { return ctrl.Result{}, err @@ -278,16 +322,19 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R return r.UpdateKubeObject(deployment.(client.Object), ctx) } if r.GithubMode { - path, pathExists := pod.Annotations["reqsizer.jatalocks.github.io/github/path"] - repo, repoExists := pod.Annotations["reqsizer.jatalocks.github.io/github/repo"] - owner, ownerExists := pod.Annotations["reqsizer.jatalocks.github.io/github/owner"] + path, pathExists := pod.Annotations["reqsizer.jatalocks.github.io/github.path"] + repo, repoExists := pod.Annotations["reqsizer.jatalocks.github.io/github.repo"] + owner, ownerExists := pod.Annotations["reqsizer.jatalocks.github.io/github.owner"] if pathExists && repoExists && ownerExists { - git.UpdateContainerRequestsInFile(path, Requests, repo, owner) + if err := git.UpdateContainerRequestsInFile(path, Requests, repo, owner); err != nil { + log.Error(err, err.Error()) + } } + } else { + log.Info("Pod is missing github annotations") } } } - } return ctrl.Result{RequeueAfter: 5 * time.Second}, nil diff --git a/pkg/cache/localcache/localcache.go b/pkg/cache/localcache/localcache.go index db23eae..8376f6d 100644 --- a/pkg/cache/localcache/localcache.go +++ b/pkg/cache/localcache/localcache.go @@ -2,17 +2,16 @@ package localcache import ( "errors" + "fmt" "github.com/jatalocks/kube-reqsizer/types" "k8s.io/client-go/tools/cache" - "k8s.io/klog" ) func AddToCache(cacheStore cache.Store, object types.PodRequests) error { err := cacheStore.Add(object) if err != nil { - klog.Errorf("failed to add key value to cache error", err) - return err + return fmt.Errorf("failed to add key value to cache error %v", err) } return nil } diff --git a/pkg/cache/rediscache/rediscache.go b/pkg/cache/rediscache/rediscache.go index 63f2514..9ca7634 100644 --- a/pkg/cache/rediscache/rediscache.go +++ b/pkg/cache/rediscache/rediscache.go @@ -2,10 +2,10 @@ package rediscache import ( "encoding/json" + "fmt" "github.com/go-redis/redis" "github.com/jatalocks/kube-reqsizer/types" - "k8s.io/klog" ) type RedisClient struct { @@ -15,13 +15,11 @@ type RedisClient struct { func (client RedisClient) AddToCache(object types.PodRequests) error { val, err := json.Marshal(object) if err != nil { - klog.Errorf("failed to add key value to cache error", err) - return err + return fmt.Errorf("failed to add key value to cache error %v", err) } err = client.Client.Set(object.Name, val, 0).Err() if err != nil { - klog.Errorf("failed to add key value to cache error", err) - return err + return fmt.Errorf("failed to add key value to cache error %v", err) } return nil } From f879b464979b7bb6373f34fe7beace846a307a7d Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:35:16 +0300 Subject: [PATCH 11/18] :pencil2: f modified: charts/kube-reqsizer/templates/deployment.yaml; modified: charts/kube-reqsizer/values.yaml --- charts/kube-reqsizer/templates/deployment.yaml | 4 ++++ charts/kube-reqsizer/values.yaml | 4 ++++ 2 files changed, 8 insertions(+) diff --git a/charts/kube-reqsizer/templates/deployment.yaml b/charts/kube-reqsizer/templates/deployment.yaml index 7ad4c75..4dc5dad 100644 --- a/charts/kube-reqsizer/templates/deployment.yaml +++ b/charts/kube-reqsizer/templates/deployment.yaml @@ -27,6 +27,8 @@ spec: - --metrics-bind-address=:8080 - --leader-elect - --annotation-filter={{.Values.enabledAnnotation}} + - --github-mode={{.Values.githubMode.enabled}} + - --verbose-mode={{.Values.verboseMode}} - --sample-size={{.Values.sampleSize}} - --min-seconds={{.Values.minSeconds}} - --zap-log-level={{.Values.logLevel}} @@ -52,6 +54,8 @@ spec: env: - name: KUBERNETES_CLUSTER_DOMAIN value: {{ .Values.kubernetesClusterDomain }} + - name: GITHUB_TOKEN + value: {{ .Values.githubMode.token }} ports: - name: metrics containerPort: {{ .Values.metricsService.port }} diff --git a/charts/kube-reqsizer/values.yaml b/charts/kube-reqsizer/values.yaml index b24a215..f206be2 100644 --- a/charts/kube-reqsizer/values.yaml +++ b/charts/kube-reqsizer/values.yaml @@ -1,4 +1,8 @@ enabledAnnotation: true +githubMode: + enabled: false + token: ghp_abc123 +verboseMode: false sampleSize: 1 minSeconds: 1 enableIncrease: true From a51bdbcb751241654b49159f676021b8c1334242 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:38:58 +0300 Subject: [PATCH 12/18] :pencil2: f modified: .github/workflows/lint.yml --- .github/workflows/lint.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 57822f1..6f782fa 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -23,7 +23,8 @@ jobs: uses: golangci/golangci-lint-action@v3 with: version: v1.50.0 - # args: -c .golang-ci.yml -v --timeout=5m - args: -v --timeout=5m + args: --timeout=10m + skip-pkg-cache: true + skip-build-cache: true env: GO111MODULES: off \ No newline at end of file From 1ca4df1b5c2940a6ac28cfc5f50fa70c0349a170 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Sun, 26 Mar 2023 23:58:46 +0300 Subject: [PATCH 13/18] :pencil2: f modified: controllers/pod_controller.go; modified: controllers/pod_controller_functions.go --- controllers/pod_controller.go | 4 ++-- controllers/pod_controller_functions.go | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 53f6cd0..ffa094d 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -209,14 +209,14 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } if r.EnablePersistence { - if err := r.RedisClient.DeleteFromCache(LatestPodRequest); err != nil { + if err = r.RedisClient.DeleteFromCache(LatestPodRequest); err != nil { log.Error(err, err.Error()) } if err = r.RedisClient.AddToCache(SumPodRequest); err != nil { log.Error(err, err.Error()) } } else { - if err := localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { + if err = localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { log.Error(err, err.Error()) } if err = localcache.AddToCache(cacheStore, SumPodRequest); err != nil { diff --git a/controllers/pod_controller_functions.go b/controllers/pod_controller_functions.go index 4021da4..86c988b 100644 --- a/controllers/pod_controller_functions.go +++ b/controllers/pod_controller_functions.go @@ -4,6 +4,7 @@ import ( "context" "encoding/json" "errors" + "fmt" "strconv" "strings" "time" @@ -178,7 +179,10 @@ func GetPodRequests(pod corev1.Pod) types.PodRequests { func GeneratePodRequestsObjectFromRestData(restData []byte) types.PodRequests { s := restData[:] data := types.PodMetricsRestData{} - json.Unmarshal([]byte(s), &data) + err := json.Unmarshal([]byte(s), &data) + if err != nil { + fmt.Println(err.Error()) + } containerData := []types.ContainerRequests{} for _, c := range data.Containers { nanoCores, _ := strconv.Atoi(RemoveLastChar(c.Usage.CPU)) From 286bd14a5a49896c8d33ea8585eedad4048184a2 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Mon, 27 Mar 2023 00:06:07 +0300 Subject: [PATCH 14/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index ffa094d..912b13c 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -209,17 +209,21 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } if r.EnablePersistence { - if err = r.RedisClient.DeleteFromCache(LatestPodRequest); err != nil { + r.RedisClient.DeleteFromCache(LatestPodRequest) + if err != nil { log.Error(err, err.Error()) } - if err = r.RedisClient.AddToCache(SumPodRequest); err != nil { + r.RedisClient.AddToCache(SumPodRequest) + if err != nil { log.Error(err, err.Error()) } } else { - if err = localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { + localcache.DeleteFromCache(cacheStore, LatestPodRequest) + if err != nil { log.Error(err, err.Error()) } - if err = localcache.AddToCache(cacheStore, SumPodRequest); err != nil { + localcache.AddToCache(cacheStore, SumPodRequest) + if err != nil { log.Error(err, err.Error()) } } From b4f32db4c43dc927149ba71a1a7851792d28ef11 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Mon, 27 Mar 2023 00:07:30 +0300 Subject: [PATCH 15/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 912b13c..d3219ff 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -209,20 +209,20 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } if r.EnablePersistence { - r.RedisClient.DeleteFromCache(LatestPodRequest) + err := r.RedisClient.DeleteFromCache(LatestPodRequest) if err != nil { log.Error(err, err.Error()) } - r.RedisClient.AddToCache(SumPodRequest) + err = r.RedisClient.AddToCache(SumPodRequest) if err != nil { log.Error(err, err.Error()) } } else { - localcache.DeleteFromCache(cacheStore, LatestPodRequest) + err := localcache.DeleteFromCache(cacheStore, LatestPodRequest) if err != nil { log.Error(err, err.Error()) } - localcache.AddToCache(cacheStore, SumPodRequest) + err = localcache.AddToCache(cacheStore, SumPodRequest) if err != nil { log.Error(err, err.Error()) } From 124ab63f49b41cf3a60ee43154b60ab871242e7a Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Mon, 27 Mar 2023 00:13:46 +0300 Subject: [PATCH 16/18] :pencil2: f modified: controllers/pod_controller.go; modified: go.mod; modified: pkg/cache/localcache/localcache.go; modified: pkg/cache/rediscache/rediscache.go --- controllers/pod_controller.go | 12 ++++-------- go.mod | 1 - pkg/cache/localcache/localcache.go | 7 +------ pkg/cache/rediscache/rediscache.go | 6 +----- 4 files changed, 6 insertions(+), 20 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index d3219ff..2189576 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -209,21 +209,17 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R } if r.EnablePersistence { - err := r.RedisClient.DeleteFromCache(LatestPodRequest) - if err != nil { + if err := r.RedisClient.DeleteFromCache(LatestPodRequest); err != nil { log.Error(err, err.Error()) } - err = r.RedisClient.AddToCache(SumPodRequest) - if err != nil { + if err := r.RedisClient.AddToCache(SumPodRequest); err != nil { log.Error(err, err.Error()) } } else { - err := localcache.DeleteFromCache(cacheStore, LatestPodRequest) - if err != nil { + if err := localcache.DeleteFromCache(cacheStore, LatestPodRequest); err != nil { log.Error(err, err.Error()) } - err = localcache.AddToCache(cacheStore, SumPodRequest) - if err != nil { + if err := localcache.AddToCache(cacheStore, SumPodRequest); err != nil { log.Error(err, err.Error()) } } diff --git a/go.mod b/go.mod index 858b261..680df18 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( k8s.io/api v0.25.0 k8s.io/apimachinery v0.26.0 k8s.io/client-go v0.25.0 - k8s.io/klog v1.0.0 sigs.k8s.io/controller-runtime v0.13.1 ) diff --git a/pkg/cache/localcache/localcache.go b/pkg/cache/localcache/localcache.go index 8376f6d..2f01de3 100644 --- a/pkg/cache/localcache/localcache.go +++ b/pkg/cache/localcache/localcache.go @@ -2,18 +2,13 @@ package localcache import ( "errors" - "fmt" "github.com/jatalocks/kube-reqsizer/types" "k8s.io/client-go/tools/cache" ) func AddToCache(cacheStore cache.Store, object types.PodRequests) error { - err := cacheStore.Add(object) - if err != nil { - return fmt.Errorf("failed to add key value to cache error %v", err) - } - return nil + return cacheStore.Add(object) } func FetchFromCache(cacheStore cache.Store, key string) (types.PodRequests, error) { diff --git a/pkg/cache/rediscache/rediscache.go b/pkg/cache/rediscache/rediscache.go index 9ca7634..264c46d 100644 --- a/pkg/cache/rediscache/rediscache.go +++ b/pkg/cache/rediscache/rediscache.go @@ -17,11 +17,7 @@ func (client RedisClient) AddToCache(object types.PodRequests) error { if err != nil { return fmt.Errorf("failed to add key value to cache error %v", err) } - err = client.Client.Set(object.Name, val, 0).Err() - if err != nil { - return fmt.Errorf("failed to add key value to cache error %v", err) - } - return nil + return client.Client.Set(object.Name, val, 0).Err() } func (client RedisClient) FetchFromCache(key string) (types.PodRequests, error) { From be29de77e40008f3d73db179704ea92bda3e2fd9 Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Mon, 27 Mar 2023 00:16:00 +0300 Subject: [PATCH 17/18] :pencil2: f modified: .github/workflows/lint.yml --- .github/workflows/lint.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 6f782fa..23bb450 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -22,7 +22,7 @@ jobs: - name: golangci-lint uses: golangci/golangci-lint-action@v3 with: - version: v1.50.0 + version: latest args: --timeout=10m skip-pkg-cache: true skip-build-cache: true From 0ccc517446441d0d6acc56e03059ef3ea8a2808b Mon Sep 17 00:00:00 2001 From: Amitai Getzler Date: Mon, 27 Mar 2023 00:20:31 +0300 Subject: [PATCH 18/18] :pencil2: f modified: controllers/pod_controller.go --- controllers/pod_controller.go | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/controllers/pod_controller.go b/controllers/pod_controller.go index 2189576..9b8c4e1 100644 --- a/controllers/pod_controller.go +++ b/controllers/pod_controller.go @@ -168,10 +168,14 @@ func (r *PodReconciler) Reconcile(ctx context.Context, req ctrl.Request) (ctrl.R SumPodRequest.Sample = 0 log.Info(fmt.Sprint("Adding cache sample ", SumPodRequest.Sample)) if r.EnablePersistence { - r.RedisClient.AddToCache(SumPodRequest) + if err := r.RedisClient.AddToCache(SumPodRequest); err != nil { + log.Error(err, err.Error()) + } log.Info(fmt.Sprint("Items in Cache: ", r.RedisClient.CacheSize())) } else { - localcache.AddToCache(cacheStore, SumPodRequest) + if err := localcache.AddToCache(cacheStore, SumPodRequest); err != nil { + log.Error(err, err.Error()) + } log.Info(fmt.Sprint("Items in Cache: ", len(cacheStore.List()))) } } else {