Skip to content

Commit 636118e

Browse files
authored
Merge pull request #47 from pranav-bhatt/master
Getting Image-hub functional with Istio
2 parents 2f32f05 + 8a4491a commit 636118e

File tree

6 files changed

+98
-23
lines changed

6 files changed

+98
-23
lines changed

README.md

Lines changed: 52 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,67 @@
1414
Image Hub is a sample application written to run on [Consul](https://meshery.layer5.io/docs/service-meshes/adapters/consul) for exploring WebAssembly modules used as Envoy filters. This demo application has been enabled by experimental works of [Nic Jackson](https://twitter.com/sheriffjackson) of HashiCorp, and [Kanishkar J](https://twitter.com/_kanishkarj_), [Lee Calcote](https://twitter.com/lcalcote), and other contributors of Layer5.
1515

1616

17-
### Deployment Instructions (pending [meshery-consul/issues/2](https://github.com/layer5io/meshery-consul/issues/2)):
17+
## Deployment Instructions
18+
19+
Image Hub supports Envoy-based data planes. Deployment instructions for each supported service mesh are below.
20+
21+
### Using Istio (pending [PR #196](https://github.com/layer5io/meshery-istio/pull/196)+release; clone and do make run for now):
22+
1) Use [Meshery](https://github.com/layer5io/meshery) to deploy [istio](https://github.com/layer5io/advanced-istio-service-mesh-workshop/blob/master/lab-1/README.md) and the Image Hub sample application (Management > Istio > Manage Sample Application Lifecycle > Image-Hub ) onto the Istio service mesh.
23+
2) To map `imagehub.meshery.io` to the appropriate IP, run the following command to add the appropriate entry in the `"\etc\hosts"` file:
24+
25+
```
26+
echo $(kubectl get nodes --selector=kubernetes.io/role!=master -o jsonpath={.items[0].status.addresses[?\(@.type==\"InternalIP\"\)].address})' 'imagehub.meshery.io | sudo tee -a /etc/hosts
27+
```
28+
3) To get the environment port, run the following command:
29+
```
30+
echo $(kubectl get svc istio-ingressgateway -n istio-system -o jsonpath='{.spec.ports[1].nodePort}')
31+
```
32+
4) Access the web UI using:
33+
```
34+
http://imagehub.meshery.io:<environment port>
35+
```
36+
37+
38+
### Using Consul:
1839
1940
1) Deploy the latest Consul:
2041
21-
```bash
22-
helm repo add hashicorp https://helm.releases.hashicorp.com # Adds helm hashicorp repo
23-
helm install consul hashicorp/consul -f config/consul-values.yaml # Setup custom Consul with support for WASM
24-
```
42+
```bash
43+
helm repo add hashicorp https://helm.releases.hashicorp.com # Adds helm hashicorp repo
44+
helm install consul hashicorp/consul -f config/consul-values.yaml # Setup custom Consul with support for WASM
45+
```
2546
2647
2) Use [Meshery](https://github.com/layer5io/meshery) to deploy the Image Hub sample application onto the Consul service mesh.
2748
28-
### Use Image Hub
49+
3) Find the port assigned to the `ingess` service:
50+
51+
```
52+
kubectl get svc ingess
53+
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
54+
ingess NodePort 10.97.34.25 <none> 80:31118/TCP 27m
55+
```
56+
57+
4) Open http://localhost:31118 (where 31118 is your environment's port number).
58+
59+
## Use Image Hub
60+
61+
1. Upon visiting the image-hub homepage, we would need to signup for an account! Go ahead and click the "Sign Up" button in the top right.
62+
1. Enter the login details, and select a plan; Personal gives you 10 pulls per minute, Team gives you 100 pulls per minute, and Enterprise will give you 1000 pulls per minute.
63+
1. After signing up, you should be redirected to the login page, where you can login and start using the sample app.
64+
1. On the main page, open up the network network tab, and reload the page. This will allow you to see the request-response of the app.
65+
1. Go ahead and click the download button a couple of times. You'll notice that there is nothing actually limiting you from crossing the number of pulls according to the plan you chose!
66+
1. Alternatively you could test the above by navigating to http://imagehub.meshery.io:<environment port>/pull, and then looking at the resquest-responses.
67+
68+
## Deploying the Rate Limiter WASM Filter for Envoy
2969
30-
1. Find the port assigned to the `ingess` service:
70+
1. Go back to Management > Istio and under "Apply Service Mesh Configuration" make sure to apply "Automatic Sidecar Injection"
71+
1. Open up a terminal, and run `kubectl get pods` to get a list of running pods. You should be able to see 2 pods, `web` and `api`. Now run
72+
the command `kubectl delete pods <exact web pod name> <exact api pod name>`. This will cause kubernetes to respawn them with the updated configuration.
73+
1. Go back to Management > Istio and under "Apply Service Mesh Configuration", select the `Envoy Filter for Image Hub` option, and wait for a few seconds.
3174
32-
```
33-
kubectl get svc ingess
34-
NAME TYPE CLUSTER-IP EXTERNAL-IP PORT(S) AGE
35-
ingess NodePort 10.97.34.25 <none> 80:31118/TCP 27m
36-
```
75+
## Use Image hub with a WASM filter
3776
38-
1. Open http://localhost:31118 (where 31118 is your environment's port number).
39-
1. Test your ability to "pull" an image (images are not in fact pulled, but an HTTP request is sent to the backend `api`). You should not be able to pull an image.
77+
1. Test your ability to "pull" an image (images are not in fact pulled, but an HTTP request is sent to the backend `api`). You would not be able to pull an image, and the response would say "unauthorized".
4078
1. Sign up a new user and select a subscription plan.
4179
1. Login as that user.
4280
1. Test your ability to "pull" an image. You should be able to pull an image.

