Skip to content

Commit

Permalink
Automated Config Connector import.
Browse files Browse the repository at this point in the history
  - 683bf0fb9046ae164622505337e7c0f29fe607dd SecretManager mock tests by Config Connector Team <no-reply@google.com>
  - 19c4a15b776e85afba3fcb874dc4124ce01efe9e tests: only write http logs if ARTIFACTS is set by Config Connector Team <no-reply@google.com>

GitOrigin-RevId: 683bf0fb9046ae164622505337e7c0f29fe607dd
  • Loading branch information
Config Connector Team authored and copybara-github committed Nov 11, 2022
1 parent 9408485 commit 29ec7f9
Show file tree
Hide file tree
Showing 80 changed files with 11,136 additions and 704 deletions.
13 changes: 7 additions & 6 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ require (
github.com/cenkalti/backoff v2.2.1+incompatible
github.com/fatih/color v1.13.0
github.com/ghodss/yaml v1.0.0
github.com/go-logr/logr v1.2.0
github.com/go-logr/logr v1.2.3
github.com/go-logr/zapr v1.2.0
github.com/golang-collections/go-datastructures v0.0.0-20150211160725-59788d5eb259
github.com/golang/glog v1.0.0
Expand Down Expand Up @@ -47,11 +47,12 @@ require (
k8s.io/client-go v0.23.0
k8s.io/code-generator v0.23.0
k8s.io/gengo v0.0.0-20210813121822-485abfe95c7c
k8s.io/klog/v2 v2.30.0
k8s.io/klog/v2 v2.70.1
sigs.k8s.io/controller-runtime v0.11.1
sigs.k8s.io/controller-tools v0.6.2
sigs.k8s.io/kubebuilder-declarative-pattern v0.0.0-20220110041111-fea7e5cc7012
sigs.k8s.io/structured-merge-diff/v4 v4.2.0
sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver v0.0.0-20221013004300-4095ad3c21ca
sigs.k8s.io/structured-merge-diff/v4 v4.2.3
sigs.k8s.io/yaml v1.3.0
)

Expand Down Expand Up @@ -178,7 +179,7 @@ require (
go.uber.org/multierr v1.6.0 // indirect
golang.org/x/crypto v0.0.0-20220517005047-85d78b3ac167 // indirect
golang.org/x/mod v0.5.0 // indirect
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e // indirect
golang.org/x/net v0.0.0-20220722155237-a158d28d115b // indirect
golang.org/x/sys v0.0.0-20220624220833-87e55d714810 // indirect
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 // indirect
golang.org/x/text v0.3.7 // indirect
Expand All @@ -196,8 +197,8 @@ require (
k8s.io/component-base v0.23.0 // indirect
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 // indirect
k8s.io/kubectl v0.22.2 // indirect
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b // indirect
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 // indirect
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed // indirect
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 // indirect
sigs.k8s.io/kustomize/api v0.10.1 // indirect
sigs.k8s.io/kustomize/kyaml v0.13.0 // indirect
)
Expand Down
21 changes: 14 additions & 7 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -284,8 +284,9 @@ github.com/go-logfmt/logfmt v0.5.0/go.mod h1:wCYkCAKZfumFQihp8CzCvQ3paCTfi41vtzG
github.com/go-logr/logr v0.1.0/go.mod h1:ixOQHD9gLJUVQQ2ZOR7zLEifBX6tGkNJF4QyIY7sIas=
github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v0.4.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTgseGU=
github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE=
github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/logr v1.2.3 h1:2DntVwHkVopvECVRSlL5PSo9eG+cAkDCuckLubN+rq0=
github.com/go-logr/logr v1.2.3/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
github.com/go-logr/zapr v1.2.0 h1:n4JnPI1T3Qq1SFEi/F8rwLrZERp2bso19PJZDB9dayk=
github.com/go-logr/zapr v1.2.0/go.mod h1:Qa4Bsj2Vb+FAVeAKsLD8RLQ+YRJB8YDmOAKxaBQf7Ro=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
Expand Down Expand Up @@ -969,8 +970,9 @@ golang.org/x/net v0.0.0-20220325170049-de3da57026de/go.mod h1:CfG3xpIq0wQ8r1q4Su
golang.org/x/net v0.0.0-20220412020605-290c469a71a5/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk=
golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e h1:TsQ7F31D3bUCLeqPT0u+yjp1guoArKaNKmCr22PYgTQ=
golang.org/x/net v0.0.0-20220624214902-1bab6f366d9e/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b h1:PxfKdU9lEEDYjdIzOtC4qFWgkU2rGHdKlKowJSMN9h0=
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.0.0-20190226205417-e64efc72b421/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
golang.org/x/oauth2 v0.0.0-20190604053449-0f29369cfe45/go.mod h1:gOpvHmFTYa4IltrdGE7lF6nIHvwfUNPOp7c8zoXwtLw=
Expand Down Expand Up @@ -1469,8 +1471,9 @@ k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.2.0/go.mod h1:Od+F08eJP+W3HUb4pSrPpgp9DGU4GzlpG/TmITuYh/Y=
k8s.io/klog/v2 v2.8.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.9.0/go.mod h1:hy9LJ/NvuK+iVyP4Ehqva4HxZG/oXyIS3n3Jmire4Ec=
k8s.io/klog/v2 v2.30.0 h1:bUO6drIvCIsvZ/XFgfxoGFQU/a4Qkh0iAlvUR7vlHJw=
k8s.io/klog/v2 v2.30.0/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/klog/v2 v2.70.1 h1:7aaoSdahviPmR+XkS7FyxlkkXs6tHISSG03RxleQAVQ=
k8s.io/klog/v2 v2.70.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0=
k8s.io/kube-openapi v0.0.0-20210305001622-591a79e4bda7/go.mod h1:wXW5VT87nVfh/iLV8FpR2uDvrFyomxbtb1KivDbvPTE=
k8s.io/kube-openapi v0.0.0-20210421082810-95288971da7e/go.mod h1:vHXdDvt9+2spS2Rx9ql3I8tycm3H9FDfdUoIuKCefvw=
k8s.io/kube-openapi v0.0.0-20211115234752-e816edb12b65 h1:E3J9oCLlaobFUqsjG9DfKbP2BmgwBL2p7pn0A3dG9W4=
Expand All @@ -1481,8 +1484,9 @@ k8s.io/metrics v0.22.2/go.mod h1:GUcsBtpsqQD1tKFS/2wCKu4ZBowwRncLOJH1rgWs3uw=
k8s.io/utils v0.0.0-20201110183641-67b214c5f920/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210802155522-efc7438f0176/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210819203725-bdf08cb9a70a/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b h1:wxEMGetGMur3J1xuGLQY7GEQYg9bZxKn3tKo5k/eYcs=
k8s.io/utils v0.0.0-20210930125809-cb0fa318a74b/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed h1:jAne/RjBTyawwAy0utX5eqigAwz/lQhTmy+Hr/Cpue4=
k8s.io/utils v0.0.0-20220728103510-ee6ede2d64ed/go.mod h1:jPW/WVKK9YHAvNhRxK0md/EJ228hCsBRufyofKtW8HA=
rsc.io/binaryregexp v0.2.0 h1:HfqmD5MEmC0zvwBuF187nq9mdnXjXsSivRiXN7SmRkE=
rsc.io/binaryregexp v0.2.0/go.mod h1:qTv7/COck+e2FymRvadv62gMdZztPaShugOCi3I+8D8=
rsc.io/quote/v3 v3.1.0/go.mod h1:yEA65RcK8LyAZtP9Kv3t0HmxON59tX3rD+tICJqUlj0=
Expand All @@ -1493,10 +1497,13 @@ sigs.k8s.io/controller-runtime v0.11.1 h1:7YIHT2QnHJArj/dk9aUkYhfqfK5cIxPOX5gPEC
sigs.k8s.io/controller-runtime v0.11.1/go.mod h1:KKwLiTooNGu+JmLZGn9Sl3Gjmfj66eMbCQznLP5zcqA=
sigs.k8s.io/controller-tools v0.6.2 h1:+Y8L0UsAugDipGRw8lrkPoAi6XqlQVZuf1DQHME3PgU=
sigs.k8s.io/controller-tools v0.6.2/go.mod h1:oaeGpjXn6+ZSEIQkUe/+3I40PNiDYp9aeawbt3xTgJ8=
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6 h1:fD1pz4yfdADVNfFmcP2aBEtudwUQ1AlLnRBALr33v3s=
sigs.k8s.io/json v0.0.0-20211020170558-c049b76a60c6/go.mod h1:p4QtZmO4uMYipTQNzagwnNoseA6OxSUutVw05NhYDRs=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2 h1:iXTIw73aPyC+oRdyqqvVJuloN1p0AC/kzH07hu3NE+k=
sigs.k8s.io/json v0.0.0-20220713155537-f223a00ba0e2/go.mod h1:B8JuhiUyNFVKdsE8h686QcCxMaH6HrOAZj4vswFpcB0=
sigs.k8s.io/kubebuilder-declarative-pattern v0.0.0-20220110041111-fea7e5cc7012 h1:Yc8XUTjAY0EvesY4SuWeiLdCdviPinmZl/qFB6NJxSs=
sigs.k8s.io/kubebuilder-declarative-pattern v0.0.0-20220110041111-fea7e5cc7012/go.mod h1:VZGyJrlEAx8A5271hx7Rbkp5h+0+sj72fvVfkeky7q0=
sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver v0.0.0-20221013004300-4095ad3c21ca h1:89zSaxx50smbx4PKXpZb/vYjPrmMh7iayCR3eKuJZdc=
sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver v0.0.0-20221013004300-4095ad3c21ca/go.mod h1:lnUjbSD3YT/lBWOZEIfhJT/uj1Ic+IRWMnT+iwsXM3Y=
sigs.k8s.io/kustomize/api v0.8.11/go.mod h1:a77Ls36JdfCWojpUqR6m60pdGY1AYFix4AH83nJtY1g=
sigs.k8s.io/kustomize/api v0.10.1 h1:KgU7hfYoscuqag84kxtzKdEC3mKMb99DPI3a0eaV1d0=
sigs.k8s.io/kustomize/api v0.10.1/go.mod h1:2FigT1QN6xKdcnGS2Ppp1uIWrtWN28Ms8A3OZUZhwr8=
Expand All @@ -1507,8 +1514,8 @@ sigs.k8s.io/kustomize/kyaml v0.13.0 h1:9c+ETyNfSrVhxvphs+K2dzT3dh5oVPPEqPOE/cUpS
sigs.k8s.io/kustomize/kyaml v0.13.0/go.mod h1:FTJxEZ86ScK184NpGSAQcfEqee0nul8oLCK30D47m4E=
sigs.k8s.io/structured-merge-diff/v4 v4.0.2/go.mod h1:bJZC9H9iH24zzfZ/41RGcq60oK1F7G282QMXDPYydCw=
sigs.k8s.io/structured-merge-diff/v4 v4.1.2/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.0 h1:kDvPBbnPk+qYmkHmSo8vKGp438IASWofnbbUKDE/bv0=
sigs.k8s.io/structured-merge-diff/v4 v4.2.0/go.mod h1:j/nl6xW8vLS49O8YvXW1ocPhZawJtm+Yrr7PPRQ0Vg4=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3 h1:PRbqxJClWWYMNV1dhaG4NsibJbArud9kFxnAMREiWFE=
sigs.k8s.io/structured-merge-diff/v4 v4.2.3/go.mod h1:qjx8mGObPmV2aSZepjQjbmb2ihdVs8cGKBraizNC69E=
sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
sigs.k8s.io/yaml v1.2.0/go.mod h1:yfXDCHCao9+ENCvLSE62v9VSji2MKu5jeNfTrofGhJc=
sigs.k8s.io/yaml v1.3.0 h1:a2VclLzOGrwOHDiV8EfBGhvjHvP46CtW5j6POvhYGGo=
Expand Down
18 changes: 16 additions & 2 deletions pkg/cli/gcpclient/client_integration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,10 @@ package gcpclient_test
import (
"context"
"fmt"
"log"
"net/http"
"os"
"path/filepath"
"testing"

corekccv1alpha1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/core/v1alpha1"
Expand Down Expand Up @@ -75,11 +78,22 @@ func init() {
// TODO: Can we initialize this globally once somewhere?
// (It shouldn't _really_ matter if we have multiple instances, it's just leaky and confusing)
tfgooglebeta.DefaultHTTPClientTransformer = func(ctx context.Context, inner *http.Client) *http.Client {
t := test.NewHTTPRecorder(inner.Transport)
artifacts := os.Getenv("ARTIFACTS")
if artifacts == "" {
log.Printf("env var ARTIFACTS is not set; will not record http log")
return inner
}
outputDir := filepath.Join(artifacts, "http-logs")
t := test.NewHTTPRecorder(inner.Transport, outputDir)
return &http.Client{Transport: t}
}
tfgooglebeta.OAuth2HTTPClientTransformer = func(ctx context.Context, inner *http.Client) *http.Client {
t := test.NewHTTPRecorder(inner.Transport)
artifacts := os.Getenv("ARTIFACTS")
if artifacts == "" {
return inner
}
outputDir := filepath.Join(artifacts, "http-logs")
t := test.NewHTTPRecorder(inner.Transport, outputDir)
return &http.Client{Transport: t}
}
}
Expand Down
175 changes: 175 additions & 0 deletions pkg/controller/mocktests/harness.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mocktests

import (
"bytes"
"context"
"io"
"os"
"strings"
"testing"

iamv1beta1 "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/apis/iam/v1beta1"
dclmetadata "github.com/GoogleCloudPlatform/k8s-config-connector/pkg/dcl/metadata"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/gvks/supportedgvks"
"github.com/GoogleCloudPlatform/k8s-config-connector/pkg/servicemapping/servicemappingloader"
corev1 "k8s.io/api/core/v1"
"k8s.io/apimachinery/pkg/api/meta"
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/schema"
yamlserializer "k8s.io/apimachinery/pkg/runtime/serializer/yaml"
yamlutil "k8s.io/apimachinery/pkg/util/yaml"
"k8s.io/client-go/rest"
"sigs.k8s.io/controller-runtime/pkg/cache"
"sigs.k8s.io/controller-runtime/pkg/client"
"sigs.k8s.io/kubebuilder-declarative-pattern/mockkubeapiserver"
)

type Harness struct {
*testing.T

k8s *mockkubeapiserver.MockKubeAPIServer
restConfig *rest.Config
Scheme *runtime.Scheme
Ctx context.Context
Client client.Client
}

func (h *Harness) RESTConfig() *rest.Config {
if h.restConfig == nil {
h.Fatalf("cannot call RESTConfig before Start")
}
return h.restConfig
}

func (h *Harness) NewClient(cache cache.Cache, config *rest.Config, options client.Options, uncachedObjects ...client.Object) (client.Client, error) {
if h.Client == nil {
h.Fatalf("WithObjects must be called before NewClient")
}
return h.Client, nil
}

func NewHarness(t *testing.T) *Harness {
h := &Harness{
T: t,
Scheme: runtime.NewScheme(),
Ctx: context.Background(),
}
corev1.AddToScheme(h.Scheme)

iamv1beta1.SchemeBuilder.AddToScheme(h.Scheme)

t.Cleanup(h.Stop)
return h
}

func (h *Harness) ParseObjects(y string) []*unstructured.Unstructured {
t := h.T

var objects []*unstructured.Unstructured

decoder := yamlutil.NewYAMLOrJSONDecoder(bytes.NewReader([]byte(y)), 100)
for {
var rawObj runtime.RawExtension
if err := decoder.Decode(&rawObj); err != nil {
if err != io.EOF {
t.Fatalf("error decoding yaml: %v", err)
}
break
}

m, _, err := yamlserializer.NewDecodingSerializer(unstructured.UnstructuredJSONScheme).Decode(rawObj.Raw, nil, nil)
if err != nil {
t.Fatalf("error decoding yaml: %v", err)
}

unstructuredMap, err := runtime.DefaultUnstructuredConverter.ToUnstructured(m)
if err != nil {
t.Fatalf("error parsing object: %v", err)
}
unstructuredObj := &unstructured.Unstructured{Object: unstructuredMap}

objects = append(objects, unstructuredObj)
}

return objects
}

func (h *Harness) WithObjects(initObjs ...*unstructured.Unstructured) {
k8s, err := mockkubeapiserver.NewMockKubeAPIServer(":0")
if err != nil {
h.Fatalf("error building mock kube-apiserver: %v", err)
}

k8s.RegisterType(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Namespace"}, "namespaces", meta.RESTScopeRoot)
k8s.RegisterType(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Secret"}, "secrets", meta.RESTScopeNamespace)

smLoader, err := servicemappingloader.New()
if err != nil {
h.Fatalf("error getting new service mapping loader: %v", err)
}
supportedGVKs := supportedgvks.All(smLoader, dclmetadata.New())
for _, gvk := range supportedGVKs {
var resource string
switch gvk.Kind {
// TODO: Any special pluralization cases go here (unless we can get them from supportedgvks)
default:
resource = strings.ToLower(gvk.Kind) + "s"
}
k8s.RegisterType(gvk, resource, meta.RESTScopeNamespace)
}

for _, obj := range initObjs {
if err := k8s.AddObject(obj); err != nil {
h.Errorf("error adding object %v: %v", obj, err)
}
}
addr, err := k8s.StartServing()
if err != nil {
h.Errorf("error starting mock kube-apiserver: %v", err)
}

h.restConfig = &rest.Config{
Host: addr.String(),
}

client, err := client.New(h.restConfig, client.Options{})
if err != nil {
h.Fatalf("error building client: %v", err)
}

h.Client = client
}

func (h *Harness) Stop() {
if h.k8s != nil {
if err := h.k8s.Stop(); err != nil {
h.Logf("error closing mock kube-apiserver: %v", err)
h.Errorf("error closing mock kube-apiserver: %v", err)
}
}
}

// MustReadFile returns the contents of the file - as a string
// It fails the test if the file cannot be read
func (h *Harness) MustReadFile(p string) string {
b, err := os.ReadFile(p)
if err != nil {
h.Fatalf("error reading file %q: %v", p, err)
}
return string(b)
}
59 changes: 59 additions & 0 deletions pkg/controller/mocktests/http_recorder.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright 2022 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package mocktests

import (
"bytes"
"io/ioutil"
"net/http"
)

type Request struct {
Method string `json:"method,omitempty"`
URL string `json:"url,omitempty"`
Header http.Header `json:"header,omitempty"`
Body string `json:"body,omitempty"`
}

type HTTPRecorder struct {
inner http.RoundTripper
Requests []Request
}

func NewRecorder(inner http.RoundTripper) *HTTPRecorder {
rt := &HTTPRecorder{inner: inner}
return rt
}

func (m *HTTPRecorder) RoundTrip(req *http.Request) (*http.Response, error) {

c := Request{
Method: req.Method,
URL: req.URL.String(),
Header: req.Header,
}

if req.Body != nil {
requestBody, err := ioutil.ReadAll(req.Body)
if err != nil {
panic("failed to read request body")
}
c.Body = string(requestBody)
req.Body = ioutil.NopCloser(bytes.NewReader(requestBody))
}
m.Requests = append(m.Requests, c)

return m.inner.RoundTrip(req)
}
Loading

0 comments on commit 29ec7f9

Please sign in to comment.