diff --git a/README.md b/README.md index 60931919..d3c2e600 100644 --- a/README.md +++ b/README.md @@ -808,6 +808,24 @@ See [advanced remote configuration](#advanced-remote-configuration) for more det +
TOFUENV_REMOTE_PASSWORD
+ +String (Default: "") + +Could be used with TOFUENV_REMOTE_USER to specify HTTP basic auth when same credential are used with TOFUENV_REMOTE and TOFUENV_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ + +
TOFUENV_REMOTE_USER
+ +String (Default: "") + +Could be used with TOFUENV_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TOFUENV_REMOTE and TOFUENV_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ +
TOFUENV_ROOT
Same as TENV_ROOT (compatibility with [tofuenv](https://github.com/tofuutils/tofuenv)). @@ -817,10 +835,10 @@ Same as TENV_ROOT (compatibility with [tofuenv](https://github.com/tofuutils/tof
TOFUENV_URL_TEMPLATE
-String (Default: "https://github.com/opentofu/opentofu/releases/download/v{{ .Version }}/{{ .Artifact }}") - - +String (Default: `https://github.com/opentofu/opentofu/releases/download/v{{ .Version }}/{{ .Artifact }}`) +Used when TOFUENV_INSTALL_MODE is "mirror" (see [TofuDL mirror specification](https://github.com/opentofu/tofudl/blob/mirror-spec/MIRROR-SPECIFICATION.md)). +
@@ -959,6 +977,24 @@ See [advanced remote configuration](#advanced-remote-configuration) for more det
+
TFENV_REMOTE_PASSWORD
+ +String (Default: "") + +Could be used with TFENV_REMOTE_USER to specify HTTP basic auth when same credential are used with TFENV_REMOTE and TFENV_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ + +
TFENV_REMOTE_USER
+ +String (Default: "") + +Could be used with TFENV_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TFENV_REMOTE and TFENV_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ +
TFENV_ROOT
Same as TENV_ROOT (compatibility with [tfenv](https://github.com/tfutils/tfenv)). @@ -1065,6 +1101,25 @@ See [advanced remote configuration](#advanced-remote-configuration) for more det
+ +
TG_REMOTE_PASSWORD
+ +String (Default: "") + +Could be used with TG_REMOTE_USER to specify HTTP basic auth when same credential are used with TG_REMOTE and TG_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ + +
TG_REMOTE_USER
+ +String (Default: "") + +Could be used with TG_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with TG_REMOTE and TG_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ +
TG_DEFAULT_CONSTRAINT
String (Default: "") @@ -1158,6 +1213,25 @@ See [advanced remote configuration](#advanced-remote-configuration) for more det
+ +
ATMOS_REMOTE_PASSWORD
+ +String (Default: "") + +Could be used with ATMOS_REMOTE_USER to specify HTTP basic auth when same credential are used with ATMOS_REMOTE and ATMOS_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ + +
ATMOS_REMOTE_USER
+ +String (Default: "") + +Could be used with ATMOS_REMOTE_PASSWORD to specify HTTP basic auth when same credential are used with ATMOS_REMOTE and ATMOS_LIST_URL (instead of `https://user:password@host.org` URL format). + +
+ +
ATMOS_DEFAULT_CONSTRAINT
String (Default: "") diff --git a/config/config.go b/config/config.go index 0f46b465..c7c56072 100644 --- a/config/config.go +++ b/config/config.go @@ -47,7 +47,9 @@ const ( listURLEnvName = "LIST_URL" logEnvName = "LOG" quietEnvName = "QUIET" + remotePassEnvName = "REMOTE_PASSWORD" remoteURLEnvName = "REMOTE" + remoteUserEnvName = "REMOTE_USER" rootPathEnvName = "ROOT" tokenEnvName = "GITHUB_TOKEN" //nolint version = "VERSION" @@ -58,7 +60,9 @@ const ( atmosInstallModeEnvName = atmosPrefix + installModeEnvName atmosListModeEnvName = atmosPrefix + listModeEnvName atmosListURLEnvName = atmosPrefix + listURLEnvName + AtmosRemotePassEnvName = atmosPrefix + remotePassEnvName AtmosRemoteURLEnvName = atmosPrefix + remoteURLEnvName + AtmosRemoteUserEnvName = atmosPrefix + remoteUserEnvName AtmosVersionEnvName = atmosPrefix + version tenvPrefix = "TENV_" @@ -82,7 +86,9 @@ const ( tfInstallModeEnvName = tfenvPrefix + installModeEnvName tfListModeEnvName = tfenvPrefix + listModeEnvName tfListURLEnvName = tfenvPrefix + listURLEnvName + TfRemotePassEnvName = tfenvPrefix + remotePassEnvName TfRemoteURLEnvName = tfenvPrefix + remoteURLEnvName + TfRemoteUserEnvName = tfenvPrefix + remoteUserEnvName tfRootPathEnvName = tfenvPrefix + rootPathEnvName TfVersionEnvName = tfenvTerraformPrefix + version @@ -92,7 +98,9 @@ const ( tgInstallModeEnvName = tgPrefix + installModeEnvName tgListModeEnvName = tgPrefix + listModeEnvName tgListURLEnvName = tgPrefix + listURLEnvName + TgRemotePassEnvName = tgPrefix + remotePassEnvName TgRemoteURLEnvName = tgPrefix + remoteURLEnvName + TgRemoteUserEnvName = tgPrefix + remoteUserEnvName TgVersionEnvName = tgPrefix + version tofuenvPrefix = "TOFUENV_" @@ -106,7 +114,9 @@ const ( tofuListModeEnvName = tofuenvPrefix + listModeEnvName tofuListURLEnvName = tofuenvPrefix + listURLEnvName tofuOpenTofuPGPKeyEnvName = tofuenvPrefix + "OPENTOFU_PGP_KEY" + TofuRemotePassEnvName = tofuenvPrefix + remotePassEnvName TofuRemoteURLEnvName = tofuenvPrefix + remoteURLEnvName + TofuRemoteUserEnvName = tofuenvPrefix + remoteUserEnvName tofuRootPathEnvName = tofuenvPrefix + rootPathEnvName tofuTokenEnvName = tofuenvPrefix + tokenEnvName TofuURLTemplateEnvName = tofuenvPrefix + "URL_TEMPLATE" diff --git a/config/remote.go b/config/remote.go index 02dc6a9a..0c0b7055 100644 --- a/config/remote.go +++ b/config/remote.go @@ -22,6 +22,8 @@ import ( "errors" "os" "strings" + + "github.com/tofuutils/tenv/v3/pkg/download" ) const ( @@ -135,3 +137,12 @@ func MapGetDefault(m map[string]string, key string, defaultValue string) string return defaultValue } + +func GetBasicAuthOption(userEnvName string, passEnvName string) []download.RequestOption { + username, password := os.Getenv(userEnvName), os.Getenv(passEnvName) + if username == "" || password == "" { + return nil + } + + return []download.RequestOption{download.WithBasicAuth(username, password)} +} diff --git a/go.mod b/go.mod index 45984faf..8f68a4f5 100644 --- a/go.mod +++ b/go.mod @@ -52,11 +52,11 @@ require ( github.com/sahilm/fuzzy v0.1.1 // indirect github.com/stretchr/testify v1.8.4 // indirect github.com/xo/terminfo v0.0.0-20220910002029-abceb7e1c41e // indirect - golang.org/x/crypto v0.25.0 // indirect - golang.org/x/mod v0.19.0 // indirect - golang.org/x/net v0.27.0 // indirect - golang.org/x/sync v0.7.0 // indirect - golang.org/x/sys v0.22.0 // indirect - golang.org/x/text v0.16.0 // indirect - golang.org/x/tools v0.23.0 // indirect + golang.org/x/crypto v0.26.0 // indirect + golang.org/x/mod v0.20.0 // indirect + golang.org/x/net v0.28.0 // indirect + golang.org/x/sync v0.8.0 // indirect + golang.org/x/sys v0.24.0 // indirect + golang.org/x/text v0.17.0 // indirect + golang.org/x/tools v0.24.0 // indirect ) diff --git a/go.sum b/go.sum index 6684ea8d..c9aa7128 100644 --- a/go.sum +++ b/go.sum @@ -119,14 +119,14 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.3.1-0.20221117191849-2c476679df9a/go.mod h1:hebNnKkNXi2UzZN1eVRvBB7co0a+JxK6XbPiWVs/3J4= golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU= -golang.org/x/crypto v0.25.0 h1:ypSNr+bnYL2YhwoMt2zPxHFmbAN1KZs/njMG3hxUp30= -golang.org/x/crypto v0.25.0/go.mod h1:T+wALwcMOSE0kXgUAnPAHqTLW+XHgcELELW8VaDgm/M= +golang.org/x/crypto v0.26.0 h1:RrRspgV4mU+YwB4FYnuBoKsUapNIL5cohGAmSH3azsw= +golang.org/x/crypto v0.26.0/go.mod h1:GY7jblb9wI+FOo5y8/S2oY4zWP07AkOJ4+jxCqdqn54= golang.org/x/exp v0.0.0-20231006140011-7918f672742d h1:jtJma62tbqLibJ5sFQz8bKtEM8rJBtfilJ2qTU199MI= golang.org/x/exp v0.0.0-20231006140011-7918f672742d/go.mod h1:ldy0pHrwJyGW56pPQzzkH36rKxoZW1tw7ZJpeKx+hdo= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4= golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs= -golang.org/x/mod v0.19.0 h1:fEdghXQSo20giMthA7cd28ZC+jts4amQ3YMXiP5oMQ8= -golang.org/x/mod v0.19.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= +golang.org/x/mod v0.20.0 h1:utOm6MM3R3dnawAiJgn0y+xvuYRsm1RKM/4giyfDgV0= +golang.org/x/mod v0.20.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= @@ -134,13 +134,13 @@ golang.org/x/net v0.2.0/go.mod h1:KqCZLdyyvdV855qA2rE3GC2aiw5xGR5TEjj8smXukLY= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc= golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns= -golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys= -golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE= +golang.org/x/net v0.28.0 h1:a9JDOJc5GMUJ0+UDqmLT86WiEy7iWyIhz8gz8E4e5hE= +golang.org/x/net v0.28.0/go.mod h1:yqtgsTWOOnlGLG9GFRrK3++bGOUEkNBoHZc8MEDWPNg= golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= -golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M= -golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= +golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ= +golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -158,8 +158,8 @@ golang.org/x/sys v0.3.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI= -golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.24.0 h1:Twjiwq9dn6R1fQcyiK+wQyHWfaz/BJB+YIpzU/Cv3Xg= +golang.org/x/sys v0.24.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.2.0/go.mod h1:TVmDHMZPmdnySmBfhjOoOdhjzdE1h4u1VwSiw2l1Nuc= @@ -173,14 +173,14 @@ golang.org/x/text v0.4.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= -golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4= -golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI= +golang.org/x/text v0.17.0 h1:XtiM5bkSOt+ewxlOE/aE/AKEHibwj/6gvWMl9Rsh0Qc= +golang.org/x/text v0.17.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU= -golang.org/x/tools v0.23.0 h1:SGsXPZ+2l4JsgaCKkx+FQ9YZ5XEtA1GZYuoDjenLjvg= -golang.org/x/tools v0.23.0/go.mod h1:pnu6ufv6vQkll6szChhK3C3L/ruaIv5eBeztNG8wtsI= +golang.org/x/tools v0.24.0 h1:J1shsA93PJUEVaUSaay7UXAyE8aimq3GW0pjlolpa24= +golang.org/x/tools v0.24.0/go.mod h1:YhNqVBIfWHdzvTLs0d8LCuMhkKUgSUKldakyV7W/WDQ= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/download/download.go b/pkg/download/download.go index 0f9b62ff..37c74b61 100644 --- a/pkg/download/download.go +++ b/pkg/download/download.go @@ -19,11 +19,14 @@ package download import ( + "encoding/json" "io" "net/http" "net/url" ) +type RequestOption = func(*http.Request) *http.Request + func ApplyUrlTranformer(urlTransformer func(string) (string, error), baseURLs ...string) ([]string, error) { transformedURLs := make([]string, 0, len(baseURLs)) for _, baseURL := range baseURLs { @@ -38,10 +41,19 @@ func ApplyUrlTranformer(urlTransformer func(string) (string, error), baseURLs .. return transformedURLs, nil } -func Bytes(url string, display func(string)) ([]byte, error) { +func Bytes(url string, display func(string), requestOptions ...RequestOption) ([]byte, error) { display("Downloading " + url) - response, err := http.Get(url) //nolint + request, err := http.NewRequest(http.MethodGet, url, http.NoBody) + if err != nil { + return nil, err + } + + for _, option := range requestOptions { + request = option(request) + } + + response, err := http.DefaultClient.Do(request) if err != nil { return nil, err } @@ -50,6 +62,20 @@ func Bytes(url string, display func(string)) ([]byte, error) { return io.ReadAll(response.Body) } +func JSON(url string, display func(string), requestOptions ...RequestOption) (any, error) { + data, err := Bytes(url, display, requestOptions...) + if err != nil { + return nil, err + } + + var value any + err = json.Unmarshal(data, &value) + + return value, err +} + +func NoDisplay(string) {} + func UrlTranformer(rewriteRule []string) func(string) (string, error) { if len(rewriteRule) < 2 { return noTransform @@ -71,6 +97,14 @@ func UrlTranformer(rewriteRule []string) func(string) (string, error) { } } +func WithBasicAuth(username string, password string) RequestOption { + return func(r *http.Request) *http.Request { + r.SetBasicAuth(username, password) + + return r + } +} + func noTransform(value string) (string, error) { return value, nil } diff --git a/pkg/github/github.go b/pkg/github/github.go index e372c6bc..6c532d07 100644 --- a/pkg/github/github.go +++ b/pkg/github/github.go @@ -19,14 +19,13 @@ package github import ( - "encoding/json" "errors" - "io" "net/http" "net/url" "strconv" "github.com/tofuutils/tenv/v3/pkg/apimsg" + "github.com/tofuutils/tenv/v3/pkg/download" versionfinder "github.com/tofuutils/tenv/v3/versionmanager/semantic/finder" ) @@ -113,32 +112,15 @@ func ListReleases(githubReleaseURL string, githubToken string) ([]string, error) } func apiGetRequest(callURL string, authorizationHeader string) (any, error) { - request, err := http.NewRequest(http.MethodGet, callURL, nil) - if err != nil { - return nil, err - } - - request.Header.Set("Accept", "application/vnd.github+json") - if authorizationHeader != "" { - request.Header.Set("Authorization", authorizationHeader) - } - request.Header.Set("X-GitHub-Api-Version", "2022-11-28") - - response, err := http.DefaultClient.Do(request) - if err != nil { - return nil, err - } - defer response.Body.Close() - - data, err := io.ReadAll(response.Body) - if err != nil { - return nil, err - } - - var value any - err = json.Unmarshal(data, &value) + return download.JSON(callURL, download.NoDisplay, func(request *http.Request) *http.Request { + request.Header.Set("Accept", "application/vnd.github+json") + if authorizationHeader != "" { + request.Header.Set("Authorization", authorizationHeader) + } + request.Header.Set("X-GitHub-Api-Version", "2022-11-28") - return value, err + return request + }) } func buildAuthorizationHeader(token string) string { diff --git a/pkg/htmlquery/html.go b/pkg/htmlquery/html.go index 47571871..79c9ff6a 100644 --- a/pkg/htmlquery/html.go +++ b/pkg/htmlquery/html.go @@ -19,21 +19,21 @@ package htmlquery import ( - "io" - "net/http" + "bytes" "strings" "github.com/PuerkitoBio/goquery" + + "github.com/tofuutils/tenv/v3/pkg/download" ) -func Request(callURL string, selector string, extractor func(*goquery.Selection) string) ([]string, error) { - response, err := http.Get(callURL) +func Request(callURL string, selector string, extractor func(*goquery.Selection) string, ro ...download.RequestOption) ([]string, error) { + data, err := download.Bytes(callURL, download.NoDisplay, ro...) if err != nil { return nil, err } - defer response.Body.Close() - return extractList(response.Body, selector, extractor) + return extractList(data, selector, extractor) } func SelectionExtractor(part string) func(*goquery.Selection) string { @@ -48,8 +48,9 @@ func SelectionExtractor(part string) func(*goquery.Selection) string { } } -func extractList(reader io.Reader, selector string, extractor func(*goquery.Selection) string) ([]string, error) { - doc, err := goquery.NewDocumentFromReader(reader) +func extractList(data []byte, selector string, extractor func(*goquery.Selection) string) ([]string, error) { + dataReader := bytes.NewReader(data) + doc, err := goquery.NewDocumentFromReader(dataReader) if err != nil { return nil, err } diff --git a/pkg/htmlquery/html_test.go b/pkg/htmlquery/html_test.go index 606eac37..8f172de3 100644 --- a/pkg/htmlquery/html_test.go +++ b/pkg/htmlquery/html_test.go @@ -19,7 +19,6 @@ package htmlquery import ( - "bytes" _ "embed" "slices" "testing" @@ -31,10 +30,8 @@ var artifactoryData []byte func TestExtractAttr(t *testing.T) { t.Parallel() - artifactoryReader := bytes.NewReader(artifactoryData) - extractor := SelectionExtractor("style") - extracted, err := extractList(artifactoryReader, "address", extractor) + extracted, err := extractList(artifactoryData, "address", extractor) if err != nil { t.Fatal("Unexpected extract error : ", err) } @@ -47,10 +44,8 @@ func TestExtractAttr(t *testing.T) { func TestExtractText(t *testing.T) { t.Parallel() - artifactoryReader := bytes.NewReader(artifactoryData) - extractor := SelectionExtractor("#text") - extracted, err := extractList(artifactoryReader, "address", extractor) + extracted, err := extractList(artifactoryData, "address", extractor) if err != nil { t.Fatal("Unexpected extract error : ", err) } @@ -63,9 +58,7 @@ func TestExtractText(t *testing.T) { func TestExtractTexts(t *testing.T) { t.Parallel() - artifactoryReader := bytes.NewReader(artifactoryData) - - extracted, err := extractList(artifactoryReader, "a", selectionTextExtractor) + extracted, err := extractList(artifactoryData, "a", selectionTextExtractor) if err != nil { t.Fatal("Unexpected extract error : ", err) } diff --git a/versionmanager/retriever/api/api.go b/versionmanager/retriever/api/api.go deleted file mode 100644 index 2ae7770e..00000000 --- a/versionmanager/retriever/api/api.go +++ /dev/null @@ -1,43 +0,0 @@ -/* - * - * Copyright 2024 tofuutils authors. - * - * 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 api - -import ( - "encoding/json" - "io" - "net/http" -) - -func GetRequest(callURL string) (any, error) { - response, err := http.Get(callURL) //nolint - if err != nil { - return nil, err - } - defer response.Body.Close() - - data, err := io.ReadAll(response.Body) - if err != nil { - return nil, err - } - - var value any - err = json.Unmarshal(data, &value) - - return value, err -} diff --git a/versionmanager/retriever/atmos/atmosretriever.go b/versionmanager/retriever/atmos/atmosretriever.go index cee3b859..40e5137f 100644 --- a/versionmanager/retriever/atmos/atmosretriever.go +++ b/versionmanager/retriever/atmos/atmosretriever.go @@ -94,12 +94,13 @@ func (r AtmosRetriever) InstallRelease(versionStr string, targetPath string) err return err } - data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display) + ro := config.GetBasicAuthOption(config.AtmosRemoteUserEnvName, config.AtmosRemotePassEnvName) + data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display, ro...) if err != nil { return err } - dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display) + dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display, ro...) if err != nil { return err } @@ -122,6 +123,8 @@ func (r AtmosRetriever) ListReleases() ([]string, error) { return nil, err } + ro := config.GetBasicAuthOption(config.AtmosRemoteUserEnvName, config.AtmosRemotePassEnvName) + listURL := r.conf.Atmos.GetListURL() switch r.conf.Atmos.GetListMode() { case config.ListModeHTML: @@ -132,7 +135,7 @@ func (r AtmosRetriever) ListReleases() ([]string, error) { r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + baseURL) - return htmlretriever.ListReleases(baseURL, r.conf.Atmos.Data) + return htmlretriever.ListReleases(baseURL, r.conf.Atmos.Data, ro) case config.ModeAPI: r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + listURL) diff --git a/versionmanager/retriever/html/htmlretriever.go b/versionmanager/retriever/html/htmlretriever.go index c777d664..4bc71b51 100644 --- a/versionmanager/retriever/html/htmlretriever.go +++ b/versionmanager/retriever/html/htmlretriever.go @@ -37,12 +37,12 @@ func BuildAssetURLs(baseAssetURL string, assetNames ...string) ([]string, error) return download.ApplyUrlTranformer(joinTransformer, assetNames...) } -func ListReleases(baseURL string, remoteConf map[string]string) ([]string, error) { +func ListReleases(baseURL string, remoteConf map[string]string, ro []download.RequestOption) ([]string, error) { selector := config.MapGetDefault(remoteConf, "selector", "a") extractor := htmlquery.SelectionExtractor(config.MapGetDefault(remoteConf, "part", "href")) versionExtractor := func(s *goquery.Selection) string { return versionfinder.Find(extractor(s)) } - return htmlquery.Request(baseURL, selector, versionExtractor) + return htmlquery.Request(baseURL, selector, versionExtractor, ro...) } diff --git a/versionmanager/retriever/terraform/terraformretriever.go b/versionmanager/retriever/terraform/terraformretriever.go index fc25ac31..4b4984a4 100644 --- a/versionmanager/retriever/terraform/terraformretriever.go +++ b/versionmanager/retriever/terraform/terraformretriever.go @@ -35,7 +35,6 @@ import ( "github.com/tofuutils/tenv/v3/pkg/pathfilter" "github.com/tofuutils/tenv/v3/pkg/winbin" "github.com/tofuutils/tenv/v3/pkg/zip" - "github.com/tofuutils/tenv/v3/versionmanager/retriever/api" htmlretriever "github.com/tofuutils/tenv/v3/versionmanager/retriever/html" releaseapi "github.com/tofuutils/tenv/v3/versionmanager/retriever/terraform/api" ) @@ -71,6 +70,8 @@ func (r TerraformRetriever) InstallRelease(version string, targetPath string) er return err } + ro := config.GetBasicAuthOption(config.TfRemoteUserEnvName, config.TfRemotePassEnvName) + var fileName, shaFileName, shaSigFileName, downloadURL, downloadSumsURL, downloadSumsSigURL string switch r.conf.Tf.GetInstallMode() { case config.InstallModeDirect: @@ -93,7 +94,7 @@ func (r TerraformRetriever) InstallRelease(version string, targetPath string) er r.conf.Displayer.Display(apimsg.MsgFetchRelease + versionUrl) - value, err := api.GetRequest(versionUrl) + value, err := download.JSON(versionUrl, download.NoDisplay, ro...) if err != nil { return err } @@ -123,12 +124,12 @@ func (r TerraformRetriever) InstallRelease(version string, targetPath string) er return err } - data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display) + data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display, ro...) if err != nil { return err } - if err = r.checkSumAndSig(fileName, data, assetURLs[1], assetURLs[2]); err != nil { + if err = r.checkSumAndSig(fileName, data, assetURLs[1], assetURLs[2], ro); err != nil { return err } @@ -146,11 +147,13 @@ func (r TerraformRetriever) ListReleases() ([]string, error) { return nil, err } + ro := config.GetBasicAuthOption(config.TfRemoteUserEnvName, config.TfRemotePassEnvName) + switch r.conf.Tf.GetListMode() { case config.ListModeHTML: r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + baseURL) - return htmlretriever.ListReleases(baseURL, r.conf.Tf.Data) + return htmlretriever.ListReleases(baseURL, r.conf.Tf.Data, ro) case config.ModeAPI: releasesURL, err := url.JoinPath(baseURL, indexJson) //nolint if err != nil { @@ -159,7 +162,7 @@ func (r TerraformRetriever) ListReleases() ([]string, error) { r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + releasesURL) - value, err := api.GetRequest(releasesURL) + value, err := download.JSON(releasesURL, download.NoDisplay, ro...) if err != nil { return nil, err } @@ -170,8 +173,8 @@ func (r TerraformRetriever) ListReleases() ([]string, error) { } } -func (r TerraformRetriever) checkSumAndSig(fileName string, data []byte, downloadSumsURL string, downloadSumsSigURL string) error { - dataSums, err := download.Bytes(downloadSumsURL, r.conf.Displayer.Display) +func (r TerraformRetriever) checkSumAndSig(fileName string, data []byte, downloadSumsURL string, downloadSumsSigURL string, ro []download.RequestOption) error { + dataSums, err := download.Bytes(downloadSumsURL, r.conf.Displayer.Display, ro...) if err != nil { return err } @@ -184,7 +187,7 @@ func (r TerraformRetriever) checkSumAndSig(fileName string, data []byte, downloa return nil } - dataSumsSig, err := download.Bytes(downloadSumsSigURL, r.conf.Displayer.Display) + dataSumsSig, err := download.Bytes(downloadSumsSigURL, r.conf.Displayer.Display, ro...) if err != nil { return err } diff --git a/versionmanager/retriever/terragrunt/terragruntretriever.go b/versionmanager/retriever/terragrunt/terragruntretriever.go index 3ce6c28e..9f876ad7 100644 --- a/versionmanager/retriever/terragrunt/terragruntretriever.go +++ b/versionmanager/retriever/terragrunt/terragruntretriever.go @@ -91,12 +91,13 @@ func (r TerragruntRetriever) InstallRelease(versionStr string, targetPath string return err } - data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display) + ro := config.GetBasicAuthOption(config.TgRemoteUserEnvName, config.TgRemotePassEnvName) + data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display, ro...) if err != nil { return err } - dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display) + dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display, ro...) if err != nil { return err } @@ -119,6 +120,8 @@ func (r TerragruntRetriever) ListReleases() ([]string, error) { return nil, err } + ro := config.GetBasicAuthOption(config.TgRemoteUserEnvName, config.TgRemotePassEnvName) + listURL := r.conf.Tg.GetListURL() switch r.conf.Tg.GetListMode() { case config.ListModeHTML: @@ -129,7 +132,7 @@ func (r TerragruntRetriever) ListReleases() ([]string, error) { r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + baseURL) - return htmlretriever.ListReleases(baseURL, r.conf.Tg.Data) + return htmlretriever.ListReleases(baseURL, r.conf.Tg.Data, ro) case config.ModeAPI: r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + listURL) diff --git a/versionmanager/retriever/tofu/tofuretriever.go b/versionmanager/retriever/tofu/tofuretriever.go index 2e37f9c8..68fbc987 100644 --- a/versionmanager/retriever/tofu/tofuretriever.go +++ b/versionmanager/retriever/tofu/tofuretriever.go @@ -38,7 +38,6 @@ import ( "github.com/tofuutils/tenv/v3/pkg/pathfilter" "github.com/tofuutils/tenv/v3/pkg/winbin" "github.com/tofuutils/tenv/v3/pkg/zip" - "github.com/tofuutils/tenv/v3/versionmanager/retriever/api" htmlretriever "github.com/tofuutils/tenv/v3/versionmanager/retriever/html" tofudlmirroring "github.com/tofuutils/tenv/v3/versionmanager/retriever/tofu/dl" ) @@ -130,12 +129,13 @@ func (r TofuRetriever) InstallRelease(versionStr string, targetPath string) erro return err } - data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display) + ro := config.GetBasicAuthOption(config.TofuRemoteUserEnvName, config.TofuRemotePassEnvName) + data, err := download.Bytes(assetURLs[0], r.conf.Displayer.Display, ro...) if err != nil { return err } - if err = r.checkSumAndSig(v, stable, data, assetNames[0], assetURLs); err != nil { + if err = r.checkSumAndSig(v, stable, data, assetNames[0], assetURLs, ro); err != nil { return err } @@ -148,6 +148,8 @@ func (r TofuRetriever) ListReleases() ([]string, error) { return nil, err } + ro := config.GetBasicAuthOption(config.TofuRemoteUserEnvName, config.TofuRemotePassEnvName) + listURL := r.conf.Tofu.GetListURL() switch r.conf.Tofu.GetListMode() { case config.ListModeHTML: @@ -158,7 +160,7 @@ func (r TofuRetriever) ListReleases() ([]string, error) { r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + baseURL) - return htmlretriever.ListReleases(baseURL, r.conf.Tofu.Data) + return htmlretriever.ListReleases(baseURL, r.conf.Tofu.Data, ro) case config.ModeAPI: r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + listURL) @@ -170,7 +172,7 @@ func (r TofuRetriever) ListReleases() ([]string, error) { r.conf.Displayer.Display(apimsg.MsgFetchAllReleases + listURL) - value, err := api.GetRequest(listURL) + value, err := download.JSON(listURL, download.NoDisplay, ro...) if err != nil { return nil, err } @@ -181,8 +183,8 @@ func (r TofuRetriever) ListReleases() ([]string, error) { } } -func (r TofuRetriever) checkSumAndSig(version *version.Version, stable bool, data []byte, fileName string, assetURLs []string) error { - dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display) +func (r TofuRetriever) checkSumAndSig(version *version.Version, stable bool, data []byte, fileName string, assetURLs []string, ro []download.RequestOption) error { + dataSums, err := download.Bytes(assetURLs[1], r.conf.Displayer.Display, ro...) if err != nil { return err } @@ -195,12 +197,12 @@ func (r TofuRetriever) checkSumAndSig(version *version.Version, stable bool, dat return nil } - dataSumsSig, err := download.Bytes(assetURLs[3], r.conf.Displayer.Display) + dataSumsSig, err := download.Bytes(assetURLs[3], r.conf.Displayer.Display, ro...) if err != nil { return err } - dataSumsCert, err := download.Bytes(assetURLs[2], r.conf.Displayer.Display) + dataSumsCert, err := download.Bytes(assetURLs[2], r.conf.Displayer.Display, ro...) if err != nil { return err } @@ -219,7 +221,7 @@ func (r TofuRetriever) checkSumAndSig(version *version.Version, stable bool, dat r.conf.Displayer.Display("cosign executable not found, fallback to pgp check") - dataSumsSig, err = download.Bytes(assetURLs[4], r.conf.Displayer.Display) + dataSumsSig, err = download.Bytes(assetURLs[4], r.conf.Displayer.Display, ro...) if err != nil { return err }