fix Incorrectly generated query strings (that rely on + not being urlencoded)
In the Kubernetes API client, we should be able to generate queries like
?labelSelector=environment+in+%28production%2Cqa%29%2Ctier+in+%28frontend%29
(from https://kubernetes.io/docs/concepts/overview/working-with-objects/labels/#list-and-watch-filtering).
When the generated URIs URL-encode the plus signs, the API server rejects them.
With this change, (newConfig :: IO KubernetesClientConfig) now sets
the default configQueryExtraUnreserved setting to "+". Requests
generated with this config object will avoid URI encoding "+" all
querystring params.
This commit is contained in:
@@ -5,7 +5,7 @@ cabal-version: 1.12
|
||||
-- see: https://github.com/sol/hpack
|
||||
|
||||
name: kubernetes-client
|
||||
version: 0.4.1.0
|
||||
version: 0.4.2.0
|
||||
synopsis: Client library for Kubernetes
|
||||
description: Client library for interacting with a Kubernetes cluster.
|
||||
.
|
||||
@@ -60,7 +60,7 @@ library
|
||||
, http-client-tls >=0.3
|
||||
, jose-jwt >=0.8
|
||||
, jsonpath >=0.1 && <0.3
|
||||
, kubernetes-client-core ==0.4.1.0
|
||||
, kubernetes-client-core ==0.4.2.0
|
||||
, microlens >=0.4
|
||||
, mtl >=2.2
|
||||
, oidc-client >=0.4
|
||||
@@ -105,7 +105,7 @@ test-suite example
|
||||
, jose-jwt >=0.8
|
||||
, jsonpath >=0.1 && <0.3
|
||||
, kubernetes-client
|
||||
, kubernetes-client-core ==0.4.1.0
|
||||
, kubernetes-client-core ==0.4.2.0
|
||||
, microlens >=0.4
|
||||
, mtl >=2.2
|
||||
, oidc-client >=0.4
|
||||
@@ -158,7 +158,7 @@ test-suite spec
|
||||
, jose-jwt >=0.8
|
||||
, jsonpath >=0.1 && <0.3
|
||||
, kubernetes-client
|
||||
, kubernetes-client-core ==0.4.1.0
|
||||
, kubernetes-client-core ==0.4.2.0
|
||||
, microlens >=0.4
|
||||
, mtl >=2.2
|
||||
, oidc-client >=0.4
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: kubernetes-client
|
||||
version: 0.4.1.0
|
||||
version: 0.4.2.0
|
||||
description: |
|
||||
Client library for interacting with a Kubernetes cluster.
|
||||
|
||||
@@ -49,7 +49,7 @@ dependencies:
|
||||
- http-client >=0.5 && <0.8
|
||||
- http-client-tls >=0.3
|
||||
- jose-jwt >=0.8
|
||||
- kubernetes-client-core ==0.4.1.0
|
||||
- kubernetes-client-core ==0.4.2.0
|
||||
- microlens >=0.4
|
||||
- mtl >=2.2
|
||||
- oidc-client >=0.4
|
||||
|
||||
@@ -1,2 +1,2 @@
|
||||
Requested Commit: df877a8cf9b5e2b7a02c6e88dc4767b1e25c0b6f
|
||||
Actual Commit: df877a8cf9b5e2b7a02c6e88dc4767b1e25c0b6f
|
||||
Requested Commit: 1247e774530b715fb54f719a3b10000d5dd2137b
|
||||
Actual Commit: 1247e774530b715fb54f719a3b10000d5dd2137b
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: kubernetes-client-core
|
||||
version: 0.4.1.0
|
||||
version: 0.4.2.0
|
||||
synopsis: Auto-generated kubernetes-client-core API Client
|
||||
description: .
|
||||
Client library for calling the Kubernetes API based on http-client.
|
||||
|
||||
@@ -550,6 +550,11 @@ instance HasOptionalParam ListClusterCustomObject Pretty where
|
||||
applyOptionalParam req (Pretty xs) =
|
||||
req `addQuery` toQuery ("pretty", Just xs)
|
||||
|
||||
-- | /Optional Param/ "allowWatchBookmarks" - allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.
|
||||
instance HasOptionalParam ListClusterCustomObject AllowWatchBookmarks where
|
||||
applyOptionalParam req (AllowWatchBookmarks xs) =
|
||||
req `addQuery` toQuery ("allowWatchBookmarks", Just xs)
|
||||
|
||||
-- | /Optional Param/ "continue" - The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.
|
||||
instance HasOptionalParam ListClusterCustomObject Continue where
|
||||
applyOptionalParam req (Continue xs) =
|
||||
@@ -575,6 +580,11 @@ instance HasOptionalParam ListClusterCustomObject ResourceVersion where
|
||||
applyOptionalParam req (ResourceVersion xs) =
|
||||
req `addQuery` toQuery ("resourceVersion", Just xs)
|
||||
|
||||
-- | /Optional Param/ "resourceVersionMatch" - resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. Defaults to unset
|
||||
instance HasOptionalParam ListClusterCustomObject ResourceVersionMatch where
|
||||
applyOptionalParam req (ResourceVersionMatch xs) =
|
||||
req `addQuery` toQuery ("resourceVersionMatch", Just xs)
|
||||
|
||||
-- | /Optional Param/ "timeoutSeconds" - Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.
|
||||
instance HasOptionalParam ListClusterCustomObject TimeoutSeconds where
|
||||
applyOptionalParam req (TimeoutSeconds xs) =
|
||||
@@ -616,6 +626,11 @@ instance HasOptionalParam ListNamespacedCustomObject Pretty where
|
||||
applyOptionalParam req (Pretty xs) =
|
||||
req `addQuery` toQuery ("pretty", Just xs)
|
||||
|
||||
-- | /Optional Param/ "allowWatchBookmarks" - allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.
|
||||
instance HasOptionalParam ListNamespacedCustomObject AllowWatchBookmarks where
|
||||
applyOptionalParam req (AllowWatchBookmarks xs) =
|
||||
req `addQuery` toQuery ("allowWatchBookmarks", Just xs)
|
||||
|
||||
-- | /Optional Param/ "continue" - The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the \"next key\". This field is not supported when watch is true. Clients may start a watch from the last resourceVersion value returned by the server and not miss any modifications.
|
||||
instance HasOptionalParam ListNamespacedCustomObject Continue where
|
||||
applyOptionalParam req (Continue xs) =
|
||||
@@ -641,6 +656,11 @@ instance HasOptionalParam ListNamespacedCustomObject ResourceVersion where
|
||||
applyOptionalParam req (ResourceVersion xs) =
|
||||
req `addQuery` toQuery ("resourceVersion", Just xs)
|
||||
|
||||
-- | /Optional Param/ "resourceVersionMatch" - resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details. Defaults to unset
|
||||
instance HasOptionalParam ListNamespacedCustomObject ResourceVersionMatch where
|
||||
applyOptionalParam req (ResourceVersionMatch xs) =
|
||||
req `addQuery` toQuery ("resourceVersionMatch", Just xs)
|
||||
|
||||
-- | /Optional Param/ "timeoutSeconds" - Timeout for the list/watch call. This limits the duration of the call, regardless of any activity or inactivity.
|
||||
instance HasOptionalParam ListNamespacedCustomObject TimeoutSeconds where
|
||||
applyOptionalParam req (TimeoutSeconds xs) =
|
||||
|
||||
@@ -32,6 +32,7 @@ import qualified Control.Exception.Safe as E
|
||||
import qualified Control.Monad.IO.Class as P
|
||||
import qualified Control.Monad as P
|
||||
import qualified Data.Aeson.Types as A
|
||||
import qualified Data.ByteString as B
|
||||
import qualified Data.ByteString.Char8 as BC
|
||||
import qualified Data.ByteString.Lazy as BL
|
||||
import qualified Data.ByteString.Lazy.Char8 as BCL
|
||||
@@ -179,13 +180,18 @@ _toInitRequest config req0 =
|
||||
(configValidateAuthMethods config && (not . null . rAuthTypes) req1)
|
||||
(E.throw $ AuthMethodException $ "AuthMethod not configured: " <> (show . head . rAuthTypes) req1)
|
||||
let req2 = req1 & _setContentTypeHeader & _setAcceptHeader
|
||||
reqHeaders = ("User-Agent", WH.toHeader (configUserAgent config)) : paramsHeaders (rParams req2)
|
||||
reqQuery = NH.renderQuery True (paramsQuery (rParams req2))
|
||||
pReq = parsedReq { NH.method = (rMethod req2)
|
||||
params = rParams req2
|
||||
reqHeaders = ("User-Agent", WH.toHeader (configUserAgent config)) : paramsHeaders params
|
||||
reqQuery = let query = paramsQuery params
|
||||
queryExtraUnreserved = configQueryExtraUnreserved config
|
||||
in if B.null queryExtraUnreserved
|
||||
then NH.renderQuery True query
|
||||
else NH.renderQueryPartialEscape True (toPartialEscapeQuery queryExtraUnreserved query)
|
||||
pReq = parsedReq { NH.method = rMethod req2
|
||||
, NH.requestHeaders = reqHeaders
|
||||
, NH.queryString = reqQuery
|
||||
}
|
||||
outReq <- case paramsBody (rParams req2) of
|
||||
outReq <- case paramsBody params of
|
||||
ParamBodyNone -> pure (pReq { NH.requestBody = mempty })
|
||||
ParamBodyB bs -> pure (pReq { NH.requestBody = NH.RequestBodyBS bs })
|
||||
ParamBodyBL bl -> pure (pReq { NH.requestBody = NH.RequestBodyLBS bl })
|
||||
|
||||
@@ -67,7 +67,7 @@ import Data.Function ((&))
|
||||
import Data.Foldable(foldlM)
|
||||
import Data.Monoid ((<>))
|
||||
import Data.Text (Text)
|
||||
import Prelude (($), (.), (<$>), (<*>), Maybe(..), Bool(..), Char, String, fmap, mempty, pure, return, show, IO, Monad, Functor)
|
||||
import Prelude (($), (.), (&&), (<$>), (<*>), Maybe(..), Bool(..), Char, String, fmap, mempty, pure, return, show, IO, Monad, Functor, maybe)
|
||||
|
||||
-- * KubernetesClientConfig
|
||||
|
||||
@@ -79,6 +79,7 @@ data KubernetesClientConfig = KubernetesClientConfig
|
||||
, configLogContext :: LogContext -- ^ Configures the logger
|
||||
, configAuthMethods :: [AnyAuthMethod] -- ^ List of configured auth methods
|
||||
, configValidateAuthMethods :: Bool -- ^ throw exceptions if auth methods are not configured
|
||||
, configQueryExtraUnreserved :: B.ByteString -- ^ Configures additional querystring characters which must not be URI encoded, e.g. '+' or ':'
|
||||
}
|
||||
|
||||
-- | display the config
|
||||
@@ -109,6 +110,7 @@ newConfig = do
|
||||
, configLogContext = logCxt
|
||||
, configAuthMethods = []
|
||||
, configValidateAuthMethods = True
|
||||
, configQueryExtraUnreserved = "+"
|
||||
}
|
||||
|
||||
-- | updates config use AuthMethod on matching requests
|
||||
@@ -336,6 +338,16 @@ toQuery :: WH.ToHttpApiData a => (BC.ByteString, Maybe a) -> [NH.QueryItem]
|
||||
toQuery x = [(fmap . fmap) toQueryParam x]
|
||||
where toQueryParam = T.encodeUtf8 . WH.toQueryParam
|
||||
|
||||
toPartialEscapeQuery :: B.ByteString -> NH.Query -> NH.PartialEscapeQuery
|
||||
toPartialEscapeQuery extraUnreserved query = fmap (\(k, v) -> (k, maybe [] go v)) query
|
||||
where go :: B.ByteString -> [NH.EscapeItem]
|
||||
go v = v & B.groupBy (\a b -> a `B.notElem` extraUnreserved && b `B.notElem` extraUnreserved)
|
||||
& fmap (\xs -> if B.null xs then NH.QN xs
|
||||
else if B.head xs `B.elem` extraUnreserved
|
||||
then NH.QN xs -- Not Encoded
|
||||
else NH.QE xs -- Encoded
|
||||
)
|
||||
|
||||
-- *** OpenAPI `CollectionFormat` Utils
|
||||
|
||||
-- | Determines the format of the array if type array is used.
|
||||
|
||||
@@ -68576,6 +68576,17 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: allowWatchBookmarks requests watch events with type "BOOKMARK".
|
||||
Servers that do not implement bookmarks may ignore this flag and bookmarks
|
||||
are sent at the server's discretion. Clients should not assume bookmarks
|
||||
are returned at any specific interval, nor may they assume the server will
|
||||
send any BOOKMARK event during a session. If this is not a watch, this field
|
||||
is ignored. If the feature gate WatchBookmarks is not enabled in apiserver,
|
||||
this field is ignored.
|
||||
in: query
|
||||
name: allowWatchBookmarks
|
||||
schema:
|
||||
type: boolean
|
||||
- description: |-
|
||||
The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key".
|
||||
|
||||
@@ -68614,6 +68625,14 @@ paths:
|
||||
name: resourceVersion
|
||||
schema:
|
||||
type: string
|
||||
- description: |-
|
||||
resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.
|
||||
|
||||
Defaults to unset
|
||||
in: query
|
||||
name: resourceVersionMatch
|
||||
schema:
|
||||
type: string
|
||||
- description: Timeout for the list/watch call. This limits the duration of
|
||||
the call, regardless of any activity or inactivity.
|
||||
in: query
|
||||
@@ -68819,6 +68838,17 @@ paths:
|
||||
required: true
|
||||
schema:
|
||||
type: string
|
||||
- description: allowWatchBookmarks requests watch events with type "BOOKMARK".
|
||||
Servers that do not implement bookmarks may ignore this flag and bookmarks
|
||||
are sent at the server's discretion. Clients should not assume bookmarks
|
||||
are returned at any specific interval, nor may they assume the server will
|
||||
send any BOOKMARK event during a session. If this is not a watch, this field
|
||||
is ignored. If the feature gate WatchBookmarks is not enabled in apiserver,
|
||||
this field is ignored.
|
||||
in: query
|
||||
name: allowWatchBookmarks
|
||||
schema:
|
||||
type: boolean
|
||||
- description: |-
|
||||
The continue option should be set when retrieving more results from the server. Since this value is server defined, clients may only use the continue value from a previous query result with identical query parameters (except for the value of continue) and the server may reject a continue value it does not recognize. If the specified continue value is no longer valid whether due to expiration (generally five to fifteen minutes) or a configuration change on the server, the server will respond with a 410 ResourceExpired error together with a continue token. If the client needs a consistent list, it must restart their list without the continue field. Otherwise, the client may send another list request with the token received with the 410 error, the server will respond with a list starting from the next key, but from the latest snapshot, which is inconsistent from the previous list results - objects that are created, modified, or deleted after the first list request will be included in the response, as long as their keys are after the "next key".
|
||||
|
||||
@@ -68857,6 +68887,14 @@ paths:
|
||||
name: resourceVersion
|
||||
schema:
|
||||
type: string
|
||||
- description: |-
|
||||
resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.
|
||||
|
||||
Defaults to unset
|
||||
in: query
|
||||
name: resourceVersionMatch
|
||||
schema:
|
||||
type: string
|
||||
- description: Timeout for the list/watch call. This limits the duration of
|
||||
the call, regardless of any activity or inactivity.
|
||||
in: query
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
resolver: lts-14.7
|
||||
resolver: lts-18.6
|
||||
build:
|
||||
haddock-arguments:
|
||||
haddock-args:
|
||||
|
||||
@@ -102276,6 +102276,13 @@
|
||||
],
|
||||
"description": "list or watch namespace scoped custom objects",
|
||||
"parameters": [
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"type": "boolean",
|
||||
"description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.",
|
||||
"name": "allowWatchBookmarks",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"in": "query",
|
||||
@@ -102311,6 +102318,13 @@
|
||||
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
"name": "resourceVersion"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"type": "string",
|
||||
"description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
"name": "resourceVersionMatch",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"in": "query",
|
||||
@@ -102502,6 +102516,13 @@
|
||||
],
|
||||
"description": "list or watch cluster scoped custom objects",
|
||||
"parameters": [
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"type": "boolean",
|
||||
"description": "allowWatchBookmarks requests watch events with type \"BOOKMARK\". Servers that do not implement bookmarks may ignore this flag and bookmarks are sent at the server's discretion. Clients should not assume bookmarks are returned at any specific interval, nor may they assume the server will send any BOOKMARK event during a session. If this is not a watch, this field is ignored. If the feature gate WatchBookmarks is not enabled in apiserver, this field is ignored.",
|
||||
"name": "allowWatchBookmarks",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"in": "query",
|
||||
@@ -102537,6 +102558,13 @@
|
||||
"description": "When specified with a watch call, shows changes that occur after that particular version of a resource. Defaults to changes from the beginning of history. When specified for list: - if unset, then the result is returned from remote storage based on quorum-read flag; - if it's 0, then we simply return what we currently have in cache, no guarantee; - if set to non zero, then the result is at least as fresh as given rv.",
|
||||
"name": "resourceVersion"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"type": "string",
|
||||
"description": "resourceVersionMatch determines how resourceVersion is applied to list calls. It is highly recommended that resourceVersionMatch be set for list calls where resourceVersion is set See https://kubernetes.io/docs/reference/using-api/api-concepts/#resource-versions for details.\n\nDefaults to unset",
|
||||
"name": "resourceVersionMatch",
|
||||
"in": "query"
|
||||
},
|
||||
{
|
||||
"uniqueItems": true,
|
||||
"in": "query",
|
||||
|
||||
Reference in New Issue
Block a user