From 6a4e482b3788230ac5ab61db46401540ee8cbbdc Mon Sep 17 00:00:00 2001 From: Rahul Sharma Date: Thu, 20 Jun 2024 11:19:46 -0400 Subject: [PATCH] add timeout for linodego http client (#219) * add timeout for linodego http client * address review comments --------- Co-authored-by: Rahul Sharma --- README.md | 13 +++++++++++-- cloud/linode/client/client.go | 29 +++++++++++++++++++++++++---- cloud/linode/cloud.go | 15 ++++++++++----- 3 files changed, 46 insertions(+), 11 deletions(-) diff --git a/README.md b/README.md index de3381da..5c2987f9 100644 --- a/README.md +++ b/README.md @@ -286,6 +286,15 @@ sessionAffinityConfig: timeoutSeconds: 100 ``` +## Additional environment variables +To tweak CCM based on needs, one can overwrite the default values set for caches and requests by setting appropriate environment variables when applying the manifest or helm chart. + +Environment Variable | Default | Description +---|---|--- +`LINODE_INSTANCE_CACHE_TTL` | `15` | Default timeout of instance cache in seconds +`LINODE_ROUTES_CACHE_TTL_SECONDS` | `60` | Default timeout of route cache in seconds +`LINODE_REQUEST_TIMEOUT_SECONDS` | `120` | Default timeout in seconds for http requests to linode API + ## Generating a Manifest for Deployment Use the script located at `./deploy/generate-manifest.sh` to generate a self-contained deployment manifest for the Linode CCM. Two arguments are required. @@ -320,7 +329,7 @@ helm repo update ccm-linode ### To deploy ccm-linode. Run the following command: ```sh -export VERSION=v0.3.22 +export VERSION=v0.4.8 export LINODE_API_TOKEN= export REGION= helm install ccm-linode --set apiToken=$LINODE_API_TOKEN,region=$REGION ccm-linode/ccm-linode @@ -335,7 +344,7 @@ _See [helm uninstall](https://helm.sh/docs/helm/helm_uninstall/) for command doc ### To upgrade when new changes are made to the helm chart. Run the following command: ```sh -export VERSION=v0.3.22 +export VERSION=v0.4.8 export LINODE_API_TOKEN= export REGION= diff --git a/cloud/linode/client/client.go b/cloud/linode/client/client.go index ce7ff307..abf5bee7 100644 --- a/cloud/linode/client/client.go +++ b/cloud/linode/client/client.go @@ -4,8 +4,19 @@ package client import ( "context" + "fmt" + "net/http" + "os" + "time" "github.com/linode/linodego" + "golang.org/x/oauth2" + "k8s.io/klog/v2" +) + +const ( + // DefaultClientTimeout is the default timeout for a client Linode API call + DefaultClientTimeout = 120 * time.Second ) type Client interface { @@ -47,15 +58,25 @@ type Client interface { // linodego.Client implements Client var _ Client = (*linodego.Client)(nil) -// New creates a new linode client with a given token, userAgent, and API URL -func New(token, userAgent, apiURL string) (*linodego.Client, error) { - linodeClient := linodego.NewClient(nil) +// New creates a new linode client with a given token and default timeout +func New(token string, timeout time.Duration) (*linodego.Client, error) { + userAgent := fmt.Sprintf("linode-cloud-controller-manager %s", linodego.DefaultUserAgent) + apiURL := os.Getenv("LINODE_URL") + + tokenSource := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: token}) + oauth2Client := &http.Client{ + Transport: &oauth2.Transport{ + Source: tokenSource, + }, + Timeout: timeout, + } + linodeClient := linodego.NewClient(oauth2Client) client, err := linodeClient.UseURL(apiURL) if err != nil { return nil, err } client.SetUserAgent(userAgent) - client.SetToken(token) + klog.V(3).Infof("Linode client created with default timeout of %v", timeout) return client, nil } diff --git a/cloud/linode/cloud.go b/cloud/linode/cloud.go index a7d5fc54..f1138988 100644 --- a/cloud/linode/cloud.go +++ b/cloud/linode/cloud.go @@ -4,9 +4,10 @@ import ( "fmt" "io" "os" + "strconv" "sync" + "time" - "github.com/linode/linodego" "github.com/spf13/pflag" "golang.org/x/exp/slices" "k8s.io/client-go/informers" @@ -20,7 +21,6 @@ const ( ProviderName = "linode" accessTokenEnv = "LINODE_API_TOKEN" regionEnv = "LINODE_REGION" - urlEnv = "LINODE_URL" ciliumLBType = "cilium-bgp" nodeBalancerLBType = "nodebalancer" ) @@ -95,10 +95,15 @@ func newCloud() (cloudprovider.Interface, error) { return nil, fmt.Errorf("%s must be set in the environment (use a k8s secret)", regionEnv) } - url := os.Getenv(urlEnv) - ua := fmt.Sprintf("linode-cloud-controller-manager %s", linodego.DefaultUserAgent) + // set timeout used by linodeclient for API calls + timeout := client.DefaultClientTimeout + if raw, ok := os.LookupEnv("LINODE_REQUEST_TIMEOUT_SECONDS"); ok { + if t, err := strconv.Atoi(raw); err == nil && t > 0 { + timeout = time.Duration(t) * time.Second + } + } - linodeClient, err := client.New(apiToken, ua, url) + linodeClient, err := client.New(apiToken, timeout) if err != nil { return nil, fmt.Errorf("client was not created succesfully: %w", err) }