diff --git a/cmd/power-control/service.go b/cmd/power-control/service.go index 2d46331e..dfca138f 100644 --- a/cmd/power-control/service.go +++ b/cmd/power-control/service.go @@ -12,7 +12,6 @@ import ( base "github.com/Cray-HPE/hms-base/v2" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/sirupsen/logrus" "golang.org/x/oauth2" "golang.org/x/oauth2/clientcredentials" @@ -23,6 +22,7 @@ import ( "github.com/OpenCHAMI/power-control/v2/internal/hsm" "github.com/OpenCHAMI/power-control/v2/internal/logger" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) // Default Port to use @@ -59,7 +59,7 @@ var ( restSrv *http.Server = nil waitGroup sync.WaitGroup rfClient, svcClient *hms_certs.HTTPClientPair - TLOC_rf, TLOC_svc trsapi.TrsAPI + TLOC_rf, TLOC_svc taskrun.TrsAPI caURI string rfClientLock *sync.RWMutex = &sync.RWMutex{} serviceName string @@ -148,7 +148,7 @@ func runPCS(pcs *pcsConfig, etcd *etcdConfig, postgres *storage.PostgresConfig, } } - var BaseTRSTask trsapi.HttpTask + var BaseTRSTask taskrun.HttpTask BaseTRSTask.ServiceName = serviceName BaseTRSTask.Timeout = time.Duration(baseTrsTaskTimeout) * time.Second BaseTRSTask.Request, _ = http.NewRequest("GET", "", nil) @@ -171,25 +171,12 @@ func runPCS(pcs *pcsConfig, etcd *etcdConfig, postgres *storage.PostgresConfig, trsLogger.SetLevel(logger.Log.GetLevel()) trsLogger.SetReportCaller(true) - envstr = os.Getenv("TRS_IMPLEMENTATION") - - if envstr == "REMOTE" { - workerSec := &trsapi.TRSHTTPRemote{} - workerSec.Logger = trsLogger - workerInsec := &trsapi.TRSHTTPRemote{} - workerInsec.Logger = trsLogger - TLOC_rf = workerSec - TLOC_svc = workerInsec - logger.Log.Infof("Using TRS_IMPLEMENTATION: REMOTE") - } else { - workerSec := &trsapi.TRSHTTPLocal{} - workerSec.Logger = trsLogger - workerInsec := &trsapi.TRSHTTPLocal{} - workerInsec.Logger = trsLogger - TLOC_rf = workerSec - TLOC_svc = workerInsec - logger.Log.Infof("Using TRS_IMPLEMENTATION: LOCAL") - } + workerSec := &taskrun.TRSHTTPLocal{} + workerSec.Logger = trsLogger + workerInsec := &taskrun.TRSHTTPLocal{} + workerInsec.Logger = trsLogger + TLOC_rf = workerSec + TLOC_svc = workerInsec //Set up TRS TLOCs and HTTP clients, all insecure to start with @@ -448,7 +435,7 @@ func runPCS(pcs *pcsConfig, etcd *etcdConfig, postgres *storage.PostgresConfig, logger.Log.Infof("Locking RF operations...") rfClientLock.Lock() //waits for all RW locks to release tchain := hms_certs.NewlineToTuple(caChain) - secInfo := trsapi.TRSHTTPLocalSecurity{CACertBundleData: tchain} + secInfo := taskrun.TRSHTTPLocalSecurity{CACertBundleData: tchain} err = TLOC_rf.SetSecurity(secInfo) if err != nil { logger.Log.Errorf("Error setting TLOC security info: %v, retrying...", diff --git a/go.mod b/go.mod index 608753ab..01deba26 100644 --- a/go.mod +++ b/go.mod @@ -10,7 +10,6 @@ require ( github.com/Cray-HPE/hms-compcredentials v1.15.0 github.com/Cray-HPE/hms-hmetcd v1.13.0 github.com/Cray-HPE/hms-securestorage v1.17.0 - github.com/Cray-HPE/hms-trs-app-api/v3 v3.0.5 github.com/Cray-HPE/hms-xname v1.4.0 github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18 github.com/OpenCHAMI/smd/v2 v2.19.1 @@ -18,6 +17,7 @@ require ( github.com/golang-migrate/migrate/v4 v4.18.3 github.com/google/go-cmp v0.7.0 github.com/google/uuid v1.6.0 + github.com/hashicorp/go-retryablehttp v0.7.7 github.com/jmoiron/sqlx v1.4.0 github.com/lestrrat-go/jwx v1.2.30 github.com/lib/pq v1.10.9 @@ -38,10 +38,8 @@ require ( require ( dario.cat/mergo v1.0.1 // indirect github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect - github.com/Cray-HPE/hms-trs-kafkalib/v2 v2.0.2 // indirect github.com/Microsoft/go-winio v0.6.2 // indirect github.com/cenkalti/backoff/v4 v4.3.0 // indirect - github.com/confluentinc/confluent-kafka-go/v2 v2.10.0 // indirect github.com/containerd/log v0.1.0 // indirect github.com/containerd/platforms v0.2.1 // indirect github.com/coreos/go-semver v0.3.1 // indirect @@ -66,7 +64,6 @@ require ( github.com/hashicorp/errwrap v1.1.0 // indirect github.com/hashicorp/go-cleanhttp v0.5.2 // indirect github.com/hashicorp/go-multierror v1.1.1 // indirect - github.com/hashicorp/go-retryablehttp v0.7.7 // indirect github.com/hashicorp/go-rootcerts v1.0.2 // indirect github.com/hashicorp/go-secure-stdlib/parseutil v0.2.0 // indirect github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 // indirect @@ -112,6 +109,7 @@ require ( go.opentelemetry.io/auto/sdk v1.1.0 // indirect go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect + go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 // indirect go.opentelemetry.io/otel/metric v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect go.uber.org/atomic v1.11.0 // indirect @@ -119,7 +117,7 @@ require ( go.uber.org/zap v1.27.0 // indirect golang.org/x/crypto v0.37.0 // indirect golang.org/x/net v0.39.0 // indirect - golang.org/x/sys v0.32.0 // indirect + golang.org/x/sys v0.33.0 // indirect golang.org/x/text v0.24.0 // indirect golang.org/x/time v0.11.0 // indirect google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e // indirect diff --git a/go.sum b/go.sum index eb6ac34c..77277c3c 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,6 @@ filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9vkmnHYOMsOr4WLk+Vo07yKIzd94sVoIqshQ4bU= github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8= -github.com/AlecAivazis/survey/v2 v2.3.7 h1:6I/u8FvytdGsgonrYsVn2t8t4QiRnh6QSTqkkhIiSjQ= -github.com/AlecAivazis/survey/v2 v2.3.7/go.mod h1:xUTIdE4KCOIjsBAE1JYsUPoCqYdZ1reCfTwbto0Fduo= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 h1:L/gRVlceqvL25UVaW/CKtUDjefjrs0SPonmDGUVOYP0= github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E= github.com/Cray-HPE/hms-base/v2 v2.3.0 h1:BjUWnxHplxg+YqjHaEcFH6TvsFb6cqYN3WI2JA6KNTo= @@ -18,78 +16,20 @@ github.com/Cray-HPE/hms-hmetcd v1.13.0 h1:CYf/rrzsfscEk06kmqju2cV/mI0XCZUAPEX+ax github.com/Cray-HPE/hms-hmetcd v1.13.0/go.mod h1:LKlLJscLxf4jMh43Psnlh/RHIJZb/kZzx8JmyMh1SsU= github.com/Cray-HPE/hms-securestorage v1.17.0 h1:9Dr96LITvt9hqs+/CIDFNOauUPSTobU8TC3jEfd8I/A= github.com/Cray-HPE/hms-securestorage v1.17.0/go.mod h1:XYnykBCkkdWCLsMNjoMNmYfFn9UDFc02UN16k8ZHktE= -github.com/Cray-HPE/hms-trs-app-api/v3 v3.0.5 h1:mpsqnqnMtaFxDes6Fvg7YMwl6F3MgIxrGqVSUSbcZh4= -github.com/Cray-HPE/hms-trs-app-api/v3 v3.0.5/go.mod h1:V1BxRjwcXx6p6Vo96Q5HASktO2Vulv+XN+na8zytifw= -github.com/Cray-HPE/hms-trs-kafkalib/v2 v2.0.2 h1:pxOp8exE/gUojwjbcpHIH+02ESfVvZNLIv+RcK/uY4Y= -github.com/Cray-HPE/hms-trs-kafkalib/v2 v2.0.2/go.mod h1:aCPDa5X/zZZk1BgEKwtYkNslkiXsDZ94eGSbL4RGMt8= github.com/Cray-HPE/hms-xname v1.4.0 h1:i47YmE8rbSfJ64simKCCC6ZVcGid3rDIX6/jfVbISAM= github.com/Cray-HPE/hms-xname v1.4.0/go.mod h1:wH7t1UXYck0VdHSWjrMsxZmaCK5W1lmwgNnsYAFPTus= -github.com/Masterminds/semver/v3 v3.2.1 h1:RN9w6+7QoMeJVGyfmbcgs28Br8cvmnucEXnY0rYXWg0= -github.com/Masterminds/semver/v3 v3.2.1/go.mod h1:qvl/7zhW3nngYb5+80sSMF+FG2BjYrf8m9wsX0PNOMQ= github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY= github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU= -github.com/Microsoft/hcsshim v0.11.5 h1:haEcLNpj9Ka1gd3B3tAEs9CpE0c+1IhoL59w/exYU38= -github.com/Microsoft/hcsshim v0.11.5/go.mod h1:MV8xMfmECjl5HdO7U/3/hFVnkmSBjAjmA09d4bExKcU= github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18 h1:oBPtXp9RVm9lk5zTmDLf+Vh21yDHpulBxUqGJQjwQCk= github.com/OpenCHAMI/jwtauth/v5 v5.0.0-20240321222802-e6cb468a2a18/go.mod h1:ggNHWgLfW/WRXcE8ZZC4S7UwHif16HVmyowOCWdNSN8= github.com/OpenCHAMI/smd/v2 v2.19.1 h1:LgDktx+0r01jcm2tUKLH5ob8WpL8WYIHgxVbVlKbZks= github.com/OpenCHAMI/smd/v2 v2.19.1/go.mod h1:HQsQAhh34Wl5QWm5lkguk6me+D2x8klSTyUjPDpmLo8= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d h1:licZJFw2RwpHMqeKTCYkitsPqHNxTmd4SNR5r94FGM8= -github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d/go.mod h1:asat636LX7Bqt5lYEZ27JNDcqxfjdBQuJ/MM4CN/Lzo= -github.com/aws/aws-sdk-go-v2 v1.26.1 h1:5554eUqIYVWpU0YmeeYZ0wU64H2VLBs8TlhRB2L+EkA= -github.com/aws/aws-sdk-go-v2 v1.26.1/go.mod h1:ffIFB97e2yNsv4aTSGkqtHnppsIJzw7G7BReUZ3jCXM= -github.com/aws/aws-sdk-go-v2/config v1.27.10 h1:PS+65jThT0T/snC5WjyfHHyUgG+eBoupSDV+f838cro= -github.com/aws/aws-sdk-go-v2/config v1.27.10/go.mod h1:BePM7Vo4OBpHreKRUMuDXX+/+JWP38FLkzl5m27/Jjs= -github.com/aws/aws-sdk-go-v2/credentials v1.17.10 h1:qDZ3EA2lv1KangvQB6y258OssCHD0xvaGiEDkG4X/10= -github.com/aws/aws-sdk-go-v2/credentials v1.17.10/go.mod h1:6t3sucOaYDwDssHQa0ojH1RpmVmF5/jArkye1b2FKMI= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1 h1:FVJ0r5XTHSmIHJV6KuDmdYhEpvlHpiSd38RQWhut5J4= -github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.1/go.mod h1:zusuAeqezXzAB24LGuzuekqMAEgWkVYukBec3kr3jUg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5 h1:aw39xVGeRWlWx9EzGVnhOR4yOjQDHPQ6o6NmBlscyQg= -github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.5/go.mod h1:FSaRudD0dXiMPK2UjknVwwTYyZMRsHv3TtkabsZih5I= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5 h1:PG1F3OD1szkuQPzDw3CIQsRIrtTlUC3lP84taWzHlq0= -github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.5/go.mod h1:jU1li6RFryMz+so64PpKtudI+QzbKoIEivqdf6LNpOc= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0 h1:hT8rVHwugYE2lEfdFE0QWVo81lF7jMrYJVDWI+f+VxU= -github.com/aws/aws-sdk-go-v2/internal/ini v1.8.0/go.mod h1:8tu/lYfQfFe6IGnaOdrpVgEL2IrrDOf6/m9RQum4NkY= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2 h1:Ji0DY1xUsUr3I8cHps0G+XM3WWU16lP6yG8qu1GAZAs= -github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.11.2/go.mod h1:5CsjAbs3NlGQyZNFACh+zztPDI7fU6eW9QsxjfnuBKg= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7 h1:ogRAwT1/gxJBcSWDMZlgyFUM962F51A5CRhDLbxLdmo= -github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.11.7/go.mod h1:YCsIZhXfRPLFFCl5xxY+1T9RKzOKjCut+28JSX2DnAk= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.4 h1:WzFol5Cd+yDxPAdnzTA5LmpHYSWinhmSj4rQChV0ee8= -github.com/aws/aws-sdk-go-v2/service/sso v1.20.4/go.mod h1:qGzynb/msuZIE8I75DVRCUXw3o3ZyBmUvMwQ2t/BrGM= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4 h1:Jux+gDDyi1Lruk+KHF91tK2KCuY61kzoCpvtvJJBtOE= -github.com/aws/aws-sdk-go-v2/service/ssooidc v1.23.4/go.mod h1:mUYPBhaF2lGiukDEjJX2BLRRKTmoUSitGDUgM4tRxak= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.6 h1:cwIxeBttqPN3qkaAjcEcsh8NYr8n2HZPkcKgPAi1phU= -github.com/aws/aws-sdk-go-v2/service/sts v1.28.6/go.mod h1:FZf1/nKNEkHdGGJP/cI2MoIMquumuRK6ol3QQJNDxmw= -github.com/aws/smithy-go v1.20.2 h1:tbp628ireGtzcHDDmLT/6ADHidqnwgF57XOXZe6tp4Q= -github.com/aws/smithy-go v1.20.2/go.mod h1:krry+ya/rV9RDcV/Q16kpu6ypI4K2czasz0NC3qS14E= -github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM= -github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw= -github.com/buger/goterm v1.0.4 h1:Z9YvGmOih81P0FbVtEYTFF6YsSgxSUKEhf/f9bTMXbY= -github.com/buger/goterm v1.0.4/go.mod h1:HiFWV3xnkolgrBV3mY8m0X0Pumt4zg4QhbdOzQtB8tE= github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8= github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE= -github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UFvs= -github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/compose-spec/compose-go/v2 v2.1.3 h1:bD67uqLuL/XgkAK6ir3xZvNLFPxPScEi1KW7R5esrLE= -github.com/compose-spec/compose-go/v2 v2.1.3/go.mod h1:lFN0DrMxIncJGYAXTfWuajfwj5haBJqrBkarHcnjJKc= -github.com/confluentinc/confluent-kafka-go/v2 v2.10.0 h1:TK5CH5RbIj/aVfmJFEsDUT6vD2izac2zmA5BUfAOxC0= -github.com/confluentinc/confluent-kafka-go/v2 v2.10.0/go.mod h1:hScqtFIGUI1wqHIgM3mjoqEou4VweGGGX7dMpcUKves= -github.com/containerd/console v1.0.4 h1:F2g4+oChYvBTsASRTz8NP6iIAi97J3TtSAsLbIFn4ro= -github.com/containerd/console v1.0.4/go.mod h1:YynlIjWYF8myEu6sdkwKIvGQq+cOckRm6So2avqoYAk= -github.com/containerd/containerd v1.7.18 h1:jqjZTQNfXGoEaZdW1WwPU0RqSn1Bm2Ay/KJPUuO8nao= -github.com/containerd/containerd v1.7.18/go.mod h1:IYEk9/IO6wAPUz2bCMVUbsfXjzw5UNP5fLz4PsUygQ4= -github.com/containerd/continuity v0.4.3 h1:6HVkalIp+2u1ZLH1J/pYX2oBVXlJZvh1X1A7bEZ9Su8= -github.com/containerd/continuity v0.4.3/go.mod h1:F6PTNCKepoxEaXLQp3wDAjygEnImnZ/7o4JzpodfroQ= -github.com/containerd/errdefs v0.1.0 h1:m0wCRBiu1WJT/Fr+iOoQHMQS/eP5myQ8lCv4Dz5ZURM= -github.com/containerd/errdefs v0.1.0/go.mod h1:YgWiiHtLmSeBrvpw+UfPijzbLaB77mEG1WwJTDETIV0= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3EhrzVo= github.com/containerd/platforms v0.2.1 h1:zvwtM3rz2YHPQsF2CHYM8+KtB5dvhISiXh5ZpSBQv6A= github.com/containerd/platforms v0.2.1/go.mod h1:XHCb+2/hzowdiut9rkudds9bE5yJ7npe7dG/wG+uFPw= -github.com/containerd/ttrpc v1.2.5 h1:IFckT1EFQoFBMG4c3sMdT8EP3/aKfumK1msY+Ze4oLU= -github.com/containerd/ttrpc v1.2.5/go.mod h1:YCXHsb32f+Sq5/72xHubdiJRQY9inL4a4ZQrAbN1q9o= -github.com/containerd/typeurl/v2 v2.1.1 h1:3Q4Pt7i8nYwy2KmQWIw2+1hTvwTE/6w9FqcttATPO/4= -github.com/containerd/typeurl/v2 v2.1.1/go.mod h1:IDp2JFvbwZ31H8dQbEIY7sDl2L3o3HZj1hsSQlywkQ0= github.com/coreos/go-semver v0.3.1 h1:yi21YpKnrx1gt5R+la8n5WgS0kCrsPp33dmEyHReZr4= github.com/coreos/go-semver v0.3.1/go.mod h1:irMmmIw/7yzSRPWryHsK7EYSg09caPQL03VsM8rvUec= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= @@ -109,42 +49,20 @@ github.com/dhui/dktest v0.4.5 h1:uUfYBIVREmj/Rw6MvgmqNAYzTiKOHJak+enB5Di73MM= github.com/dhui/dktest v0.4.5/go.mod h1:tmcyeHDKagvlDrz7gDKq4UAJOLIfVZYkfD5OnHDwcCo= github.com/distribution/reference v0.6.0 h1:0IXCQ5g4/QMHHkarYzh5l+u8T3t73zM5QvfrDyIgxBk= github.com/distribution/reference v0.6.0/go.mod h1:BbU0aIcezP1/5jX/8MP0YiH4SdvB5Y4f/wlDRiLyi3E= -github.com/docker/buildx v0.15.1 h1:1cO6JIc0rOoC8tlxfXoh1HH1uxaNvYH1q7J7kv5enhw= -github.com/docker/buildx v0.15.1/go.mod h1:16DQgJqoggmadc1UhLaUTPqKtR+PlByN/kyXFdkhFCo= -github.com/docker/cli v27.0.3+incompatible h1:usGs0/BoBW8MWxGeEtqPMkzOY56jZ6kYlSN5BLDioCQ= -github.com/docker/cli v27.0.3+incompatible/go.mod h1:JLrzqnKDaYBop7H2jaqPtU4hHvMKP+vjCwu2uszcLI8= -github.com/docker/compose/v2 v2.28.1 h1:ORPfiVHrpnRQBDoC3F8JJyWAY8N5gWuo3FgwyivxFdM= -github.com/docker/compose/v2 v2.28.1/go.mod h1:wDtGQFHe99sPLCHXeVbCkc+Wsl4Y/2ZxiAJa/nga6rA= -github.com/docker/distribution v2.8.3+incompatible h1:AtKxIZ36LoNK51+Z6RpzLpddBirtxJnzDrHLEKxTAYk= -github.com/docker/distribution v2.8.3+incompatible/go.mod h1:J2gT2udsDAN96Uj4KfcMRqY0/ypR+oyYUYmja8H+y+w= github.com/docker/docker v28.0.1+incompatible h1:FCHjSRdXhNRFjlHMTv4jUNlIBbTeRjrWfeFuJp7jpo0= github.com/docker/docker v28.0.1+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= -github.com/docker/docker-credential-helpers v0.8.0 h1:YQFtbBQb4VrpoPxhFuzEBPQ9E16qz5SpHLS+uswaCp8= -github.com/docker/docker-credential-helpers v0.8.0/go.mod h1:UGFXcuoQ5TxPiB54nHOZ32AWRqQdECoh/Mg0AlEYb40= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c h1:lzqkGL9b3znc+ZUgi7FlLnqjQhcXxkNM/quxIjBVMD0= -github.com/docker/go v1.5.1-1.0.20160303222718-d30aec9fd63c/go.mod h1:CADgU4DSXK5QUlFslkQu2yW2TKzFZcXq/leZfM0UH5Q= github.com/docker/go-connections v0.5.0 h1:USnMq7hx7gwdVZq1L49hLXaFtUdTADjXGp+uj1Br63c= github.com/docker/go-connections v0.5.0/go.mod h1:ov60Kzw0kKElRwhNs9UlUHAE/F9Fe6GLaXnqyDdmEXc= -github.com/docker/go-metrics v0.0.1 h1:AgB/0SvBxihN0X8OR4SjsblXkbMvalQ8cjmtKQ2rQV8= -github.com/docker/go-metrics v0.0.1/go.mod h1:cG1hvH2utMXtqgqqYE9plW6lDxS3/5ayHzueweSI3Vw= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/ebitengine/purego v0.8.2 h1:jPPGWs2sZ1UgOSgD2bClL0MJIqu58nOmIcBuXr62z1I= github.com/ebitengine/purego v0.8.2/go.mod h1:iIjxzd6CiRiOG0UyXP+V1+jWqUXVjPKLAI0mRfJZTmQ= -github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203 h1:XBBHcIb256gUJtLmY22n99HaZTz+r2Z51xUPi01m3wg= -github.com/eiannone/keyboard v0.0.0-20220611211555-0d226195f203/go.mod h1:E1jcSv8FaEny+OP/5k9UxZVw9YFWGj7eI4KR/iOBqCg= -github.com/emicklei/go-restful/v3 v3.11.0 h1:rAQeMHw1c7zTmncogyy8VvRZwtkmkZ4FxERmMY4rD+g= -github.com/emicklei/go-restful/v3 v3.11.0/go.mod h1:6n3XBCmQQb25CM2LCACGz8ukIrRry+4bhvbpWn3mrbc= github.com/fatih/color v1.16.0 h1:zmkK9Ngbjj+K0yRhTVONQh1p/HknKYSlNT+vZCzyokM= github.com/fatih/color v1.16.0/go.mod h1:fL2Sau1YI5c0pdGEVCbKQbLXB6edEj1ZgiY4NijnWvE= github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg= github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U= -github.com/fsnotify/fsevents v0.2.0 h1:BRlvlqjvNTfogHfeBOFvSC9N0Ddy+wzQCQukyoD7o/c= -github.com/fsnotify/fsevents v0.2.0/go.mod h1:B3eEk39i4hz8y1zaWS/wPrAP4O6wkIl7HQwKBr1qH/w= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/fvbommel/sortorder v1.0.2 h1:mV4o8B2hKboCdkJm+a7uX/SIpZob4JzUpc5GGnM45eo= -github.com/fvbommel/sortorder v1.0.2/go.mod h1:uk88iVf1ovNn1iLfgUVU2F9o5eO30ui720w+kxuqRs0= github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8= github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops= github.com/go-jose/go-jose/v4 v4.1.0 h1:cYSYxd3pw5zd2FSXk2vGdn9igQU2PS8MuxrCOCl0FdY= @@ -156,46 +74,24 @@ github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY= github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= -github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE= -github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs= -github.com/go-openapi/jsonreference v0.20.2 h1:3sVjiK66+uXK/6oQ8xgcRKcFgQ5KXa2KvnJRumpMGbE= -github.com/go-openapi/jsonreference v0.20.2/go.mod h1:Bl1zwGIM8/wsvqjsOQLJ/SH+En5Ap4rVB5KVcIDZG2k= -github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= -github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y= github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg= github.com/go-test/deep v1.1.0 h1:WOcxcdHcvdgThNXjw0t76K42FXTU7HpNQWHpA2HHNlg= github.com/go-test/deep v1.1.0/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= -github.com/go-viper/mapstructure/v2 v2.0.0 h1:dhn8MZ1gZ0mzeodTG3jt5Vj/o87xZKuNAprG2mQfMfc= -github.com/go-viper/mapstructure/v2 v2.0.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/goccy/go-json v0.10.3 h1:KZ5WoDbxAIgm2HNbYckL0se1fHD6rz5j4ywS6ebzDqA= github.com/goccy/go-json v0.10.3/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= -github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= -github.com/gogo/googleapis v1.4.1 h1:1Yx4Myt7BxzvUr5ldGSbwYiZG6t9wGBZ+8/fX3Wvtq0= -github.com/gogo/googleapis v1.4.1/go.mod h1:2lpHqI5OcWCtVElxXnPt+s8oJvMpySlOyM6xDCrzib4= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/golang-migrate/migrate/v4 v4.18.3 h1:EYGkoOsvgHHfm5U/naS1RP/6PL/Xv3S4B/swMiAmDLs= github.com/golang-migrate/migrate/v4 v4.18.3/go.mod h1:99BKpIi6ruaaXRM1A77eqZ+FWPQ3cfRa+ZVy5bmWMaY= github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek= github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps= -github.com/google/gnostic-models v0.6.8 h1:yo/ABAfM5IMRsS1VnXjTBvUb61tFIHozhlYvRgGre9I= -github.com/google/gnostic-models v0.6.8/go.mod h1:5n7qKqH0f5wFt+aWF8CW6pZLLNOfYuF5OpfBSENuI8U= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8= github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU= -github.com/google/gofuzz v1.2.0 h1:xRy4A+RhZaiKjJ1bPfwQ8sedCA+YS2YcCHW6ec7JMi0= -github.com/google/gofuzz v1.2.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4= -github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ= github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0= github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= -github.com/gorilla/mux v1.8.1 h1:TuBL49tXwgrFYWhqrNgrUNEY92u81SPhu7sTdzQEiWY= -github.com/gorilla/mux v1.8.1/go.mod h1:AKf9I4AEqPTmMytcMc0KkNouC66V3BtZ4qD5fmWSiMQ= -github.com/gorilla/websocket v1.5.0 h1:PPwGk2jz7EePpoHN/+ClbZu8SPxiqlu12wZP/3sWmnc= -github.com/gorilla/websocket v1.5.0/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE= github.com/grpc-ecosystem/grpc-gateway v1.16.0 h1:gmcG1KaJ57LophUzW0Hy8NmPhnMZb4M0+kPpLofRdBo= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rHAxPBD8KFhJpmcqms= github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg= @@ -218,16 +114,10 @@ github.com/hashicorp/go-secure-stdlib/strutil v0.1.2 h1:kes8mmyCpxJsI7FTwtzRqEy9 github.com/hashicorp/go-secure-stdlib/strutil v0.1.2/go.mod h1:Gou2R9+il93BqX25LAKCLuM+y9U2T4hlwvT1yprcna4= github.com/hashicorp/go-sockaddr v1.0.7 h1:G+pTkSO01HpR5qCxg7lxfsFEZaG+C0VssTy/9dbT+Fw= github.com/hashicorp/go-sockaddr v1.0.7/go.mod h1:FZQbEYa1pxkQ7WLpyXJ6cbjpT8q0YgQaK/JakXqGyWw= -github.com/hashicorp/go-version v1.7.0 h1:5tqGy27NaOTB8yJKUZELlFAS/LTKJkrmONwQKeRZfjY= -github.com/hashicorp/go-version v1.7.0/go.mod h1:fltr4n8CU8Ke44wwGCBoEymUuxUHl09ZGVZPK5anwXA= github.com/hashicorp/hcl v1.0.1-vault-5 h1:kI3hhbbyzr4dldA8UdTb7ZlVVlI2DACdCfz31RPDgJM= github.com/hashicorp/hcl v1.0.1-vault-5/go.mod h1:XYhtn6ijBSAj6n4YqAaf7RBPS4I06AItNorpy+MoQNM= github.com/hashicorp/vault/api v1.16.0 h1:nbEYGJiAPGzT9U4oWgaaB0g+Rj8E59QuHKyA5LhwQN4= github.com/hashicorp/vault/api v1.16.0/go.mod h1:KhuUhzOD8lDSk29AtzNjgAu2kxRA9jL9NAbkFlqvkBA= -github.com/imdario/mergo v0.3.16 h1:wwQJbIsHYGMUyLSPrEq1CT16AhnhNJQ51+4fdHUnCl4= -github.com/imdario/mergo v0.3.16/go.mod h1:WBLT9ZmE3lPoWsEzCh9LPo3TiwVN+ZKEjmz+hD27ysY= -github.com/in-toto/in-toto-golang v0.5.0 h1:hb8bgwr0M2hGdDsLjkJ3ZqJ8JFLL/tgYdAxF/XEFBbY= -github.com/in-toto/in-toto-golang v0.5.0/go.mod h1:/Rq0IZHLV7Ku5gielPT4wPHJfH1GdHMCq8+WPxw8/BE= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM= @@ -240,14 +130,6 @@ github.com/jackc/puddle/v2 v2.2.1 h1:RhxXJtFG022u4ibrCSMSiu5aOq1i77R3OHKNJj77OAk github.com/jackc/puddle/v2 v2.2.1/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4= github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= -github.com/jonboulle/clockwork v0.4.0 h1:p4Cf1aMWXnXAUh8lVfewRBx1zaTSYKrKMF2g3ST4RZ4= -github.com/jonboulle/clockwork v0.4.0/go.mod h1:xgRqUGwRcjKCO1vbZUEtSLrqKoPSsUpK7fnezOII0kc= -github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY= -github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y= -github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM= -github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNUXsshfwJMBgNA0RU6/i7WVaAegv3PtuIHPMs= -github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/klauspost/compress v1.17.9 h1:6KIumPrER1LHsvBVuDa0r5xaG0Es51mhhB9BQB2qeMA= @@ -279,66 +161,34 @@ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/magiconair/properties v1.8.10 h1:s31yESBquKXCV9a/ScB3ESkOjUYYv+X0rg8SYxI99mE= github.com/magiconair/properties v1.8.10/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0= -github.com/mailru/easyjson v0.9.0 h1:PrnmzHw7262yW8sTBwxi1PdJA3Iw/EKBa8psRf7d9a4= -github.com/mailru/easyjson v0.9.0/go.mod h1:1+xMtQp2MRNVL/V1bOzuP3aP8VNwRW55fQUto+XFtTU= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= -github.com/mattn/go-runewidth v0.0.15 h1:UNAjwbU9l54TA3KzvqLGxwWjHmMgBUVhBiTjelZgg3U= -github.com/mattn/go-runewidth v0.0.15/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w= -github.com/mattn/go-shellwords v1.0.12 h1:M2zGm7EW6UQJvDeQxo4T51eKPurbeFbe8WtebGE2xrk= -github.com/mattn/go-shellwords v1.0.12/go.mod h1:EZzvwXDESEeg03EKmM+RmDnNOPKG4lLtQsUlTZDWQ8Y= github.com/mattn/go-sqlite3 v1.14.22 h1:2gZY6PC6kBnID23Tichd1K+Z0oS6nE/XwU+Vz/5o4kU= github.com/mattn/go-sqlite3 v1.14.22/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y= -github.com/matttproud/golang_protobuf_extensions v1.0.4 h1:mmDVorXM7PCGKw94cs5zkfA9PSy5pEvNWRP0ET0TIVo= -github.com/matttproud/golang_protobuf_extensions v1.0.4/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/mdelapenya/tlscert v0.2.0 h1:7H81W6Z/4weDvZBNOfQte5GpIMo0lGYEeWbkGp5LJHI= github.com/mdelapenya/tlscert v0.2.0/go.mod h1:O4njj3ELLnJjGdkN7M/vIVCpZ+Cf0L6muqOG4tLSl8o= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b h1:j7+1HpAFS1zy5+Q4qx1fWh90gTKwiN4QCGoY9TWyyO4= -github.com/mgutz/ansi v0.0.0-20170206155736-9520e82c474b/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE= -github.com/miekg/pkcs11 v1.1.1 h1:Ugu9pdy6vAYku5DEpVWVFPYnzV+bxB+iRdbuFSu7TvU= -github.com/miekg/pkcs11 v1.1.1/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/mitchellh/go-homedir v1.1.0 h1:lukF9ziXFxDFPkA1vsr5zpc1XuPDn/wFntq5mG+4E0Y= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY= github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo= -github.com/moby/buildkit v0.14.1 h1:2epLCZTkn4CikdImtsLtIa++7DzCimrrZCT1sway+oI= -github.com/moby/buildkit v0.14.1/go.mod h1:1XssG7cAqv5Bz1xcGMxJL123iCv5TYN4Z/qf647gfuk= github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0= github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo= -github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= -github.com/moby/locker v1.0.1/go.mod h1:S7SDdo5zpBK84bzzVlKr2V0hz+7x9hWbYC/kq7oQppc= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/spdystream v0.2.0 h1:cjW1zVyyoiM0T7b6UoySUFqzXMoqRckQtXwGPiBhOM8= -github.com/moby/spdystream v0.2.0/go.mod h1:f7i0iNDQJ059oMTcWxx8MA/zKFIuD/lY+0GqbN2Wy8c= -github.com/moby/sys/mountinfo v0.7.1 h1:/tTvQaSJRr2FshkhXiIpux6fQ2Zvc4j7tAhMTStAG2g= -github.com/moby/sys/mountinfo v0.7.1/go.mod h1:IJb6JQeOklcdMU9F5xQ8ZALD+CUr5VlGpwtX+VE0rpI= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= -github.com/moby/sys/signal v0.7.0 h1:25RW3d5TnQEoKvRbEKUGay6DCQ46IxAVTT9CUMgmsSI= -github.com/moby/sys/signal v0.7.0/go.mod h1:GQ6ObYZfqacOwTtlXvcmh9A26dVRul/hbOZn88Kg8Tg= -github.com/moby/sys/symlink v0.2.0 h1:tk1rOM+Ljp0nFmfOIBtlV3rTDlWOwFRhjEeAhZB0nZc= -github.com/moby/sys/symlink v0.2.0/go.mod h1:7uZVF2dqJjG/NsClqul95CqKOBRQyYSNnJ6BMgR/gFs= github.com/moby/sys/user v0.1.0 h1:WmZ93f5Ux6het5iituh9x2zAG7NFY9Aqi49jjE1PaQg= github.com/moby/sys/user v0.1.0/go.mod h1:fKJhFOnsCN6xZ5gSfbM6zaHGgDJMrqt9/reuj4T7MmU= github.com/moby/sys/userns v0.1.0 h1:tVLXkFOxVu9A64/yh59slHVv9ahO9UIev4JZusOLG/g= github.com/moby/sys/userns v0.1.0/go.mod h1:IHUYgu/kao6N8YZlp9Cf444ySSvCmDlmzUcYfDHOl28= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= github.com/moby/term v0.5.0/go.mod h1:8FzsFHVUBGZdbDsJw/ot+X+d5HLUbvklYLJ9uGfcI3Y= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg= -github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q= -github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9Gz0M= -github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk= github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA= -github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f h1:y5//uYreIhSUg3J1GEMiLbxo1LJaP8RfCpH6pymGZus= -github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+o7JKHSa8/e818NopupXU1YMK5fe1lsApnBw= github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700 h1:XADGipD2FZ9swuFUqeL7h63j3voiq9qA7P0aKsqgZKg= github.com/openchami/chi-middleware/auth v0.0.0-20240812224658-b16b83c70700/go.mod h1:kswb9kU5cZAFRAvf1dAUJRWbQyjDEb0qkxW4ncDdEXg= github.com/openchami/chi-middleware/log v0.0.0-20240812224658-b16b83c70700 h1:Gzt5f6RK39CHvY3SJudzBb/RK4tVh/S3CpJ0eQlbNdg= @@ -347,8 +197,6 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.1 h1:y0fUlFfIZhPF1W537XOLg0/fcx6zcHCJwooC2xJA040= github.com/opencontainers/image-spec v1.1.1/go.mod h1:qpqAh3Dmcf36wStyyWU+kCeDgrGnAve2nCC8+7h8Q0M= -github.com/pelletier/go-toml v1.9.5 h1:4yBQzkHv+7BHq2PQUZF3Mx0IYxG7LsP222s7Agd3ve8= -github.com/pelletier/go-toml v1.9.5/go.mod h1:u1nR/EPcESfeI/szUZKdtJ0xRNbUoANCkoOuaOx1Y+c= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= @@ -356,18 +204,6 @@ github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRI github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw= github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE= -github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q= -github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY= -github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw= -github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI= -github.com/prometheus/common v0.44.0 h1:+5BrQJwiBB9xsMygAB3TNvpQKOwlkc25LbISbrdOOfY= -github.com/prometheus/common v0.44.0/go.mod h1:ofAIvZbQ1e/nugmZGz4/qCb9Ap1VoSTIO7x0VV9VvuY= -github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo= -github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo= -github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc h1:zAsgcP8MhzAbhMnB1QQ2O7ZhWYVGYSR2iVcjzQuPV+o= -github.com/r3labs/sse v0.0.0-20210224172625-26fe804710bc/go.mod h1:S8xSOnV3CgpNrWd0GQ/OoQfMtlg2uPRSuTzcSGrzwK8= -github.com/rivo/uniseg v0.2.0 h1:S1pD9weZBuJdFmowNwbpi7BJ8TNftyUImj/0WQi72jY= -github.com/rivo/uniseg v0.2.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII= github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o= github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= @@ -376,20 +212,12 @@ github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWR github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/go-glob v1.0.0 h1:iQh3xXAumdQ+4Ufa5b25cRpC5TYKlno6hsv6Cb3pkBk= github.com/ryanuber/go-glob v1.0.0/go.mod h1:807d1WSdnB0XRJzKNil9Om6lcp/3a0v4qIHxIXzX/Yc= -github.com/secure-systems-lab/go-securesystemslib v0.4.0 h1:b23VGrQhTA8cN2CbBw7/FulN9fTtqYUdS5+Oxzt+DUE= -github.com/secure-systems-lab/go-securesystemslib v0.4.0/go.mod h1:FGBZgq2tXWICsxWQW1msNf49F0Pf2Op5Htayx335Qbs= github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys= github.com/segmentio/asm v1.2.0/go.mod h1:BqMnlJP91P8d+4ibuonYZw9mfnzI9HfxselHZr5aAcs= -github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b h1:h+3JX2VoWTFuyQEo87pStk/a99dzIO1mM9KxIyLPGTU= -github.com/serialx/hashring v0.0.0-20200727003509-22c0c7ab6b1b/go.mod h1:/yeG0My1xr/u+HZrFQ1tOQQQQrOawfyMUH13ai5brBc= -github.com/shibumi/go-pathspec v1.3.0 h1:QUyMZhFo0Md5B8zV8x2tesohbb5kfbpTi9rBnKh5dkI= -github.com/shibumi/go-pathspec v1.3.0/go.mod h1:Xutfslp817l2I1cZvgcfeMQJG5QnU2lh5tVaaMCl3jE= github.com/shirou/gopsutil/v4 v4.25.1 h1:QSWkTc+fu9LTAWfkZwZ6j8MSUk4A2LV7rbH0ZqmLjXs= github.com/shirou/gopsutil/v4 v4.25.1/go.mod h1:RoUCUpndaJFtT+2zsZzzmhvbfGoDCJ7nFXKJf8GqJbI= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966 h1:JIAuq3EEf9cgbU6AtGPK4CTG3Zf6CKMNqf0MHTggAUA= -github.com/skratchdot/open-golang v0.0.0-20200116055534-eef842397966/go.mod h1:sUM3LWHvSMaG192sy56D9F7CNvL7jUJVXoqM1QKLnog= github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo= github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0= github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= @@ -404,32 +232,14 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= github.com/testcontainers/testcontainers-go v0.37.0 h1:L2Qc0vkTw2EHWQ08djon0D2uw7Z/PtHS/QzZZ5Ra/hg= github.com/testcontainers/testcontainers-go v0.37.0/go.mod h1:QPzbxZhQ6Bclip9igjLFj6z0hs01bU8lrl2dHQmgFGM= -github.com/testcontainers/testcontainers-go/modules/compose v0.33.0 h1:PyrUOF+zG+xrS3p+FesyVxMI+9U+7pwhZhyFozH3jKY= -github.com/testcontainers/testcontainers-go/modules/compose v0.33.0/go.mod h1:oqZaUnFEskdZriO51YBquku/jhgzoXHPot6xe1DqKV4= github.com/testcontainers/testcontainers-go/modules/etcd v0.37.0 h1:1Jm1my2OAd3qNGG3pUpCB6tRPOxZMsOrPRI18cInZrY= github.com/testcontainers/testcontainers-go/modules/etcd v0.37.0/go.mod h1:bLj0UboNNVpeQXsB3z0jB/J9WPGHbqzF4U54OmAqjrs= github.com/testcontainers/testcontainers-go/modules/postgres v0.37.0 h1:hsVwFkS6s+79MbKEO+W7A1wNIw1fmkMtF4fg83m6kbc= github.com/testcontainers/testcontainers-go/modules/postgres v0.37.0/go.mod h1:Qj/eGbRbO/rEYdcRLmN+bEojzatP/+NS1y8ojl2PQsc= -github.com/theupdateframework/notary v0.7.0 h1:QyagRZ7wlSpjT5N2qQAh/pN+DVqgekv4DzbAiAiEL3c= -github.com/theupdateframework/notary v0.7.0/go.mod h1:c9DRxcmhHmVLDay4/2fUYdISnHqbFDGRSlXPO0AhYWw= -github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375 h1:QB54BJwA6x8QU9nHY3xJSZR2kX9bgpZekRKGkLTmEXA= -github.com/tilt-dev/fsnotify v1.4.8-0.20220602155310-fff9c274a375/go.mod h1:xRroudyp5iVtxKqZCrA6n2TLFRBf8bmnjr1UD4x+z7g= github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU= github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI= github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk= github.com/tklauser/numcpus v0.6.1/go.mod h1:1XfjsgE2zo8GVw7POkMbHENHzVg3GzmoZ9fESEdAacY= -github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c h1:+6wg/4ORAbnSoGDzg2Q1i3CeMcT/jjhye/ZfnBHy7/M= -github.com/tonistiigi/fsutil v0.0.0-20240424095704-91a3fc46842c/go.mod h1:vbbYqJlnswsbJqWUcJN8fKtBhnEgldDrcagTgnBVKKM= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea h1:SXhTLE6pb6eld/v/cCndK0AMpt1wiVFb/YYmqB3/QG0= -github.com/tonistiigi/units v0.0.0-20180711220420-6950e57a87ea/go.mod h1:WPnis/6cRcDZSUvVmezrxJPkiO87ThFYsoUiMwWNDJk= -github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab h1:H6aJ0yKQ0gF49Qb2z5hI1UHxSQt4JMyxebFR15KnApw= -github.com/tonistiigi/vt100 v0.0.0-20240514184818-90bafcd6abab/go.mod h1:ulncasL3N9uLrVann0m+CDlJKWsIAP34MPcOJF6VRvc= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb h1:zGWFAtiMcyryUHoUjUJX0/lt1H2+i2Ka2n+D3DImSNo= -github.com/xeipuuv/gojsonpointer v0.0.0-20190905194746-02993c407bfb/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415 h1:EzJWgHovont7NscjpAxXsDA8S8BMYve8Y5+7cuRE7R0= -github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= -github.com/xeipuuv/gojsonschema v1.2.0 h1:LhYJRs+L4fBtjZUfuSZIKGeVu0QRy8e5Xi7D17UxZ74= -github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0= @@ -442,24 +252,12 @@ go.etcd.io/etcd/client/v3 v3.5.21 h1:T6b1Ow6fNjOLOtM0xSoKNQt1ASPCLWrF9XMHcH9pEyY go.etcd.io/etcd/client/v3 v3.5.21/go.mod h1:mFYy67IOqmbRf/kRUvsHixzo3iG+1OF2W2+jVIQRAnU= go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA= go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0 h1:4Pp6oUg3+e/6M4C0A/3kJ2VYa++dsWVTtGgLVj5xtHg= -go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.49.0/go.mod h1:Mjt1i1INqiaoZOMGR1RIUJN+i3ChKoFRqzrRQhlkbs0= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1 h1:gbhw/u49SS3gkPWiYweQNJGm/uJN5GkI/FrosxSHT7A= -go.opentelemetry.io/contrib/instrumentation/net/http/httptrace/otelhttptrace v0.46.1/go.mod h1:GnOaBaFQ2we3b9AGWJpsBa7v1S5RlQzlC3O7dRMxZhM= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0 h1:TT4fX+nBOA/+LUkobKGW1ydGcn+G3vRw9+g5HwCphpk= go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.54.0/go.mod h1:L7UH0GbB0p47T4Rri3uHjbpCFYrVrwc1I25QhNPiGK8= go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ= go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0 h1:ZtfnDL+tUrs1F0Pzfwbg2d59Gru9NCH3bgSHBM6LDwU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric v0.42.0/go.mod h1:hG4Fj/y8TR/tlEDREo8tWstl9fO9gcFkn4xrx0Io8xU= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0 h1:NmnYCiR0qNufkldjVvyQfZTHSdzeHoZ41zggMsdMcLM= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetricgrpc v0.42.0/go.mod h1:UVAO61+umUsHLtYb8KXXRoHtxUkdOPkYidzW3gipRLQ= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0 h1:wNMDy/LVGLj2h3p6zg4d0gypKfWKSWI14E1C4smOgl8= -go.opentelemetry.io/otel/exporters/otlp/otlpmetric/otlpmetrichttp v0.42.0/go.mod h1:YfbDdXAAkemWJK3H/DshvlrxqFB2rtW4rY6ky/3x/H0= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0 h1:dIIDULZJpgdiHz5tXrTgKIMLkus6jEFa7x5SOKcyR7E= go.opentelemetry.io/otel/exporters/otlp/otlptrace v1.29.0/go.mod h1:jlRVBe7+Z1wyxFSUs48L6OBQZ5JwH2Hg/Vbl+t9rAgI= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0 h1:tIqheXEFWAZ7O8A7m+J0aPTmpJN3YQ7qetUAdkkkKpk= -go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc v1.21.0/go.mod h1:nUeKExfxAQVbiVFn32YXpXZZHZ61Cc3s3Rn1pDBGAb0= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0 h1:digkEZCJWobwBqMwC0cwCq8/wkkRy/OowZg5OArWZrM= go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp v1.21.0/go.mod h1:/OpE/y70qVkndM0TrxT4KBoN3RsFZP0QaofcfYrj76I= go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M= @@ -476,8 +274,6 @@ go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE= go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= -go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU= -go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= @@ -516,8 +312,8 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o= golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= @@ -534,8 +330,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa h1:ePqxpG3LVx+feAUOx8YmR5T7rc0rdzK8DyxM8cQ9zq0= -google.golang.org/genproto v0.0.0-20240325203815-454cdb8f5daa/go.mod h1:CnZenrTdRJb7jc+jOm0Rkywq+9wh0QC4U8tyiRbEPPM= google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e h1:UdXH7Kzbj+Vzastr5nVfccbmFsmYNygVLSPk1pEfDoY= google.golang.org/genproto/googleapis/api v0.0.0-20250414145226-207652e42e2e/go.mod h1:085qFyf2+XaZlRdCgKNCIZ3afY2p4HHZdoIRpId8F4A= google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA= @@ -544,37 +338,11 @@ google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM= google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY= -gopkg.in/cenkalti/backoff.v1 v1.1.0 h1:Arh75ttbsvlpVA7WtVpH4u9h6Zl46xuptxqLxPiSo4Y= -gopkg.in/cenkalti/backoff.v1 v1.1.0/go.mod h1:J6Vskwqd+OMVJl8C33mmtxTBs2gyzfv7UDAkHu8BrjI= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= -gopkg.in/inf.v0 v0.9.1 h1:73M5CoZyi3ZLMOyDlQh031Cx6N9NDJ2Vvfl76EDAgDc= -gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gotest.tools/v3 v3.5.1 h1:EENdUnS3pdur5nybKYIh2Vfgc8IUNBjxDPSjtiJcOzU= gotest.tools/v3 v3.5.1/go.mod h1:isy3WKz7GK6uNw/sbHzfKBLvlvXwUyV06n6brMxxopU= -k8s.io/api v0.29.2 h1:hBC7B9+MU+ptchxEqTNW2DkUosJpp1P+Wn6YncZ474A= -k8s.io/api v0.29.2/go.mod h1:sdIaaKuU7P44aoyyLlikSLayT6Vb7bvJNCX105xZXY0= -k8s.io/apimachinery v0.29.2 h1:EWGpfJ856oj11C52NRCHuU7rFDwxev48z+6DSlGNsV8= -k8s.io/apimachinery v0.29.2/go.mod h1:6HVkd1FwxIagpYrHSwJlQqZI3G9LfYWRPAkUvLnXTKU= -k8s.io/client-go v0.29.2 h1:FEg85el1TeZp+/vYJM7hkDlSTFZ+c5nnK44DJ4FyoRg= -k8s.io/client-go v0.29.2/go.mod h1:knlvFZE58VpqbQpJNbCbctTVXcd35mMyAAwBdpt4jrA= -k8s.io/klog/v2 v2.110.1 h1:U/Af64HJf7FcwMcXyKm2RPM22WZzyR7OSpYj5tg3cL0= -k8s.io/klog/v2 v2.110.1/go.mod h1:YGtd1984u+GgbuZ7e08/yBuAfKLSO0+uR1Fhi6ExXjo= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00 h1:aVUu9fTY98ivBPKR9Y5w/AuzbMm96cd3YHRTU83I780= -k8s.io/kube-openapi v0.0.0-20231010175941-2dd684a91f00/go.mod h1:AsvuZPBlUDVuCdzJ87iajxtXuR9oktsTctW/R9wwouA= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b h1:sgn3ZU783SCgtaSJjpcVVlRqd6GSnlTLKgpAAttJvpI= -k8s.io/utils v0.0.0-20230726121419-3b25d923346b/go.mod h1:OLgZIPagt7ERELqWJFomSt595RzquPNLL48iOWgYOg0= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd h1:EDPBXCAspyGV4jQlpZSudPeMmr1bNJefnuqLsRAsHZo= -sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1 h1:150L+0vs/8DA78h1u02ooW1/fFq/Lwr+sGiqlzvrtq4= -sigs.k8s.io/structured-merge-diff/v4 v4.4.1/go.mod h1:N8hJocpFajUSSeSJ9bOZ77VzejKZaXsTtZo4/u7Io08= -sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo= -sigs.k8s.io/yaml v1.3.0/go.mod h1:GeOyir5tyXNByN85N/dRIT9es5UQNerPYEKK56eTBm8= -tags.cncf.io/container-device-interface v0.7.2 h1:MLqGnWfOr1wB7m08ieI4YJ3IoLKKozEnnNYBtacDPQU= -tags.cncf.io/container-device-interface v0.7.2/go.mod h1:Xb1PvXv2BhfNb3tla4r9JL129ck1Lxv9KuU6eVOfKto= diff --git a/internal/api/health_test.go b/internal/api/health_test.go index 23a88209..5e265426 100644 --- a/internal/api/health_test.go +++ b/internal/api/health_test.go @@ -36,7 +36,6 @@ import ( base "github.com/Cray-HPE/hms-base/v2" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/sirupsen/logrus" "github.com/stretchr/testify/suite" @@ -45,6 +44,7 @@ import ( "github.com/OpenCHAMI/power-control/v2/internal/hsm" "github.com/OpenCHAMI/power-control/v2/internal/logger" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) type Models_TS struct { @@ -55,7 +55,7 @@ var glogger = logrus.New() var ( Running bool - TLOC_rf trsapi.TrsAPI + TLOC_rf taskrun.TrsAPI DSP storage.StorageProvider HSM hsm.HSMProvider CS credstore.CredStoreProvider @@ -87,7 +87,7 @@ func setupGlobals(suite *Models_TS) { err = HSM.Init(&glb) suite.Assert().Equal(err, nil, "ERROR calling Init(): %v", err) - workerSec := &trsapi.TRSHTTPLocal{} + workerSec := &taskrun.TRSHTTPLocal{} TLOC_rf = workerSec TLOC_rf.Init("HealthTest", glogger) diff --git a/internal/domain/globals.go b/internal/domain/globals.go index 0a275504..37cfb5e1 100644 --- a/internal/domain/globals.go +++ b/internal/domain/globals.go @@ -29,12 +29,12 @@ import ( "time" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/OpenCHAMI/power-control/v2/internal/credstore" "github.com/OpenCHAMI/power-control/v2/internal/hsm" "github.com/OpenCHAMI/power-control/v2/internal/logger" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) var GLOB *DOMAIN_GLOBALS @@ -45,9 +45,9 @@ func Init(glob *DOMAIN_GLOBALS) { type DOMAIN_GLOBALS struct { CAUri string - BaseTRSTask *trs_http_api.HttpTask - RFTloc *trs_http_api.TrsAPI - HSMTloc *trs_http_api.TrsAPI + BaseTRSTask *taskrun.HttpTask + RFTloc *taskrun.TrsAPI + HSMTloc *taskrun.TrsAPI RFClientLock *sync.RWMutex Running *bool DSP *storage.StorageProvider @@ -63,9 +63,9 @@ type DOMAIN_GLOBALS struct { PodName string } -func (g *DOMAIN_GLOBALS) NewGlobals(base *trs_http_api.HttpTask, - tlocRF *trs_http_api.TrsAPI, - tlocSVC *trs_http_api.TrsAPI, +func (g *DOMAIN_GLOBALS) NewGlobals(base *taskrun.HttpTask, + tlocRF *taskrun.TrsAPI, + tlocSVC *taskrun.TrsAPI, clientRF *hms_certs.HTTPClientPair, clientSVC *hms_certs.HTTPClientPair, rfClientLock *sync.RWMutex, diff --git a/internal/domain/power-cap_test.go b/internal/domain/power-cap_test.go index 9f6aff35..25482f2e 100644 --- a/internal/domain/power-cap_test.go +++ b/internal/domain/power-cap_test.go @@ -37,12 +37,12 @@ import ( "time" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/OpenCHAMI/power-control/v2/internal/hsm" "github.com/OpenCHAMI/power-control/v2/internal/logger" "github.com/OpenCHAMI/power-control/v2/internal/model" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) var RFServerUrl string @@ -219,14 +219,14 @@ func doSetup() error { err error Running bool = true svcClient *hms_certs.HTTPClientPair - TLOC_rf, TLOC_svc trsapi.TrsAPI + TLOC_rf, TLOC_svc taskrun.TrsAPI rfClientLock *sync.RWMutex = &sync.RWMutex{} serviceName string = "PCS-domain-power-cap-test" DSP storage.StorageProvider HSM hsm.HSMProvider VaultEnabled bool = false StateManagerServer string - BaseTRSTask trsapi.HttpTask + BaseTRSTask taskrun.HttpTask domainGlobals DOMAIN_GLOBALS ) @@ -251,9 +251,9 @@ func doSetup() error { BaseTRSTask.Request.Header.Set("Content-Type", "application/json") BaseTRSTask.Request.Header.Add("HMS-Service", BaseTRSTask.ServiceName) - workerSec := &trsapi.TRSHTTPLocal{} + workerSec := &taskrun.TRSHTTPLocal{} workerSec.Logger = logger.Log - workerInsec := &trsapi.TRSHTTPLocal{} + workerInsec := &taskrun.TRSHTTPLocal{} workerInsec.Logger = logger.Log TLOC_rf = workerSec TLOC_svc = workerInsec diff --git a/internal/domain/power-status.go b/internal/domain/power-status.go index 0c37f4a6..9c5611eb 100644 --- a/internal/domain/power-status.go +++ b/internal/domain/power-status.go @@ -33,16 +33,15 @@ import ( "time" base "github.com/Cray-HPE/hms-base/v2" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/Cray-HPE/hms-xname/xnametypes" rf "github.com/OpenCHAMI/smd/v2/pkg/redfish" + "github.com/sirupsen/logrus" "github.com/OpenCHAMI/power-control/v2/internal/credstore" pcshsm "github.com/OpenCHAMI/power-control/v2/internal/hsm" pcsmodel "github.com/OpenCHAMI/power-control/v2/internal/model" "github.com/OpenCHAMI/power-control/v2/internal/storage" - - "github.com/sirupsen/logrus" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) // Power monitoring framework. The general flow of this framework: @@ -67,7 +66,7 @@ type componentPowerInfo struct { // Used for local TRS response handling type rspStuff struct { - task *trsapi.HttpTask + task *taskrun.HttpTask body []byte } @@ -82,7 +81,7 @@ var hsmHandle *pcshsm.HSMProvider var kvStore *storage.StorageProvider var ccStore *credstore.CredStoreProvider var distLocker *storage.DistributedLockProvider -var tloc *trsapi.TrsAPI +var tloc *taskrun.TrsAPI var pmSampleInterval time.Duration var distLockMaxTime time.Duration var pstateMonitorRunning bool @@ -447,7 +446,7 @@ func getVaultCredsAll(compMap map[string]*componentPowerInfo) error { // // So for now, if there is no Response data and Err is nil, we will consider // that a 204. If there is no Response and Err is populated, it will be a 500. -func getStatusCode(tp *trsapi.HttpTask) int { +func getStatusCode(tp *taskrun.HttpTask) int { var ecode int if tp.Request.Response != nil { ecode = int(tp.Request.Response.StatusCode) @@ -483,13 +482,13 @@ func getHWStatesFromHW() error { idleConnTimeout := (statusTimeout + int(pmSampleInterval/time.Second)) * 15 / 10 - sourceTL := trsapi.HttpTask{ + sourceTL := taskrun.HttpTask{ Timeout: time.Duration(statusTimeout) * time.Second, - CPolicy: trsapi.ClientPolicy{ - Retry: trsapi.RetryPolicy{ + CPolicy: taskrun.ClientPolicy{ + Retry: taskrun.RetryPolicy{ Retries: httpRetries, }, - Tx: trsapi.HttpTxPolicy{ + Tx: taskrun.HttpTxPolicy{ Enabled: true, MaxIdleConns: maxIdleConns, MaxIdleConnsPerHost: maxIdleConnsPerHost, diff --git a/internal/domain/power-status_test.go b/internal/domain/power-status_test.go index efcf4e4a..005daad8 100644 --- a/internal/domain/power-status_test.go +++ b/internal/domain/power-status_test.go @@ -36,7 +36,6 @@ import ( base "github.com/Cray-HPE/hms-base/v2" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/Cray-HPE/hms-xname/xnametypes" "github.com/sirupsen/logrus" "github.com/stretchr/testify/suite" @@ -45,6 +44,7 @@ import ( "github.com/OpenCHAMI/power-control/v2/internal/hsm" pcsmodel "github.com/OpenCHAMI/power-control/v2/internal/model" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) type PwrStat_TS struct { @@ -62,7 +62,7 @@ func glbInit() { var credStoreGlob credstore.CREDSTORE_GLOBALS lsvcName := "PwrControlTest" - var TLOC_rf trsapi.TrsAPI + var TLOC_rf taskrun.TrsAPI var CS credstore.CredStoreProvider tcs := &credstore.VAULTv0{} var HSM hsm.HSMProvider @@ -102,7 +102,7 @@ func glbInit() { DSP = sprov DSP.Init(tlogger) - winsec := &trsapi.TRSHTTPLocal{} + winsec := &taskrun.TRSHTTPLocal{} winsec.Logger = tlogger TLOC_rf = winsec TLOC_rf.Init(lsvcName, tlogger) diff --git a/internal/domain/transitions_test.go b/internal/domain/transitions_test.go index e0aee994..3d07f720 100644 --- a/internal/domain/transitions_test.go +++ b/internal/domain/transitions_test.go @@ -35,7 +35,6 @@ import ( "time" "github.com/Cray-HPE/hms-certs/pkg/hms_certs" - trsapi "github.com/Cray-HPE/hms-trs-app-api/v3/pkg/trs_http_api" "github.com/Cray-HPE/hms-xname/xnametypes" "github.com/google/uuid" "github.com/stretchr/testify/suite" @@ -45,6 +44,7 @@ import ( "github.com/OpenCHAMI/power-control/v2/internal/logger" "github.com/OpenCHAMI/power-control/v2/internal/model" "github.com/OpenCHAMI/power-control/v2/internal/storage" + "github.com/OpenCHAMI/power-control/v2/internal/taskrun" ) type Transitions_TS struct { @@ -58,7 +58,7 @@ func (ts *Transitions_TS) SetupSuite() { var ( Running bool = true svcClient *hms_certs.HTTPClientPair - TLOC_rf, TLOC_svc trsapi.TrsAPI + TLOC_rf, TLOC_svc taskrun.TrsAPI rfClientLock *sync.RWMutex = &sync.RWMutex{} serviceName string = "PCS-domain-transitions-test" DSP storage.StorageProvider @@ -67,7 +67,7 @@ func (ts *Transitions_TS) SetupSuite() { // StateManagerServer string credStoreGlob credstore.CREDSTORE_GLOBALS CS credstore.CredStoreProvider - BaseTRSTask trsapi.HttpTask + BaseTRSTask taskrun.HttpTask domainGlobals DOMAIN_GLOBALS ) @@ -98,9 +98,9 @@ func (ts *Transitions_TS) SetupSuite() { BaseTRSTask.Request.Header.Set("Content-Type", "application/json") BaseTRSTask.Request.Header.Add("HMS-Service", BaseTRSTask.ServiceName) - workerSec := &trsapi.TRSHTTPLocal{} + workerSec := &taskrun.TRSHTTPLocal{} workerSec.Logger = logger.Log - workerInsec := &trsapi.TRSHTTPLocal{} + workerInsec := &taskrun.TRSHTTPLocal{} workerInsec.Logger = logger.Log TLOC_rf = workerSec TLOC_svc = workerInsec diff --git a/internal/taskrun/models.go b/internal/taskrun/models.go new file mode 100644 index 00000000..a920b52a --- /dev/null +++ b/internal/taskrun/models.go @@ -0,0 +1,90 @@ +// MIT License +// +// (C) Copyright [2021,2024-2025] Hewlett Packard Enterprise Development LP +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +package taskrun + +import ( + "context" + "errors" + "net/http" + "time" + + "github.com/google/uuid" +) + +type RetryPolicy struct { + Retries int // number of retries to attempt (default is 3) + BackoffTimeout time.Duration // base backoff timeout between retries (default is 5 seconds) +} + +type HttpTxPolicy struct { + Enabled bool // policy enabled (default is false) + MaxIdleConns int // max idle connections across all hosts (default is 100) + MaxIdleConnsPerHost int // max idle connections per host (default is 2) + IdleConnTimeout time.Duration // duration an idle connection remains open (default is unlimited) + ResponseHeaderTimeout time.Duration // max wait time for a host's response header (default is unlimited) + TLSHandshakeTimeout time.Duration // max duration for the TLS handshake (default is 10 seconds) + DisableKeepAlives bool // disable HTTP keep-alives if true (default is false) +} + +type ClientPolicy struct { + Retry RetryPolicy // task's retry policy + Tx HttpTxPolicy // task's transport policy +} + +type HttpTask struct { + id uuid.UUID // message id + ServiceName string // name of the service (defaults to TRSHTTPLocal.svcName) + Request *http.Request // the http request + TimeStamp string // time the request was created/sent RFC3339Nano + Err *error // any error associated with the request + Timeout time.Duration // task's context timeout (default is 30 seconds) + CPolicy ClientPolicy // task's retry and transport policies + Ignore bool // if true, trs will ignore this task + context context.Context // task's context + contextCancel context.CancelFunc // task's context cancellation function + forceInsecure bool // if true, force insecure communication +} + +func (ht HttpTask) Validate() (valid bool, err error) { + if ht.TimeStamp == "" { + return false, errors.New("Timstamp is empty") + } else if ht.Request == nil { + return false, errors.New("Request is nil") + } else if ht.ServiceName == "" { + return false, errors.New("ServiceName is empty") + } else if ht.id == uuid.Nil { + return false, errors.New("ID is nil") + } + return true, nil +} + +func (ht *HttpTask) GetID() uuid.UUID { + return ht.id +} + +func (ht *HttpTask) SetIDIfNotPopulated() uuid.UUID { + if ht.id == uuid.Nil { + ht.id = uuid.New() + } + return ht.id +} diff --git a/internal/taskrun/models_test.go b/internal/taskrun/models_test.go new file mode 100644 index 00000000..4622ac5e --- /dev/null +++ b/internal/taskrun/models_test.go @@ -0,0 +1,93 @@ +// MIT License +// +// (C) Copyright [2021,2024] Hewlett Packard Enterprise Development LP +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +package taskrun + +import ( + "net/http" + "testing" + "time" + + "github.com/google/uuid" + "github.com/stretchr/testify/suite" +) + +type ModelsTS struct { + suite.Suite +} + +func GenerateStockHttpTask() HttpTask { + return HttpTask{ + id: uuid.New(), + ServiceName: "ServiceName", + Request: GenerateStockRequest(), + TimeStamp: time.Now().String(), + } +} + +func GenerateStockRequest() *http.Request { + req, _ := http.NewRequest("GET", "http://127.0.0.1", nil) + return req +} + +func (suite *ModelsTS) TestHttpTaskValidate_HappyPath() { + ht := GenerateStockHttpTask() + valid, err := ht.Validate() + suite.Equal(true, valid) + suite.Equal(nil, err) +} + +func (suite *ModelsTS) TestHttpTaskValidate_ErrorPath_NilID() { + ht := GenerateStockHttpTask() + ht.id = uuid.Nil + valid, err := ht.Validate() + suite.Equal(false, valid) + suite.True(err != nil) +} + +func (suite *ModelsTS) TestHttpTaskValidate_ErrorPath_EmptyTimestamp() { + ht := GenerateStockHttpTask() + ht.TimeStamp = "" + valid, err := ht.Validate() + suite.Equal(false, valid) + suite.True(err != nil) +} + +func (suite *ModelsTS) TestHttpTaskValidate_ErrorPath_EmptyServiceName() { + ht := GenerateStockHttpTask() + ht.ServiceName = "" + valid, err := ht.Validate() + suite.Equal(false, valid) + suite.True(err != nil) +} + +func (suite *ModelsTS) TestHttpTaskValidate_ErrorPath_NilRequest() { + ht := GenerateStockHttpTask() + ht.Request = nil + valid, err := ht.Validate() + suite.Equal(false, valid) + suite.True(err != nil) +} + +func TestModelApplicationSuite(t *testing.T) { + suite.Run(t, new(ModelsTS)) +} diff --git a/internal/taskrun/trshttp_interface.go b/internal/taskrun/trshttp_interface.go new file mode 100644 index 00000000..82432096 --- /dev/null +++ b/internal/taskrun/trshttp_interface.go @@ -0,0 +1,110 @@ +// MIT License +// +// (C) Copyright [2020-2022,2024-2025] Hewlett Packard Enterprise Development LP +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +package taskrun + +import ( + "context" + "crypto/tls" + "crypto/x509" + "sync" + "time" + + "github.com/google/uuid" + "github.com/hashicorp/go-retryablehttp" + "github.com/sirupsen/logrus" +) + +// Once there was Kafka stuff here, and now it is banished to the shadow realm, for it was never used. +// See https://github.com/Cray-HPE/hms-trs-app-api/blob/v3.0.6/README.md?plain=1#L20-L24 for original upstream code +// and some discussion of scaling limits. + +type TrsAPI interface { + Init(serviceName string, logger *logrus.Logger) error + SetSecurity(params interface{}) error + CreateTaskList(source *HttpTask, numTasks int) []HttpTask + Launch(taskList *[]HttpTask) (chan *HttpTask, error) + Check(taskList *[]HttpTask) (running bool, err error) + Cancel(taskList *[]HttpTask) + Close(taskList *[]HttpTask) + Alive() (ok bool, err error) + Cleanup() +} + +// Local operations + +type TRSHTTPLocalSecurity struct { + CACertBundleData string + ClientCertData string + ClientKeyData string +} + +type clientPack struct { + secure *retryablehttp.Client + insecure *retryablehttp.Client +} + +type TRSHTTPLocal struct { + Logger *logrus.Logger + svcName string + ctx context.Context + ctxCancelFunc context.CancelFunc + CACertPool *x509.CertPool + ClientCert tls.Certificate + clientMap map[ClientPolicy]*clientPack + clientMutex sync.Mutex + taskMap map[uuid.UUID]*taskChannelTuple + taskMutex sync.Mutex +} + +type taskChannelTuple struct { + taskListChannel chan *HttpTask + task *HttpTask +} + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +// Generic func to create a task array. Called by the interface methods +// with similar names. +// +// source: Ptr to source HTTP task descriptor. +// svcName: Service or application name. +// sender: Sender/k8s UUID name. Can be "". +// nitems: Number of elements to create in resulting task array. +// Return: Array of HTTP task descriptors. + +func createHTTPTaskArray(source *HttpTask, + nitems int) []HttpTask { + sarr := make([]HttpTask, nitems) + + for ii := 0; ii < nitems; ii++ { + sarr[ii] = *source + if sarr[ii].Request != nil { + sarr[ii].Request = source.Request.Clone(context.Background()) + } + sarr[ii].TimeStamp = time.Now().String() + sarr[ii].id = uuid.New() + } + + return sarr +} diff --git a/internal/taskrun/trshttp_local.go b/internal/taskrun/trshttp_local.go new file mode 100644 index 00000000..acfc0473 --- /dev/null +++ b/internal/taskrun/trshttp_local.go @@ -0,0 +1,785 @@ +// MIT License +// +// (C) Copyright [2020-2021,2024-2025] Hewlett Packard Enterprise Development LP +// +// Permission is hereby granted, free of charge, to any person obtaining a +// copy of this software and associated documentation files (the "Software"), +// to deal in the Software without restriction, including without limitation +// the rights to use, copy, modify, merge, publish, distribute, sublicense, +// and/or sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included +// in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL +// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR +// OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, +// ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. + +package taskrun + +import ( + "context" + "crypto/tls" + "crypto/x509" + "errors" + "fmt" + "io" + "net/http" + "runtime" + "sync" + "time" + + base "github.com/Cray-HPE/hms-base/v2" + "github.com/google/uuid" + "github.com/hashicorp/go-retryablehttp" + "github.com/sirupsen/logrus" +) + +const ( + DFLT_RETRY_MAX = 3 //default max # of retries on failure + DFLT_BACKOFF_MAX = 5 //default max seconds per retry + DFLT_CTX_TIMEOUT = 30 //default context timeout in seconds +) + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +// L O C A L I N T E R F A C E +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + +// Initialize the local HTTP task system. +// +// serviceName: Name of the service or application +// logger: The logger to use; if nil, a default logger is created +// +// Return: Nil on success; error string on failure + +func (tloc *TRSHTTPLocal) Init(serviceName string, logger *logrus.Logger) error { + if logger != nil { + tloc.Logger = logger + } else { + tloc.Logger = logrus.New() + } + + tloc.ctx, tloc.ctxCancelFunc = context.WithCancel(context.Background()) + + if tloc.taskMap == nil { + tloc.taskMutex.Lock() + tloc.taskMap = make(map[uuid.UUID]*taskChannelTuple) + tloc.taskMutex.Unlock() + } + if tloc.clientMap == nil { + tloc.clientMutex.Lock() + tloc.clientMap = make(map[ClientPolicy]*clientPack) + tloc.clientMutex.Unlock() + } + tloc.svcName = serviceName + + tloc.Logger.Tracef("Init() successful") + + return nil +} + +// Set up the local HTTP task system to use a CA cert bundle and optional +// client cert/key data. This is used to set up a secure connection to the +// target system. The CA cert bundle is required. The client cert/key data +// is optional. +// +// inParams: Pointer to a TRSHTTPLocalSecurity struct containing the CA cert +// bundle and optional client cert/key data. +// +// Return: Nil on success; error string on failure + +func (tloc *TRSHTTPLocal) SetSecurity(inParams interface{}) error { + params := inParams.(TRSHTTPLocalSecurity) + + if params.CACertBundleData == "" { + err := fmt.Errorf("CA cert bundle required.") + tloc.Logger.Errorf("SetSecurity(): %v", err) + return err + } + + tloc.CACertPool, _ = x509.SystemCertPool() + if tloc.CACertPool == nil { + tloc.CACertPool = x509.NewCertPool() + } + tloc.CACertPool.AppendCertsFromPEM([]byte(params.CACertBundleData)) + + if (params.ClientCertData != "") && (params.ClientKeyData != "") { + var err error + tloc.ClientCert, err = tls.X509KeyPair([]byte(params.ClientCertData), []byte(params.ClientKeyData)) + if err != nil { + tloc.Logger.Errorf("SetSecurity(): Error generating client cert: %v", + err) + return err + } + } + + tloc.Logger.Tracef("SetSecurity() successful") + + return nil +} + +// Create an array of task descriptors. Data is copied from the source task +// into each element of the returned array. Per-task data should then be +// populated by the caller after control returns. +// +// A unique message id and TimeStamp in each task is populated regardless of +// the value in the source. It is generated using a pseudo-random value in +// the upper 32 bits, which is the message group id, followed by a +// monotonically increasing value in the lower 32 bits, starting with 0, +// which functions as the message id. +// +// source: Pounter to a task descriptor populated with relevant data. The +// only fields that should be set by the caller are: +// - ServiceName +// - Request +// - Timeout +// - CPolicy +// - Ignore +// - forceInsecure +// numTasks: Number of elements in the array to be returned +// +// Return: Array of populated task descriptors + +func (tloc *TRSHTTPLocal) CreateTaskList(source *HttpTask, numTasks int) []HttpTask { + return createHTTPTaskArray(source, numTasks) +} + +// The retryablehttp module closes idle connections in an overly aggressive +// manner. If a single request experiences a timeout, all idle connections +// are closed. If a single requests exceeds all retries, all idle +// connections are closed. The following RoundTrip wrapper helps us +// wrap various retryablehttp and http interfaces to prevent this. + +type trsRoundTripper struct { + transport *http.Transport + closeIdleConnectionsFn func() + skipCloseCount uint64 + skipCloseMutex sync.Mutex + timeLastClosedOrReachedZeroCloseCount time.Time +} + +// Our RoundTripper(). Just call RoundTrip interface at next level down. +func (c *trsRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { + return c.transport.RoundTrip(req) +} + +// Our wrapper around the standard http.Client's CloseIdleConnections() +// We only call the interface at the next level down if skipCloseCount +// counter is zero. This counter is decremented by our CheckRetry +// wrapper (further below) if it detects a http timeout, context +// timeout, or retry limit exceeded for a request. +// +// There may be a hole in the logic whereby a request sets the skip +// counter but is then killed for whatever reason before it can call into +// this wrapper. This would leave the counter at non-zero forever. It +// would be very unlikely to happen, but logically possible. We guard +// against this by resetting the counter to zero if its been 2 hours since: +// +// * The last call to c.CloseIdleConnectionsFn() +// * The last time the c.skipCloseCount reached zero +// +// Prior to this change, the TRS module would ALWAYS closing all idle +// connections after every single http timeout, context timeout, or retry +// count exceeded condition. So, if we close out all the connections +// occasionally after a two hour period, not a big deal. +// +// WARNING! The Go runtime behavior surrounding connections has changed in +// more recent versions of Go. Prior to version 1.23, if any +// request experiences a timeout, the Go runtime closes ALL idle +// connections. There is nothing we can do about this in TRS, +// other than use a newer version of Go that doesn't exhibit this +// behavior. Issue is documented here: +// +// * https://github.com/golang/go/issues/59017 +// * https://github.com/golang/go/commit/334ce510046ad30b1be466634cf313aad3040892 +// +// Will attempt to jump to Go 1.23 with this commit. + +//var wrapperLogger *logrus.Logger // only uncomment if debugging wrapper issues + +func (c *trsRoundTripper) CloseIdleConnections() { + // Skip closing idle connections if counter > 0 + + c.skipCloseMutex.Lock() + if c.skipCloseCount > 0 { + c.skipCloseCount-- + + if c.skipCloseCount == 0 { + // Mark the time the counter last reached zero + c.timeLastClosedOrReachedZeroCloseCount = time.Now() + } + + if time.Since(c.timeLastClosedOrReachedZeroCloseCount) > (2 * time.Hour) { + // If its been two hours since we last closed idle connections + // or since the counter last reached zero, reset the counter to + // zero and proceed to close idle connections + + c.skipCloseCount = 0 + + // Time will be marked below when we close idle connections + } else { + c.skipCloseMutex.Unlock() + + return + } + } + + // Continue holding mutex until skipCloseCountResetTime is updated + + if c.closeIdleConnectionsFn == nil { + // Nothing to do so release mutex + c.skipCloseMutex.Unlock() + + } else { + // Mark the time of this call to close connections + c.timeLastClosedOrReachedZeroCloseCount = time.Now() + + c.skipCloseMutex.Unlock() + + // Call next level down + c.closeIdleConnectionsFn() + } +} + +// Custom request wrapper that includes a retry counter that we'll use to +// determine whether or not to close idle connections +type trsWrappedReq struct { + orig *http.Request // request we're wrapping + retryMax int // retry max from request + retryCount int // retry count for this request +} + +// drainAndCloseBody is a simple helper function reused in many places + +func drainAndCloseBody(resp *http.Response) { + if resp != nil && resp.Body != nil { + _, _ = io.Copy(io.Discard, resp.Body) // Drain the body + resp.Body.Close() // Close the body + resp.Body = nil // Prevent double-handling + } +} + +// Our wrapper around retryablehttp's CheckRetry(). if we detect an http +// timeout, context timeout, or a retry limit exceeded for a request, then +// we decrement the skipCloseCount counter so that the next time our +// CloseIdleConnections() wrapper is called, it skips calling the lower +// level system version that actually closes idle connections. + +type retryKey string // avoids compiler warning +var trsRetryCountKey retryKey = "trsRetryCount" + +func (c *trsRoundTripper) trsCheckRetry(ctx context.Context, resp *http.Response, err error) (bool, error) { + + // Skip a retry for this request if it hit one of these specific timeouts + + if err != nil { + c.skipCloseMutex.Lock() + + // Skip retries for HTTPClient.Timeout + if err.Error() == "net/http: request canceled" { + c.skipCloseCount++ + + c.skipCloseMutex.Unlock() + + // retryablehttp will close any response bodies on retry skip + error + + return false, err // skip it + } + + // Context timeout set by TRS. No request should retry. + if errors.Is(err, context.DeadlineExceeded) { + c.skipCloseCount++ + + c.skipCloseMutex.Unlock() + + // retryablehttp will close any response bodies on retry skip + error + + return false, err // skip it + } + + // Lower level HTTPClient.Timeout triggered timeouts + // + // Unsure if this is wise so I left it commented out. If these + // happen they don't happen very much so closing all idle + // connections when they do happen is not a big deal. + // + // if netErr, ok := err.(net.Error); ok && netErr.Timeout() { + // c.skipCloseCount++ + // + // c.skipCloseMutex.Unlock() + // + // wrapperLogger.Errorf("trsCheckRetry: skipCloseCount now %v (ctx timeout)", c.skipCloseCount) + // + // // retryablehttp will close any response bodies on retry skip + error + // + // return false, err // skip it + // } + + c.skipCloseMutex.Unlock() + + } + + // If none of the above, delegate retry check to retryablehttp + shouldRetry, defaultRPErr := retryablehttp.DefaultRetryPolicy(ctx, resp, err) + + // Determine if we should override DefaultRetryPolicy()'s opinion + if shouldRetry { + // This is our own personal copy of the retry counter for this + // request. Let's increment it then compare to the retry limit + + trsWR := ctx.Value(trsRetryCountKey).(*trsWrappedReq) + trsWR.retryCount++ + + // If the retry limit was reached we do not want to close all idle + // connections unnecessarily so imcrement skipCloseCount counter so + // that our CloseIdleConnections() wrapper skips the next one + + if trsWR.retryCount > trsWR.retryMax { + // If no error present, let's give the caller the underlying + // reason why retries were exhausted, if we can determine it + if err == nil { + if resp != nil { + err = fmt.Errorf("retries exhausted: last attempt received status %d (%s)", + resp.StatusCode, http.StatusText(resp.StatusCode)) + } else { + err = fmt.Errorf("retries exhausted") + } + } + + // Skip an idle connection close + c.skipCloseMutex.Lock() + c.skipCloseCount++ + c.skipCloseMutex.Unlock() + + // retryablehttp will close any response bodies on retry skip + error + + return false, err + } + } + + return shouldRetry, defaultRPErr +} + +// Create and configure a new client transport for use with HTTP clients. +func createClient(task *HttpTask, tloc *TRSHTTPLocal, clientType string) (client *retryablehttp.Client) { + // Configure the base transport + + tr := &http.Transport{} + + if clientType == "insecure" { + tr.TLSClientConfig = &tls.Config{ + InsecureSkipVerify: true, + } + } else { // secure + tr.TLSClientConfig = &tls.Config{ + RootCAs: tloc.CACertPool, + } + tr.TLSClientConfig.BuildNameToCertificate() + } + + // Configure base transport policies if requested + httpTxPolicy := task.CPolicy.Tx + if httpTxPolicy.Enabled { + tr.MaxIdleConns = httpTxPolicy.MaxIdleConns // if 0 defaults to 100 + tr.MaxIdleConnsPerHost = httpTxPolicy.MaxIdleConnsPerHost // if 0 defaults to 2 + tr.IdleConnTimeout = httpTxPolicy.IdleConnTimeout // if 0 defaults to no timeout + tr.ResponseHeaderTimeout = httpTxPolicy.ResponseHeaderTimeout // if 0 defaults to no timeout + tr.TLSHandshakeTimeout = httpTxPolicy.TLSHandshakeTimeout // if 0 defaults to 10s + tr.DisableKeepAlives = httpTxPolicy.DisableKeepAlives // if 0 defaults to false + } + + // Wrap base transport with retryablehttp + retryabletr := &trsRoundTripper{ + transport: tr, + closeIdleConnectionsFn: tr.CloseIdleConnections, + timeLastClosedOrReachedZeroCloseCount: time.Now(), + } + + // Create the httpretryable client and start configuring it + client = retryablehttp.NewClient() + + client.HTTPClient.Transport = retryabletr + + // We could set a global http timeout for all users of the client but + // that's a bit inflexible. Let's keep it at the default (unlimited) + // and use the user provided context timeout to limit the request. + // The context timeout they provide could be different from caller to + // caller as well. + // + //client.HTTPClient.Timeout = task.Timeout * 9 / 10 + + // Wrap httpretryable's DefaultRetryPolicy() so we can override + client.CheckRetry = retryabletr.trsCheckRetry + + // Configure the httpretryable client retry count + if task.CPolicy.Retry.Retries >= 0 { + client.RetryMax = task.CPolicy.Retry.Retries + } else { + client.RetryMax = DFLT_RETRY_MAX + } + + // Configure the httpretryable client backoff timeout + if task.CPolicy.Retry.BackoffTimeout > 0 { + client.RetryWaitMax = task.CPolicy.Retry.BackoffTimeout + } else { + client.RetryWaitMax = DFLT_BACKOFF_MAX * time.Second + } + + // Log this client's requested configuration and actual configuration + + tloc.Logger.Tracef("Created %s TRS client", clientType) + tloc.Logger.Tracef(" CPolicy request: %v", task.CPolicy) + tloc.Logger.Tracef(" RetryMax: %v", client.RetryMax) + tloc.Logger.Tracef(" RetryWaitMax: %v", client.RetryWaitMax) + tloc.Logger.Tracef(" task.Timeout: %v", task.Timeout) + tloc.Logger.Tracef(" HTTPClient.Timeout: %v", client.HTTPClient.Timeout) + + if httpTxPolicy.Enabled { + tloc.Logger.Tracef(" tx.MaxIdleConns: %v", tr.MaxIdleConns) + tloc.Logger.Tracef(" tx.MaxIdleConnsPerHost: %v", tr.MaxIdleConnsPerHost) + tloc.Logger.Tracef(" tx.IdleConnTimeout: %v", tr.IdleConnTimeout) + tloc.Logger.Tracef(" tx.ResponseHeaderTimeout: %v", tr.ResponseHeaderTimeout) + tloc.Logger.Tracef(" tx.TLSHandshakeTimeout: %v", tr.TLSHandshakeTimeout) + tloc.Logger.Tracef(" tx.DisableKeepAlives: %v", tr.DisableKeepAlives) + } + + tloc.Logger.Tracef(" Client pair count: %v", len(tloc.clientMap)+1) + tloc.Logger.Tracef(" Log level: %v", tloc.Logger.GetLevel()) + tloc.Logger.Tracef(" Go version: %v", runtime.Version()) + + return client +} + +// Reference: https://pkg.go.dev/github.com/hashicorp/go-retryablehttp + +func ExecuteTask(tloc *TRSHTTPLocal, tct taskChannelTuple) { + + // Find a client to use, or make a new one! + + var cpack *clientPack + tloc.clientMutex.Lock() + if _, ok := tloc.clientMap[tct.task.CPolicy]; !ok { + cpack = new(clientPack) + + cpack.insecure = createClient(tct.task, tloc, "insecure") + + // Do not use leveled logging for now. See explanation further + // up in the source code. Instead, use standard logger set at + // error level to avoid excessive logging + // + //httpLogger := logrus.New() + //httpLogger.SetLevel(tloc.Logger.GetLevel()) + //retryablehttpLogger := retryablehttp.LeveledLogger(&leveledLogrus{httpLogger}) + //cpack.insecure.Logger = retryablehttpLogger + + httpLogger := logrus.New() + httpLogger.SetLevel(logrus.ErrorLevel) + cpack.insecure.Logger = httpLogger + + if tloc.CACertPool != nil { + cpack.secure = createClient(tct.task, tloc, "secure") + + //cpack.secure.Logger = retryablehttpLogger + cpack.secure.Logger = httpLogger + } + + tloc.clientMap[tct.task.CPolicy] = cpack + } else { + cpack = tloc.clientMap[tct.task.CPolicy] + } + tloc.clientMutex.Unlock() + + // Found a client to use (or created a new one), now set up a request + + // First validate our task + if ok, err := tct.task.Validate(); !ok { + tloc.Logger.Errorf("Failed validation of request: %+v, err: %s", tct.task, err) + tct.task.Err = &err + tct.taskListChannel <- tct.task + return + } + + // Add user agent header to the request + base.SetHTTPUserAgent(tct.task.Request, tloc.svcName) + + // Wrap the request so trsCheckRetry() can keep its own retry count + // We'll attach this to the context further below so that it has access + // to it + trsWR := &trsWrappedReq{ + orig: tct.task.Request, // Core request + retryCount: 0, // Counter for CLIC() + retryMax: cpack.insecure.RetryMax, // CLIC() will need access to this + // same for both secure & insecure + } + + // Create child context with timeout and our own retry counter + + ctxTimeout := time.Duration(DFLT_CTX_TIMEOUT * time.Second) + if tct.task.Timeout > 0 { + ctxTimeout = tct.task.Timeout + } + + baseCtx, cancel := context.WithTimeout(tloc.ctx, ctxTimeout) + ctxWithValue := context.WithValue(baseCtx, trsRetryCountKey, trsWR) + + tct.task.context = ctxWithValue + tct.task.contextCancel = cancel + + // Create a retryablehttp request using the caller's request + req, err := retryablehttp.FromRequest(tct.task.Request) + if err != nil { + tloc.Logger.Errorf("Failed wrapping request with retryablehttp: %v", err) + tct.task.Err = &err + tct.taskListChannel <- tct.task + return + } + + // Link retryablehttp's request context to the task's context + req.Request = req.Request.WithContext(tct.task.context) + + // Execute the request + var tmpError error + if tct.task.forceInsecure || tloc.CACertPool == nil || cpack.secure == nil { + tloc.Logger.Tracef("Using INSECURE client to send request") + tct.task.Request.Response, tmpError = cpack.insecure.Do(req) + } else { + tloc.Logger.Tracef("Using secure client to send request") + tct.task.Request.Response, tmpError = cpack.secure.Do(req) + + // Fall back to insecure only if the enclosing context was not + // cancelled or timed out. + if tmpError != nil && tct.task.context.Err() == nil { + // But first make sure we drain/close the body of the failed + // response, if there was one + drainAndCloseBody(tct.task.Request.Response) + + tloc.Logger.Warnf("TLS request failed, retrying using INSECURE client (TLS failure: '%v')", tmpError) + tct.task.Request.Response, tmpError = cpack.insecure.Do(req) + } + } + + tct.task.Err = &tmpError + if (*tct.task.Err) != nil { + tloc.Logger.Tracef("Request failed: %s", (*tct.task.Err).Error()) + } + if tct.task.Request.Response != nil { + tloc.Logger.Tracef("Response: %d", tct.task.Request.Response.StatusCode) + } else { + tloc.Logger.Tracef("No response received") + } + + // TODO: Consider cancelling the context for this task here instead of + // leaving it up to the caller - Would have to read and close response + // here as well + + tct.taskListChannel <- tct.task +} + +// Launch an array of tasks. This is non-blocking. The caller can use +// either the returned Go channel or Check() to check for compleetion. The +// caller should close all HTTP response bodies after they are received and +// processed and close the returned Go channel when done. +// +// taskList: Pointer to a list of HTTP tasks to launch +// +// Return: +// +// chan: A Go channel of *HttpTxTask, sized by task list, which caller can +// use to get notified of each task's completion. The caller MUST +// CLOSE THE CHANNEL WHEN DONE even if using Done() to check for +// completion. +// error: Nil on success; error string on failure + +func (tloc *TRSHTTPLocal) Launch(taskList *[]HttpTask) (chan *HttpTask, error) { + if len(*taskList) == 0 { + rchan := make(chan *HttpTask, 1) + err := fmt.Errorf("Empty task list, nothing to do.") + return rchan, err + } + + //Set all time stamps + taskListChannel := make(chan *HttpTask, len(*taskList)) + + for ii := 0; ii < len(*taskList); ii++ { + if (*taskList)[ii].Ignore == true { + continue + } + + //Always set the response to nil; make sure its clean. + //Add user-agent header. + if (*taskList)[ii].Request != nil { + (*taskList)[ii].Request.Response = nil + base.SetHTTPUserAgent((*taskList)[ii].Request, tloc.svcName) + } + //make sure the id is set + (*taskList)[ii].SetIDIfNotPopulated() + + //make sure the service name is set + if (*taskList)[ii].ServiceName == "" { + (*taskList)[ii].ServiceName = tloc.svcName + } + + //make sure the timestamp is set + if (*taskList)[ii].TimeStamp == "" { + (*taskList)[ii].TimeStamp = time.Now().Format(time.RFC3339Nano) + } + + //Setup the channel stuff + tct := taskChannelTuple{ + taskListChannel: taskListChannel, + task: &(*taskList)[ii], + } + tloc.taskMutex.Lock() + tloc.taskMap[(*taskList)[ii].id] = &tct + tloc.taskMutex.Unlock() + + // pass the Tloc (so it can find a client) + the task channel tuple (so it knows what to do); + // let it execute! + go ExecuteTask(tloc, tct) + } + + tloc.Logger.Tracef("Launch() completed") + + return taskListChannel, nil +} + +// Check the status of the launched task list. This is an alternative to +// waiting on the task-complete channel returned by Launch(). +// +// taskList: Pointer to the task list +// +// Return: +// +// bool: True or false if the task list is still running +// error: Nil on success; error string on failure + +func (tloc *TRSHTTPLocal) Check(taskList *[]HttpTask) (bool, error) { + if taskList != nil { + for _, v := range *taskList { + if v.Ignore == false { + if v.Request.Response == nil && v.Err == nil { + return true, nil + } + } + } + } + return false, nil +} + +// Check the health of the local HTTP task launch system. +// +// Return: +// +// bool: True or false if alive and operational +// error: Error message associated with non-alive/functional state + +func (tloc *TRSHTTPLocal) Alive() (bool, error) { + if tloc.taskMap == nil { + return false, errors.New("taskMap is nil") + } + return true, nil +} + +// Cancel a currently-running task set. Note that this won't kill +// the individual in-flight tasks, but just kills the overall operation. +// Thus, for tasks with no time-out which are hung, it could result in +// a resource leak. But this can be used to at least wrestle control +// over a task set. +// +// taskList: Pointer to the task list to cancel + +func (tloc *TRSHTTPLocal) Cancel(taskList *[]HttpTask) { + if taskList != nil { + for _, v := range *taskList { + if v.Ignore == false { + v.contextCancel() + } + } + } + tloc.Logger.Tracef("Cancel() completed") +} + +// Close out a task list transaction. This frees up resources so it +// should not be skipped. +// +// taskList: Pointer to the task list to close + +func (tloc *TRSHTTPLocal) Close(taskList *[]HttpTask) { + if taskList != nil { + for _, v := range *taskList { + if v.Ignore == false { + // The caller should have closed the response body, but we'll also + // do it here to prevent resource leaks. Note that if that was + // the case, that connection was closed by the above cancel. + + drainAndCloseBody(v.Request.Response) + + // All tasks must be cancelled to prevent resource leaks. The + // caller may have called Cancel() to prematurely cancel the + // operation, but that's probably not a common thing so we will + // do it here. There is no harm in cancelling twice. We must + // do this before closing the response body. + // + // TODO: We may also want to consider having each go routine + // call cancel above in ExecuteTask() for themselves. Doing it + // like that might be less error prone. + + v.contextCancel() + } + tloc.taskMutex.Lock() + delete(tloc.taskMap, v.id) + tloc.taskMutex.Unlock() + + } + } + + tloc.Logger.Tracef("Close() completed") +} + +// Clean up a local HTTP task system. This is called when after it will no +// longer be used. + +func (tloc *TRSHTTPLocal) Cleanup() { + //Just call the cancel func. + tloc.ctxCancelFunc() + + //clean up client map? + if tloc.clientMap != nil { + for k := range tloc.clientMap { + //cancel it first + if tloc.clientMap[k].insecure != nil { + tloc.clientMap[k].insecure.HTTPClient.CloseIdleConnections() + } + if tloc.clientMap[k].secure != nil { + tloc.clientMap[k].secure.HTTPClient.CloseIdleConnections() + } + //delete it out of the map + tloc.clientMutex.Lock() + delete(tloc.clientMap, k) + tloc.clientMutex.Unlock() + } + } + + //clean up task map + if tloc.taskMap != nil { + for k := range tloc.taskMap { + //cancel it first + tloc.taskMap[k].task.contextCancel() + //close the channel + close(tloc.taskMap[k].taskListChannel) + //delete it out of the map + tloc.taskMutex.Lock() + delete(tloc.taskMap, k) + tloc.taskMutex.Unlock() + } + } + tloc.Logger.Tracef("Cleanup() completed") + // this really just a big red button to STOP ALL? b/c im not clearing any memory +} diff --git a/internal/taskrun/trshttp_local_test.go b/internal/taskrun/trshttp_local_test.go new file mode 100644 index 00000000..012c7bff --- /dev/null +++ b/internal/taskrun/trshttp_local_test.go @@ -0,0 +1,214 @@ +package taskrun + +import ( + "encoding/pem" + "flag" + "log" + "net/http" + "net/http/httptest" + "os" + "sync/atomic" + "testing" + "time" + + "github.com/sirupsen/logrus" +) + +var logLevel logrus.Level + +func TestMain(m *testing.M) { + var logLevelInt int + flag.IntVar(&logLevelInt, "logLevel", int(logrus.ErrorLevel), + "set log level (0=Panic, 1=Fatal, 2=Error 3=Warn, 4=Info, 5=Debug, 6=Trace)") + flag.Parse() + logLevel = logrus.Level(logLevelInt) + log.Printf("logLevel set to %v", logLevel) + os.Exit(m.Run()) +} + +func createLogger() *logrus.Logger { + l := logrus.New() + l.SetFormatter(&logrus.TextFormatter{FullTimestamp: true}) + l.SetLevel(logrus.Level(logLevel)) + l.SetReportCaller(true) + return l +} + +var svcName = "TestMe" + +func TestInit(t *testing.T) { + tloc := &TRSHTTPLocal{} + tloc.Init(svcName, createLogger()) + if tloc.taskMap == nil { + t.Errorf("failed to create task map") + } + if tloc.clientMap == nil { + t.Errorf("failed to create client map") + } + if tloc.svcName != svcName { + t.Errorf("failed to set service name") + } +} + +// launchHandler handles requests for the test HTTP servers. Depending on +// request headers it can return 503 for retry testing, stall until signalled, +// or return 200 immediately. + +var handlerLogger *testing.T +var handlerSleep int = 2 +var retrySleep int = 0 +var nRetries int32 = 0 + +func launchHandler(w http.ResponseWriter, req *http.Request) { + singletonRetry := false + alwaysFail := req.Header.Get("Trs-Fail-All-Retries") != "" + + if !alwaysFail { + singletonRetry = atomic.AddInt32(&nRetries, -1) >= 0 + } + + if singletonRetry || alwaysFail { + if singletonRetry { + atomic.AddInt32(&nRetries, -1) + } + time.Sleep(time.Duration(retrySleep) * time.Second) + retrySleep = 0 + w.Header().Set("Content-Type", "application/json") + w.Header().Set("Retry-After", "1") + w.WriteHeader(http.StatusServiceUnavailable) + w.Write([]byte(`{"Message":"Service Unavailable"}`)) + return + } + + if req.Header.Get("Trs-Context-Timeout") != "" { + stallHandler(w, req) + return + } + + time.Sleep(time.Duration(handlerSleep) * time.Second) + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"Message":"OK"}`)) +} + +var stallCancel chan bool + +func stallHandler(w http.ResponseWriter, req *http.Request) { + time.Sleep(100 * time.Millisecond) + <-stallCancel + w.Header().Set("Content-Type", "application/json") + w.WriteHeader(http.StatusOK) + w.Write([]byte(`{"Message":"OK"}`)) +} + +func TestLaunch(t *testing.T) { + testLaunch(t, 5, false, false, 8) +} + +func TestSecureLaunch(t *testing.T) { + testLaunch(t, 1, true, false, 8) +} + +func TestSecureLaunchBadCert(t *testing.T) { + // Despite the cert being bad, TRS falls back to the insecure client and succeeds. + testLaunch(t, 1, true, true, 8) +} + +func TestLaunchZeroTimeout(t *testing.T) { + // Zero should cause the default timeout to be applied; if not, the test hangs. + testLaunch(t, 5, false, false, 0) +} + +func testLaunch(t *testing.T, numTasks int, testSecure bool, useBadCert bool, timeout time.Duration) { + tloc := &TRSHTTPLocal{} + tloc.Init(svcName, createLogger()) + + var srv *httptest.Server + if testSecure { + srv = httptest.NewTLSServer(http.HandlerFunc(launchHandler)) + certData := "BAD CERT" + if !useBadCert { + certData = string(pem.EncodeToMemory( + &pem.Block{Type: "CERTIFICATE", Bytes: srv.Certificate().Raw}, + )) + } + if err := tloc.SetSecurity(TRSHTTPLocalSecurity{CACertBundleData: certData}); err != nil { + t.Errorf("SetSecurity() failed: %v", err) + return + } + } else { + srv = httptest.NewServer(http.HandlerFunc(launchHandler)) + } + defer srv.Close() + + handlerLogger = t + + req, _ := http.NewRequest("GET", srv.URL, nil) + tproto := HttpTask{Request: req, Timeout: timeout * time.Second} + tList := tloc.CreateTaskList(&tproto, numTasks) + + tch, err := tloc.Launch(&tList) + if err != nil { + t.Errorf("Launch() failed: %v", err) + } + + nDone, nErr := 0, 0 + for { + tdone := <-tch + nDone++ + if tdone == nil { + t.Errorf("Launch chan returned nil ptr") + } else if tdone.Request == nil { + t.Errorf("Launch chan returned nil Request") + } else if tdone.Request.Response == nil { + t.Errorf("Launch chan returned nil Response") + } else { + if tdone.Request.Response.StatusCode != http.StatusOK { + t.Errorf("Launch chan returned bad status: %v", tdone.Request.Response.StatusCode) + nErr++ + } + if tdone.Err != nil && *tdone.Err != nil { + t.Errorf("Launch chan returned error: %v", *tdone.Err) + } + } + if nDone == len(tList) { + break + } + } + + if nErr != 0 { + t.Errorf("Got %d errors from Launch", nErr) + } +} + +func TestLaunchTimeout(t *testing.T) { + tloc := &TRSHTTPLocal{} + tloc.Init(svcName, createLogger()) + srv := httptest.NewServer(http.HandlerFunc(stallHandler)) + defer srv.Close() + + handlerLogger = t + + req, _ := http.NewRequest("GET", srv.URL, nil) + tproto := HttpTask{ + Request: req, + Timeout: 3 * time.Second, + CPolicy: ClientPolicy{ + Retry: RetryPolicy{Retries: 1, BackoffTimeout: 3 * time.Second}, + }, + } + tList := tloc.CreateTaskList(&tproto, 1) + stallCancel = make(chan bool, 1) + + tch, err := tloc.Launch(&tList) + if err != nil { + t.Errorf("Launch() failed: %v", err) + } + time.Sleep(100 * time.Millisecond) + + for range tList { + <-tch + stallCancel <- true + } + close(stallCancel) +}