Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WIP] Spike: todo example on IBM Cloud [DO NOT MERGE] #1574

Closed
wants to merge 3 commits into from

Conversation

hacksparrow
Copy link
Contributor

@hacksparrow hacksparrow commented Jul 30, 2018

Add todo example on IBM Cloud - see #1446

Checklist

  • npm test passes on your machine
  • New tests added or existing tests modified to cover all changes
  • Code conforms with the style guide
  • API Documentation in code was updated
  • Documentation in /docs/site was updated
  • Affected artifact templates in packages/cli were updated
  • Affected example projects in examples/* were updated

@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch from df28ab7 to 7fa075c Compare July 31, 2018 07:19
@hacksparrow hacksparrow requested a review from virkt25 as a code owner July 31, 2018 07:19
@hacksparrow hacksparrow self-assigned this Jul 31, 2018
@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch from 7fa075c to 2a72bac Compare July 31, 2018 07:53
@bajtos
Copy link
Member

bajtos commented Jul 31, 2018

Nice start! Could you please start writing a guide explaining how to deploy your modified todo example to bluemix? For example, you can put the content into a new file examples/todo/DEPLOYING.md. That way we can review the changes in the deployment guide alongside the changes in code.

@@ -8,6 +8,13 @@ import {ApplicationConfig} from '@loopback/core';
import {RestServer} from '@loopback/rest';

export async function main(options?: ApplicationConfig) {
// IBM Cloud app port is set on process.env.PORT
if (!options) {
options = {rest: {port: process.env.PORT}};
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't needed since the port default to process.env.PORT in the else statement below. So this can be just:

options.rest = options.rest ? options.rest : {};
options.rest.port = process.env.PORT || options.rest.port;

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Where is options defined?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooops. For some reason I through the check was for options.rest.

@bajtos bajtos mentioned this pull request Aug 1, 2018
31 tasks
@virkt25 virkt25 added this to the August Milestone milestone Aug 1, 2018
@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch 2 times, most recently from e19396f to 81e099f Compare August 9, 2018 07:33
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It looks like deploying LB4 apps to IBM Cloud requires only small changes - I like that.

IIUC, this deployment is based on CloudFoundry. I wish we were targeting Kubernetes based deployments, as that seems to be the new way forward, but CloudFoundry is good enough for the initial spike.

"localStorage": "",
"file": "./data/db.json"
"connector": "cloudant",
"url": "http://admin:pass@localhost:8080",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please confirm that this URL works with Cloudant running locally via Docker?

See #1446:

When developing and testing locally, the app should use local docker-based Cloudant Developer Edition.

In my experience, Docker containers cannot be accessed at localhost.

If there is a reasonably easy way how to run Cloudant locally on localhost, perhaps without Docker, then I am fine with your current approach, but we need instructions for users how to set up such Cloudant instance.

See also acceptance criteria:

A deployment guide for IBM cloud added to our docs. If the current LB4 feature-set is not sufficient to support such deployments, then create a new wiki page instead of an official doc article.

Copy link
Contributor Author

@hacksparrow hacksparrow Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, it works with Cloudant at http://admin:pass@localhost:8080 works fine.

Will push the "deployment guide" in a while.


// tslint:disable-next-line:no-any
serviceGroup.forEach((service: VcapService) => {
if (service.name === config.name) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have you considered using an npm library to handle VCAP_SERVICES processing for you?

Few examples found by my quick search:

The latter package says in its README: Unfortunately the instance name is rarely known in advance, so you may pass it as a separate environment variable. Is this something we need to take care of?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I haven't looked at them, since I was focussed on just making the app work. Will take a look at them.

@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch from 81e099f to b3a1a46 Compare August 14, 2018 06:48
add todo example on IBM Cloud
@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch from b3a1a46 to c21fb60 Compare August 14, 2018 06:52
@bajtos bajtos changed the title [WIP] chore: todo example on IBM Cloud [WIP] Spike: todo example on IBM Cloud [DO NOT MERGE] Aug 14, 2018
};

if (shouldConfigureForIbmCloud()) {
const services = JSON.parse(process.env.VCAP_SERVICES!);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realized just now: we should not be accessing process.env from inside our application code (e.g. db.datasource.ts). Any environment-specific overrides should happen as close to the top-level main function as possible.

In LoopBack 3.x, it's the job of loopback-boot to deal with environment variables.

For the purpose of this spike, we can add VCAP_SERVICES processing code to the main function as you have already did for PORT variable.

Instead of modifying the config object loaded directly from datasource JSON file, we should iterate over all datasource configurations bound to app context, match them with VCAP_SERVICES entries and update the bound value using the URL from VCAP_SERVICES.

Later on, we can extract the code processing VCAP_SERVICES and other CF-related configuration into an extension people can add to their app.


function shouldConfigureForIbmCloud() {
if (
process.env.HOME === '/home/vcap/app' && // relatively reliable way to detect the app is running on IBM Cloud
Copy link
Member

@bajtos bajtos Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not be necessary to detect IBM Cloud. If the environment provides VCAP_SERVICES variable, then we should apply it, regardless of the specific cloud we are running on. (Isn't CloudFoundry an open source project that anyone can run on their own machines?)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Agreed. If there is VCAP_SERVICES in env, it is CF env.

function shouldConfigureForIbmCloud() {
if (
process.env.HOME === '/home/vcap/app' && // relatively reliable way to detect the app is running on IBM Cloud
config.ibmCloud && // have to explicitly config datasource to mark it as an IBM Cloud service with a matching name locally
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How about changing this flag from boolean ibmCloud: true into a VCAP SERVICE name to look up (e.g. vcapServiceName: 'db'?

It looks like VCAP_SERVICES provide binding_name and instance_name properties in addition to name, maybe we should use binding_name to find the right service record? See this presentation linked from cf-services for some background info.

To be honest, my knowledge of CloudFoundry and VCAP_SERVICES is pretty minimal, please correct me if I am talking nonsense :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great suggestion.


### LoopBack

1. Model configuration change is drastic.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please add more details? AFAICT, there is no change in model/repository configuration, it's the DataSource config that requires modification.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is just a note about first-time experience with LB4: model-config.json in LB3 was simpler. I don't think anything has to be done about this.


1. Model configuration change is drastic.
2. Repository creation and linking to a model is manual. There should be a
provision to do these from the `lb` commands.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this referring to #1588? If so, then please add a link to your document.

1. Model configuration change is drastic.
2. Repository creation and linking to a model is manual. There should be a
provision to do these from the `lb` commands.
3. There no API Explorer to play around with the models.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could you please explain more? We do have API explorer hosted at loopback.io, LB4 apps provide /swagger-ui endpoint to access it, e.g. http://[::1]:3000/swagger-ui. Is this perhaps an issue of a missing documentation? Or maybe we should modify scaffolded app code to print explorer (swagger-ui) URL to console at startup?

The hosted API Explorer works well in Chrome and Firefox. It does not work in Safari for me, because swagger-ui is served from HTTPS while the app is running on HTTP and Safari does not allow mixed content. I guess we have a bug to fix here - see #1603

Copy link
Contributor Author

@hacksparrow hacksparrow Aug 14, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, due to mixed content the API Explorer does not load on IBM Cloud. Tested on Firefox, Chrome, Safari; fails on all. Works on Firefox, fails on Chrome and Safari.

@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch 3 times, most recently from af409a6 to 5bec856 Compare August 14, 2018 10:19
review 1
@hacksparrow hacksparrow force-pushed the spike/deploy-to-ibm-cloud branch from 5bec856 to 139a702 Compare August 14, 2018 13:32
review 2
Copy link
Member

@bajtos bajtos left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think the updated code is good enough for spike purposes now 👍

@dhmlau
Copy link
Member

dhmlau commented Sep 19, 2018

@hacksparrow , since your spike is done, and the docs are out, is this PR good to close?

@hacksparrow
Copy link
Contributor Author

This is done - #1446

@hacksparrow hacksparrow closed this Oct 4, 2018
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants