Skip to content

Commit 698729e

Browse files
Dai.OtsukaDai.Otsuka
Dai.Otsuka
authored and
Dai.Otsuka
committed
add list subscriptions by topic v1
review ref
1 parent aa31fa4 commit 698729e

File tree

10 files changed

+445
-127
lines changed

10 files changed

+445
-127
lines changed

app/gosns/gosns.go

Lines changed: 0 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"fmt"
88
"net/http"
99
"strconv"
10-
"strings"
1110
"time"
1211

1312
"github.com/google/uuid"
@@ -146,31 +145,6 @@ func ConfirmSubscription(w http.ResponseWriter, req *http.Request) {
146145

147146
}
148147

149-
func ListSubscriptionsByTopic(w http.ResponseWriter, req *http.Request) {
150-
content := req.FormValue("ContentType")
151-
topicArn := req.FormValue("TopicArn")
152-
153-
uriSegments := strings.Split(topicArn, ":")
154-
topicName := uriSegments[len(uriSegments)-1]
155-
156-
if topic, ok := app.SyncTopics.Topics[topicName]; ok {
157-
uuid, _ := common.NewUUID()
158-
respStruct := app.ListSubscriptionsByTopicResponse{}
159-
respStruct.Xmlns = "http://queue.amazonaws.com/doc/2012-11-05/"
160-
respStruct.Metadata.RequestId = uuid
161-
respStruct.Result.Subscriptions.Member = make([]app.TopicMemberResult, 0, 0)
162-
163-
for _, sub := range topic.Subscriptions {
164-
tar := app.TopicMemberResult{TopicArn: topic.Arn, Protocol: sub.Protocol,
165-
SubscriptionArn: sub.SubscriptionArn, Endpoint: sub.EndPoint, Owner: app.CurrentEnvironment.AccountID}
166-
respStruct.Result.Subscriptions.Member = append(respStruct.Result.Subscriptions.Member, tar)
167-
}
168-
SendResponseBack(w, req, respStruct, content)
169-
} else {
170-
createErrorResponse(w, req, "TopicNotFound")
171-
}
172-
}
173-
174148
func SetSubscriptionAttributes(w http.ResponseWriter, req *http.Request) {
175149
content := req.FormValue("ContentType")
176150
subsArn := req.FormValue("SubscriptionArn")

app/gosns/gosns_test.go

Lines changed: 0 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -7,73 +7,12 @@ import (
77
"strings"
88
"testing"
99

10-
"github.com/Admiral-Piett/goaws/app/conf"
1110
"github.com/Admiral-Piett/goaws/app/test"
1211

1312
"github.com/Admiral-Piett/goaws/app"
1413
"github.com/Admiral-Piett/goaws/app/common"
1514
)
1615

17-
// TODO - add a subscription and I think this should work
18-
func TestListSubscriptionByTopicResponse_No_Owner(t *testing.T) {
19-
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "Local")
20-
defer func() {
21-
test.ResetApp()
22-
}()
23-
24-
// set accountID to test value so it can be populated in response
25-
app.CurrentEnvironment.AccountID = "100010001000"
26-
27-
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
28-
// pass 'nil' as the third parameter.
29-
req, err := http.NewRequest("POST", "/", nil)
30-
if err != nil {
31-
t.Fatal(err)
32-
}
33-
34-
form := url.Values{}
35-
form.Add("TopicArn", "arn:aws:sns:local:000000000000:local-topic1")
36-
req.PostForm = form
37-
38-
// Prepare existant topic
39-
topic := &app.Topic{
40-
Name: "UnitTestTopic1",
41-
Arn: "arn:aws:sns:local:100010001000:UnitTestTopic1",
42-
Subscriptions: []*app.Subscription{
43-
{
44-
TopicArn: "",
45-
Protocol: "",
46-
SubscriptionArn: "",
47-
EndPoint: "",
48-
Raw: false,
49-
FilterPolicy: &app.FilterPolicy{},
50-
},
51-
},
52-
}
53-
app.SyncTopics.Topics["UnitTestTopic1"] = topic
54-
55-
// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
56-
rr := httptest.NewRecorder()
57-
handler := http.HandlerFunc(ListSubscriptionsByTopic)
58-
59-
// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
60-
// directly and pass in our Request and ResponseRecorder.
61-
handler.ServeHTTP(rr, req)
62-
63-
// Check the status code is what we expect.
64-
if status := rr.Code; status != http.StatusOK {
65-
t.Errorf("handler returned wrong status code: got %v want %v",
66-
status, http.StatusOK)
67-
}
68-
69-
// Check the response body is what we expect.
70-
expected := `<Owner>` + app.CurrentEnvironment.AccountID + `</Owner>`
71-
if !strings.Contains(rr.Body.String(), expected) {
72-
t.Errorf("handler returned empty owner for subscription member: got %v want %v",
73-
rr.Body.String(), expected)
74-
}
75-
}
76-
7716
func TestGetSubscriptionAttributesHandler_POST_Success(t *testing.T) {
7817
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
7918
// pass 'nil' as the third parameter.
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
package gosns
2+
3+
import (
4+
"net/http"
5+
"strings"
6+
7+
"github.com/Admiral-Piett/goaws/app"
8+
"github.com/Admiral-Piett/goaws/app/interfaces"
9+
"github.com/Admiral-Piett/goaws/app/models"
10+
"github.com/Admiral-Piett/goaws/app/utils"
11+
"github.com/google/uuid"
12+
log "github.com/sirupsen/logrus"
13+
)
14+
15+
func ListSubscriptionsByTopicV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
16+
requestBody := models.NewListSubscriptionsByTopicRequest()
17+
ok := utils.REQUEST_TRANSFORMER(requestBody, req, false)
18+
if !ok {
19+
log.Error("Invalid Request - ListSubscriptionsByTopicV1")
20+
return utils.CreateErrorResponseV1("InvalidParameterValue", false)
21+
}
22+
23+
topicArn := requestBody.TopicArn
24+
uriSegments := strings.Split(topicArn, ":")
25+
topicName := uriSegments[len(uriSegments)-1]
26+
var topic app.Topic
27+
28+
if value, ok := app.SyncTopics.Topics[topicName]; ok {
29+
topic = *value
30+
} else {
31+
return utils.CreateErrorResponseV1("TopicNotFound", false)
32+
}
33+
34+
resultMember := make([]models.TopicMemberResult, 0)
35+
36+
for _, sub := range topic.Subscriptions {
37+
tar := models.TopicMemberResult{TopicArn: topic.Arn, Protocol: sub.Protocol,
38+
SubscriptionArn: sub.SubscriptionArn, Endpoint: sub.EndPoint, Owner: app.CurrentEnvironment.AccountID}
39+
resultMember = append(resultMember, tar)
40+
}
41+
42+
respStruct := models.ListSubscriptionsByTopicResponse{
43+
Xmlns: models.BASE_XMLNS,
44+
Result: models.ListSubscriptionsByTopicResult{
45+
Subscriptions: models.TopicSubscriptions{
46+
Member: resultMember,
47+
},
48+
},
49+
Metadata: app.ResponseMetadata{RequestId: uuid.NewString()},
50+
}
51+
return http.StatusOK, respStruct
52+
53+
}
Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
package gosns
2+
3+
import (
4+
"net/http"
5+
"testing"
6+
7+
"github.com/Admiral-Piett/goaws/app"
8+
"github.com/Admiral-Piett/goaws/app/conf"
9+
"github.com/Admiral-Piett/goaws/app/interfaces"
10+
"github.com/Admiral-Piett/goaws/app/models"
11+
"github.com/Admiral-Piett/goaws/app/test"
12+
"github.com/Admiral-Piett/goaws/app/utils"
13+
"github.com/stretchr/testify/assert"
14+
)
15+
16+
func TestListSubscriptionsByTopicV1_Not_Found(t *testing.T) {
17+
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "NoQueuesOrTopics")
18+
defer func() {
19+
test.ResetApp()
20+
utils.REQUEST_TRANSFORMER = utils.TransformRequest
21+
}()
22+
23+
utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
24+
v := resultingStruct.(*models.ListSubscriptionsByTopicRequest)
25+
*v = models.ListSubscriptionsByTopicRequest{
26+
NextToken: "",
27+
TopicArn: "not exist arn",
28+
}
29+
return true
30+
}
31+
32+
_, r := test.GenerateRequestInfo("POST", "/", nil, true)
33+
code, res := ListSubscriptionsByTopicV1(r)
34+
response, _ := res.(models.ListSubscriptionsByTopicResponse)
35+
36+
assert.Equal(t, http.StatusBadRequest, code)
37+
assert.Empty(t, response.Result.Subscriptions.Member)
38+
}
39+
40+
func TestListSubscriptionsByTopicV1_Transform_Error(t *testing.T) {
41+
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "NoQueuesOrTopics")
42+
defer func() {
43+
test.ResetApp()
44+
utils.REQUEST_TRANSFORMER = utils.TransformRequest
45+
}()
46+
47+
utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
48+
return false
49+
}
50+
51+
_, r := test.GenerateRequestInfo("POST", "/", nil, true)
52+
code, _ := ListSubscriptionsByTopicV1(r)
53+
assert.Equal(t, http.StatusBadRequest, code)
54+
}
55+
56+
func TestListSubscriptionsByTopicV1_Success_Multiple_Subscription(t *testing.T) {
57+
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "Local")
58+
defer func() {
59+
test.ResetApp()
60+
utils.REQUEST_TRANSFORMER = utils.TransformRequest
61+
}()
62+
63+
topicArn := app.SyncTopics.Topics["local-topic1"].Arn
64+
subscriptions := app.SyncTopics.Topics["local-topic1"].Subscriptions
65+
utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
66+
v := resultingStruct.(*models.ListSubscriptionsByTopicRequest)
67+
*v = models.ListSubscriptionsByTopicRequest{
68+
NextToken: "",
69+
TopicArn: topicArn,
70+
}
71+
return true
72+
}
73+
74+
_, r := test.GenerateRequestInfo("POST", "/", nil, true)
75+
code, res := ListSubscriptionsByTopicV1(r)
76+
response, _ := res.(models.ListSubscriptionsByTopicResponse)
77+
78+
assert.Equal(t, http.StatusOK, code)
79+
assert.Len(t, response.Result.Subscriptions.Member, 2)
80+
81+
expectedMember := []models.TopicMemberResult{
82+
{
83+
TopicArn: subscriptions[0].TopicArn,
84+
SubscriptionArn: subscriptions[0].SubscriptionArn,
85+
Protocol: subscriptions[0].Protocol,
86+
Owner: app.CurrentEnvironment.AccountID,
87+
Endpoint: subscriptions[0].EndPoint,
88+
},
89+
{
90+
TopicArn: subscriptions[1].TopicArn,
91+
SubscriptionArn: subscriptions[1].SubscriptionArn,
92+
Protocol: subscriptions[1].Protocol,
93+
Owner: app.CurrentEnvironment.AccountID,
94+
Endpoint: subscriptions[1].EndPoint,
95+
},
96+
}
97+
98+
assert.ElementsMatch(t, expectedMember, response.Result.Subscriptions.Member)
99+
}

