Skip to content

Commit

Permalink
add delete topic v1 support
Browse files Browse the repository at this point in the history
add request transform test to delete topic

revise comments
- change deletetopicv1 println to log.Info
- remove unnecessary deletetopicv1 request setAttributesFromForm

update deletetopics test to handle new mock config
  • Loading branch information
NRatSony authored and Admiral-Piett committed Sep 20, 2024
1 parent 150a02b commit 4d51d27
Show file tree
Hide file tree
Showing 10 changed files with 338 additions and 89 deletions.
47 changes: 47 additions & 0 deletions app/gosns/delete_topic.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package gosns

import (
"net/http"
"strings"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/common"
"github.com/Admiral-Piett/goaws/app/interfaces"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/utils"

log "github.com/sirupsen/logrus"
)

func DeleteTopicV1(req *http.Request) (int, interfaces.AbstractResponseBody) {
requestBody := models.NewDeleteTopicRequest()
ok := utils.REQUEST_TRANSFORMER(requestBody, req, false)
if !ok {
log.Error("Invalid Request - DeleteTopicV1")
return utils.CreateErrorResponseV1("InvalidParameterValue", false)
}

topicArn := requestBody.TopicArn
uriSegments := strings.Split(topicArn, ":")
topicName := uriSegments[len(uriSegments)-1]

log.Info("Delete Topic - TopicName:", topicName)

_, ok = app.SyncTopics.Topics[topicName]

if !ok {
return utils.CreateErrorResponseV1("TopicNotFound", false)
}

app.SyncTopics.Lock()
delete(app.SyncTopics.Topics, topicName)
app.SyncTopics.Unlock()
uuid, _ := common.NewUUID()
respStruct := models.DeleteTopicResponse{
Xmlns: "http://queue.amazonaws.com/doc/2012-11-05/",
Metadata: app.ResponseMetadata{RequestId: uuid},
}

return http.StatusOK, respStruct

}
88 changes: 88 additions & 0 deletions app/gosns/delete_topic_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
package gosns

import (
"net/http"
"testing"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/conf"
"github.com/Admiral-Piett/goaws/app/interfaces"
"github.com/Admiral-Piett/goaws/app/models"
"github.com/Admiral-Piett/goaws/app/test"
"github.com/Admiral-Piett/goaws/app/utils"
"github.com/stretchr/testify/assert"
)

func TestDeleteTopicV1_Success(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

initial_num_topics := len(app.SyncTopics.Topics)

topicName1 := "unit-topic1"

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
v := resultingStruct.(*models.DeleteTopicRequest)
*v = models.DeleteTopicRequest{
TopicArn: "arn:aws:sns:region:accountID:" + topicName1,
}
return true
}

_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, res := DeleteTopicV1(r)

response, _ := res.(models.DeleteTopicResponse)

assert.Equal(t, http.StatusOK, code)
assert.Equal(t, models.BASE_XMLNS, response.Xmlns)
assert.NotEqual(t, "", response.Metadata)

topics := app.SyncTopics.Topics
assert.Equal(t, initial_num_topics-1, len(topics))
_, ok := topics[topicName1]
assert.False(t, ok)
}

func TestDeleteTopicV1_NotFound(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "NoQueuesOrTopics")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
v := resultingStruct.(*models.DeleteTopicRequest)
*v = models.DeleteTopicRequest{
TopicArn: "asdf",
}
return true
}

_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, res := DeleteTopicV1(r)
resp := res.(models.ErrorResponse)

assert.Equal(t, http.StatusBadRequest, code)
assert.Equal(t, resp.Result.Type, "Not Found")
}

func TestDeleteTopicV1_request_transformer_error(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "BaseUnitTests")
defer func() {
test.ResetApp()
utils.REQUEST_TRANSFORMER = utils.TransformRequest
}()

utils.REQUEST_TRANSFORMER = func(resultingStruct interfaces.AbstractRequestBody, req *http.Request, emptyRequestValid bool) (success bool) {
return false
}

_, r := test.GenerateRequestInfo("POST", "/", nil, true)
code, _ := DeleteTopicV1(r)

assert.Equal(t, http.StatusBadRequest, code)
}
23 changes: 0 additions & 23 deletions app/gosns/gosns.go
Original file line number Diff line number Diff line change
Expand Up @@ -288,29 +288,6 @@ func GetSubscriptionAttributes(w http.ResponseWriter, req *http.Request) {
createErrorResponse(w, req, "SubscriptionNotFound")
}

func DeleteTopic(w http.ResponseWriter, req *http.Request) {
content := req.FormValue("ContentType")
topicArn := req.FormValue("TopicArn")

uriSegments := strings.Split(topicArn, ":")
topicName := uriSegments[len(uriSegments)-1]

log.Println("Delete Topic - TopicName:", topicName)

_, ok := app.SyncTopics.Topics[topicName]
if ok {
app.SyncTopics.Lock()
delete(app.SyncTopics.Topics, topicName)
app.SyncTopics.Unlock()
uuid, _ := common.NewUUID()
respStruct := app.DeleteTopicResponse{"http://queue.amazonaws.com/doc/2012-11-05/", app.ResponseMetadata{RequestId: uuid}}
SendResponseBack(w, req, respStruct, content)
} else {
createErrorResponse(w, req, "TopicNotFound")
}

}

