diff --git a/build/ci/library_owners.json b/build/ci/library_owners.json index 2255ed8bc0..ba62692b19 100644 --- a/build/ci/library_owners.json +++ b/build/ci/library_owners.json @@ -53,5 +53,6 @@ "sigs.k8s.io/kind": "atlas_kubernetes_team", "golang.org/x/exp": "atlas_kubernetes_team", "github.com/denisbrodbeck/machineid": "apix-2", - "github.com/shirou/gopsutil/v4": "apix-2" + "github.com/shirou/gopsutil/v4": "apix-2", + "github.com/rapid7/go-get-proxied": "apix-2" } diff --git a/go.mod b/go.mod index 708a1ba8e9..0abd870df7 100644 --- a/go.mod +++ b/go.mod @@ -32,6 +32,7 @@ require ( github.com/mongodb/mongodb-atlas-kubernetes/v2 v2.5.0 github.com/pelletier/go-toml v1.9.5 github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c + github.com/rapid7/go-get-proxied v0.0.0-20240311092404-798791728c56 github.com/shirou/gopsutil/v4 v4.24.10 github.com/spf13/afero v1.11.0 github.com/spf13/cobra v1.8.1 diff --git a/go.sum b/go.sum index 56732a1303..1214b67924 100644 --- a/go.sum +++ b/go.sum @@ -301,6 +301,8 @@ github.com/prometheus/common v0.55.0 h1:KEi6DK7lXW/m7Ig5i47x0vRzuBsHuvJdi5ee6Y3G github.com/prometheus/common v0.55.0/go.mod h1:2SECS4xJG1kd8XF9IcM1gMX6510RAEL65zxzNImwdc8= github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc= github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk= +github.com/rapid7/go-get-proxied v0.0.0-20240311092404-798791728c56 h1:NMFnJUxI7m/To0on5bGzxyqZbFQBIK6yfacNj+JP1dg= +github.com/rapid7/go-get-proxied v0.0.0-20240311092404-798791728c56/go.mod h1:ELOKvSUbHx1oVeecsknc02S0eEAFD+TdV3rTt3BcNzM= github.com/redis/go-redis/v9 v9.6.1 h1:HHDteefn6ZkTtY5fGUE8tj8uy85AHk6zP7CpzIAM0y4= github.com/redis/go-redis/v9 v9.6.1/go.mod h1:0C0c6ycQsdpVNQpxb1njEQIqkx5UcsM8FJCQLgE9+RA= github.com/rogpeppe/go-internal v1.12.0 h1:exVL4IDcn6na9z1rAb56Vxr+CgyK3nn3O+epU5NdKM8= diff --git a/internal/oauth/oauth.go b/internal/oauth/oauth.go index 14844a0c8a..f2e076d535 100644 --- a/internal/oauth/oauth.go +++ b/internal/oauth/oauth.go @@ -15,36 +15,13 @@ package oauth import ( - "net" "net/http" - "time" "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config" + "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/transport" "go.mongodb.org/atlas/auth" ) -const ( - timeout = 5 * time.Second - keepAlive = 30 * time.Second - maxIdleConns = 5 - maxIdleConnsPerHost = 4 - idleConnTimeout = 30 * time.Second - expectContinueTimeout = 1 * time.Second - cloudGovServiceURL = "https://cloud.mongodbgov.com/" -) - -var defaultTransport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: timeout, - KeepAlive: keepAlive, - }).DialContext, - MaxIdleConns: maxIdleConns, - MaxIdleConnsPerHost: maxIdleConnsPerHost, - Proxy: http.ProxyFromEnvironment, - IdleConnTimeout: idleConnTimeout, - ExpectContinueTimeout: expectContinueTimeout, -} - type ServiceGetter interface { Service() string OpsManagerURL() string @@ -58,7 +35,7 @@ const ( func FlowWithConfig(c ServiceGetter) (*auth.Config, error) { client := http.DefaultClient - client.Transport = defaultTransport + client.Transport = transport.DefaultTransport id := ClientID if c.Service() == config.CloudGovService { id = GovClientID @@ -75,7 +52,7 @@ func FlowWithConfig(c ServiceGetter) (*auth.Config, error) { if configURL := c.OpsManagerURL(); configURL != "" { authOpts = append(authOpts, auth.SetAuthURL(c.OpsManagerURL())) } else if c.Service() == config.CloudGovService { - authOpts = append(authOpts, auth.SetAuthURL(cloudGovServiceURL)) + authOpts = append(authOpts, auth.SetAuthURL(transport.CloudGovServiceURL)) } return auth.NewConfigWithOptions(client, authOpts...) } diff --git a/internal/store/store.go b/internal/store/store.go index 8cf08a18ab..280a2ac027 100644 --- a/internal/store/store.go +++ b/internal/store/store.go @@ -20,31 +20,19 @@ import ( "context" "errors" "fmt" - "net" "net/http" "strings" - "time" "github.com/mongodb-forks/digest" "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/config" "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/log" + "github.com/mongodb/mongodb-atlas-cli/atlascli/internal/transport" atlasClustersPinned "go.mongodb.org/atlas-sdk/v20240530005/admin" atlasv2 "go.mongodb.org/atlas-sdk/v20241023002/admin" atlasauth "go.mongodb.org/atlas/auth" atlas "go.mongodb.org/atlas/mongodbatlas" ) -const ( - telemetryTimeout = 1 * time.Second - timeout = 5 * time.Second - keepAlive = 30 * time.Second - maxIdleConns = 5 - maxIdleConnsPerHost = 4 - idleConnTimeout = 30 * time.Second - expectContinueTimeout = 1 * time.Second - cloudGovServiceURL = "https://cloud.mongodbgov.com/" -) - var errUnsupportedService = errors.New("unsupported service") type Store struct { @@ -62,30 +50,6 @@ type Store struct { ctx context.Context } -var defaultTransport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: timeout, - KeepAlive: keepAlive, - }).DialContext, - MaxIdleConns: maxIdleConns, - MaxIdleConnsPerHost: maxIdleConnsPerHost, - Proxy: http.ProxyFromEnvironment, - IdleConnTimeout: idleConnTimeout, - ExpectContinueTimeout: expectContinueTimeout, -} - -var telemetryTransport = &http.Transport{ - DialContext: (&net.Dialer{ - Timeout: telemetryTimeout, - KeepAlive: keepAlive, - }).DialContext, - MaxIdleConns: maxIdleConns, - MaxIdleConnsPerHost: maxIdleConnsPerHost, - Proxy: http.ProxyFromEnvironment, - IdleConnTimeout: idleConnTimeout, - ExpectContinueTimeout: expectContinueTimeout, -} - func (s *Store) httpClient(httpTransport http.RoundTripper) (*http.Client, error) { if s.username != "" && s.password != "" { t := &digest.Transport{ @@ -120,9 +84,9 @@ func (tr *Transport) RoundTrip(req *http.Request) (*http.Response, error) { func (s *Store) transport() *http.Transport { switch { case s.telemetry: - return telemetryTransport + return transport.TelemetryTransport default: - return defaultTransport + return transport.DefaultTransport } } @@ -306,7 +270,7 @@ func baseURLOption(c ServiceGetter) Option { if configURL := c.OpsManagerURL(); configURL != "" { return WithBaseURL(configURL) } else if c.Service() == config.CloudGovService { - return WithBaseURL(cloudGovServiceURL) + return WithBaseURL(transport.CloudGovServiceURL) } return nil } diff --git a/internal/transport/transport.go b/internal/transport/transport.go new file mode 100644 index 0000000000..4f856a778b --- /dev/null +++ b/internal/transport/transport.go @@ -0,0 +1,75 @@ +// Copyright 2024 MongoDB 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. + +package transport + +import ( + "net" + "net/http" + "net/url" + "time" + + "github.com/rapid7/go-get-proxied/proxy" +) + +const ( + timeout = 5 * time.Second + keepAlive = 30 * time.Second + maxIdleConns = 5 + maxIdleConnsPerHost = 4 + idleConnTimeout = 30 * time.Second + expectContinueTimeout = 1 * time.Second + CloudGovServiceURL = "https://cloud.mongodbgov.com/" + telemetryTimeout = 1 * time.Second +) + +func proxyFromSettingsAndEnv(req *http.Request) (*url.URL, error) { + switch req.URL.Scheme { + case "http": + p := proxy.NewProvider("").GetHTTPProxy(req.URL.String()) + if p != nil { + return p.URL(), nil + } + case "https": + p := proxy.NewProvider("").GetHTTPSProxy(req.URL.String()) + if p != nil { + return p.URL(), nil + } + } + return nil, nil +} + +var DefaultTransport = &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: timeout, + KeepAlive: keepAlive, + }).DialContext, + MaxIdleConns: maxIdleConns, + MaxIdleConnsPerHost: maxIdleConnsPerHost, + Proxy: proxyFromSettingsAndEnv, + IdleConnTimeout: idleConnTimeout, + ExpectContinueTimeout: expectContinueTimeout, +} + +var TelemetryTransport = &http.Transport{ + DialContext: (&net.Dialer{ + Timeout: telemetryTimeout, + KeepAlive: keepAlive, + }).DialContext, + MaxIdleConns: maxIdleConns, + MaxIdleConnsPerHost: maxIdleConnsPerHost, + Proxy: proxyFromSettingsAndEnv, + IdleConnTimeout: idleConnTimeout, + ExpectContinueTimeout: expectContinueTimeout, +}