k8s: use patch to add annotations to avoid race (#106)

* upgrade kubernetes client

* cleanup provider helpers

* use kubernetes patch to avoid update races
This commit is contained in:
David Dollar 2020-01-31 10:12:26 -05:00 committed by GitHub
parent f5fa1a643e
commit 282b4ee88e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
985 changed files with 126195 additions and 67976 deletions

17
go.mod
View File

@ -25,18 +25,14 @@ require (
github.com/convox/version v0.0.0-20160822184233-ffefa0d565d2
github.com/creack/pty v1.1.9
github.com/docker/docker v1.4.2-0.20190710153559-aa8249ae1b8b
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96 // indirect
github.com/dustin/go-humanize v1.0.0
github.com/elastic/go-elasticsearch/v6 v6.8.2
github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e // indirect
github.com/fsouza/go-dockerclient v1.4.2
github.com/go-redis/redis v6.15.2+incompatible
github.com/gobuffalo/packr v1.30.1
github.com/gobwas/glob v0.2.3
github.com/golang/groupcache v0.0.0-20160516000752-02826c3e7903 // indirect
github.com/gorilla/mux v1.7.3
github.com/gorilla/websocket v1.4.0
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 // indirect
github.com/headzoo/surf v1.0.0
github.com/headzoo/ut v0.0.0-20181013193318-a13b5a7a02ca // indirect
github.com/imdario/mergo v0.3.7 // indirect
@ -44,21 +40,16 @@ require (
github.com/karalabe/xgo v0.0.0-20191115072854-c5ccff8648a7
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
github.com/miekg/dns v1.1.15
github.com/onsi/ginkgo v1.8.0 // indirect
github.com/onsi/gomega v1.5.0 // indirect
github.com/peterbourgon/diskv v2.0.1+incompatible // indirect
github.com/pkg/errors v0.8.1
github.com/stretchr/testify v1.3.0
github.com/vektra/mockery v0.0.0-20181123154057-e78b021dcbb5
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 // indirect
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 // indirect
golang.org/x/time v0.0.0-20190308202827-9d24e82272b4 // indirect
google.golang.org/api v0.9.0
gopkg.in/inf.v0 v0.9.0 // indirect
gopkg.in/yaml.v2 v2.2.4
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841
k8s.io/client-go v0.0.0-20190117233410-4022682532b3
k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd
k8s.io/api v0.16.6
k8s.io/apimachinery v0.16.6
k8s.io/client-go v0.16.6
k8s.io/code-generator v0.16.6
)

52
go.sum
View File

@ -137,6 +137,8 @@ github.com/elazarl/goproxy v0.0.0-20170405201442-c4fc26588b6e/go.mod h1:/Zj4wYkg
github.com/emicklei/go-restful v0.0.0-20170410110728-ff4f55a20633/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/emicklei/go-restful v2.9.5+incompatible h1:spTtZBk5DYEvbxMVutUuTyh1Ao2r4iyvLdACqsl/Ljk=
github.com/emicklei/go-restful v2.9.5+incompatible/go.mod h1:otzb+WCGbkyDHkqmQmT5YD2WR4BBwUdeQoFo8l/7tVs=
github.com/evanphx/json-patch v4.2.0+incompatible h1:fUDGZCv/7iAN7u0puUVhvKCcsR6vRfwrJatElLBEf0I=
github.com/evanphx/json-patch v4.2.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0 h1:DkWD4oS2D8LGGgTQ6IvwJJXSL5Vp2ffcQg58nFV38Ys=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/fatih/structs v1.0.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M=
@ -151,6 +153,8 @@ github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7
github.com/go-openapi/jsonpointer v0.0.0-20160704185906-46af16f9f7b1/go.mod h1:+35s3my2LFTysnkMfxsJBAMHj/DoqoB9knIWoYG/Vk0=
github.com/go-openapi/jsonpointer v0.19.2 h1:A9+F4Dc/MCNB5jibxf6rRvOvR/iFgQdyNx9eIhnGqq0=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3 h1:gihV7YNZK1iK6Tgwwsxo2rJbD1GTbdm72325Bq8FI3w=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.0.0-20160704190145-13c6e3589ad9/go.mod h1:W3Z9FmVs9qj+KR4zFKmDPGiLdk1D9Rlm7cyMvf57TTg=
github.com/go-openapi/jsonreference v0.19.2 h1:o20suLFB4Ri0tuzpWtyHlh7E7HnkqTNLq6aR6WVNS1w=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
@ -160,6 +164,8 @@ github.com/go-openapi/spec v0.19.2/go.mod h1:sCxk3jxKgioEJikev4fgkNmwS+3kuYdJtcs
github.com/go-openapi/swag v0.0.0-20160704191624-1d0bd113de87/go.mod h1:DXUve3Dpr1UfpPtxFw+EFuQ41HhCWZfha5jSVRG7C7I=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-redis/redis v6.15.2+incompatible h1:9SpNVG76gr6InJGxoZ6IuuxaCOQwDAhzyXg+Bs+0Sb4=
github.com/go-redis/redis v6.15.2+incompatible/go.mod h1:NAIEuMOZ/fxfXJIrKDQDz8wamY7mA7PouImQ2Jvg6kA=
github.com/go-sql-driver/mysql v1.4.0/go.mod h1:zAC/RDZ24gD3HViQzih4MyKcchzm+sOG5ZlKdlhCg5w=
@ -368,11 +374,13 @@ github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/
github.com/google/martian v2.1.0+incompatible h1:/CP5g8u/VJHijgedC/Legn3BAbAaWPgecwXBIDzw5no=
github.com/google/martian v2.1.0+incompatible/go.mod h1:9I4somxYTbIHy5NJKHRl3wXiIaQGbYVAs8BPL6v8lEs=
github.com/google/pprof v0.0.0-20181206194817-3ea8567a2e57/go.mod h1:zfwlbNMJ+OItoe0UupaVj+oy1omPYYDuagoSzA8v9mc=
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5 h1:sjZBwGj9Jlw33ImPtvFviGYvseOtDM7hkSKB7+Tv3SM=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d h1:7XGaL1e6bYS1yIonGp9761ExpPPV1ui0SAC59Yube9k=
github.com/googleapis/gnostic v0.0.0-20170729233727-0c5108395e2d/go.mod h1:sJBsCZ4ayReDTBIg8b9dl28c5xFWyhBTVRp3pOg5EKY=
github.com/gophercloud/gophercloud v0.1.0/go.mod h1:vxM41WHh5uqHVBMZHzuwNOHh8XEoIEcSTewFxm1c5g8=
github.com/gorilla/context v1.1.1 h1:AWwleXJkX/nhcU9bZSnZoi3h/qGYqQAGhq6zZe/aQW8=
github.com/gorilla/context v1.1.1/go.mod h1:kBGZzfjB9CEq2AlWe17Uuf7NDRt0dE0s8S51q0aT7Yg=
github.com/gorilla/mux v1.6.2/go.mod h1:1lud6UwP+6orDFRuTfBEV8e9/aOM/c4fVVCaMa2zaAs=
@ -387,8 +395,7 @@ github.com/gorilla/sessions v1.1.3 h1:uXoZdcdA5XdXF3QzuSlheVRUvjl+1rKY7zBXL68L9R
github.com/gorilla/sessions v1.1.3/go.mod h1:8KCfur6+4Mqcc6S0FEfKuN15Vl5MgXW92AE8ovaJD0w=
github.com/gorilla/websocket v1.4.0 h1:WDFjx/TMzVgy9VdMMQi2K2Emtwi2QcUQsztZ/zLaH/Q=
github.com/gorilla/websocket v1.4.0/go.mod h1:E7qHFY5m1UJ88s3WnNqhKjPHQ0heANvMoAMk2YaljkQ=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7 h1:6TSoaYExHper8PYsJu23GWVNOyYRCSnIFyxKgLSZ54w=
github.com/gregjones/httpcache v0.0.0-20170728041850-787624de3eb7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/gregjones/httpcache v0.0.0-20180305231024-9cad4c3443a7/go.mod h1:FecbI9+v66THATjSRHfNgh1IVFe/9kFxbXtjV0ctIMA=
github.com/hashicorp/errwrap v0.0.0-20141028054710-7554cd9344ce/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
github.com/hashicorp/go-multierror v0.0.0-20161216184304-ed905158d874/go.mod h1:JMRHfdO9jKNzS/+BTlxCjKNQHg/jZAft8U7LloJvN7I=
github.com/hashicorp/golang-lru v0.5.0/go.mod h1:/m3WP610KZHVQ1SGc6re/UDhFvYD7pJ4Ao+sR/qLZy8=
@ -403,6 +410,7 @@ github.com/hpcloud/tail v1.0.0 h1:nfCOvKYfkgYP8hkirhJocXT2+zOD8yUNjXaWfTlyFKI=
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd h1:anPrsicrIi2ColgWTVPk+TrN42hJIWlfPHSBP9S0ZkM=
github.com/ijc/Gotty v0.0.0-20170406111628-a8b993ba6abd/go.mod h1:3LVOLeyx9XVvwPgrt2be44XgSqndprz1G18rSk8KD84=
github.com/imdario/mergo v0.3.5/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/imdario/mergo v0.3.7 h1:Y+UAYTZ7gDEuOfhxKWy+dvb5dRQ6rJjFSdX2HZY1/gI=
github.com/imdario/mergo v0.3.7/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
github.com/inconshreveable/go-update v0.0.0-20160112193335-8152e7eb6ccf h1:WfD7VjIE6z8dIvMsI4/s+1qr5EL+zoIGev1BQj1eoJ8=
@ -448,6 +456,8 @@ github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czP
github.com/mailru/easyjson v0.0.0-20160728113105-d5b7844b561a/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/markbates/deplist v1.0.4/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
github.com/markbates/deplist v1.0.5/go.mod h1:gRRbPbbuA8TmMiRvaOzUlRfzfjeCCBqX2A6arxN01MM=
github.com/markbates/going v1.0.2/go.mod h1:UWCk3zm0UKefHZ7l8BNqi26UyiEMniznk8naLdTcy6c=
@ -489,6 +499,7 @@ github.com/modern-go/reflect2 v1.0.1 h1:9f412s+6RmYXLWZSEzVVgPGK7C2PphHj5RJrvfx9
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
github.com/monoculum/formam v0.0.0-20180901015400-4e68be1d79ba/go.mod h1:RKgILGEJq24YyJ2ban8EO0RUVSJlF1pGsEvoLEACr/Q=
github.com/munnerz/goautoneg v0.0.0-20120707110453-a547fc61f48d/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw=
github.com/nicksnyder/go-i18n v1.10.0/go.mod h1:HrK7VCrbOvQoUAQ7Vpy7i87N7JZZZ7R2xBGjv0j365Q=
github.com/onsi/ginkgo v0.0.0-20170829012221-11459a886d9c/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
@ -550,6 +561,7 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.0/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.2.0/go.mod h1:r2rcYCSwa1IExKTDiTfzaxqT2FNHs8hODu4LnUfgKEg=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.3/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@ -602,12 +614,14 @@ golang.org/x/crypto v0.0.0-20181127143415-eb0de9b17e85/go.mod h1:6SG95UA2DQfeDnf
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190102171810-8d7daa0c54b3/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190103213133-ff983b9c42bc/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190211182817-74369b46fc67/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190418165655-df01cb2cc480/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20190611184440-5c40567a22f8/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190621222207-cc06ce4a13d4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4 h1:HuIa8hRrWRSrqYzx1qI49NNxhdi2PrY7gxVSq1JjLDc=
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad h1:Jh8cai0fqIK+f6nG0UgPW5wFk8wmiMhM3AyciDBdtQg=
golang.org/x/crypto v0.0.0-20200117160349-530e935923ad/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
@ -645,8 +659,8 @@ golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc h1:gkKoSkUmnU6bpS/VhkuO27bzQeSA51uaEfbOW5dNb68=
golang.org/x/net v0.0.0-20190812203447-cdfb69ac37fc/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191004110552-13f9640d40b9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9 h1:DPz9iiH3YoKiKhX/ijjoZvT0VFwK2c6CWYWQ7Zyr8TU=
golang.org/x/net v0.0.0-20191101175033-0deb6923b6d9/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
@ -680,6 +694,7 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181206074257-70b957f3b65e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190102155601-82a175fd1598/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190116161447-11f53e031339/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190209173611-3b5209105503/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@ -692,6 +707,7 @@ golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542 h1:6ZQFf1D2YYDDI7eSwW8adlkkavTB9sw5I24FVtEvNUQ=
golang.org/x/sys v0.0.0-20190710143415-6ec70d6a5542/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82 h1:ywK/j/KkyTHcdyYSZNXGjMwgmDSfjglYZ3vStQ/gSCU=
golang.org/x/sys v0.0.0-20200122134326-e047566fdf82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/text v0.0.0-20160726164857-2910a502d2bf/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
@ -738,9 +754,11 @@ golang.org/x/tools v0.0.0-20190312170243-e65039ee4138/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c h1:KfpJVdWhuRqNk4XVXzjXf2KAV4TBEP77SYdFGjeGuIE=
golang.org/x/tools v0.0.0-20190624180213-70d37148ca0c/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72 h1:bw9doJza/SFBEweII/rHQh338oozWyiFsBRHtrflcws=
golang.org/x/tools v0.0.0-20190920225731-5eefd052ad72/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485 h1:OB/uP/Puiu5vS5QMRPrXCDWUPb+kt8f1KW8oQzFejQw=
gonum.org/v1/gonum v0.0.0-20190331200053-3d26580ed485/go.mod h1:2ltnJ7xHfj0zHS40VVPYEAAMTa3ZGguvHGBSJeRWqE0=
gonum.org/v1/netlib v0.0.0-20190313105609-8cb42192e0e0/go.mod h1:wa6Ws7BG/ESfp6dHfk7C6KdzKA7wR7u/rKwOGE66zvw=
@ -776,8 +794,8 @@ gopkg.in/fsnotify.v1 v1.4.7 h1:xOHLXZwVvI9hhs+cLKq5+I5onOuwQLhQwiu63xxlHs4=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/gomail.v2 v2.0.0-20160411212932-81ebce5c23df/go.mod h1:LRQQ+SO6ZHR7tOkpBDuZnXENFzX8qRjMDMyPD6BRkCw=
gopkg.in/inf.v0 v0.9.0 h1:3zYtXIO92bvsdS3ggAdA8Gb4Azj0YU+TVY1uGYNFA8o=
gopkg.in/inf.v0 v0.9.0/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/mail.v2 v2.0.0-20180731213649-a0242b2233b4/go.mod h1:htwXN1Qh09vZJ1NVKxQqHPBaCBbzKhp5GzuJEA4VJWw=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
@ -792,28 +810,32 @@ honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWh
honnef.co/go/tools v0.0.0-20190106161140-3f1c8253044a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190418001031-e561f6794a2a/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
honnef.co/go/tools v0.0.0-20190523083050-ea95bdfd59fc/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3 h1:lV0+KGoNkvZOt4zGT4H83hQrzWMt/US/LSz4z4+BQS4=
k8s.io/api v0.0.0-20190118113203-912cbe2bfef3/go.mod h1:iuAfoD4hCxJ8Onx9kaTIt30j7jUFS00AXQi6QMi99vA=
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841 h1:Q4RZrHNtlC/mSdC1sTrcZ5RchC/9vxLVj57pWiCBKv4=
k8s.io/apimachinery v0.0.0-20190223001710-c182ff3b9841/go.mod h1:ccL7Eh7zubPUSh9A3USN90/OzHNSVN6zxzde07TDCL0=
k8s.io/client-go v0.0.0-20190117233410-4022682532b3 h1:7VVBo3+/iX6dzB8dshNuo6Duds/6AoNP5R59IUnwoxg=
k8s.io/client-go v0.0.0-20190117233410-4022682532b3/go.mod h1:7vJpHMYJwNQCWgzmNV+VYUl1zCObLyodBc8nIyt8L5s=
k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd h1:5WjZ3cIbClYC5mJf+H/ODCo36y8rRqtZRxol4Ujln8c=
k8s.io/code-generator v0.0.0-20191003035328-700b1226c0bd/go.mod h1:HC9p4y3SBN+txSs8x57qmNPXFZ/CxdCHiDTNnocCSEw=
k8s.io/api v0.16.6 h1:FyTv/Z4RBlddLGJXRjGXE40QtYGHOjdZKRFSW5rU1oE=
k8s.io/api v0.16.6/go.mod h1:naJcEPKsa3oqutLPPMxA2oLSqV4KxGDLU6IgkqHqgFE=
k8s.io/apimachinery v0.16.6 h1:A4RWH7F3jhkD6YyBpsm/2yXiFUEf9fiNqrz7bxZHPMc=
k8s.io/apimachinery v0.16.6/go.mod h1:mhhO3hoLkWO+2eCvqjPtH2Ly92l9nJDwsswzWKpkN2w=
k8s.io/client-go v0.16.6 h1:OR6ZaSlIn9dUdpiN4r5mAvMv5aCupUJUiDJZdrrvmhw=
k8s.io/client-go v0.16.6/go.mod h1:xIQ44uaAH4SD1EHMtCHsB9By7D0qblbv1ADeGyXpZUQ=
k8s.io/code-generator v0.16.6 h1:wykZVkEDQd/BcOZxcQMEW6uFgoM4ZmvjIhxkbmEJ3WA=
k8s.io/code-generator v0.16.6/go.mod h1:2aiDuxDU7RQK2PVypXAXHo6+YwOlF33iezHQbSmKSA4=
k8s.io/gengo v0.0.0-20190128074634-0689ccc1d7d6/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/gengo v0.0.0-20190822140433-26a664648505 h1:ZY6yclUKVbZ+SdWnkfY+Je5vrMpKOxmGeKRbsXVmqYM=
k8s.io/gengo v0.0.0-20190822140433-26a664648505/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog v0.0.0-20181102134211-b9b56d5dfc92/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v0.3.0/go.mod h1:Gq+BEi5rUBO/HRz0bTSXDUcqjScdoY3a9IHpCEIOOfk=
k8s.io/klog v1.0.0 h1:Pt+yjF5aB1xDSVbau4VsWe+dQNzA0qv1LlXdC2dF6Q8=
k8s.io/klog v1.0.0/go.mod h1:4Bi6QPql/J/LkTDqv7R/cd3hPo4k2DG6Ptcz060Ez5I=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf h1:EYm5AW/UUDbnmnI+gK0TJDVK9qPLhM+sRHYanNKw0EQ=
k8s.io/kube-openapi v0.0.0-20190816220812-743ec37842bf/go.mod h1:1TqjTSzOxsLGIKfj0lK8EeCP7K1iUG65v09OM0/WG5E=
k8s.io/kubernetes v1.13.0 h1:qTfB+u5M92k2fCCCVP2iuhgwwSOv1EkAkvQY1tQODD8=
k8s.io/kubernetes v1.13.0/go.mod h1:ocZa8+6APFNC2tX1DZASIbocyYT5jHzqFVsY5aoB7Jk=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1 h1:+ySTxfHnfzZb9ys375PXNlLhkJPLKgHajBU0N62BDvE=
k8s.io/utils v0.0.0-20190801114015-581e00157fb1/go.mod h1:sZAwmy6armz5eXlNoLmJcl4F1QuKu7sr+mFQ0byX7Ew=
modernc.org/cc v1.0.0/go.mod h1:1Sk4//wdnYJiUIxnW8ddKpaOJCF37yAdqYnkxUpaYxw=
modernc.org/golex v1.0.0/go.mod h1:b/QX9oBD/LhixY6NDh+IdGv17hgB+51fET1i2kPSmvk=
modernc.org/mathutil v1.0.0/go.mod h1:wU0vUrJsVWBZ4P6e7xtFJEhFSNsfRLJ8H458uRjg03k=
modernc.org/strutil v1.0.0/go.mod h1:lstksw84oURvj9y3tn8lGvRxyRC1S2+g5uuIzNfIOBs=
modernc.org/xc v1.0.0/go.mod h1:mRNCo0bvLjGhHO9WsyuKVU4q0ceiDDDoEeWDJHrNx8I=
sigs.k8s.io/structured-merge-diff v0.0.0-20190525122527-15d366b2352e/go.mod h1:wWxsB5ozmmv/SG7nM11ayaAW51xMvak/t1r0CSlcokI=
sigs.k8s.io/yaml v1.1.0 h1:4A07+ZFc2wgJwo8YNlQpr1rVlgUDlxXHhPJciaPY5gs=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=

17
hack/boilerplate.txt Normal file
View File

@ -0,0 +1,17 @@
/*
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/

View File

@ -1,11 +1,15 @@
.PHONY: generate mocks
generate:
$(eval tmp := $(shell mktemp -d))
bash ../../vendor/k8s.io/code-generator/generate-groups.sh all \
github.com/convox/convox/pkg/atom/pkg/client \
github.com/convox/convox/pkg/atom/pkg/apis \
atom:v1
atom:v1 \
--output-base $(tmp) \
--go-header-file ../../hack/boilerplate.txt
rsync -a $(tmp)/github.com/convox/convox/pkg/atom/pkg .
mocks:
rm -f mock_Interface.go
go run ../../vendor/github.com/vektra/mockery/cmd/mockery/mockery.go -inpkg -name Interface
go run ../../vendor/github.com/vektra/mockery/cmd/mockery/mockery.go -inpkg -name Interface

View File

@ -231,7 +231,7 @@ func (c *Client) check(ns, version string) (bool, error) {
cfg := *c.config
cfg.APIPath = "/apis"
cfg.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
cfg.NegotiatedSerializer = serializer.WithoutConversionCodecFactory{CodecFactory: scheme.Codecs}
v, err := c.atom.AtomV1().AtomVersions(ns).Get(version, am.GetOptions{})
if err != nil {

View File

@ -1,7 +1,8 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,6 +15,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
@ -95,7 +97,7 @@ func (in *AtomConditionMatch) DeepCopy() *AtomConditionMatch {
func (in *AtomList) DeepCopyInto(out *AtomList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Atom, len(*in))
@ -178,7 +180,7 @@ func (in *AtomVersion) DeepCopyObject() runtime.Object {
func (in *AtomVersionList) DeepCopyInto(out *AtomVersionList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]AtomVersion, len(*in))

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,6 +21,8 @@ limitations under the License.
package versioned
import (
"fmt"
atomv1 "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/typed/atom/v1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@ -28,8 +32,6 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
AtomV1() atomv1.AtomV1Interface
// Deprecated: please explicitly pick a version if possible.
Atom() atomv1.AtomV1Interface
}
// Clientset contains the clients for groups. Each group has exactly one
@ -44,12 +46,6 @@ func (c *Clientset) AtomV1() atomv1.AtomV1Interface {
return c.atomV1
}
// Deprecated: Atom retrieves the default version of AtomClient.
// Please explicitly pick a version.
func (c *Clientset) Atom() atomv1.AtomV1Interface {
return c.atomV1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@ -59,9 +55,14 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
}
// NewForConfig creates a new Clientset for the given config.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfig will generate a rate-limiter in configShallowCopy.
func NewForConfig(c *rest.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
if configShallowCopy.Burst <= 0 {
return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var cs Clientset

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -41,7 +43,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
}
}
cs := &Clientset{}
cs := &Clientset{tracker: o}
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
@ -63,20 +65,20 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
type Clientset struct {
testing.Fake
discovery *fakediscovery.FakeDiscovery
tracker testing.ObjectTracker
}
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return c.discovery
}
func (c *Clientset) Tracker() testing.ObjectTracker {
return c.tracker
}
var _ clientset.Interface = &Clientset{}
// AtomV1 retrieves the AtomV1Client
func (c *Clientset) AtomV1() atomv1.AtomV1Interface {
return &fakeatomv1.FakeAtomV1{Fake: &c.Fake}
}
// Atom retrieves the AtomV1Client
func (c *Clientset) Atom() atomv1.AtomV1Interface {
return &fakeatomv1.FakeAtomV1{Fake: &c.Fake}
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -24,15 +26,14 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme)
func init() {
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
AddToScheme(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
atomv1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@ -45,10 +46,13 @@ func init() {
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
atomv1.AddToScheme(scheme)
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(scheme))
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -24,15 +26,14 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
AddToScheme(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
atomv1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@ -45,10 +46,13 @@ func init() {
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
atomv1.AddToScheme(scheme)
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(Scheme))
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,9 +21,11 @@ limitations under the License.
package v1
import (
"time"
v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
scheme "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
@ -38,11 +42,11 @@ type AtomInterface interface {
Create(*v1.Atom) (*v1.Atom, error)
Update(*v1.Atom) (*v1.Atom, error)
UpdateStatus(*v1.Atom) (*v1.Atom, error)
Delete(name string, options *meta_v1.DeleteOptions) error
DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
Get(name string, options meta_v1.GetOptions) (*v1.Atom, error)
List(opts meta_v1.ListOptions) (*v1.AtomList, error)
Watch(opts meta_v1.ListOptions) (watch.Interface, error)
Delete(name string, options *metav1.DeleteOptions) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions) (*v1.Atom, error)
List(opts metav1.ListOptions) (*v1.AtomList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.Atom, err error)
AtomExpansion
}
@ -62,7 +66,7 @@ func newAtoms(c *AtomV1Client, namespace string) *atoms {
}
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
func (c *atoms) Get(name string, options meta_v1.GetOptions) (result *v1.Atom, err error) {
func (c *atoms) Get(name string, options metav1.GetOptions) (result *v1.Atom, err error) {
result = &v1.Atom{}
err = c.client.Get().
Namespace(c.ns).
@ -75,24 +79,34 @@ func (c *atoms) Get(name string, options meta_v1.GetOptions) (result *v1.Atom, e
}
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
func (c *atoms) List(opts meta_v1.ListOptions) (result *v1.AtomList, err error) {
func (c *atoms) List(opts metav1.ListOptions) (result *v1.AtomList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1.AtomList{}
err = c.client.Get().
Namespace(c.ns).
Resource("atoms").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested atoms.
func (c *atoms) Watch(opts meta_v1.ListOptions) (watch.Interface, error) {
func (c *atoms) Watch(opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("atoms").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
@ -138,7 +152,7 @@ func (c *atoms) UpdateStatus(atom *v1.Atom) (result *v1.Atom, err error) {
}
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
func (c *atoms) Delete(name string, options *meta_v1.DeleteOptions) error {
func (c *atoms) Delete(name string, options *metav1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("atoms").
@ -149,11 +163,16 @@ func (c *atoms) Delete(name string, options *meta_v1.DeleteOptions) error {
}
// DeleteCollection deletes a collection of objects.
func (c *atoms) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error {
func (c *atoms) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("atoms").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -21,7 +23,6 @@ package v1
import (
v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
"github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
rest "k8s.io/client-go/rest"
)
@ -76,7 +77,7 @@ func setConfigDefaults(config *rest.Config) error {
gv := v1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,9 +21,11 @@ limitations under the License.
package v1
import (
"time"
v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
scheme "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned/scheme"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
types "k8s.io/apimachinery/pkg/types"
watch "k8s.io/apimachinery/pkg/watch"
rest "k8s.io/client-go/rest"
@ -38,11 +42,11 @@ type AtomVersionInterface interface {
Create(*v1.AtomVersion) (*v1.AtomVersion, error)
Update(*v1.AtomVersion) (*v1.AtomVersion, error)
UpdateStatus(*v1.AtomVersion) (*v1.AtomVersion, error)
Delete(name string, options *meta_v1.DeleteOptions) error
DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error
Get(name string, options meta_v1.GetOptions) (*v1.AtomVersion, error)
List(opts meta_v1.ListOptions) (*v1.AtomVersionList, error)
Watch(opts meta_v1.ListOptions) (watch.Interface, error)
Delete(name string, options *metav1.DeleteOptions) error
DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error
Get(name string, options metav1.GetOptions) (*v1.AtomVersion, error)
List(opts metav1.ListOptions) (*v1.AtomVersionList, error)
Watch(opts metav1.ListOptions) (watch.Interface, error)
Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *v1.AtomVersion, err error)
AtomVersionExpansion
}
@ -62,7 +66,7 @@ func newAtomVersions(c *AtomV1Client, namespace string) *atomVersions {
}
// Get takes name of the atomVersion, and returns the corresponding atomVersion object, and an error if there is any.
func (c *atomVersions) Get(name string, options meta_v1.GetOptions) (result *v1.AtomVersion, err error) {
func (c *atomVersions) Get(name string, options metav1.GetOptions) (result *v1.AtomVersion, err error) {
result = &v1.AtomVersion{}
err = c.client.Get().
Namespace(c.ns).
@ -75,24 +79,34 @@ func (c *atomVersions) Get(name string, options meta_v1.GetOptions) (result *v1.
}
// List takes label and field selectors, and returns the list of AtomVersions that match those selectors.
func (c *atomVersions) List(opts meta_v1.ListOptions) (result *v1.AtomVersionList, err error) {
func (c *atomVersions) List(opts metav1.ListOptions) (result *v1.AtomVersionList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1.AtomVersionList{}
err = c.client.Get().
Namespace(c.ns).
Resource("atomversions").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
}
// Watch returns a watch.Interface that watches the requested atomVersions.
func (c *atomVersions) Watch(opts meta_v1.ListOptions) (watch.Interface, error) {
func (c *atomVersions) Watch(opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("atomversions").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
@ -138,7 +152,7 @@ func (c *atomVersions) UpdateStatus(atomVersion *v1.AtomVersion) (result *v1.Ato
}
// Delete takes name of the atomVersion and deletes it. Returns an error if one occurs.
func (c *atomVersions) Delete(name string, options *meta_v1.DeleteOptions) error {
func (c *atomVersions) Delete(name string, options *metav1.DeleteOptions) error {
return c.client.Delete().
Namespace(c.ns).
Resource("atomversions").
@ -149,11 +163,16 @@ func (c *atomVersions) Delete(name string, options *meta_v1.DeleteOptions) error
}
// DeleteCollection deletes a collection of objects.
func (c *atomVersions) DeleteCollection(options *meta_v1.DeleteOptions, listOptions meta_v1.ListOptions) error {
func (c *atomVersions) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("atomversions").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,7 +21,7 @@ limitations under the License.
package fake
import (
atom_v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
atomv1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -39,20 +41,20 @@ var atomsResource = schema.GroupVersionResource{Group: "atom.convox.com", Versio
var atomsKind = schema.GroupVersionKind{Group: "atom.convox.com", Version: "v1", Kind: "Atom"}
// Get takes name of the atom, and returns the corresponding atom object, and an error if there is any.
func (c *FakeAtoms) Get(name string, options v1.GetOptions) (result *atom_v1.Atom, err error) {
func (c *FakeAtoms) Get(name string, options v1.GetOptions) (result *atomv1.Atom, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(atomsResource, c.ns, name), &atom_v1.Atom{})
Invokes(testing.NewGetAction(atomsResource, c.ns, name), &atomv1.Atom{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.Atom), err
return obj.(*atomv1.Atom), err
}
// List takes label and field selectors, and returns the list of Atoms that match those selectors.
func (c *FakeAtoms) List(opts v1.ListOptions) (result *atom_v1.AtomList, err error) {
func (c *FakeAtoms) List(opts v1.ListOptions) (result *atomv1.AtomList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(atomsResource, atomsKind, c.ns, opts), &atom_v1.AtomList{})
Invokes(testing.NewListAction(atomsResource, atomsKind, c.ns, opts), &atomv1.AtomList{})
if obj == nil {
return nil, err
@ -62,8 +64,8 @@ func (c *FakeAtoms) List(opts v1.ListOptions) (result *atom_v1.AtomList, err err
if label == nil {
label = labels.Everything()
}
list := &atom_v1.AtomList{ListMeta: obj.(*atom_v1.AtomList).ListMeta}
for _, item := range obj.(*atom_v1.AtomList).Items {
list := &atomv1.AtomList{ListMeta: obj.(*atomv1.AtomList).ListMeta}
for _, item := range obj.(*atomv1.AtomList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
@ -79,43 +81,43 @@ func (c *FakeAtoms) Watch(opts v1.ListOptions) (watch.Interface, error) {
}
// Create takes the representation of a atom and creates it. Returns the server's representation of the atom, and an error, if there is any.
func (c *FakeAtoms) Create(atom *atom_v1.Atom) (result *atom_v1.Atom, err error) {
func (c *FakeAtoms) Create(atom *atomv1.Atom) (result *atomv1.Atom, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(atomsResource, c.ns, atom), &atom_v1.Atom{})
Invokes(testing.NewCreateAction(atomsResource, c.ns, atom), &atomv1.Atom{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.Atom), err
return obj.(*atomv1.Atom), err
}
// Update takes the representation of a atom and updates it. Returns the server's representation of the atom, and an error, if there is any.
func (c *FakeAtoms) Update(atom *atom_v1.Atom) (result *atom_v1.Atom, err error) {
func (c *FakeAtoms) Update(atom *atomv1.Atom) (result *atomv1.Atom, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(atomsResource, c.ns, atom), &atom_v1.Atom{})
Invokes(testing.NewUpdateAction(atomsResource, c.ns, atom), &atomv1.Atom{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.Atom), err
return obj.(*atomv1.Atom), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeAtoms) UpdateStatus(atom *atom_v1.Atom) (*atom_v1.Atom, error) {
func (c *FakeAtoms) UpdateStatus(atom *atomv1.Atom) (*atomv1.Atom, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(atomsResource, "status", c.ns, atom), &atom_v1.Atom{})
Invokes(testing.NewUpdateSubresourceAction(atomsResource, "status", c.ns, atom), &atomv1.Atom{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.Atom), err
return obj.(*atomv1.Atom), err
}
// Delete takes name of the atom and deletes it. Returns an error if one occurs.
func (c *FakeAtoms) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(atomsResource, c.ns, name), &atom_v1.Atom{})
Invokes(testing.NewDeleteAction(atomsResource, c.ns, name), &atomv1.Atom{})
return err
}
@ -124,17 +126,17 @@ func (c *FakeAtoms) Delete(name string, options *v1.DeleteOptions) error {
func (c *FakeAtoms) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(atomsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &atom_v1.AtomList{})
_, err := c.Fake.Invokes(action, &atomv1.AtomList{})
return err
}
// Patch applies the patch and returns the patched atom.
func (c *FakeAtoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *atom_v1.Atom, err error) {
func (c *FakeAtoms) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *atomv1.Atom, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(atomsResource, c.ns, name, data, subresources...), &atom_v1.Atom{})
Invokes(testing.NewPatchSubresourceAction(atomsResource, c.ns, name, pt, data, subresources...), &atomv1.Atom{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.Atom), err
return obj.(*atomv1.Atom), err
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,7 +21,7 @@ limitations under the License.
package fake
import (
atom_v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
atomv1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
labels "k8s.io/apimachinery/pkg/labels"
schema "k8s.io/apimachinery/pkg/runtime/schema"
@ -39,20 +41,20 @@ var atomversionsResource = schema.GroupVersionResource{Group: "atom.convox.com",
var atomversionsKind = schema.GroupVersionKind{Group: "atom.convox.com", Version: "v1", Kind: "AtomVersion"}
// Get takes name of the atomVersion, and returns the corresponding atomVersion object, and an error if there is any.
func (c *FakeAtomVersions) Get(name string, options v1.GetOptions) (result *atom_v1.AtomVersion, err error) {
func (c *FakeAtomVersions) Get(name string, options v1.GetOptions) (result *atomv1.AtomVersion, err error) {
obj, err := c.Fake.
Invokes(testing.NewGetAction(atomversionsResource, c.ns, name), &atom_v1.AtomVersion{})
Invokes(testing.NewGetAction(atomversionsResource, c.ns, name), &atomv1.AtomVersion{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.AtomVersion), err
return obj.(*atomv1.AtomVersion), err
}
// List takes label and field selectors, and returns the list of AtomVersions that match those selectors.
func (c *FakeAtomVersions) List(opts v1.ListOptions) (result *atom_v1.AtomVersionList, err error) {
func (c *FakeAtomVersions) List(opts v1.ListOptions) (result *atomv1.AtomVersionList, err error) {
obj, err := c.Fake.
Invokes(testing.NewListAction(atomversionsResource, atomversionsKind, c.ns, opts), &atom_v1.AtomVersionList{})
Invokes(testing.NewListAction(atomversionsResource, atomversionsKind, c.ns, opts), &atomv1.AtomVersionList{})
if obj == nil {
return nil, err
@ -62,8 +64,8 @@ func (c *FakeAtomVersions) List(opts v1.ListOptions) (result *atom_v1.AtomVersio
if label == nil {
label = labels.Everything()
}
list := &atom_v1.AtomVersionList{ListMeta: obj.(*atom_v1.AtomVersionList).ListMeta}
for _, item := range obj.(*atom_v1.AtomVersionList).Items {
list := &atomv1.AtomVersionList{ListMeta: obj.(*atomv1.AtomVersionList).ListMeta}
for _, item := range obj.(*atomv1.AtomVersionList).Items {
if label.Matches(labels.Set(item.Labels)) {
list.Items = append(list.Items, item)
}
@ -79,43 +81,43 @@ func (c *FakeAtomVersions) Watch(opts v1.ListOptions) (watch.Interface, error) {
}
// Create takes the representation of a atomVersion and creates it. Returns the server's representation of the atomVersion, and an error, if there is any.
func (c *FakeAtomVersions) Create(atomVersion *atom_v1.AtomVersion) (result *atom_v1.AtomVersion, err error) {
func (c *FakeAtomVersions) Create(atomVersion *atomv1.AtomVersion) (result *atomv1.AtomVersion, err error) {
obj, err := c.Fake.
Invokes(testing.NewCreateAction(atomversionsResource, c.ns, atomVersion), &atom_v1.AtomVersion{})
Invokes(testing.NewCreateAction(atomversionsResource, c.ns, atomVersion), &atomv1.AtomVersion{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.AtomVersion), err
return obj.(*atomv1.AtomVersion), err
}
// Update takes the representation of a atomVersion and updates it. Returns the server's representation of the atomVersion, and an error, if there is any.
func (c *FakeAtomVersions) Update(atomVersion *atom_v1.AtomVersion) (result *atom_v1.AtomVersion, err error) {
func (c *FakeAtomVersions) Update(atomVersion *atomv1.AtomVersion) (result *atomv1.AtomVersion, err error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateAction(atomversionsResource, c.ns, atomVersion), &atom_v1.AtomVersion{})
Invokes(testing.NewUpdateAction(atomversionsResource, c.ns, atomVersion), &atomv1.AtomVersion{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.AtomVersion), err
return obj.(*atomv1.AtomVersion), err
}
// UpdateStatus was generated because the type contains a Status member.
// Add a +genclient:noStatus comment above the type to avoid generating UpdateStatus().
func (c *FakeAtomVersions) UpdateStatus(atomVersion *atom_v1.AtomVersion) (*atom_v1.AtomVersion, error) {
func (c *FakeAtomVersions) UpdateStatus(atomVersion *atomv1.AtomVersion) (*atomv1.AtomVersion, error) {
obj, err := c.Fake.
Invokes(testing.NewUpdateSubresourceAction(atomversionsResource, "status", c.ns, atomVersion), &atom_v1.AtomVersion{})
Invokes(testing.NewUpdateSubresourceAction(atomversionsResource, "status", c.ns, atomVersion), &atomv1.AtomVersion{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.AtomVersion), err
return obj.(*atomv1.AtomVersion), err
}
// Delete takes name of the atomVersion and deletes it. Returns an error if one occurs.
func (c *FakeAtomVersions) Delete(name string, options *v1.DeleteOptions) error {
_, err := c.Fake.
Invokes(testing.NewDeleteAction(atomversionsResource, c.ns, name), &atom_v1.AtomVersion{})
Invokes(testing.NewDeleteAction(atomversionsResource, c.ns, name), &atomv1.AtomVersion{})
return err
}
@ -124,17 +126,17 @@ func (c *FakeAtomVersions) Delete(name string, options *v1.DeleteOptions) error
func (c *FakeAtomVersions) DeleteCollection(options *v1.DeleteOptions, listOptions v1.ListOptions) error {
action := testing.NewDeleteCollectionAction(atomversionsResource, c.ns, listOptions)
_, err := c.Fake.Invokes(action, &atom_v1.AtomVersionList{})
_, err := c.Fake.Invokes(action, &atomv1.AtomVersionList{})
return err
}
// Patch applies the patch and returns the patched atomVersion.
func (c *FakeAtomVersions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *atom_v1.AtomVersion, err error) {
func (c *FakeAtomVersions) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *atomv1.AtomVersion, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(atomversionsResource, c.ns, name, data, subresources...), &atom_v1.AtomVersion{})
Invokes(testing.NewPatchSubresourceAction(atomversionsResource, c.ns, name, pt, data, subresources...), &atomv1.AtomVersion{})
if obj == nil {
return nil, err
}
return obj.(*atom_v1.AtomVersion), err
return obj.(*atomv1.AtomVersion), err
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
@ -21,11 +23,11 @@ package v1
import (
time "time"
atom_v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
atomv1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
v1 "github.com/convox/convox/pkg/atom/pkg/client/listers/atom/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
@ -57,20 +59,20 @@ func NewAtomInformer(client versioned.Interface, namespace string, resyncPeriod
func NewFilteredAtomInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) {
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AtomV1().Atoms(namespace).List(options)
},
WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) {
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AtomV1().Atoms(namespace).Watch(options)
},
},
&atom_v1.Atom{},
&atomv1.Atom{},
resyncPeriod,
indexers,
)
@ -81,7 +83,7 @@ func (f *atomInformer) defaultInformer(client versioned.Interface, resyncPeriod
}
func (f *atomInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&atom_v1.Atom{}, f.defaultInformer)
return f.factory.InformerFor(&atomv1.Atom{}, f.defaultInformer)
}
func (f *atomInformer) Lister() v1.AtomLister {

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
@ -21,11 +23,11 @@ package v1
import (
time "time"
atom_v1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
atomv1 "github.com/convox/convox/pkg/atom/pkg/apis/atom/v1"
versioned "github.com/convox/convox/pkg/atom/pkg/client/clientset/versioned"
internalinterfaces "github.com/convox/convox/pkg/atom/pkg/client/informers/externalversions/internalinterfaces"
v1 "github.com/convox/convox/pkg/atom/pkg/client/listers/atom/v1"
meta_v1 "k8s.io/apimachinery/pkg/apis/meta/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
runtime "k8s.io/apimachinery/pkg/runtime"
watch "k8s.io/apimachinery/pkg/watch"
cache "k8s.io/client-go/tools/cache"
@ -57,20 +59,20 @@ func NewAtomVersionInformer(client versioned.Interface, namespace string, resync
func NewFilteredAtomVersionInformer(client versioned.Interface, namespace string, resyncPeriod time.Duration, indexers cache.Indexers, tweakListOptions internalinterfaces.TweakListOptionsFunc) cache.SharedIndexInformer {
return cache.NewSharedIndexInformer(
&cache.ListWatch{
ListFunc: func(options meta_v1.ListOptions) (runtime.Object, error) {
ListFunc: func(options metav1.ListOptions) (runtime.Object, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AtomV1().AtomVersions(namespace).List(options)
},
WatchFunc: func(options meta_v1.ListOptions) (watch.Interface, error) {
WatchFunc: func(options metav1.ListOptions) (watch.Interface, error) {
if tweakListOptions != nil {
tweakListOptions(&options)
}
return client.AtomV1().AtomVersions(namespace).Watch(options)
},
},
&atom_v1.AtomVersion{},
&atomv1.AtomVersion{},
resyncPeriod,
indexers,
)
@ -81,7 +83,7 @@ func (f *atomVersionInformer) defaultInformer(client versioned.Interface, resync
}
func (f *atomVersionInformer) Informer() cache.SharedIndexInformer {
return f.factory.InformerFor(&atom_v1.AtomVersion{}, f.defaultInformer)
return f.factory.InformerFor(&atomv1.AtomVersion{}, f.defaultInformer)
}
func (f *atomVersionInformer) Lister() v1.AtomVersionLister {

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
@ -27,6 +29,7 @@ import (
cache "k8s.io/client-go/tools/cache"
)
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
@ -35,4 +38,5 @@ type SharedInformerFactory interface {
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
}
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
type TweakListOptionsFunc func(*v1.ListOptions)

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

37
pkg/common/string.go Normal file
View File

@ -0,0 +1,37 @@
package common
import "strings"
func UpperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -1,6 +1,7 @@
package kctl
import (
"context"
"fmt"
"os"
"time"
@ -25,6 +26,7 @@ type Controller struct {
errch chan error
recorder record.EventRecorder
stopper chan struct{}
}
type ControllerHandler interface {
@ -80,6 +82,7 @@ func (c *Controller) Run(informer cache.SharedInformer, ch chan error) {
RetryPeriod: 2 * time.Second,
Callbacks: leaderelection.LeaderCallbacks{
OnStartedLeading: c.leaderStart(informer),
OnStoppedLeading: c.leaderStop,
},
})
if err != nil {
@ -87,11 +90,13 @@ func (c *Controller) Run(informer cache.SharedInformer, ch chan error) {
return
}
go el.Run()
ctx := context.Background()
go el.Run(ctx)
}
func (c *Controller) leaderStart(informer cache.SharedInformer) func(<-chan struct{}) {
return func(stop <-chan struct{}) {
func (c *Controller) leaderStart(informer cache.SharedInformer) func(ctx context.Context) {
return func(ctx context.Context) {
fmt.Printf("started leading: %s/%s (%s)\n", c.Namespace, c.Name, c.Identifier)
informer.AddEventHandler(cache.ResourceEventHandlerFuncs{
@ -104,13 +109,20 @@ func (c *Controller) leaderStart(informer cache.SharedInformer) func(<-chan stru
c.errch <- err
}
go informer.Run(stop)
c.stopper = make(chan struct{})
fmt.Printf("stopped leading: %s/%s (%s)\n", c.Namespace, c.Name, c.Identifier)
go informer.Run(c.stopper)
}
}
if err := c.Handler.Stop(); err != nil {
c.errch <- err
}
func (c *Controller) leaderStop() {
fmt.Printf("stopped leading: %s/%s (%s)\n", c.Namespace, c.Name, c.Identifier)
close(c.stopper)
c.stopper = nil
if err := c.Handler.Stop(); err != nil {
c.errch <- err
}
}

View File

@ -1,13 +1,14 @@
package aws
import (
"encoding/json"
"fmt"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/convox/convox/pkg/structs"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
"github.com/convox/convox/provider/k8s"
"k8s.io/apimachinery/pkg/types"
)
func (p *Provider) AppCreate(name string, opts structs.AppCreateOptions) (*structs.App, error) {
@ -23,18 +24,16 @@ func (p *Provider) AppCreate(name string, opts structs.AppCreateOptions) (*struc
return nil, err
}
ns, err := p.Provider.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(name), am.GetOptions{})
patches := []k8s.Patch{
{Op: "add", Path: "/metadata/annotations/convox.com~1registry", Value: *res.Repository.RepositoryUri},
}
patch, err := json.Marshal(patches)
if err != nil {
return nil, err
}
if ns.ObjectMeta.Annotations == nil {
ns.ObjectMeta.Annotations = map[string]string{}
}
ns.ObjectMeta.Annotations["convox.registry"] = *res.Repository.RepositoryUri
if _, err := p.Provider.Cluster.CoreV1().Namespaces().Update(ns); err != nil {
if _, err := p.Cluster.CoreV1().Namespaces().Patch(p.AppNamespace(name), types.JSONPatchType, patch); err != nil {
return nil, err
}

View File

@ -1,22 +1,17 @@
package aws
import (
"context"
"encoding/base64"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-sdk-go/aws/credentials"
"github.com/aws/aws-sdk-go/aws/session"
"github.com/aws/aws-sdk-go/service/cloudformation"
"github.com/aws/aws-sdk-go/service/ecr"
"github.com/convox/convox/pkg/common"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
)
@ -30,8 +25,11 @@ func (p *Provider) appRegistry(app string) (string, error) {
return "", err
}
registry, ok := ns.ObjectMeta.Annotations["convox.registry"]
if !ok {
as := ns.ObjectMeta.Annotations
registry := common.CoalesceString(as["convox.com/registry"], as["convox.registry"])
if registry == "" {
return "", fmt.Errorf("no registry for app: %s", app)
}
@ -83,66 +81,6 @@ func (p *Provider) ecrAuth(host, access, secret string) (string, string, error)
return parts[0], parts[1], nil
}
func (p *Provider) stackOutputs(stack string) (map[string]string, error) {
res, err := p.CloudFormation.DescribeStacks(&cloudformation.DescribeStacksInput{
StackName: aws.String(stack),
})
if err != nil {
return nil, err
}
if len(res.Stacks) != 1 {
return nil, fmt.Errorf("no such stack: %s", stack)
}
outputs := map[string]string{}
for _, o := range res.Stacks[0].Outputs {
outputs[*o.OutputKey] = *o.OutputValue
}
return outputs, nil
}
func (p *Provider) stackTags(stack string) (map[string]string, error) {
res, err := p.CloudFormation.DescribeStacks(&cloudformation.DescribeStacksInput{
StackName: aws.String(stack),
})
if err != nil {
return nil, err
}
if len(res.Stacks) != 1 {
return nil, fmt.Errorf("no such stack: %s", stack)
}
tags := map[string]string{}
for _, t := range res.Stacks[0].Tags {
tags[*t.Key] = *t.Value
}
return tags, nil
}
func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid string, cancel func()) {
defer cancel()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-ctx.Done():
return
case <-tick.C:
if _, err := p.ProcessGet(app, pid); err != nil {
time.Sleep(2 * time.Second)
cancel()
return
}
}
}
}
func awsErrorCode(err error) string {
if ae, ok := err.(awserr.Error); ok {
return ae.Code()
@ -150,66 +88,3 @@ func awsErrorCode(err error) string {
return ""
}
func cloudformationErrorNoUpdates(err error) bool {
if ae, ok := err.(awserr.Error); ok {
if ae.Code() == "ValidationError" && strings.Contains(ae.Message(), "No updates are to be performed") {
return true
}
}
return false
}
func kubectl(args ...string) error {
cmd := exec.Command("kubectl", args...)
cmd.Env = os.Environ()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.New(strings.TrimSpace(string(out)))
}
return nil
}
var outputConverter = regexp.MustCompile("([a-z])([A-Z])") // lower case letter followed by upper case
func outputToEnvironment(name string) string {
return strings.ToUpper(outputConverter.ReplaceAllString(name, "${1}_${2}"))
}
func upperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -25,7 +25,7 @@ func (p *Provider) templateHelpers() template.FuncMap {
return template.HTML(fmt.Sprintf("%q", s))
},
"upper": func(s string) string {
return upperName(s)
return common.UpperName(s)
},
}
}

View File

@ -1,106 +0,0 @@
package azure
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
// gv "github.com/GoogleCloudPlatform/gke-managed-certs/pkg/clientgen/clientset/versioned"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (p *Provider) appRegistry(app string) (string, error) {
ns, err := p.Provider.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(app), am.GetOptions{})
if err != nil {
return "", err
}
registry, ok := ns.ObjectMeta.Annotations["convox.registry"]
if !ok {
return "", fmt.Errorf("no registry for app: %s", app)
}
return registry, nil
}
// func (p *Provider) gkeManagedCertsClient() (gv.Interface, error) {
// return gv.NewForConfig(p.Config)
// }
func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid string, cancel func()) {
defer cancel()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-ctx.Done():
return
case <-tick.C:
if _, err := p.ProcessGet(app, pid); err != nil {
time.Sleep(2 * time.Second)
cancel()
return
}
}
}
}
func kubectl(args ...string) error {
cmd := exec.Command("kubectl", args...)
cmd.Env = os.Environ()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.New(strings.TrimSpace(string(out)))
}
return nil
}
var outputConverter = regexp.MustCompile("([a-z])([A-Z])") // lower case letter followed by upper case
func outputToEnvironment(name string) string {
return strings.ToUpper(outputConverter.ReplaceAllString(name, "${1}_${2}"))
}
func upperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -1,106 +1 @@
package do
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
// gv "github.com/GoogleCloudPlatform/gke-managed-certs/pkg/clientgen/clientset/versioned"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (p *Provider) appRegistry(app string) (string, error) {
ns, err := p.Provider.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(app), am.GetOptions{})
if err != nil {
return "", err
}
registry, ok := ns.ObjectMeta.Annotations["convox.registry"]
if !ok {
return "", fmt.Errorf("no registry for app: %s", app)
}
return registry, nil
}
// func (p *Provider) gkeManagedCertsClient() (gv.Interface, error) {
// return gv.NewForConfig(p.Config)
// }
func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid string, cancel func()) {
defer cancel()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-ctx.Done():
return
case <-tick.C:
if _, err := p.ProcessGet(app, pid); err != nil {
time.Sleep(2 * time.Second)
cancel()
return
}
}
}
}
func kubectl(args ...string) error {
cmd := exec.Command("kubectl", args...)
cmd.Env = os.Environ()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.New(strings.TrimSpace(string(out)))
}
return nil
}
var outputConverter = regexp.MustCompile("([a-z])([A-Z])") // lower case letter followed by upper case
func outputToEnvironment(name string) string {
return strings.ToUpper(outputConverter.ReplaceAllString(name, "${1}_${2}"))
}
func upperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -8,9 +8,7 @@ import (
"cloud.google.com/go/storage"
"github.com/convox/convox/pkg/elastic"
"github.com/convox/convox/pkg/structs"
"github.com/convox/convox/pkg/templater"
"github.com/convox/convox/provider/k8s"
"github.com/gobuffalo/packr"
)
type Provider struct {
@ -22,9 +20,8 @@ type Provider struct {
Region string
Registry string
elastic *elastic.Client
storage *storage.Client
templater *templater.Templater
elastic *elastic.Client
storage *storage.Client
}
func FromEnv() (*Provider, error) {
@ -48,8 +45,6 @@ func FromEnv() (*Provider, error) {
p.Key = key
p.templater = templater.New(packr.NewBox("../gcp/template"), p.templateHelpers())
k.Engine = p
return p, nil

View File

@ -1,106 +1 @@
package gcp
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
// gv "github.com/GoogleCloudPlatform/gke-managed-certs/pkg/clientgen/clientset/versioned"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (p *Provider) appRegistry(app string) (string, error) {
ns, err := p.Provider.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(app), am.GetOptions{})
if err != nil {
return "", err
}
registry, ok := ns.ObjectMeta.Annotations["convox.registry"]
if !ok {
return "", fmt.Errorf("no registry for app: %s", app)
}
return registry, nil
}
// func (p *Provider) gkeManagedCertsClient() (gv.Interface, error) {
// return gv.NewForConfig(p.Config)
// }
func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid string, cancel func()) {
defer cancel()
tick := time.NewTicker(2 * time.Second)
defer tick.Stop()
for {
select {
case <-ctx.Done():
return
case <-tick.C:
if _, err := p.ProcessGet(app, pid); err != nil {
time.Sleep(2 * time.Second)
cancel()
return
}
}
}
}
func kubectl(args ...string) error {
cmd := exec.Command("kubectl", args...)
cmd.Env = os.Environ()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.New(strings.TrimSpace(string(out)))
}
return nil
}
var outputConverter = regexp.MustCompile("([a-z])([A-Z])") // lower case letter followed by upper case
func outputToEnvironment(name string) string {
return strings.ToUpper(outputConverter.ReplaceAllString(name, "${1}_${2}"))
}
func upperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -1,31 +0,0 @@
package gcp
import (
"fmt"
"html/template"
"github.com/convox/convox/pkg/common"
)
func (p *Provider) RenderTemplate(name string, params map[string]interface{}) ([]byte, error) {
data, err := p.templater.Render(fmt.Sprintf("%s.yml.tmpl", name), params)
if err != nil {
return nil, err
}
return common.FormatYAML(data)
}
func (p *Provider) templateHelpers() template.FuncMap {
return template.FuncMap{
"coalesce": func(ss ...string) string {
return common.CoalesceString(ss...)
},
"safe": func(s string) template.HTML {
return template.HTML(fmt.Sprintf("%q", s))
},
"upper": func(s string) string {
return upperName(s)
},
}
}

View File

@ -1,8 +1,11 @@
all: generate
generate:
# go get -u k8s.io/code-generator/...
$(eval tmp := $(shell mktemp -d))
bash ../../vendor/k8s.io/code-generator/generate-groups.sh all \
github.com/convox/convox/provider/k8s/pkg/client \
github.com/convox/convox/provider/k8s/pkg/apis \
convox:v1
convox:v1 \
--output-base $(tmp) \
--go-header-file ../../hack/boilerplate.txt
rsync -a $(tmp)/github.com/convox/convox/provider/k8s/pkg .

View File

@ -4,8 +4,6 @@ import (
"encoding/json"
"fmt"
"io"
"reflect"
"time"
"github.com/convox/convox/pkg/common"
"github.com/convox/convox/pkg/options"
@ -13,6 +11,7 @@ import (
ac "k8s.io/api/core/v1"
ae "k8s.io/apimachinery/pkg/api/errors"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
func (p *Provider) AppCancel(name string) error {
@ -35,6 +34,10 @@ func (p *Provider) AppCreate(name string, opts structs.AppCreateOptions) (*struc
ns := &ac.Namespace{
ObjectMeta: am.ObjectMeta{
Name: p.AppNamespace(name),
Annotations: map[string]string{
"convox.com/lock": "false",
"convox.com/params": "{}",
},
Labels: map[string]string{
"name": name,
"type": "app",
@ -264,40 +267,24 @@ func (p *Provider) appParametersUpdate(a *structs.App, params map[string]string)
}
func (p *Provider) appUpdate(a *structs.App) error {
ns, err := p.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(a.Name), am.GetOptions{})
params, err := json.Marshal(a.Parameters)
if err != nil {
return err
}
if ns.Annotations == nil {
ns.Annotations = map[string]string{}
patches := []Patch{
{Op: "add", Path: "/metadata/annotations/convox.com~1lock", Value: fmt.Sprintf("%t", a.Locked)},
{Op: "add", Path: "/metadata/annotations/convox.com~1params", Value: string(params)},
}
ns.Annotations["convox.com/lock"] = fmt.Sprintf("%t", a.Locked)
data, err := json.Marshal(a.Parameters)
patch, err := json.Marshal(patches)
if err != nil {
return err
}
ns.Annotations["convox.com/params"] = string(data)
if _, err := p.Cluster.CoreV1().Namespaces().Update(ns); err != nil {
if _, err := p.Cluster.CoreV1().Namespaces().Patch(p.AppNamespace(a.Name), types.JSONPatchType, patch); err != nil {
return err
}
for {
nsn, err := p.Cluster.CoreV1().Namespaces().Get(ns.Name, am.GetOptions{})
if err != nil {
return err
}
if reflect.DeepEqual(nsn.Annotations, ns.Annotations) {
break
}
time.Sleep(1 * time.Second)
}
return nil
}

View File

@ -231,6 +231,40 @@ func TestAppUpdateLocked(t *testing.T) {
err := p.AppUpdate("app1", structs.AppUpdateOptions{Lock: options.Bool(true)})
require.NoError(t, err)
ns, err := p.Cluster.CoreV1().Namespaces().Get("rack1-app1", am.GetOptions{})
require.NoError(t, err)
require.Equal(t, "true", ns.Annotations["convox.com/lock"])
})
}
func TestAppUpdateDoesNotOverwriteExisting(t *testing.T) {
testProvider(t, func(p *k8s.Provider) {
aa := p.Atom.(*atom.MockInterface)
kk := p.Cluster.(*fake.Clientset)
aa.On("Apply", "rack1-app1", "app", "", mock.Anything, int32(30)).Return(nil).Once().Run(func(args mock.Arguments) {
requireYamlFixture(t, args.Get(3).([]byte), "app-locked.yml")
}).Once()
aa.On("Apply", "rack1-app1", "app", "", mock.Anything, int32(30)).Return(nil).Once().Run(func(args mock.Arguments) {
requireYamlFixture(t, args.Get(3).([]byte), "app-locked-params.yml")
}).Once()
aa.On("Status", "rack1-app1", "app").Return("Running", "", nil).Times(4)
require.NoError(t, appCreate(kk, "rack1", "app1"))
err := p.AppUpdate("app1", structs.AppUpdateOptions{Lock: options.Bool(true)})
require.NoError(t, err)
err = p.AppUpdate("app1", structs.AppUpdateOptions{Parameters: map[string]string{"Test": "bar"}})
require.NoError(t, err)
ns, err := p.Cluster.CoreV1().Namespaces().Get("rack1-app1", am.GetOptions{})
require.NoError(t, err)
require.Equal(t, "true", ns.Annotations["convox.com/lock"])
require.Equal(t, `{"Test":"bar"}`, ns.Annotations["convox.com/params"])
})
}
@ -249,6 +283,10 @@ func TestAppUpdateParameters(t *testing.T) {
err := p.AppUpdate("app1", structs.AppUpdateOptions{Parameters: map[string]string{"Test": "bar"}})
require.NoError(t, err)
ns, err := p.Cluster.CoreV1().Namespaces().Get("rack1-app1", am.GetOptions{})
require.NoError(t, err)
require.Equal(t, `{"Test":"bar"}`, ns.Annotations["convox.com/params"])
})
}
@ -266,7 +304,8 @@ func TestAppUpdateMissing(t *testing.T) {
func appCreate(c kubernetes.Interface, rack, name string) error {
_, err := c.CoreV1().Namespaces().Create(&ac.Namespace{
ObjectMeta: am.ObjectMeta{
Name: fmt.Sprintf("%s-%s", rack, name),
Name: fmt.Sprintf("%s-%s", rack, name),
Annotations: map[string]string{"convox.com/lock": "false"},
Labels: map[string]string{
"app": name,
"name": name,

View File

@ -25,6 +25,12 @@ const (
ScannerMaxSize = 1024 * 1024
)
type Patch struct {
Op string `json:"op"`
Path string `json:"path"`
Value interface{} `json:"value"`
}
func (p *Provider) convoxClient() (cv.Interface, error) {
return cv.NewForConfig(p.Config)
}

View File

@ -1,7 +1,8 @@
// +build !ignore_autogenerated
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -14,6 +15,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by deepcopy-gen. DO NOT EDIT.
@ -55,7 +57,7 @@ func (in *Build) DeepCopyObject() runtime.Object {
func (in *BuildList) DeepCopyInto(out *BuildList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Build, len(*in))
@ -131,7 +133,7 @@ func (in *Release) DeepCopyObject() runtime.Object {
func (in *ReleaseList) DeepCopyInto(out *ReleaseList) {
*out = *in
out.TypeMeta = in.TypeMeta
out.ListMeta = in.ListMeta
in.ListMeta.DeepCopyInto(&out.ListMeta)
if in.Items != nil {
in, out := &in.Items, &out.Items
*out = make([]Release, len(*in))

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,6 +21,8 @@ limitations under the License.
package versioned
import (
"fmt"
convoxv1 "github.com/convox/convox/provider/k8s/pkg/client/clientset/versioned/typed/convox/v1"
discovery "k8s.io/client-go/discovery"
rest "k8s.io/client-go/rest"
@ -28,8 +32,6 @@ import (
type Interface interface {
Discovery() discovery.DiscoveryInterface
ConvoxV1() convoxv1.ConvoxV1Interface
// Deprecated: please explicitly pick a version if possible.
Convox() convoxv1.ConvoxV1Interface
}
// Clientset contains the clients for groups. Each group has exactly one
@ -44,12 +46,6 @@ func (c *Clientset) ConvoxV1() convoxv1.ConvoxV1Interface {
return c.convoxV1
}
// Deprecated: Convox retrieves the default version of ConvoxClient.
// Please explicitly pick a version.
func (c *Clientset) Convox() convoxv1.ConvoxV1Interface {
return c.convoxV1
}
// Discovery retrieves the DiscoveryClient
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
if c == nil {
@ -59,9 +55,14 @@ func (c *Clientset) Discovery() discovery.DiscoveryInterface {
}
// NewForConfig creates a new Clientset for the given config.
// If config's RateLimiter is not set and QPS and Burst are acceptable,
// NewForConfig will generate a rate-limiter in configShallowCopy.
func NewForConfig(c *rest.Config) (*Clientset, error) {
configShallowCopy := *c
if configShallowCopy.RateLimiter == nil && configShallowCopy.QPS > 0 {
if configShallowCopy.Burst <= 0 {
return nil, fmt.Errorf("Burst is required to be greater than 0 when RateLimiter is not set and QPS is set to greater than 0")
}
configShallowCopy.RateLimiter = flowcontrol.NewTokenBucketRateLimiter(configShallowCopy.QPS, configShallowCopy.Burst)
}
var cs Clientset

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -41,7 +43,7 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
}
}
cs := &Clientset{}
cs := &Clientset{tracker: o}
cs.discovery = &fakediscovery.FakeDiscovery{Fake: &cs.Fake}
cs.AddReactor("*", "*", testing.ObjectReaction(o))
cs.AddWatchReactor("*", func(action testing.Action) (handled bool, ret watch.Interface, err error) {
@ -63,20 +65,20 @@ func NewSimpleClientset(objects ...runtime.Object) *Clientset {
type Clientset struct {
testing.Fake
discovery *fakediscovery.FakeDiscovery
tracker testing.ObjectTracker
}
func (c *Clientset) Discovery() discovery.DiscoveryInterface {
return c.discovery
}
func (c *Clientset) Tracker() testing.ObjectTracker {
return c.tracker
}
var _ clientset.Interface = &Clientset{}
// ConvoxV1 retrieves the ConvoxV1Client
func (c *Clientset) ConvoxV1() convoxv1.ConvoxV1Interface {
return &fakeconvoxv1.FakeConvoxV1{Fake: &c.Fake}
}
// Convox retrieves the ConvoxV1Client
func (c *Clientset) Convox() convoxv1.ConvoxV1Interface {
return &fakeconvoxv1.FakeConvoxV1{Fake: &c.Fake}
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -24,15 +26,14 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var scheme = runtime.NewScheme()
var codecs = serializer.NewCodecFactory(scheme)
var parameterCodec = runtime.NewParameterCodec(scheme)
func init() {
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
AddToScheme(scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
convoxv1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@ -45,10 +46,13 @@ func init() {
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
convoxv1.AddToScheme(scheme)
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(scheme))
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -24,15 +26,14 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
schema "k8s.io/apimachinery/pkg/runtime/schema"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
)
var Scheme = runtime.NewScheme()
var Codecs = serializer.NewCodecFactory(Scheme)
var ParameterCodec = runtime.NewParameterCodec(Scheme)
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
AddToScheme(Scheme)
var localSchemeBuilder = runtime.SchemeBuilder{
convoxv1.AddToScheme,
}
// AddToScheme adds all types of this clientset into the given scheme. This allows composition
@ -45,10 +46,13 @@ func init() {
// )
//
// kclientset, _ := kubernetes.NewForConfig(c)
// aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
// _ = aggregatorclientsetscheme.AddToScheme(clientsetscheme.Scheme)
//
// After this, RawExtensions in Kubernetes types will serialize kube-aggregator types
// correctly.
func AddToScheme(scheme *runtime.Scheme) {
convoxv1.AddToScheme(scheme)
var AddToScheme = localSchemeBuilder.AddToScheme
func init() {
v1.AddToGroupVersion(Scheme, schema.GroupVersion{Version: "v1"})
utilruntime.Must(AddToScheme(Scheme))
}

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,6 +21,8 @@ limitations under the License.
package v1
import (
"time"
v1 "github.com/convox/convox/provider/k8s/pkg/apis/convox/v1"
scheme "github.com/convox/convox/provider/k8s/pkg/client/clientset/versioned/scheme"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -75,11 +79,16 @@ func (c *builds) Get(name string, options metav1.GetOptions) (result *v1.Build,
// List takes label and field selectors, and returns the list of Builds that match those selectors.
func (c *builds) List(opts metav1.ListOptions) (result *v1.BuildList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1.BuildList{}
err = c.client.Get().
Namespace(c.ns).
Resource("builds").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
@ -87,11 +96,16 @@ func (c *builds) List(opts metav1.ListOptions) (result *v1.BuildList, err error)
// Watch returns a watch.Interface that watches the requested builds.
func (c *builds) Watch(opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("builds").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
@ -133,10 +147,15 @@ func (c *builds) Delete(name string, options *metav1.DeleteOptions) error {
// DeleteCollection deletes a collection of objects.
func (c *builds) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("builds").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -21,7 +23,6 @@ package v1
import (
v1 "github.com/convox/convox/provider/k8s/pkg/apis/convox/v1"
"github.com/convox/convox/provider/k8s/pkg/client/clientset/versioned/scheme"
serializer "k8s.io/apimachinery/pkg/runtime/serializer"
rest "k8s.io/client-go/rest"
)
@ -76,7 +77,7 @@ func setConfigDefaults(config *rest.Config) error {
gv := v1.SchemeGroupVersion
config.GroupVersion = &gv
config.APIPath = "/apis"
config.NegotiatedSerializer = serializer.DirectCodecFactory{CodecFactory: scheme.Codecs}
config.NegotiatedSerializer = scheme.Codecs.WithoutConversion()
if config.UserAgent == "" {
config.UserAgent = rest.DefaultKubernetesUserAgent()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -119,7 +121,7 @@ func (c *FakeBuilds) DeleteCollection(options *v1.DeleteOptions, listOptions v1.
// Patch applies the patch and returns the patched build.
func (c *FakeBuilds) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *convoxv1.Build, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(buildsResource, c.ns, name, data, subresources...), &convoxv1.Build{})
Invokes(testing.NewPatchSubresourceAction(buildsResource, c.ns, name, pt, data, subresources...), &convoxv1.Build{})
if obj == nil {
return nil, err

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -119,7 +121,7 @@ func (c *FakeReleases) DeleteCollection(options *v1.DeleteOptions, listOptions v
// Patch applies the patch and returns the patched release.
func (c *FakeReleases) Patch(name string, pt types.PatchType, data []byte, subresources ...string) (result *convoxv1.Release, err error) {
obj, err := c.Fake.
Invokes(testing.NewPatchSubresourceAction(releasesResource, c.ns, name, data, subresources...), &convoxv1.Release{})
Invokes(testing.NewPatchSubresourceAction(releasesResource, c.ns, name, pt, data, subresources...), &convoxv1.Release{})
if obj == nil {
return nil, err

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by client-gen. DO NOT EDIT.
@ -19,6 +21,8 @@ limitations under the License.
package v1
import (
"time"
v1 "github.com/convox/convox/provider/k8s/pkg/apis/convox/v1"
scheme "github.com/convox/convox/provider/k8s/pkg/client/clientset/versioned/scheme"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
@ -75,11 +79,16 @@ func (c *releases) Get(name string, options metav1.GetOptions) (result *v1.Relea
// List takes label and field selectors, and returns the list of Releases that match those selectors.
func (c *releases) List(opts metav1.ListOptions) (result *v1.ReleaseList, err error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
result = &v1.ReleaseList{}
err = c.client.Get().
Namespace(c.ns).
Resource("releases").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Do().
Into(result)
return
@ -87,11 +96,16 @@ func (c *releases) List(opts metav1.ListOptions) (result *v1.ReleaseList, err er
// Watch returns a watch.Interface that watches the requested releases.
func (c *releases) Watch(opts metav1.ListOptions) (watch.Interface, error) {
var timeout time.Duration
if opts.TimeoutSeconds != nil {
timeout = time.Duration(*opts.TimeoutSeconds) * time.Second
}
opts.Watch = true
return c.client.Get().
Namespace(c.ns).
Resource("releases").
VersionedParams(&opts, scheme.ParameterCodec).
Timeout(timeout).
Watch()
}
@ -133,10 +147,15 @@ func (c *releases) Delete(name string, options *metav1.DeleteOptions) error {
// DeleteCollection deletes a collection of objects.
func (c *releases) DeleteCollection(options *metav1.DeleteOptions, listOptions metav1.ListOptions) error {
var timeout time.Duration
if listOptions.TimeoutSeconds != nil {
timeout = time.Duration(*listOptions.TimeoutSeconds) * time.Second
}
return c.client.Delete().
Namespace(c.ns).
Resource("releases").
VersionedParams(&listOptions, scheme.ParameterCodec).
Timeout(timeout).
Body(options).
Do().
Error()

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by informer-gen. DO NOT EDIT.
@ -27,6 +29,7 @@ import (
cache "k8s.io/client-go/tools/cache"
)
// NewInformerFunc takes versioned.Interface and time.Duration to return a SharedIndexInformer.
type NewInformerFunc func(versioned.Interface, time.Duration) cache.SharedIndexInformer
// SharedInformerFactory a small interface to allow for adding an informer without an import cycle
@ -35,4 +38,5 @@ type SharedInformerFactory interface {
InformerFor(obj runtime.Object, newFunc NewInformerFunc) cache.SharedIndexInformer
}
// TweakListOptionsFunc is a function that transforms a v1.ListOptions.
type TweakListOptionsFunc func(*v1.ListOptions)

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

View File

@ -1,5 +1,6 @@
/*
Copyright The Kubernetes Authors.
Copyright 2020 Convox, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
@ -12,6 +13,7 @@ distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
// Code generated by lister-gen. DO NOT EDIT.

View File

@ -0,0 +1,22 @@
apiVersion: v1
kind: Namespace
metadata:
annotations:
convox.com/lock: "true"
convox.com/params: '{"Test":"bar"}'
labels:
app: app1
name: app1
provider: k8s
rack: rack1
release: ""
system: convox
type: app
name: rack1-app1
ownerReferences:
- apiVersion: v1
blockOwnerDeletion: true
controller: true
kind: Namespace
name: ns1
uid: uid1

View File

@ -2,36 +2,9 @@ package local
import (
"context"
"errors"
"fmt"
"os"
"os/exec"
"regexp"
"strings"
"time"
// gv "github.com/GoogleCloudPlatform/gke-managed-certs/pkg/clientgen/clientset/versioned"
am "k8s.io/apimachinery/pkg/apis/meta/v1"
)
func (p *Provider) appRegistry(app string) (string, error) {
ns, err := p.Provider.Cluster.CoreV1().Namespaces().Get(p.AppNamespace(app), am.GetOptions{})
if err != nil {
return "", err
}
registry, ok := ns.ObjectMeta.Annotations["convox.registry"]
if !ok {
return "", fmt.Errorf("no registry for app: %s", app)
}
return registry, nil
}
// func (p *Provider) gkeManagedCertsClient() (gv.Interface, error) {
// return gv.NewForConfig(p.Config)
// }
func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid string, cancel func()) {
defer cancel()
@ -51,56 +24,3 @@ func (p *Provider) watchForProcessTermination(ctx context.Context, app, pid stri
}
}
}
func kubectl(args ...string) error {
cmd := exec.Command("kubectl", args...)
cmd.Env = os.Environ()
out, err := cmd.CombinedOutput()
if err != nil {
return errors.New(strings.TrimSpace(string(out)))
}
return nil
}
var outputConverter = regexp.MustCompile("([a-z])([A-Z])") // lower case letter followed by upper case
func outputToEnvironment(name string) string {
return strings.ToUpper(outputConverter.ReplaceAllString(name, "${1}_${2}"))
}
func upperName(name string) string {
if name == "" {
return ""
}
// replace underscores with dashes
name = strings.Replace(name, "_", "-", -1)
// myapp -> Myapp; my-app -> MyApp
us := strings.ToUpper(name[0:1]) + name[1:]
for {
i := strings.Index(us, "-")
if i == -1 {
break
}
s := us[0:i]
if len(us) > i+1 {
s += strings.ToUpper(us[i+1 : i+2])
}
if len(us) > i+2 {
s += us[i+2:]
}
us = s
}
return us
}

View File

@ -1,11 +0,0 @@
Auto-generated logging v2 clients
=================================
This package includes auto-generated clients for the logging v2 API.
Use the handwritten logging client (in the parent directory,
cloud.google.com/go/logging) in preference to this.
This code is EXPERIMENTAL and subject to CHANGE AT ANY TIME.

View File

@ -1,438 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
package logging
import (
"context"
"fmt"
"math"
"time"
"github.com/golang/protobuf/proto"
gax "github.com/googleapis/gax-go/v2"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/api/transport"
loggingpb "google.golang.org/genproto/googleapis/logging/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
)
// ConfigCallOptions contains the retry settings for each method of ConfigClient.
type ConfigCallOptions struct {
ListSinks []gax.CallOption
GetSink []gax.CallOption
CreateSink []gax.CallOption
UpdateSink []gax.CallOption
DeleteSink []gax.CallOption
ListExclusions []gax.CallOption
GetExclusion []gax.CallOption
CreateExclusion []gax.CallOption
UpdateExclusion []gax.CallOption
DeleteExclusion []gax.CallOption
}
func defaultConfigClientOptions() []option.ClientOption {
return []option.ClientOption{
option.WithEndpoint("logging.googleapis.com:443"),
option.WithScopes(DefaultAuthScopes()...),
}
}
func defaultConfigCallOptions() *ConfigCallOptions {
retry := map[[2]string][]gax.CallOption{
{"default", "idempotent"}: {
gax.WithRetry(func() gax.Retryer {
return gax.OnCodes([]codes.Code{
codes.DeadlineExceeded,
codes.Internal,
codes.Unavailable,
}, gax.Backoff{
Initial: 100 * time.Millisecond,
Max: 60000 * time.Millisecond,
Multiplier: 1.3,
})
}),
},
}
return &ConfigCallOptions{
ListSinks: retry[[2]string{"default", "idempotent"}],
GetSink: retry[[2]string{"default", "idempotent"}],
CreateSink: retry[[2]string{"default", "non_idempotent"}],
UpdateSink: retry[[2]string{"default", "idempotent"}],
DeleteSink: retry[[2]string{"default", "idempotent"}],
ListExclusions: retry[[2]string{"default", "idempotent"}],
GetExclusion: retry[[2]string{"default", "idempotent"}],
CreateExclusion: retry[[2]string{"default", "non_idempotent"}],
UpdateExclusion: retry[[2]string{"default", "non_idempotent"}],
DeleteExclusion: retry[[2]string{"default", "idempotent"}],
}
}
// ConfigClient is a client for interacting with Stackdriver Logging API.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type ConfigClient struct {
// The connection to the service.
conn *grpc.ClientConn
// The gRPC API client.
configClient loggingpb.ConfigServiceV2Client
// The call options for this service.
CallOptions *ConfigCallOptions
// The x-goog-* metadata to be sent with each request.
xGoogMetadata metadata.MD
}
// NewConfigClient creates a new config service v2 client.
//
// Service for configuring sinks used to export log entries out of
// Logging.
func NewConfigClient(ctx context.Context, opts ...option.ClientOption) (*ConfigClient, error) {
conn, err := transport.DialGRPC(ctx, append(defaultConfigClientOptions(), opts...)...)
if err != nil {
return nil, err
}
c := &ConfigClient{
conn: conn,
CallOptions: defaultConfigCallOptions(),
configClient: loggingpb.NewConfigServiceV2Client(conn),
}
c.SetGoogleClientInfo()
return c, nil
}
// Connection returns the client's connection to the API service.
func (c *ConfigClient) Connection() *grpc.ClientConn {
return c.conn
}
// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *ConfigClient) Close() error {
return c.conn.Close()
}
// SetGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *ConfigClient) SetGoogleClientInfo(keyval ...string) {
kv := append([]string{"gl-go", versionGo()}, keyval...)
kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}
// ListSinks lists sinks.
func (c *ConfigClient) ListSinks(ctx context.Context, req *loggingpb.ListSinksRequest, opts ...gax.CallOption) *LogSinkIterator {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.ListSinks[0:len(c.CallOptions.ListSinks):len(c.CallOptions.ListSinks)], opts...)
it := &LogSinkIterator{}
req = proto.Clone(req).(*loggingpb.ListSinksRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogSink, string, error) {
var resp *loggingpb.ListSinksResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.ListSinks(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.Sinks, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// GetSink gets a sink.
func (c *ConfigClient) GetSink(ctx context.Context, req *loggingpb.GetSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "sink_name", req.GetSinkName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.GetSink[0:len(c.CallOptions.GetSink):len(c.CallOptions.GetSink)], opts...)
var resp *loggingpb.LogSink
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.GetSink(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// CreateSink creates a sink that exports specified log entries to a destination. The
// export of newly-ingested log entries begins immediately, unless the sink's
// writer_identity is not permitted to write to the destination. A sink can
// export log entries only from the resource owning the sink.
func (c *ConfigClient) CreateSink(ctx context.Context, req *loggingpb.CreateSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.CreateSink[0:len(c.CallOptions.CreateSink):len(c.CallOptions.CreateSink)], opts...)
var resp *loggingpb.LogSink
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.CreateSink(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// UpdateSink updates a sink. This method replaces the following fields in the existing
// sink with values from the new sink: destination, and filter.
// The updated sink might also have a new writer_identity; see the
// unique_writer_identity field.
func (c *ConfigClient) UpdateSink(ctx context.Context, req *loggingpb.UpdateSinkRequest, opts ...gax.CallOption) (*loggingpb.LogSink, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "sink_name", req.GetSinkName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.UpdateSink[0:len(c.CallOptions.UpdateSink):len(c.CallOptions.UpdateSink)], opts...)
var resp *loggingpb.LogSink
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.UpdateSink(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// DeleteSink deletes a sink. If the sink has a unique writer_identity, then that
// service account is also deleted.
func (c *ConfigClient) DeleteSink(ctx context.Context, req *loggingpb.DeleteSinkRequest, opts ...gax.CallOption) error {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "sink_name", req.GetSinkName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.DeleteSink[0:len(c.CallOptions.DeleteSink):len(c.CallOptions.DeleteSink)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.configClient.DeleteSink(ctx, req, settings.GRPC...)
return err
}, opts...)
return err
}
// ListExclusions lists all the exclusions in a parent resource.
func (c *ConfigClient) ListExclusions(ctx context.Context, req *loggingpb.ListExclusionsRequest, opts ...gax.CallOption) *LogExclusionIterator {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.ListExclusions[0:len(c.CallOptions.ListExclusions):len(c.CallOptions.ListExclusions)], opts...)
it := &LogExclusionIterator{}
req = proto.Clone(req).(*loggingpb.ListExclusionsRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogExclusion, string, error) {
var resp *loggingpb.ListExclusionsResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.ListExclusions(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.Exclusions, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// GetExclusion gets the description of an exclusion.
func (c *ConfigClient) GetExclusion(ctx context.Context, req *loggingpb.GetExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.GetExclusion[0:len(c.CallOptions.GetExclusion):len(c.CallOptions.GetExclusion)], opts...)
var resp *loggingpb.LogExclusion
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.GetExclusion(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// CreateExclusion creates a new exclusion in a specified parent resource.
// Only log entries belonging to that resource can be excluded.
// You can have up to 10 exclusions in a resource.
func (c *ConfigClient) CreateExclusion(ctx context.Context, req *loggingpb.CreateExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.CreateExclusion[0:len(c.CallOptions.CreateExclusion):len(c.CallOptions.CreateExclusion)], opts...)
var resp *loggingpb.LogExclusion
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.CreateExclusion(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// UpdateExclusion changes one or more properties of an existing exclusion.
func (c *ConfigClient) UpdateExclusion(ctx context.Context, req *loggingpb.UpdateExclusionRequest, opts ...gax.CallOption) (*loggingpb.LogExclusion, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.UpdateExclusion[0:len(c.CallOptions.UpdateExclusion):len(c.CallOptions.UpdateExclusion)], opts...)
var resp *loggingpb.LogExclusion
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.configClient.UpdateExclusion(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// DeleteExclusion deletes an exclusion.
func (c *ConfigClient) DeleteExclusion(ctx context.Context, req *loggingpb.DeleteExclusionRequest, opts ...gax.CallOption) error {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "name", req.GetName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.DeleteExclusion[0:len(c.CallOptions.DeleteExclusion):len(c.CallOptions.DeleteExclusion)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.configClient.DeleteExclusion(ctx, req, settings.GRPC...)
return err
}, opts...)
return err
}
// LogExclusionIterator manages a stream of *loggingpb.LogExclusion.
type LogExclusionIterator struct {
items []*loggingpb.LogExclusion
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []*loggingpb.LogExclusion, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *LogExclusionIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *LogExclusionIterator) Next() (*loggingpb.LogExclusion, error) {
var item *loggingpb.LogExclusion
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *LogExclusionIterator) bufLen() int {
return len(it.items)
}
func (it *LogExclusionIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}
// LogSinkIterator manages a stream of *loggingpb.LogSink.
type LogSinkIterator struct {
items []*loggingpb.LogSink
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []*loggingpb.LogSink, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *LogSinkIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *LogSinkIterator) Next() (*loggingpb.LogSink, error) {
var item *loggingpb.LogSink
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *LogSinkIterator) bufLen() int {
return len(it.items)
}
func (it *LogSinkIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}

View File

@ -1,106 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
// Package logging is an auto-generated package for the
// Stackdriver Logging API.
//
// NOTE: This package is in alpha. It is not stable, and is likely to change.
//
// Writes log entries and manages your Logging configuration.
//
// Use of Context
//
// The ctx passed to NewClient is used for authentication requests and
// for creating the underlying connection, but is not used for subsequent calls.
// Individual methods on the client use the ctx given to them.
//
// To close the open connection, use the Close() method.
//
// For information about setting deadlines, reusing contexts, and more
// please visit godoc.org/cloud.google.com/go.
//
// Use the client at cloud.google.com/go/logging in preference to this.
package logging // import "cloud.google.com/go/logging/apiv2"
import (
"context"
"runtime"
"strings"
"unicode"
"google.golang.org/grpc/metadata"
)
func insertMetadata(ctx context.Context, mds ...metadata.MD) context.Context {
out, _ := metadata.FromOutgoingContext(ctx)
out = out.Copy()
for _, md := range mds {
for k, v := range md {
out[k] = append(out[k], v...)
}
}
return metadata.NewOutgoingContext(ctx, out)
}
// DefaultAuthScopes reports the default set of authentication scopes to use with this package.
func DefaultAuthScopes() []string {
return []string{
"https://www.googleapis.com/auth/cloud-platform",
"https://www.googleapis.com/auth/cloud-platform.read-only",
"https://www.googleapis.com/auth/logging.admin",
"https://www.googleapis.com/auth/logging.read",
"https://www.googleapis.com/auth/logging.write",
}
}
// versionGo returns the Go runtime version. The returned string
// has no whitespace, suitable for reporting in header.
func versionGo() string {
const develPrefix = "devel +"
s := runtime.Version()
if strings.HasPrefix(s, develPrefix) {
s = s[len(develPrefix):]
if p := strings.IndexFunc(s, unicode.IsSpace); p >= 0 {
s = s[:p]
}
return s
}
notSemverRune := func(r rune) bool {
return strings.IndexRune("0123456789.", r) < 0
}
if strings.HasPrefix(s, "go1") {
s = s[2:]
var prerelease string
if p := strings.IndexFunc(s, notSemverRune); p >= 0 {
s, prerelease = s[:p], s[p:]
}
if strings.HasSuffix(s, ".") {
s += "0"
} else if strings.Count(s, ".") < 2 {
s += ".0"
}
if prerelease != "" {
s += "-" + prerelease
}
return s
}
return "UNKNOWN"
}
const versionClient = "20190404"

View File

@ -1,410 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
package logging
import (
"context"
"fmt"
"math"
"time"
"github.com/golang/protobuf/proto"
gax "github.com/googleapis/gax-go/v2"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/api/transport"
monitoredrespb "google.golang.org/genproto/googleapis/api/monitoredres"
loggingpb "google.golang.org/genproto/googleapis/logging/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
)
// CallOptions contains the retry settings for each method of Client.
type CallOptions struct {
DeleteLog []gax.CallOption
WriteLogEntries []gax.CallOption
ListLogEntries []gax.CallOption
ListMonitoredResourceDescriptors []gax.CallOption
ListLogs []gax.CallOption
}
func defaultClientOptions() []option.ClientOption {
return []option.ClientOption{
option.WithEndpoint("logging.googleapis.com:443"),
option.WithScopes(DefaultAuthScopes()...),
}
}
func defaultCallOptions() *CallOptions {
retry := map[[2]string][]gax.CallOption{
{"default", "idempotent"}: {
gax.WithRetry(func() gax.Retryer {
return gax.OnCodes([]codes.Code{
codes.DeadlineExceeded,
codes.Internal,
codes.Unavailable,
}, gax.Backoff{
Initial: 100 * time.Millisecond,
Max: 60000 * time.Millisecond,
Multiplier: 1.3,
})
}),
},
}
return &CallOptions{
DeleteLog: retry[[2]string{"default", "idempotent"}],
WriteLogEntries: retry[[2]string{"default", "idempotent"}],
ListLogEntries: retry[[2]string{"default", "idempotent"}],
ListMonitoredResourceDescriptors: retry[[2]string{"default", "idempotent"}],
ListLogs: retry[[2]string{"default", "idempotent"}],
}
}
// Client is a client for interacting with Stackdriver Logging API.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type Client struct {
// The connection to the service.
conn *grpc.ClientConn
// The gRPC API client.
client loggingpb.LoggingServiceV2Client
// The call options for this service.
CallOptions *CallOptions
// The x-goog-* metadata to be sent with each request.
xGoogMetadata metadata.MD
}
// NewClient creates a new logging service v2 client.
//
// Service for ingesting and querying logs.
func NewClient(ctx context.Context, opts ...option.ClientOption) (*Client, error) {
conn, err := transport.DialGRPC(ctx, append(defaultClientOptions(), opts...)...)
if err != nil {
return nil, err
}
c := &Client{
conn: conn,
CallOptions: defaultCallOptions(),
client: loggingpb.NewLoggingServiceV2Client(conn),
}
c.SetGoogleClientInfo()
return c, nil
}
// Connection returns the client's connection to the API service.
func (c *Client) Connection() *grpc.ClientConn {
return c.conn
}
// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *Client) Close() error {
return c.conn.Close()
}
// SetGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *Client) SetGoogleClientInfo(keyval ...string) {
kv := append([]string{"gl-go", versionGo()}, keyval...)
kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}
// DeleteLog deletes all the log entries in a log.
// The log reappears if it receives new entries.
// Log entries written shortly before the delete operation might not be
// deleted.
func (c *Client) DeleteLog(ctx context.Context, req *loggingpb.DeleteLogRequest, opts ...gax.CallOption) error {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "log_name", req.GetLogName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.DeleteLog[0:len(c.CallOptions.DeleteLog):len(c.CallOptions.DeleteLog)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.client.DeleteLog(ctx, req, settings.GRPC...)
return err
}, opts...)
return err
}
// WriteLogEntries writes log entries to Logging. This API method is the
// only way to send log entries to Logging. This method
// is used, directly or indirectly, by the Logging agent
// (fluentd) and all logging libraries configured to use Logging.
// A single request may contain log entries for a maximum of 1000
// different resources (projects, organizations, billing accounts or
// folders)
func (c *Client) WriteLogEntries(ctx context.Context, req *loggingpb.WriteLogEntriesRequest, opts ...gax.CallOption) (*loggingpb.WriteLogEntriesResponse, error) {
ctx = insertMetadata(ctx, c.xGoogMetadata)
opts = append(c.CallOptions.WriteLogEntries[0:len(c.CallOptions.WriteLogEntries):len(c.CallOptions.WriteLogEntries)], opts...)
var resp *loggingpb.WriteLogEntriesResponse
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.client.WriteLogEntries(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// ListLogEntries lists log entries. Use this method to retrieve log entries from
// Logging. For ways to export log entries, see
// Exporting Logs (at /logging/docs/export).
func (c *Client) ListLogEntries(ctx context.Context, req *loggingpb.ListLogEntriesRequest, opts ...gax.CallOption) *LogEntryIterator {
ctx = insertMetadata(ctx, c.xGoogMetadata)
opts = append(c.CallOptions.ListLogEntries[0:len(c.CallOptions.ListLogEntries):len(c.CallOptions.ListLogEntries)], opts...)
it := &LogEntryIterator{}
req = proto.Clone(req).(*loggingpb.ListLogEntriesRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogEntry, string, error) {
var resp *loggingpb.ListLogEntriesResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.client.ListLogEntries(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.Entries, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// ListMonitoredResourceDescriptors lists the descriptors for monitored resource types used by Logging.
func (c *Client) ListMonitoredResourceDescriptors(ctx context.Context, req *loggingpb.ListMonitoredResourceDescriptorsRequest, opts ...gax.CallOption) *MonitoredResourceDescriptorIterator {
ctx = insertMetadata(ctx, c.xGoogMetadata)
opts = append(c.CallOptions.ListMonitoredResourceDescriptors[0:len(c.CallOptions.ListMonitoredResourceDescriptors):len(c.CallOptions.ListMonitoredResourceDescriptors)], opts...)
it := &MonitoredResourceDescriptorIterator{}
req = proto.Clone(req).(*loggingpb.ListMonitoredResourceDescriptorsRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]*monitoredrespb.MonitoredResourceDescriptor, string, error) {
var resp *loggingpb.ListMonitoredResourceDescriptorsResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.client.ListMonitoredResourceDescriptors(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.ResourceDescriptors, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// ListLogs lists the logs in projects, organizations, folders, or billing accounts.
// Only logs that have entries are listed.
func (c *Client) ListLogs(ctx context.Context, req *loggingpb.ListLogsRequest, opts ...gax.CallOption) *StringIterator {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.ListLogs[0:len(c.CallOptions.ListLogs):len(c.CallOptions.ListLogs)], opts...)
it := &StringIterator{}
req = proto.Clone(req).(*loggingpb.ListLogsRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]string, string, error) {
var resp *loggingpb.ListLogsResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.client.ListLogs(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.LogNames, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// LogEntryIterator manages a stream of *loggingpb.LogEntry.
type LogEntryIterator struct {
items []*loggingpb.LogEntry
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []*loggingpb.LogEntry, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *LogEntryIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *LogEntryIterator) Next() (*loggingpb.LogEntry, error) {
var item *loggingpb.LogEntry
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *LogEntryIterator) bufLen() int {
return len(it.items)
}
func (it *LogEntryIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}
// MonitoredResourceDescriptorIterator manages a stream of *monitoredrespb.MonitoredResourceDescriptor.
type MonitoredResourceDescriptorIterator struct {
items []*monitoredrespb.MonitoredResourceDescriptor
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []*monitoredrespb.MonitoredResourceDescriptor, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *MonitoredResourceDescriptorIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *MonitoredResourceDescriptorIterator) Next() (*monitoredrespb.MonitoredResourceDescriptor, error) {
var item *monitoredrespb.MonitoredResourceDescriptor
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *MonitoredResourceDescriptorIterator) bufLen() int {
return len(it.items)
}
func (it *MonitoredResourceDescriptorIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}
// StringIterator manages a stream of string.
type StringIterator struct {
items []string
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []string, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *StringIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *StringIterator) Next() (string, error) {
var item string
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *StringIterator) bufLen() int {
return len(it.items)
}
func (it *StringIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}

View File

@ -1,274 +0,0 @@
// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// Code generated by gapic-generator. DO NOT EDIT.
package logging
import (
"context"
"fmt"
"math"
"time"
"github.com/golang/protobuf/proto"
gax "github.com/googleapis/gax-go/v2"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
"google.golang.org/api/transport"
loggingpb "google.golang.org/genproto/googleapis/logging/v2"
"google.golang.org/grpc"
"google.golang.org/grpc/codes"
"google.golang.org/grpc/metadata"
)
// MetricsCallOptions contains the retry settings for each method of MetricsClient.
type MetricsCallOptions struct {
ListLogMetrics []gax.CallOption
GetLogMetric []gax.CallOption
CreateLogMetric []gax.CallOption
UpdateLogMetric []gax.CallOption
DeleteLogMetric []gax.CallOption
}
func defaultMetricsClientOptions() []option.ClientOption {
return []option.ClientOption{
option.WithEndpoint("logging.googleapis.com:443"),
option.WithScopes(DefaultAuthScopes()...),
}
}
func defaultMetricsCallOptions() *MetricsCallOptions {
retry := map[[2]string][]gax.CallOption{
{"default", "idempotent"}: {
gax.WithRetry(func() gax.Retryer {
return gax.OnCodes([]codes.Code{
codes.DeadlineExceeded,
codes.Internal,
codes.Unavailable,
}, gax.Backoff{
Initial: 100 * time.Millisecond,
Max: 60000 * time.Millisecond,
Multiplier: 1.3,
})
}),
},
}
return &MetricsCallOptions{
ListLogMetrics: retry[[2]string{"default", "idempotent"}],
GetLogMetric: retry[[2]string{"default", "idempotent"}],
CreateLogMetric: retry[[2]string{"default", "non_idempotent"}],
UpdateLogMetric: retry[[2]string{"default", "idempotent"}],
DeleteLogMetric: retry[[2]string{"default", "idempotent"}],
}
}
// MetricsClient is a client for interacting with Stackdriver Logging API.
//
// Methods, except Close, may be called concurrently. However, fields must not be modified concurrently with method calls.
type MetricsClient struct {
// The connection to the service.
conn *grpc.ClientConn
// The gRPC API client.
metricsClient loggingpb.MetricsServiceV2Client
// The call options for this service.
CallOptions *MetricsCallOptions
// The x-goog-* metadata to be sent with each request.
xGoogMetadata metadata.MD
}
// NewMetricsClient creates a new metrics service v2 client.
//
// Service for configuring logs-based metrics.
func NewMetricsClient(ctx context.Context, opts ...option.ClientOption) (*MetricsClient, error) {
conn, err := transport.DialGRPC(ctx, append(defaultMetricsClientOptions(), opts...)...)
if err != nil {
return nil, err
}
c := &MetricsClient{
conn: conn,
CallOptions: defaultMetricsCallOptions(),
metricsClient: loggingpb.NewMetricsServiceV2Client(conn),
}
c.SetGoogleClientInfo()
return c, nil
}
// Connection returns the client's connection to the API service.
func (c *MetricsClient) Connection() *grpc.ClientConn {
return c.conn
}
// Close closes the connection to the API service. The user should invoke this when
// the client is no longer required.
func (c *MetricsClient) Close() error {
return c.conn.Close()
}
// SetGoogleClientInfo sets the name and version of the application in
// the `x-goog-api-client` header passed on each request. Intended for
// use by Google-written clients.
func (c *MetricsClient) SetGoogleClientInfo(keyval ...string) {
kv := append([]string{"gl-go", versionGo()}, keyval...)
kv = append(kv, "gapic", versionClient, "gax", gax.Version, "grpc", grpc.Version)
c.xGoogMetadata = metadata.Pairs("x-goog-api-client", gax.XGoogHeader(kv...))
}
// ListLogMetrics lists logs-based metrics.
func (c *MetricsClient) ListLogMetrics(ctx context.Context, req *loggingpb.ListLogMetricsRequest, opts ...gax.CallOption) *LogMetricIterator {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.ListLogMetrics[0:len(c.CallOptions.ListLogMetrics):len(c.CallOptions.ListLogMetrics)], opts...)
it := &LogMetricIterator{}
req = proto.Clone(req).(*loggingpb.ListLogMetricsRequest)
it.InternalFetch = func(pageSize int, pageToken string) ([]*loggingpb.LogMetric, string, error) {
var resp *loggingpb.ListLogMetricsResponse
req.PageToken = pageToken
if pageSize > math.MaxInt32 {
req.PageSize = math.MaxInt32
} else {
req.PageSize = int32(pageSize)
}
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.metricsClient.ListLogMetrics(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, "", err
}
return resp.Metrics, resp.NextPageToken, nil
}
fetch := func(pageSize int, pageToken string) (string, error) {
items, nextPageToken, err := it.InternalFetch(pageSize, pageToken)
if err != nil {
return "", err
}
it.items = append(it.items, items...)
return nextPageToken, nil
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(fetch, it.bufLen, it.takeBuf)
it.pageInfo.MaxSize = int(req.PageSize)
return it
}
// GetLogMetric gets a logs-based metric.
func (c *MetricsClient) GetLogMetric(ctx context.Context, req *loggingpb.GetLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "metric_name", req.GetMetricName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.GetLogMetric[0:len(c.CallOptions.GetLogMetric):len(c.CallOptions.GetLogMetric)], opts...)
var resp *loggingpb.LogMetric
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.metricsClient.GetLogMetric(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// CreateLogMetric creates a logs-based metric.
func (c *MetricsClient) CreateLogMetric(ctx context.Context, req *loggingpb.CreateLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "parent", req.GetParent()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.CreateLogMetric[0:len(c.CallOptions.CreateLogMetric):len(c.CallOptions.CreateLogMetric)], opts...)
var resp *loggingpb.LogMetric
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.metricsClient.CreateLogMetric(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// UpdateLogMetric creates or updates a logs-based metric.
func (c *MetricsClient) UpdateLogMetric(ctx context.Context, req *loggingpb.UpdateLogMetricRequest, opts ...gax.CallOption) (*loggingpb.LogMetric, error) {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "metric_name", req.GetMetricName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.UpdateLogMetric[0:len(c.CallOptions.UpdateLogMetric):len(c.CallOptions.UpdateLogMetric)], opts...)
var resp *loggingpb.LogMetric
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
resp, err = c.metricsClient.UpdateLogMetric(ctx, req, settings.GRPC...)
return err
}, opts...)
if err != nil {
return nil, err
}
return resp, nil
}
// DeleteLogMetric deletes a logs-based metric.
func (c *MetricsClient) DeleteLogMetric(ctx context.Context, req *loggingpb.DeleteLogMetricRequest, opts ...gax.CallOption) error {
md := metadata.Pairs("x-goog-request-params", fmt.Sprintf("%s=%v", "metric_name", req.GetMetricName()))
ctx = insertMetadata(ctx, c.xGoogMetadata, md)
opts = append(c.CallOptions.DeleteLogMetric[0:len(c.CallOptions.DeleteLogMetric):len(c.CallOptions.DeleteLogMetric)], opts...)
err := gax.Invoke(ctx, func(ctx context.Context, settings gax.CallSettings) error {
var err error
_, err = c.metricsClient.DeleteLogMetric(ctx, req, settings.GRPC...)
return err
}, opts...)
return err
}
// LogMetricIterator manages a stream of *loggingpb.LogMetric.
type LogMetricIterator struct {
items []*loggingpb.LogMetric
pageInfo *iterator.PageInfo
nextFunc func() error
// InternalFetch is for use by the Google Cloud Libraries only.
// It is not part of the stable interface of this package.
//
// InternalFetch returns results from a single call to the underlying RPC.
// The number of results is no greater than pageSize.
// If there are no more results, nextPageToken is empty and err is nil.
InternalFetch func(pageSize int, pageToken string) (results []*loggingpb.LogMetric, nextPageToken string, err error)
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *LogMetricIterator) PageInfo() *iterator.PageInfo {
return it.pageInfo
}
// Next returns the next result. Its second return value is iterator.Done if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *LogMetricIterator) Next() (*loggingpb.LogMetric, error) {
var item *loggingpb.LogMetric
if err := it.nextFunc(); err != nil {
return item, err
}
item = it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *LogMetricIterator) bufLen() int {
return len(it.items)
}
func (it *LogMetricIterator) takeBuf() interface{} {
b := it.items
it.items = nil
return b
}

View File

@ -1,107 +0,0 @@
// Copyright 2018 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logging
// ConfigProjectPath returns the path for the project resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s", project)
// instead.
func ConfigProjectPath(project string) string {
return "" +
"projects/" +
project +
""
}
// ConfigSinkPath returns the path for the sink resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s/sinks/%s", project, sink)
// instead.
func ConfigSinkPath(project, sink string) string {
return "" +
"projects/" +
project +
"/sinks/" +
sink +
""
}
// ConfigExclusionPath returns the path for the exclusion resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s/exclusions/%s", project, exclusion)
// instead.
func ConfigExclusionPath(project, exclusion string) string {
return "" +
"projects/" +
project +
"/exclusions/" +
exclusion +
""
}
// ProjectPath returns the path for the project resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s", project)
// instead.
func ProjectPath(project string) string {
return "" +
"projects/" +
project +
""
}
// LogPath returns the path for the log resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s/logs/%s", project, log)
// instead.
func LogPath(project, log string) string {
return "" +
"projects/" +
project +
"/logs/" +
log +
""
}
// MetricsProjectPath returns the path for the project resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s", project)
// instead.
func MetricsProjectPath(project string) string {
return "" +
"projects/" +
project +
""
}
// MetricsMetricPath returns the path for the metric resource.
//
// Deprecated: Use
// fmt.Sprintf("projects/%s/metrics/%s", project, metric)
// instead.
func MetricsMetricPath(project, metric string) string {
return "" +
"projects/" +
project +
"/metrics/" +
metric +
""
}

View File

@ -1,134 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
/*
Package logging contains a Stackdriver Logging client suitable for writing logs.
For reading logs, and working with sinks, metrics and monitored resources,
see package cloud.google.com/go/logging/logadmin.
This client uses Logging API v2.
See https://cloud.google.com/logging/docs/api/v2/ for an introduction to the API.
Creating a Client
Use a Client to interact with the Stackdriver Logging API.
// Create a Client
ctx := context.Background()
client, err := logging.NewClient(ctx, "my-project")
if err != nil {
// TODO: Handle error.
}
Basic Usage
For most use cases, you'll want to add log entries to a buffer to be periodically
flushed (automatically and asynchronously) to the Stackdriver Logging service.
// Initialize a logger
lg := client.Logger("my-log")
// Add entry to log buffer
lg.Log(logging.Entry{Payload: "something happened!"})
Closing your Client
You should call Client.Close before your program exits to flush any buffered log entries to the Stackdriver Logging service.
// Close the client when finished.
err = client.Close()
if err != nil {
// TODO: Handle error.
}
Synchronous Logging
For critical errors, you may want to send your log entries immediately.
LogSync is slow and will block until the log entry has been sent, so it is
not recommended for normal use.
err = lg.LogSync(ctx, logging.Entry{Payload: "ALERT! Something critical happened!"})
if err != nil {
// TODO: Handle error.
}
Payloads
An entry payload can be a string, as in the examples above. It can also be any value
that can be marshaled to a JSON object, like a map[string]interface{} or a struct:
type MyEntry struct {
Name string
Count int
}
lg.Log(logging.Entry{Payload: MyEntry{Name: "Bob", Count: 3}})
If you have a []byte of JSON, wrap it in json.RawMessage:
j := []byte(`{"Name": "Bob", "Count": 3}`)
lg.Log(logging.Entry{Payload: json.RawMessage(j)})
The Standard Logger Interface
You may want use a standard log.Logger in your program.
// stdlg implements log.Logger
stdlg := lg.StandardLogger(logging.Info)
stdlg.Println("some info")
Log Levels
An Entry may have one of a number of severity levels associated with it.
logging.Entry{
Payload: "something terrible happened!",
Severity: logging.Critical,
}
Viewing Logs
You can view Stackdriver logs for projects at
https://console.cloud.google.com/logs/viewer. Use the dropdown at the top left. When
running from a Google Cloud Platform VM, select "GCE VM Instance". Otherwise, select
"Google Project" and then the project ID. Logs for organizations, folders and billing
accounts can be viewed on the command line with the "gcloud logging read" command.
Grouping Logs by Request
To group all the log entries written during a single HTTP request, create two
Loggers, a "parent" and a "child," with different log IDs. Both should be in the same
project, and have the same MonitoredResouce type and labels.
- Parent entries must have HTTPRequest.Request populated. (Strictly speaking, only the URL is necessary.)
- A child entry's timestamp must be within the time interval covered by the parent request (i.e., older
than parent.Timestamp, and newer than parent.Timestamp - parent.HTTPRequest.Latency, assuming the
parent timestamp marks the end of the request.
- The trace field must be populated in all of the entries and match exactly.
You should observe the child log entries grouped under the parent on the console. The
parent entry will not inherit the severity of its children; you must update the
parent severity yourself.
*/
package logging // import "cloud.google.com/go/logging"

View File

@ -1,41 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package internal
import (
"fmt"
"strings"
)
const (
// ProdAddr is the production address.
ProdAddr = "logging.googleapis.com:443"
)
// LogPath creates a formatted path from a parent and a logID.
func LogPath(parent, logID string) string {
logID = strings.Replace(logID, "/", "%2F", -1)
return fmt.Sprintf("%s/logs/%s", parent, logID)
}
// LogIDFromPath parses and returns the ID from a log path.
func LogIDFromPath(parent, path string) string {
start := len(parent) + len("/logs/")
if len(path) < start {
return ""
}
logID := path[start:]
return strings.Replace(logID, "%2F", "/", -1)
}

View File

@ -1,397 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// These features are missing now, but will likely be added:
// - There is no way to specify CallOptions.
// Package logadmin contains a Stackdriver Logging client that can be used
// for reading logs and working with sinks, metrics and monitored resources.
// For a client that can write logs, see package cloud.google.com/go/logging.
//
// The client uses Logging API v2.
// See https://cloud.google.com/logging/docs/api/v2/ for an introduction to the API.
//
// Note: This package is in beta. Some backwards-incompatible changes may occur.
package logadmin // import "cloud.google.com/go/logging/logadmin"
import (
"context"
"fmt"
"net/http"
"net/url"
"strings"
"time"
"cloud.google.com/go/internal/version"
"cloud.google.com/go/logging"
vkit "cloud.google.com/go/logging/apiv2"
"cloud.google.com/go/logging/internal"
"github.com/golang/protobuf/ptypes"
gax "github.com/googleapis/gax-go/v2"
"google.golang.org/api/iterator"
"google.golang.org/api/option"
_ "google.golang.org/genproto/googleapis/appengine/logging/v1" // Import the following so EntryIterator can unmarshal log protos.
_ "google.golang.org/genproto/googleapis/cloud/audit"
logtypepb "google.golang.org/genproto/googleapis/logging/type"
logpb "google.golang.org/genproto/googleapis/logging/v2"
"google.golang.org/grpc/codes"
)
// Client is a Logging client. A Client is associated with a single Cloud project.
type Client struct {
lClient *vkit.Client // logging client
sClient *vkit.ConfigClient // sink client
mClient *vkit.MetricsClient // metric client
parent string
closed bool
}
// NewClient returns a new logging client associated with the provided project ID.
//
// By default NewClient uses AdminScope. To use a different scope, call
// NewClient using a WithScopes option (see https://godoc.org/google.golang.org/api/option#WithScopes).
func NewClient(ctx context.Context, parent string, opts ...option.ClientOption) (*Client, error) {
if !strings.ContainsRune(parent, '/') {
parent = "projects/" + parent
}
opts = append([]option.ClientOption{
option.WithEndpoint(internal.ProdAddr),
option.WithScopes(logging.AdminScope),
}, opts...)
lc, err := vkit.NewClient(ctx, opts...)
if err != nil {
return nil, err
}
// TODO(jba): pass along any client options that should be provided to all clients.
sc, err := vkit.NewConfigClient(ctx, option.WithGRPCConn(lc.Connection()))
if err != nil {
return nil, err
}
mc, err := vkit.NewMetricsClient(ctx, option.WithGRPCConn(lc.Connection()))
if err != nil {
return nil, err
}
// Retry some non-idempotent methods on INTERNAL, because it happens sometimes
// and in all observed cases the operation did not complete.
retryerOnInternal := func() gax.Retryer {
return gax.OnCodes([]codes.Code{
codes.Internal,
}, gax.Backoff{
Initial: 100 * time.Millisecond,
Max: 1000 * time.Millisecond,
Multiplier: 1.2,
})
}
mc.CallOptions.CreateLogMetric = []gax.CallOption{gax.WithRetry(retryerOnInternal)}
mc.CallOptions.UpdateLogMetric = []gax.CallOption{gax.WithRetry(retryerOnInternal)}
lc.SetGoogleClientInfo("gccl", version.Repo)
sc.SetGoogleClientInfo("gccl", version.Repo)
mc.SetGoogleClientInfo("gccl", version.Repo)
client := &Client{
lClient: lc,
sClient: sc,
mClient: mc,
parent: parent,
}
return client, nil
}
// Close closes the client.
func (c *Client) Close() error {
if c.closed {
return nil
}
// Return only the first error. Since all clients share an underlying connection,
// Closes after the first always report a "connection is closing" error.
err := c.lClient.Close()
_ = c.sClient.Close()
_ = c.mClient.Close()
c.closed = true
return err
}
// DeleteLog deletes a log and all its log entries. The log will reappear if it receives new entries.
// logID identifies the log within the project. An example log ID is "syslog". Requires AdminScope.
func (c *Client) DeleteLog(ctx context.Context, logID string) error {
return c.lClient.DeleteLog(ctx, &logpb.DeleteLogRequest{
LogName: internal.LogPath(c.parent, logID),
})
}
func toHTTPRequest(p *logtypepb.HttpRequest) (*logging.HTTPRequest, error) {
if p == nil {
return nil, nil
}
u, err := url.Parse(p.RequestUrl)
if err != nil {
return nil, err
}
var dur time.Duration
if p.Latency != nil {
dur, err = ptypes.Duration(p.Latency)
if err != nil {
return nil, err
}
}
hr := &http.Request{
Method: p.RequestMethod,
URL: u,
Header: map[string][]string{},
}
if p.UserAgent != "" {
hr.Header.Set("User-Agent", p.UserAgent)
}
if p.Referer != "" {
hr.Header.Set("Referer", p.Referer)
}
return &logging.HTTPRequest{
Request: hr,
RequestSize: p.RequestSize,
Status: int(p.Status),
ResponseSize: p.ResponseSize,
Latency: dur,
RemoteIP: p.RemoteIp,
CacheHit: p.CacheHit,
CacheValidatedWithOriginServer: p.CacheValidatedWithOriginServer,
}, nil
}
// An EntriesOption is an option for listing log entries.
type EntriesOption interface {
set(*logpb.ListLogEntriesRequest)
}
// ProjectIDs sets the project IDs or project numbers from which to retrieve
// log entries. Examples of a project ID: "my-project-1A", "1234567890".
func ProjectIDs(pids []string) EntriesOption { return projectIDs(pids) }
type projectIDs []string
func (p projectIDs) set(r *logpb.ListLogEntriesRequest) {
r.ResourceNames = make([]string, len(p))
for i, v := range p {
r.ResourceNames[i] = fmt.Sprintf("projects/%s", v)
}
}
// ResourceNames sets the resource names from which to retrieve
// log entries. Examples: "projects/my-project-1A", "organizations/my-org".
func ResourceNames(rns []string) EntriesOption { return resourceNames(rns) }
type resourceNames []string
func (rn resourceNames) set(r *logpb.ListLogEntriesRequest) {
r.ResourceNames = append([]string(nil), rn...)
}
// Filter sets an advanced logs filter for listing log entries (see
// https://cloud.google.com/logging/docs/view/advanced_filters). The filter is
// compared against all log entries in the projects specified by ProjectIDs.
// Only entries that match the filter are retrieved. An empty filter (the
// default) matches all log entries.
//
// In the filter string, log names must be written in their full form, as
// "projects/PROJECT-ID/logs/LOG-ID". Forward slashes in LOG-ID must be
// replaced by %2F before calling Filter.
//
// Timestamps in the filter string must be written in RFC 3339 format. See the
// timestamp example.
func Filter(f string) EntriesOption { return filter(f) }
type filter string
func (f filter) set(r *logpb.ListLogEntriesRequest) { r.Filter = string(f) }
// NewestFirst causes log entries to be listed from most recent (newest) to
// least recent (oldest). By default, they are listed from oldest to newest.
func NewestFirst() EntriesOption { return newestFirst{} }
type newestFirst struct{}
func (newestFirst) set(r *logpb.ListLogEntriesRequest) { r.OrderBy = "timestamp desc" }
// Entries returns an EntryIterator for iterating over log entries. By default,
// the log entries will be restricted to those from the project passed to
// NewClient. This may be overridden by passing a ProjectIDs option. Requires ReadScope or AdminScope.
func (c *Client) Entries(ctx context.Context, opts ...EntriesOption) *EntryIterator {
it := &EntryIterator{
it: c.lClient.ListLogEntries(ctx, listLogEntriesRequest(c.parent, opts)),
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
it.fetch,
func() int { return len(it.items) },
func() interface{} { b := it.items; it.items = nil; return b })
return it
}
func listLogEntriesRequest(parent string, opts []EntriesOption) *logpb.ListLogEntriesRequest {
req := &logpb.ListLogEntriesRequest{
ResourceNames: []string{parent},
}
for _, opt := range opts {
opt.set(req)
}
return req
}
// An EntryIterator iterates over log entries.
type EntryIterator struct {
it *vkit.LogEntryIterator
pageInfo *iterator.PageInfo
nextFunc func() error
items []*logging.Entry
}
// PageInfo supports pagination. See https://godoc.org/google.golang.org/api/iterator package for details.
func (it *EntryIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
// Next returns the next result. Its second return value is iterator.Done
// (https://godoc.org/google.golang.org/api/iterator) if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *EntryIterator) Next() (*logging.Entry, error) {
if err := it.nextFunc(); err != nil {
return nil, err
}
item := it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *EntryIterator) fetch(pageSize int, pageToken string) (string, error) {
return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
item, err := it.it.Next()
if err != nil {
return err
}
e, err := fromLogEntry(item)
if err != nil {
return err
}
it.items = append(it.items, e)
return nil
})
}
var slashUnescaper = strings.NewReplacer("%2F", "/", "%2f", "/")
func fromLogEntry(le *logpb.LogEntry) (*logging.Entry, error) {
time, err := ptypes.Timestamp(le.Timestamp)
if err != nil {
return nil, err
}
var payload interface{}
switch x := le.Payload.(type) {
case *logpb.LogEntry_TextPayload:
payload = x.TextPayload
case *logpb.LogEntry_ProtoPayload:
var d ptypes.DynamicAny
if err := ptypes.UnmarshalAny(x.ProtoPayload, &d); err != nil {
return nil, fmt.Errorf("logging: unmarshalling proto payload: %v", err)
}
payload = d.Message
case *logpb.LogEntry_JsonPayload:
// Leave this as a Struct.
// TODO(jba): convert to map[string]interface{}?
payload = x.JsonPayload
default:
return nil, fmt.Errorf("logging: unknown payload type: %T", le.Payload)
}
hr, err := toHTTPRequest(le.HttpRequest)
if err != nil {
return nil, err
}
return &logging.Entry{
Timestamp: time,
Severity: logging.Severity(le.Severity),
Payload: payload,
Labels: le.Labels,
InsertID: le.InsertId,
HTTPRequest: hr,
Operation: le.Operation,
LogName: slashUnescaper.Replace(le.LogName),
Resource: le.Resource,
Trace: le.Trace,
SourceLocation: le.SourceLocation,
}, nil
}
// Logs lists the logs owned by the parent resource of the client.
func (c *Client) Logs(ctx context.Context) *LogIterator {
it := &LogIterator{
parentResource: c.parent,
it: c.lClient.ListLogs(ctx, &logpb.ListLogsRequest{Parent: c.parent}),
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
it.fetch,
func() int { return len(it.items) },
func() interface{} { b := it.items; it.items = nil; return b })
return it
}
// A LogIterator iterates over logs.
type LogIterator struct {
parentResource string
it *vkit.StringIterator
pageInfo *iterator.PageInfo
nextFunc func() error
items []string
}
// PageInfo supports pagination. See https://godoc.org/google.golang.org/api/iterator package for details.
func (it *LogIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
// Next returns the next result. Its second return value is iterator.Done
// (https://godoc.org/google.golang.org/api/iterator) if there are no more
// results. Once Next returns Done, all subsequent calls will return Done.
func (it *LogIterator) Next() (string, error) {
if err := it.nextFunc(); err != nil {
return "", err
}
item := it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *LogIterator) fetch(pageSize int, pageToken string) (string, error) {
return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
logPath, err := it.it.Next()
if err != nil {
return err
}
logID := internal.LogIDFromPath(it.parentResource, logPath)
it.items = append(it.items, logID)
return nil
})
}
// Common fetch code for iterators that are backed by vkit iterators.
func iterFetch(pageSize int, pageToken string, pi *iterator.PageInfo, next func() error) (string, error) {
pi.MaxSize = pageSize
pi.Token = pageToken
// Get one item, which will fill the buffer.
if err := next(); err != nil {
return "", err
}
// Collect the rest of the buffer.
for pi.Remaining() > 0 {
if err := next(); err != nil {
return "", err
}
}
return pi.Token, nil
}

