forked from delta-io/delta-sharing
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add Lightsail terraform deployment module (#149)
- Loading branch information
1 parent
ba9394e
commit 1f64477
Showing
13 changed files
with
296 additions
and
14 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
WHITEFOX_TEST_AWS_REGION=eu-west-1 | ||
WHITEFOX_TEST_AWS_SECRET_ACCESS_KEY=weashdfgvkeuajysmjtsrq2384we | ||
WHITEFOX_TEST_AWS_ACCESS_KEY_ID=AKIAYTRD345SDUY |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
112 changes: 112 additions & 0 deletions
112
client-spark/src/test/java/io/whitefox/api/client/ApiUtils.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,112 @@ | ||
package io.whitefox.api.client; | ||
|
||
import com.fasterxml.jackson.databind.JsonNode; | ||
import com.fasterxml.jackson.databind.ObjectMapper; | ||
import io.whitefox.api.utils.ApiClient; | ||
import io.whitefox.api.utils.ApiException; | ||
|
||
import java.io.File; | ||
import java.io.FileInputStream; | ||
import java.io.IOException; | ||
import java.io.InputStream; | ||
import java.net.URI; | ||
import java.net.URISyntaxException; | ||
import java.util.function.Supplier; | ||
|
||
public class ApiUtils { | ||
/** | ||
* Returns the result of the call of the first argument (f) unless it throws an ApiException with HTTP status code 409, | ||
* in that case, returns the result of the call of the second argument (defaultValue). | ||
* If defaultValue is not dynamic, you can use also {@link ApiUtils#recoverConflict recoverConflinct}. | ||
*/ | ||
public static <T> T recoverConflictLazy(Supplier<T> f, Supplier<T> defaultValue) { | ||
try { | ||
return f.get(); | ||
} catch (ApiException e) { | ||
if (e.getCode() == 409) { | ||
return defaultValue.get(); | ||
} else { | ||
throw e; | ||
} | ||
} | ||
} | ||
|
||
/** | ||
* Returns the result of the call of the first argument (f) unless it throws an ApiException with HTTP status code 409, | ||
* in that case, returns the second argument (defaultValue). | ||
* If defaultValue is dynamic, you can use also {@link ApiUtils#recoverConflictLazy recoverConflictLazy}. | ||
*/ | ||
public static <T> T recoverConflict(Supplier<T> f, T defaultValue) { | ||
return recoverConflictLazy(f, new Supplier<T>() { | ||
@Override | ||
public T get() { | ||
return defaultValue; | ||
} | ||
}); | ||
} | ||
|
||
/** | ||
* Calls the first argument (f), if the call throws an ApiException with HTTP status code 409 will swallow the exception. | ||
*/ | ||
public static <T> void ignoreConflict(Supplier<T> f) { | ||
recoverConflict(f, null); | ||
} | ||
|
||
private static final ObjectMapper objectMapper = new ObjectMapper(); | ||
public static final String ENDPOINT_FIELD_NAME = "endpoint"; | ||
public static final String BEARER_TOKEN_FIELD_NAME = "bearerToken"; | ||
|
||
/** | ||
* Reads a resource named as the parameter, parses it following | ||
* <a href="https://github.com/delta-io/delta-sharing/blob/main/PROTOCOL.md#profile-file-format">delta sharing specification</a> | ||
* and configures an {@link ApiClient ApiClient} accordingly. | ||
*/ | ||
public static ApiClient configureApiClientFromResource(String resourceName) { | ||
try (InputStream is = ApiUtils.class.getClassLoader().getResourceAsStream(resourceName)) { | ||
return configureClientInternal(objectMapper.reader().readTree(is)); | ||
} catch (IOException e) { | ||
throw new RuntimeException(String.format("Cannot read %s", resourceName), e); | ||
} catch (NullPointerException e) { | ||
throw new RuntimeException(String.format("Cannot find resource %s", resourceName), e); | ||
} | ||
} | ||
|
||
/** | ||
* Reads a local file named as the parameter, parses it following | ||
* <a href="https://github.com/delta-io/delta-sharing/blob/main/PROTOCOL.md#profile-file-format">delta sharing specification</a> | ||
* and configures an {@link ApiClient ApiClient} accordingly. | ||
*/ | ||
public static ApiClient configureClientFromFile(File file) { | ||
try (InputStream is = new FileInputStream(file)) { | ||
return configureClientInternal(objectMapper.reader().readTree(is)); | ||
} catch (IOException e) { | ||
throw new RuntimeException(String.format("Cannot read %s", file), e); | ||
} | ||
} | ||
|
||
private static ApiClient configureClientInternal(JsonNode conf) { | ||
var endpointText = getRequiredField(conf, ENDPOINT_FIELD_NAME).asText(); | ||
var token = getRequiredField(conf, BEARER_TOKEN_FIELD_NAME).asText(); | ||
try { | ||
var endpoint = new URI(endpointText); | ||
var apiClient = new ApiClient(); | ||
apiClient.setHost(endpoint.getHost()); | ||
apiClient.setPort(endpoint.getPort()); | ||
apiClient.setScheme(endpoint.getScheme()); | ||
apiClient.setRequestInterceptor( | ||
builder -> builder.header("Authorization", String.format("Bearer %s", token))); | ||
return apiClient; | ||
} catch (URISyntaxException u) { | ||
throw new RuntimeException(String.format("Invalid endpoint syntax %s", endpointText), u); | ||
} | ||
} | ||
|
||
private static JsonNode getRequiredField(JsonNode node, String fieldName) { | ||
if (node.has(fieldName)) { | ||
return node.get(fieldName); | ||
} else { | ||
throw new RuntimeException( | ||
String.format("Cannot find required field %s in %s", fieldName, node)); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,6 +1,6 @@ | ||
{ | ||
"shareCredentialsVersion": 1, | ||
"endpoint": "http://localhost:8080/delta-api/v1/", | ||
"bearerToken": "fakeToken", | ||
"bearerToken": "token", | ||
"expirationTime": null | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
region = "eu-west-1" | ||
whitefox_token = "aSuperSecretToken" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,52 @@ | ||
provider "aws" { | ||
region = var.region | ||
} | ||
variable "region" { | ||
type = string | ||
} | ||
variable "whitefox_token" { | ||
type = string | ||
} | ||
resource "aws_lightsail_container_service" "whitefox-container-service" { | ||
name = "whitefox-container-service" | ||
power = "nano" | ||
scale = 1 | ||
is_disabled = false | ||
} | ||
|
||
resource "aws_lightsail_container_service_deployment_version" "whitefox-server" { | ||
container { | ||
container_name = "whitefox-server" | ||
image = "ghcr.io/agile-lab-dev/io.whitefox.server:latest" | ||
|
||
command = [] | ||
|
||
environment = { | ||
"WHITEFOX_SERVER_AUTHENTICATION_BEARERTOKEN" = var.whitefox_token | ||
"WHITEFOX_SERVER_AUTHENTICATION_ENABLED" = true | ||
} | ||
|
||
ports = { | ||
8080 = "HTTP" | ||
} | ||
} | ||
|
||
public_endpoint { | ||
container_name = "whitefox-server" | ||
container_port = 8080 | ||
|
||
health_check { | ||
healthy_threshold = 2 | ||
unhealthy_threshold = 2 | ||
timeout_seconds = 2 | ||
interval_seconds = 5 | ||
path = "/q/health/live" | ||
success_codes = "200" | ||
} | ||
} | ||
|
||
service_name = aws_lightsail_container_service.whitefox-container-service.name | ||
} | ||
output "public_endpoint" { | ||
value = aws_lightsail_container_service.whitefox-container-service.url | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,15 @@ | ||
# Deployment | ||
|
||
Whitefox is developed using Quarkus framework, therefore its natural habitat is a containerized environment. | ||
|
||
Due to dependencies upon Apache Hadoop, it's not possible to create GrallVM native images of whitefox (for now) | ||
so right now, you need a JVM. | ||
|
||
For your convenience, we publish on [ghcr](https://github.com/orgs/agile-lab-dev/packages?repo_name=whitefox) container | ||
images at each push on the main branch, therefore you can pick the runtime of your choice, | ||
pull the image from the registry, and you're good to go. | ||
|
||
To make things even easier we will collect ready to go guides on deploying whitefox in this section. | ||
|
||
Right now we feature the following platforms: | ||
- [Amazon lightsail](lightsail.md) |
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,90 @@ | ||
# Amazon Lightsail | ||
|
||
[Amazon Lightsail](https://aws.amazon.com/lightsail) lets you build applications and websites fast with low-cost, | ||
pre-configured cloud resources. | ||
|
||
In order to deploy a minimal and **public** setup of whitefox you'll need: | ||
|
||
- [an AWS account](https://aws.amazon.com/free/) | ||
- [Terraform installed locally](https://developer.hashicorp.com/terraform/install) | ||
- 10 minutes of your time | ||
|
||
:::warning | ||
|
||
**This is not a production ready deployment**, but is a pretty cheap one: approximately 8$ a month. | ||
|
||
::: | ||
|
||
:::danger | ||
|
||
Your secret token will be set as an environment variable of the container and will be visible to whoever | ||
has access to the Amazon Lightsail console. | ||
|
||
::: | ||
|
||
---- | ||
|
||
## Configuration | ||
|
||
You need to configure a few things: | ||
|
||
### AWS region | ||
|
||
head over to `deployment/lightsail/demo.tfvars` and change the value of `region` to your preferred AWS region. | ||
|
||
### Secret token | ||
|
||
head over to `deployment/lightsail/demo.tfvars` and change the value of `whitefox_token` to a secret string that | ||
you will need to provide as the bearer token to access whitefox API. | ||
|
||
### AWS credentials | ||
|
||
You need to provide terraform a way to authenticate to aws, so head over [terraform docs](https://registry.terraform.io/providers/hashicorp/aws/latest/docs) | ||
and find the way that suits your needs. | ||
|
||
## Show time | ||
|
||
Run: | ||
|
||
```shell | ||
cd deployment/lightsail | ||
terraform init | ||
terraform apply -var-file="demo.tfvars" | ||
``` | ||
|
||
To verify that the deployment was successful, grab the output of the previous command, especially the `public_endpoint` | ||
and issue the command: | ||
|
||
```shell | ||
curl $public_endpoint/q/health/live | ||
``` | ||
|
||
the output should be something similar to: | ||
|
||
```json | ||
{ | ||
"status": "UP", | ||
"checks": [ | ||
] | ||
} | ||
``` | ||
|
||
If you log into your aws lightsail account: https://lightsail.aws.amazon.com/ls/webapp/home/instances you should | ||
see something like this: | ||
|
||
![lightsail console](imgs/lightsail_console.png) | ||
|
||
|
||
## Wrap up | ||
|
||
Destroy everything running: | ||
|
||
```shell | ||
terraform destroy -var-file="demo.tfvars" | ||
``` | ||
|
||
:::warning | ||
|
||
**Might not be the best idea to store terraform state locally, [evaluate to configure a different backend](https://developer.hashicorp.com/terraform/language/settings/backends/configuration).** | ||
|
||
::: |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters