Skip to content

Commit

Permalink
Merge sample 1 and 2 (#113)
Browse files Browse the repository at this point in the history
* Update README.md for 1.hello-world.

Update README.md for 1.hello-world to reflect latest version.

* Changing samples 1 and 2 to share the same sample apps.
  • Loading branch information
artursouza authored Nov 25, 2019
1 parent e269677 commit 6656056
Show file tree
Hide file tree
Showing 14 changed files with 96 additions and 571 deletions.
83 changes: 70 additions & 13 deletions 1.hello-world/README.md
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
# Hello World

This tutorial will demonstrate how to get Dapr running locally on your machine. We'll be deploying a Node.js app that subscribes to order messages and persists them. The following architecture diagram illustrates the components that make up this sample:
This tutorial will demonstrate how to get Dapr running locally on your machine. We'll be deploying a Node.js app that subscribes to order messages and persists them. Later on, we'll deploy a Python app to act as the publisher. The following architecture diagram illustrates the components that make up this sample:

![Architecture Diagram](./img/Architecture_Diagram.png)

## Prerequisites
This sample requires you to have the following installed on your machine:
- [Docker](https://docs.docker.com/)
- [Node.js version 8 or greater](https://nodejs.org/en/)
- [Python 3.x](https://www.python.org/downloads/)
- [Postman](https://www.getpostman.com/) [Optional]

## Step 1 - Setup Dapr
Expand Down Expand Up @@ -107,12 +108,12 @@ This calls out to our Redis cache to grab the latest value of the "order" key, w

1. Install dependencies: `npm install`. This will install `express` and `body-parser`, dependencies that are shown in our `package.json`.

2. Run Node.js app with Dapr: `dapr run --app-id mynode --app-port 3000 --port 3500 node app.js`.
2. Run Node.js app with Dapr: `dapr run --app-id nodeapp --app-port 3000 --port 3500 node app.js`.

The command should output text that looks like the following, along with logs:

```
Starting Dapr with id mynode on port 3500
Starting Dapr with id nodeapp. HTTP Port: 3500. gRPC Port: 9165
You're up and running! Both Dapr and your app logs will appear here.
...
```
Expand All @@ -125,14 +126,14 @@ Now that Dapr and our Node.js app are running, let's POST messages against it. *
You can do this using `curl` with:

```sh
curl -XPOST -d @sample.json http://localhost:3500/v1.0/invoke/mynode/method/neworder
curl -XPOST -d @sample.json http://localhost:3500/v1.0/invoke/nodeapp/method/neworder
```

You can also do this using the Visual Studio Code [Rest Client Plugin](https://marketplace.visualstudio.com/items?itemName=humao.rest-client)

[sample.http](sample.http)
```http
POST http://localhost:3500/v1.0/invoke/mynode/method/neworder
POST http://localhost:3500/v1.0/invoke/nodeapp/method/neworder
{
"data": {
Expand All @@ -143,27 +144,27 @@ POST http://localhost:3500/v1.0/invoke/mynode/method/neworder

Or you can use the Postman GUI

Open Postman and create a POST request against `http://localhost:3500/v1.0/invoke/mynode/method/neworder`
Open Postman and create a POST request against `http://localhost:3500/v1.0/invoke/nodeapp/method/neworder`
![Postman Screenshot](./img/postman1.jpg)
In your terminal window, you should see logs indicating that the message was received and state was updated:
```bash
== APP == Got a new order! Order ID: 42
== APP == Successfully persisted state
== APP == Successfully persisted state.
```

## Step 5 - Confirm Successful Persistence

Now, let's just make sure that our order was successfully persisted to our state store. Create a GET request against: `http://localhost:3500/v1.0/invoke/mynode/method/order`. **Note**: Again, be sure to reflect the right port if you chose a port other than 3500.
Now, let's just make sure that our order was successfully persisted to our state store. Create a GET request against: `http://localhost:3500/v1.0/invoke/nodeapp/method/order`. **Note**: Again, be sure to reflect the right port if you chose a port other than 3500.

```sh
curl http://localhost:3500/v1.0/invoke/mynode/method/order
curl http://localhost:3500/v1.0/invoke/nodeapp/method/order
```

or using the Visual Studio Code [Rest Client Plugin](https://marketplace.visualstudio.com/items?itemName=humao.rest-client)

[sample.http](sample.http)
```http
GET http://localhost:3500/v1.0/invoke/mynode/method/order
GET http://localhost:3500/v1.0/invoke/nodeapp/method/order
```

or use the Postman GUI
Expand All @@ -172,15 +173,71 @@ or use the Postman GUI

This invokes the `/order` route, which calls out to our Redis store for the latest data. Observe the expected result!

## Step 7 - Run the Python App with Dapr

Let's take a look at our Python App to see how another application can invoke the Node App via Dapr without being aware of the destination's hostname or port. In the `app.py` file we can find the endpoint definition to call the Node App via Dapr.

```python
dapr_port = os.getenv("DAPR_HTTP_PORT", 3500)
dapr_url = "http://localhost:{}/v1.0/invoke/nodeapp/method/neworder".format(dapr_port)
```
It is important to notice the Node App's name (`nodeapp`) in the URL, it will allow Dapr to redirect the request to the right API endpoint. This name needs to match the name used to run the Node App earlier in this exercise.

The code block below shows how the Python App will incrementally post a new orderId every second, or print an exception if the post call fails.
```python
n = 0
while True:
n += 1
message = {"data": {"orderId": n}}

try:
response = requests.post(dapr_url, json=message)
except Exception as e:
print(e)

time.sleep(1)
```

Now we can open a **new** command line terminal and go to the `1.hello-world` directory.

1. Install dependencies via `pip install requests` or `pip3 install requests`, depending on your local setup.

2. Start the Python App with Dapr: `dapr run --app-id pythonapp python app.py` or `dapr run --app-id pythonapp python3 app.py`

3. If all went well, the **other** terminal, running the Node App, should log entries like these:

```
Got a new order! Order ID: 1
Successfully persisted state
Got a new order! Order ID: 2
Successfully persisted state
Got a new order! Order ID: 3
Successfully persisted state
```

4. Now, we perform a GET request a few times and see how the orderId changes every second (enter it into the web browser, use Postman, or curl):

```http
GET http://localhost:3500/v1.0/invoke/nodeapp/method/order
```
```json
{
"orderId": 3
}
```

> **Note**: we did not run `dapr init` in the **second** command line terminal because dapr was already setup on your local machine initially, running this command again would fail.
## Step 6 - Cleanup

To stop your services from running, simply stop the "dapr run" process. Alternatively, you can spin down each of your services with the Dapr CLI "stop" command. For example, to spin down your Node service, run:
To stop your services from running, simply stop the "dapr run" process. Alternatively, you can spin down each of your services with the Dapr CLI "stop" command. For example, to spin down both services, run these commands in a new command line terminal:

```bash
dapr stop --app-id mynode
dapr stop --app-id nodeapp
dapr stop --app-id pythonapp
```

To see that services have stopped running, run `dapr list`, noting that your service no longer appears!
To see that services have stopped running, run `dapr list`, noting that your services no longer appears!

## Next Steps

Expand Down
File renamed without changes.
Binary file modified 1.hello-world/img/postman1.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified 1.hello-world/img/postman2.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
4 changes: 2 additions & 2 deletions 1.hello-world/sample.http
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
POST http://localhost:3500/v1.0/invoke/mynode/method/neworder
POST http://localhost:3500/v1.0/invoke/nodeapp/method/neworder

{ "data": {"orderId":"42"} }

###

GET http://localhost:3500/v1.0/invoke/mynode/method/order
GET http://localhost:3500/v1.0/invoke/nodeapp/method/order
80 changes: 6 additions & 74 deletions 2.hello-kubernetes/README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Hello Kubernetes

This tutorial will get you up and running with Dapr in a Kubernetes cluster. We'll be deploying a python app that generates messages and a Node app that consumes and persists them. The following architecture diagram illustrates the components that make up this sample:
This tutorial will get you up and running with Dapr in a Kubernetes cluster. We'll be deploying the same applications from [Hello World](../1.hello-world). To recap, the Python App generates messages and the Node app consumes and persists them. The following architecture diagram illustrates the components that make up this sample:

![Architecture Diagram](./img/Architecture_Diagram.png)

Expand Down Expand Up @@ -36,75 +36,7 @@ Dapr can use a number of different state stores (Redis, CosmosDB, DynamoDB, Cass
component.dapr.io "statestore" configured
```

## Step 3 - Understand the Code

Now that we've setup Dapr and state, let's take a look at our services. Clone the sample repository:
```bash
git clone https://github.com/dapr/samples.git
```

Navigate to the Node.js app in the Kubernetes sample: `cd samples/2.hello-kubernetes/node`.

In the `app.js` you'll find a simple `express` application, which exposes a few routes and handlers.

Let's take a look at the ```neworder``` handler:

```js
app.post('/neworder', (req, res) => {
const data = req.body.data;
const orderId = data.orderId;
console.log("Got a new order! Order ID: " + orderId);

const state = [{
key: "order",
value: data
}];

fetch(`${daprUrl}/state`, {
method: "POST",
body: JSON.stringify(state),
headers: {
"Content-Type": "application/json"
}
}).then((response) => {
console.log((response.ok) ? "Successfully persisted state" : "Failed to persist state");
});

res.status(200).send();
});
```

Here we're exposing an endpoint that will receive and handle `neworder` messages. We first log the incoming message, and then persist the order ID to our Redis store by posting a state array to the `/state` endpoint.

Alternatively, we could have persisted our state by simply returning it with our response object:

```js
res.json({
state: [{
key: "order",
value: order
}]
})
```

We chose to avoid this approach, as it doesn't allow us to verify if our message successfully persisted.

We also expose a GET endpoint, `/order`:

```js
app.get('/order', (_req, res) => {
fetch(`${daprUrl}/state/order`)
.then((response) => {
return response.json();
}).then((orders) => {
res.send(orders);
});
});
```

This calls out to our Redis cache to grab the latest value of the "order" key, which effectively allows our Node.js app to be _stateless_.

## Step 4 - Deploy the Node.js App with the Dapr Sidecar
## Step 3 - Deploy the Node.js App with the Dapr Sidecar

```
kubectl apply -f ../deploy/node.yaml
Expand Down Expand Up @@ -134,7 +66,7 @@ You can also export it to a variable:
export NODE_APP=$(kubectl get svc nodeapp --output 'jsonpath={.status.loadBalancer.ingress[0].ip}')
```

## Step 5 - Deploy the Python App with the Dapr Sidecar
## Step 4 - Deploy the Python App with the Dapr Sidecar
Next, let's take a quick look at our python app. Navigate to the python app in the kubernetes sample: `cd samples/2.hello-kubernetes/python` and open `app.py`.

At a quick glance, this is a basic python app that posts JSON messages to `localhost:3500`, which is the default listening port for Dapr. We invoke our Node.js application's `neworder` endpoint by posting to `v1.0/invoke/nodeapp/method/neworder`. Our message contains some `data` with an orderId that increments once per second:
Expand Down Expand Up @@ -164,7 +96,7 @@ Now let's just wait for the pod to be in ```Running``` state:
kubectl get pods --selector=app=python -w
```

## Step 6 - Observe Messages
## Step 5 - Observe Messages

Now that we have our Node.js and python applications deployed, let's watch messages come through.<br>
Get the logs of our Node.js app:
Expand All @@ -184,7 +116,7 @@ Got a new order! Order ID: 3
Successfully persisted state
```

## Step 7 - Confirm Successful Persistence
## Step 6 - Confirm Successful Persistence

Hit the Node.js app's order endpoint to get the latest order. Grab the external IP address that we saved before and, append "/order" and perform a GET request against it (enter it into your browser, use Postman, or curl it!):

Expand All @@ -195,7 +127,7 @@ curl $NODE_APP/order

You should see the latest JSON in response!

## Step 8 - Cleanup
## Step 7 - Cleanup

Once you're done using the sample, you can spin down your Kubernetes resources by navigating to the `./deploy` directory and running:

Expand Down
13 changes: 11 additions & 2 deletions 2.hello-kubernetes/makefile
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,16 @@ DOCKERFILE:=Dockerfile
.PHONY: build

SAMPLE_APPS:=$(foreach ITEM,$(APPS),$(DOCKER_IMAGE_PREFIX)$(ITEM))
build: $(SAMPLE_APPS)
build: copy $(SAMPLE_APPS)

# copy app files from 1.hello-world
copy:
mkdir -p python/.dockerfiles
mkdir -p node/.dockerfiles
cp ../1.hello-world/app.py python/.dockerfiles/
cp ../1.hello-world/app.js node/.dockerfiles/
cp ../1.hello-world/package.json node/.dockerfiles/
cp ../1.hello-world/package-lock.json node/.dockerfiles/

# Generate docker image build targets
# Params:
Expand Down Expand Up @@ -49,4 +58,4 @@ endif
endef

# Generate docker image push targets
$(foreach ITEM,$(APPS),$(eval $(call genDockerImagePush,$(ITEM),$(REL_VERSION))))
$(foreach ITEM,$(APPS),$(eval $(call genDockerImagePush,$(ITEM),$(REL_VERSION))))
3 changes: 2 additions & 1 deletion 2.hello-kubernetes/node/.gitignore
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
node_modules
node_modules
.dockerfiles
6 changes: 3 additions & 3 deletions 2.hello-kubernetes/node/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
FROM node:8-alpine
WORKDIR /usr/src/app
COPY . .
WORKDIR /app
COPY .dockerfiles .
RUN npm install
EXPOSE 3000
CMD [ "node", "app.js" ]
CMD [ "node", "app.js" ]
49 changes: 0 additions & 49 deletions 2.hello-kubernetes/node/app.js

This file was deleted.

Loading

0 comments on commit 6656056

Please sign in to comment.