View File

@ -1,154 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logadmin
import (
"context"
"fmt"
vkit "cloud.google.com/go/logging/apiv2"
"google.golang.org/api/iterator"
logpb "google.golang.org/genproto/googleapis/logging/v2"
)
// Metric describes a logs-based metric. The value of the metric is the
// number of log entries that match a logs filter.
//
// Metrics are a feature of Stackdriver Monitoring.
// See https://cloud.google.com/monitoring/api/v3/metrics for more about them.
type Metric struct {
// ID is a client-assigned metric identifier. Example:
// "severe_errors". Metric identifiers are limited to 1000
// characters and can include only the following characters: A-Z,
// a-z, 0-9, and the special characters _-.,+!*',()%/\. The
// forward-slash character (/) denotes a hierarchy of name pieces,
// and it cannot be the first character of the name.
ID string
// Description describes this metric. It is used in documentation.
Description string
// Filter is an advanced logs filter (see
// https://cloud.google.com/logging/docs/view/advanced_filters).
// Example: "logName:syslog AND severity>=ERROR".
Filter string
}
// CreateMetric creates a logs-based metric.
func (c *Client) CreateMetric(ctx context.Context, m *Metric) error {
_, err := c.mClient.CreateLogMetric(ctx, &logpb.CreateLogMetricRequest{
Parent: c.parent,
Metric: toLogMetric(m),
})
return err
}
// DeleteMetric deletes a log-based metric.
// The provided metric ID is the metric identifier. For example, "severe_errors".
func (c *Client) DeleteMetric(ctx context.Context, metricID string) error {
return c.mClient.DeleteLogMetric(ctx, &logpb.DeleteLogMetricRequest{
MetricName: c.metricPath(metricID),
})
}
// Metric gets a logs-based metric.
// The provided metric ID is the metric identifier. For example, "severe_errors".
// Requires ReadScope or AdminScope.
func (c *Client) Metric(ctx context.Context, metricID string) (*Metric, error) {
lm, err := c.mClient.GetLogMetric(ctx, &logpb.GetLogMetricRequest{
MetricName: c.metricPath(metricID),
})
if err != nil {
return nil, err
}
return fromLogMetric(lm), nil
}
// UpdateMetric creates a logs-based metric if it does not exist, or updates an
// existing one.
func (c *Client) UpdateMetric(ctx context.Context, m *Metric) error {
_, err := c.mClient.UpdateLogMetric(ctx, &logpb.UpdateLogMetricRequest{
MetricName: c.metricPath(m.ID),
Metric: toLogMetric(m),
})
return err
}
func (c *Client) metricPath(metricID string) string {
return fmt.Sprintf("%s/metrics/%s", c.parent, metricID)
}
// Metrics returns a MetricIterator for iterating over all Metrics in the Client's project.
// Requires ReadScope or AdminScope.
func (c *Client) Metrics(ctx context.Context) *MetricIterator {
it := &MetricIterator{
it: c.mClient.ListLogMetrics(ctx, &logpb.ListLogMetricsRequest{Parent: c.parent}),
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
it.fetch,
func() int { return len(it.items) },
func() interface{} { b := it.items; it.items = nil; return b })
return it
}
// A MetricIterator iterates over Metrics.
type MetricIterator struct {
it *vkit.LogMetricIterator
pageInfo *iterator.PageInfo
nextFunc func() error
items []*Metric
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *MetricIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
// Next returns the next result. Its second return value is Done if there are
// no more results. Once Next returns Done, all subsequent calls will return
// Done.
func (it *MetricIterator) Next() (*Metric, error) {
if err := it.nextFunc(); err != nil {
return nil, err
}
item := it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *MetricIterator) fetch(pageSize int, pageToken string) (string, error) {
return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
item, err := it.it.Next()
if err != nil {
return err
}
it.items = append(it.items, fromLogMetric(item))
return nil
})
}
func toLogMetric(m *Metric) *logpb.LogMetric {
return &logpb.LogMetric{
Name: m.ID,
Description: m.Description,
Filter: m.Filter,
}
}
func fromLogMetric(lm *logpb.LogMetric) *Metric {
return &Metric{
ID: lm.Name,
Description: lm.Description,
Filter: lm.Filter,
}
}

