diff --git a/pkg/compose/config.go b/pkg/compose/config.go index b9650ed..81a7c4b 100644 --- a/pkg/compose/config.go +++ b/pkg/compose/config.go @@ -23,10 +23,13 @@ type ( AppStoreFactoryFunc func(c *Config) (AppStore, error) BlockSize int64 DBFilePath string - + Proxy ProxyProvider + } + ProxyConfig struct { ProxyURL *url.URL ProxyCerts *x509.CertPool } + ProxyProvider func() *ProxyConfig ) func (c *Config) GetAppComposeDir(appName string) string { diff --git a/pkg/compose/provider.go b/pkg/compose/provider.go index 5b982f8..9751b7c 100644 --- a/pkg/compose/provider.go +++ b/pkg/compose/provider.go @@ -88,14 +88,15 @@ func (t tokenProxyTripper) RoundTrip(req *http.Request) (*http.Response, error) func NewRemoteBlobProviderFromConfig(config *Config) BlobProvider { client := NewHttpClient(config.ConnectTimeout, config.ReadTimeout) - if config.ProxyURL != nil { + if config.Proxy != nil { + proxyConfig := config.Proxy() tpt := tokenProxyTripper{ base: client.Transport, - host: config.ProxyURL, + host: proxyConfig.ProxyURL, } - if config.ProxyCerts != nil { - client.Transport.(*http.Transport).TLSClientConfig.RootCAs = config.ProxyCerts + if proxyConfig.ProxyCerts != nil { + client.Transport.(*http.Transport).TLSClientConfig.RootCAs = proxyConfig.ProxyCerts } client.Transport = tpt } diff --git a/pkg/compose/v1/config.go b/pkg/compose/v1/config.go index b11e410..0293a50 100644 --- a/pkg/compose/v1/config.go +++ b/pkg/compose/v1/config.go @@ -22,6 +22,7 @@ type ( ReadTimeout time.Duration SkopeoSupport bool UpdateDBPath string + Proxy compose.ProxyProvider } ConfigOpt func(*ConfigOpts) ) @@ -65,6 +66,12 @@ func WithConnectTimeout(timeout time.Duration) ConfigOpt { } } +func WithProxy(proxy compose.ProxyProvider) ConfigOpt { + return func(opts *ConfigOpts) { + opts.Proxy = proxy + } +} + func NewDefaultConfig(options ...ConfigOpt) (*compose.Config, error) { opts := &ConfigOpts{ ConnectTimeout: DefaultConnectTimeout, @@ -113,27 +120,13 @@ func NewDefaultConfig(options ...ConfigOpt) (*compose.Config, error) { return nil, fmt.Errorf("failed to get file system stat; path: %s, err: %s", opts.StoreRoot, err.Error()) } - var proxyURL *url.URL - var proxyCerts *x509.CertPool - - proxyEnv := os.Getenv("COMPOSE_APPS_PROXY") - if len(proxyEnv) > 0 { - proxyURL, err = url.Parse(proxyEnv) - if err != nil { - return nil, fmt.Errorf("invalid COMPOSE_APPS_PROXY: %s: %w", proxyEnv, err) - } - - proxyCa := os.Getenv("COMPOSE_APPS_PROXY_CA") - if len(proxyCa) > 0 { - proxyCerts = x509.NewCertPool() - - pemData, err := os.ReadFile(proxyCa) - if err != nil { - return nil, fmt.Errorf("unable to read COMPOSE_APPS_PROXY_CA: %w", err) - } else if ok := proxyCerts.AppendCertsFromPEM(pemData); !ok { - return nil, fmt.Errorf("failed to set COMPOSE_APPS_PROXY_CA: %w", err) - } - } + // Set proxy provider specified via configuration options + proxy := opts.Proxy + // Override or set proxy provider if specified via environment variable + if proxyFromEnv, err := getProxyProviderFromEnvIfSet(); err != nil { + return nil, err + } else if proxyFromEnv != nil { + proxy = proxyFromEnv } // Load docker config @@ -157,7 +150,39 @@ func NewDefaultConfig(options ...ConfigOpt) (*compose.Config, error) { }, BlockSize: s.BlockSize, DBFilePath: opts.UpdateDBPath, - ProxyURL: proxyURL, - ProxyCerts: proxyCerts, + Proxy: proxy, + }, nil +} + +func getProxyProviderFromEnvIfSet() (compose.ProxyProvider, error) { + proxyEnv := os.Getenv("COMPOSE_APPS_PROXY") + if len(proxyEnv) == 0 { + return nil, nil + } + + var proxyURL *url.URL + var proxyCerts *x509.CertPool + var err error + + if proxyURL, err = url.Parse(proxyEnv); err != nil { + return nil, fmt.Errorf("invalid COMPOSE_APPS_PROXY URL: %s: %w", proxyEnv, err) + } + proxyCa := os.Getenv("COMPOSE_APPS_PROXY_CA") + if len(proxyCa) > 0 { + proxyCerts = x509.NewCertPool() + if b, err := os.ReadFile(proxyCa); err == nil { + if ok := proxyCerts.AppendCertsFromPEM(b); !ok { + return nil, fmt.Errorf("failed to parse COMPOSE_APPS_PROXY_CA: %s", proxyCa) + } + } else { + return nil, fmt.Errorf("unable to read COMPOSE_APPS_PROXY_CA: %w", err) + } + } + + return func() *compose.ProxyConfig { + return &compose.ProxyConfig{ + ProxyURL: proxyURL, + ProxyCerts: proxyCerts, + } }, nil }