13. Packages

Packages contain all the necessary information to install your application or group of applications. The approach to decribing the applications is to use a YAML file that provides all the necessary information to help facilitate searching for your application hosted in a Package Registry and to install your application to a platform.

To make it easy to customize a package, the YAML files are templated. The final version of the YAML file, with all values substituted is known as the release manifest. Skipper currently understands how to deploy applications based off a YAML file that contains the information needed for a Spring Cloud Deployer implementation to deploy an application. It describes, where to find the application (either a http, maven or docker location) , application properties (think Spring Boot @ConfigurationProperties), an deployment properites (e.g. how much memory to use).

13.1 Package Format

A package is a collection of YAML files that are zipped up into a file with the naming convention [PackageName]-[PackageVersion].zip for example: mypackage-1.0.0.zip

A package can define a single application or a group of applications.

The single application package file, mypackage-1.0.0.zip when unzipped, should have the following directory structure.

mypackage-1.0.0
├── package.yml
├── templates
│   └── template.yml
└── values.yml

The package.yml file contains metadata about the package and is used to support Skipper’s search functionality. The template.yml file contains placeholders for values that are specified in the values.yml file. When installing a package, placeholder values can also be specified and they would override the values in the values.yml file. The templating engine that Skipper uses JMustache. The YAML files can have either .yml or .yaml extensions.

The files helloworld-1.0.0.zip or helloworld-docker-1.0.0.zip are good examples to use as a basis to create your own package 'by-hand'.

The source code for the helloword sample can be found here.

13.2 Package with multiple applications

A package can contain a group of applications bundled in it. In those cases, the structure of the package would look like this:

mypackagegroup-1.0.0
├── package.yml
├── packages
│   ├── app1
│   │   ├── package.yml
│   │   ├── templates
│   │   │   └── log.yml
│   │   └── values.yml
│   └── app2
│       ├── package.yml
│       ├── templates
│       │   └── time.yml
│       └── values.yml
└── values.yml

In the above, the mypackagegroup would still have its own package.yml, values.yml to specify the package metadata and the values to override. All the applications inside the mypackagegroup are considered sub-packages and would follow the similar package structure as the individual packages. These sub packages need to be specified inside the packages directory of the root package mypackagegroup.

The file ticktock-1.0.0.zip is a good example to use as a basis for creating your own package 'by-hand'.

13.3 Package Metadata

The package.yml file specifies the package metadata. A sample package metadata would look like this:

# Required Fields
apiVersion: skipper.spring.io/v1
kind: SkipperPackageMetadata
name: mypackage
version: 1.0.0

# Optional Fields
packageSourceUrl: https://github.com/some-mypackage-project/v1.0.0.RELEASE
packageHomeUrl: http://some-mypackage-project/
tags: skipper, mypackage, sample
maintainer: https://github.com/maintainer
description: This is a mypackage sample.

Required Fields:

  • apiVersion - The Package Index spec version this file is based on
  • kinds - What type of package system is being used
  • name - name of the package
  • version - version of the package

Optional Fields:

  • packageSourceUrl - Location to source code for this package.
  • packageHomeUrl - The home page of the package
  • tags - A comma separated list of tags to be used for searching
  • maintainer - Who is maintaining this package
  • description Free form text describing the functionality of the package. Will generally be shown in search results.
  • sha256 - Hash of package binary (not yet enforced)
  • iconUrl - URL for an icon to show for this package.
  • origin - Free form text describing the origin of this package, for example your company name.
[Note]Note

Currently, the package search functionality is only a wildcard match against the name of the package.

A Package Repository exposes an index.yml file that contains multiple metadata documents, separated by the standard three dash notation --- to separate the documents. For example index.yml.

13.4 Package Templates

The template.yml file in a package structure such as

mypackage-1.0.0
├── package.yml
├── templates
│   └── template.yml
└── values.yml

will commonly have the following content:

# template.yml
apiVersion: skipper.spring.io/v1
kind: SpringCloudDeployerApplication
metadata:
  name: mypackage
  type: sample
