mirror of
https://github.com/kyverno/kyverno.git
synced 2025-03-31 03:45:17 +00:00
fix: context in api call (#6885)
Signed-off-by: Charles-Edouard Brétéché <charles.edouard@nirmata.com>
This commit is contained in:
parent
2d64cdf6e2
commit
f7f3bc79d2
3 changed files with 41 additions and 39 deletions
|
@ -90,11 +90,11 @@ func LoadImageData(ctx context.Context, rclient registryclient.Client, logger lo
|
|||
}
|
||||
|
||||
func LoadAPIData(ctx context.Context, logger logr.Logger, entry kyvernov1.ContextEntry, enginectx enginecontext.Interface, client dclient.Interface) error {
|
||||
executor, err := apicall.New(ctx, entry, enginectx, client, logger)
|
||||
executor, err := apicall.New(logger, entry, enginectx, client)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to initialize APICall: %w", err)
|
||||
}
|
||||
if _, err := executor.Execute(); err != nil {
|
||||
if _, err := executor.Execute(ctx); err != nil {
|
||||
return fmt.Errorf("failed to execute APICall: %w", err)
|
||||
}
|
||||
return nil
|
||||
|
|
|
@ -2,7 +2,7 @@ package apicall
|
|||
|
||||
import (
|
||||
"bytes"
|
||||
goctx "context"
|
||||
"context"
|
||||
"crypto/tls"
|
||||
"crypto/x509"
|
||||
"encoding/json"
|
||||
|
@ -14,40 +14,42 @@ import (
|
|||
"github.com/go-logr/logr"
|
||||
kyvernov1 "github.com/kyverno/kyverno/api/kyverno/v1"
|
||||
"github.com/kyverno/kyverno/pkg/clients/dclient"
|
||||
"github.com/kyverno/kyverno/pkg/engine/context"
|
||||
enginecontext "github.com/kyverno/kyverno/pkg/engine/context"
|
||||
"github.com/kyverno/kyverno/pkg/engine/jmespath"
|
||||
"github.com/kyverno/kyverno/pkg/engine/variables"
|
||||
)
|
||||
|
||||
type apiCall struct {
|
||||
log logr.Logger
|
||||
logger logr.Logger
|
||||
entry kyvernov1.ContextEntry
|
||||
ctx goctx.Context
|
||||
jsonCtx context.Interface
|
||||
jsonCtx enginecontext.Interface
|
||||
client dclient.Interface
|
||||
}
|
||||
|
||||
func New(ctx goctx.Context, entry kyvernov1.ContextEntry, jsonCtx context.Interface, client dclient.Interface, log logr.Logger) (*apiCall, error) {
|
||||
func New(
|
||||
log logr.Logger,
|
||||
entry kyvernov1.ContextEntry,
|
||||
jsonCtx enginecontext.Interface,
|
||||
client dclient.Interface,
|
||||
) (*apiCall, error) {
|
||||
if entry.APICall == nil {
|
||||
return nil, fmt.Errorf("missing APICall in context entry %v", entry)
|
||||
}
|
||||
|
||||
return &apiCall{
|
||||
ctx: ctx,
|
||||
entry: entry,
|
||||
jsonCtx: jsonCtx,
|
||||
client: client,
|
||||
log: log,
|
||||
logger: log,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (a *apiCall) Execute() ([]byte, error) {
|
||||
call, err := variables.SubstituteAllInType(a.log, a.jsonCtx, a.entry.APICall)
|
||||
func (a *apiCall) Execute(ctx context.Context) ([]byte, error) {
|
||||
call, err := variables.SubstituteAllInType(a.logger, a.jsonCtx, a.entry.APICall)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context entry %s %s: %v", a.entry.Name, a.entry.APICall.URLPath, err)
|
||||
}
|
||||
|
||||
data, err := a.execute(call)
|
||||
data, err := a.execute(ctx, call)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -60,25 +62,25 @@ func (a *apiCall) Execute() ([]byte, error) {
|
|||
return result, nil
|
||||
}
|
||||
|
||||
func (a *apiCall) execute(call *kyvernov1.APICall) ([]byte, error) {
|
||||
func (a *apiCall) execute(ctx context.Context, call *kyvernov1.APICall) ([]byte, error) {
|
||||
if call.URLPath != "" {
|
||||
return a.executeK8sAPICall(call.URLPath)
|
||||
return a.executeK8sAPICall(ctx, call.URLPath)
|
||||
}
|
||||
|
||||
return a.executeServiceCall(call.Service)
|
||||
return a.executeServiceCall(ctx, call.Service)
|
||||
}
|
||||
|
||||
func (a *apiCall) executeK8sAPICall(path string) ([]byte, error) {
|
||||
jsonData, err := a.client.RawAbsPath(a.ctx, path)
|
||||
func (a *apiCall) executeK8sAPICall(ctx context.Context, path string) ([]byte, error) {
|
||||
jsonData, err := a.client.RawAbsPath(ctx, path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get resource with raw url\n: %s: %v", path, err)
|
||||
}
|
||||
|
||||
a.log.V(4).Info("executed APICall", "name", a.entry.Name, "len", len(jsonData))
|
||||
a.logger.V(4).Info("executed APICall", "name", a.entry.Name, "len", len(jsonData))
|
||||
return jsonData, nil
|
||||
}
|
||||
|
||||
func (a *apiCall) executeServiceCall(service *kyvernov1.ServiceCall) ([]byte, error) {
|
||||
func (a *apiCall) executeServiceCall(ctx context.Context, service *kyvernov1.ServiceCall) ([]byte, error) {
|
||||
if service == nil {
|
||||
return nil, fmt.Errorf("missing service for APICall %s", a.entry.Name)
|
||||
}
|
||||
|
@ -88,7 +90,7 @@ func (a *apiCall) executeServiceCall(service *kyvernov1.ServiceCall) ([]byte, er
|
|||
return nil, err
|
||||
}
|
||||
|
||||
req, err := a.buildHTTPRequest(service)
|
||||
req, err := a.buildHTTPRequest(ctx, service)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to build HTTP request for APICall %s: %w", a.entry.Name, err)
|
||||
}
|
||||
|
@ -113,11 +115,11 @@ func (a *apiCall) executeServiceCall(service *kyvernov1.ServiceCall) ([]byte, er
|
|||
return nil, fmt.Errorf("failed to read data from APICall %s: %w", a.entry.Name, err)
|
||||
}
|
||||
|
||||
a.log.Info("executed service APICall", "name", a.entry.Name, "len", len(body))
|
||||
a.logger.Info("executed service APICall", "name", a.entry.Name, "len", len(body))
|
||||
return body, nil
|
||||
}
|
||||
|
||||
func (a *apiCall) buildHTTPRequest(service *kyvernov1.ServiceCall) (req *http.Request, err error) {
|
||||
func (a *apiCall) buildHTTPRequest(ctx context.Context, service *kyvernov1.ServiceCall) (req *http.Request, err error) {
|
||||
token := a.getToken()
|
||||
defer func() {
|
||||
if token != "" && req != nil {
|
||||
|
@ -126,7 +128,7 @@ func (a *apiCall) buildHTTPRequest(service *kyvernov1.ServiceCall) (req *http.Re
|
|||
}()
|
||||
|
||||
if service.Method == "GET" {
|
||||
req, err = http.NewRequest("GET", service.URL, nil)
|
||||
req, err = http.NewRequestWithContext(ctx, "GET", service.URL, nil)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -147,7 +149,7 @@ func (a *apiCall) getToken() string {
|
|||
fileName := "/var/run/secrets/kubernetes.io/serviceaccount/token"
|
||||
b, err := os.ReadFile(fileName)
|
||||
if err != nil {
|
||||
a.log.Info("failed to read service account token", "path", fileName)
|
||||
a.logger.Info("failed to read service account token", "path", fileName)
|
||||
return ""
|
||||
}
|
||||
|
||||
|
@ -198,7 +200,7 @@ func (a *apiCall) transformAndStore(jsonData []byte) ([]byte, error) {
|
|||
return jsonData, nil
|
||||
}
|
||||
|
||||
path, err := variables.SubstituteAll(a.log, a.jsonCtx, a.entry.APICall.JMESPath)
|
||||
path, err := variables.SubstituteAll(a.logger, a.jsonCtx, a.entry.APICall.JMESPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to substitute variables in context entry %s JMESPath %s: %w", a.entry.Name, a.entry.APICall.JMESPath, err)
|
||||
}
|
||||
|
@ -218,7 +220,7 @@ func (a *apiCall) transformAndStore(jsonData []byte) ([]byte, error) {
|
|||
return nil, fmt.Errorf("failed to add APICall results for context entry %s: %w", a.entry.Name, err)
|
||||
}
|
||||
|
||||
a.log.V(4).Info("added context data", "name", a.entry.Name, "len", len(contextData))
|
||||
a.logger.V(4).Info("added context data", "name", a.entry.Name, "len", len(contextData))
|
||||
return contextData, nil
|
||||
}
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ func Test_serviceGetRequest(t *testing.T) {
|
|||
entry := kyvernov1.ContextEntry{}
|
||||
ctx := enginecontext.NewContext()
|
||||
|
||||
_, err := New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
_, err := New(logr.Discard(), entry, ctx, nil)
|
||||
assert.ErrorContains(t, err, "missing APICall")
|
||||
|
||||
entry.Name = "test"
|
||||
|
@ -50,22 +50,22 @@ func Test_serviceGetRequest(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
call, err := New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
call, err := New(logr.Discard(), entry, ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = call.Execute()
|
||||
_, err = call.Execute(context.TODO())
|
||||
assert.ErrorContains(t, err, "invalid request type")
|
||||
|
||||
entry.APICall.Service.Method = "GET"
|
||||
call, err = New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
call, err = New(logr.Discard(), entry, ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
_, err = call.Execute()
|
||||
_, err = call.Execute(context.TODO())
|
||||
assert.ErrorContains(t, err, "HTTP 404")
|
||||
|
||||
entry.APICall.Service.URL = s.URL + "/resource"
|
||||
call, err = New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
call, err = New(logr.Discard(), entry, ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
|
||||
data, err := call.Execute()
|
||||
data, err := call.Execute(context.TODO())
|
||||
assert.NilError(t, err)
|
||||
assert.Assert(t, data != nil, "nil data")
|
||||
assert.Equal(t, string(serverResponse), string(data))
|
||||
|
@ -87,9 +87,9 @@ func Test_servicePostRequest(t *testing.T) {
|
|||
}
|
||||
|
||||
ctx := enginecontext.NewContext()
|
||||
call, err := New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
call, err := New(logr.Discard(), entry, ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
data, err := call.Execute()
|
||||
data, err := call.Execute(context.TODO())
|
||||
assert.NilError(t, err)
|
||||
assert.Equal(t, "{}\n", string(data))
|
||||
|
||||
|
@ -135,9 +135,9 @@ func Test_servicePostRequest(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
call, err = New(context.TODO(), entry, ctx, nil, logr.Discard())
|
||||
call, err = New(logr.Discard(), entry, ctx, nil)
|
||||
assert.NilError(t, err)
|
||||
data, err = call.Execute()
|
||||
data, err = call.Execute(context.TODO())
|
||||
assert.NilError(t, err)
|
||||
|
||||
expectedResults := `{"images":["https://ghcr.io/tomcat/tomcat:9","https://ghcr.io/vault/vault:v3","https://ghcr.io/busybox/busybox:latest"]}`
|
||||
|
|
Loading…
Add table
Reference in a new issue