AWS Lambda with aws-sdk-go-v2 - amazon-web-services

I migrated aws-sdk-go-v2 to v0.31.0 from v0.25.0.
My code is a bit of a Frankenstein's Monster and I want to fully migrate to this version but I can't find the current location/approach for some features.
Specifically:
I had:
func HandleRequest(ctx context.Context, event events.APIGatewayV2HTTPRequest) (string, error) {}
The relevant import was "github.com/aws/aws-lambda-go/events". I had a rake around various service but can't locate an update, is that still correct?
Also func main() used to be:
func main() {
lambda.Start(HandleRequest)}
But no more Start() method, so what is the correct paradigm now ?
The sdk is a lot better, but I am missing the examples.

Are you importing both github.com/aws/aws-lambda-go/lambda and github.com/aws/aws-sdk-go-v2/service/lambda? If so, try importing the former with:
runtime "github.com/aws/aws-lambda-go/lambda"
And then call runtime.Start(HandleRequest)
As for handling events, see the samples in https://github.com/aws/aws-lambda-go/tree/master/events.

Related

tracing subscriber which async log function

I was planning on creating a new Layer for logging to gcp LogExplorer. Because we are working in rust, the api for logging is an async function call.
The tracing Layer trait exposes on_event function which is not async, which is where the problem comes in (link here)
I was thinking of ways to solve this, a simple solution which came to my mind was to send the events (the relevant fields) through a channel and then consume the channel on a tokio::spawn where my gcp client can make the grpc calls.
What I have in mind looks roughly like this (glossing over a lot of the details)
fn get_fields_from_event(event: &tracing::Event<'_>) -> LogEntry {
unimplemented!("some code here to convert to a type I can use with grpc coded for logging in gcp");
}
let (events_sender, events_receiver) = futures::channel::mpsc();
impl<S> Layer<S> for CustomLayer
where
S: tracing::Subscriber,
{
fn on_event(
&self,
event: &tracing::Event<'_>,
_ctx: tracing_subscriber::layer::Context<'_, S>,
) {
events_sender.clone().send(get_fields_from_event(event))
}
}
tokio::spawn(async move {
events_receiver.for_each(|event| async {grpc_client.send(event);});
});
Some obvious flaws I see with this approach is:
if the tokio::spawn silently exists, we might loose logging (I can safeguard against it .. but logging is kinda important for debugging so I would have to restart the process completely or manage the tokio::spawn process)
tokio::spawn itself feels a bit weird to get async based logging client supported. For some reason this feels a bit weird to me.
Are there any other alternatives or insights I am missing, or some crate which might provide support for working with async logging clients and integrating them in tracing Layer.
Thanks!

mocking and spying in golang without DI