View File

@ -1,75 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logadmin
import (
"context"
vkit "cloud.google.com/go/logging/apiv2"
"google.golang.org/api/iterator"
mrpb "google.golang.org/genproto/googleapis/api/monitoredres"
logpb "google.golang.org/genproto/googleapis/logging/v2"
)
// ResourceDescriptors returns a ResourceDescriptorIterator
// for iterating over MonitoredResourceDescriptors. Requires ReadScope or AdminScope.
// See https://cloud.google.com/logging/docs/api/v2/#monitored-resources for an explanation of
// monitored resources.
// See https://cloud.google.com/logging/docs/api/v2/resource-list for a list of monitored resources.
func (c *Client) ResourceDescriptors(ctx context.Context) *ResourceDescriptorIterator {
it := &ResourceDescriptorIterator{
it: c.lClient.ListMonitoredResourceDescriptors(ctx,
&logpb.ListMonitoredResourceDescriptorsRequest{}),
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
it.fetch,
func() int { return len(it.items) },
func() interface{} { b := it.items; it.items = nil; return b })
return it
}
// ResourceDescriptorIterator is an iterator over MonitoredResourceDescriptors.
type ResourceDescriptorIterator struct {
it *vkit.MonitoredResourceDescriptorIterator
pageInfo *iterator.PageInfo
nextFunc func() error
items []*mrpb.MonitoredResourceDescriptor
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *ResourceDescriptorIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
// Next returns the next result. Its second return value is Done if there are
// no more results. Once Next returns Done, all subsequent calls will return
// Done.
func (it *ResourceDescriptorIterator) Next() (*mrpb.MonitoredResourceDescriptor, error) {
if err := it.nextFunc(); err != nil {
return nil, err
}
item := it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *ResourceDescriptorIterator) fetch(pageSize int, pageToken string) (string, error) {
return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
item, err := it.it.Next()
if err != nil {
return err
}
it.items = append(it.items, item)
return nil
})
}