rate-limit-filter/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,10 @@ edition = "2018"
99
crate-type = ["cdylib"]
1010

1111
[dependencies]
12-
proxy-wasm = "0.1.0"
12+
wasm-bindgen = "0.2"
13+
proxy-wasm = "^0.1"
1314
serde = { version = "1.0", default-features = false, features = ["derive"] }
1415
bincode = "1.0"
16+
#postgres = "^0.19.0"
1517
base64 = "0.12.1"
1618
serde_json ="1.0"

rate-limit-filter/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# wasm_test
143 KB
Binary file not shown.

rate-limit-filter/src/lib.rs

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
mod rate_limiter;
22

3+
//use postgres::{Client, Error, NoTls};
34
use proxy_wasm::traits::*;
45
use proxy_wasm::types::*;
56
use rate_limiter::RateLimiter;
@@ -16,14 +17,31 @@ pub fn _start() {
1617
}
1718

1819
#[derive(Debug)]
19-
struct UpstreamCall {}
20+
struct UpstreamCall {
21+
//paths: Vec<String>,
22+
}
2023

2124
impl UpstreamCall {
2225
fn new() -> Self {
23-
return Self {};
26+
return Self {
27+
//paths: retrieve().unwrap(),
28+
};
2429
}
2530
}
2631

32+
/*
33+
fn retrieve() -> Result<Vec<String>, Error> {
34+
let mut client = Client::connect("host=localhost user=postgres dbname=mesherydb", NoTls)?;
35+
let array = client
36+
.query("SELECT PathName FROM Paths", &[])?
37+
.iter()
38+
.map(|x| x.get(0))
39+
.collect();
40+
Ok(array)
41+
}
42+
*/
43+
44+
//to be removed
2745
static ALLOWED_PATHS: [&str; 4] = ["/auth", "/signup", "/upgrade", "/pull"];
2846
static CORS_HEADERS: [(&str, &str); 5] = [
2947
("Powered-By", "proxy-wasm"),
@@ -52,6 +70,12 @@ impl HttpContext for UpstreamCall {
5270
return Action::Continue;
5371
}
5472
}
73+
/*
74+
if let Some(path) = self.get_http_request_header(":path") {
75+
if self.paths.binary_search(&path.to_string()).is_ok() {
76+
return Action::Continue;
77+
}
78+
}*/
5579
if let Some(header) = self.get_http_request_header("Authorization") {
5680
if let Ok(token) = base64::decode(header) {
5781
let obj: Data = serde_json::from_slice(&token).unwrap();
@@ -61,13 +85,22 @@ impl HttpContext for UpstreamCall {
6185
let mn = (tm.as_secs() / 60) % 60;
6286
let _sc = tm.as_secs() % 60;
6387
let mut rl = RateLimiter::get(obj.username, obj.plan);
88+
89+
let mut headers = CORS_HEADERS.to_vec();
90+
let count: String;
91+
6492
if !rl.update(mn as i32) {
65-
self.send_http_response(429, CORS_HEADERS.to_vec(), Some(b"Limit exceeded.\n"));
93+
count = rl.count.to_string();
94+
headers.append(&mut vec![("x-rate-limit", &count), ("x-app-user", &rl.key)]);
95+
self.send_http_response(429, headers, Some(b"Limit exceeded.\n"));
6696
rl.set();
6797
return Action::Pause;
6898
}
6999
proxy_wasm::hostcalls::log(LogLevel::Debug, format!("Obj {:?}", &rl).as_str()).ok();
100+
count = rl.count.to_string();
70101
rl.set();
102+
headers.append(&mut vec![("x-rate-limit", &count), ("x-app-user", &rl.key)]);
103+
self.send_http_response(200, headers, Some(b"All Good!\n"));
71104
return Action::Continue;
72105
}
73106
}

rate-limit-filter/src/rate_limiter.rs

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ use serde::{Deserialize, Serialize};
55

66
#[derive(Debug, Serialize, Deserialize, Clone)]
77
pub struct RateLimiter {
8-
rpm: Option<u32>,
9-
min: i32,
10-
count: u32,
11-
key: String,
8+
pub rpm: Option<u32>,
9+
pub min: i32,
10+
pub count: u32,
11+
pub key: String,
1212
}
1313

1414
impl RateLimiter {
@@ -58,7 +58,8 @@ impl RateLimiter {
5858
proxy_wasm::hostcalls::log(
5959
LogLevel::Debug,
6060
format!("Obj {:?} {:?}", self.count, self.rpm).as_str(),
61-
).ok();
61+
)
62+
.ok();
6263
if let Some(sm) = self.rpm {
6364
if self.count > sm {
6465
return false;

0 commit comments

Comments
 (0)