diff --git a/go.mod b/go.mod index 2d56d64..746ac2e 100644 --- a/go.mod +++ b/go.mod @@ -4,16 +4,25 @@ go 1.23.5 require ( github.com/cloudfoundry/go-cfclient/v3 v3.0.0-alpha.9 - github.com/google/go-cmp v0.6.0 + github.com/google/go-cmp v0.7.0 github.com/spf13/cobra v1.8.1 ) require ( + code.cloudfoundry.org/cf-networking-helpers v0.47.0 // indirect + github.com/go-task/slim-sprig/v3 v3.0.0 // indirect + github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a // indirect github.com/kr/pretty v0.3.1 // indirect + github.com/onsi/ginkgo/v2 v2.23.4 // indirect + github.com/openzipkin/zipkin-go v0.4.3 // indirect + go.uber.org/automaxprocs v1.6.0 // indirect + golang.org/x/tools v0.34.0 // indirect gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 // indirect ) require ( + code.cloudfoundry.org/lager/v3 v3.39.0 + code.cloudfoundry.org/policy_client v0.57.0 github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 // indirect github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab // indirect diff --git a/go.sum b/go.sum index 7ada064..8aa66de 100644 --- a/go.sum +++ b/go.sum @@ -1,3 +1,11 @@ +code.cloudfoundry.org/cf-networking-helpers v0.47.0 h1:kHOw6K/eaMDuq87uQ/kl1art6MV0e8VvhZeayhuz0AY= +code.cloudfoundry.org/cf-networking-helpers v0.47.0/go.mod h1:BRbPfwQACMDPGaxmfPR1bmynjXPfb6nSqda0FhEJd7s= +code.cloudfoundry.org/lager/v3 v3.39.0 h1:axxT3QTIu7ZWNyV7IKtNrSP4xmtMPbgbIJ5lY3ixYU8= +code.cloudfoundry.org/lager/v3 v3.39.0/go.mod h1:xcAxUZal+NkRwwF40JEY/rouQB/IaIfzjf5wi3jSYUs= +code.cloudfoundry.org/policy_client v0.57.0 h1:YW+NpBuEHz9arTxRnyz7DPTX3N5KgcrFrNXjZcycjB0= +code.cloudfoundry.org/policy_client v0.57.0/go.mod h1:jnUDM9jyNwf8/nHhBBadlPbhPkzmi/ihlkGAhEPtmEs= +filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA= +filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4= github.com/cloudfoundry/go-cfclient/v3 v3.0.0-alpha.9 h1:HK3+nJEPgwlhc5H74aw/V4mVowqWaTKGjHONdVQQ2Vw= github.com/cloudfoundry/go-cfclient/v3 v3.0.0-alpha.9/go.mod h1:eUjFfpsU3lRv388wKlXMmkQfsJ9pveUHZEia7AoBCPY= github.com/codegangsta/inject v0.0.0-20150114235600-33e0aa1cb7c0 h1:sDMmm+q/3+BukdIpxwO365v/Rbspp2Nt5XntgQRXq8Q= @@ -7,26 +15,48 @@ github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ3 github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM= github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab h1:xveKWz2iaueeTaUgdetzel+U7exyigDYBryyVfV/rZk= github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8= -github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= -github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= +github.com/go-sql-driver/mysql v1.9.3 h1:U/N249h2WzJ3Ukj8SowVFjdtZKfu9vlLZxjPXV1aweo= +github.com/go-sql-driver/mysql v1.9.3/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU= +github.com/go-task/slim-sprig/v3 v3.0.0 h1:sUs3vkvUymDpBKi3qH1YSqBQk9+9D/8M2mN1vB6EwHI= +github.com/go-task/slim-sprig/v3 v3.0.0/go.mod h1:W848ghGpv3Qj3dhTPRyJypKRiqCdHZiAzKg9hl15HA8= +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/pprof v0.0.0-20250607225305-033d6d78b36a h1://KbezygeMJZCSHH+HgUZiTeSoiuFspbMg1ge+eFj18= +github.com/google/pprof v0.0.0-20250607225305-033d6d78b36a/go.mod h1:5hDyRhoBCxViHszMt12TnOpEI4VVi+U8Gm9iphldiMA= github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8= github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw= +github.com/jmoiron/sqlx v1.4.0 h1:1PLqN7S1UYp5t4SrVVnt4nUVNemrDAtxlulVe+Qgm3o= +github.com/jmoiron/sqlx v1.4.0/go.mod h1:ZrZ7UsYB/weZdl2Bxg6jCRO9c3YHl8r3ahlKmRT4JLY= github.com/joho/godotenv v1.5.1 h1:7eLL/+HRGLY0ldzfGMeQkb7vMd0as4CfYvUVzLqw0N0= github.com/joho/godotenv v1.5.1/go.mod h1:f4LDr5Voq0i2e/R5DDNOoa2zzDfwtkZa6DnEwAbqwq4= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= +github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw= +github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11 h1:YFh+sjyJTMQSYjKwM4dFKhJPJC/wfo98tPUc17HdoYw= github.com/martini-contrib/render v0.0.0-20150707142108-ec18f8345a11/go.mod h1:Ah2dBMoxZEqk118as2T4u4fjfXarE0pPnMJaArZQZsI= +github.com/onsi/ginkgo/v2 v2.23.4 h1:ktYTpKJAVZnDT4VjxSbiBenUjmlL/5QkBEocaWXiQus= +github.com/onsi/ginkgo/v2 v2.23.4/go.mod h1:Bt66ApGPBFzHyR+JO10Zbt0Gsp4uWxu5mIOTusL46e8= +github.com/onsi/gomega v1.37.0 h1:CdEG8g0S133B4OswTDC/5XPSzE1OeP29QOioj2PID2Y= +github.com/onsi/gomega v1.37.0/go.mod h1:8D9+Txp43QWKhM24yyOBEdpkzN8FvJyAwecBgsU4KU0= +github.com/openzipkin/zipkin-go v0.4.3 h1:9EGwpqkgnwdEIJ+Od7QVSEIH+ocmm5nPat0G7sjsSdg= +github.com/openzipkin/zipkin-go v0.4.3/go.mod h1:M9wCJZFWCo2RiY+o1eBCEMe0Dp2S5LDHcMZmk3RmK7c= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c h1:rp5dCmg/yLR3mgFuSOe4oEnDDmGLROTvMragMUXpTQw= github.com/oxtoacart/bpool v0.0.0-20190530202638-03653db5a59c/go.mod h1:X07ZCGwUbLaax7L0S3Tw4hpejzu63ZrrQiUe6W0hcy0= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= +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= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U= github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= +github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g= +github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= @@ -34,14 +64,34 @@ github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM= github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/square/certstrap v1.3.0 h1:N9P0ZRA+DjT8pq5fGDj0z3FjafRKnBDypP0QHpMlaAk= +github.com/square/certstrap v1.3.0/go.mod h1:wGZo9eE1B7WX2GKBn0htJ+B3OuRl2UsdCFySNooy9hU= github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY= github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/tedsuo/ifrit v0.0.0-20230516164442-7862c310ad26 h1:mWCRvpoEMVlslxEvvptKgIUb35va9yj9Oq5wGw/er5I= +github.com/tedsuo/ifrit v0.0.0-20230516164442-7862c310ad26/go.mod h1:0uD3VMXkZ7Bw0ojGCwDzebBBzPBXtzEZeXai+56BLX4= +go.step.sm/crypto v0.66.0 h1:9TW6BEguOtcS9NIjja9bDQ+j8OjhenU/F6lJfHjbXNU= +go.step.sm/crypto v0.66.0/go.mod h1:anqGyvO/Px05D1mznHq4/a9wwP1I1DmMZvk+TWX5Dzo= +go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs= +go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= golang.org/x/oauth2 v0.21.0 h1:tsimM75w1tF/uws5rbeHzIWxEqElMehnc+iW793zsZs= golang.org/x/oauth2 v0.21.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= +golang.org/x/tools v0.34.0 h1:qIpSLOxeCYGg9TrcJokLBG4KFA6d795g0xkBkiESGlo= +golang.org/x/tools v0.34.0/go.mod h1:pAP9OwEaY1CAW3HOmg3hLZC5Z0CCmzjAF2UQMSqNARg= +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/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/runner-manager/cfd/cloudgov/cf_client.go b/runner-manager/cfd/cloudgov/cf_client.go index 0f0b838..fc1b83d 100644 --- a/runner-manager/cfd/cloudgov/cf_client.go +++ b/runner-manager/cfd/cloudgov/cf_client.go @@ -3,6 +3,11 @@ package cloudgov import ( "context" "os" + "strconv" + "strings" + + "code.cloudfoundry.org/lager/v3" + "code.cloudfoundry.org/policy_client" "github.com/cloudfoundry/go-cfclient/v3/client" "github.com/cloudfoundry/go-cfclient/v3/config" @@ -132,7 +137,46 @@ func (cf *CFClientAPI) mapRoute( return err } -// addNetworkPolicy implements ClientAPI. -func (cf *CFClientAPI) addNetworkPolicy(app *App, dest string, space string, port string) error { - panic("unimplemented") +func parsePortRange(prange string) (start int, end int, err error) { + ports := strings.Split(prange, "-") + + start, err = strconv.Atoi(ports[0]) + if err != nil { + return + } + + if len(ports) == 1 || ports[1] == "" { + end = start + return + } + end, err = strconv.Atoi(ports[1]) + return +} + +func (cf *CFClientAPI) addNetworkPolicy(fromGUID string, toGUID string, portRanges []string) error { + pclient := policy_client.NewExternal( + lager.NewLogger("ExternalPolicyClient"), + cf.conn().HTTPAuthClient(), + cf.conn().ApiURL(""), + ) + + policies := make([]policy_client.Policy, len(portRanges)) + + for i, prange := range portRanges { + start, end, err := parsePortRange(prange) + if err != nil { + return err + } + + policies[i] = policy_client.Policy{ + Source: policy_client.Source{ID: fromGUID}, + Destination: policy_client.Destination{ + ID: toGUID, + Ports: policy_client.Ports{Start: start, End: end}, + Protocol: "tcp", + }, + } + } + + return pclient.AddPolicies("", policies) } diff --git a/runner-manager/cfd/cloudgov/cf_client_test.go b/runner-manager/cfd/cloudgov/cf_client_test.go new file mode 100644 index 0000000..a82d9ef --- /dev/null +++ b/runner-manager/cfd/cloudgov/cf_client_test.go @@ -0,0 +1,44 @@ +package cloudgov + +import "testing" + +func Test_parsePortRange(t *testing.T) { + tests := []struct { + name string // description of this test case + // Named input parameters for target function. + prange string + want int + want2 int + wantErr bool + }{ + {name: "parses a range", prange: "80-85", want: 80, want2: 85}, + {name: "parses redundant range", prange: "81-81", want: 81, want2: 81}, + {name: "parses single port", prange: "80", want: 80, want2: 80}, + {name: "parses single number with separator", prange: "8-", want: 8, want2: 8}, + {name: "parses zero", prange: "0", want: 0, want2: 0}, + {name: "fails to parse range with non-int", prange: "60-cat", wantErr: true}, + {name: "fails to parse single with non-int", prange: "cat", wantErr: true}, + {name: "fails with empty string", prange: "", wantErr: true}, + {name: "fails with only separator", prange: "-", wantErr: true}, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + got, got2, gotErr := parsePortRange(tt.prange) + if gotErr != nil { + if !tt.wantErr { + t.Errorf("parsePortRange() failed: %v", gotErr) + } + return + } + if tt.wantErr { + t.Fatal("parsePortRange() succeeded unexpectedly") + } + if got != tt.want { + t.Errorf("parsePortRange() = %v, want %v", got, tt.want) + } + if got2 != tt.want2 { + t.Errorf("parsePortRange() = %v, want %v", got2, tt.want2) + } + }) + } +} diff --git a/runner-manager/cfd/cloudgov/cloudgov.go b/runner-manager/cfd/cloudgov/cloudgov.go index b4b4f75..5de49ed 100644 --- a/runner-manager/cfd/cloudgov/cloudgov.go +++ b/runner-manager/cfd/cloudgov/cloudgov.go @@ -1,3 +1,4 @@ +// Package cloudgov provides methods to interact CloudFoundry on cloud.gov. package cloudgov import "context" @@ -12,7 +13,7 @@ type ClientAPI interface { sshCode() (string, error) mapRoute(ctx context.Context, app *App, domain string, space string, host string, path string, port int) error - addNetworkPolicy(app *App, dest string, space string, port string) error + addNetworkPolicy(fromGUID string, toGUID string, portRanges []string) error } type CredsGetter interface { @@ -96,9 +97,9 @@ func (c *Client) AppsList() ([]*App, error) { return c.appsList() } -// TODO: this abstraction might belong in /cmd, -// unless it can be further generalized to all pushes func (c *Client) Push(manifest *AppManifest) (*App, error) { + // TODO: this abstraction might belong in /cmd, + // unless it can be further generalized to all pushes containerID := manifest.Name if containerID == "" { @@ -112,8 +113,8 @@ func (c *Client) Push(manifest *AppManifest) (*App, error) { return c.appPush(manifest) } -// TODO: use this in prepare or get rid of it func (c *Client) ServicesPush(manifests []*AppManifest) ([]*App, error) { + // TODO: use this in prepare or get rid of it if len(manifests) < 1 { return nil, nil } @@ -136,5 +137,14 @@ func (c *Client) SSHCode() (string, error) { } func (c *Client) MapServiceRoute(app *App) error { - return c.mapRoute(context.Background(), app, internalDomainGUID, app.SpaceGUID, app.Name, "", 0) + return c.mapRoute( + context.Background(), app, internalDomainGUID, app.SpaceGUID, app.Name, "", 0, + ) +} + +// AddNetworkPolicy opens portRanges (e.g. "80", "80-85") on toApp for fromApp. +func (c *Client) AddNetworkPolicy( + fromApp *App, toApp *App, portRanges []string, +) error { + return c.addNetworkPolicy(fromApp.GUID, toApp.GUID, portRanges) } diff --git a/runner-manager/cfd/cloudgov/cloudgov_integration_test.go b/runner-manager/cfd/cloudgov/cloudgov_integration_test.go index 46ea48f..e589840 100644 --- a/runner-manager/cfd/cloudgov/cloudgov_integration_test.go +++ b/runner-manager/cfd/cloudgov/cloudgov_integration_test.go @@ -8,6 +8,7 @@ import ( "fmt" "os/exec" "regexp" + "strings" "testing" cg "github.com/GSA-TTS/gitlab-runner-cloudgov/runner-manager/cfd/cloudgov" @@ -32,7 +33,7 @@ func setup(t testing.TB) { } func getCmpOpts() cmp.Option { - return cmpopts.IgnoreFields(cg.App{}, "GUID") + return cmpopts.IgnoreFields(cg.App{}, "GUID", "SpaceGUID") } func Test_CFAdapter_AppGet(t *testing.T) { @@ -41,6 +42,9 @@ func Test_CFAdapter_AppGet(t *testing.T) { want := []*cg.App{{ Name: app, State: "STARTED", + }, { + Name: fmt.Sprintf("%v_2", app), + State: "STARTED", }} got, err := cgClient.AppsList() @@ -166,10 +170,10 @@ func TestClient_MapServiceRoute(t *testing.T) { t.Log(err) } - wantUrl := fmt.Sprintf("%s.apps.internal", app.Name) + wantURL := fmt.Sprintf("%s.apps.internal", app.Name) for _, m := range routeOut["resources"] { - if m["host"] == app.Name && m["url"] == wantUrl { + if m["host"] == app.Name && m["url"] == wantURL { return } } @@ -177,3 +181,77 @@ func TestClient_MapServiceRoute(t *testing.T) { t.Logf("%#v", routeOut["resources"]) t.Fatalf("could not find route with %s host and correct url", app.Name) } + +func cleanupNetPolicy( + t testing.TB, fromApp *cg.App, toApp *cg.App, pranges []string, +) error { + t.Helper() + + for _, prange := range pranges { + delPolCmd := exec.Command( + "cf", "remove-network-policy", fromApp.Name, toApp.Name, + "--port", prange, + "--protocol", "tcp", + ) + + out, err := delPolCmd.CombinedOutput() + if err != nil { + t.Log(string(out)) + if exErr, ok := err.(*exec.ExitError); ok { + t.Log(exErr.Error()) + t.Fatal(string(exErr.Stderr)) + } else { + t.Fatal(err) + } + } + + if err != nil { + return err + } + } + + return nil +} + +func getNetPolicyRe(elems ...any) *regexp.Regexp { + var b strings.Builder + for i := len(elems); i >= 1; i-- { + fmt.Fprintf(&b, `%%v\s+`) + } + b.WriteString(`\s+`) // to make sure last value terminates + return regexp.MustCompile(fmt.Sprintf(b.String(), elems...)) +} + +func TestClient_AddNetworkPolicy(t *testing.T) { + setup(t) + + apps, err := cgClient.AppsList() + if err != nil { + t.Fatal(err) + } + if len(apps) < 2 { + t.Fatalf("can't test without >= 2 apps, got %v", len(apps)) + } + + pranges := []string{"80-85", "443"} + err = cgClient.AddNetworkPolicy(apps[0], apps[1], pranges) + defer cleanupNetPolicy(t, apps[0], apps[1], pranges) + if err != nil { + t.Fatal(err) + } + + ckNetPolCmd := exec.Command("cf", "network-policies", "--source", apps[0].Name) + out, err := ckNetPolCmd.CombinedOutput() + got := string(out) + if err != nil { + t.Log(got) + t.Fatal(err) + } + + for _, prange := range pranges { + re := getNetPolicyRe(apps[0].Name, apps[1].Name, "tcp", prange) + if !re.MatchString(got) { + t.Errorf("wanted string matching /%v/, got:\n%v", re, got) + } + } +} diff --git a/runner-manager/cfd/sh/integration_setup.sh b/runner-manager/cfd/sh/integration_setup.sh index f0c674a..3968d07 100755 --- a/runner-manager/cfd/sh/integration_setup.sh +++ b/runner-manager/cfd/sh/integration_setup.sh @@ -71,6 +71,8 @@ fi # create a teeny app we can use to test client.AppGet cf push --no-route -k 8M -m 128M -o busybox -u process -c /bin/sh "$app_name" +# and another to test communication betwixt them +cf push --no-route -k 8M -m 128M -o busybox -u process -c /bin/sh "${app_name}_2" out_arr=( # get the credentials from key and output diff --git a/runner-manager/cfd/sh/integration_teardown.sh b/runner-manager/cfd/sh/integration_teardown.sh index 924c926..d587f2f 100755 --- a/runner-manager/cfd/sh/integration_teardown.sh +++ b/runner-manager/cfd/sh/integration_teardown.sh @@ -61,8 +61,9 @@ if [[ $org != 'sandbox-gsa' ]]; then exit 1 fi -# delete the teeny app +# delete the teeny apps cf delete -r "${args[@]}" "$app_name" +cf delete -r "${args[@]}" "${app_name}_2" # delete the deployer and key cf delete-service-key "${args[@]}" "$basename"-deployer "$basename"-key