View File

@ -1,256 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package logadmin
import (
"context"
"errors"
"fmt"
vkit "cloud.google.com/go/logging/apiv2"
"google.golang.org/api/iterator"
logpb "google.golang.org/genproto/googleapis/logging/v2"
maskpb "google.golang.org/genproto/protobuf/field_mask"
)
// Sink describes a sink used to export log entries outside Stackdriver
// Logging. Incoming log entries matching a filter are exported to a
// destination (a Cloud Storage bucket, BigQuery dataset or Cloud Pub/Sub
// topic).
//
// For more information, see https://cloud.google.com/logging/docs/export/using_exported_logs.
// (The Sinks in this package are what the documentation refers to as "project sinks".)
type Sink struct {
// ID is a client-assigned sink identifier. Example:
// "my-severe-errors-to-pubsub".
// Sink identifiers are limited to 1000 characters
// and can include only the following characters: A-Z, a-z,
// 0-9, and the special characters "_-.".
ID string
// Destination is the export destination. See
// https://cloud.google.com/logging/docs/api/tasks/exporting-logs.
// Examples: "storage.googleapis.com/a-bucket",
// "bigquery.googleapis.com/projects/a-project-id/datasets/a-dataset".
Destination string
// Filter optionally specifies an advanced logs filter (see
// https://cloud.google.com/logging/docs/view/advanced_filters) that
// defines the log entries to be exported. Example: "logName:syslog AND
// severity>=ERROR". If omitted, all entries are returned.
Filter string
// WriterIdentity must be a service account name. When exporting logs, Logging
// adopts this identity for authorization. The export destination's owner must
// give this service account permission to write to the export destination.
WriterIdentity string
// IncludeChildren, when set to true, allows the sink to export log entries from
// the organization or folder, plus (recursively) from any contained folders, billing
// accounts, or projects. IncludeChildren is false by default. You can use the sink's
// filter to choose log entries from specific projects, specific resource types, or
// specific named logs.
//
// Caution: If you enable this feature, your aggregated export sink might export
// a very large number of log entries. To avoid exporting too many log entries,
// design your aggregated export sink filter carefully, as described on
// https://cloud.google.com/logging/docs/export/aggregated_exports.
IncludeChildren bool
}
// CreateSink creates a Sink. It returns an error if the Sink already exists.
// Requires AdminScope.
func (c *Client) CreateSink(ctx context.Context, sink *Sink) (*Sink, error) {
return c.CreateSinkOpt(ctx, sink, SinkOptions{})
}
// CreateSinkOpt creates a Sink using the provided options. It returns an
// error if the Sink already exists. Requires AdminScope.
func (c *Client) CreateSinkOpt(ctx context.Context, sink *Sink, opts SinkOptions) (*Sink, error) {
ls, err := c.sClient.CreateSink(ctx, &logpb.CreateSinkRequest{
Parent: c.parent,
Sink: toLogSink(sink),
UniqueWriterIdentity: opts.UniqueWriterIdentity,
})
if err != nil {
return nil, err
}
return fromLogSink(ls), nil
}
// SinkOptions define options to be used when creating or updating a sink.
type SinkOptions struct {
// Determines the kind of IAM identity returned as WriterIdentity in the new
// sink. If this value is omitted or set to false, and if the sink's parent is a
// project, then the value returned as WriterIdentity is the same group or
// service account used by Stackdriver Logging before the addition of writer
// identities to the API. The sink's destination must be in the same project as
// the sink itself.
//
// If this field is set to true, or if the sink is owned by a non-project
// resource such as an organization, then the value of WriterIdentity will
// be a unique service account used only for exports from the new sink.
UniqueWriterIdentity bool
// These fields apply only to UpdateSinkOpt calls. The corresponding sink field
// is updated if and only if the Update field is true.
UpdateDestination bool
UpdateFilter bool
UpdateIncludeChildren bool
}
// DeleteSink deletes a sink. The provided sinkID is the sink's identifier, such as
// "my-severe-errors-to-pubsub".
// Requires AdminScope.
func (c *Client) DeleteSink(ctx context.Context, sinkID string) error {
return c.sClient.DeleteSink(ctx, &logpb.DeleteSinkRequest{
SinkName: c.sinkPath(sinkID),
})
}
// Sink gets a sink. The provided sinkID is the sink's identifier, such as
// "my-severe-errors-to-pubsub".
// Requires ReadScope or AdminScope.
func (c *Client) Sink(ctx context.Context, sinkID string) (*Sink, error) {
ls, err := c.sClient.GetSink(ctx, &logpb.GetSinkRequest{
SinkName: c.sinkPath(sinkID),
})
if err != nil {
return nil, err
}
return fromLogSink(ls), nil
}
// UpdateSink updates an existing Sink. Requires AdminScope.
//
// WARNING: UpdateSink will always update the Destination, Filter and IncludeChildren
// fields of the sink, even if they have their zero values. Use UpdateSinkOpt
// for more control over which fields to update.
func (c *Client) UpdateSink(ctx context.Context, sink *Sink) (*Sink, error) {
return c.UpdateSinkOpt(ctx, sink, SinkOptions{
UpdateDestination: true,
UpdateFilter: true,
UpdateIncludeChildren: true,
})
}
// UpdateSinkOpt updates an existing Sink, using the provided options. Requires AdminScope.
//
// To change a sink's writer identity to a service account unique to the sink, set
// opts.UniqueWriterIdentity to true. It is not possible to change a sink's writer identity
// from a unique service account to a non-unique writer identity.
func (c *Client) UpdateSinkOpt(ctx context.Context, sink *Sink, opts SinkOptions) (*Sink, error) {
mask := &maskpb.FieldMask{}
if opts.UpdateDestination {
mask.Paths = append(mask.Paths, "destination")
}
if opts.UpdateFilter {
mask.Paths = append(mask.Paths, "filter")
}
if opts.UpdateIncludeChildren {
mask.Paths = append(mask.Paths, "include_children")
}
if opts.UniqueWriterIdentity && len(mask.Paths) == 0 {
// Hack: specify a deprecated, unchangeable field so that we have a non-empty
// field mask. (An empty field mask would cause the destination, filter and include_children
// fields to be changed.)
mask.Paths = append(mask.Paths, "output_version_format")
}
if len(mask.Paths) == 0 {
return nil, errors.New("logadmin: UpdateSinkOpt: nothing to update")
}
ls, err := c.sClient.UpdateSink(ctx, &logpb.UpdateSinkRequest{
SinkName: c.sinkPath(sink.ID),
Sink: toLogSink(sink),
UniqueWriterIdentity: opts.UniqueWriterIdentity,
UpdateMask: mask,
})
if err != nil {
return nil, err
}
return fromLogSink(ls), err
}
func (c *Client) sinkPath(sinkID string) string {
return fmt.Sprintf("%s/sinks/%s", c.parent, sinkID)
}
// Sinks returns a SinkIterator for iterating over all Sinks in the Client's project.
// Requires ReadScope or AdminScope.
func (c *Client) Sinks(ctx context.Context) *SinkIterator {
it := &SinkIterator{
it: c.sClient.ListSinks(ctx, &logpb.ListSinksRequest{Parent: c.parent}),
}
it.pageInfo, it.nextFunc = iterator.NewPageInfo(
it.fetch,
func() int { return len(it.items) },
func() interface{} { b := it.items; it.items = nil; return b })
return it
}
// A SinkIterator iterates over Sinks.
type SinkIterator struct {
it *vkit.LogSinkIterator
pageInfo *iterator.PageInfo
nextFunc func() error
items []*Sink
}
// PageInfo supports pagination. See the google.golang.org/api/iterator package for details.
func (it *SinkIterator) PageInfo() *iterator.PageInfo { return it.pageInfo }
// Next returns the next result. Its second return value is Done if there are
// no more results. Once Next returns Done, all subsequent calls will return
// Done.
func (it *SinkIterator) Next() (*Sink, error) {
if err := it.nextFunc(); err != nil {
return nil, err
}
item := it.items[0]
it.items = it.items[1:]
return item, nil
}
func (it *SinkIterator) fetch(pageSize int, pageToken string) (string, error) {
return iterFetch(pageSize, pageToken, it.it.PageInfo(), func() error {
item, err := it.it.Next()
if err != nil {
return err
}
it.items = append(it.items, fromLogSink(item))
return nil
})
}
func toLogSink(s *Sink) *logpb.LogSink {
return &logpb.LogSink{
Name: s.ID,
Destination: s.Destination,
Filter: s.Filter,
IncludeChildren: s.IncludeChildren,
OutputVersionFormat: logpb.LogSink_V2,
// omit WriterIdentity because it is output-only.
}
}
func fromLogSink(ls *logpb.LogSink) *Sink {
return &Sink{
ID: ls.Name,
Destination: ls.Destination,
Filter: ls.Filter,
WriterIdentity: ls.WriterIdentity,
IncludeChildren: ls.IncludeChildren,
}
}

View File

@ -1,874 +0,0 @@
// Copyright 2016 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
// API/gRPC features intentionally missing from this client:
// - You cannot have the server pick the time of the entry. This client
// always sends a time.
// - There is no way to provide a protocol buffer payload.
// - No support for the "partial success" feature when writing log entries.
// TODO(jba): test whether forward-slash characters in the log ID must be URL-encoded.
// These features are missing now, but will likely be added:
// - There is no way to specify CallOptions.
package logging
import (
"bytes"
"context"
"encoding/json"
"errors"
"fmt"
"log"
"net/http"
"strconv"
"strings"
"sync"
"time"
"unicode/utf8"
"cloud.google.com/go/compute/metadata"
"cloud.google.com/go/internal/version"
vkit "cloud.google.com/go/logging/apiv2"
"cloud.google.com/go/logging/internal"
"github.com/golang/protobuf/proto"
"github.com/golang/protobuf/ptypes"
structpb "github.com/golang/protobuf/ptypes/struct"
tspb "github.com/golang/protobuf/ptypes/timestamp"
"google.golang.org/api/option"
"google.golang.org/api/support/bundler"
mrpb "google.golang.org/genproto/googleapis/api/monitoredres"
logtypepb "google.golang.org/genproto/googleapis/logging/type"
logpb "google.golang.org/genproto/googleapis/logging/v2"
)
const (
// ReadScope is the scope for reading from the logging service.
ReadScope = "https://www.googleapis.com/auth/logging.read"
// WriteScope is the scope for writing to the logging service.
WriteScope = "https://www.googleapis.com/auth/logging.write"
// AdminScope is the scope for administrative actions on the logging service.
AdminScope = "https://www.googleapis.com/auth/logging.admin"
)
const (
// defaultErrorCapacity is the capacity of the channel used to deliver
// errors to the OnError function.
defaultErrorCapacity = 10
// DefaultDelayThreshold is the default value for the DelayThreshold LoggerOption.
DefaultDelayThreshold = time.Second
// DefaultEntryCountThreshold is the default value for the EntryCountThreshold LoggerOption.
DefaultEntryCountThreshold = 1000
// DefaultEntryByteThreshold is the default value for the EntryByteThreshold LoggerOption.
DefaultEntryByteThreshold = 1 << 20 // 1MiB
// DefaultBufferedByteLimit is the default value for the BufferedByteLimit LoggerOption.
DefaultBufferedByteLimit = 1 << 30 // 1GiB
// defaultWriteTimeout is the timeout for the underlying write API calls. As
// write API calls are not idempotent, they are not retried on timeout. This
// timeout is to allow clients to degrade gracefully if underlying logging
// service is temporarily impaired for some reason.
defaultWriteTimeout = 10 * time.Minute
)
// For testing:
var now = time.Now
// ErrOverflow signals that the number of buffered entries for a Logger
// exceeds its BufferLimit.
var ErrOverflow = bundler.ErrOverflow
// ErrOversizedEntry signals that an entry's size exceeds the maximum number of
// bytes that will be sent in a single call to the logging service.
var ErrOversizedEntry = bundler.ErrOversizedItem
// Client is a Logging client. A Client is associated with a single Cloud project.
type Client struct {
client *vkit.Client // client for the logging service
parent string // e.g. "projects/proj-id"
errc chan error // should be buffered to minimize dropped errors
donec chan struct{} // closed on Client.Close to close Logger bundlers
loggers sync.WaitGroup // so we can wait for loggers to close
closed bool
mu sync.Mutex
nErrs int // number of errors we saw
lastErr error // last error we saw
// OnError is called when an error occurs in a call to Log or Flush. The
// error may be due to an invalid Entry, an overflow because BufferLimit
// was reached (in which case the error will be ErrOverflow) or an error
// communicating with the logging service. OnError is called with errors
// from all Loggers. It is never called concurrently. OnError is expected
// to return quickly; if errors occur while OnError is running, some may
// not be reported. The default behavior is to call log.Printf.
//
// This field should be set only once, before any method of Client is called.
OnError func(err error)
}
// NewClient returns a new logging client associated with the provided parent.
// A parent can take any of the following forms:
// projects/PROJECT_ID
// folders/FOLDER_ID
// billingAccounts/ACCOUNT_ID
// organizations/ORG_ID
// for backwards compatibility, a string with no '/' is also allowed and is interpreted
// as a project ID.
//
// By default NewClient uses WriteScope. To use a different scope, call
// NewClient using a WithScopes option (see https://godoc.org/google.golang.org/api/option#WithScopes).
func NewClient(ctx context.Context, parent string, opts ...option.ClientOption) (*Client, error) {
if !strings.ContainsRune(parent, '/') {
parent = "projects/" + parent
}
opts = append([]option.ClientOption{
option.WithEndpoint(internal.ProdAddr),
option.WithScopes(WriteScope),
}, opts...)
c, err := vkit.NewClient(ctx, opts...)
if err != nil {
return nil, err
}
c.SetGoogleClientInfo("gccl", version.Repo)
client := &Client{
client: c,
parent: parent,
errc: make(chan error, defaultErrorCapacity), // create a small buffer for errors
donec: make(chan struct{}),
OnError: func(e error) { log.Printf("logging client: %v", e) },
}
// Call the user's function synchronously, to make life easier for them.
go func() {
for err := range client.errc {
// This reference to OnError is memory-safe if the user sets OnError before
// calling any client methods. The reference happens before the first read from
// client.errc, which happens before the first write to client.errc, which
// happens before any call, which happens before the user sets OnError.
if fn := client.OnError; fn != nil {
fn(err)
} else {
log.Printf("logging (parent %q): %v", parent, err)
}
}
}()
return client, nil
}
var unixZeroTimestamp *tspb.Timestamp
func init() {
var err error
unixZeroTimestamp, err = ptypes.TimestampProto(time.Unix(0, 0))
if err != nil {
panic(err)
}
}
// Ping reports whether the client's connection to the logging service and the
// authentication configuration are valid. To accomplish this, Ping writes a
// log entry "ping" to a log named "ping".
func (c *Client) Ping(ctx context.Context) error {
ent := &logpb.LogEntry{
Payload: &logpb.LogEntry_TextPayload{TextPayload: "ping"},
Timestamp: unixZeroTimestamp, // Identical timestamps and insert IDs are both
InsertId: "ping", // necessary for the service to dedup these entries.
}
_, err := c.client.WriteLogEntries(ctx, &logpb.WriteLogEntriesRequest{
LogName: internal.LogPath(c.parent, "ping"),
Resource: monitoredResource(c.parent),
Entries: []*logpb.LogEntry{ent},
})
return err
}
// error puts the error on the client's error channel
// without blocking, and records summary error info.
func (c *Client) error(err error) {
select {
case c.errc <- err:
default:
}
c.mu.Lock()
c.lastErr = err
c.nErrs++
c.mu.Unlock()
}
func (c *Client) extractErrorInfo() error {
var err error
c.mu.Lock()
if c.lastErr != nil {
err = fmt.Errorf("saw %d errors; last: %v", c.nErrs, c.lastErr)
c.nErrs = 0
c.lastErr = nil
}
c.mu.Unlock()
return err
}
// A Logger is used to write log messages to a single log. It can be configured
// with a log ID, common monitored resource, and a set of common labels.
type Logger struct {
client *Client
logName string // "projects/{projectID}/logs/{logID}"
stdLoggers map[Severity]*log.Logger
bundler *bundler.Bundler
// Options
commonResource *mrpb.MonitoredResource
commonLabels map[string]string
ctxFunc func() (context.Context, func())
}
// A LoggerOption is a configuration option for a Logger.
type LoggerOption interface {
set(*Logger)
}
// CommonResource sets the monitored resource associated with all log entries
// written from a Logger. If not provided, the resource is automatically
// detected based on the running environment. This value can be overridden
// per-entry by setting an Entry's Resource field.
func CommonResource(r *mrpb.MonitoredResource) LoggerOption { return commonResource{r} }
type commonResource struct{ *mrpb.MonitoredResource }
func (r commonResource) set(l *Logger) { l.commonResource = r.MonitoredResource }
var detectedResource struct {
pb *mrpb.MonitoredResource
once sync.Once
}
func detectResource() *mrpb.MonitoredResource {
detectedResource.once.Do(func() {
if !metadata.OnGCE() {
return
}
projectID, err := metadata.ProjectID()
if err != nil {
return
}
id, err := metadata.InstanceID()
if err != nil {
return
}
zone, err := metadata.Zone()
if err != nil {
return
}
name, err := metadata.InstanceName()
if err != nil {
return
}
detectedResource.pb = &mrpb.MonitoredResource{
Type: "gce_instance",
Labels: map[string]string{
"project_id": projectID,
"instance_id": id,
"instance_name": name,
"zone": zone,
},
}
})
return detectedResource.pb
}
var resourceInfo = map[string]struct{ rtype, label string }{
"organizations": {"organization", "organization_id"},
"folders": {"folder", "folder_id"},
"projects": {"project", "project_id"},
"billingAccounts": {"billing_account", "account_id"},
}
func monitoredResource(parent string) *mrpb.MonitoredResource {
parts := strings.SplitN(parent, "/", 2)
if len(parts) != 2 {
return globalResource(parent)
}
info, ok := resourceInfo[parts[0]]
if !ok {
return globalResource(parts[1])
}
return &mrpb.MonitoredResource{
Type: info.rtype,
Labels: map[string]string{info.label: parts[1]},
}
}
func globalResource(projectID string) *mrpb.MonitoredResource {
return &mrpb.MonitoredResource{
Type: "global",
Labels: map[string]string{
"project_id": projectID,
},
}
}
// CommonLabels are labels that apply to all log entries written from a Logger,
// so that you don't have to repeat them in each log entry's Labels field. If
// any of the log entries contains a (key, value) with the same key that is in
// CommonLabels, then the entry's (key, value) overrides the one in
// CommonLabels.
func CommonLabels(m map[string]string) LoggerOption { return commonLabels(m) }
type commonLabels map[string]string
func (c commonLabels) set(l *Logger) { l.commonLabels = c }
// ConcurrentWriteLimit determines how many goroutines will send log entries to the
// underlying service. The default is 1. Set ConcurrentWriteLimit to a higher value to
// increase throughput.
func ConcurrentWriteLimit(n int) LoggerOption { return concurrentWriteLimit(n) }
type concurrentWriteLimit int
func (c concurrentWriteLimit) set(l *Logger) { l.bundler.HandlerLimit = int(c) }
// DelayThreshold is the maximum amount of time that an entry should remain
// buffered in memory before a call to the logging service is triggered. Larger
// values of DelayThreshold will generally result in fewer calls to the logging
// service, while increasing the risk that log entries will be lost if the
// process crashes.
// The default is DefaultDelayThreshold.
func DelayThreshold(d time.Duration) LoggerOption { return delayThreshold(d) }
type delayThreshold time.Duration
func (d delayThreshold) set(l *Logger) { l.bundler.DelayThreshold = time.Duration(d) }
// EntryCountThreshold is the maximum number of entries that will be buffered
// in memory before a call to the logging service is triggered. Larger values
// will generally result in fewer calls to the logging service, while
// increasing both memory consumption and the risk that log entries will be
// lost if the process crashes.
// The default is DefaultEntryCountThreshold.
func EntryCountThreshold(n int) LoggerOption { return entryCountThreshold(n) }
type entryCountThreshold int
func (e entryCountThreshold) set(l *Logger) { l.bundler.BundleCountThreshold = int(e) }
// EntryByteThreshold is the maximum number of bytes of entries that will be
// buffered in memory before a call to the logging service is triggered. See
// EntryCountThreshold for a discussion of the tradeoffs involved in setting
// this option.
// The default is DefaultEntryByteThreshold.
func EntryByteThreshold(n int) LoggerOption { return entryByteThreshold(n) }
type entryByteThreshold int
func (e entryByteThreshold) set(l *Logger) { l.bundler.BundleByteThreshold = int(e) }
// EntryByteLimit is the maximum number of bytes of entries that will be sent
// in a single call to the logging service. ErrOversizedEntry is returned if an
// entry exceeds EntryByteLimit. This option limits the size of a single RPC
// payload, to account for network or service issues with large RPCs. If
// EntryByteLimit is smaller than EntryByteThreshold, the latter has no effect.
// The default is zero, meaning there is no limit.
func EntryByteLimit(n int) LoggerOption { return entryByteLimit(n) }
type entryByteLimit int
func (e entryByteLimit) set(l *Logger) { l.bundler.BundleByteLimit = int(e) }
// BufferedByteLimit is the maximum number of bytes that the Logger will keep
// in memory before returning ErrOverflow. This option limits the total memory
// consumption of the Logger (but note that each Logger has its own, separate
// limit). It is possible to reach BufferedByteLimit even if it is larger than
// EntryByteThreshold or EntryByteLimit, because calls triggered by the latter
// two options may be enqueued (and hence occupying memory) while new log
// entries are being added.
// The default is DefaultBufferedByteLimit.
func BufferedByteLimit(n int) LoggerOption { return bufferedByteLimit(n) }
type bufferedByteLimit int
func (b bufferedByteLimit) set(l *Logger) { l.bundler.BufferedByteLimit = int(b) }
// ContextFunc is a function that will be called to obtain a context.Context for the
// WriteLogEntries RPC executed in the background for calls to Logger.Log. The
// default is a function that always returns context.Background. The second return
// value of the function is a function to call after the RPC completes.
//
// The function is not used for calls to Logger.LogSync, since the caller can pass
// in the context directly.
//
// This option is EXPERIMENTAL. It may be changed or removed.
func ContextFunc(f func() (ctx context.Context, afterCall func())) LoggerOption {
return contextFunc(f)
}
type contextFunc func() (ctx context.Context, afterCall func())
func (c contextFunc) set(l *Logger) { l.ctxFunc = c }
// Logger returns a Logger that will write entries with the given log ID, such as
// "syslog". A log ID must be less than 512 characters long and can only
// include the following characters: upper and lower case alphanumeric
// characters: [A-Za-z0-9]; and punctuation characters: forward-slash,
// underscore, hyphen, and period.
func (c *Client) Logger(logID string, opts ...LoggerOption) *Logger {
r := detectResource()
if r == nil {
r = monitoredResource(c.parent)
}
l := &Logger{
client: c,
logName: internal.LogPath(c.parent, logID),
commonResource: r,
ctxFunc: func() (context.Context, func()) { return context.Background(), nil },
}
l.bundler = bundler.NewBundler(&logpb.LogEntry{}, func(entries interface{}) {
l.writeLogEntries(entries.([]*logpb.LogEntry))
})
l.bundler.DelayThreshold = DefaultDelayThreshold
l.bundler.BundleCountThreshold = DefaultEntryCountThreshold
l.bundler.BundleByteThreshold = DefaultEntryByteThreshold
l.bundler.BufferedByteLimit = DefaultBufferedByteLimit
for _, opt := range opts {
opt.set(l)
}
l.stdLoggers = map[Severity]*log.Logger{}
for s := range severityName {
l.stdLoggers[s] = log.New(severityWriter{l, s}, "", 0)
}
c.loggers.Add(1)
// Start a goroutine that cleans up the bundler, its channel
// and the writer goroutines when the client is closed.
go func() {
defer c.loggers.Done()
<-c.donec
l.bundler.Flush()
}()
return l
}
type severityWriter struct {
l *Logger
s Severity
}
func (w severityWriter) Write(p []byte) (n int, err error) {
w.l.Log(Entry{
Severity: w.s,
Payload: string(p),
})
return len(p), nil
}
// Close waits for all opened loggers to be flushed and closes the client.
func (c *Client) Close() error {
if c.closed {
return nil
}
close(c.donec) // close Logger bundlers
c.loggers.Wait() // wait for all bundlers to flush and close
// Now there can be no more errors.
close(c.errc) // terminate error goroutine
// Prefer errors arising from logging to the error returned from Close.
err := c.extractErrorInfo()
err2 := c.client.Close()
if err == nil {
err = err2
}
c.closed = true
return err
}
// Severity is the severity of the event described in a log entry. These
// guideline severity levels are ordered, with numerically smaller levels
// treated as less severe than numerically larger levels.
type Severity int
const (
// Default means the log entry has no assigned severity level.
Default = Severity(logtypepb.LogSeverity_DEFAULT)
// Debug means debug or trace information.
Debug = Severity(logtypepb.LogSeverity_DEBUG)
// Info means routine information, such as ongoing status or performance.
Info = Severity(logtypepb.LogSeverity_INFO)
// Notice means normal but significant events, such as start up, shut down, or configuration.
Notice = Severity(logtypepb.LogSeverity_NOTICE)
// Warning means events that might cause problems.
Warning = Severity(logtypepb.LogSeverity_WARNING)
// Error means events that are likely to cause problems.
Error = Severity(logtypepb.LogSeverity_ERROR)
// Critical means events that cause more severe problems or brief outages.
Critical = Severity(logtypepb.LogSeverity_CRITICAL)
// Alert means a person must take an action immediately.
Alert = Severity(logtypepb.LogSeverity_ALERT)
// Emergency means one or more systems are unusable.
Emergency = Severity(logtypepb.LogSeverity_EMERGENCY)
)
var severityName = map[Severity]string{
Default: "Default",
Debug: "Debug",
Info: "Info",
Notice: "Notice",
Warning: "Warning",
Error: "Error",
Critical: "Critical",
Alert: "Alert",
Emergency: "Emergency",
}
// String converts a severity level to a string.
func (v Severity) String() string {
// same as proto.EnumName
s, ok := severityName[v]
if ok {
return s
}
return strconv.Itoa(int(v))
}
// ParseSeverity returns the Severity whose name equals s, ignoring case. It
// returns Default if no Severity matches.
func ParseSeverity(s string) Severity {
sl := strings.ToLower(s)
for sev, name := range severityName {
if strings.ToLower(name) == sl {
return sev
}
}
return Default
}
// Entry is a log entry.
// See https://cloud.google.com/logging/docs/view/logs_index for more about entries.
type Entry struct {
// Timestamp is the time of the entry. If zero, the current time is used.
Timestamp time.Time
// Severity is the entry's severity level.
// The zero value is Default.
Severity Severity
// Payload must be either a string, or something that marshals via the
// encoding/json package to a JSON object (and not any other type of JSON value).
Payload interface{}
// Labels optionally specifies key/value labels for the log entry.
// The Logger.Log method takes ownership of this map. See Logger.CommonLabels
// for more about labels.
Labels map[string]string
// InsertID is a unique ID for the log entry. If you provide this field,
// the logging service considers other log entries in the same log with the
// same ID as duplicates which can be removed. If omitted, the logging
// service will generate a unique ID for this log entry. Note that because
// this client retries RPCs automatically, it is possible (though unlikely)
// that an Entry without an InsertID will be written more than once.
InsertID string
// HTTPRequest optionally specifies metadata about the HTTP request
// associated with this log entry, if applicable. It is optional.
HTTPRequest *HTTPRequest
// Operation optionally provides information about an operation associated
// with the log entry, if applicable.
Operation *logpb.LogEntryOperation
// LogName is the full log name, in the form
// "projects/{ProjectID}/logs/{LogID}". It is set by the client when
// reading entries. It is an error to set it when writing entries.
LogName string
// Resource is the monitored resource associated with the entry.
Resource *mrpb.MonitoredResource
// Trace is the resource name of the trace associated with the log entry,
// if any. If it contains a relative resource name, the name is assumed to
// be relative to //tracing.googleapis.com.
Trace string
// ID of the span within the trace associated with the log entry.
// The ID is a 16-character hexadecimal encoding of an 8-byte array.
SpanID string
// Optional. Source code location information associated with the log entry,
// if any.
SourceLocation *logpb.LogEntrySourceLocation
}
// HTTPRequest contains an http.Request as well as additional
// information about the request and its response.
type HTTPRequest struct {
// Request is the http.Request passed to the handler.
Request *http.Request
// RequestSize is the size of the HTTP request message in bytes, including
// the request headers and the request body.
RequestSize int64
// Status is the response code indicating the status of the response.
// Examples: 200, 404.
Status int
// ResponseSize is the size of the HTTP response message sent back to the client, in bytes,
// including the response headers and the response body.
ResponseSize int64
// Latency is the request processing latency on the server, from the time the request was
// received until the response was sent.
Latency time.Duration
// LocalIP is the IP address (IPv4 or IPv6) of the origin server that the request
// was sent to.
LocalIP string
// RemoteIP is the IP address (IPv4 or IPv6) of the client that issued the
// HTTP request. Examples: "192.168.1.1", "FE80::0202:B3FF:FE1E:8329".
RemoteIP string
// CacheHit reports whether an entity was served from cache (with or without
// validation).
CacheHit bool
// CacheValidatedWithOriginServer reports whether the response was
// validated with the origin server before being served from cache. This
// field is only meaningful if CacheHit is true.
CacheValidatedWithOriginServer bool
}
func fromHTTPRequest(r *HTTPRequest) *logtypepb.HttpRequest {
if r == nil {
return nil
}
if r.Request == nil {
panic("HTTPRequest must have a non-nil Request")
}
u := *r.Request.URL
u.Fragment = ""
pb := &logtypepb.HttpRequest{
RequestMethod: r.Request.Method,
RequestUrl: fixUTF8(u.String()),
RequestSize: r.RequestSize,
Status: int32(r.Status),
ResponseSize: r.ResponseSize,
UserAgent: r.Request.UserAgent(),
ServerIp: r.LocalIP,
RemoteIp: r.RemoteIP, // TODO(jba): attempt to parse http.Request.RemoteAddr?
Referer: r.Request.Referer(),
CacheHit: r.CacheHit,
CacheValidatedWithOriginServer: r.CacheValidatedWithOriginServer,
}
if r.Latency != 0 {
pb.Latency = ptypes.DurationProto(r.Latency)
}
return pb
}
// fixUTF8 is a helper that fixes an invalid UTF-8 string by replacing
// invalid UTF-8 runes with the Unicode replacement character (U+FFFD).
// See Issue https://github.com/googleapis/google-cloud-go/issues/1383.
func fixUTF8(s string) string {
if utf8.ValidString(s) {
return s
}
// Otherwise time to build the sequence.
buf := new(bytes.Buffer)
buf.Grow(len(s))
for _, r := range s {
if utf8.ValidRune(r) {
buf.WriteRune(r)
} else {
buf.WriteRune('\uFFFD')
}
}
return buf.String()
}
// toProtoStruct converts v, which must marshal into a JSON object,
// into a Google Struct proto.
func toProtoStruct(v interface{}) (*structpb.Struct, error) {
// Fast path: if v is already a *structpb.Struct, nothing to do.
if s, ok := v.(*structpb.Struct); ok {
return s, nil
}
// v is a Go value that supports JSON marshalling. We want a Struct
// protobuf. Some day we may have a more direct way to get there, but right
// now the only way is to marshal the Go value to JSON, unmarshal into a
// map, and then build the Struct proto from the map.
var jb []byte
var err error
if raw, ok := v.(json.RawMessage); ok { // needed for Go 1.7 and below
jb = []byte(raw)
} else {
jb, err = json.Marshal(v)
if err != nil {
return nil, fmt.Errorf("logging: json.Marshal: %v", err)
}
}
var m map[string]interface{}
err = json.Unmarshal(jb, &m)
if err != nil {
return nil, fmt.Errorf("logging: json.Unmarshal: %v", err)
}
return jsonMapToProtoStruct(m), nil
}
func jsonMapToProtoStruct(m map[string]interface{}) *structpb.Struct {
fields := map[string]*structpb.Value{}
for k, v := range m {
fields[k] = jsonValueToStructValue(v)
}
return &structpb.Struct{Fields: fields}
}
func jsonValueToStructValue(v interface{}) *structpb.Value {
switch x := v.(type) {
case bool:
return &structpb.Value{Kind: &structpb.Value_BoolValue{BoolValue: x}}
case float64:
return &structpb.Value{Kind: &structpb.Value_NumberValue{NumberValue: x}}
case string:
return &structpb.Value{Kind: &structpb.Value_StringValue{StringValue: x}}
case nil:
return &structpb.Value{Kind: &structpb.Value_NullValue{}}
case map[string]interface{}:
return &structpb.Value{Kind: &structpb.Value_StructValue{StructValue: jsonMapToProtoStruct(x)}}
case []interface{}:
var vals []*structpb.Value
for _, e := range x {
vals = append(vals, jsonValueToStructValue(e))
}
return &structpb.Value{Kind: &structpb.Value_ListValue{ListValue: &structpb.ListValue{Values: vals}}}
default:
panic(fmt.Sprintf("bad type %T for JSON value", v))
}
}
// LogSync logs the Entry synchronously without any buffering. Because LogSync is slow
// and will block, it is intended primarily for debugging or critical errors.
// Prefer Log for most uses.
// TODO(jba): come up with a better name (LogNow?) or eliminate.
func (l *Logger) LogSync(ctx context.Context, e Entry) error {
ent, err := l.toLogEntry(e)
if err != nil {
return err
}
_, err = l.client.client.WriteLogEntries(ctx, &logpb.WriteLogEntriesRequest{
LogName: l.logName,
Resource: l.commonResource,
Labels: l.commonLabels,
Entries: []*logpb.LogEntry{ent},
})
return err
}
// Log buffers the Entry for output to the logging service. It never blocks.
func (l *Logger) Log(e Entry) {
ent, err := l.toLogEntry(e)
if err != nil {
l.client.error(err)
return
}
if err := l.bundler.Add(ent, proto.Size(ent)); err != nil {
l.client.error(err)
}
}
// Flush blocks until all currently buffered log entries are sent.
//
// If any errors occurred since the last call to Flush from any Logger, or the
// creation of the client if this is the first call, then Flush returns a non-nil
// error with summary information about the errors. This information is unlikely to
// be actionable. For more accurate error reporting, set Client.OnError.
func (l *Logger) Flush() error {
l.bundler.Flush()
return l.client.extractErrorInfo()
}
func (l *Logger) writeLogEntries(entries []*logpb.LogEntry) {
req := &logpb.WriteLogEntriesRequest{
LogName: l.logName,
Resource: l.commonResource,
Labels: l.commonLabels,
Entries: entries,
}
ctx, afterCall := l.ctxFunc()
ctx, cancel := context.WithTimeout(ctx, defaultWriteTimeout)
defer cancel()
_, err := l.client.client.WriteLogEntries(ctx, req)
if err != nil {
l.client.error(err)
}
if afterCall != nil {
afterCall()
}
}
// StandardLogger returns a *log.Logger for the provided severity.
//
// This method is cheap. A single log.Logger is pre-allocated for each
// severity level in each Logger. Callers may mutate the returned log.Logger
// (for example by calling SetFlags or SetPrefix).
func (l *Logger) StandardLogger(s Severity) *log.Logger { return l.stdLoggers[s] }
func (l *Logger) toLogEntry(e Entry) (*logpb.LogEntry, error) {
if e.LogName != "" {
return nil, errors.New("logging: Entry.LogName should be not be set when writing")
}
t := e.Timestamp
if t.IsZero() {
t = now()
}
ts, err := ptypes.TimestampProto(t)
if err != nil {
return nil, err
}
if e.Trace == "" && e.HTTPRequest != nil && e.HTTPRequest.Request != nil {
traceHeader := e.HTTPRequest.Request.Header.Get("X-Cloud-Trace-Context")
if traceHeader != "" {
// Set to a relative resource name, as described at
// https://cloud.google.com/appengine/docs/flexible/go/writing-application-logs.
e.Trace = fmt.Sprintf("%s/traces/%s", l.client.parent, traceHeader)
}
}
ent := &logpb.LogEntry{
Timestamp: ts,
Severity: logtypepb.LogSeverity(e.Severity),
InsertId: e.InsertID,
HttpRequest: fromHTTPRequest(e.HTTPRequest),
Operation: e.Operation,
Labels: e.Labels,
Trace: e.Trace,
SpanId: e.SpanID,
Resource: e.Resource,
SourceLocation: e.SourceLocation,
}
switch p := e.Payload.(type) {
case string:
ent.Payload = &logpb.LogEntry_TextPayload{TextPayload: p}
default:
s, err := toProtoStruct(p)
if err != nil {
return nil, err
}
ent.Payload = &logpb.LogEntry_JsonPayload{JsonPayload: s}
}
return ent, nil
}