app/models/responses.go

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -493,3 +493,23 @@ func (r ListSubscriptionsResponse) GetResult() interface{} {
493493
func (r ListSubscriptionsResponse) GetRequestId() string {
494494
return r.Metadata.RequestId
495495
}
496+
497+
/*** List Subscriptions By Topic Response */
498+
type ListSubscriptionsByTopicResult struct {
499+
NextToken string `xml:"NextToken"` // not implemented
500+
Subscriptions TopicSubscriptions `xml:"Subscriptions"`
501+
}
502+
503+
type ListSubscriptionsByTopicResponse struct {
504+
Xmlns string `xml:"xmlns,attr"`
505+
Result ListSubscriptionsByTopicResult `xml:"ListSubscriptionsByTopicResult"`
506+
Metadata app.ResponseMetadata `xml:"ResponseMetadata"`
507+
}
508+
509+
func (r ListSubscriptionsByTopicResponse) GetResult() interface{} {
510+
return r.Result
511+
}
512+
513+
func (r ListSubscriptionsByTopicResponse) GetRequestId() string {
514+
return r.Metadata.RequestId
515+
}

app/models/sns.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -260,3 +260,16 @@ type ListSubscriptionsRequest struct {
260260
}
261261

262262
func (r *ListSubscriptionsRequest) SetAttributesFromForm(values url.Values) {}
263+
264+
// List Subscriptions By Topic
265+
266+
func NewListSubscriptionsByTopicRequest() *ListSubscriptionsByTopicRequest {
267+
return &ListSubscriptionsByTopicRequest{}
268+
}
269+
270+
type ListSubscriptionsByTopicRequest struct {
271+
NextToken string `json:"NextToken" schema:"NextToken"` // not implemented
272+
TopicArn string `json:"TopicArn" schema:"TopicArn"`
273+
}
274+
275+
func (r *ListSubscriptionsByTopicRequest) SetAttributesFromForm(values url.Values) {}

app/router/router.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -79,20 +79,20 @@ var routingTableV1 = map[string]func(r *http.Request) (int, interfaces.AbstractR
7979
"DeleteMessageBatch": sqs.DeleteMessageBatchV1,
8080

8181
// SNS
82-
"Subscribe": sns.SubscribeV1,
83-
"Unsubscribe": sns.UnsubscribeV1,
84-
"Publish": sns.PublishV1,
85-
"ListTopics": sns.ListTopicsV1,
86-
"CreateTopic": sns.CreateTopicV1,
87-
"DeleteTopic": sns.DeleteTopicV1,
88-
"ListSubscriptions": sns.ListSubscriptionsV1,
82+
"Subscribe": sns.SubscribeV1,
83+
"Unsubscribe": sns.UnsubscribeV1,
84+
"Publish": sns.PublishV1,
85+
"ListTopics": sns.ListTopicsV1,
86+
"CreateTopic": sns.CreateTopicV1,
87+
"DeleteTopic": sns.DeleteTopicV1,
88+
"ListSubscriptions": sns.ListSubscriptionsV1,
89+
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopicV1,
8990
}
9091

9192
var routingTable = map[string]http.HandlerFunc{
9293
// SNS
9394
"SetSubscriptionAttributes": sns.SetSubscriptionAttributes,
9495
"GetSubscriptionAttributes": sns.GetSubscriptionAttributes,
95-
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopic,
9696

9797
// SNS Internal
9898
"ConfirmSubscription": sns.ConfirmSubscription,

app/router/router_test.go

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -271,20 +271,20 @@ func TestActionHandler_v0_xml(t *testing.T) {
271271
"DeleteMessageBatch": sqs.DeleteMessageBatchV1,
272272

273273
// SNS
274-
"Subscribe": sns.SubscribeV1,
275-
"Unsubscribe": sns.UnsubscribeV1,
276-
"Publish": sns.PublishV1,
277-
"ListTopics": sns.ListTopicsV1,
278-
"CreateTopic": sns.CreateTopicV1,
279-
"DeleteTopic": sns.DeleteTopicV1,
280-
"ListSubscriptions": sns.ListSubscriptionsV1,
274+
"Subscribe": sns.SubscribeV1,
275+
"Unsubscribe": sns.UnsubscribeV1,
276+
"Publish": sns.PublishV1,
277+
"ListTopics": sns.ListTopicsV1,
278+
"CreateTopic": sns.CreateTopicV1,
279+
"DeleteTopic": sns.DeleteTopicV1,
280+
"ListSubscriptions": sns.ListSubscriptionsV1,
281+
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopicV1,
281282
}
282283

283284
routingTable = map[string]http.HandlerFunc{
284285
// SNS
285286
"SetSubscriptionAttributes": sns.SetSubscriptionAttributes,
286287
"GetSubscriptionAttributes": sns.GetSubscriptionAttributes,
287-
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopic,
288288

289289
// SNS Internal
290290
"ConfirmSubscription": sns.ConfirmSubscription,

app/sns_messages.go

Lines changed: 0 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -26,27 +26,3 @@ type GetSubscriptionAttributesResponse struct {
2626
Result GetSubscriptionAttributesResult `xml:"GetSubscriptionAttributesResult"`
2727
Metadata ResponseMetadata `xml:"ResponseMetadata,omitempty"`
2828
}
29-
30-
/*** List Subscriptions By Topic Response */
31-
32-
type TopicMemberResult struct {
33-
TopicArn string `xml:"TopicArn"`
34-
Protocol string `xml:"Protocol"`
35-
SubscriptionArn string `xml:"SubscriptionArn"`
36-
Owner string `xml:"Owner"`
37-
Endpoint string `xml:"Endpoint"`
38-
}
39-
40-
type TopicSubscriptions struct {
41-
Member []TopicMemberResult `xml:"member"`
42-
}
43-
44-
type ListSubscriptionsByTopicResult struct {
45-
Subscriptions TopicSubscriptions `xml:"Subscriptions"`
46-
}
47-
48-
type ListSubscriptionsByTopicResponse struct {
49-
Xmlns string `xml:"xmlns,attr"`
50-
Result ListSubscriptionsByTopicResult `xml:"ListSubscriptionsByTopicResult"`
51-
Metadata ResponseMetadata `xml:"ResponseMetadata"`
52-
}

0 commit comments

Comments
 (0)