How to get host name when testing using GAE? - unit-testing

When using the local development server, the port for my default service always defaults to 8080. However, when I use aetest, the port number always changes. The command used to start the local server when unit testing specifies --port=0. However, since this is in the app engine package, I do not want to modify it. I also can't specify the port number manually since tests are run using go test and not dev_appserver.py.
What I need
The code I am testing requires a particular response from a different microservice to continue execution successfully. To keep testing to this microservice, I am trying to set up a fake endpoint to provide me with the response I need.
Sample of code being tested
func Sample(c *gin.Context) {
...
url := os.Getenv("some_service") + "/some-endpoint"
req, err := http.NewRequest("POST", url, r.Body)
if err != nil {
// error handling
}
...
}
I need the host of the current service being tested to be able to set dummy environment variables for another microservice it interacts with. The host url should be the url of the service currently undergoing tests. This way I can use factory responses since I am not testing the other services in this set of tests.
What I've Tried
Using appengine.DefaultVersionHostname(), however this returns an empty string
Using the http request I create to get the url from that, however it does not include the host as needed (just the path)
Question
Is there any way to obtain the host for the local development server when running unit tests in GAE? Or, is there a way to specify the port number for app engine tests?

I was able to achieve my goal by first getting the list of modules. (It is likely the service name you are looking for will be default, however I chose to use the first name in the list anyways). Using the module name, I got the default version for the module. Using both of these (and an empty instance name), I was able to get the module host name which provided the value I was looking for.
A code sample is shown below:
ml, - := module.List(ctx)
mv, _ := module.DefaultVersion(ctx, ml[0])
hn, _ := appengine.ModuleHostname(ctx, ml[0], mv, "")
Thanks to Dan for pointing me in the right direction.

Related

How Do I Test A Camel Route That Reads From A Directory?

I am creating a Camel application that reads files dropped into a directory on an FTP server, converts them and uploads to a REST API.
If I create a route that reads a file like this:
from("file://target/input?delay=5s")
.choice()
.when(header(Exchange.FILE_NAME).endsWith(".xml"))
.unmarshal(jaxb)
The target/input directory has to exist which then makes testing a bit awkward as my test resources might not be in the correct directory.
In my test it would be easier to just get the contents of the test file and put it into the unmarshal part of the route
from("direct:xml")
.unmarshal(jaxb)
How do I make my Route flexible enough to test without just copying the whole route to a test class and modifying the input component?
You can simply make your from endpoint configurable and configure it through application properties.
For example if you use Spring:
#Value("${endpoint.consumer}")
private String consumerEndpoint;
...
from(consumerEndpoint)
...
You can then provide a test configuration that configures the endpoint as direct:input and use a ProducerTemplate to send test messages with different payloads to this endpoint.
Real application properties:
endpoint.consumer=file://target/input?delay=5s
Test properties:
endpoint.consumer=direct:input
Like this you get rid of any file endpoints in your tests.
If you also got to endpoints, you can make them configurable too. You can turn them into mocks in your tests by configure them as mock:whatever.

Why do I get a 404 for my static webpage?

I’ve been working for about 2 years developing full stack apps (which were fairly mature when I get to them initially) and am starting up my first from scratch. I spent the day spinning up an EC2 instance, loading the dependencies for my stack (Postgres, golang, react), and all the other frills a shiny new machine needs (tmux, npm, vim plugins, git integration etc). I’m now stuck.
I used create-react-app to get started on my front end and running npm start to have a build going. To see this, I can go to my instanceip:3000.
I created golang server code which is serving up on port 8080 and I can hit my helloworld code by going to instanceip:8080/hello.
I added an axios call in my react code to get endpoint /hello which returns a 404.
I also attempted to make my golang handle the index.js as a static page for the instanceip:8080 and that returns a 404.
How do I get my different ports to play nice? I can’t figure out what I’m missing here.
Here’s a snippet of my server code in main:
indexLoc := os.Genenv(webRootEnv) + "/index.html" // verified this is the correct path to my static index.html file by logging it out
fs := http.FileServer(http.Dir(indexLoc))
http.ListenAndServe(":8080", nil)
http.Handle("/", fs)
Anyone have any ideas what I’m missing? Thanks in advance!
There are two things that could be the cause:
You're giving a file name to http.Dir, which expects a directory.
Your handler is registered after calling ListenAndServe, thus making it useless (http.Handle is never called)
You could fix it by changing your code like this:
indexLoc := os.Genenv(webRootEnv) // webRootEnv is a directory path
fs := http.FileServer(http.Dir(indexLoc))
http.Handle("/", fs) // register handler before listening
http.ListenAndServe(":8080", nil)
You might also want to handle the error returned from ListenAndServe to prevent silent failures of your program

Inspec (Kitchen) Multiple Control / Target Types