16
vendor/github.com/evanphx/json-patch/.travis.yml generated vendored Normal file
View File

@ -0,0 +1,16 @@
language: go
go:
- 1.8
- 1.7
install:
- if ! go get code.google.com/p/go.tools/cmd/cover; then go get golang.org/x/tools/cmd/cover; fi
- go get github.com/jessevdk/go-flags
script:
- go get
- go test -cover ./...
notifications:
email: false

25
vendor/github.com/evanphx/json-patch/LICENSE generated vendored Normal file
View File

@ -0,0 +1,25 @@
Copyright (c) 2014, Evan Phoenix
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
* Neither the name of the Evan Phoenix nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

297
vendor/github.com/evanphx/json-patch/README.md generated vendored Normal file
View File

@ -0,0 +1,297 @@
# JSON-Patch
`jsonpatch` is a library which provides functionallity for both applying
[RFC6902 JSON patches](http://tools.ietf.org/html/rfc6902) against documents, as
well as for calculating & applying [RFC7396 JSON merge patches](https://tools.ietf.org/html/rfc7396).
[![GoDoc](https://godoc.org/github.com/evanphx/json-patch?status.svg)](http://godoc.org/github.com/evanphx/json-patch)
[![Build Status](https://travis-ci.org/evanphx/json-patch.svg?branch=master)](https://travis-ci.org/evanphx/json-patch)
[![Report Card](https://goreportcard.com/badge/github.com/evanphx/json-patch)](https://goreportcard.com/report/github.com/evanphx/json-patch)
# Get It!
**Latest and greatest**:
```bash
go get -u github.com/evanphx/json-patch
```
**Stable Versions**:
* Version 4: `go get -u gopkg.in/evanphx/json-patch.v4`
(previous versions below `v3` are unavailable)
# Use It!
* [Create and apply a merge patch](#create-and-apply-a-merge-patch)
* [Create and apply a JSON Patch](#create-and-apply-a-json-patch)
* [Comparing JSON documents](#comparing-json-documents)
* [Combine merge patches](#combine-merge-patches)
# Configuration
* There is a global configuration variable `jsonpatch.SupportNegativeIndices`.
This defaults to `true` and enables the non-standard practice of allowing
negative indices to mean indices starting at the end of an array. This
functionality can be disabled by setting `jsonpatch.SupportNegativeIndices =
false`.
* There is a global configuration variable `jsonpatch.AccumulatedCopySizeLimit`,
which limits the total size increase in bytes caused by "copy" operations in a
patch. It defaults to 0, which means there is no limit.
## Create and apply a merge patch
Given both an original JSON document and a modified JSON document, you can create
a [Merge Patch](https://tools.ietf.org/html/rfc7396) document.
It can describe the changes needed to convert from the original to the
modified JSON document.
Once you have a merge patch, you can apply it to other JSON documents using the
`jsonpatch.MergePatch(document, patch)` function.
```go
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
// Let's create a merge patch from these two documents...
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
target := []byte(`{"name": "Jane", "age": 24}`)
patch, err := jsonpatch.CreateMergePatch(original, target)
if err != nil {
panic(err)
}
// Now lets apply the patch against a different JSON document...
alternative := []byte(`{"name": "Tina", "age": 28, "height": 3.75}`)
modifiedAlternative, err := jsonpatch.MergePatch(alternative, patch)
fmt.Printf("patch document: %s\n", patch)
fmt.Printf("updated alternative doc: %s\n", modifiedAlternative)
}
```
When ran, you get the following output:
```bash
$ go run main.go
patch document: {"height":null,"name":"Jane"}
updated tina doc: {"age":28,"name":"Jane"}
```
## Create and apply a JSON Patch
You can create patch objects using `DecodePatch([]byte)`, which can then
be applied against JSON documents.
The following is an example of creating a patch from two operations, and
applying it against a JSON document.
```go
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
patchJSON := []byte(`[
{"op": "replace", "path": "/name", "value": "Jane"},
{"op": "remove", "path": "/height"}
]`)
patch, err := jsonpatch.DecodePatch(patchJSON)
if err != nil {
panic(err)
}
modified, err := patch.Apply(original)
if err != nil {
panic(err)
}
fmt.Printf("Original document: %s\n", original)
fmt.Printf("Modified document: %s\n", modified)
}
```
When ran, you get the following output:
```bash
$ go run main.go
Original document: {"name": "John", "age": 24, "height": 3.21}
Modified document: {"age":24,"name":"Jane"}
```
## Comparing JSON documents
Due to potential whitespace and ordering differences, one cannot simply compare
JSON strings or byte-arrays directly.
As such, you can instead use `jsonpatch.Equal(document1, document2)` to
determine if two JSON documents are _structurally_ equal. This ignores
whitespace differences, and key-value ordering.
```go
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
similar := []byte(`
{
"age": 24,
"height": 3.21,
"name": "John"
}
`)
different := []byte(`{"name": "Jane", "age": 20, "height": 3.37}`)
if jsonpatch.Equal(original, similar) {
fmt.Println(`"original" is structurally equal to "similar"`)
}
if !jsonpatch.Equal(original, different) {
fmt.Println(`"original" is _not_ structurally equal to "similar"`)
}
}
```
When ran, you get the following output:
```bash
$ go run main.go
"original" is structurally equal to "similar"
"original" is _not_ structurally equal to "similar"
```
## Combine merge patches
Given two JSON merge patch documents, it is possible to combine them into a
single merge patch which can describe both set of changes.
The resulting merge patch can be used such that applying it results in a
document structurally similar as merging each merge patch to the document
in succession.
```go
package main
import (
"fmt"
jsonpatch "github.com/evanphx/json-patch"
)
func main() {
original := []byte(`{"name": "John", "age": 24, "height": 3.21}`)
nameAndHeight := []byte(`{"height":null,"name":"Jane"}`)
ageAndEyes := []byte(`{"age":4.23,"eyes":"blue"}`)
// Let's combine these merge patch documents...
combinedPatch, err := jsonpatch.MergeMergePatches(nameAndHeight, ageAndEyes)
if err != nil {
panic(err)
}
// Apply each patch individual against the original document
withoutCombinedPatch, err := jsonpatch.MergePatch(original, nameAndHeight)
if err != nil {
panic(err)
}
withoutCombinedPatch, err = jsonpatch.MergePatch(withoutCombinedPatch, ageAndEyes)
if err != nil {
panic(err)
}
// Apply the combined patch against the original document
withCombinedPatch, err := jsonpatch.MergePatch(original, combinedPatch)
if err != nil {
panic(err)
}
// Do both result in the same thing? They should!
if jsonpatch.Equal(withCombinedPatch, withoutCombinedPatch) {
fmt.Println("Both JSON documents are structurally the same!")
}
fmt.Printf("combined merge patch: %s", combinedPatch)
}
```
When ran, you get the following output:
```bash
$ go run main.go
Both JSON documents are structurally the same!
combined merge patch: {"age":4.23,"eyes":"blue","height":null,"name":"Jane"}
```
# CLI for comparing JSON documents
You can install the commandline program `json-patch`.
This program can take multiple JSON patch documents as arguments,
and fed a JSON document from `stdin`. It will apply the patch(es) against
the document and output the modified doc.
**patch.1.json**
```json
[
{"op": "replace", "path": "/name", "value": "Jane"},
{"op": "remove", "path": "/height"}
]
```
**patch.2.json**
```json
[
{"op": "add", "path": "/address", "value": "123 Main St"},
{"op": "replace", "path": "/age", "value": "21"}
]
```
**document.json**
```json
{
"name": "John",
"age": 24,
"height": 3.21
}
```
You can then run:
```bash
$ go install github.com/evanphx/json-patch/cmd/json-patch
$ cat document.json | json-patch -p patch.1.json -p patch.2.json
{"address":"123 Main St","age":"21","name":"Jane"}
```
# Help It!
Contributions are welcomed! Leave [an issue](https://github.com/evanphx/json-patch/issues)
or [create a PR](https://github.com/evanphx/json-patch/compare).
Before creating a pull request, we'd ask that you make sure tests are passing
and that you have added new tests when applicable.
Contributors can run tests using:
```bash
go test -cover ./...
```
Builds for pull requests are tested automatically
using [TravisCI](https://travis-ci.org/evanphx/json-patch).

38
vendor/github.com/evanphx/json-patch/errors.go generated vendored Normal file
View File

@ -0,0 +1,38 @@
package jsonpatch
import "fmt"
// AccumulatedCopySizeError is an error type returned when the accumulated size
// increase caused by copy operations in a patch operation has exceeded the
// limit.
type AccumulatedCopySizeError struct {
limit int64
accumulated int64
}
// NewAccumulatedCopySizeError returns an AccumulatedCopySizeError.
func NewAccumulatedCopySizeError(l, a int64) *AccumulatedCopySizeError {
return &AccumulatedCopySizeError{limit: l, accumulated: a}
}
// Error implements the error interface.
func (a *AccumulatedCopySizeError) Error() string {
return fmt.Sprintf("Unable to complete the copy, the accumulated size increase of copy is %d, exceeding the limit %d", a.accumulated, a.limit)
}
// ArraySizeError is an error type returned when the array size has exceeded
// the limit.
type ArraySizeError struct {
limit int
size int
}
// NewArraySizeError returns an ArraySizeError.
func NewArraySizeError(l, s int) *ArraySizeError {
return &ArraySizeError{limit: l, size: s}
}
// Error implements the error interface.
func (a *ArraySizeError) Error() string {
return fmt.Sprintf("Unable to create array of size %d, limit is %d", a.size, a.limit)
}

383
vendor/github.com/evanphx/json-patch/merge.go generated vendored Normal file
View File

@ -0,0 +1,383 @@
package jsonpatch
import (
"bytes"
"encoding/json"
"fmt"
"reflect"
)
func merge(cur, patch *lazyNode, mergeMerge bool) *lazyNode {
curDoc, err := cur.intoDoc()
if err != nil {
pruneNulls(patch)
return patch
}
patchDoc, err := patch.intoDoc()
if err != nil {
return patch
}
mergeDocs(curDoc, patchDoc, mergeMerge)
return cur
}
func mergeDocs(doc, patch *partialDoc, mergeMerge bool) {
for k, v := range *patch {
if v == nil {
if mergeMerge {
(*doc)[k] = nil
} else {
delete(*doc, k)
}
} else {
cur, ok := (*doc)[k]
if !ok || cur == nil {
pruneNulls(v)
(*doc)[k] = v
} else {
(*doc)[k] = merge(cur, v, mergeMerge)
}
}
}
}
func pruneNulls(n *lazyNode) {
sub, err := n.intoDoc()
if err == nil {
pruneDocNulls(sub)
} else {
ary, err := n.intoAry()
if err == nil {
pruneAryNulls(ary)
}
}
}
func pruneDocNulls(doc *partialDoc) *partialDoc {
for k, v := range *doc {
if v == nil {
delete(*doc, k)
} else {
pruneNulls(v)
}
}
return doc
}
func pruneAryNulls(ary *partialArray) *partialArray {
newAry := []*lazyNode{}
for _, v := range *ary {
if v != nil {
pruneNulls(v)
newAry = append(newAry, v)
}
}
*ary = newAry
return ary
}
var errBadJSONDoc = fmt.Errorf("Invalid JSON Document")
var errBadJSONPatch = fmt.Errorf("Invalid JSON Patch")
var errBadMergeTypes = fmt.Errorf("Mismatched JSON Documents")
// MergeMergePatches merges two merge patches together, such that
// applying this resulting merged merge patch to a document yields the same
// as merging each merge patch to the document in succession.
func MergeMergePatches(patch1Data, patch2Data []byte) ([]byte, error) {
return doMergePatch(patch1Data, patch2Data, true)
}
// MergePatch merges the patchData into the docData.
func MergePatch(docData, patchData []byte) ([]byte, error) {
return doMergePatch(docData, patchData, false)
}
func doMergePatch(docData, patchData []byte, mergeMerge bool) ([]byte, error) {
doc := &partialDoc{}
docErr := json.Unmarshal(docData, doc)
patch := &partialDoc{}
patchErr := json.Unmarshal(patchData, patch)
if _, ok := docErr.(*json.SyntaxError); ok {
return nil, errBadJSONDoc
}
if _, ok := patchErr.(*json.SyntaxError); ok {
return nil, errBadJSONPatch
}
if docErr == nil && *doc == nil {
return nil, errBadJSONDoc
}
if patchErr == nil && *patch == nil {
return nil, errBadJSONPatch
}
if docErr != nil || patchErr != nil {
// Not an error, just not a doc, so we turn straight into the patch
if patchErr == nil {
if mergeMerge {
doc = patch
} else {
doc = pruneDocNulls(patch)
}
} else {
patchAry := &partialArray{}
patchErr = json.Unmarshal(patchData, patchAry)
if patchErr != nil {
return nil, errBadJSONPatch
}
pruneAryNulls(patchAry)
out, patchErr := json.Marshal(patchAry)
if patchErr != nil {
return nil, errBadJSONPatch
}
return out, nil
}
} else {
mergeDocs(doc, patch, mergeMerge)
}
return json.Marshal(doc)
}
// resemblesJSONArray indicates whether the byte-slice "appears" to be
// a JSON array or not.
// False-positives are possible, as this function does not check the internal
// structure of the array. It only checks that the outer syntax is present and
// correct.
func resemblesJSONArray(input []byte) bool {
input = bytes.TrimSpace(input)
hasPrefix := bytes.HasPrefix(input, []byte("["))
hasSuffix := bytes.HasSuffix(input, []byte("]"))
return hasPrefix && hasSuffix
}
// CreateMergePatch will return a merge patch document capable of converting
// the original document(s) to the modified document(s).
// The parameters can be bytes of either two JSON Documents, or two arrays of
// JSON documents.
// The merge patch returned follows the specification defined at http://tools.ietf.org/html/draft-ietf-appsawg-json-merge-patch-07
func CreateMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
originalResemblesArray := resemblesJSONArray(originalJSON)
modifiedResemblesArray := resemblesJSONArray(modifiedJSON)
// Do both byte-slices seem like JSON arrays?
if originalResemblesArray && modifiedResemblesArray {
return createArrayMergePatch(originalJSON, modifiedJSON)
}
// Are both byte-slices are not arrays? Then they are likely JSON objects...
if !originalResemblesArray && !modifiedResemblesArray {
return createObjectMergePatch(originalJSON, modifiedJSON)
}
// None of the above? Then return an error because of mismatched types.
return nil, errBadMergeTypes
}
// createObjectMergePatch will return a merge-patch document capable of
// converting the original document to the modified document.
func createObjectMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
originalDoc := map[string]interface{}{}
modifiedDoc := map[string]interface{}{}
err := json.Unmarshal(originalJSON, &originalDoc)
if err != nil {
return nil, errBadJSONDoc
}
err = json.Unmarshal(modifiedJSON, &modifiedDoc)
if err != nil {
return nil, errBadJSONDoc
}
dest, err := getDiff(originalDoc, modifiedDoc)
if err != nil {
return nil, err
}
return json.Marshal(dest)
}
// createArrayMergePatch will return an array of merge-patch documents capable
// of converting the original document to the modified document for each
// pair of JSON documents provided in the arrays.
// Arrays of mismatched sizes will result in an error.
func createArrayMergePatch(originalJSON, modifiedJSON []byte) ([]byte, error) {
originalDocs := []json.RawMessage{}
modifiedDocs := []json.RawMessage{}
err := json.Unmarshal(originalJSON, &originalDocs)
if err != nil {
return nil, errBadJSONDoc
}
err = json.Unmarshal(modifiedJSON, &modifiedDocs)
if err != nil {
return nil, errBadJSONDoc
}
total := len(originalDocs)
if len(modifiedDocs) != total {
return nil, errBadJSONDoc
}
result := []json.RawMessage{}
for i := 0; i < len(originalDocs); i++ {
original := originalDocs[i]
modified := modifiedDocs[i]
patch, err := createObjectMergePatch(original, modified)
if err != nil {
return nil, err
}
result = append(result, json.RawMessage(patch))
}
return json.Marshal(result)
}
// Returns true if the array matches (must be json types).
// As is idiomatic for go, an empty array is not the same as a nil array.
func matchesArray(a, b []interface{}) bool {
if len(a) != len(b) {
return false
}
if (a == nil && b != nil) || (a != nil && b == nil) {
return false
}
for i := range a {
if !matchesValue(a[i], b[i]) {
return false
}
}
return true
}
// Returns true if the values matches (must be json types)
// The types of the values must match, otherwise it will always return false
// If two map[string]interface{} are given, all elements must match.
func matchesValue(av, bv interface{}) bool {
if reflect.TypeOf(av) != reflect.TypeOf(bv) {
return false
}
switch at := av.(type) {
case string:
bt := bv.(string)
if bt == at {
return true
}
case float64:
bt := bv.(float64)
if bt == at {
return true
}
case bool:
bt := bv.(bool)
if bt == at {
return true
}
case nil:
// Both nil, fine.
return true
case map[string]interface{}:
bt := bv.(map[string]interface{})
for key := range at {
if !matchesValue(at[key], bt[key]) {
return false
}
}
for key := range bt {
if !matchesValue(at[key], bt[key]) {
return false
}
}
return true
case []interface{}:
bt := bv.([]interface{})
return matchesArray(at, bt)
}
return false
}
// getDiff returns the (recursive) difference between a and b as a map[string]interface{}.
func getDiff(a, b map[string]interface{}) (map[string]interface{}, error) {
into := map[string]interface{}{}
for key, bv := range b {
av, ok := a[key]
// value was added
if !ok {
into[key] = bv
continue
}
// If types have changed, replace completely
if reflect.TypeOf(av) != reflect.TypeOf(bv) {
into[key] = bv
continue
}
// Types are the same, compare values
switch at := av.(type) {
case map[string]interface{}:
bt := bv.(map[string]interface{})
dst := make(map[string]interface{}, len(bt))
dst, err := getDiff(at, bt)
if err != nil {
return nil, err
}
if len(dst) > 0 {
into[key] = dst
}
case string, float64, bool:
if !matchesValue(av, bv) {
into[key] = bv
}
case []interface{}:
bt := bv.([]interface{})
if !matchesArray(at, bt) {
into[key] = bv
}
case nil:
switch bv.(type) {
case nil:
// Both nil, fine.
default:
into[key] = bv
}
default:
panic(fmt.Sprintf("Unknown type:%T in key %s", av, key))
}
}
// Now add all deleted values as nil
for key := range a {
_, found := b[key]
if !found {
into[key] = nil
}
}
return into, nil
}

696
vendor/github.com/evanphx/json-patch/patch.go generated vendored Normal file
View File

@ -0,0 +1,696 @@
package jsonpatch
import (
"bytes"
"encoding/json"
"fmt"
"strconv"
"strings"
)
const (
eRaw = iota
eDoc
eAry
)
var (
// SupportNegativeIndices decides whether to support non-standard practice of
// allowing negative indices to mean indices starting at the end of an array.
// Default to true.
SupportNegativeIndices bool = true
// AccumulatedCopySizeLimit limits the total size increase in bytes caused by
// "copy" operations in a patch.
AccumulatedCopySizeLimit int64 = 0
)
type lazyNode struct {
raw *json.RawMessage
doc partialDoc
ary partialArray
which int
}
type operation map[string]*json.RawMessage
// Patch is an ordered collection of operations.
type Patch []operation
type partialDoc map[string]*lazyNode
type partialArray []*lazyNode
type container interface {
get(key string) (*lazyNode, error)
set(key string, val *lazyNode) error
add(key string, val *lazyNode) error
remove(key string) error
}
func newLazyNode(raw *json.RawMessage) *lazyNode {
return &lazyNode{raw: raw, doc: nil, ary: nil, which: eRaw}
}
func (n *lazyNode) MarshalJSON() ([]byte, error) {
switch n.which {
case eRaw:
return json.Marshal(n.raw)
case eDoc:
return json.Marshal(n.doc)
case eAry:
return json.Marshal(n.ary)
default:
return nil, fmt.Errorf("Unknown type")
}
}
func (n *lazyNode) UnmarshalJSON(data []byte) error {
dest := make(json.RawMessage, len(data))
copy(dest, data)
n.raw = &dest
n.which = eRaw
return nil
}
func deepCopy(src *lazyNode) (*lazyNode, int, error) {
if src == nil {
return nil, 0, nil
}
a, err := src.MarshalJSON()
if err != nil {
return nil, 0, err
}
sz := len(a)
ra := make(json.RawMessage, sz)
copy(ra, a)
return newLazyNode(&ra), sz, nil
}
func (n *lazyNode) intoDoc() (*partialDoc, error) {
if n.which == eDoc {
return &n.doc, nil
}
if n.raw == nil {
return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial document")
}
err := json.Unmarshal(*n.raw, &n.doc)
if err != nil {
return nil, err
}
n.which = eDoc
return &n.doc, nil
}
func (n *lazyNode) intoAry() (*partialArray, error) {
if n.which == eAry {
return &n.ary, nil
}
if n.raw == nil {
return nil, fmt.Errorf("Unable to unmarshal nil pointer as partial array")
}
err := json.Unmarshal(*n.raw, &n.ary)
if err != nil {
return nil, err
}
n.which = eAry
return &n.ary, nil
}
func (n *lazyNode) compact() []byte {
buf := &bytes.Buffer{}
if n.raw == nil {
return nil
}
err := json.Compact(buf, *n.raw)
if err != nil {
return *n.raw
}
return buf.Bytes()
}
func (n *lazyNode) tryDoc() bool {
if n.raw == nil {
return false
}
err := json.Unmarshal(*n.raw, &n.doc)
if err != nil {
return false
}
n.which = eDoc
return true
}
func (n *lazyNode) tryAry() bool {
if n.raw == nil {
return false
}
err := json.Unmarshal(*n.raw, &n.ary)
if err != nil {
return false
}
n.which = eAry
return true
}
func (n *lazyNode) equal(o *lazyNode) bool {
if n.which == eRaw {
if !n.tryDoc() && !n.tryAry() {
if o.which != eRaw {
return false
}
return bytes.Equal(n.compact(), o.compact())
}
}
if n.which == eDoc {
if o.which == eRaw {
if !o.tryDoc() {
return false
}
}
if o.which != eDoc {
return false
}
for k, v := range n.doc {
ov, ok := o.doc[k]
if !ok {
return false
}
if v == nil && ov == nil {
continue
}
if !v.equal(ov) {
return false
}
}
return true
}
if o.which != eAry && !o.tryAry() {
return false
}
if len(n.ary) != len(o.ary) {
return false
}
for idx, val := range n.ary {
if !val.equal(o.ary[idx]) {
return false
}
}
return true
}
func (o operation) kind() string {
if obj, ok := o["op"]; ok && obj != nil {
var op string
err := json.Unmarshal(*obj, &op)
if err != nil {
return "unknown"
}
return op
}
return "unknown"
}
func (o operation) path() string {
if obj, ok := o["path"]; ok && obj != nil {
var op string
err := json.Unmarshal(*obj, &op)
if err != nil {
return "unknown"
}
return op
}
return "unknown"
}
func (o operation) from() string {
if obj, ok := o["from"]; ok && obj != nil {
var op string
err := json.Unmarshal(*obj, &op)
if err != nil {
return "unknown"
}
return op
}
return "unknown"
}
func (o operation) value() *lazyNode {
if obj, ok := o["value"]; ok {
return newLazyNode(obj)
}
return nil
}
func isArray(buf []byte) bool {
Loop:
for _, c := range buf {
switch c {
case ' ':
case '\n':
case '\t':
continue
case '[':
return true
default:
break Loop
}
}
return false
}
func findObject(pd *container, path string) (container, string) {
doc := *pd
split := strings.Split(path, "/")
if len(split) < 2 {
return nil, ""
}
parts := split[1 : len(split)-1]
key := split[len(split)-1]
var err error
for _, part := range parts {
next, ok := doc.get(decodePatchKey(part))
if next == nil || ok != nil {
return nil, ""
}
if isArray(*next.raw) {
doc, err = next.intoAry()
if err != nil {
return nil, ""
}
} else {
doc, err = next.intoDoc()
if err != nil {
return nil, ""
}
}
}
return doc, decodePatchKey(key)
}
func (d *partialDoc) set(key string, val *lazyNode) error {
(*d)[key] = val
return nil
}
func (d *partialDoc) add(key string, val *lazyNode) error {
(*d)[key] = val
return nil
}
func (d *partialDoc) get(key string) (*lazyNode, error) {
return (*d)[key], nil
}
func (d *partialDoc) remove(key string) error {
_, ok := (*d)[key]
if !ok {
return fmt.Errorf("Unable to remove nonexistent key: %s", key)
}
delete(*d, key)
return nil
}
// set should only be used to implement the "replace" operation, so "key" must
// be an already existing index in "d".
func (d *partialArray) set(key string, val *lazyNode) error {
idx, err := strconv.Atoi(key)
if err != nil {
return err
}
(*d)[idx] = val
return nil
}
func (d *partialArray) add(key string, val *lazyNode) error {
if key == "-" {
*d = append(*d, val)
return nil
}
idx, err := strconv.Atoi(key)
if err != nil {
return err
}
sz := len(*d) + 1
ary := make([]*lazyNode, sz)
cur := *d
if idx >= len(ary) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if SupportNegativeIndices {
if idx < -len(ary) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(ary)
}
}
copy(ary[0:idx], cur[0:idx])
ary[idx] = val
copy(ary[idx+1:], cur[idx:])
*d = ary
return nil
}
func (d *partialArray) get(key string) (*lazyNode, error) {
idx, err := strconv.Atoi(key)
if err != nil {
return nil, err
}
if idx >= len(*d) {
return nil, fmt.Errorf("Unable to access invalid index: %d", idx)
}
return (*d)[idx], nil
}
func (d *partialArray) remove(key string) error {
idx, err := strconv.Atoi(key)
if err != nil {
return err
}
cur := *d
if idx >= len(cur) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if SupportNegativeIndices {
if idx < -len(cur) {
return fmt.Errorf("Unable to access invalid index: %d", idx)
}
if idx < 0 {
idx += len(cur)
}
}
ary := make([]*lazyNode, len(cur)-1)
copy(ary[0:idx], cur[0:idx])
copy(ary[idx:], cur[idx+1:])
*d = ary
return nil
}
func (p Patch) add(doc *container, op operation) error {
path := op.path()
con, key := findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch add operation does not apply: doc is missing path: \"%s\"", path)
}
return con.add(key, op.value())
}
func (p Patch) remove(doc *container, op operation) error {
path := op.path()
con, key := findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch remove operation does not apply: doc is missing path: \"%s\"", path)
}
return con.remove(key)
}
func (p Patch) replace(doc *container, op operation) error {
path := op.path()
con, key := findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing path: %s", path)
}
_, ok := con.get(key)
if ok != nil {
return fmt.Errorf("jsonpatch replace operation does not apply: doc is missing key: %s", path)
}
return con.set(key, op.value())
}
func (p Patch) move(doc *container, op operation) error {
from := op.from()
con, key := findObject(doc, from)
if con == nil {
return fmt.Errorf("jsonpatch move operation does not apply: doc is missing from path: %s", from)
}
val, err := con.get(key)
if err != nil {
return err
}
err = con.remove(key)
if err != nil {
return err
}
path := op.path()
con, key = findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch move operation does not apply: doc is missing destination path: %s", path)
}
return con.add(key, val)
}
func (p Patch) test(doc *container, op operation) error {
path := op.path()
con, key := findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch test operation does not apply: is missing path: %s", path)
}
val, err := con.get(key)
if err != nil {
return err
}
if val == nil {
if op.value().raw == nil {
return nil
}
return fmt.Errorf("Testing value %s failed", path)
} else if op.value() == nil {
return fmt.Errorf("Testing value %s failed", path)
}
if val.equal(op.value()) {
return nil
}
return fmt.Errorf("Testing value %s failed", path)
}
func (p Patch) copy(doc *container, op operation, accumulatedCopySize *int64) error {
from := op.from()
con, key := findObject(doc, from)
if con == nil {
return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing from path: %s", from)
}
val, err := con.get(key)
if err != nil {
return err
}
path := op.path()
con, key = findObject(doc, path)
if con == nil {
return fmt.Errorf("jsonpatch copy operation does not apply: doc is missing destination path: %s", path)
}
valCopy, sz, err := deepCopy(val)
if err != nil {
return err
}
(*accumulatedCopySize) += int64(sz)
if AccumulatedCopySizeLimit > 0 && *accumulatedCopySize > AccumulatedCopySizeLimit {
return NewAccumulatedCopySizeError(AccumulatedCopySizeLimit, *accumulatedCopySize)
}
return con.add(key, valCopy)
}
// Equal indicates if 2 JSON documents have the same structural equality.
func Equal(a, b []byte) bool {
ra := make(json.RawMessage, len(a))
copy(ra, a)
la := newLazyNode(&ra)
rb := make(json.RawMessage, len(b))
copy(rb, b)
lb := newLazyNode(&rb)
return la.equal(lb)
}
// DecodePatch decodes the passed JSON document as an RFC 6902 patch.
func DecodePatch(buf []byte) (Patch, error) {
var p Patch
err := json.Unmarshal(buf, &p)
if err != nil {
return nil, err
}
return p, nil
}
// Apply mutates a JSON document according to the patch, and returns the new
// document.
func (p Patch) Apply(doc []byte) ([]byte, error) {
return p.ApplyIndent(doc, "")
}
// ApplyIndent mutates a JSON document according to the patch, and returns the new
// document indented.
func (p Patch) ApplyIndent(doc []byte, indent string) ([]byte, error) {
var pd container
if doc[0] == '[' {
pd = &partialArray{}
} else {
pd = &partialDoc{}
}
err := json.Unmarshal(doc, pd)
if err != nil {
return nil, err
}
err = nil
var accumulatedCopySize int64
for _, op := range p {
switch op.kind() {
case "add":
err = p.add(&pd, op)
case "remove":
err = p.remove(&pd, op)
case "replace":
err = p.replace(&pd, op)
case "move":
err = p.move(&pd, op)
case "test":
err = p.test(&pd, op)
case "copy":
err = p.copy(&pd, op, &accumulatedCopySize)
default:
err = fmt.Errorf("Unexpected kind: %s", op.kind())
}
if err != nil {
return nil, err
}
}
if indent != "" {
return json.MarshalIndent(pd, "", indent)
}
return json.Marshal(pd)
}
// From http://tools.ietf.org/html/rfc6901#section-4 :
//
// Evaluation of each reference token begins by decoding any escaped
// character sequence. This is performed by first transforming any
// occurrence of the sequence '~1' to '/', and then transforming any
// occurrence of the sequence '~0' to '~'.
var (
rfc6901Decoder = strings.NewReplacer("~1", "/", "~0", "~")
)
func decodePatchKey(k string) string {
return rfc6901Decoder.Replace(k)
}

View File

@ -1,7 +0,0 @@
language: go
go:
- 1.3
- 1.4
script:
- go test
- go build

View File

@ -1,6 +1,9 @@
module github.com/go-openapi/jsonpointer
require (
github.com/go-openapi/swag v0.19.2
github.com/go-openapi/swag v0.19.5
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e // indirect
github.com/stretchr/testify v1.3.0
)
go 1.13

View File

@ -1,8 +1,8 @@
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/go-openapi/swag v0.19.2 h1:jvO6bCMBEilGwMfHhrd61zIID4oIFdwb76V17SM88dE=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5 h1:lTz6Ys4CmqqCQmZPBlbQENR1/GucA2bzYTE12Pw4tFY=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/kr/pretty v0.1.0 h1:L/CwN0zerZDmRFUapSPitk6f+Q3+0za1rQkzVuMiMFI=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
@ -10,6 +10,8 @@ github.com/kr/text v0.1.0 h1:45sCR5RtlFHMR4UwH9sdQ5TC8v0qDQCHnXt+kaKSTVE=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63 h1:nTT4s92Dgz2HlrB2NaMgvlfqHH39OgMhA7z3PK7PGD4=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e h1:hB2xlXdHp/pmPZq0y3QnmWAArdw9PqbmotexnWx/FU8=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=

View File

@ -135,7 +135,7 @@ func getSingleImpl(node interface{}, decodedToken string, nameProvider *swag.Nam
kv := reflect.ValueOf(decodedToken)
mv := rValue.MapIndex(kv)
if mv.IsValid() && !swag.IsZero(mv) {
if mv.IsValid() {
return mv.Interface(), kind, nil
}
return nil, kind, fmt.Errorf("object has no key %q", decodedToken)

View File

@ -1,3 +1,4 @@
secrets.yml
vendor
Godeps
.idea

View File

@ -39,11 +39,12 @@ func IsFloat64AJSONInteger(f float64) bool {
diff := math.Abs(f - g)
// more info: https://floating-point-gui.de/errors/comparison/#look-out-for-edge-cases
if f == g { // best case
switch {
case f == g: // best case
return true
} else if f == float64(int64(f)) || f == float64(uint64(f)) { // optimistic case
case f == float64(int64(f)) || f == float64(uint64(f)): // optimistic case
return true
} else if f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64 { // very close to 0 values
case f == 0 || g == 0 || diff < math.SmallestNonzeroFloat64: // very close to 0 values
return diff < (epsilon * math.SmallestNonzeroFloat64)
}
// check the relative error

Some files were not shown because too many files have changed in this diff Show More