Is there a way to mock and/or spy on methods in golang without using dependency injection. For example lets say that I want to unit test the following method
import (
"github.com/spf13/viper"
"google.golang.org/grpc"
)
func startGrpcServer(ctx context.Context, wg *sync.WaitGroup) {
defer wg.Done()
listen, err := net.Listen("tcp", fmt.Sprintf(":%v", viper.GetString("GRPC_PORT")))
if err != nil {
log.Fatal(err)
}
var opts []grpc.ServerOption
grpcServer := grpc.NewServer(opts...)
reflection.Register(grpcServer)
s := health.NewHealthServer()
proto.RegisterHealthServer(grpcServer, s)
go func() {
<-ctx.Done()
log.Print("Stopping grpc server")
grpcServer.GracefulStop()
}()
log.Print("Starting grpc server")
grpcServer.Serve(listen)
}
I want to make sure of the following
The server is started (spying on the grpcServer.Serve method.
The environment value is ready from viper.GetString method.
As you can see the packages for these methods are global imports and I am not using DI. Also this is legacy code so I cannot go and change all the code to support DI. From my reading and initial researches done you cannot use mock/spy in golang without DI. Is this correct ? or is there some way to do this ?
I came across the following but this is fairly dated How do I mock a function from another package without using dependency injection? and from what I see in this, my options are fairly limited.
Is there a way to mock and/or spy on methods in golang without using dependency injection.
No, there isn't.

How to unit test go code that interacts with Elasticsearch

I have an application that defines a type Client struct {} which talks to various other clients in my code that talk to services like github, elasticsearch etc.
Now I have the following ES code in one of my packages
type SinkService interface {
Write(context, index, mapping, doc)
}
type ESSink struct {
client *elastic.Client
}
func NewESSink() *ESSink {}
// checks if the index exists and writes the doc
func (s *ESSink) Write(context, index, mapping, doc) {}
I use this method in my main client that runs the whole application like this c.es.Write(...). Now if I want to write client_test.go I can simply make a mockESSink and use it with some stub code but that won't cover the lines written in my ES code.
How do I unit test my ES code? My ESSink uses an elastic.Client. How do I mock that?
I would like to embed some mock ES client that gives me stub responses and I will be able to test my ESSink.Write method that way.
Based on your question, I assume you're using github.com/olivere/elastic, and you want to be able to test by using stub http responses. When I first read this question, I also have never written Go test code that use ES client. So, in addition to answering this question, I'm also sharing how I find out the answer from the godocs.
First, we can see that elastic.NewClient accepts client option functions. So I checked what kind of client option functions the library provides. Turns out the library provides elastic.SetHttpClient that accepts elastic.Doer. The Doer is an interface that http.Client can implement. From here, the answer becomes clear.
So, you have to:
Change your func NewESSink() to accept http Client or elastic Client.
Write stub http Client (implements elastic.Doer).
ESSink
type ESSink struct {
client *elastic.Client
}
func NewESSink(client *elastic.Client) *ESSink {
return &ESSink{client: client}
}
Stub HttpClient
package stubs
import "net/http"
type HTTPClient struct {
Response *http.Response
Error error
}
func (c *HTTPClient) Do(*http.Request) (*http.Response, error) {
return c.Response, c.Error
}
Your testing code
func TestWrite(t *testing.T) {
// set the body and error according to your test case
stubHttpClient := stubs.HTTPClient{
Response: &http.Response{Body: ...},
Error: ...,
}
elasticClient := elastic.NewClient(elastic.SetHttpClient(stubHttpClient))
esSink := NewESSink(elasticClient)
esSink.Write(...)
}
In your production code, you can use http.Client{} when setting ES http client.

What's C++'s `using` equivalent in golang

What's C++'s using some_namespace::object equivalent in golang?
According to the question here
I can get using namespace common with statement below:
import (
. "common"
)
But this would import the entire namespace. Right now I only want to use, say platform definition, something like using common::platform
Is there an equivalent for this in Go, so that I don't have to type common.platform all the time?
The following code comes close in terms of readability, but is less efficient, since the compiler cannot inline function calls anymore.
import (
"fmt"
"strings"
)
var (
Sprintf = fmt.Sprintf
HasPrefix = strings.HasPrefix
)
And, it has the side-effect of importing the names fmt and strings into the file scope, which is something that C++'s using does not do.
There is currently no such functionality in Go.
That's not to say it will never be added: there is open proposal to add "Alias declarations" to the language.
As others said, it is not possible in Go. In Go you import packages, not functions or types from packages.
Note that you can easily achieve what you want if you create a helper package.
Let's say you want "using" the fmt.Println() and fmt.Printf() functions only. Create a helper package:
package helper
import "fmt"
func Println(a ...interface{}) (n int, err error) {
return fmt.Println(a...)
}
func Printf(format string, a ...interface{}) (n int, err error) {
return fmt.Printf(format, a...)
}
And where you want the C++'s "using" functionality, import using a dot .:
import . "helper"
func Something() {
Println("Hi")
Printf("Using format string: %d", 3)
}
The result is that only the exported identifiers of the helper package will be in scope, nothing else from the fmt package. You can use this single helper package to make functions available from packages other than fmt of course, too. helper can import any other packages and have a "proxy" or delegator function publishing their functionality.
Personally I don't feel the need of this. I would just import fmt and call its functions using fmt.Println() and fmt.Printf().
Perhaps you could rename the package:
import (
c "common"
cout2 "github.com/one/cout"
cout2 "github.com/two/cout"
)
Then you would only have to type c.Platform

Mocking method from golang package

I have been unable to find a solution to mocking methods from golang packages.
For example, my project has code that attempts to recover when Os.Getwd() returns an error. The easiest way I can thinking of making a unit test for this, is by mocking the Os.Getwd() method to return an error, and verify that the code works accordingly.
I tried using testify, but it does not seem to be possible.
Anyone have any experience with that?
My own solution was to take the method as an argument, which allow to inject a "mock" instead when testing. Additionnaly, create an exported method as public facade and an unexported one for testing.
Example:
func Foo() int {
return foo(os.Getpid)
}
func foo(getpid func() int) int {
return getpid()
}
Looks like that taking a look at the os.Getwd test could give you some example of how you could test your code. Look for the functions TestChdirAndGetwd and TestProgWideChdir.
From reading those, it seems that the tests create temporary folders.
So a pragmatic approach would be to create temporary folders, like the tests mentioned above do, then break them so os.Getwd throws an error for you to catch on your test.
Just be careful doing these operations as they can mess up your system. I'd suggest testing in a lightweight container or a virtual machine.
I know this is a bit late but, here is how you can do it.
Testing DAL or SystemCalls or package calls is usually difficult. My approach to solve this problem is to push your system function calls behind an interface and then mock the functions of those interface. For example.
type SystemCalls interface {
Getwd() error
}
type SystemCallsImplementation struct{
}
func (SystemCallsImplementation) Getwd() error{
return Os.Getwd()
}
func MyFunc(sysCall SystemCalls) error{
sysCall.Getwd()
}
With this you inject your interface that has the system calls to your function. Now you can easily create a mock implementation of your interface for testing.
like
type MockSystemCallsImplementation struct{
err error
}
func (MockSystemCallsImplementation) Getwd() error{
return err //this can be set to nil or some value in your test function
}
Hope this answers your question.
This is the limitation of go compiler, google developers don't want to allow any hooks or monkey patching. If unit tests are important for you - than you have to select a method of source code poisoning. All these methods are the following:
You can't use global packages directly.
You have to create isolated version of method and test it.
Production version of method includes isolated version of method and global package.
But the best solution is to ignore go language completely (if possible).