// NOTE: The use case for this is to use GoAWS to call some external system with the message payload. Essentially
// it is a localized subscription to some non-AWS endpoint.
func callEndpoint(endpoint string, subArn string, msg app.SNSMessage, raw bool) error {
Expand Down
58 changes: 0 additions & 58 deletions app/gosns/gosns_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (

"github.com/Admiral-Piett/goaws/app/conf"
"github.com/Admiral-Piett/goaws/app/test"
"github.com/stretchr/testify/assert"

"github.com/Admiral-Piett/goaws/app"
"github.com/Admiral-Piett/goaws/app/common"
Expand Down Expand Up @@ -134,63 +133,6 @@ func TestListSubscriptionsResponse_No_Owner(t *testing.T) {
}
}

func TestDeleteTopichandler_POST_Success(t *testing.T) {
conf.LoadYamlConfig("../conf/mock-data/mock-config.yaml", "Local")
defer func() {
test.ResetApp()
}()

// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
req, err := http.NewRequest("POST", "/", nil)
if err != nil {
t.Fatal(err)
}

form := url.Values{}
form.Add("TopicArn", "arn:aws:sns:local:000000000000:local-topic1")
form.Add("Message", "TestMessage1")
req.PostForm = form

// Prepare existant topic
topic := &app.Topic{
Name: "local-topic1",
Arn: "arn:aws:sns:local:000000000000:local-topic1",
}
app.SyncTopics.Topics["local-topic1"] = topic

// We create a ResponseRecorder (which satisfies http.ResponseWriter) to record the response.
rr := httptest.NewRecorder()
handler := http.HandlerFunc(DeleteTopic)

// Our handlers satisfy http.Handler, so we can call their ServeHTTP method
// directly and pass in our Request and ResponseRecorder.
handler.ServeHTTP(rr, req)

// Check the status code is what we expect.
if status := rr.Code; status != http.StatusOK {
t.Errorf("handler returned wrong status code: got %v want %v",
status, http.StatusOK)
}

// Check the response body is what we expect.
expected := "</DeleteTopicResponse>"
if !strings.Contains(rr.Body.String(), expected) {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}
// Check the response body is what we expect.
expected = "</ResponseMetadata>"
if !strings.Contains(rr.Body.String(), expected) {
t.Errorf("handler returned unexpected body: got %v want %v",
rr.Body.String(), expected)
}

// Target topic should be disappeared
_, ok := app.SyncTopics.Topics["local-topic1"]
assert.False(t, ok)
}

func TestGetSubscriptionAttributesHandler_POST_Success(t *testing.T) {
// Create a request to pass to our handler. We don't have any query parameters for now, so we'll
// pass 'nil' as the third parameter.
Expand Down
14 changes: 14 additions & 0 deletions app/models/responses.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,3 +447,17 @@ func (r ListTopicsResponse) GetResult() interface{} {
func (r ListTopicsResponse) GetRequestId() string {
return r.Metadata.RequestId
}

/*** Delete Topic ***/
type DeleteTopicResponse struct {
Xmlns string `xml:"xmlns,attr"`
Metadata app.ResponseMetadata `xml:"ResponseMetadata"`
}

func (r DeleteTopicResponse) GetResult() interface{} {
return nil
}

func (r DeleteTopicResponse) GetRequestId() string {
return r.Metadata.RequestId
}
12 changes: 12 additions & 0 deletions app/models/sns.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,3 +236,15 @@ type ListTopicsRequest struct {
}

func (r *ListTopicsRequest) SetAttributesFromForm(values url.Values) {}

// DeleteTopicV1

func NewDeleteTopicRequest() *DeleteTopicRequest {
return &DeleteTopicRequest{}
}

type DeleteTopicRequest struct {
TopicArn string `json:"TopicArn" schema:"TopicArn"`
}

func (r *DeleteTopicRequest) SetAttributesFromForm(values url.Values) {}
2 changes: 1 addition & 1 deletion app/router/router.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,11 +84,11 @@ var routingTableV1 = map[string]func(r *http.Request) (int, interfaces.AbstractR
"Publish": sns.PublishV1,
"ListTopics": sns.ListTopicsV1,
"CreateTopic": sns.CreateTopicV1,
"DeleteTopic": sns.DeleteTopicV1,
}

var routingTable = map[string]http.HandlerFunc{
// SNS
"DeleteTopic": sns.DeleteTopic,
"SetSubscriptionAttributes": sns.SetSubscriptionAttributes,
"GetSubscriptionAttributes": sns.GetSubscriptionAttributes,
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopic,
Expand Down
2 changes: 1 addition & 1 deletion app/router/router_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -276,11 +276,11 @@ func TestActionHandler_v0_xml(t *testing.T) {
"Publish": sns.PublishV1,
"ListTopics": sns.ListTopicsV1,
"CreateTopic": sns.CreateTopicV1,
"DeleteTopic": sns.DeleteTopicV1,
}

routingTable = map[string]http.HandlerFunc{
// SNS
"DeleteTopic": sns.DeleteTopic,
"SetSubscriptionAttributes": sns.SetSubscriptionAttributes,
"GetSubscriptionAttributes": sns.GetSubscriptionAttributes,
"ListSubscriptionsByTopic": sns.ListSubscriptionsByTopic,
Expand Down
6 changes: 0 additions & 6 deletions app/sns_messages.go
Original file line number Diff line number Diff line change
Expand Up @@ -61,9 +61,3 @@ type ListSubscriptionsByTopicResponse struct {
Result ListSubscriptionsByTopicResult `xml:"ListSubscriptionsByTopicResult"`
Metadata ResponseMetadata `xml:"ResponseMetadata"`
}

/*** Delete Topic ***/
type DeleteTopicResponse struct {
Xmlns string `xml:"xmlns,attr"`
Metadata ResponseMetadata `xml:"ResponseMetadata"`
}
Loading

0 comments on commit 4d51d27

Please sign in to comment.