-
Notifications
You must be signed in to change notification settings - Fork 226
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
add mutation tracking to the fake client
- Loading branch information
Showing
7 changed files
with
775 additions
and
32 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
package manifestclient | ||
|
||
import ( | ||
"k8s.io/apimachinery/pkg/runtime/schema" | ||
"k8s.io/apimachinery/pkg/util/sets" | ||
"sync" | ||
) | ||
|
||
type AllActionsTracker struct { | ||
lock sync.RWMutex | ||
|
||
ActionToTracker map[Action]*ActionTracker | ||
} | ||
|
||
type Action string | ||
|
||
const ( | ||
// this is really a subset of patch, but we treat it separately because it is useful to do so | ||
ActionApply Action = "server-side-apply" | ||
ActionApplyStatus Action = "server-side-apply-status" | ||
ActionUpdate Action = "update" | ||
ActionUpdateStatus Action = "update-status" | ||
ActionCreate Action = "create" | ||
ActionDelete Action = "delete" | ||
) | ||
|
||
type ActionMetadata struct { | ||
Action Action | ||
GVR schema.GroupVersionResource | ||
Namespace string | ||
Name string | ||
} | ||
|
||
type ActionTracker struct { | ||
Action Action | ||
ResourceToTracker map[schema.GroupVersionResource]*ResourceTracker | ||
} | ||
|
||
type ResourceTracker struct { | ||
GVR schema.GroupVersionResource | ||
NamespaceToTracker map[string]*NamespaceTracker | ||
} | ||
|
||
type NamespaceTracker struct { | ||
Namespace string | ||
NameToTracker map[string]*NameTracker | ||
} | ||
|
||
type NameTracker struct { | ||
Name string | ||
SerializedRequests []SerializedRequest | ||
} | ||
|
||
type SerializedRequest struct { | ||
Options []byte | ||
Body []byte | ||
} | ||
|
||
func (a *AllActionsTracker) AddRequest(metadata ActionMetadata, request SerializedRequest) { | ||
a.lock.Lock() | ||
defer a.lock.Unlock() | ||
|
||
if a.ActionToTracker == nil { | ||
a.ActionToTracker = map[Action]*ActionTracker{} | ||
} | ||
if _, ok := a.ActionToTracker[metadata.Action]; !ok { | ||
a.ActionToTracker[metadata.Action] = &ActionTracker{Action: metadata.Action} | ||
} | ||
a.ActionToTracker[metadata.Action].AddRequest(metadata, request) | ||
} | ||
|
||
func (a *AllActionsTracker) ListActions() []Action { | ||
a.lock.Lock() | ||
defer a.lock.Unlock() | ||
|
||
return sets.KeySet(a.ActionToTracker).UnsortedList() | ||
} | ||
|
||
func (a *AllActionsTracker) MutationsForAction(action Action) *ActionTracker { | ||
a.lock.RLock() | ||
defer a.lock.RUnlock() | ||
|
||
return a.ActionToTracker[action] | ||
} | ||
|
||
func (a *AllActionsTracker) MutationsForMetadata(metadata ActionMetadata) []SerializedRequest { | ||
a.lock.RLock() | ||
defer a.lock.RUnlock() | ||
|
||
actionTracker := a.MutationsForAction(metadata.Action) | ||
if actionTracker == nil { | ||
return nil | ||
} | ||
resourceTracker := actionTracker.MutationsForResource(metadata.GVR) | ||
if resourceTracker == nil { | ||
return nil | ||
} | ||
namespaceTracker := resourceTracker.MutationsForNamespace(metadata.Namespace) | ||
if namespaceTracker == nil { | ||
return nil | ||
} | ||
nameTracker := namespaceTracker.MutationsForName(metadata.Name) | ||
if nameTracker == nil { | ||
return nil | ||
} | ||
return nameTracker.SerializedRequests | ||
} | ||
|
||
func (a *ActionTracker) AddRequest(metadata ActionMetadata, request SerializedRequest) { | ||
if a.ResourceToTracker == nil { | ||
a.ResourceToTracker = map[schema.GroupVersionResource]*ResourceTracker{} | ||
} | ||
if _, ok := a.ResourceToTracker[metadata.GVR]; !ok { | ||
a.ResourceToTracker[metadata.GVR] = &ResourceTracker{GVR: metadata.GVR} | ||
} | ||
a.ResourceToTracker[metadata.GVR].AddRequest(metadata, request) | ||
} | ||
|
||
func (a *ActionTracker) ListResources() []schema.GroupVersionResource { | ||
return sets.KeySet(a.ResourceToTracker).UnsortedList() | ||
} | ||
|
||
func (a *ActionTracker) MutationsForResource(gvr schema.GroupVersionResource) *ResourceTracker { | ||
return a.ResourceToTracker[gvr] | ||
} | ||
|
||
func (a *ResourceTracker) AddRequest(metadata ActionMetadata, request SerializedRequest) { | ||
if a.NamespaceToTracker == nil { | ||
a.NamespaceToTracker = map[string]*NamespaceTracker{} | ||
} | ||
if _, ok := a.NamespaceToTracker[metadata.Namespace]; !ok { | ||
a.NamespaceToTracker[metadata.Namespace] = &NamespaceTracker{Namespace: metadata.Namespace} | ||
} | ||
a.NamespaceToTracker[metadata.Namespace].AddRequest(metadata, request) | ||
} | ||
|
||
func (a *ResourceTracker) ListNamespaces() []string { | ||
return sets.KeySet(a.NamespaceToTracker).UnsortedList() | ||
} | ||
|
||
func (a *ResourceTracker) MutationsForNamespace(namespace string) *NamespaceTracker { | ||
return a.NamespaceToTracker[namespace] | ||
} | ||
|
||
func (a *NamespaceTracker) AddRequest(metadata ActionMetadata, request SerializedRequest) { | ||
if a.NameToTracker == nil { | ||
a.NameToTracker = map[string]*NameTracker{} | ||
} | ||
if _, ok := a.NameToTracker[metadata.Name]; !ok { | ||
a.NameToTracker[metadata.Name] = &NameTracker{Name: metadata.Name} | ||
} | ||
a.NameToTracker[metadata.Name].AddRequest(request) | ||
} | ||
|
||
func (a *NamespaceTracker) ListNames() []string { | ||
return sets.KeySet(a.NameToTracker).UnsortedList() | ||
} | ||
|
||
func (a *NamespaceTracker) MutationsForName(name string) *NameTracker { | ||
return a.NameToTracker[name] | ||
} | ||
|
||
func (a *NameTracker) AddRequest(request SerializedRequest) { | ||
if a.SerializedRequests == nil { | ||
a.SerializedRequests = []SerializedRequest{} | ||
} | ||
a.SerializedRequests = append(a.SerializedRequests, request) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,94 @@ | ||
package manifestclient | ||
|
||
import ( | ||
"bytes" | ||
"embed" | ||
"fmt" | ||
"io" | ||
"net/http" | ||
) | ||
|
||
// Enter here and call `NewForConfigAndClient(&rest.Config{}, httpClient)` | ||
func NewHTTPClient(mustGatherDir string) MutationTrackingClient { | ||
mutationTrackingRoundTripper := newReadWriteRoundTripper(newMustGatherReader(mustGatherDir)) | ||
return &mutationTrackingClient{ | ||
httpClient: &http.Client{ | ||
Transport: mutationTrackingRoundTripper, | ||
}, | ||
mutationTrackingRoundTripper: mutationTrackingRoundTripper, | ||
} | ||
} | ||
|
||
// Enter here and call `NewForConfigAndClient(&rest.Config{}, httpClient)` | ||
func NewTestingHTTPClient(embedFS embed.FS, prefix string) MutationTrackingClient { | ||
mutationTrackingRoundTripper := newReadWriteRoundTripper(newPrefixedReader(embedFS, prefix)) | ||
return &mutationTrackingClient{ | ||
httpClient: &http.Client{ | ||
Transport: mutationTrackingRoundTripper, | ||
}, | ||
mutationTrackingRoundTripper: mutationTrackingRoundTripper, | ||
} | ||
} | ||
|
||
func NewTestingRoundTripper(embedFS embed.FS, prefix string) *readWriteRoundTripper { | ||
return newReadWriteRoundTripper(newPrefixedReader(embedFS, prefix)) | ||
} | ||
|
||
func NewRoundTripper(mustGatherDir string) *readWriteRoundTripper { | ||
return newReadWriteRoundTripper(newMustGatherReader(mustGatherDir)) | ||
} | ||
|
||
func newReadWriteRoundTripper(contentReader RawReader) *readWriteRoundTripper { | ||
return &readWriteRoundTripper{ | ||
readDelegate: newReadRoundTripper(contentReader), | ||
writeDelegate: newWriteRoundTripper(), | ||
} | ||
} | ||
|
||
type readWriteRoundTripper struct { | ||
readDelegate *manifestRoundTripper | ||
writeDelegate *writeTrackingRoundTripper | ||
} | ||
|
||
type MutationTrackingRoundTripper interface { | ||
http.RoundTripper | ||
GetMutations() *AllActionsTracker | ||
} | ||
|
||
type mutationTrackingClient struct { | ||
httpClient *http.Client | ||
|
||
mutationTrackingRoundTripper MutationTrackingRoundTripper | ||
} | ||
|
||
func (m mutationTrackingClient) GetHTTPClient() *http.Client { | ||
return m.httpClient | ||
} | ||
|
||
func (m mutationTrackingClient) GetMutations() *AllActionsTracker { | ||
return m.mutationTrackingRoundTripper.GetMutations() | ||
} | ||
|
||
type MutationTrackingClient interface { | ||
GetHTTPClient() *http.Client | ||
GetMutations() *AllActionsTracker | ||
} | ||
|
||
func (rt *readWriteRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { | ||
switch req.Method { | ||
case "GET", "HEAD": | ||
return rt.readDelegate.RoundTrip(req) | ||
case "POST", "PUT", "PATCH", "DELETE": | ||
return rt.writeDelegate.RoundTrip(req) | ||
default: | ||
resp := &http.Response{} | ||
resp.StatusCode = http.StatusInternalServerError | ||
resp.Status = http.StatusText(resp.StatusCode) | ||
resp.Body = io.NopCloser(bytes.NewBufferString(fmt.Sprintf("unhandled verb: %q", req.Method))) | ||
return resp, nil | ||
} | ||
} | ||
|
||
func (rt *readWriteRoundTripper) GetMutations() *AllActionsTracker { | ||
return rt.writeDelegate.actionTracker | ||
} |
Oops, something went wrong.