Skip to content

Commit

Permalink
Add option for fallback post serve action on passing empty action name (
Browse files Browse the repository at this point in the history
#1127)

* add option for fallback post serve action

* removing fallback option and from view - review comment changes
  • Loading branch information
kapishmalik authored May 6, 2024
1 parent 2cb8acc commit b12b6eb
Show file tree
Hide file tree
Showing 12 changed files with 162 additions and 37 deletions.
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

0 comments on commit b12b6eb

Please sign in to comment.