Skip to content

Commit 60fb4c6

Browse files
jrussettgeofffranks
authored andcommitted
Add GetSecurityGroups tests
- Add initial pagination support - Regen fakes + get all tests passing
1 parent 64a352d commit 60fb4c6

File tree

6 files changed

+643
-3
lines changed

6 files changed

+643
-3
lines changed

src/code.cloudfoundry.org/policy-server/cc_client/client.go

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,13 +22,56 @@ type CCClient interface {
2222
GetSubjectSpaces(token, subjectId string) (map[string]struct{}, error)
2323
GetLiveAppGUIDs(token string, appGUIDs []string) (map[string]struct{}, error)
2424
GetLiveSpaceGUIDs(token string, spaceGUIDs []string) (map[string]struct{}, error)
25+
GetSecurityGroups(token string) ([]SecurityGroupResource, error)
2526
}
2627

2728
type Client struct {
2829
Logger lager.Logger
2930
JSONClient json_client.JsonClient
3031
}
3132

33+
type GetSecurityGroupsResponse struct {
34+
Pagination struct {
35+
TotalPages int `json:"total_pages"`
36+
First struct {
37+
Href string `json:"href"`
38+
} `json:"first"`
39+
Last struct {
40+
Href string `json:"href"`
41+
} `json:"last"`
42+
Next struct {
43+
Href string `json:"href"`
44+
} `json:"next"`
45+
} `json:"pagination"`
46+
Resources []SecurityGroupResource `json:"resources"`
47+
}
48+
49+
type SecurityGroupResource struct {
50+
GUID string `json:"guid"`
51+
Name string `json:"name"`
52+
GloballyEnabled struct {
53+
Running bool `json:"running"`
54+
Staging bool `json:"staging"`
55+
} `json:"globally_enabled"`
56+
Rules []struct {
57+
Protocol string `json:"protocol"`
58+
Destination string `json:"destination"`
59+
Ports string `json:"ports"`
60+
Type int `json:"type"`
61+
Code int `json:"code"`
62+
Description string `json:"description"`
63+
Log bool `json:"log"`
64+
} `json:"rules"`
65+
Relationships struct {
66+
StagingSpaces struct {
67+
Data []map[string]string `json:"data"`
68+
} `json:"staging_spaces"`
69+
RunningSpaces struct {
70+
Data []map[string]string `json:"data"`
71+
} `json:"running_spaces"`
72+
} `json:"relationships"`
73+
}
74+
3275
type AppsV3Response struct {
3376
Pagination struct {
3477
TotalPages int `json:"total_pages"`
@@ -312,3 +355,39 @@ func (c *Client) GetSubjectSpaces(token, subjectId string) (map[string]struct{},
312355

313356
return subjectSpaces, nil
314357
}
358+
359+
func (c *Client) GetSecurityGroups(token string) ([]SecurityGroupResource, error) {
360+
token = fmt.Sprintf("bearer %s", token)
361+
362+
securityGroups := []SecurityGroupResource{}
363+
364+
nextPage := "?"
365+
for nextPage != "" {
366+
queryParams := strings.Split(nextPage, "?")[1]
367+
response, err := c.makeGetSecurityGroupsRequest(queryParams, token)
368+
if err != nil {
369+
return nil, err
370+
}
371+
for _, resource := range response.Resources {
372+
securityGroups = append(securityGroups, resource)
373+
}
374+
nextPage = response.Pagination.Next.Href
375+
}
376+
return securityGroups, nil
377+
}
378+
379+
func (c *Client) makeGetSecurityGroupsRequest(queryParams, token string) (*GetSecurityGroupsResponse, error) {
380+
route := "/v3/security_groups"
381+
382+
if queryParams != "" {
383+
route = fmt.Sprintf("%s?%s", route, queryParams)
384+
}
385+
386+
var response GetSecurityGroupsResponse
387+
err := c.JSONClient.Do("GET", route, nil, &response, token)
388+
if err != nil {
389+
return nil, fmt.Errorf("json client do: %s", err)
390+
}
391+
392+
return &response, nil
393+
}

src/code.cloudfoundry.org/policy-server/cc_client/client_test.go

Lines changed: 160 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -574,4 +574,164 @@ var _ = Describe("Client", func() {
574574
})
575575
})
576576
})
577+
578+
Describe("GetSecurityGroups", func() {
579+
BeforeEach(func() {
580+
fakeJSONClient.DoStub = func(method, route string, reqData, respData interface{}, token string) error {
581+
err := json.Unmarshal([]byte(fixtures.OneSecurityGroup), respData)
582+
Expect(err).ToNot(HaveOccurred())
583+
return nil
584+
}
585+
})
586+
587+
It("polls the Cloud Controller successfully", func() {
588+
sgs, err := client.GetSecurityGroups("some-token")
589+
Expect(err).NotTo(HaveOccurred())
590+
Expect(fakeJSONClient.DoCallCount()).To(Equal(1))
591+
592+
method, route, reqData, _, _ := fakeJSONClient.DoArgsForCall(0)
593+
594+
Expect(method).To(Equal("GET"))
595+
Expect(route).To(Equal("/v3/security_groups"))
596+
Expect(reqData).To(BeNil())
597+
598+
Expect(len(sgs)).To(Equal(1))
599+
Expect(sgs[0].Name).To(Equal("my-group0"))
600+
Expect(sgs[0].GUID).To(Equal("b85a788e-671f-4549-814d-e34cdb2f539a"))
601+
Expect(sgs[0].GloballyEnabled.Running).To(BeTrue())
602+
Expect(sgs[0].GloballyEnabled.Staging).To(BeFalse())
603+
Expect(sgs[0].Rules[0].Protocol).To(Equal("tcp"))
604+
Expect(sgs[0].Rules[1].Protocol).To(Equal("icmp"))
605+
})
606+
607+
Context("when there are no security groups", func() {
608+
BeforeEach(func() {
609+
fakeJSONClient.DoStub = func(method, route string, reqData, respData interface{}, token string) error {
610+
err := json.Unmarshal([]byte(fixtures.NoSecurityGroups), respData)
611+
Expect(err).ToNot(HaveOccurred())
612+
return nil
613+
}
614+
})
615+
616+
It("Returns them all", func() {
617+
sgs, err := client.GetSecurityGroups("some-token")
618+
Expect(err).NotTo(HaveOccurred())
619+
Expect(fakeJSONClient.DoCallCount()).To(Equal(1))
620+
621+
method, route, reqData, _, _ := fakeJSONClient.DoArgsForCall(0)
622+
623+
Expect(method).To(Equal("GET"))
624+
Expect(route).To(Equal("/v3/security_groups"))
625+
Expect(reqData).To(BeNil())
626+
627+
Expect(len(sgs)).To(Equal(0))
628+
})
629+
})
630+
631+
Context("when multiple security groups are returned", func() {
632+
BeforeEach(func() {
633+
fakeJSONClient.DoStub = func(method, route string, reqData, respData interface{}, token string) error {
634+
err := json.Unmarshal([]byte(fixtures.TwoSecurityGroups), respData)
635+
Expect(err).ToNot(HaveOccurred())
636+
return nil
637+
}
638+
})
639+
640+
It("Returns them all", func() {
641+
sgs, err := client.GetSecurityGroups("some-token")
642+
Expect(err).NotTo(HaveOccurred())
643+
Expect(fakeJSONClient.DoCallCount()).To(Equal(1))
644+
645+
method, route, reqData, _, _ := fakeJSONClient.DoArgsForCall(0)
646+
647+
Expect(method).To(Equal("GET"))
648+
Expect(route).To(Equal("/v3/security_groups"))
649+
Expect(reqData).To(BeNil())
650+
651+
Expect(len(sgs)).To(Equal(2))
652+
Expect(sgs[1].Name).To(Equal("my-group2"))
653+
Expect(sgs[1].GUID).To(Equal("second-guid"))
654+
Expect(sgs[1].GloballyEnabled.Running).To(BeFalse())
655+
Expect(sgs[1].GloballyEnabled.Staging).To(BeTrue())
656+
Expect(sgs[1].Rules[0].Protocol).To(Equal("tcp"))
657+
Expect(sgs[1].Rules[0].Ports).To(Equal("53"))
658+
})
659+
})
660+
661+
Context("when there are multiple pages", func() {
662+
BeforeEach(func() {
663+
fakeJSONClient.DoStub = func(method, route string, reqData, respData interface{}, token string) error {
664+
if route == "/v3/security_groups?page=2&per_page=1" {
665+
err := json.Unmarshal([]byte(fixtures.SecurityGroupsMultiplePagesPg2), respData)
666+
Expect(err).ToNot(HaveOccurred())
667+
} else if route == "/v3/security_groups?page=3&per_page=1" {
668+
err := json.Unmarshal([]byte(fixtures.SecurityGroupsMultiplePagesPg3), respData)
669+
Expect(err).ToNot(HaveOccurred())
670+
} else {
671+
err := json.Unmarshal([]byte(fixtures.SecurityGroupsMultiplePages), respData)
672+
Expect(err).ToNot(HaveOccurred())
673+
}
674+
return nil
675+
}
676+
})
677+
678+
It("returns all the security groups", func() {
679+
sgs, err := client.GetSecurityGroups("some-token")
680+
Expect(err).NotTo(HaveOccurred())
681+
Expect(fakeJSONClient.DoCallCount()).To(Equal(3))
682+
683+
method, route, reqData, _, token := fakeJSONClient.DoArgsForCall(0)
684+
685+
Expect(method).To(Equal("GET"))
686+
Expect(route).To(Equal("/v3/security_groups"))
687+
Expect(reqData).To(BeNil())
688+
Expect(token).To(Equal("bearer some-token"))
689+
690+
method, route, reqData, _, token = fakeJSONClient.DoArgsForCall(1)
691+
692+
Expect(method).To(Equal("GET"))
693+
Expect(route).To(Equal("/v3/security_groups?page=2&per_page=1"))
694+
Expect(reqData).To(BeNil())
695+
Expect(token).To(Equal("bearer some-token"))
696+
697+
method, route, reqData, _, token = fakeJSONClient.DoArgsForCall(2)
698+
699+
Expect(method).To(Equal("GET"))
700+
Expect(route).To(Equal("/v3/security_groups?page=3&per_page=1"))
701+
Expect(reqData).To(BeNil())
702+
Expect(token).To(Equal("bearer some-token"))
703+
704+
Expect(len(sgs)).To(Equal(3))
705+
Expect(sgs[0].Name).To(Equal("my-group0"))
706+
Expect(sgs[0].GUID).To(Equal("b85a788e-671f-4549-814d-e34cdb2f539a"))
707+
Expect(sgs[0].GloballyEnabled.Running).To(BeTrue())
708+
Expect(sgs[0].GloballyEnabled.Staging).To(BeFalse())
709+
Expect(sgs[0].Rules[0].Protocol).To(Equal("tcp"))
710+
Expect(sgs[0].Rules[1].Protocol).To(Equal("icmp"))
711+
Expect(sgs[1].Name).To(Equal("my-group2"))
712+
Expect(sgs[1].GUID).To(Equal("second-guid"))
713+
Expect(sgs[1].GloballyEnabled.Running).To(BeFalse())
714+
Expect(sgs[1].GloballyEnabled.Staging).To(BeTrue())
715+
Expect(sgs[1].Rules[0].Protocol).To(Equal("tcp"))
716+
Expect(sgs[1].Rules[0].Ports).To(Equal("53"))
717+
Expect(sgs[2].Name).To(Equal("my-group3"))
718+
Expect(sgs[2].GUID).To(Equal("third-guid"))
719+
Expect(sgs[2].GloballyEnabled.Running).To(BeTrue())
720+
Expect(sgs[2].GloballyEnabled.Staging).To(BeTrue())
721+
Expect(sgs[2].Rules[0].Protocol).To(Equal("tcp"))
722+
Expect(sgs[2].Rules[0].Ports).To(Equal("123"))
723+
})
724+
})
725+
726+
Context("when the json client returns an error", func() {
727+
BeforeEach(func() {
728+
fakeJSONClient.DoReturns(errors.New("kissa ja undulaatti"))
729+
})
730+
731+
It("returns a helpful error", func() {
732+
_, err := client.GetSubjectSpaces("some-token", "some-subject-id")
733+
Expect(err).To(MatchError(ContainSubstring("json client do: kissa ja undulaatti")))
734+
})
735+
})
736+
})
577737
})

src/code.cloudfoundry.org/policy-server/cc_client/fakes/cc_client.go

Lines changed: 79 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)