Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option for fallback post serve action on passing empty action name #1127

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 2 additions & 10 deletions core/action/action.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import (
"os"
"os/exec"
"path"
"strings"
"time"

v2 "github.com/SpectoLabs/hoverfly/core/handlers/v2"
Expand All @@ -27,12 +26,9 @@ type Action struct {
DelayInMs int
}

func NewLocalAction(actionName, binary, scriptContent string, delayInMs int) (*Action, error) {
func NewLocalAction(binary, scriptContent string, delayInMs int) (*Action, error) {

scriptInfo := &Action{}
if strings.TrimSpace(actionName) == "" {
return nil, errors.New("empty action name passed")
}

scriptInfo.DelayInMs = delayInMs

Expand All @@ -46,11 +42,7 @@ func NewLocalAction(actionName, binary, scriptContent string, delayInMs int) (*A
return scriptInfo, nil
}

func NewRemoteAction(actionName, host string, delayInMs int) (*Action, error) {

if strings.TrimSpace(actionName) == "" {
return nil, errors.New("empty action name passed")
}
func NewRemoteAction(host string, delayInMs int) (*Action, error) {

if !isValidURL(host) {
return nil, errors.New("remote host is invalid")
Expand Down
20 changes: 10 additions & 10 deletions core/action/action_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ const pythonBasicScript = "import sys\nprint(sys.stdin.readlines()[0])"
func Test_NewLocalActionMethod(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewLocalAction("test-callback", "python3", "dummy-script", 1800)
newAction, err := action.NewLocalAction("python3", "dummy-script", 1800)

Expect(err).To(BeNil())
Expect(newAction).NotTo(BeNil())
Expand All @@ -33,7 +33,7 @@ func Test_NewLocalActionMethod(t *testing.T) {
func Test_NewRemoteActionMethodWithEmptyHost(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewRemoteAction("test-callback", "", 1800)
newAction, err := action.NewRemoteAction("", 1800)

Expect(err).NotTo(BeNil())
Expect(newAction).To(BeNil())
Expand All @@ -42,7 +42,7 @@ func Test_NewRemoteActionMethodWithEmptyHost(t *testing.T) {
func Test_NewRemoteActionMethodWithInvalidHost(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewRemoteAction("test-callback", "testing", 1800)
newAction, err := action.NewRemoteAction("testing", 1800)

Expect(err).NotTo(BeNil())
Expect(err.Error()).To(Equal("remote host is invalid"))
Expand All @@ -52,7 +52,7 @@ func Test_NewRemoteActionMethodWithInvalidHost(t *testing.T) {
func Test_NewRemoteActionMethodWithHttpHost(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewRemoteAction("test-callback", "http://localhost", 1800)
newAction, err := action.NewRemoteAction("http://localhost", 1800)

Expect(err).To(BeNil())
Expect(newAction).NotTo(BeNil())
Expand All @@ -63,7 +63,7 @@ func Test_NewRemoteActionMethodWithHttpHost(t *testing.T) {
func Test_NewRemoteActionMethodWithHttpsHost(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewRemoteAction("test-callback", "https://test.com", 1800)
newAction, err := action.NewRemoteAction("https://test.com", 1800)

Expect(err).To(BeNil())
Expect(newAction).NotTo(BeNil())
Expand All @@ -74,7 +74,7 @@ func Test_NewRemoteActionMethodWithHttpsHost(t *testing.T) {
func Test_GetLocalActionViewMethod(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewLocalAction("test-callback", "python3", "dummy-script", 1800)
newAction, err := action.NewLocalAction("python3", "dummy-script", 1800)

Expect(err).To(BeNil())
actionView := newAction.GetActionView("test-callback")
Expand All @@ -88,7 +88,7 @@ func Test_GetLocalActionViewMethod(t *testing.T) {
func Test_GetRemoteActionViewMethod(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewRemoteAction("test-callback", "http://localhost:8000", 1800)
newAction, err := action.NewRemoteAction("http://localhost:8000", 1800)

Expect(err).To(BeNil())
actionView := newAction.GetActionView("test-callback")
Expand All @@ -102,7 +102,7 @@ func Test_GetRemoteActionViewMethod(t *testing.T) {

func Test_ExecuteLocalPostServeAction(t *testing.T) {
RegisterTestingT(t)
newAction, err := action.NewLocalAction("test-callback", "python3", pythonBasicScript, 0)
newAction, err := action.NewLocalAction("python3", pythonBasicScript, 0)

Expect(err).To(BeNil())

Expand Down Expand Up @@ -136,7 +136,7 @@ func Test_ExecuteRemotePostServeAction(t *testing.T) {
journalIDChannel := make(chan string, 1)
newJournal := journal.NewJournal()
journalIDChannel <- "1"
newAction, err := action.NewRemoteAction("test-callback", server.URL+"/process", 0)
newAction, err := action.NewRemoteAction(server.URL+"/process", 0)
close(journalIDChannel)
Expect(err).To(BeNil())
err = newAction.Execute(&originalPair, journalIDChannel, newJournal)
Expand All @@ -150,7 +150,7 @@ func Test_ExecuteRemotePostServeAction_WithUnReachableHost(t *testing.T) {
},
}

newAction, err := action.NewRemoteAction("test-callback", "http://test", 0)
newAction, err := action.NewRemoteAction("http://test", 0)
Expect(err).To(BeNil())

//not adding entry as update journal method will be tested in its file
Expand Down
22 changes: 15 additions & 7 deletions core/action/postserveactiondetails.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,12 +2,14 @@ package action

import (
"fmt"
"strings"
"sync"
)

type PostServeActionDetails struct {
Actions map[string]Action
RWMutex sync.RWMutex
Actions map[string]Action
FallbackAction *Action
RWMutex sync.RWMutex
}

func NewPostServeActionDetails() *PostServeActionDetails {
Expand All @@ -20,12 +22,18 @@ func NewPostServeActionDetails() *PostServeActionDetails {
func (postServeActionDetails *PostServeActionDetails) SetAction(actionName string, newAction *Action) error {

postServeActionDetails.RWMutex.Lock()
//cleanup
if existingAction, ok := postServeActionDetails.Actions[actionName]; ok {
existingAction.DeleteScript()
delete(postServeActionDetails.Actions, actionName)
if strings.TrimSpace(actionName) == "" {
if postServeActionDetails.FallbackAction != nil {
postServeActionDetails.FallbackAction.DeleteScript()
}
postServeActionDetails.FallbackAction = newAction
} else {
if existingAction, ok := postServeActionDetails.Actions[actionName]; ok {
existingAction.DeleteScript()
delete(postServeActionDetails.Actions, actionName)
}
postServeActionDetails.Actions[actionName] = *newAction
}
postServeActionDetails.Actions[actionName] = *newAction
postServeActionDetails.RWMutex.Unlock()
return nil
}
Expand Down
17 changes: 15 additions & 2 deletions core/action/postserveactiondetails_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import (
func Test_SetPostServeActionMethod(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewLocalAction("test-callback", "python3", "dummy script", 1800)
newAction, err := action.NewLocalAction("python3", "dummy script", 1800)
Expect(err).To(BeNil())

unit := action.NewPostServeActionDetails()
Expand All @@ -22,10 +22,23 @@ func Test_SetPostServeActionMethod(t *testing.T) {
Expect(unit.Actions["test-callback"].DelayInMs).To(Equal(1800))
}

func Test_SetPostServeActionMethod_WithEmptyActionName(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewLocalAction("python3", "dummy script", 1800)
Expect(err).To(BeNil())

unit := action.NewPostServeActionDetails()
err = unit.SetAction("", newAction)

Expect(err).To(BeNil())
Expect(unit.FallbackAction).NotTo(BeNil())
}

func Test_DeletePostServeActionMethod(t *testing.T) {
RegisterTestingT(t)

newAction, err := action.NewLocalAction("test-callback", "python3", "dummy script", 1800)
newAction, err := action.NewLocalAction("python3", "dummy script", 1800)
Expect(err).To(BeNil())

unit := action.NewPostServeActionDetails()
Expand Down
2 changes: 1 addition & 1 deletion core/handlers/v2/postserveactiondetails_views.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ type PostServeActionDetailsView struct {
}

type ActionView struct {
ActionName string `json:"actionName"`
ActionName string `json:"actionName,omitempty"`
Binary string `json:"binary,omitempty"`
ScriptContent string `json:"script,omitempty"`
Remote string `json:"remote,omitempty"`
Expand Down
4 changes: 4 additions & 0 deletions core/hoverfly.go
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,10 @@ func (hf *Hoverfly) processRequest(req *http.Request) (*http.Response, chan stri
journalIDChannel := make(chan string, 1)
go postServeAction.Execute(result.PostServeActionInputDetails.Pair, journalIDChannel, hf.Journal)
return result.Response, journalIDChannel
} else if hf.PostServeActionDetails.FallbackAction != nil {
journalIDChannel := make(chan string, 1)
go hf.PostServeActionDetails.FallbackAction.Execute(result.PostServeActionInputDetails.Pair, journalIDChannel, hf.Journal)
return result.Response, journalIDChannel
}
}

Expand Down
9 changes: 7 additions & 2 deletions core/hoverfly_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -467,14 +467,19 @@ func (hf *Hoverfly) GetAllPostServeActions() v2.PostServeActionDetailsView {
for actionName, action := range hf.PostServeActionDetails.Actions {
actions = append(actions, action.GetActionView(actionName))
}

if hf.PostServeActionDetails.FallbackAction != nil {
actions = append(actions, hf.PostServeActionDetails.FallbackAction.GetActionView(""))
}

return v2.PostServeActionDetailsView{
Actions: actions,
}
}

func (hf *Hoverfly) SetLocalPostServeAction(actionName string, binary string, scriptContent string, delayInMs int) error {

action, err := action.NewLocalAction(actionName, binary, scriptContent, delayInMs)
action, err := action.NewLocalAction(binary, scriptContent, delayInMs)
if err != nil {
return err
}
Expand All @@ -488,7 +493,7 @@ func (hf *Hoverfly) SetLocalPostServeAction(actionName string, binary string, sc

func (hf *Hoverfly) SetRemotePostServeAction(actionName, remote string, delayInMs int) error {

action, err := action.NewRemoteAction(actionName, remote, delayInMs)
action, err := action.NewRemoteAction(remote, delayInMs)
if err != nil {
return err
}
Expand Down
59 changes: 59 additions & 0 deletions core/hoverfly_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1379,6 +1379,36 @@ func TestHoverfly_GetPostServeActions(t *testing.T) {
Expect(postServeActions.Actions[1].DelayInMs).To(Equal(1800))
}

func TestHoverfly_GetPostServeActions_WithFallback(t *testing.T) {

RegisterTestingT(t)

unit := NewHoverflyWithConfiguration(&Configuration{})
localActionDetails := action.Action{Binary: "python3", DelayInMs: 1900}
remoteActionDetails := action.Action{Remote: "http://localhost", DelayInMs: 1800}
fallbackActionDetails := action.Action{Remote: "http://localhost:8081", DelayInMs: 1800}
actionMap := map[string]action.Action{
"test-local-callback": localActionDetails,
"test-remote-callback": remoteActionDetails,
}

unit.PostServeActionDetails.Actions = actionMap
unit.PostServeActionDetails.FallbackAction = &fallbackActionDetails
postServeActions := unit.GetAllPostServeActions()

Expect(postServeActions).NotTo(BeNil())
Expect(postServeActions.Actions).To(HaveLen(3))
Expect(postServeActions.Actions[0].ActionName).To(Equal("test-local-callback"))
Expect(postServeActions.Actions[0].Binary).To(Equal("python3"))
Expect(postServeActions.Actions[0].DelayInMs).To(Equal(1900))
Expect(postServeActions.Actions[1].ActionName).To(Equal("test-remote-callback"))
Expect(postServeActions.Actions[1].Remote).To(Equal("http://localhost"))
Expect(postServeActions.Actions[1].DelayInMs).To(Equal(1800))
Expect(postServeActions.Actions[2]).NotTo(BeNil())
Expect(postServeActions.Actions[2].Remote).To(Equal("http://localhost:8081"))
Expect(postServeActions.Actions[2].DelayInMs).To(Equal(1800))
}

func TestHoverfly_SetLocalPostServeAction(t *testing.T) {

RegisterTestingT(t)
Expand Down Expand Up @@ -1409,6 +1439,35 @@ func TestHoverfly_SetRemotePostServeAction(t *testing.T) {
Expect(unit.PostServeActionDetails.Actions["test-callback"].DelayInMs).To(Equal(1800))
}

func TestHoverfly_SetFallbackLocalPostServeAction(t *testing.T) {

RegisterTestingT(t)

unit := NewHoverflyWithConfiguration(&Configuration{})

err := unit.SetLocalPostServeAction("", "script", "dummy script", 1800)

Expect(err).To(BeNil())
Expect(unit.PostServeActionDetails.FallbackAction).NotTo(BeNil())
Expect(unit.PostServeActionDetails.FallbackAction.Binary).To(Equal("script"))
Expect(unit.PostServeActionDetails.FallbackAction.DelayInMs).To(Equal(1800))

}

func TestHoverfly_SetFallbackRemotePostServeAction(t *testing.T) {

RegisterTestingT(t)

unit := NewHoverflyWithConfiguration(&Configuration{})

err := unit.SetRemotePostServeAction("", "http://localhost:8080", 1800)

Expect(err).To(BeNil())
Expect(unit.PostServeActionDetails.FallbackAction).NotTo(BeNil())
Expect(unit.PostServeActionDetails.FallbackAction.Remote).To(Equal("http://localhost:8080"))
Expect(unit.PostServeActionDetails.FallbackAction.DelayInMs).To(Equal(1800))
}

func TestHoverfly_DeleteLocalPostServeAction(t *testing.T) {

RegisterTestingT(t)
Expand Down
2 changes: 1 addition & 1 deletion core/import.go
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ func (hf *Hoverfly) importRequestResponsePairViewsWithCustomData(pairViews []v2.
failed := 0
for i, pairView := range pairViews {

if _, ok := hf.PostServeActionDetails.Actions[pairView.Response.PostServeAction]; pairView.Response.PostServeAction != "" && !ok {
if _, ok := hf.PostServeActionDetails.Actions[pairView.Response.PostServeAction]; pairView.Response.PostServeAction != "" && !ok && hf.PostServeActionDetails.FallbackAction == nil {
importResult.SetError(fmt.Errorf("invalid post server action name provided"))
break
}
Expand Down
20 changes: 20 additions & 0 deletions functional-tests/core/ft_postserveaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,26 @@ var _ = Describe("Manage post serve actions in hoverfly", func() {
Expect(postServeActionDetails.Actions[0].DelayInMs).To(Equal(1400))
})
})

Context("start hoverfly and set fallback remote post serve action", func() {

BeforeEach(func() {
hoverfly.Start()
})

AfterEach(func() {
hoverfly.Stop()
})

It("Should set post serve action", func() {
postServeActionDetails := hoverfly.SetRemotePostServeAction("", "http://localhost:8080", 1600)
Expect(postServeActionDetails).NotTo(BeNil())
Expect(postServeActionDetails.Actions).NotTo(BeNil())
Expect(postServeActionDetails.Actions[0].ActionName).To(Equal(""))
Expect(postServeActionDetails.Actions[0].Remote).To(Equal("http://localhost:8080"))
Expect(postServeActionDetails.Actions[0].DelayInMs).To(Equal(1600))
})
})
})

Context("delete post serve action", func() {
Expand Down
17 changes: 17 additions & 0 deletions functional-tests/hoverctl/postserveaction_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,12 @@ var _ = Describe("When I use hoverctl", func() {
Expect(output).To(ContainSubstring("Success"))
})

It("should return success on setting fallback remote post-serve-action", func() {
output := functional_tests.Run(hoverctlBinary, "post-serve-action", "set", "--remote", "http://localhost", "--delay", "1500")

Expect(output).To(ContainSubstring("Success"))
})

})

Describe("delete post-serve-action", func() {
Expand Down Expand Up @@ -106,5 +112,16 @@ var _ = Describe("When I use hoverctl", func() {
Expect(output).To(ContainSubstring("1700"))
})

It("should return remote default post-serve-action", func() {
output := functional_tests.Run(hoverctlBinary, "post-serve-action", "set", "--remote", "http://localhost", "--delay", "1700")

Expect(output).To(ContainSubstring("Success"))

output = functional_tests.Run(hoverctlBinary, "post-serve-action", "get-all")
Expect(output).To(ContainSubstring("fallback"))
Expect(output).To(ContainSubstring("http://localhost"))
Expect(output).To(ContainSubstring("1700"))
})

})
})
Loading
Loading