MARTIN OMANDER: Hey, Roger.
How's it going?
ROGER MARTINEZ: Hey, Martin.
Not bad.
How are you?
MARTIN OMANDER: Sweating it out here with this heat wave
we have here in Mountain View today.
ROGER MARTINEZ: Yeah, man, I'm feeling it too.
It's a little warm out today.
MARTIN OMANDER: It is.
Those are some cool dog photos behind you.
Where are they from?
ROGER MARTINEZ: These are just some of the few shots
I've taken over the years.
I do some dog photography sometimes.
So I just like to put my favorite shots on the wall.
There they are.
MARTIN OMANDER: Cool.
That gives me an idea.
Several viewers have actually asked in the YouTube comments
if we could build a REST API, serverless
REST API with a serverless compute
and a serverless database.
Maybe we could have a REST API that
tells you about dog breeds.
ROGER MARTINEZ: That is a very good idea.
And I think we should use a Firestore back-end.
How does that sound?
MARTIN OMANDER: Sounds great.
Let's do it.
[THEME MUSIC]
All right Roger, so I went ahead and created a project here
in Google Cloud Platform called dog-breed-api.
ROGER MARTINEZ: Good name.
MARTIN OMANDER: Yeah, and our database was Firestore, right?
ROGER MARTINEZ: Yep.
Let's jump to Firestore.
And--
MARTIN OMANDER: Per your instructions,
I created a dogs collection.
And let's see.
What are we looking at here?
ROGER MARTINEZ: So collection in the Firestore world
is pretty much a table.
And in that table, we're going to have
different entries, which are going to be documents.
So we have a table, dogs.
And we have one document there I see.
And it has four fields--
lifeExpectancy, a name, origin, and a type.
MARTIN OMANDER: So we have one breed in our database so far.
And that breed is Dalmatian, it looks like.
ROGER MARTINEZ: Yes, and every breed will have one document.
So the cool thing is that we have these four fields.
But it's not just those four.
We can always add more fields if we need to in the future.
But for now, I think we're cool with just lifeExpectancy, name,
origin, and type.
MARTIN OMANDER: OK, very good.
So then we need to put a REST API in front of this.
So I guess we'll jump over to code.
Before our call here today, I set up a bare-bones node
application and imported the Firestore client library
and the Express library.
ROGER MARTINEZ: Yep, and Express is just
going to serve as our HTTP server that's
going to respond to our GET requests
and give us the dog breed information that we want.
MARTIN OMANDER: Very good.
And then I added start here that will tell the container,
or tell the thing running our container,
to execute this container by executing node
with index.js as the parameter.
ROGER MARTINEZ: Exactly.
So now that you mention it, index.js, let's check that out.
MARTIN OMANDER: All right, I put a little bit of code in here.
This is sort of a bare bones REST API, right?
ROGER MARTINEZ: Yep, not much happening right now
except for the bare minimum.
We are starting our HTTP server.
And it's listening to port 8080.
And we'll know that because it'll
console log that nice little listening line there on line 9.
And then it's going to respond to any GET requests
to the root with a "Bark!
Bark!
Ready to roll." status message in a JSON object.
So let's just test that out real quick just
to make sure we're not messing things up.
NPM start.
MARTIN OMANDER: Yeah, look at that.
ROGER MARTINEZ: OK, it is listening.
MARTIN OMANDER: We got this far.
ROGER MARTINEZ: We got that far.
MARTIN OMANDER: Now how do we get to this part?
ROGER MARTINEZ: We either go to a browser.
But to make it quick, just jump to another terminal window.
And curl localhost:8080.
MARTIN OMANDER: Oops.
Yay, look at that.
Bark, bark.
Ready to roll.
ROGER MARTINEZ: But nothing is happening yet with Firestore.
But you'll see on line 2 that we have the library for Firestore.
And we're bringing it into our project there.
And then on line 4, we have a new instance
of Firestore, which is going to use our application default
credentials to access the Firestore associated
with our project.
MARTIN OMANDER: Oh, that's so cool.
Yeah, on line 4 here, we don't really
need a password or connection string or anything, right?
ROGER MARTINEZ: Right.
Once this gets built into the container and run on Cloud Run,
it's just going to use some application default
credentials, which will use a service
account to run what needs to run to access our Firestore.
MARTIN OMANDER: Very nice.
ROGER MARTINEZ: OK, so we'll start with our app get.
We already have an app.get for the root.
But now we have an app.get for colon breed.
And that colon breed is going to refer to a variable,
for example, Dalmatian.
And it's going to run this asynchronous function.
As you can see, we're going to make a variable, breed.
And it's going to take that breed value from the URL.
And then we're going to construct a query.
So the query's not doing anything now.
We're just constructing it right now.
And it's going to look at the collection dogs, which
we saw earlier, where the name is that breed variable.
Exactly.
And now the query snapshot is going
to hold the actual results.
So it's going to be asynchronous function query get.
We're going to want to tell the user the results
if we have results, and tell her that we don't have results
if we don't have results.
So there we have an if statement saying
that if the query snapshot size is greater than 0, which is not
nothing, we're going to respond with the first document
of the data that we get back.
MARTIN OMANDER: Very good.
Yeah, we could potentially get several back.
But we'll just return the first.
ROGER MARTINEZ: Yep.
Else, we want to respond something nice like, sorry,
couldn't find it, or not found, or something to let the user
know that something is wrong.
Status--
MARTIN OMANDER: How about something like this?
ROGER MARTINEZ: "Not found." yes, perfect.
MARTIN OMANDER: All right, very good.
There we go.
ROGER MARTINEZ: Deploy that sh.
So let's jump to that file and see what's happening right now.
MARTIN OMANDER: Yeah, so this is a several-part file here.
It looks like we just set a variable here.
But then there are two pieces.
What's this one?
ROGER MARTINEZ: So we have gcloud
builds, which is going to take our code
and build a container out of it based on the Docker file
that we provide in the same directory.
So it's going to build that.
It's going to upload it a Google Container Registry.
And then it's going to go into the second part of our command,
which is going to do Cloud Run, which
is going to deploy our application based
on that image.
MARTIN OMANDER: Ah, right.
So the first part just builds a container.
And the second part starts that container-- spins it up
so it can start serving traffic.
ROGER MARTINEZ: Exactly.
To get a better look at this, we can
jump to our Cloud Build page.
Yep, there it is.
MARTIN OMANDER: Oh, it just finished.
Good.
ROGER MARTINEZ: Yep, [INAUDIBLE] that one.
Yep, click that build.
And if something went wrong, we would see it here in our
build log.
So I see a lot of green check boxes, check marks.
So that's always a good sign.
Let's jump to our Container Registry page.
MARTIN OMANDER: Very good.
So here's our barkbarkapi.
And here we have one container.
It was built just now.
ROGER MARTINEZ: Just now, right on time.
And you see that Latest Tag?
Hit that little pencil right next the Latest.
We could add other tags.
So in this case, it's going to be version, yeah, version 1.0.
MARTIN OMANDER: The most dangerous version
of any software.
ROGER MARTINEZ: Yep.
And we'll come back to that Latest Tag later.
But for now, let's go to Cloud Run page on our console.
MARTIN OMANDER: Yeah, let's see.
So Cloud Run.
No we are actually going to look at the deployed container, not
just the list of built containers but--
ROGER MARTINEZ: Yep, there's barkbarkapi.
MARTIN OMANDER: And no requests have come in.
No errors either.
And it looks like we have one version of the API.
ROGER MARTINEZ: Yeah, and this is where all your revisions
would show up.
So once we start building more and more and more,
they will all show up here.
And the cool thing is that you can direct traffic
to more than one.
That way if you want to, for example, test out a canary
build of something, you can do it here.
MARTIN OMANDER: Yeah, like Google does, right?
So they redeploy a new version, send that new version
to 1% of users, then 10% of users.
ROGER MARTINEZ: Exactly.
And you have the option of rolling back if you have to.
So if we click that URL up there, that is our application.
MARTIN OMANDER: Look at that.
Bark!
Ready to roll.
It's working.
ROGER MARTINEZ: There it is.
Perfect.
Now let's see if it's actually talking to our Firestore.
So remember we have that one entry, Dalmatian?
Yep.
So that's that breed variable.
We need Dalmatian.
And yes, that is our Dalmatian information that we wanted.
MARTIN OMANDER: Oh, OK.
And I like poodles.
Ah, not found.
ROGER MARTINEZ: No poodles for you.
So it's not very useful still.
This is pretty much a Dalmatian information API.
It's not serving much information.
MARTIN OMANDER: Nothing wrong with that.
ROGER MARTINEZ: Nothing wrong with that.
I like Dalmatians.
But like I said before, there's a lot more dogs out there.
So what we want to do is be able to use a POST request
to add entries to our Firestore, to our Firestore database.
MARTIN OMANDER: So this is for so
that people can create new breeds in our database.
ROGER MARTINEZ: Exactly, yes.
So similar to our app.get function from before,
we're going to have, this time it's
app.post for POST requests.
And yeah, slash is fine.
Yeah, and we're going to construct our data object.
It's going to correspond with the values,
the fields in our document.
So it's pulling it from the body of our request.
So what we're going to do, we're going
to make it so that the POST request is
sent in a JSON format.
And we're going to pull the fields from that JSON object
and put it into this data object here.
And this is just for readability's sake.
MARTIN OMANDER: And lifeExpectancy
is so hard to spell.
Did I spell it right?
ROGER MARTINEZ: Yeah, I never spell that right,
so you did pretty good this time.
MARTIN OMANDER: All right.
ROGER MARTINEZ: Yes, perfect, OK.
And here comes our wait line.
And similar to before--
and our collection, again, is dogs, right?
And then it's going to be a new doc.
So it's going to be empty.
And we're in a set data.
MARTIN OMANDER: All right, so [INAUDIBLE]..
ROGER MARTINEZ: --our data variable.
MARTIN OMANDER: Mm-hmm.
And what are we returning to users?
ROGER MARTINEZ: So once that happens,
we want to respond a JSON object that just
says that it's been a success.
So yeah, there you go-- success.
And just to make sure that we know what we're doing,
we want to respond with the object
that we just sent it, so.
That all looks good to me.
If it looks good to you, let's deploy ploy, yep.
And we're running the same exact deploy script as we did before.
So it's going to know that this is
a new version of the same container that we did before.
And it's going to do what it has to do accordingly.
So while that goes, we can jump to the Cloud Build page
on the console.
MARTIN OMANDER: Very good.
Cloud Build.
There is Cloud Build.
Aha, the build is running.
ROGER MARTINEZ: You'll see it is spinning.
It's going.
It's running.
Things are happening right now.
MARTIN OMANDER: Mm-hmm.
Step two out of six, step three out of six,
step four out of six.
OK, it's getting there.
ROGER MARTINEZ: It's getting there.
MARTIN OMANDER: Five out of six.
ROGER MARTINEZ: It should only take another moment.
But in the meantime, we could jump to the Container Registry
page again.
MARTIN OMANDER: Yep.
Container Registry.
barkbarkapi, our old friend.
Aha, now there are two of them in here.
ROGER MARTINEZ: Just now.
Again, perfect timing.
So you see v1, v1 that we just did a little while ago.
But you see the latest tag that I mentioned before?
It moved up to the container that we just uploaded.
So now we add another tag to it.
MARTIN OMANDER: Yeah, what if we call this version 2.0?
Our dog breed startup is going very well.
5 minutes from version 1.0 to 2.0.
ROGER MARTINEZ: Yeah, so the cool thing about the latest
is that you never have to worry about updating the latest
tag to another container.
And also the fact that you can use tags
means that you can deploy different versions
of the same container however you need to.
[INTERPOSING VOICES]
MARTIN OMANDER: We'll see them over here I think.
So here we are in Cloud Run.
Cloud Run is actually handling traffic from users.
And it looks like we jumped from this old version to new one.
It's 0% of traffic is going to the old one.
100% to the new version of this container.
ROGER MARTINEZ: Yes, exactly.
So like we mentioned before, if you had to do a canary build,
we can always change that traffic percentage.
That way, we're not just jumping straight to the newest
version 100% traffic.
MARTIN OMANDER: Yeah, OK.
Shall we see if we broke anything?
ROGER MARTINEZ: Let's see if we broke anything.
MARTIN OMANDER: So Roger, what are the chances
that this will work, you think?
ROGER MARTINEZ: I mean, I like breaking things.
But I think we did pretty good.
I have 90% confidence that this is fine.
MARTIN OMANDER: For once, but only this once,
I am going to say more, higher percentage than you--
95%.
ROGER MARTINEZ: 95, all right.
Let's see what happens.
MARTIN OMANDER: All right, that looks good.
ROGER MARTINEZ: We didn't break that.
Let's see if we still have our Dalmatian entry.
MARTIN OMANDER: Uh-huh, very good.
ROGER MARTINEZ: There's our Dalmatian.
MARTIN OMANDER: And the thing we added, what was that?
ROGER MARTINEZ: So we want to test the POST functionality,
right?
So let's jump to Postman, yeah.
MARTIN OMANDER: Postman, excellent piece
of software for testing APIs.
So first, actually, I'll just send a real quick request here
with this GET just to make sure everything works.
We got the Dalmatian back.
But it's not to GET we're supposed to test here.
We are supposed to test POST, right?
ROGER MARTINEZ: POST, yeah.
All right, so remember, we're posting to the root.
So yeah, just leave the URL blank like that.
Make sure we have a JSON object.
And let's construct our JSON object.
So again, it's going to correspond with the fields
of the documents.
MARTIN OMANDER: Yeah, what breed should we
add to our breeds database, do you think?
ROGER MARTINEZ: Let's go with beagle.
MARTIN OMANDER: Bea-gle.
Did I get that right?
ROGER MARTINEZ: That's correct, yep.
MARTIN OMANDER: All right, where do beagles come from?
ROGER MARTINEZ: Beagles come from England.
MARTIN OMANDER: England, all right.
And nope, that was not it.
Life-- I was hoping I wouldn't have to spell out
lifeExpec-tanc--
ROGER MARTINEZ: Nice try.
MARTIN OMANDER: Yeah, oh, so I forgot the quotes.
All right, how long do beagles live?
ROGER MARTINEZ: 13.
MARTIN OMANDER: 13, a little longer than Dalmatians, huh.
ROGER MARTINEZ: And then type--
so beagles are famously known as being a scent--
MARTIN OMANDER: Scent dog.
Oh, I see.
ROGER MARTINEZ: They are really good smellers.
They can smell things really good.
MARTIN OMANDER: All right, so POST.
We POST to the root of this API.
We send this JSON along.
So this should add it to the database.
Let's hit it.
ROGER MARTINEZ: It should.
MARTIN OMANDER: It should.
Let's see if it does.
ROGER MARTINEZ: It's taking quite a while.
Let's check it out.
Let's see what's going on here.
MARTIN OMANDER: Yeah, fortunately everything
goes into the logs.
Let's see here.
Uh-huh, looks like a juicy error here.
Type db.collection docs-- db.collection dot docs--
is--
ROGER MARTINEZ: --is not a function.
MARTIN OMANDER: All right, let's look in the code.
ROGER MARTINEZ: Let's check that out.
MARTIN OMANDER: db.collection dot--
oh, stupid me.
ROGER MARTINEZ: Yes, doc.
MARTIN OMANDER: All right, just doc.
ROGER MARTINEZ: Deploy it again.
MARTIN OMANDER: Yeah, so just to take this as a learning moment
here, we're taking this collection, which
is kind of like a table.
And this piece here is creating one new document, so
an empty document in that table.
And this piece here sets the data.
So sets this data for this new empty document.
ROGER MARTINEZ: Exactly.
So now we can just rerun that same deploy script again.
So again, it's going to know exactly what container
to upload this to on the Container Registry.
So we jump back to Container Registry.
MARTIN OMANDER: And by the way, just one more thing here.
We are running this gcloud commands interactively here
as developers.
If you're in a larger organization,
you would typically have this at the end of a CI/CD pipeline,
where your CI/CD tool would run something along those lines.
For example, check in something to the master branch.
ROGER MARTINEZ: Yeah, and that pipeline
might have some type of code review,
where they might pick up on typos, like the one
we just saw, so.
MARTIN OMANDER: Humans or machines
that look at your code, yeah.
ROGER MARTINEZ: Yes, correct.
All right, so it looks like it finished.
So let's try that again.
Let's just go straight into the POST and see if we can--
MARTIN OMANDER: Yeah, let's see if this works.
We got something.
Oh, look at that.
ROGER MARTINEZ: We got something-- success.
That is our success message that we asked it to respond with.
So it looks like it worked.
But let's make absolutely sure that it did work.
MARTIN OMANDER: Yeah, so I'll do a GET to hit--
[INAUDIBLE] beagle.
Oh, I should not send a body along with that.
There we go, all right.
ROGER MARTINEZ: There's our beagle.
MARTIN OMANDER: The beagle--
so I guess the beagle's in the database?
ROGER MARTINEZ: I don't believe you.
Show me.
MARTIN OMANDER: Show me.
That's right.
Only one way to make sure.
ROGER MARTINEZ: Spinning, spinning, spinning.
I see dogs.
I see two documents.
I see Dalmatian.
And now--
MARTIN OMANDER: Is this the one?
ROGER MARTINEZ: And that should be beagle.
There is beagle.
All right, so now it's a lot easier
to enter all the dogs your heart desires
and not have to do it manually sitting there.
MARTIN OMANDER: And everything here was serverless.
Cloud Run is serverless.
You don't have to deal with setup
and maintaining servers and scaling up and down.
And Firestore is serverless.
So you don't have to deal with planning capacity.
ROGER MARTINEZ: Beautiful.
MARTIN OMANDER: Very good.
If you have any questions about anything we built here
or any questions or requests for other videos
that we should shoot about serverless computing,
please let us know in the comments.
[THEME MUSIC]