github.com/mweagle/Sparta@v1.15.0/explore.go (about) 1 // +build !lambdabinary 2 3 package sparta 4 5 import ( 6 "github.com/aws/aws-sdk-go/aws" 7 "github.com/aws/aws-sdk-go/service/cloudformation" 8 broadcast "github.com/dustin/go-broadcast" 9 "github.com/gdamore/tcell" 10 spartaAWS "github.com/mweagle/Sparta/aws" 11 "github.com/rivo/tview" 12 "github.com/sirupsen/logrus" 13 ) 14 15 const ( 16 broadcasterFunctionSelect = "functionSelect" 17 broadcasterFileSubmit = "fileSubmit" 18 ) 19 20 //////////////////////////////////////////////////////////////////////////////// 21 // 22 // Public 23 // 24 25 // ExploreWithInputFilter allows the caller to provide additional filters 26 // for the source files that will be used as inputs 27 func ExploreWithInputFilter(serviceName string, 28 serviceDescription string, 29 lambdaAWSInfos []*LambdaAWSInfo, 30 api APIGateway, 31 site *S3Site, 32 inputExtensions []string, 33 s3BucketName string, 34 buildTags string, 35 linkerFlags string, 36 logger *logrus.Logger) error { 37 38 // Great - everybody get's an aws session 39 awsSession := spartaAWS.NewSession(logger) 40 // Go get the stack and put the ARNs in the list of things. For that 41 // we need to get the stack resources... 42 cfSvc := cloudformation.New(awsSession) 43 input := &cloudformation.DescribeStackResourcesInput{ 44 StackName: aws.String(serviceName), 45 } 46 stackResourceOutputs, stackResourceOutputsErr := cfSvc.DescribeStackResources(input) 47 if stackResourceOutputsErr != nil { 48 return stackResourceOutputsErr 49 } 50 51 // Load the settings 52 settingsMap := loadSettings() 53 54 // Make the channel map 55 channelMap := make(map[string]broadcast.Broadcaster) 56 channelMap[broadcasterFunctionSelect] = broadcast.NewBroadcaster(1) 57 channelMap[broadcasterFileSubmit] = broadcast.NewBroadcaster(1) 58 application := tview.NewApplication() 59 60 // That's the list of functions, which we can map up against the operations to perform 61 // Create the logger first, since it will change the output sink 62 logView, logViewFocusable := newLogOutputView(awsSession, 63 application, 64 lambdaAWSInfos, 65 settingsMap, 66 logger) 67 68 focusTargets := []tview.Primitive{} 69 dropdown, selectorFocusable := newFunctionSelector(awsSession, 70 stackResourceOutputs.StackResources, 71 application, 72 lambdaAWSInfos, 73 settingsMap, 74 channelMap[broadcasterFunctionSelect], 75 logger) 76 eventDropdown, eventFocusable := newEventInputSelector(awsSession, 77 application, 78 lambdaAWSInfos, 79 settingsMap, 80 inputExtensions, 81 channelMap[broadcasterFunctionSelect], 82 logger) 83 outputView, outputViewFocusable := newCloudWatchLogTailView(awsSession, 84 application, 85 lambdaAWSInfos, 86 settingsMap, 87 channelMap[broadcasterFunctionSelect], 88 logger) 89 90 // There are four primary views 91 if selectorFocusable != nil { 92 focusTargets = append(focusTargets, selectorFocusable...) 93 } 94 if eventFocusable != nil { 95 focusTargets = append(focusTargets, eventFocusable...) 96 } 97 if logViewFocusable != nil { 98 focusTargets = append(focusTargets, logViewFocusable...) 99 } 100 if outputViewFocusable != nil { 101 focusTargets = append(focusTargets, outputViewFocusable...) 102 } 103 104 // Make it easy and use a Flex layout... 105 flex := tview.NewFlex(). 106 SetDirection(tview.FlexRow). 107 AddItem(dropdown, 3, 0, true). 108 AddItem(tview.NewFlex(). 109 SetDirection(tview.FlexColumn). 110 AddItem(eventDropdown, 0, 1, false). 111 AddItem(logView, 0, 2, false), 0, 1, false). 112 AddItem(outputView, 0, 1, false) 113 114 // Run it... 115 application.SetRoot(flex, true).SetFocus(flex) 116 currentIndex := 0 117 application.SetInputCapture(func(event *tcell.EventKey) *tcell.EventKey { 118 logger.WithFields(logrus.Fields{ 119 "Key": event.Key(), 120 "Name": event.Name(), 121 "Modifier": event.Modifiers(), 122 }).Debug("Input key") 123 124 switch event.Key() { 125 case tcell.KeyTab, 126 tcell.KeyBacktab: 127 128 direction := 1 129 if event.Key() == tcell.KeyBacktab { 130 direction = -1 131 } 132 nextIndex := (currentIndex + direction*1) % len(focusTargets) 133 application.SetFocus(focusTargets[nextIndex]) 134 currentIndex = nextIndex 135 default: 136 // NOP 137 } 138 return event 139 }) 140 return application.Run() 141 142 } 143 144 // Explore is an interactive command that brings up a GUI to test 145 // lambda functions previously deployed into AWS lambda. It's not supported in the 146 // AWS binary build 147 func Explore(serviceName string, 148 serviceDescription string, 149 lambdaAWSInfos []*LambdaAWSInfo, 150 api APIGateway, 151 site *S3Site, 152 s3BucketName string, 153 buildTags string, 154 linkerFlags string, 155 logger *logrus.Logger) error { 156 157 return ExploreWithInputFilter(serviceName, 158 serviceDescription, 159 lambdaAWSInfos, 160 api, 161 site, 162 []string{"json"}, 163 s3BucketName, 164 buildTags, 165 linkerFlags, 166 logger) 167 }