It doesn't seem as if I am able to run Inspec against multiple targets using different controls. For instance I have the following:
control "aws" do
describe aws_ec2_instance(name: 'Terraform Test Instance') do
it { should exist }
end
end
And I have the following
control 'operating_system' do
describe command('lsb_release -a') do
its('stdout') { should match (/Ubuntu/) }
end
end
When I run inspec directly I can pass -t for either ssh or aws, and the aws control works when I pass the aws target (aws://us-east-1) and the operating system control passes when I pass the ssh target.
Is there a way to make BOTH of these run using Kitchen-Inspec? I found the feature request that was closed by Inspec team that multiple targets is out of scope Issue 268, I didn't know however if Kitchen addressed this since it wraps Inspec.
No, this is not supported by Kitchen-Inspec. We only aim to support host-based tests since it's part of an integration testing cycle for that host.

strongloop/loopback - Change connection string based on route value

My application's users are geographically dispersed and data is stored in various regions. Each region has it's own data center and database server.
I would like to include a route value to indicate the region that the user wants to access and connect to, as follows:
/api/region/1/locations/
/api/region/2/locations/
/api/region/3/locations/
Depending on the region passed in, I would like to change the connection string being used. I assume this can be performed somewhere in the middleware chain, but don't know where/how. Any help is appreciated!
What should not be done
Loopback provides a method MyModel.attachTo (doesnt seem to be documented, but a reference to it is made there ).
But since it is a static method, it affects the entire Model, not a single instance.
So for this to work on a per-request basis, you must switch the DB right before the call to the datasource method, to make sure nothing async starts in between. I don't think this is possible.
This is an example using an operation hook (and define all datasources, include dbRegion1 below in datasources.json)
Bad, don't that below. Just for reference
Region.observe('loaded', function filterProperties(ctx, next) {
app.models.Region.attachTo(app.dataSources.dbRegion1);
}
But then you will most likely face concurrency issues when your API receives multiple requests in a short time.
(Another way to see it is that the server is no longer truly stateless, execution will not depend only on inputs but also on a shared state).
The hook may set region2 for request 2 while the method called after the hook was expecting to use region1 for request 1. This will be the case if something async is triggered between the hook and the actual call to the datasource method.
So ultimately, I don't think you should do that. I'm just putting it there because some people have recommended it in other SO posts, but it's just bad.
Potential option 1
Build an external re-routing server, that will re-route the requests from the API server to the appropriate region database.
Use the loopback-connector-rest in your API server to consume this microservice, and use it as a single datasource for all your models. This provides abstraction over database selection.
Then of course there is still the matter of implementing the microservice, but maybe you can find some other ORM than loopback's that will support database sharding, and use it in that microservice.
Potential option 2
Create a custom loopback connector that will act as router for MySQL queries. Depending on region value passed inside the query, re-route the query to the appropriate DB.
Option 3
Use a more distributed architecture.
Write a region-specific server to persist region-specific data.
Run for instance 3 different servers, each one configured for a region.
+ 1 common server for routing
Then build a routing middleware for your single user-facing REST api server.
Basic example:
var express = require('express');
var request = require('request');
var ips = ['127.0.0.1', '127.0.0.2'];
app.all('/api/region/:id', function (req, res, next) {
console.log('Reroute to region server ' + req.params.id);
request(ips[req.params.id], function (error, response, body) {
if (err) return next(err);
next(null, body);
});
});
Maybe this option is the easiest to do

How do you get the python Google App Engine development server (dev_server.py) running for unit test in GWT?

So, I have a GWT client, which interacts with a Python Google App Engine server. The client makes request to server resources, the server responds in JSON. It is simple, no RPC or anything like that. I am using Eclipse to develop my GWT code.
I have GWTTestCase test that I would like to run. Unfortunately, I have no idea how to actually get the google app engine server running per test. I had the bright idea below of trying to start the app engine server from the command line, but of course this does not work, as Process and ProcessBuilder are not classes that the GWT Dev kit actually contains.
package com.google.gwt.sample.quizzer.client;
import java.io.IOException;
import java.lang.ProcessBuilder;
import java.lang.Process;
import com.google.gwt.junit.client.GWTTestCase;
public class QuizzerTest extends GWTTestCase {
public String getModuleName() {
return "com.google.gwt.sample.quizzer.Quizzer";
}
public void gwtSetUp(){
ProcessBuilder pb = new ProcessBuilder("dev_appserver.py",
"--clear_datastore",
"--port=9000",
"server_python");
try {
p = pb.start();
} catch (IOException e) {
System.out.println("Something happened when starting the app server!");
}
public void gwtTearDown(){ p.destroy(); }
public void testSimple() {
//NOTE: do some actual network testing from the GWT client to GAE here
assertTrue(true);}
}
I get the following errors when compiling this file:
[ERROR] Line 21: No source code is available for type java.lang.Process; did you forget to inherit a required module?
[ERROR] Line 30: No source code is available for type java.lang.ProcessBuilder; did you forget to inherit a required module?
As you can see below, I basically want it to be the case that per test it:
Starts a datastore-empty instance of my GAE server
runs the test across the network, against this server instance.
Stop the server
Of course, report the result of the test back to me.
Does anyone have a good way of doing this? Partial solutions are welcome! Hacks are fine as well. Maybe some progress on this problem could be made by editing the ".launch" config file? The only important criteria is that I would like to "unit test" portions of my GWT code against my actual GAE Python server.
Thank you.
I would recommend creating an Ant target for this - take a look at this page for the full ant build file for GWT.
Then, as the first line of the testing target, add an execution task to start the server. Look here for exec docs.
Then set up that ant task in your IDE. This way you get the server running before your tests irrespective of where you run the tests from, and it can be integrated into your build process if you want.