spec:
  resource: maven://org.mysample:mypackage
  resourceMetadata:  maven://org.mysample:mypackage:jar:metadata:{{spec.version}}
  version: {{spec.version}}
  applicationProperties:
    {{#spec.applicationProperties.entrySet}}
    {{key}}: {{value}}
    {{/spec.applicationProperties.entrySet}}
  deploymentProperties:
    {{#spec.deploymentProperties.entrySet}}
    {{key}}: {{value}}
    {{/spec.deploymentProperties.entrySet}}

Skipper only knows how to manage applications defined in this way. A future release will introduce support for different formats, for example supporting the Cloud Foundry manifest format.

The apiVersion, kind and spec.resource are required.

The spec.resource and spec.version define where the application executable is located. The spec.resourceMetadata field defines where a Spring Boot Configuration meta-data jar is located that contains configuration properties of the application. This is either a Spring Boot uberjar hosted under a http endpoint or a maven or docker repository. The template placeholder {{spec.version}} so that the version of a specific application can be easily upgraded without having to create a new package .zip file.

The resource is http:// or a maven:// or docker: based. The format for specifying a resource is shown below.

13.4.1 HTTP Resources

spec:
  resource: http://example.com/app/hello-world
  version: 1.0.0.RELEASE

There is a naming convention that must be followed for HTTP based resource so that Skipper can assemble a full URL from the resource and version field and also parse the version number given the URL. The above spec will reference a URL at example.com/app/hello-world-1.0.0.RELEASE.jar. The resource and version fields should not have any numbers after the - character.

13.4.2 Docker Resources

spec:
  resource: docker:springcloud/spring-cloud-skipper-samples-helloworld
  version: 1.0.0.RELEASE

The mapping to docker registry names is

spec:
  resource: docker:<user>/<repo>
  version: <tag>

13.4.3 Maven Resources

spec:
  resource: maven://org.springframework.cloud.samples:spring-cloud-skipper-samples-helloworld:1.0.0.RELEASE
  version: 1.0.0.RELEASE

The mapping to maven artifact names is

spec:
  resource: maven://<maven-group-name>:<maven-artifact-name>
  version:<maven-version>

There is only one setting to specify with maven repositories to search. This applies across all platform accounts. By default the configuration:

maven:
  remoteRepositories:
    springRepo: https://repo.spring.io/libs-snapshot

is used. You can specify other entries and also specify proxy properties. This is currently best documented here. Essentially, this needs to be set a property in your launch properties or manifest.yml (when pushing to PCF) like so:

# manifest.yml
...
env:
    MAVEN_REMOTE_REPOSITORIES_{{REPOSITORY_NAME}}_URL: https://repo.spring.io
...

The metadata section is used to help search for applications after they have been installed. This feature will be made available in a future release.

Currently, only SpringCloudDeployerApplication kind is supported which means the applications can be deployed into the target platforms only using their corresponding Spring Cloud Deployer implementations (CF, Kubernetes Deployer etc.).

The spec contains the resource specification and the properties for the package.

The resource represents the resource URI to download the application from. This would typically be a maven co-ordinate or a docker image URL.

The SpringCloudDeployerApplication kind of application can have applicationProperties and deploymentProperties as the configuration properties.

The application properties correspond to the properties for the application itself.

The deployment properties correspond to the properties for the deployment operation performed by Spring Cloud Deployer implementations.

[Note]Note

The name of the template file can be anything as all the files under templates directory are loaded to apply the template configurations.

13.5 Package Values

The values.yml file contains the default values for any of the keys specified in the template files.

For instance, in a package that defines one application, the format is

version: 1.0.0.RELEASE
spec:
  applicationProperties:
    server.port: 9090

If the package defines multiple applications, provide the name of the package in the top level YML section to scope the spec section. That is, given a multiple application package with the layout

ticktock-1.0.0/
├── packages
│   ├── log
│   │   ├── package.yml
│   │   └── values.yml
│   └── time
│       ├── package.yml
│       └── values.yml
├── package.yml
└── values.yml

A top level values.yml file

#values.yml

hello: world

time:
  appVersion: 1.3.0.M1
  deployment:
    applicationProperties:
      log.level: WARN
      trigger.fixed-delay: 1
log:
  deployment:
    count: 2
    applicationProperties:
      log.level: WARN
      log.name: skipperlogger

Would set hello as a variable available to be used as a placeholder in the packages\log\values.yml file and the packages\time\values.yml. However, the YML section under time: is applied only to the packages\time\values.yml file and the YML section under log: is applied only to the packages\time\values.yml file.

13.6 Package Upload

After creating the package in the above structure, we can compress it in a zip file with the name [PackageName]-[PackageVersion].zip e.g. mypackage-1.0.0.zip

For instance, the package directory would look like this before compression:

mypackage-1.0.0
├── package.yml
├── templates
│   └── template.yml
└── values.yml

This zip file can be uploaded into one of the local repositories of Skipper server. By default, Skipper server has the local repository with the name local.

Using the Skipper Shell, we can upload the package zip into Skipper server’s local repository.

skipper:>package upload --path /path-to-package/mypackage-1.0.0.zip
Package uploaded successfully:[mypackage:1.0.0]

If no --repo-name is set, the upload command will use local as the repository to upload.

skipper:>package search
╔═════════════════╤═══════╤════════════════════════════════════════════════════════════════════════════════╗
║      Name       │Version│                                  Description                                   ║
╠═════════════════╪═══════╪════════════════════════════════════════════════════════════════════════════════╣
║helloworld       │1.0.0  │The app has two endpoints, /about and /greeting in English.  Maven resource.    ║
║helloworld       │1.0.1  │The app has two endpoints, /about and /greeting in Portuguese.  Maven resource. ║
║helloworld-docker│1.0.0  │The app has two endpoints, /about and /greeting in English.  Docker resource.   ║
║helloworld-docker│1.0.1  │The app has two endpoints, /about and /greeting in Portuguese.  Docker resource.║
║mypackage        │1.0.0  │This is a mypackage sample                                                      ║
╚═════════════════╧═══════╧════════════════════════════════════════════════════════════════════════════════╝

13.7 Creating Your Own Package

In this section, we will try to create a package that can be deployed using Spring Cloud Deployer implementations.

For this package, we are going to be creating a super simple package and uploading it to our local machine.

To get started creating your own package, create a folder following the naming convention ([package-name]-[package-version]), in our case it will be demo-1.0.0. In this directory, create empty files values.yml, package.yml and a templates directory. In the templates directory create an empty template.yml file.

Go into the package.yml where we are going to specify the package metadata, for this app we are only going to be filling the minimum values possible:

# package.yml

apiVersion: skipper.spring.io/v1
kind: SkipperPackageMetadata
name: demo
version: 1.0.0
description: Greets the world!

Importantly here, ensure that your name and version matches the name and version in your folder name or you will get an error.

Next, open up your templates/template.yml. Here we are going to be specifying the actual information about your package and most importantly setting default values. In the template.yml, copy the template for the kind SpringCloudDeployerApplication from the above sample.

# templates/template.yml

apiVersion: skipper.spring.io/v1
kind: SpringCloudDeployerApplication
metadata:
  name: demo
spec:
  resource: maven://org.springframework.cloud.samples:spring-cloud-skipper-samples-helloworld
  version: {{version}}
  applicationProperties:
    {{#spec.applicationProperties.entrySet}}
    {{key}}: {{value}}
    {{/spec.applicationProperties.entrySet}}
  deploymentProperties:
    {{#spec.deploymentProperties.entrySet}}
    {{key}}: {{value}}
    {{/spec.deploymentProperties.entrySet}}

Simply, this specifies our application name is demo, and finds our package in maven and we can specify a version, applicationProperties and deploymentProperties in our values.yml. So lets do that.

# values.yml

# This is a YAML-formatted file.
# Declare variables to be passed into your templates
version: 1.0.0.RELEASE
spec:
  applicationProperties:
    server.port: 8100

This will set out version to 1.0.0.RELEASE and also set the server.port=8100 as one of the application properties. When the Skipper Package reader resolves these values by merging the values.yml against the template, the resolved values would look like this:

# hypothetical template.yml

apiVersion: skipper.spring.io/v1
kind: SpringCloudDeployerApplication
metadata:
  name: demo
spec:
  resource: maven://org.springframework.cloud.samples:spring-cloud-skipper-samples-helloworld
  version: 1.0.0.RELEASE
  applicationProperties:
    server.port: 8100
  deploymentProperties:

The reason to use values.yml instead of entering the values directly is that it allows you to overwrite the values at run time using the --file or --properties flags.

We have now finished making our file, we now have to zip it up. The easiest way to do is the zip -r command line command. You should see something like:

$ zip -r demo-1.0.0.zip demo-1.0.0/
  adding: demo-1.0.0/ (stored 0%)
  adding: demo-1.0.0/package.yml (deflated 14%)
  adding: demo-1.0.0/templates/ (stored 0%)
  adding: demo-1.0.0/templates/template.yml (deflated 55%)
  adding: demo-1.0.0/values.yml (deflated 4%)

Armed with our zipped file and the path to it, we can head to skipper and use the upload command:

skipper:>package upload --path /Users/path-to-your-zip/demo-1.0.0.zip
Package uploaded successfully:[demo:1.0.0]

Now you can search for it as shown above, then install it!

skipper:>package install --package-name demo --package-version 1.0.0 --release-name demo
Released demo. Now at version v1.

Congratulations! You have now created, packaged, uploaded and installed your own Skipper Package!