github.com/dtroyer-salad/og2/v2@v2.0.0-20240412154159-c47231610877/registry/remote/credentials/trace/trace.go (about) 1 /* 2 Copyright The ORAS Authors. 3 Licensed under the Apache License, Version 2.0 (the "License"); 4 you may not use this file except in compliance with the License. 5 You may obtain a copy of the License at 6 7 http://www.apache.org/licenses/LICENSE-2.0 8 9 Unless required by applicable law or agreed to in writing, software 10 distributed under the License is distributed on an "AS IS" BASIS, 11 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 See the License for the specific language governing permissions and 13 limitations under the License. 14 */ 15 16 package trace 17 18 import "context" 19 20 // executableTraceContextKey is a value key used to retrieve the ExecutableTrace 21 // from Context. 22 type executableTraceContextKey struct{} 23 24 // ExecutableTrace is a set of hooks used to trace the execution of binary 25 // executables. Any particular hook may be nil. 26 type ExecutableTrace struct { 27 // ExecuteStart is called before the execution of the executable. The 28 // executableName parameter is the name of the credential helper executable 29 // used with NativeStore. The action parameter is one of "store", "get" and 30 // "erase". 31 // 32 // Reference: 33 // - https://docs.docker.com/engine/reference/commandline/login#credentials-store 34 ExecuteStart func(executableName string, action string) 35 36 // ExecuteDone is called after the execution of an executable completes. 37 // The executableName parameter is the name of the credential helper 38 // executable used with NativeStore. The action parameter is one of "store", 39 // "get" and "erase". The err parameter is the error (if any) returned from 40 // the execution. 41 // 42 // Reference: 43 // - https://docs.docker.com/engine/reference/commandline/login#credentials-store 44 ExecuteDone func(executableName string, action string, err error) 45 } 46 47 // ContextExecutableTrace returns the ExecutableTrace associated with the 48 // context. If none, it returns nil. 49 func ContextExecutableTrace(ctx context.Context) *ExecutableTrace { 50 trace, _ := ctx.Value(executableTraceContextKey{}).(*ExecutableTrace) 51 return trace 52 } 53 54 // WithExecutableTrace takes a Context and an ExecutableTrace, and returns a 55 // Context with the ExecutableTrace added as a Value. If the Context has a 56 // previously added trace, the hooks defined in the new trace will be added 57 // in addition to the previous ones. The recent hooks will be called first. 58 func WithExecutableTrace(ctx context.Context, trace *ExecutableTrace) context.Context { 59 if trace == nil { 60 return ctx 61 } 62 if oldTrace := ContextExecutableTrace(ctx); oldTrace != nil { 63 trace.compose(oldTrace) 64 } 65 return context.WithValue(ctx, executableTraceContextKey{}, trace) 66 } 67 68 // compose takes an oldTrace and modifies the existing trace to include 69 // the hooks defined in the oldTrace. The hooks in the existing trace will 70 // be called first. 71 func (trace *ExecutableTrace) compose(oldTrace *ExecutableTrace) { 72 if oldStart := oldTrace.ExecuteStart; oldStart != nil { 73 start := trace.ExecuteStart 74 if start != nil { 75 trace.ExecuteStart = func(executableName, action string) { 76 start(executableName, action) 77 oldStart(executableName, action) 78 } 79 } else { 80 trace.ExecuteStart = oldStart 81 } 82 } 83 if oldDone := oldTrace.ExecuteDone; oldDone != nil { 84 done := trace.ExecuteDone 85 if done != nil { 86 trace.ExecuteDone = func(executableName, action string, err error) { 87 done(executableName, action, err) 88 oldDone(executableName, action, err) 89 } 90 } else { 91 trace.ExecuteDone = oldDone 92 } 93 } 94 }