Guest blog post by Trevor Conn, Principal Software Engineer, Dell Technologies
A short while ago I was introduced to the EdgeX Foundry platform when I attended a local IoT Meetup in Austin, TX. The presentation was given by fellow Dell Technologies colleague Jim White and I went up to introduce myself afterwards. We discussed the future possibility of making the EdgeX Foundry services cloud ready and I told him of my experience using Pivotal Cloud Foundry (PCF) in a production environment. Given the popularity of PCF, we thought it would make sense to see what it would take to port a couple EdgeX services into the platform.
The proof of concept I present below involves porting two of the foundational EdgeX services to PCF and then calling those services from the Virtual Device service running on my local workstation. Basically, I took the scenario Jim presents in Session 1 of the EdgeX Foundry Tech talks as my scope of work for this proof of concept. If you’re going to follow along, then you will want to fork the Github repos for the following three services:
You will be making changes to the first two, deploying those to PCF and then running the last service on your local machine while pointing to your PCF deployments.
The changes to be made to core-data and core-metadata are essentially the same:
1.Add three new packages for Spring Cloud functionality with regard to configuration, as well as PCF integration. You accomplish this by adding the following to the pom.xml
2. Next, add another configuration class which will be annotated with @Profile in order to differentiate which configuration to use when deployed to a PCF cloud environment versus the default local environment. In my case, I called this new class “CloudConfig” and inherited from AbstractCloudConfig.
3. As you can see in the screenshot above, a new property is necessary to indicate the name of the data service we need to connect to. In our case, this is a Mongo database hosted outside of PCF. However, we still need to provide the cloud infrastructure with a name and a connection string whereby the persistence layer can function. I’ll go into more details about that below. For now, add the following entries to the application.properties file:
#—————–Mongo Cloud Config——————————————
The data-service value will be injected into the private dataServiceName member.
4. Since we are now distinguishing our configuration by profile, I needed to also add an @Profile annotation to the existing AppConfig class.
5. In our case, connectivity to Mongo was a little challenging. The PCF infrastructure at our disposal does not have MongoDB available within the cloud marketplace. That is to say, Mongo for PCF is not enabled. The only option available was to set up a Mongo instance on an external VM and then configure a user provided service within PCF consisting of the service’s name and a connection string. This limitation unfortunately meant I could not utilize the auto-configuration that Spring Cloud Service Connectors
Once I had the user provided service created, I then implemented my Mongo client within the above CloudConfig class like so:
So as you can see, the dataServiceName is used to find the service within PCF. Since we know we’re trying to access a Mongo database, I then cast the ServiceInfo to a MongoServiceInfo which gives me access to the URI I specified when creating my user defined service.
6. With those changes in place you’re ready to deploy. PCF will require a manifest file during deployment that provides parameters for the definition of the container your service will run on. Rather than including all of the content here, I will just link to the manifest file I created for the core-data service. The core-metadata manifest is the same except for the application name.
For a thorough explanation of what all of these settings mean, I refer you to the Cloud Foundry manifest documentation.
7. For the actual deployment, I found that it required use of both the Cloud Foundry command line as well as the Boot Dashboard provided within the Spring Tool Suite editor. There is certainly a way to streamline this step, but I have not had time to dig into it further. You would want to eliminate reliance on the Boot Dashboard for any kind of real deployment pipeline.
The issues I faced here were as follows:
- The CF command line would provision the container appropriately, download the necessary buildpacks, create the necessary mappings for the user provided service to my application, but then it could never successfully build the application.
- The Boot Dashboard was unable to do any of the above if I was deploying the service for the first time. At the point where it should have created the initial mapping of the services, it would just hang and then time out.
The approach I took for deployment of new services was to use the command line tool first, which would establish the necessary scaffolding in PCF, and then use the Boot Dashboard to deploy the code and get it built correctly.
Again, a little more work needs to be done here to make this cleaner.
8. And with all of that done, you’re ready to test!
Again, the test scenario involves running the Virtual Device service locally and pointing it to the deployed PCF endpoints. There are two changes necessary to the properties of the device-virtual project
- In the src/main/resources/rest-endpoint.properties file, you will want to change all of the entries to point to the relevant PCF routes instead of localhost
- In the src/main/resources/application.properties file, you will want to change the “service.host” value to either your IP address or your fully qualified host name
** NOTE: In our case we were running our tests on a VPN whereby our local machines were on the same network as the PCF cluster. If you are behind a firewall trying to hit an external PCF cluster, this reverse lookup will not work without some additional network configuration. **
9. Start the device-virtual project as a Java application and you should start seeing the core-data service’s event counter increment.
The above was a fun, brief initiative undertaken in order to gauge the amount of work necessary to move the whole EdgeX Foundry platform to a cloud infrastructure. Due to the modularity of Spring along with the flexibility in the design of the EdgeX services themselves, the changes needed to accomplish this were not at all extensive. With this effort somewhat quantified, I look forward to hopefully working more on these capabilities in the coming year.