diff --git a/docs-old/README.md b/docs-old/README.md new file mode 100644 index 00000000000..62a8e27886b --- /dev/null +++ b/docs-old/README.md @@ -0,0 +1,17 @@ +# Table of Contents + +* [Read Me](../README.md) +* [Introduction](./introduction/README.md) + * [Getting Started](./introduction/getting-started.md) + * [Motivation](./introduction/motivation.md) +* [Guides](./guides/README.md) + * [Configuration](./guides/configuration.md) + * [Using Garden with Minikube](./guides/minikube.md) + * [Remote Kubernetes](./guides/remote-kubernetes.md) + * [Glossary](./guides/glossary.md) +* [Reference](./reference/README.md) + * [Commands](./reference/commands.md) + * [Config](./reference/config.md) +* [Examples](./examples/README.md) + * [Simple Project](./examples/simple-project.md) +* [FAQs](./faqs.md) \ No newline at end of file diff --git a/docs-old/examples/README.md b/docs-old/examples/README.md new file mode 100644 index 00000000000..1fcbf2b2ebf --- /dev/null +++ b/docs-old/examples/README.md @@ -0,0 +1,6 @@ +# Examples + +The source code for the examples in this section can be found in our Github repository under the +[examples directory](https://github.com/garden-io/garden/tree/master/examples). + +* [Simple Project](./simple-project.md) \ No newline at end of file diff --git a/docs-old/examples/simple-project.md b/docs-old/examples/simple-project.md new file mode 100644 index 00000000000..60b9842968c --- /dev/null +++ b/docs-old/examples/simple-project.md @@ -0,0 +1,309 @@ +# Simple Project + +In this guide, we'll walk you through configuring a simple project to run on the Garden framework. The project will consist of two Dockerized web services that communicate with one another, along with unit and integration tests. + +In what follows you'll learn how to: + +* [Configure the project](#project-wide-configuration) +* [Configure individual modules](#module-configuration) +* [Deploy the project locally](#deploying) +* [Have the services communicate with one another](#inter-service-communication) +* [Manage service dependencies](#dependencies) +* [Test services](#testing) + +## Before you get started + +This tutorial assumes that you have already have a running [installation of Garden](../introduction/getting-started.md). + +## Clone the example repo + +The code for this tutorial can be found in our Github repository under the [examples directory](https://github.com/garden-io/garden/tree/master/examples). We'll use the [simple-project-start](https://github.com/garden-io/garden/tree/master/examples/simple-project-start/) example and work our way from there. The complete version is under [simple-project](https://github.com/garden-io/garden/tree/master/examples/simple-project). + +First, let's clone the examples repo, change into the directory, and take a look inside: +```sh +$ git clone https://github.com/garden-io/garden/examples.git +$ cd garden/examples/simple-project-start +$ tree . +. +└── services + ├── go-service + │   ├── Dockerfile + │   └── webserver + │   └── main.go + └── node-service + ├── Dockerfile + ├── app.js + ├── main.js + ├── package.json + └── test + └── integ.js + +5 directories, 7 files + ``` + +As you can see the project consists of two super simple services and their accompanying Dockerfiles. One of the core tenets of multi-service backends is being able to pick the right tool for the job, and therefore we have a Node.js service and a Golang service, that we can pretend have different responsibilities. + +The task at hand is to configure these services so that they can run on the Garden framework. + +## Project-wide configuration + +To begin with, every project needs a project-wide `garden.yml` [configuration file](../guides/configuration.md#Config) at the root level. There we define, among other things, the name of the project, and the [providers](../guides/glossary.md#Provider) used for each [plugin](../guides/glossary.md#Plugin) the project requires. + +Let's go ahead and create one: + +```sh +$ touch garden.yml +``` + +and add the following configuration: + +```yaml +project: + name: simple-project + environments: + - name: local + providers: + - name: local-kubernetes +``` + +Above, we've specified the name of our project and configured it to use the local-kubernetes plugin for local development. Note, that this file must be located in the project root directory. + +## Module configuration + +Now, let's turn to our services. Services live inside [modules](../guides/glossary.md#Module), and each module has it's own `garden.yml` configuration file. + +We'll start with the module for the `node-service`: + +```sh +$ touch services/node-service/garden.yml +``` + +and add the following: + +```yaml +module: + description: Node service container + type: container +``` + +By running the `scan` command we can see that Garden detects our module config: + +```sh +$ garden scan +- name: node-service + type: container + path: /Users/eysi/code/simple-project/services/node-service + description: Node service container + version: + versionString: 2c8818986d-1528373640 + latestCommit: 2c8818986d + dirtyTimestamp: 1528373640 +``` + +Under the `module` directive of our `services/node-service/garden.yml` file we can now specify how to run our service: + +```yaml +module: + description: Node service container + type: container + services: + - name: node-service + command: [npm, start] + ports: + - name: http + containerPort: 8080 + endpoints: + - path: /hello-node + port: http +``` +The [services](../guides/configuration.md#Services) directive is specific to container modules, and defines the services exposed by the module. In this case, our containerized Node.js server. The sub-directives tell Garden how to start the service and which endpoints to expose. + +## Deploying + +With this configuration we're almost ready to deploy. First, we'll need to create a user namespace for our environment with the login command: + +```sh +$ garden login +``` + +Garden can now deploy our service to a local Kubernetes cluster: + +```sh +$ garden deploy +``` + +To verify that everything is working, we can call the service at the `/hello-node` endpoint defined in `/services/node-service/app.js`: + +```sh +$ garden call node-service/hello-node +✔ Sending HTTP GET request to http://simple-project.local.app.garden/hello-node + +200 OK + +Hello from Node server! +``` + +In a similar manner, we create a config file for our `go-service`: + +```sh +$ touch services/go-service/garden.yml +``` + +and add the following: + +```yaml +module: + description: Go service container + type: container + services: + - name: go-service + ports: + - name: http + containerPort: 80 + endpoints: + - path: /hello-go + port: http +``` + +Run the deploy command again, this time only for the `go-service`: + +```sh +$ garden deploy go-service +``` + +Another way to verify that our services are up and running is to have a look at the service logs. We can either get an aggregate from all our services, by running `garden logs`, or we can specify a list of services. This time we're only interested in our `go-service`: + +```sh +$ garden logs go-service +go-service → 2018-06-07T12:52:41.075Z → Server running... +``` + +Looks good! Let's take stock: + +* We started out with a project consisting of multiple containerized services (really just two, but hey, it's a _simple_ project). +* We added a project wide configuration at the root level, and a module configuration for each service. +* We deployed our entire project with the `garden deploy` command +* We saw how we could call our services and read their logs with the `garden call` and `garden logs` commands. + +## Inter-service communication + +Calling our `go-service` from our `node-service` is straightforward from within the application code. Crack open `services/node-service/app.js` with your favorite editor and add the following: + +```javascript +const request = require('request-promise') + +// Unless configured otherwise, the hostname is simply the service name +const goServiceEndpoint = `http://go-service/hello-go`; + +app.get('/call-go-service', (req, res) => { + // Query the go-service and return the response + request.get(goServiceEndpoint) + .then(message => { + res.json({ + message, + }) + }) + .catch((err) => { + res.statusCode = 500 + res.json({ + error: err, + message: "Unable to reach service at " + goServiceEndpoint, + }) + }) +}) +``` + +Now let's re-deploy the `node-service` and try out our new endpoint: + +```sh +$ garden deploy node-service +$ garden call node-service/call-go-service +✔ Sending HTTP GET request to http://simple-project.local.app.garden/call-go-service + +200 OK + +{ + "message": "Hello from Go!" +} +``` + +Nice! + +So far, we've seen how to configure a simple project and it's modules, how to deploy our services, and how these services can communicate. Next, let's take a look at how we can define dependencies and set up testing. + +## Dependencies + +An attentive reader will no doubt have noticed that our `node-service` depends on the `go-service` for it's `call-go-service` endpoint. We can express this in the `node-service` module configuration by adding `dependencies` under the `services` directive: + +```yaml +module: + description: Node service container + ... + services: + - name: node-service + command: [npm, start] + ... + dependencies: + - go-service +``` + +This will ensure that our `go-service` will be deployed before the `node-service`. + +## Testing + +Finally, we'll update our `node-service` module configuration to tell Garden how to run our tests. Add the following test config under the `module` directive in `services/node-service/garden.yml`: + +```yaml +module: + description: Node service container + ... + services: + - name: node-service + command: [npm, start] + ... + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - go-service +``` + +This allows us to run individual test groups by name or all of them at once with the test command: + +```sh +$ garden test +``` + +Notice also that the integration test depends on the `go-service` being deployed. + +The entire module config should now look like this: + +```yaml +module: + description: Node service container + type: container + services: + - name: node-service + command: [npm, start] + ports: + - name: http + containerPort: 8080 + endpoints: + - path: / + port: http + dependencies: + - go-service + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - go-service +``` + +And that's it! Our services are up and running locally, dependencies are resolved, and tests are ready to run. + +Check out some of our other [Guides](../guides/README.md) for more of an in-depth look at the Garden framework. \ No newline at end of file diff --git a/docs-old/faqs.md b/docs-old/faqs.md new file mode 100644 index 00000000000..9b92ecddb13 --- /dev/null +++ b/docs-old/faqs.md @@ -0,0 +1,6 @@ +# Frequently Asked Questions + +### When using garden inside tmux, colors look wonky. What gives? + +You need to set tmux to use 256 colors. As per the [official documentation](https://github.com/tmux/tmux/wiki/FAQ#how-do-i-use-a-256-colour-terminal), you +can do that by adding `set -g default-terminal "screen-256color"` or `set -g default-terminal "tmux-256color"` to your `~/.tmux.conf` file. diff --git a/docs/garden-banner-logotype-left-2.png b/docs-old/garden-banner-logotype-left-2.png similarity index 100% rename from docs/garden-banner-logotype-left-2.png rename to docs-old/garden-banner-logotype-left-2.png diff --git a/docs/guides/README.md b/docs-old/guides/README.md similarity index 100% rename from docs/guides/README.md rename to docs-old/guides/README.md diff --git a/docs/guides/configuration.md b/docs-old/guides/configuration.md similarity index 100% rename from docs/guides/configuration.md rename to docs-old/guides/configuration.md diff --git a/docs/guides/glossary.md b/docs-old/guides/glossary.md similarity index 100% rename from docs/guides/glossary.md rename to docs-old/guides/glossary.md diff --git a/docs/guides/minikube.md b/docs-old/guides/minikube.md similarity index 100% rename from docs/guides/minikube.md rename to docs-old/guides/minikube.md diff --git a/docs/guides/remote-kubernetes.md b/docs-old/guides/remote-kubernetes.md similarity index 100% rename from docs/guides/remote-kubernetes.md rename to docs-old/guides/remote-kubernetes.md diff --git a/docs/introduction/README.md b/docs-old/introduction/README.md similarity index 100% rename from docs/introduction/README.md rename to docs-old/introduction/README.md diff --git a/docs-old/introduction/getting-started.md b/docs-old/introduction/getting-started.md new file mode 100644 index 00000000000..e0d58c1006d --- /dev/null +++ b/docs-old/introduction/getting-started.md @@ -0,0 +1,42 @@ +# Getting Started + +This guide will walk you through setting up the Garden framework. + +Please follow the guide for your operating system: + +* [macOS](#macos) +* [Windows](#windows) +* [Linux (or manual installation on other platforms)](#linux-manual-installation) + +## Using the CLI + +With the CLI installed, we can now try out a few commands using the [hello-world](https://github.com/garden-io/garden/examples/tree/master/simple-project) project from our Github [examples repository](https://github.com/garden-io/garden/examples). The example consists of a a couple of simple services. + +_Note: check if Kubernetes is running with `kubectl version`. You should see both a `Client Version` and a `Server Version` in the response. If not, please start it up before proceeding._ + +Clone the repo and change into the `hello-world` directory: + +```sh +$ git clone https://github.com/garden-io/garden/examples.git +$ cd garden/examples/hello-world +``` + +First, let's check the environment status by running the following from the project root: + +```sh +$ garden status +``` + +The response tells us how the environment is configured and the status of the providers. Next, we'll deploy the services with: + +```sh +$ garden deploy +``` + +And that's it! The services are now running on the Garden framework. You can see for yourself by querying the `/hello` endpoint of the container with: + +```sh +$ garden call hello-container/hello +``` + +Check out our [Commands guide](../guides/commands.md) for other features like auto-reload, streaming service logs, running tests and lots more, or see how a Garden project is configured from scratch in our [Simple Project](../guides/simple-project.md) guide. \ No newline at end of file diff --git a/docs/introduction/motivation.md b/docs-old/introduction/motivation.md similarity index 100% rename from docs/introduction/motivation.md rename to docs-old/introduction/motivation.md diff --git a/docs-old/reference/README.md b/docs-old/reference/README.md new file mode 100644 index 00000000000..aa067ae31dc --- /dev/null +++ b/docs-old/reference/README.md @@ -0,0 +1,5 @@ +# Reference + +* [Commands](./commands.md) +* [Config](./config.md) +* [Template strings](./template-strings.md) diff --git a/docs/reference/commands.md b/docs-old/reference/commands.md similarity index 100% rename from docs/reference/commands.md rename to docs-old/reference/commands.md diff --git a/docs/reference/config.md b/docs-old/reference/config.md similarity index 100% rename from docs/reference/config.md rename to docs-old/reference/config.md diff --git a/docs/reference/template-strings.md b/docs-old/reference/template-strings.md similarity index 100% rename from docs/reference/template-strings.md rename to docs-old/reference/template-strings.md diff --git a/docs/README.md b/docs/README.md index d7b1654595f..8652c49885f 100644 --- a/docs/README.md +++ b/docs/README.md @@ -1,17 +1,87 @@ -# Table of Contents - -* [Read Me](../README.md) -* [Introduction](./introduction/README.md) - * [Getting Started](./introduction/getting-started.md) - * [Motivation](./introduction/motivation.md) -* [Guides](./guides/README.md) - * [Configuration](./guides/configuration.md) - * [Using Garden with Minikube](./guides/minikube.md) - * [Remote Kubernetes](./guides/remote-kubernetes.md) - * [Glossary](./guides/glossary.md) -* [Reference](./reference/README.md) - * [Commands](./reference/commands.md) - * [Config](./reference/config.md) -* [Examples](./examples/README.md) - * [Simple Project](./examples/simple-project.md) -* [FAQs](./faqs.md) +[![CircleCI](https://circleci.com/gh/garden-io/garden/tree/master.svg?style=svg&circle-token=ac1ec9984d093f91e594e5a0a03b34cec2c2a093)](https://circleci.com/gh/garden-io/garden/tree/master) + + +![](docs/garden-banner-logotype-left-2.png) + +*Welcome! Garden is a full-featured development framework for containers and serverless backends, designed to make +it easy to develop and test distributed systems.* +

+ +### Status + +The project is in _early alpha_ (or developer preview, if you prefer). This means APIs may well change (not drastically, but still), overall stability will improve and platform support is still limited. + +All that said, Garden can already be highly useful if the following applies to you: + +* **You're deploying to (or transitioning to) Kubernetes.** +* **You really don't want to spend your precious hours building your own developer tooling!** + +If that sounds right for you, please give it a go and don't hesitate to report issues. + + +## Features + +With Garden, you can... + +* Configure and deploy a fleet of services to a local Kubernetes cluster using simple declarations. +* Use an integrated framework for building, testing and deploying services. +* Easily run end-to-end tests across multiple services without waiting for a slow CI pipeline. +* Automatically build, deploy and/or test when your code changes, using the `--watch` flag or the `garden dev` command. +* Manage build and runtime dependencies across all your services. +* Leverage a suite of commands and helpers to facilitate developing and running your stack. +* _Write code the way you want, and run your production system however suits you! Garden does not impose any new libraries or languages aside from the config files._ + +Garden is also designed to be pluggable and modular, with Kubernetes being just one plugin (albeit an important one). Over time we will add native support for a variety of platforms, including AWS (Lambda, ECS, Fargate and more), GCP, Heroku... and the list will continue growing. + + +## Usage + +Head over to our [Quick Start guide](https://docs.garden.io/basics/getting-started/quick-start), and then look through our [Simple Project](https://docs.garden.io/examples/simple-project) guide to get a quick sense of how everything works. + +For a more in-depth approach, just keep reading this documentation. + +[![asciicast](https://asciinema.org/a/SKI7qe7DFVVHxvoaIVrLPb6Es.png)](https://asciinema.org/a/SKI7qe7DFVVHxvoaIVrLPb6Es?speed=2) + +## Contributing + +We welcome any and all contributions to Garden! What we're trying to achieve is a big task, and +developers have a lot of diverse needs, so we need and appreciate your input, whether it's through +code, docs, issues or developing plugins for your needs. + +For more detailed guidelines, see [CONTRIBUTING.md](CONTRIBUTING.md). + + +# Motivation + +The landscape of server-side development has changed immensely over the last decade. +This has partly been driven by evolving needs — **scalability has become table-stakes for most +projects and companies** — and also by the rapid development and proliferation of new technologies +like containers. + +From an operations standpoint, all of this is fantastic. Scaling out is increasingly simple +and cost-effective, and managing production systems is easier than ever. So much so, that the +notion of DevOps has caught on — if ops is so easy, why not have the developers do it +themselves? + +And the promise of it all is great. Microservices, immutable infrastructure, continuous +integration and deployment, all that jazz. Trouble is, all this tends to come at the expense +of application developer productivity. In embracing these new technologies and tools, we've +_over-optimized for ops, and in turn made it more difficult and tedious to work on the actual +application code_. + +Now, rather than lament and pine for the good ol' monolith days, we at Garden feel that this can +be addressed by **a new generation of developer tooling**. So that's what we've set out to make. +It's certainly not a trivial task, but we truly believe that it's possible to not only reclaim the +rapid feedback loops we're used to when developing individual services, but to go further and +leverage the benefits of modern backend platforms to make development easier and faster than ever. + +So think of Garden as the missing layer on top of Kubernetes, AWS, GCP, etc., that focuses purely +on the **developer experience**, makes it trivial to work across multiple platforms, and closes the +gap between infrastructure and application development. + +We do this by frameworking around the basic primitives of development — building, testing, +debugging and deploying — and making the _how_ of each of those pluggable and configurable. +This allows the framework to grow with you and adapt as your needs evolve in terms of how you +architect and run your code in production, and allows us to easily tie together all the amazing +open-source tools that are being developed in the ecosystem, into an **integrated, consistent +and easy-to-use development framework**. diff --git a/docs/basics/README.md b/docs/basics/README.md new file mode 100644 index 00000000000..f0c272935ff --- /dev/null +++ b/docs/basics/README.md @@ -0,0 +1,11 @@ +# Basics + +The following articles cover the basics of installing and using Garden: + + * Installation instructions for your platform: [Installation](./basics/installation.md). + * A very brief guide on the main commands you should be familiar with, and an example project to test them in: [Quick Start](./basics/quick-start.md). + * An overview of the framework's main concepts, to help get you started using Garden with your own projects: [Concepts](./basics/concepts.md). + +If you're already familiar with the basics, feel free to move on to the next chapter: [Using Garden](./using-garden/README.md). + +Or dive right in by exploring our [Guides](./guides/README.md) and [Example projects](./examples/README.md). diff --git a/docs/basics/concepts.md b/docs/basics/concepts.md new file mode 100644 index 00000000000..3b9e2478d14 --- /dev/null +++ b/docs/basics/concepts.md @@ -0,0 +1,51 @@ +# How Garden works + +The mechanics for how Garden works are fundamentally straight forward: + +The main functionality is housed under what we call providers. We have, for example, a provider for containers, one for OpenFaaS, one for Kubernetes, and providers are how we control the behavior of these different types of tools. + +Garden projects, in turn, consist of modules. Each module in a project has a type (e.g. container, OpenFaaS), and the type then indicates which provider should deal with each specific module when it comes to building, deploying, and testing it. + +This information is conveyed through [configuration files](../using-garden/configuration-files.md), usually in YAML format, which live in the project root for project-wide settings, and in each module's directory (for module-specific settings). + +# Projects vs. modules vs. services + +Garden has three main organizational units: projects, modules, and services. + +A project is the largest unit, and it contains all the others. You can think of a project as a context: there aren't any hard rules or limitations as to how big or small your project should be, but it's advisable to keep all elements belonging to a same context inside the same project. + +Modules can be thought of as build units. So, for example, every container and every serverless function should, as a rule of thumb, have its own module. + +Lastly, services are units of deployment, or instances. They're *usually* one per module, but not necessarily: you might have, for example, two instances of the same container working on different queues or data streams. + +To sum it all up: A project consists of one or modules, and each module may deploy zero or more services. + +# The build → test → deploy sequence + +One of the main tools of Garden to make the development of distributed systems extremely agile is the developer framework. You can call with `garden dev`. + +It is a combination of the `build`, `deploy` and `test` commands, that is, it builds, deploys and tests all your modules and services, and re-builds, re-deploys and re-tests as you modify the code. + +The `build`, `deploy` and `test` commands, and by extension the `dev` command, are all dependency-aware. They will always build, test, and deploy modules in the right order so that all dependencies are respected. + +# How inter-service communication works + +Arguably the most important thing a distributed system needs to do is to allow its different parts to talk to one another. Garden makes inter-service communication extremely simple: a service's hostname is simply its name as declared in the configuration file. + +For example, if you have a service called `my-service`, you can access its `/feature` endpoint by simply calling `http://my-service/feature`. + +# Hot reload + +Hot reloading is updating a running service when its source files are changed, without re-building and re-deploying the whole thing. + +In the case of a container, for example, we would not destroy the container, change the files, and then re-deploy a new container. Instead, we would update the changed files without stopping the running container, thus potentially not losing the current state of the application. + +Hot reload is off for all modules by default, and it needs to be enabled with the `hotReload` field a module's configuration file. For more detailed information, see the [configuring hot reload](./guides/configuring-hot-reload.md) guide. + +# Projects with multiple and/or remote repositories + +Garden projects may include sources hosted in any number of local or remote repositories. Remote sources may be later linked to local directories for convenience or to work offline. + +You could have, for example, a project that has one local module, then one remote module from an external source, and then a second external source that contains, let's say, two more modules. + +For specifics see our [Remote sources project](../examples/remote-sources.md) example. \ No newline at end of file diff --git a/docs/basics/installation.md b/docs/basics/installation.md new file mode 100644 index 00000000000..c30f0464cb7 --- /dev/null +++ b/docs/basics/installation.md @@ -0,0 +1,175 @@ +## Installation + +This guide will walk you through setting up the Garden framework. + +Please follow the guide for your operating system: + +* [macOS](#macos) +* [Windows](#windows) +* [Linux (Manual Installation)](#linux-manual-installation) + +And if you decide to use Minikube, please see our [Minikube Instructions](#minikube-instructions) further down this +document. + +### macOS + +For Mac, we recommend the following steps to install Garden. You can also follow the manual installation +steps below if you prefer. + +#### Step 1: Install homebrew + +If you haven't already set up homebrew, please follow [their instructions](https://brew.sh/) to set it up. + +#### Step 2: Docker and local Kubernetes + +To install Docker, Kubernetes and kubectl, we strongly recommend Docker for Mac (edge version). + +_Note: you need to install the **edge version** of Docker for Mac to enable Kubernetes support._ + +Once installed, open the Docker for Mac preferences, go to the Kubernetes section, +tick `Enable Kubernetes` and save. Please refer to their +[installation guide](https://docs.docker.com/engine/installation/) for details. + +Alternatively, you can use Minikube. We generally find it less stable and more hassle to +configure and use, but we do fully support it on Mac. Please look at the +[Minikube Instructions](#minikube-instructions) section for details. + +#### Step 3: Install `garden-cli` + +We have a Homebrew tap and package that you can use to easily install `garden-cli` and all dependencies: + +```sh +brew tap garden-io/garden +brew install garden-cli +``` + +To later upgrade to the newest version, simply run `brew update` and then `brew upgrade garden-cli` +(or `brew upgrade` to upgrade all your Homebrew packages). + +### Windows + +You can run Garden on Windows 10 Pro or Enterprise editions (unfortunately, the Home edition does not work, because it +does not support virtualization). To install the Garden CLI, please use our _automated installation script_, which will +check for dependencies, install missing dependencies if needed, and finally install the `garden-cli` npm package. + +The script will check for the following: + +* The [Chocolatey](https://chocolatey.org) package manager. +* Whether you have Hyper-V enabled. This is required for _Docker for Windows_. If you do not already have it enabled, + the script will enable it (you will then need to restart your computer before starting Docker for Windows). +* Docker - We strongly recommend using the _Edge version_ of + [Docker for Windows](https://www.docker.com/docker-windows), which has built-in support for Kubernetes. Garden also supports different configurations of Docker and Kubernetes, using Minikube for example, but + Docker for Windows is generally easier to install and configure, and is well supported. The script will check if Docker is + installed, and whether Kubernetes has been enabled as the default orchestrator. +* Node.js - The script will install it via Chocolatey if it is missing. _If you already have Node.js + installed, please make sure it is version 8.x or newer._ +* Git and rsync - The script will install those if they are missing. + +To run the script, open PowerShell as an Administrator and run: + +```PowerShell +Set-ExecutionPolicy Bypass -Scope Process -Force; iex ((New-Object System.Net.WebClient).DownloadString('https://raw.githubusercontent.com/garden-io/garden/master/garden-service/support/install.ps1')) +``` + +To later upgrade to the newest version, run `npm install -g -U garden-cli`. + +### Linux (manual installation) + +You need the following dependencies on your local machine to use Garden: + +* Node.js >= 8.x +* [Docker](https://docs.docker.com/) +* Git +* rsync +* Local installation of Kubernetes and kubectl + +#### Step 1: Docker + +To install Docker, please follow the instructions in the [official documentation](https://docs.docker.com/install/). + +#### Step 2: Local Kubernetes + +For local Kubernetes, you can use [Minikube](https://github.com/kubernetes/minikube). Please see our +[Minikube Instructions](#minikube-instructions). + +#### Step 3: Install other dependencies + +Use your preferred method or package manager to install `node` (version 8.x or higher), `git`, and `rsync`. + +On Ubuntu 18, you'd do `sudo apt install git rsync` for Git and rsync. + +To install Node, we recommend using nvm. You can install nvm e.g. by executing the following in a shell: +```sh +curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.11/install.sh | bash +``` +and restarting your terminal. You can then install Node via `nvm install node`. + +#### Step 4: Install `garden-cli` + +Once you have the dependencies set up, install the Garden CLI via `npm`: + +```sh +npm install -g garden-cli +``` + +To later upgrade to the newest version, run `npm install -g -U garden-cli`. + + +# Minikube Instructions + +Garden can be used with [Minikube](https://github.com/kubernetes/minikube) on supported platforms. + +_NOTE: We highly recommend using Docker for Mac and Docker for Windows, for macOS and Windows respectively._ + +## Installation + +For Minikube installation instructions, please see the [official guide](https://github.com/kubernetes/minikube#installation). + +You'll likely also need to install a driver to run the Minikube VM, please follow the +[instructions here](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md) +and note the name of the driver you use. The driver you choose will likely vary depending on your +OS/platform. We recommend [hyperkit](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#hyperkit-driver) +for macOS and [kvm2](https://github.com/kubernetes/minikube/blob/master/docs/drivers.md#kvm2-driver) on most Linux +platforms. + +Once Minikube and the appropriate driver for your OS is installed, you can start it by running: + +```sh +minikube start --vm-driver= # e.g. hyperkit on macOS +``` + +You'll also need to have Docker (for macOS, we recommend [Docker for Mac](https://docs.docker.com/engine/installation/)) +and [kubectl](https://kubernetes.io/docs/tasks/tools/install-kubectl/) installed. + +## Usage + +The `local-kubernetes` plugin attempts to automatically detect if it is installed and set the appropriate context +for connecting to the local Kubernetes instance. In most cases you should not have to update your `garden.yml`, +since it uses the `local-kubernetes` plugin by default, but you can configure it explicitly in your project-level +`garden.yml` as follows: + +```yaml +project: + environments: + - name: local + providers: + - name: local-kubernetes + context: minikube +``` + +If you happen to have installed both Minikube and a version of Docker for Mac with Kubernetes support enabled, +`garden` will choose whichever one is configured as the current context in your `kubectl` configuration, and if neither +is set as the current context, Docker for Mac is preferred by default. + +(If you're not yet familiar with Garden configuration files, see: [Configuration files](../using-garden/configuration-files.md)) + +## Hostname + +Garden needs the Kubernetes instance to have a hostname. By default Garden will use `.nip.io`. If you'd +like to use a custom hostname, you can specify it via the `ingressHostname` in the `local-kubernetes` provider config +(see above). + +## Anything else? + +Once the above is set up, the `local-kubernetes` plugin will automatically configure everything else Garden needs to +work. The built-in nginx ingress controller will be automatically enabled and used to route requests to services. diff --git a/docs/basics/quick-start.md b/docs/basics/quick-start.md new file mode 100644 index 00000000000..585b3c33080 --- /dev/null +++ b/docs/basics/quick-start.md @@ -0,0 +1,58 @@ +# Getting Started + +This guide will walk you through setting up the Garden framework. It assumes you already have Garden installed. If you don't, please check out our [installation guide](./installation.md). + +## Using the CLI + +With the CLI installed, we can now try out a few commands using the [Simple Project](../examples/simple-project.md) from our [example projects](../examples/README.md). The example project consists of a couple of simple modules, each defining one service. + +_Note: Check if Kubernetes is running with `kubectl version`. You should see both a `Client Version` and a `Server Version` in the response. If not, please start it up before proceeding._ + +Clone the repo and change into the `simple-project` directory: + +```sh +$ git clone https://github.com/garden-io/garden.git +$ cd garden/examples/simple-project +``` + +First, let's check the environment status by running the following from the project root: + +```sh +$ garden get status +``` + +The response tells us how the environment is configured and the status of the providers. Next, we'll build our modules with: + +```sh +$ garden build +``` + +This builds Docker images for `go-service` and `node-service` respectively. Next, we'll deploy the services with: + +```sh +$ garden deploy +``` + +And that's it! The `garden build` step above is actually unnecessary (only included here for clarity), since `garden deploy` will also rebuild modules as needed. The services are now running on the Garden framework. You can see for yourself by querying the `/hello` endpoint of `go-service`'s running container: + +```sh +$ garden call go-service/hello-go +``` + +To run tests for all modules: + +```sh +$ garden test +``` + +And if you prefer an interactive terminal that watches your project for changes and re-builds, re-deploys, and re-tests automatically, try: + +```sh +$ garden dev +``` + +Go ahead, leave it running and change one of the files in the project, then watch it re-build. + +That's it for now. Check out our [Using Garden](../using-garden/README.md) section for other features like hot reload, remote clusters, integration tests, and lots more. + +To see how a Garden project is configured from scratch check, out the [Simple Project](../examples/simple-project.md) guide for a more in-depth presentation. diff --git a/docs/contributing.md b/docs/contributing.md new file mode 100644 index 00000000000..e10b3699789 --- /dev/null +++ b/docs/contributing.md @@ -0,0 +1,92 @@ +!!! WORK IN PROGRESS !!! + +# README.md + +This is the source code for the garden framework. + +Here's a high-level overview of how the whole thing works: + +![](schematic.jpg) + +The main components are plugins, projects, and the framework itself. + +### Projects + +Projects are your user's files. A project is composed of modules, which are in turn composed of services. + +Let's see our [hello-world](https://github.com/garden-io/garden/tree/master/examples/hello-world) example: + - It has two modules, `hello-container` and `hello-function`. + - `hello-container` contains one service, named `hello-container`. + - `hello-function` also contains only one service, named `hello-function`. + +Just as you may have many modules per project, you may have many services per module. + +Beware that no two services may have the same name in the project. (You could want to, for example, have a `logging` service on multiple modules. In this case you'll need a different name for each.) + +### Plugins + +Plugins are garden's way of knowing what to do about each module in a project. The way a container behaves is different than a serverless function, for example, and plugins are the way to define those different behaviours. + +Plugins interact with the project via the plugin interface. For more detailed information, see the README.md file in the plugin directory. + +### The Framework + +In the context of projects and plugins, what the framework does is: + + 1. Watch project files for changes + 2. Provide plugins with context so they can operate on the project + 3. Keep track of state as multiple plugins work independently + +# Plugins + +To define a plugin you need to return a `GardenPlugin` object, and then declare that on the `builtinPlugins` object on the `garden/src/plugins/plugins.ts` file. + +`GardenPlugin` is an interface that lives on `garden/src/types/plugin/plugin.ts`: + +```typescript +export interface GardenPlugin { + config?: object + configKeys?: string[] + + modules?: string[] + + actions?: Partial + moduleActions?: { [moduleType: string]: Partial } +} +``` + +The way your plugin interacts with the rest of the world is via actions. These can be of three types: plugin actions, module actions, and service actions. They are: + +Plugin Actions: + + - getEnvironmentStatus + - configureEnvironment + - destroyEnvironment + - getConfig + - setConfig + - deleteConfig + - getLoginStatus + - login + - logout + +Module Actions: + + - parseModule + - getModuleBuildStatus + - buildModule + - pushModule + - runModule + - testModule + - getTestResult + +Service Actions: + + - getServiceStatus + - deployService + - getServiceOutputs + - execInService + - getServiceLogs + - runService + + + diff --git a/docs/examples/README.md b/docs/examples/README.md index 1fcbf2b2ebf..2d9f17faf9f 100644 --- a/docs/examples/README.md +++ b/docs/examples/README.md @@ -1,6 +1,17 @@ -# Examples +# Example projects -The source code for the examples in this section can be found in our Github repository under the -[examples directory](https://github.com/garden-io/garden/tree/master/examples). +## [Hello world](./hello-world.md) -* [Simple Project](./simple-project.md) \ No newline at end of file +In this project we see in practice the basics of configuring dependencies, defining ports and endpoints, and setting up tests. + +## [Simple project](./simple-project.md) + +Here we see how to "gardenify" a pre-existing project, creating a project config and the individual module configs for every part. + +## [TLS project](./tls-project.md) + +This is an example project of how to set up TLS using the `mkcert` tool. + +## [Remote sources project](./remote-sources.md) + +This project demonstrates how to use multiple sources and repositories together into the same project. Although in this project we're using _remote_ sources, the same applies to using multiple _local_ repositories. \ No newline at end of file diff --git a/docs/examples/hello-world.md b/docs/examples/hello-world.md new file mode 100644 index 00000000000..64ae919e71c --- /dev/null +++ b/docs/examples/hello-world.md @@ -0,0 +1,127 @@ +# Hello World + +In this example, we'll have a practical look at the main characteristics of a Garden project: + +- Dependencies +- Ports, endpoints, and health check settings +- Tests + +This project contains four configuration files. [This one](https://github.com/garden-io/garden/tree/master/examples/hello-world/garden.yml) for project-wide settings, and three separate ones for each of the modules: [`hello-container`](https://github.com/garden-io/garden/tree/master/examples/hello-world/services/hello-container/garden.yml), [`hello-function`](https://github.com/garden-io/garden/tree/master/examples/hello-world/services/hello-function/garden.yml), and [`hello-npm-package`](https://github.com/garden-io/garden/tree/master/examples/hello-world/libraries/hello-npm-package/garden.yml). + +# Configuring dependencies + +There are three main types of dependencies we'll be dealing with: build dependencies, runtime dependencies, and test dependencies. + +You can think of build dependencies as libraries. For example, our `hello-world/services/hello-container/app.js` file in the `hello-container` module requires the `hello-npm-package` to be imported: + +```js +const hello = require("./libraries/hello-npm-package") +``` + +For `hello-npm-package` to be imported by `hello-container`, of course, it needs to be built first. Thus, we specify it as a build dependency. Take a look at its `config.yml`: + +```yml + build: + dependencies: + - name: hello-npm-package + copy: + - source: "./" + target: libraries/hello-npm-package/ +``` + +_Note: `source` refers to the path on the dependency module being specified, and `target` refers to where it will be accessed from by the dependant module (picture it as a mount directory)._ + +Runtime dependencies, on the other hand, are irrelevant at build time, but required for execution. For example, as we can see on the `app.js` file, the `hello-container` module depends on `hello-function` being up and running: + +```js +const functionEndpoint = process.env.GARDEN_SERVICES_HELLO_FUNCTION_ENDPOINT +``` + +So let's see how to make sure `hello-function` is running before `hello-container`: + +```yaml +module: + description: Hello world container service + type: container + name: hello-container + services: + ... + dependencies: + - hello-function +``` + +Test dependencies will be covered further ahead. + +# Defining ports, endpoints, and health checks + +Before we can define our endpoints and health checks we'll to define the ports we'll be working with. For example, below we'll assign the name `http` to port number `8080`: + +```yml +module: + description: Hello world container service + ... + services: + ... + ports: + - name: http + containerPort: 8080 +``` + +Now let's use that port and a path to define an ingress endpoint for the service to expose: + +```yml +module: + description: Hello world container service + ... + services: + ... + ports: + - name: http + containerPort: 8080 + endpoints: + - path: /hello + port: http +``` + +Lastly, health checks currently have three possible types: `httpGet`, `command`, and `tcpPort`. They're specified in the [Config Files Reference](../reference/config-files-reference.md). + +For the Hello World project, we'll use the first one. This `healthCheck` endpoint will be pinged periodically to ensure that the service is still healthy. Here's what it looks like: + +```yml +module: + description: Hello world container service + ... + services: + ... + ports: + - name: http + containerPort: 8080 + endpoints: + - path: /hello + port: http + healthCheck: + httpGet: + path: /_ah/health + port: http +``` + +# Setting up tests + +Since Garden is language-agnostic, there aren't any low level requirements about how tests should be arranged. The only requirements are: + +- You must be able to execute a command to run your tests. +- Any non-zero exit codes returned by the command mean your tests have failed, and zero indicates the tests are passing. + +The only difference between unit tests and integration tests, then, are that to run the latter you might need other services to be up and running as well. You can specify them as test dependencies. + +Here's what it looks like in practice: + +```yml + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - hello-function +``` \ No newline at end of file diff --git a/docs/examples/remote-sources.md b/docs/examples/remote-sources.md new file mode 100644 index 00000000000..223ff010c02 --- /dev/null +++ b/docs/examples/remote-sources.md @@ -0,0 +1,106 @@ +# Remote sources example project + +This example demonstrates how you can import remote sources and remote modules into a Garden project. + +_Note: To use multiple local repositories—not remote, as this article describes—simply utilize `file:///my/other/project/path` in the `repositoryUrl` field described below._ + +Important concepts: + +> Remote _source_: A collection of one or more Garden modules that live in a repository different from the main project repository. The `garden.yml` config files are co-located with the modules in the remote repository. + +> Remote _module_: The remote source code for a single Garden module. In this case, the `garden.yml` config file is stored in the main project repository while the module code itself is in the remote repository. + +## About + +This project is the same as the [multi-container example](https://github.com/garden-io/garden/tree/master/examples/multi-container)—except that in this case the services live in their own repositories. The repositories are: + +* [Database services](https://github.com/garden-io/garden-example-remote-sources-db-services) (contains the Postgres and Redis services) +* [Web services](https://github.com/garden-io/garden-example-remote-sources-web-services) (contains the Python Vote web service and the Node.js Result web service) +* [Java worker module](https://github.com/garden-io/garden-example-remote-module-jworker) + +_This split is pretty arbitrary and doesn't necessarily reflect how you would normally separate services into different repositories._ + +## Usage + +This project doesn't require any setup and can be deployed right away. If this is your first time working with this project, Garden will start by fetching the remote source code: +```sh +garden deploy +``` +Garden will continue to use the version originally downloaded. Use the `update-remote sources|modules|all` command to fetch the latest version of your remote sources and modules: +```sh +garden update-remote modules jworker +``` +If you however change the repository URL of your remote source or module (e.g. switch to a different tag or branch), Garden will automatically fetch the correct version. + +It's also possible to link remote sources and modules to a local directory with the `link source|module` command. This is useful for when you want to try out changes to the remote source without having to push them to the remote repository. In this case, you clone the remote source to a local directory and link to its path: +```sh +garden link source web-services path/to/web-services +``` +Now Garden will read the module from its local path, and changes you make will be visible immediately. + +Use the `unlink source|module` command to unlink it again, and revert to the module version the repository URL points to: +```sh +garden unlink source web-services +``` + +## Further reading + +### Project structure + +Looking at the project structure, you'll notice that the project doesn't contain any code outside the `garden.yml` config files. Rather, the config files themselves contain the URLs to the remote repositories. + +```sh +$ tree +. +├── README.md +├── garden.yml +└── services + └── jworker + └── garden.yml + +2 directories, 3 files +``` + +### Configuring remote sources + +For this project, we want to import the database and web services as remote _sources_. This means that the entire source code gets embedded into the project and treated just like our other project files. As usual, Garden will scan the project for `garden.yml` files, and include all modules it finds. + +To import remote sources, we add them under the `sources` key in the top-level project configuration file: + +```yaml +project: + name: remote-sources + sources: + - name: web-services + repositoryUrl: https://github.com/garden-io/garden-example-remote-sources-web-services.git#v0.1.0 + - name: db-services + repositoryUrl: https://github.com/garden-io/garden-example-remote-sources-db-services.git#v0.1.0 +``` + +> Remote repository URLs must contain a hash part that references a specific branch or tag, e.g. `https://github.com/org/repo.git/#my-tag-or-branch`. The remote repositories used in this example all contain the tag `v0.1.0`. Read more about Git tagging [here](https://git-scm.com/book/en/v2/Git-Basics-Tagging). + +### Configuring remote modules + +Additionally, we want to import the Java worker as a remote _module_. In that case, Garden assumes that the remote repository contains the source code for a single Garden module. Furthermore, the `garden.yml` config file for that module is kept in the main project repo: +```sh +$ tree services +services +└── jworker + └── garden.yml + +1 directory, 1 file +``` +and the path to the repository URL is added under the `repositoryUrl` key like so: +```yaml +module: + description: worker + type: container + name: jworker + repositoryUrl: https://github.com/garden-io/garden-example-remote-module-jworker.git#v0.1.0 + services: + - name: javaworker + dependencies: + - redis +``` + +Note that a project can contain its own modules and also import remote sources and modules. \ No newline at end of file diff --git a/docs/examples/simple-project.md b/docs/examples/simple-project.md index 60b9842968c..cf004291f8e 100644 --- a/docs/examples/simple-project.md +++ b/docs/examples/simple-project.md @@ -1,6 +1,6 @@ # Simple Project -In this guide, we'll walk you through configuring a simple project to run on the Garden framework. The project will consist of two Dockerized web services that communicate with one another, along with unit and integration tests. +In this guide, we'll walk you through configuring a simple project to run on Garden. The project will consist of two Dockerized web services that communicate with one another, along with unit and integration tests. In what follows you'll learn how to: @@ -13,23 +13,23 @@ In what follows you'll learn how to: ## Before you get started -This tutorial assumes that you have already have a running [installation of Garden](../introduction/getting-started.md). +This tutorial assumes that you have already have a running [installation of Garden](../basics/installation.md). ## Clone the example repo -The code for this tutorial can be found in our Github repository under the [examples directory](https://github.com/garden-io/garden/tree/master/examples). We'll use the [simple-project-start](https://github.com/garden-io/garden/tree/master/examples/simple-project-start/) example and work our way from there. The complete version is under [simple-project](https://github.com/garden-io/garden/tree/master/examples/simple-project). +The code for this tutorial can be found in our Github repository under the [examples directory](https://github.com/garden-io/garden/tree/master/examples). We'll use the [simple-project-start](https://github.com/garden-io/garden/tree/master/examples/simple-project-start/) example and work our way from there. The final version is under [simple-project](https://github.com/garden-io/garden/tree/master/examples/simple-project). First, let's clone the examples repo, change into the directory, and take a look inside: ```sh -$ git clone https://github.com/garden-io/garden/examples.git +$ git clone https://github.com/garden-io/garden.git $ cd garden/examples/simple-project-start $ tree . . └── services ├── go-service - │   ├── Dockerfile - │   └── webserver - │   └── main.go + │ ├── Dockerfile + │ └── webserver + │ └── main.go └── node-service ├── Dockerfile ├── app.js @@ -41,13 +41,13 @@ $ tree . 5 directories, 7 files ``` -As you can see the project consists of two super simple services and their accompanying Dockerfiles. One of the core tenets of multi-service backends is being able to pick the right tool for the job, and therefore we have a Node.js service and a Golang service, that we can pretend have different responsibilities. +As you can see, the project consists of two super simple services and their accompanying Dockerfiles. One of the core tenets of multi-service backends is being able to pick the right tool for the job, and therefore we have a Node.js service and a Go service, that we can pretend have different responsibilities. The task at hand is to configure these services so that they can run on the Garden framework. ## Project-wide configuration -To begin with, every project needs a project-wide `garden.yml` [configuration file](../guides/configuration.md#Config) at the root level. There we define, among other things, the name of the project, and the [providers](../guides/glossary.md#Provider) used for each [plugin](../guides/glossary.md#Plugin) the project requires. +To begin with, every project needs a project-wide `garden.yml` [configuration file](../using-garden/configuration-files.md) at the root level. There we define, among other things, the name of the project, and the [providers](../reference/glossary.md#Provider) the project requires. Let's go ahead and create one: @@ -66,11 +66,11 @@ project: - name: local-kubernetes ``` -Above, we've specified the name of our project and configured it to use the local-kubernetes plugin for local development. Note, that this file must be located in the project root directory. +Above, we've specified the name of our project and configured it to use the local-kubernetes provider for local development. Note that this file must be located in the project root directory. ## Module configuration -Now, let's turn to our services. Services live inside [modules](../guides/glossary.md#Module), and each module has it's own `garden.yml` configuration file. +Now, let's turn to our services. Services live inside [modules](../reference/glossary.md#Module), and each module has it's own `garden.yml` configuration file. We'll start with the module for the `node-service`: @@ -92,7 +92,7 @@ By running the `scan` command we can see that Garden detects our module config: $ garden scan - name: node-service type: container - path: /Users/eysi/code/simple-project/services/node-service + path: /Users/username/code/simple-project/services/node-service description: Node service container version: versionString: 2c8818986d-1528373640 @@ -112,18 +112,19 @@ module: ports: - name: http containerPort: 8080 - endpoints: + ingresses: - path: /hello-node port: http ``` -The [services](../guides/configuration.md#Services) directive is specific to container modules, and defines the services exposed by the module. In this case, our containerized Node.js server. The sub-directives tell Garden how to start the service and which endpoints to expose. +The [services](../using-garden/configuration-files.md#Services) directive is specific to container modules, and defines the services exposed by the module. In this case, our containerized Node.js server. The sub-directives tell Garden how to start the service and which ingress endpoints to expose. ## Deploying -With this configuration we're almost ready to deploy. First, we'll need to create a user namespace for our environment with the login command: +With this configuration we're almost ready to deploy. First, we'll need to make sure the environment is ready, by +running the init command: ```sh -$ garden login +$ garden init ``` Garden can now deploy our service to a local Kubernetes cluster: @@ -132,7 +133,7 @@ Garden can now deploy our service to a local Kubernetes cluster: $ garden deploy ``` -To verify that everything is working, we can call the service at the `/hello-node` endpoint defined in `/services/node-service/app.js`: +To verify that everything is working, we can call the service at the `/hello-node` ingress defined in `/services/node-service/app.js`: ```sh $ garden call node-service/hello-node @@ -143,7 +144,7 @@ $ garden call node-service/hello-node Hello from Node server! ``` -In a similar manner, we create a config file for our `go-service`: +In a similar manner, we create a config file for our `go-service` with ```sh $ touch services/go-service/garden.yml @@ -160,7 +161,7 @@ module: ports: - name: http containerPort: 80 - endpoints: + ingresses: - path: /hello-go port: http ``` @@ -187,7 +188,7 @@ Looks good! Let's take stock: ## Inter-service communication -Calling our `go-service` from our `node-service` is straightforward from within the application code. Crack open `services/node-service/app.js` with your favorite editor and add the following: +Calling the `go-service` from the `node-service` is straightforward from within the application code. Open `services/node-service/app.js` with your favorite editor and add the following: ```javascript const request = require('request-promise') @@ -290,7 +291,7 @@ module: ports: - name: http containerPort: 8080 - endpoints: + ingresses: - path: / port: http dependencies: @@ -306,4 +307,4 @@ module: And that's it! Our services are up and running locally, dependencies are resolved, and tests are ready to run. -Check out some of our other [Guides](../guides/README.md) for more of an in-depth look at the Garden framework. \ No newline at end of file +Check out some of our other [Example projects](./examples/README.md) for more of an in-depth look. \ No newline at end of file diff --git a/docs/examples/tls-project.md b/docs/examples/tls-project.md new file mode 100644 index 00000000000..610c7f985a8 --- /dev/null +++ b/docs/examples/tls-project.md @@ -0,0 +1,58 @@ +# Local TLS example project + +This project shows how you can configure a TLS certificate to use for local development on Kubernetes. + +For the example to work you need to configure a local certificate authority (CA) on your computer for development. We'll use +[mkcert](https://github.com/FiloSottile/mkcert) for this purpose. + +## Setup + +### Step 1 - Install mkcert + +If you don't have mkcert installed, follow the instructions [here](https://github.com/FiloSottile/mkcert#installation). + +### Step 2 - Generate a certificate + +After you've run `mkcert -install`, run + +```sh +mkcert garden.dev '*.garden.dev' +``` + +_Note: You may choose another hostname if you prefer, but you'll need to update the project `garden.yml` accordingly._ + +### Step 3 - Configure the certificate in your Kubernetes installation + +Create a Kubernetes Secret with your generated certificate and key. + +```sh +kubectl create secret tls tls-garden-dev --key garden.dev+1-key.pem --cert garden.dev+1.pem +``` + +_The filenames above will be different if you used a different hostname._ + +### Step 4 - Configure the hostname in your hosts file + +Add the `garden.dev` hostname to the hosts file on your machine, and have it point to the IP of your local cluster. +If you use Docker for Desktop, the IP will be `127.0.0.1`. If you use minikube, you can get the IP by running +`minikube ip`. + +We recommend using the [hosts](https://github.com/alphabetum/hosts) tool (or something similar) to modify your hosts +file, but you may also edit it directly (it's at `/etc/hosts` on most platforms). + +## Usage + +Once you've completed the above, you can deploy the example project and the exposed ingress endpoints will be +secured with TLS! + +Deploy the project: + +```sh +garden deploy +``` + +And then try sending a simple request using: + +```sh +garden call node-service/hello +``` \ No newline at end of file diff --git a/docs/introduction/getting-started.md b/docs/introduction/getting-started.md deleted file mode 100644 index e583d55819a..00000000000 --- a/docs/introduction/getting-started.md +++ /dev/null @@ -1,162 +0,0 @@ -# Getting Started - -This guide will walk you through setting up the Garden framework. - -## Installation - -### macOS - -For Mac, we recommend the following steps to install Garden. You can also follow the manual installation -steps below if you prefer. - -#### Step 1: Install homebrew - -If you haven't already set up homebrew, please follow [their instructions](https://brew.sh/) to set it up. - -#### Step 2: Docker and local Kubernetes - -To install Docker, Kubernetes and kubectl, we strongly recommend Docker for Mac (edge version). - -_Note: you need to install the **edge version** of Docker for Mac in -order to enable Kubernetes support._ - -Once installed, open the Docker for Mac preferences, go to the Kubernetes section, -tick `Enable Kubernetes` and save. Please refer to their -[installation guide](https://docs.docker.com/engine/installation/) for details. - -Alternatively, you can use Minikube. We generally find it less stable and more hassle to -configure and use, but we do fully support it on Mac if you have it running. Please look at our -[Minikube guide](../guides/minikube.md) for details. - -#### Step 3: Install `garden-cli` - -We have a Homebrew tap and package that you can use to easily install `garden-cli` and all dependencies: - -```sh -brew tap garden-io/garden -brew install garden-cli -``` - -To later upgrade to the newest version, simply run `brew update` and then `brew upgrade garden-cli` -(or `brew upgrade` to upgrade all your Homebrew packages). - -### Windows - -You can run garden on Windows 10 Pro or Enterprise editions. Follow these instructions to get started. - -#### Step 1: Chocolatey - -If you haven't already, install the [Chocolatey](https://chocolatey.org) package manager. - -#### Step 2: Enable Hyper-V - -This is required for _Docker for Windows_ to run. Open PowerShell as an administrator and run: - -```powershell -Enable-WindowsOptionalFeature -Online -FeatureName Microsoft-Hyper-V -All -``` - -This will require a restart. - -#### Step 3: Docker for Windows - -Install the Edge version of [Docker for Windows](https://www.docker.com/docker-windows). - -Once installed, open the Docker for Windows settings, go to the Kubernetes section, -tick `Enable Kubernetes` and save. Please refer to their -[installation guide](https://docs.docker.com/engine/installation/) for details. - -#### Step 4: Install dependencies - -Open PowerShell as an administrator and run: - -```powershell -# install choco packages (note: python is needed to build some dependencies) -choco install -y git nodejs rsync kubernetes-helm - -# install Stern (currently not available as a choco package) -[Net.ServicePointManager]::SecurityProtocol = "tls12, tls11, tls" -Invoke-WebRequest -Uri "https://github.com/wercker/stern/releases/download/1.7.0/stern_windows_amd64.exe" -OutFile "$Env:SystemRoot\system32\stern.exe" - -# install build tools so that node-gyp works -npm install --global --production windows-build-tools -npm config set msvs_version 2015 --global -``` - -#### Step 5: Install `garden-cli` - -Once you have the dependencies set up, open a new PowerShell and install the Garden CLI via `npm`: - -```powershell -npm install -g garden-cli -``` - -To later upgrade to the newest version, run `npm install -g -U garden-cli`. - -### Linux / manual installation - -You need the following dependencies on your local machine to use Garden: - -* Node.js >= 8.x -* [Docker](https://docs.docker.com/) -* Git -* rsync -* [Helm](https://github.com/kubernetes/helm) -* Local installation of Kubernetes and kubectl - -#### Step 1: Docker - -To install Docker, please follow the instructions in the [official documentation](https://docs.docker.com/install/). - -#### Step 2: Local Kubernetes - -For local Kubernetes, you can use [Minikube](https://github.com/kubernetes/minikube). Please see our -[Minikube guide](../guides/minikube.md) for instructions. - -#### Step 3: Install other dependencies - -Use your preferred method or package manager to install `node` (version 8.x or higher), `git`, `rsync` and -[Helm](https://github.com/kubernetes/helm). - -#### Step 4: Install `garden-cli` - -Once you have the dependencies set up, install the Garden CLI via `npm`: - -```sh -npm install -g garden-cli -``` - -To later upgrade to the newest version, run `npm install -g -U garden-cli`. - -## Using the CLI - -With the CLI installed, we can now try out a few commands using the [hello-world](https://github.com/garden-io/garden/examples/tree/master/simple-project) project from our Github [examples repository](https://github.com/garden-io/garden/examples). The example consists of a a couple of simple services. - -_Note: check if Kubernetes is running with `kubectl version`. You should see both a `Client Version` and a `Server Version` in the response. If not, please start it up before proceeding._ - -Clone the repo and change into the `hello-world` directory: - -```sh -$ git clone https://github.com/garden-io/garden/examples.git -$ cd garden/examples/hello-world -``` - -First, let's check the environment status by running the following from the project root: - -```sh -$ garden status -``` - -The response tells us how the environment is configured and the status of the providers. Next, we'll deploy the services with: - -```sh -$ garden deploy -``` - -And that's it! The services are now running on the Garden framework. You can see for yourself by querying the `/hello` endpoint of the container with: - -```sh -$ garden call hello-container/hello -``` - -Check out our [Commands guide](../guides/commands.md) for other features like auto-reload, streaming service logs, running tests and lots more, or see how a Garden project is configured from scratch in our [Simple Project](../guides/simple-project.md) guide. diff --git a/docs/outline.md b/docs/outline.md new file mode 100644 index 00000000000..01e5899aef0 --- /dev/null +++ b/docs/outline.md @@ -0,0 +1,164 @@ +# DELETE THIS FILE ONCE NEW DOCS ARE COMPLETE + +# README + +- Logo +- Status +- Features +- Usage +- Contributing +- Motivation +- Acknowledgements + +# Basics + +- Chapter outline + +## Installation + +- Intro +- macOS +- Windows +- Linux (manual installation) +- Minikube Instructions + +## Quick Start + +- Using the CLI + - garden get status + - garden build + - garden deploy + - garden test + - garden dev + - garden call + +## Concepts + +- How Garden works +- Projects vs. modules vs. services +- The build → test → deploy sequence +- How inter-service communication works +- An overview of the providers system +- Hot reload +- Projects with multiple and/or remote repositories + +# Using Garden + + +## Features and usage + +- File watching, building, and deploying +- Testing +- Hot reload +- TLS +- Remote Clusters +- Multiple/remote repos + +## Configuration files + +- Introduction +- Project configs +- Module configs +- Services +- Tests + +## Providers + +- How providers work +- What's expected of providers +- Provider actions + +# Example projects + + +## Hello world + + +## Simple project + + +## TLS project + + +## Socks shop or Coolstore set-up + + +## Something heavy on serverless + + +# Guides + + +## Projects with multiple remote and local repos + + +## Configuring hot reload + + +## Setting up TLS + + +## How to "gardenify" an existing project + + +## Migration guide from Docker Compose to Garden + + +## Getting started with Kubernetes using the Garden framework + + +# Contributing to Garden + + +# Reference + + +## Glossary + +- When you get here to through the relevant places in the docs and add links to the definitions. + + +## Commands Reference + + +## Config Files Reference + + +## Provider Configurations + + +### Container + + +### Kubernetes + + +### OpenFaaS + + +### Local Kubernetes + + +### Google Cloud Functions + + +## Module Configurations + + +### Container + + +### Kubernetes + + +### OpenFaaS + + +### Local Kubernetes + + +### Google Cloud Functions + + +# FAQs + diff --git a/docs/reference/README.md b/docs/reference/README.md index aa067ae31dc..f4caf28db90 100644 --- a/docs/reference/README.md +++ b/docs/reference/README.md @@ -1,5 +1,5 @@ # Reference -* [Commands](./commands.md) -* [Config](./config.md) -* [Template strings](./template-strings.md) +* [Glossary](./glossary.md) +* [Commands Reference](./command-reference.md) +* [Config Files Reference](./config-files-reference.md) diff --git a/docs/reference/command-reference.md b/docs/reference/command-reference.md new file mode 100644 index 00000000000..e3c4fde7668 --- /dev/null +++ b/docs/reference/command-reference.md @@ -0,0 +1,716 @@ +## Garden CLI commands + +Below is a list of Garden CLI commands and usage information. + +The commands should be run in a Garden project root, and are always scoped to that project. + +Note: You can get a list of commands in the CLI by running `garden -h/--help`, +and detailed help for each command using `garden -h/--help` + +##### Global options + +The following option flags can be used with any of the CLI commands: + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--root` | `-r` | string | Override project root directory (defaults to working directory). + | `--silent` | `-s` | boolean | Suppress log output. + | `--env` | `-e` | string | The environment (and optionally namespace) to work against + | `--loglevel` | `-l` | `error` `warn` `info` `verbose` `debug` `silly` `0` `1` `2` `3` `4` `5` | Set logger level. Values can be either string or numeric and are prioritized from 0 to 5 (highest to lowest) as follows: error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5 + | `--output` | `-o` | `json` `yaml` | Output command result in specified format (note: disables progress logging). + +### garden build + +Build your modules. + +Builds all or specified modules, taking into account build dependency order. +Optionally stays running and automatically builds modules if their source (or their dependencies' sources) change. + +Examples: + + garden build # build all modules in the project + garden build my-module # only build my-module + garden build --force # force rebuild of modules + garden build --watch # watch for changes to code + +##### Usage + + garden build [module] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | Specify module(s) to build. Use comma separator to specify multiple modules. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-build. + +### garden call + +Call a service ingress endpoint. + +This command resolves the deployed ingress endpoint for the given service and path, calls the given endpoint and +outputs the result. + +Examples: + + garden call my-container + garden call my-container/some-path + +Note: Currently only supports simple GET requests for HTTP/HTTPS ingresses. + +##### Usage + + garden call + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `serviceAndPath` | Yes | The name of the service(s) to call followed by the ingress path (e.g. my-container/somepath). + +### garden create project + +Creates a new Garden project. + +The 'create project' command walks the user through setting up a new Garden project and +generates scaffolding based on user input. + +Examples: + + garden create project # creates a new Garden project in the current directory (project name defaults to + directory name) + garden create project my-project # creates a new Garden project in my-project directory + garden create project --module-dirs=path/to/modules1,path/to/modules2 + # creates a new Garden project and looks for pre-existing modules in the modules1 and modules2 directories + garden create project --name my-project + # creates a new Garden project in the current directory and names it my-project + +##### Usage + + garden create project [project-dir] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `project-dir` | No | Directory of the project. (Defaults to current directory.) + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--module-dirs` | | array:path | Relative path to modules directory. Use comma as a separator to specify multiple directories + | `--name` | | string | Assigns a custom name to the project. (Defaults to name of the current directory.) + +### garden create module + +Creates a new Garden module. + +Creates a new Garden module of the given type + +Examples: + + garden create module # creates a new module in the current directory (module name defaults to directory name) + garden create module my-module # creates a new module in my-module directory + garden create module --type=container # creates a new container module + garden create module --name=my-module # creates a new module in current directory and names it my-module + +##### Usage + + garden create module [module-dir] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module-dir` | No | Directory of the module. (Defaults to current directory.) + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--name` | | string | Assigns a custom name to the module. (Defaults to name of the current directory.) + | `--type` | | `container` `google-cloud-function` `npm-package` | Type of module. + +### garden delete secret + +Delete a secret from the environment. + +Returns with an error if the provided key could not be found by the provider. + +Examples: + + garden delete secret kubernetes somekey + garden del secret local-kubernetes some-other-key + +##### Usage + + garden delete secret + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `provider` | Yes | The name of the provider to remove the secret from. + | `key` | Yes | The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested). + +### garden delete environment + +Deletes a running environment. + +This will trigger providers to clear up any deployments in a Garden environment and reset it. +When you then run `garden init`, the environment will be reconfigured. + +This can be useful if you find the environment to be in an inconsistent state, or need/want to free up +resources. + +##### Usage + + garden delete environment + +### garden delete service + +Deletes a running service. + +Deletes (i.e. un-deploys) the specified services. Note that this command does not take into account any +services depending on the deleted service, and might therefore leave the project in an unstable state. +Running `garden deploy` will re-deploy any missing services. + +Examples: + + garden delete service my-service # deletes my-service + +##### Usage + + garden delete service + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | Yes | The name of the service(s) to delete. Use comma as separator to specify multiple services. + +### garden deploy + +Deploy service(s) to your environment. + + + Deploys all or specified services, taking into account service dependency order. + Also builds modules and dependencies if needed. + + Optionally stays running and automatically re-builds and re-deploys services if their module source + (or their dependencies' sources) change. + + Examples: + + garden deploy # deploy all modules in the project + garden deploy my-service # only deploy my-service + garden deploy --force # force re-deploy of modules, even if they're already deployed + garden deploy --watch # watch for changes to code + garden deploy --env stage # deploy your services to an environment called stage + + +##### Usage + + garden deploy [service] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | No | The name of the service(s) to deploy (skip to deploy all services). Use comma as separator to specify multiple services. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force redeploy of service(s). + | `--force-build` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-deploy. + +### garden dev + +Starts the garden development console. + + + The Garden dev console is a combination of the `build`, `deploy` and `test` commands. + It builds, deploys and tests all your modules and services, and re-builds, re-deploys and re-tests + as you modify the code. + + Examples: + + garden dev + + +##### Usage + + garden dev + +### garden exec + +Executes a command (such as an interactive shell) in a running service. + +Finds an active container for a deployed service and executes the given command within the container. +Supports interactive shells. + +_NOTE: This command may not be supported for all module types._ + +Examples: + + garden exec my-service /bin/sh # runs a shell in the my-service container + +##### Usage + + garden exec + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | Yes | The service to exec the command in. + | `command` | Yes | The command to run. + +### garden get secret + +Get a secret from the environment. + +Returns with an error if the provided key could not be found. + +Examples: + + garden get secret kubernetes somekey + garden get secret local-kubernetes some-other-key + +##### Usage + + garden get secret + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `provider` | Yes | The name of the provider to read the secret from. + | `key` | Yes | The key of the configuration variable. + +### garden get status + +Outputs the status of your environment. + + +##### Usage + + garden get status + +### garden init + +Initialize system, environment or other runtime components. + +This command needs to be run before first deploying a Garden project, and occasionally after updating Garden, +plugins or project configuration. + +Examples: + + garden init + garden init --force # runs the init flows even if status checks report that the environment is ready + +##### Usage + + garden init [options] + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force` | | boolean | Force initalization of environment, ignoring the environment status check. + +### garden link source + +Link a remote source to a local directory. + +After linking a remote source, Garden will read it from its local directory instead of +from the remote URL. Garden can only link remote sources that have been declared in the project +level garden.yml config. + +Examples: + + garden link source my-source path/to/my-source # links my-source to its local version at the given path + +##### Usage + + garden link source + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `source` | Yes | Name of the source to link as declared in the project config. + | `path` | Yes | Path to the local directory that containes the source. + +### garden link module + +Link a module to a local directory. + +After linking a remote module, Garden will read the source from the module's local directory instead of from +the remote URL. Garden can only link modules that have a remote source, +i.e. modules that specifiy a repositoryUrl in their garden.yml config file. + +Examples: + + garden link module my-module path/to/my-module # links my-module to its local version at the given path + +##### Usage + + garden link module + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | Yes | Name of the module to link. + | `path` | Yes | Path to the local directory that containes the module. + +### garden logs + +Retrieves the most recent logs for the specified service(s). + +Outputs logs for all or specified services, and optionally waits for news logs to come in. + +Examples: + + garden logs # prints latest logs from all services + garden logs my-service # prints latest logs for my-service + garden logs -t # keeps running and streams all incoming logs to the console + +##### Usage + + garden logs [service] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | No | The name of the service(s) to logs (skip to logs all services). Use comma as separator to specify multiple services. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--tail` | `-t` | boolean | Continuously stream new logs from the service(s). + +### garden publish + +Build and publish module(s) to a remote registry. + +Publishes built module artifacts for all or specified modules. +Also builds modules and dependencies if needed. + +Examples: + + garden publish # publish artifacts for all modules in the project + garden publish my-container # only publish my-container + garden publish --force-build # force re-build of modules before publishing artifacts + garden publish --allow-dirty # allow publishing dirty builds (which by default triggers error) + +##### Usage + + garden publish [module] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | The name of the module(s) to publish (skip to publish all modules). Use comma as separator to specify multiple modules. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force-build` | | boolean | Force rebuild of module(s) before publishing. + | `--allow-dirty` | | boolean | Allow publishing dirty builds (with untracked/uncommitted changes). + +### garden run module + +Run an ad-hoc instance of a module. + +This is useful for debugging or ad-hoc experimentation with modules. + +Examples: + + garden run module my-container # run an ad-hoc instance of a my-container container and attach to it + garden run module my-container /bin/sh # run an interactive shell in a new my-container container + garden run module my-container --i=false /some/script # execute a script in my-container and return the output + +##### Usage + + garden run module [command] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | Yes | The name of the module to run. + | `command` | No | The command to run in the module. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result. + | `--force-build` | | boolean | Force rebuild of module before running. + +### garden run service + +Run an ad-hoc instance of the specified service + +This can be useful for debugging or ad-hoc experimentation with services. + +Examples: + + garden run service my-service # run an ad-hoc instance of a my-service and attach to it + +##### Usage + + garden run service [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `service` | Yes | The service to run + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--force-build` | | boolean | Force rebuild of module + +### garden run test + +Run the specified module test. + +This can be useful for debugging tests, particularly integration/end-to-end tests. + +Examples: + + garden run test my-module integ # run the test named 'integ' in my-module + garden run test my-module integ --i=false # do not attach to the test run, just output results when completed + +##### Usage + + garden run test [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | Yes | The name of the module to run. + | `test` | Yes | The name of the test to run in the module. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--interactive` | | boolean | Set to false to skip interactive mode and just output the command result. + | `--force-build` | | boolean | Force rebuild of module before running. + +### garden scan + +Scans your project and outputs an overview of all modules. + + +##### Usage + + garden scan + +### garden set secret + +Set a secret value for a provider in an environment. + +These secrets are handled by each provider, and may for example be exposed as environment +variables for services or mounted as files, depending on how the provider is implemented +and configured. + +_Note: The value is currently always stored as a string._ + +Examples: + + garden set secret kubernetes somekey myvalue + garden set secret local-kubernets somekey myvalue + +##### Usage + + garden set secret + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `provider` | Yes | The name of the provider to store the secret with. + | `key` | Yes | A unique identifier for the secret. + | `value` | Yes | The value of the secret. + +### garden test + +Test all or specified modules. + + + Runs all or specified tests defined in the project. Also builds modules and dependencies, + and deploy service dependencies if needed. + + Optionally stays running and automatically re-runs tests if their module source + (or their dependencies' sources) change. + + Examples: + + garden test # run all tests in the project + garden test my-module # run all tests in the my-module module + garden test -n integ # run all tests with the name 'integ' in the project + garden test --force # force tests to be re-run, even if they're already run successfully + garden test --watch # watch for changes to code + + +##### Usage + + garden test [module] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | The name of the module(s) to deploy (skip to test all modules). Use comma as separator to specify multiple modules. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--name` | `-n` | string | Only run tests with the specfied name (e.g. unit or integ). + | `--force` | `-f` | boolean | Force re-test of module(s). + | `--force-build` | | boolean | Force rebuild of module(s). + | `--watch` | `-w` | boolean | Watch for changes in module(s) and auto-test. + +### garden unlink source + +Unlink a previously linked remote source from its local directory. + +After unlinking a remote source, Garden will go back to reading it from its remote URL instead +of its local directory. + +Examples: + + garden unlink source my-source # unlinks my-source + garden unlink source --all # unlinks all sources + +##### Usage + + garden unlink source [source] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `source` | No | Name of the source(s) to unlink. Use comma separator to specify multiple sources. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--all` | `-a` | boolean | Unlink all sources. + +### garden unlink module + +Unlink a previously linked remote module from its local directory. + +After unlinking a remote module, Garden will go back to reading the module's source from +its remote URL instead of its local directory. + +Examples: + + garden unlink module my-module # unlinks my-module + garden unlink module --all # unlink all modules + +##### Usage + + garden unlink module [module] [options] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | Name of the module(s) to unlink. Use comma separator to specify multiple modules. + +##### Options + +| Argument | Alias | Type | Description | +| -------- | ----- | ---- | ----------- | + | `--all` | `-a` | boolean | Unlink all modules. + +### garden update-remote sources + +Update remote sources. + +Update the remote sources declared in the project config. + +Examples: + + garden update-remote sources # update all remote sources in the project config + garden update-remote sources my-source # update remote source my-source + +##### Usage + + garden update-remote sources [source] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `source` | No | Name of the remote source(s) to update. Use comma separator to specify multiple sources. + +### garden update-remote modules + +Update remote modules. + +Remote modules are modules that have a repositoryUrl field +in their garden.yml config that points to a remote repository. + +Examples: + + garden update-remote modules # update all remote modules in the project + garden update-remote modules my-module # update remote module my-module + +##### Usage + + garden update-remote modules [module] + +##### Arguments + +| Argument | Required | Description | +| -------- | -------- | ----------- | + | `module` | No | Name of the remote module(s) to update. Use comma separator to specify multiple modules. + +### garden update-remote all + +Update all remote sources and modules. + +Examples: + + garden update-remote all # update all remote sources and modules in the project + +##### Usage + + garden update-remote all + +### garden validate + +Check your garden configuration for errors. + +Throws an error and exits with code 1 if something's not right in your garden.yml files. + +##### Usage + + garden validate diff --git a/docs/reference/config-files-reference.md b/docs/reference/config-files-reference.md new file mode 100644 index 00000000000..d8404f87066 --- /dev/null +++ b/docs/reference/config-files-reference.md @@ -0,0 +1,645 @@ +## garden.yml reference + +Below is the full schema for the `garden.yml` configuration files. For an introduction, +please look at our [configuration guide](../guides/configuration.md). + +Note that individual module types, e.g. `container`, add additional configuration keys. The built-in module types +are listed in the [Built-in module types](#built-in-module-types) section. Please refer to those for more details +on module configuration. + +```yaml + +# The schema version of the config file (currently not used). +# +# Required. +# Allowed values: "0" +version: 0 + +# Configure a module whose sources are located in this directory. +# +# Optional. +module: + # The type of this module. + # + # Example: "container" + # + # Required. + type: + + # The name of this module. + # + # Example: "my-sweet-module" + # + # Required. + name: + + description: + + # A remote repository URL to fetch the module from. Garden will read the garden.yml config from + # the local module. Currently only supports git servers. + # + # Example: "# or + # git+https://github.com/organization/some-module.git#v2.0" + # + # Optional. + repositoryUrl: + + # Variables that this module can reference and expose as environment variables. + # + # Example: + # my-variable: some-value + # + # Optional. + variables: + {} + + # Set to false to disable pushing this module to remote registries. + # + # Optional. + allowPush: true + + # Specify how to build the module. Note that plugins may specify additional keys on this object. + # + # Optional. + build: + # The command to run inside the module directory to perform the build. + # + # Example: + # - npm + # - run + # - build + # + # Optional. + command: + - + + # A list of modules that must be built before this module is built. + # + # Example: + # - name: some-other-module-name + # + # Optional. + dependencies: + - # Module name to build ahead of this module + # + # Required. + name: + + # Specify one or more files or directories to copy from the built dependency to this + # module. + # + # Optional. + copy: + - # POSIX-style path or filename of the directory or file(s) to copy to the target. + # + # Required. + source: + + # POSIX-style path or filename to copy the directory or file(s) to (defaults to same + # as source path). + # + # Optional. + target: + +# The configuration for a Garden project. This should be specified in the garden.yml file in your +# project root. +# +# Optional. +project: + # The name of the project. + # + # Example: "my-sweet-project" + # + # Required. + name: + + # The default environment to use when calling commands without the `--env` parameter. + # + # Optional. + defaultEnvironment: + + # Default environment settings, that are inherited (but can be overridden) by each configured + # environment + # + # Example: + # providers: [] + # variables: {} + # + # Optional. + environmentDefaults: + # Specify the provider that should store configuration variables for this environment. Use + # this when you configure multiple providers that can manage configuration. + # + # Optional. + configurationHandler: + + # A list of providers that should be used for this environment, and their configuration. + # Please refer to individual plugins/providers for details on how to configure them. + # + # Optional. + providers: + - # The name of the provider plugin to configure. + # + # Example: "local-kubernetes" + # + # Required. + name: + + # A key/value map of variables that modules can reference when using this environment. + # + # Optional. + variables: + {} + + # A list of environments to configure for the project. + # + # Example: + # - name: local + # providers: + # - name: local-kubernetes + # variables: {} + # + # Optional. + environments: + - # Specify the provider that should store configuration variables for this environment. Use + # this when you configure multiple providers that can manage configuration. + # + # Optional. + configurationHandler: + + # A list of providers that should be used for this environment, and their configuration. + # Please refer to individual plugins/providers for details on how to configure them. + # + # Optional. + providers: + - # The name of the provider plugin to configure. + # + # Example: "local-kubernetes" + # + # Required. + name: + + # A key/value map of variables that modules can reference when using this environment. + # + # Optional. + variables: + {} + + # Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must + # start with a letter, and cannot end with a dash) and additionally cannot contain + # consecutive dashes or be longer than 63 characters. + # + # Required. + name: + + # A list of remote sources to import into project + # + # Optional. + sources: + - # The name of the source to import + # + # Required. + name: + + # A remote respository URL. Currently only supports git servers. Use hash notation (#) to + # point to a specific branch or tag + # + # Example: "# or + # git+https://github.com/organization/some-module.git#v2.0" + # + # Required. + repositoryUrl: +``` + +## Built-in module types + +### generic + +```yaml + +# The module specification for a generic module. +# +# Required. +module: + # The type of this module. + # + # Example: "container" + # + # Required. + type: + + # The name of this module. + # + # Example: "my-sweet-module" + # + # Required. + name: + + description: + + # A remote repository URL to fetch the module from. Garden will read the garden.yml config from + # the local module. Currently only supports git servers. + # + # Example: "# or + # git+https://github.com/organization/some-module.git#v2.0" + # + # Optional. + repositoryUrl: + + # Variables that this module can reference and expose as environment variables. + # + # Example: + # my-variable: some-value + # + # Optional. + variables: + {} + + # Set to false to disable pushing this module to remote registries. + # + # Optional. + allowPush: true + + # Specify how to build the module. Note that plugins may specify additional keys on this object. + # + # Optional. + build: + # The command to run inside the module directory to perform the build. + # + # Example: + # - npm + # - run + # - build + # + # Optional. + command: + - + + # A list of modules that must be built before this module is built. + # + # Example: + # - name: some-other-module-name + # + # Optional. + dependencies: + - # Module name to build ahead of this module + # + # Required. + name: + + # Specify one or more files or directories to copy from the built dependency to this + # module. + # + # Optional. + copy: + - # POSIX-style path or filename of the directory or file(s) to copy to the target. + # + # Required. + source: + + # POSIX-style path or filename to copy the directory or file(s) to (defaults to same + # as source path). + # + # Optional. + target: + + # Key/value map of environment variables. Keys must be valid POSIX environment variable names + # (must be uppercase, may not start with `GARDEN`) and values must be primitives. + # + # Optional. + env: + {} + + # A list of tests to run in the module. + # + # Optional. + tests: + # The test specification of a generic module. + # + # Optional. + - # The name of the test. + # + # Required. + name: + + # The names of services that must be running before the test is run. + # + # Optional. + dependencies: + - + + # Maximum duration (in seconds) of the test run. + # + # Optional. + timeout: null + + # The command to run in the module build context in order to test it. + # + # Optional. + command: + - + + # Key/value map of environment variables. Keys must be valid POSIX environment variable + # names (must be uppercase, may not start with `GARDEN`) and values must be primitives. + # + # Optional. + env: + {} +``` + +### container + +```yaml + +# Configuration for a container module. +# +# Required. +module: + # The type of this module. + # + # Example: "container" + # + # Required. + type: + + # The name of this module. + # + # Example: "my-sweet-module" + # + # Required. + name: + + description: + + # A remote repository URL to fetch the module from. Garden will read the garden.yml config from + # the local module. Currently only supports git servers. + # + # Example: "# or + # git+https://github.com/organization/some-module.git#v2.0" + # + # Optional. + repositoryUrl: + + # Variables that this module can reference and expose as environment variables. + # + # Example: + # my-variable: some-value + # + # Optional. + variables: + {} + + # Set to false to disable pushing this module to remote registries. + # + # Optional. + allowPush: true + + # Specify how to build the module. Note that plugins may specify additional keys on this object. + # + # Optional. + build: + # The command to run inside the module directory to perform the build. + # + # Example: + # - npm + # - run + # - build + # + # Optional. + command: + - + + # A list of modules that must be built before this module is built. + # + # Example: + # - name: some-other-module-name + # + # Optional. + dependencies: + - # Module name to build ahead of this module + # + # Required. + name: + + # Specify one or more files or directories to copy from the built dependency to this + # module. + # + # Optional. + copy: + - # POSIX-style path or filename of the directory or file(s) to copy to the target. + # + # Required. + source: + + # POSIX-style path or filename to copy the directory or file(s) to (defaults to same + # as source path). + # + # Optional. + target: + + # Specify build arguments when building the container image. + # + # Optional. + buildArgs: + {} + + # Specify the image name for the container. Should be a valid docker image identifier. If + # specified and the module does not contain a Dockerfile, this image will be used to deploy the + # container services. If specified and the module does contain a Dockerfile, this identifier is + # used when pushing the built image. + # + # Optional. + image: + + # List of services to deploy from this container module. + # + # Optional. + services: + # The required attributes of a service. This is generally further defined by plugins. + # + # Optional. + - # Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must + # start with a letter, and cannot end with a dash) and additionally cannot contain + # consecutive dashes or be longer than 63 characters. + # + # Required. + name: + + # The names of services that this service depends on at runtime. + # + # Optional. + dependencies: + # Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, + # must start with a letter, and cannot end with a dash) and additionally cannot contain + # consecutive dashes or be longer than 63 characters. + # + # Optional. + - + + # Key/value map, keys must be valid identifiers. + # + # Optional. + outputs: + {} + + # The arguments to run the container with when starting the service. + # + # Optional. + command: + - + + # Whether to run the service as a daemon (to ensure only one runs per node). + # + # Optional. + daemon: false + + # List of endpoints that the service exposes. + # + # Example: + # - path: /api + # port: http + # + # Optional. + endpoints: + - # The hostname that should route to this service. Defaults to the default hostname + # configured + # in the provider configuration. + # + # Note that if you're developing locally you may need to add this hostname to your hosts + # file. + # + # Optional. + hostname: + + # The path which should be routed to the service. + # + # Optional. + path: / + + # The name of the container port where the specified paths should be routed. + # + # Required. + port: + + # Key/value map of environment variables. Keys must be valid POSIX environment variable + # names (must be uppercase, may not start with `GARDEN`) and values must be primitives. + # + # Optional. + env: + {} + + # Specify how the service's health should be checked after deploying. + # + # Optional. + healthCheck: + # Set this to check the service's health by making an HTTP request + # + # Optional. + httpGet: + # The path of the service's health check endpoint. + # + # Required. + path: + + # The name of the port where the service's health check endpoint should be available. + # + # Required. + port: + + scheme: HTTP + + # Set this to check the service's health by running a command in its container. + # + # Optional. + command: + - + + # Set this to check the service's health by checking if this TCP port is accepting + # connections. + # + # Optional. + tcpPort: + + # List of ports that the service container exposes. + # + # Optional. + ports: + # + # Required. + - # The name of the port (used when referencing the port elsewhere in the service + # configuration. + # + # Required. + name: + + # The protocol of the service container port. + # + # Optional. + protocol: TCP + + # The port number on the service container. + # + # Required. + containerPort: + + hostPort: + + # Set this to expose the service on the specified port on the host node (may not be + # supported by all providers). + # + # Optional. + nodePort: + + # List of volumes that should be mounted when deploying the container. + # + # Optional. + volumes: + - # The name of the allocated volume. + # + # Required. + name: + + # The path where the volume should be mounted in the container. + # + # Required. + containerPath: + + hostPath: + + # A list of tests to run in the module. + # + # Optional. + tests: + # The test specification of a generic module. + # + # Optional. + - # The name of the test. + # + # Required. + name: + + # The names of services that must be running before the test is run. + # + # Optional. + dependencies: + - + + # Maximum duration (in seconds) of the test run. + # + # Optional. + timeout: null + + # The command to run in the module build context in order to test it. + # + # Optional. + command: + - + + # Key/value map of environment variables. Keys must be valid POSIX environment variable + # names (must be uppercase, may not start with `GARDEN`) and values must be primitives. + # + # Optional. + env: + {} +``` + diff --git a/docs/reference/glossary.md b/docs/reference/glossary.md new file mode 100644 index 00000000000..bf9998f6593 --- /dev/null +++ b/docs/reference/glossary.md @@ -0,0 +1,46 @@ +# Glossary + +#### Environment +Represents the current configuration and status of any running services in the [project](#project), which may be +inspected and modified via the Garden CLI's `environment` command. + +Several named environment configurations may be defined (e.g. _dev_, _testing_, ...) in the [project's +`garden.yml`](../guides/configuration.md#project-configuration). + +#### Module +The basic unit of configuration in Garden. A module is defined by its +[`garden.yml` configuration file](../guides/configuration.md#module-configuration), located in the module's top-level +directory, +which +is a subdirectory of the [project](#project) repository's top-level directory. + +Each module has a [plugin](#plugin) type, and may define one or more [services](#service). + +Essentially, a project is organized into modules at the granularity of its *build* steps. A module's build step may +depend on one or more other modules, as specified in its `garden.yml`, in which case those modules will be built +first, and their build output made available to the requiring module's build step. + +#### Provider +A [module's](#module) plugin type defines its behavior when it is built, deployed, run and tested. Currently, +`container` is the only stable plugin type, but plugin types for serverless functions and for build-only use cases +(such as NPM modules) are under development. + +#### Project +The top-level unit of organization in Garden. A project consists of one or more [modules](#module), along with a +project-level [`garden.yml` configuration file](../guides/configuration.md#project-configuration). + +Garden CLI commands are run in the context of a project, and are aware of all its modules and services. + +Currently, Garden projects assume that all their modules are rooted in subdirectories of the same Git repository, with +the project-level `garden.yml` located in the repository's top-level directory. In a future release, this mono-repo +structure will be made optional. + +#### Provider +An implementation of a [plugin type](#plugin) (e.g. `local-kubernetes` for the `container` plugin). + +#### Service +The unit of deployment in Garden. Services are defined in their parent [module](#module)'s `garden.yml`, each +exposing [one or more endpoints](../guides/configuration.md#services). + +Services may depend on services defined in other modules, in which case those services will be deployed first, and +their deployment output made available to the requiring service's deploy step. diff --git a/docs/reference/module-configs/README.md b/docs/reference/module-configs/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/module-configs/container.md b/docs/reference/module-configs/container.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/module-configs/google-cloud-functions.md b/docs/reference/module-configs/google-cloud-functions.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/module-configs/openfaas.md b/docs/reference/module-configs/openfaas.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/README.md b/docs/reference/provider-configs/README.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/container.md b/docs/reference/provider-configs/container.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/google-cloud-functions.md b/docs/reference/provider-configs/google-cloud-functions.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/kubernetes.md b/docs/reference/provider-configs/kubernetes.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/local-kubernetes.md b/docs/reference/provider-configs/local-kubernetes.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/reference/provider-configs/openfaas.md b/docs/reference/provider-configs/openfaas.md new file mode 100644 index 00000000000..e69de29bb2d diff --git a/docs/schematic.jpg b/docs/schematic.jpg new file mode 100644 index 00000000000..6225628018d Binary files /dev/null and b/docs/schematic.jpg differ diff --git a/docs/toc.md b/docs/toc.md new file mode 100644 index 00000000000..05d69eecb28 --- /dev/null +++ b/docs/toc.md @@ -0,0 +1,22 @@ +# Table of Contents + +* [Table of Contents](./toc.md) +* [Basics](./basics/README.md) + * [Installation](./basics/installation.md) + * [Quick Start](./basics/quick-start.md) + * [Concepts](./basics/concepts.md) +* [Using Garden](./using-garden/README.md) + * [Features and usage](./using-garden/features-and-usage.md) + * [Configuration files](./using-garden/configuration-files.md) + * [Remote Clusters](./using-garden/remote-clusters.md) + * [Hot Reload](./using-garden/hot-reload.md) +* [Example projects](./examples/README.md) + * [Hello world](./examples/hello-world.md) + * [Simple project](./examples/simple-project.md) + * [TLS project](./examples/tls-project.md) + * [Remote sources project](./examples/remote-sources.md) +* [Reference](./reference/README.md) + * [Glossary](./reference/glossary.md) + * [Commands Reference](./reference/command-reference.md) + * [Config Files Reference](./reference/config-files-reference.md) +* [FAQs](./faqs.md) \ No newline at end of file diff --git a/docs/using-garden/README.md b/docs/using-garden/README.md new file mode 100644 index 00000000000..60640b4acab --- /dev/null +++ b/docs/using-garden/README.md @@ -0,0 +1,17 @@ +# Using Garden + +## [Features and usage](./features-and-usage.md) + +In this article we discuss how to start a new project with `garden create`, the basic development workflow, how Garden's providers work, and the basics of testing and dependencies. + +## [Configuration files](./configuration-files.md) + +This one is all about Garden's configuration files. The difference between project and module configs, some significant specific fields, setting up services, and a primer on tests. + +## [Remote Clusters](./remote-clusters.md) + +Most of the time we want to develop locally, with our project running in Minikube or Docker. If you'd like to use a remote cluster though, check out this guide. + +## [Hot Reload](./hot-reload.md) + +This article discusses how to use hot reload, so that you can update files on the fly, without losing state and without having to destroy and re-create your container. \ No newline at end of file diff --git a/docs/using-garden/configuration-files.md b/docs/using-garden/configuration-files.md new file mode 100644 index 00000000000..ad97f197e1a --- /dev/null +++ b/docs/using-garden/configuration-files.md @@ -0,0 +1,201 @@ +# Configuration + +Garden is configured via `garden.yml` configuration files. + +The [project-wide](#project-configuration) `garden.yml` file should be located in the top-level directory of the +project's Git repository. + +In addition, each of the project's [modules](../reference/glossary.md#module)' `garden.yml` should be located in that +module's top-level directory. + +To get started, create a `garden.yml` file in the top-level directory of your repository, and a `garden.yml` file +in the top-level directory of each of the modules you'd like to define for your project. + +To decide how to split your project up into modules, it's useful to consider what parts of it are built as a single +step, and what the dependency relationships are between your build steps. For example, each container and each +serverless function should be represented by its own module. + +Below, we'll be using examples from the +[Hello world](../examples/hello-world.md) example project, which touches +on many of the things you're likely to want to configure in a project. + +## Project Configuration + +We'll start by looking at the top-level [project configuration file](https://github.com/garden-io/garden/blob/master/examples/hello-world/garden.yml). + +```yaml +# examples/hello-world/garden.yml +project: + name: hello-world + environmentDefaults: + variables: + my-variable: hello-variable + environments: + - name: local + providers: + - name: local-kubernetes + - name: openfaas +``` + +The project-wide `garden.yml` defines the project's name, the default configuration used for each +[environment](../reference/glossary.md#environment) (via the `environmentDefaults` directive), and +environment-specific provider configuration. The above only configures a `local` environment, but you could add +further environments, such as a remote Kubernetes environment. + +Here, project-wide configuration variables can also be specified (global, and/or environment-specific). These are +then available for substitution in any string value in any module's `garden.yml`. + +For example, assuming the above project configuration, `"foo-${variables.my-variable}-bar"` would evaluate to +`"foo-hello-variable-bar"` when used as a string value in a module's `garden.yml`. + +## Module Configuration + +Below, we'll use the module configurations of `hello-function` and `hello-container` from the +[Hello world](../examples/hello-world.md) example project +as examples to illustrate some of the primary module-level configuration options. + +The following is a snippet from `hello-container`'s module config: + +```yaml +module: + name: hello-container + type: container + description: Hello world container service + ... + build: + dependencies: + - name: hello-npm-package + copy: + - source: "./" + target: libraries/hello-npm-package/ +``` + +The first lines you'll find in all module configurations, and describe the module at a high level. + +The second part, the `build` key, demonstrates how Garden can serve as a build framework, managing build dependencies +and even copying files between modules as they are built. + +Below is a run-down of the individual configuration keys, and what they represent: + +### name + +The module's name, used e.g. when referring to it from another module's configuration as a +build dependency, or when building specific modules with `garden build`. + +Note that module names must be unique within a given project. An error will be thrown in any Garden CLI command if two +modules use the same name. + +### type + +A [module](../reference/glossary.md#module)'s `type` specifies what kind of module this is, which will control how the +module's code gets built, tested, deployed, etc. The module types are defined by _providers_. The built-in providers +include `container` and `generic` (which basically provides a way to run commands locally). + +The example above is a `container` module, and the `hello-function` module is an `openfaas` module +(which is one of many ways to run functions-as-a-service on Kubernetes). + +In this particular project, the `container` module type is deployed by the `local-kubernetes` provider, and the +`openfaas` module is built and deployed by the corresponding `openfaas` provider. + +### build + +A module's build configuration is specified via the `build` directive, and the implementation of what `build` does varies depending on which provider is responsible for that module. + +Regardless of the implementation, a module's build command is executed +with its working directory set to a copy of the module's top-level directory, located at +`[project-root]/.garden/build/[module-name]`. This internal directory is referred to as the module's +[build directory](../reference/glossary.md#build-directory). + +The `.garden` directory should not be modified by users, since this may lead to unexpected errors when the Garden CLI +tools are used in the project. + +The `build.dependencies` subdirective lists the module's build dependencies, which need to be built ahead of this module. +`name` is the required module's name. In many cases you only need to declare the build dependency name. For example, +you simply need to build one container before another because it's used as a base image. + +In other cases, you may actually need files to be copied from one built module to another. +The `copy` key indicates what files/folders, if any, should be copied from the required module's build directory to the +module in question after the required module is built (`source`), and where they should be copied to (`target`). + +In the above example, we copy the entire contents of `hello-npm-package`'s build directory, after it has been built, +into the `libraries/hello-npm-package/` in the `hello-container` build directory, _before the container is built_. + +## Services + +A module may contain zero or more _services_. Services are deployed when running `garden deploy` or `garden dev` as +part of your runtime stack. + +How services are configured will depend on the module type. An `openfaas` module always contains a single service. A +`container` module can contain any number of services (or none at all, if it's just used as a base image, for example). + +The following is a snippet from `hello-container`'s module config: + +```yaml +module: + description: Hello world container service + type: container + services: + - name: hello-container + command: [npm, start] + ports: + - name: http + containerPort: 8080 + endpoints: + - path: /hello + port: http + healthCheck: + httpGet: + path: /_ah/health + port: http + dependencies: + - hello-function + ... +``` + +Here the `services` directive defines the services exposed by the module. We only have one service in this example, +but you may add another service, for example a background worker, that is started using a different +`command`. + +For more details on how to configure services in a `container` module, please refer to the +[Config Files Reference](../reference/config-files-reference.md). + +## Tests + +Each module can define one or more test suites. How these tests are specified, much like services, depends on the +individual module type. However the concepts are most often the same; you specify one or more test suites, how to +execute them, and in some cases which services need to be running for the tests to run successfully. + +For an example, here is another snippet from the `hello-container` module configuration: + +```yaml +module: + description: Hello world container service + type: container + ... + tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - hello-function +``` + +Here we define two types of tests. First are unit tests, which can be run on their own without any dependencies. The +framework only needs to know which command to run, and the rest is handled by the module's code itself. + +The other test suite, `integ`, leverages the Garden framework's ability to manage runtime dependencies for tests. In +this case, the integ test suite needs the `hello-function` service to be running for the tests to execute. + +This allows you write tests that actually call out to other services, rather than having to mock or stub those services +in your tests. + +Tests can be run via `garden test`, as well as `garden dev`. + +## Next steps + +We highly recommend browsing through the [Example projects](../examples/README.md) to see different examples of how projects and modules can be configured. + +Also be sure to look at the [Config Files Reference](../reference/config-files-reference.md) + for more details on each of the available +configuration keys. diff --git a/docs/using-garden/features-and-usage.md b/docs/using-garden/features-and-usage.md new file mode 100644 index 00000000000..23fe1a6b95e --- /dev/null +++ b/docs/using-garden/features-and-usage.md @@ -0,0 +1,109 @@ +# Features and Usage + +Now that you've had a glimpse at the basic Garden commands on the [Quick Start](./basics/quick-start.md) guide, and a brief look at the main [Concepts](../basics/concepts.md) we'll be dealing with, let's go through what the typical usage of Garden looks like. + +## Starting a new project + +For starting a new project with Garden there are two options: + +- You can create all the configuration files by hand, and for that you should take a look at our [Configuration files](./configuration-files.md) document. +- Or you can use the `garden create` command—a lot easier. + +### `garden create` + +The `garden create` command can be used to create either whole projects, or just modules. Essentially what it does is help you create configuration files so you don't have to do it by hand. + +The command `garden create project` will create a new project in the current directory and prompt you to add modules to it, which should each have a name and a type. It will then create the appropriate folders and the configuration files within them. + +If this is a pre-existing project and you want to "gardenify" code that's already there, you can try, for example, `garden create project --module-dirs=./services`. This will prompt you to create configuration files for every subfolder within the `./services` directory. + +To add individual modules later on you can use `garden create module`. + +``` +➜ test-project g create project + +Initializing new Garden project test-project +--------- +? Would you like to add a module to your project? Yes +? Enter module name my-module +? Module type container +? Add another module? (current modules: my-module) Yes +? Enter module name my-module-2 +? Module type container +? Add another module? (current modules: my-module, my-module-2) No +--------- +✔ Setting up project +✔ Writing config for my-module +✔ Writing config for my-module-2 +✔ Writing config for test-project +Project created! Be sure to check out our docs for how to get sarted! +``` + +For a practical example of "gardenifying" an existing project, check out the [Simple project](../examples/simple-project.md) example. + +## The development workflow + +Most of the time, the development workflow when using Garden after the configuration files are set is extremely simple: you leave `garden dev` running, and Garden will automatically re-build, re-deploy, and re-test your project as you work on it. + +Sometimes though you might prefer to skip the testing step, in which case you can simply use `garden deploy --watch`. This will watch for changes, then build and deploy them, but it'll skip testing. + +Another important topic to keep in mind is [inter-service communication](../basics/concepts.md#how-inter-service-communication-works). As previously discussed, your project has multiple services, and they need to talk to each other at some point. That's pretty simple: a service's hostname is simply its name. So a the hostname for a service called `my-service` is simply `http://my-service/`. + +For example, the following snippet calls a separate service in the project called `go-service`. + +```js +request.get('http://go-service/hello-go').then(message => {res.json({message})}) +``` + +Lastly, when things go wrong you should refer to the error logs. That's an `error.log` file in the project root, and the service logs that you can retrieve from the individual pods in your cluster. + +For the latter, you can use the `garden logs` command, followed by the name of the service you'd like to query. For example `garden logs go-service` would fetch the logs for the `go-service` service, while `garden logs go-service,node-service` would fetch the logs for both the `go-service` and the `node-service` services. + +The `garden logs` command is functionally equivalent to `kubectl logs`, but simpler to execute. + +## Providers + +Whenever "a module's type" is mentioned in the documentation, what's meant is "which provider will handle this module?" Providers, as [previously discussed](../basics/concepts.md), are responsible for implementing different behaviors for say containers and serverless functions, and they need to be specified in a module's configuration files. + +For a comprehensive list of providers available in Garden, check out the [References](../reference/README.md) + + +## Testing and dependencies + +Both tests and dependencies are specified in the Garden configuration files. + +Dependencies are a field within the services declaration. Here's a snippet, from our [TLS project](../examples/tls-project.md) example: + +```yaml +module: + name: node-service + description: Node service container + type: container + services: + - name: node-service + ... + dependencies: + - go-service +``` + +Tests should be specified the same way, and in the case of integration tests their dependencies should be present as well. Another snippet from the same file: + +```yaml +tests: + - name: unit + command: [npm, test] + - name: integ + command: [npm, run, integ] + dependencies: + - go-service +``` + +Above we're using `npm test` and `npm run integ` for our tests, but they can be anything you'd like. The only constraint is that Garden follows the typical Unix exit codes convention: `0` means success, and any non-zero exit codes represent failures. + +## Advanced features + +For Garden's more advanced features, see the following docs: + +- [Hot Reload](./hot-reload.md), for how to update the files in a container without having to restart it and lose state. +- [TLS project](../examples/tls-project.md), for—drumroll!—how to set up TLS with Garden. +- [Remote sources project](../examples/remote-sources.md), for how to integrate multiple remote and local repositories within the same project. diff --git a/docs/using-garden/hot-reload.md b/docs/using-garden/hot-reload.md new file mode 100644 index 00000000000..4716a2a3330 --- /dev/null +++ b/docs/using-garden/hot-reload.md @@ -0,0 +1,49 @@ +# Hot Reload + +When the `local-kubernetes` provider is used, `container` modules can be configured to hot-reload their running services when the module's sources change (i.e. without redeploying). In essence, hot-reloading copies source files into the appropriate running containers when code is changed by the user. + +For example, services that can be run with a file system watcher that automatically update the running application process when sources change (e.g. nodemon, Django, Ruby on Rails, and many other web app frameworks) are a natural fit for this feature. + +# Usage + +Currently, modules configured for hot reloading are only deployed with hot reloading enabled when they're deployed via `garden deploy -w` or `garden dev`; and not, for example, when deployed via `garden deploy` without the `-w` flag. + +Subsequently deploying a service belonging to a module configured for hot reloading via `garden deploy` (without the watch flag) results in the service being redeployed in standard configuration. (See [this link](https://github.com/garden-io/garden/pull/291) for a more technical discussion.) + +Since hot reloading is triggered via Garden's file system watcher, hot reloading only occurs while a `garden deploy -w`, `garden build -w`, or `garden dev` command is running. + +# Quick example + +Following is a simple example of a module configured for hot reloading: + +```yaml +module: + description: My Test Service + name: test-service + type: container + hotReload: + sync: + - target: /app/ + services: + - name: test-service + command: [npm, start] # runs `node main.js` + hotReloadCommand: [npm, run, dev] # runs `nodemon main.js` +``` + +In the above, the `hotReload` field specifies the destination path inside the running container that the module's (top-level) directory (where its `garden.yml` resides) is synced to. + +Note that only files tracked in version control are synced, e.g. respecting `.gitignore`. + +If a `source` is specified along with `target`, that subpath in the module's directory is synced to the target instead of the default of syncing the module's top-level directory. + +You can configure several such `source`/`target` pairs, but note that the `source` path must be disjoint, i.e. a `source` path may not be a subdirectory of another `source` path within the same module. Here's an example: + +```yaml + sync: + - source: /foo + target: /app/foo + - source: /bar + target: /app/bar +``` + +Lastly, `hotReloadCommand` determines which command should be ran inside the container (when deployed with hot reloading enabled). If no `hotReloadCommand` is specified, `command` is also used in hot reload mode. diff --git a/docs/using-garden/remote-clusters.md b/docs/using-garden/remote-clusters.md new file mode 100644 index 00000000000..9f5740a1d7a --- /dev/null +++ b/docs/using-garden/remote-clusters.md @@ -0,0 +1,130 @@ +# Using Garden with a remote Kubernetes cluster + +Below are some notes on steps you need to take before deploying Garden projects to a remote Kubernetes cluster. + +Many of the steps are not specific to Garden as such, so you may have already performed some of these steps +and/or may need to follow the provided links in each section for details on how to perform the steps you have +not yet completed. + +## Setup + +### Connecting to the cluster + +Start by making sure you have a [kubectl context](https://kubernetes.io/docs/tasks/access-application-cluster/configure-access-multiple-clusters/) +set up on your development machine to access your cluster. How you set this up will vary by how and where you +have deployed your cluster. + +Then configure the project and provider in your project `garden.yml`, along with the kubectl context you use to +connect to your cluster. + +Example: + +```yaml +project: + name: my-project + environments: + - name: dev + providers: + - name: kubernetes + context: my-dev-context # the name of the kubectl context for the cluster + ... + defaultEnvironment: dev +``` + +### Ingress, TLS and DNS + +The cluster needs to have a configured [nginx ingress controller](https://github.com/kubernetes/ingress-nginx). + +You'll also need to point one or more DNS entries to your cluster, and configure a TLS certificate for the hostnames +you will expose for ingress. +_How you configure DNS and prepare the certificates will depend on how you manage DNS and certificates in general, +so we won't cover that in detail here._ + +Once you have the certificates on hand (the `.crt` and `.key` files), create a +[Secret](https://kubernetes.io/docs/concepts/configuration/secret/) for each cert in the cluster so that +they can be referenced when deploying services: + +```sh +kubectl create secret tls mydomain-tls-secret --key --cert +``` + +Then configure each certificate/secret in your `garden.yml` provider configuration: + +```yaml +project: + name: my-project + environments: + - name: dev + providers: + - name: kubernetes + context: my-dev-context + tlsCertificates: + - name: main + # Optionally set particular hostnames to use this certificate for + # (useful if you have multiple certs for the same hostname). + hostnames: [mydomain.com] + secretRef: + # Change to whatever name you chose for the secret above. + name: my-tls-secret + # Change this if you store the secret in another namespace. + namespace: default + - name: wildcard + secretRef: + name: wildcard-tls-secret + namespace: default + ... + defaultEnvironment: dev +``` + +### Configuring a container registry + +When you deploy to the environment (via `garden deploy` or `garden dev`), containers are first built and then pushed +to the configured _deployment registry_, where the K8s cluster will then pull the built images when deploying. +This should generally be a _private_ container registry, or at least a private project in a public registry. + +Similarly to the above TLS configuration, you may also need to set up auth for the registry using K8s Secrets, in this +case via the `kubectl create secret docker-registry` helper. + +_Note that you do not need to configure the authentication and imagePullSecrets when using GKE along with GCR, +as long as your deployment registry is in the same project as the GKE cluster._ + +The lovely folks at [Heptio](https://heptio.com) have prepared good guides on how to configure private registries +for Kubernetes, which you can find [here](http://docs.heptio.com/content/private-registries.html). + +Once you've created the auth secret in the cluster, you can configure the registry and the secrets in your +`garden.yml` project config like this: + +```yaml +project: + name: my-project + environments: + - name: dev + providers: + - name: kubernetes + context: my-dev-context + ... + deploymentRegistry: + # The hostname of the registry, e.g. gcr.io for GCR (Google Container Registry) + hostname: my.registry.io + # Namespace (aka project ID) to use in the registry for this project. + # For GKE/GCR, use the project ID where your cluster is. + namespace: my-project-id + imagePullSecrets: + # The name of the secret you stored using `kubectl create secret docker-registry` + - name: my-registry-secret + # Change this if you store the secret in another namespace. + namespace: default + defaultEnvironment: dev +``` + +You also need to login to the `docker` CLI, so that images can be pushed to the registry. Please refer +to your registry's documentation on how to do that (for Docker Hub you simply run `docker login`). + +### Permissions + +Note that you need to have permissions to create namespaces and to create deployments, +daemonsets, services and ingresses within the namespaces created. + +The plugin will create two or more namespaces per user and project, one to run services, another to manage +metadata and configuration (this is so that your environment can be reset without +clearing your configuration variables), and potentially more to support specific plugins/providers. \ No newline at end of file diff --git a/garden-cli/garden-cli b/garden-cli/garden-cli new file mode 100755 index 00000000000..f90024a76a5 Binary files /dev/null and b/garden-cli/garden-cli differ diff --git a/garden-service/build/actions.d.ts b/garden-service/build/actions.d.ts new file mode 100644 index 00000000000..e2091961f8a --- /dev/null +++ b/garden-service/build/actions.d.ts @@ -0,0 +1,81 @@ +import { Garden } from "./garden"; +import { PrimitiveMap } from "./config/common"; +import { Module } from "./types/module"; +import { BuildResult, BuildStatus, DeleteSecretResult, EnvironmentStatusMap, ExecInServiceResult, GetSecretResult, GetServiceLogsResult, PushResult, RunResult, SetSecretResult, TestResult, PublishResult } from "./types/plugin/outputs"; +import { BuildModuleParams, DeleteSecretParams, DeployServiceParams, DeleteServiceParams, ExecInServiceParams, GetSecretParams, GetBuildStatusParams, GetServiceLogsParams, GetServiceOutputsParams, GetServiceStatusParams, GetTestResultParams, ModuleActionParams, PluginActionContextParams, PluginActionParams, PluginActionParamsBase, PluginServiceActionParamsBase, PushModuleParams, RunModuleParams, RunServiceParams, SetSecretParams, TestModuleParams, GetEnvironmentStatusParams, PluginModuleActionParamsBase, PublishModuleParams } from "./types/plugin/params"; +import { ServiceStatus } from "./types/service"; +import { Omit } from "./util/util"; +import { RuntimeContext } from "./types/service"; +import { ProcessResults } from "./process"; +import { LogEntry } from "./logger/log-entry"; +import { CleanupEnvironmentParams } from "./types/plugin/params"; +declare type TypeGuard = { + readonly [P in keyof (PluginActionParams | ModuleActionParams)]: (...args: any[]) => Promise; +}; +export interface ContextStatus { + providers: EnvironmentStatusMap; + services: { + [name: string]: ServiceStatus; + }; +} +export interface DeployServicesParams { + serviceNames?: string[]; + force?: boolean; + forceBuild?: boolean; +} +declare type ActionHelperParams = Omit & { + pluginName?: string; +}; +declare type ModuleActionHelperParams = Omit & { + pluginName?: string; +}; +declare type ServiceActionHelperParams = Omit & { + runtimeContext?: RuntimeContext; + pluginName?: string; +}; +declare type RequirePluginName = T & { + pluginName: string; +}; +export declare class ActionHelper implements TypeGuard { + private garden; + constructor(garden: Garden); + getEnvironmentStatus({ pluginName }: ActionHelperParams): Promise; + /** + * Checks environment status and calls prepareEnvironment for each provider that isn't flagged as ready. + * + * If any of the getEnvironmentStatus handlers returns needUserInput=true, this throws and guides the user to + * run `garden init` + */ + prepareEnvironment({ force, pluginName, logEntry, allowUserInput }: { + force?: boolean; + pluginName?: string; + logEntry?: LogEntry; + allowUserInput?: boolean; + }): Promise<{}>; + cleanupEnvironment({ pluginName }: ActionHelperParams): Promise; + getSecret(params: RequirePluginName>): Promise; + setSecret(params: RequirePluginName>): Promise; + deleteSecret(params: RequirePluginName>): Promise; + getBuildStatus(params: ModuleActionHelperParams>): Promise; + build(params: ModuleActionHelperParams>): Promise; + pushModule(params: ModuleActionHelperParams>): Promise; + publishModule(params: ModuleActionHelperParams>): Promise; + runModule(params: ModuleActionHelperParams>): Promise; + testModule(params: ModuleActionHelperParams>): Promise; + getTestResult(params: ModuleActionHelperParams>): Promise; + getServiceStatus(params: ServiceActionHelperParams): Promise; + deployService(params: ServiceActionHelperParams): Promise; + deleteService(params: ServiceActionHelperParams): Promise; + getServiceOutputs(params: ServiceActionHelperParams): Promise; + execInService(params: ServiceActionHelperParams): Promise; + getServiceLogs(params: ServiceActionHelperParams): Promise; + runService(params: ServiceActionHelperParams): Promise; + getStatus(): Promise; + deployServices({ serviceNames, force, forceBuild }: DeployServicesParams): Promise; + private commonParams; + private callActionHandler; + private callModuleHandler; + private callServiceHandler; +} +export {}; +//# sourceMappingURL=actions.d.ts.map \ No newline at end of file diff --git a/garden-service/build/actions.js b/garden-service/build/actions.js new file mode 100644 index 00000000000..fee9eae75b1 --- /dev/null +++ b/garden-service/build/actions.js @@ -0,0 +1,319 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const service_1 = require("./types/service"); +const lodash_1 = require("lodash"); +const process_1 = require("./process"); +const deploy_1 = require("./tasks/deploy"); +const plugin_context_1 = require("./plugin-context"); +const exceptions_1 = require("./exceptions"); +class ActionHelper { + constructor(garden) { + this.garden = garden; + } + //=========================================================================== + //region Environment Actions + //=========================================================================== + getEnvironmentStatus({ pluginName }) { + return __awaiter(this, void 0, void 0, function* () { + const handlers = this.garden.getActionHandlers("getEnvironmentStatus", pluginName); + return Bluebird.props(lodash_1.mapValues(handlers, h => h(Object.assign({}, this.commonParams(h))))); + }); + } + /** + * Checks environment status and calls prepareEnvironment for each provider that isn't flagged as ready. + * + * If any of the getEnvironmentStatus handlers returns needUserInput=true, this throws and guides the user to + * run `garden init` + */ + prepareEnvironment({ force = false, pluginName, logEntry, allowUserInput = false }) { + return __awaiter(this, void 0, void 0, function* () { + const handlers = this.garden.getActionHandlers("prepareEnvironment", pluginName); + const statuses = yield this.getEnvironmentStatus({ pluginName }); + const needUserInput = Object.entries(statuses) + .map(([name, status]) => (Object.assign({}, status, { name }))) + .filter(status => status.needUserInput === true); + if (!allowUserInput && needUserInput.length > 0) { + const names = needUserInput.map(s => s.name).join(", "); + const msgPrefix = needUserInput.length === 1 + ? `Plugin ${names} has been updated or hasn't been configured, and requires user input.` + : `Plugins ${names} have been updated or haven't been configured, and require user input.`; + throw new exceptions_1.ConfigurationError(`${msgPrefix}. Please run \`garden init\` and then re-run this command.`, { statuses }); + } + const output = {}; + // sequentially go through the preparation steps, to allow plugins to request user input + for (const [name, handler] of Object.entries(handlers)) { + const status = statuses[name] || { ready: false }; + if (status.ready && !force) { + continue; + } + const envLogEntry = (logEntry || this.garden.log).info({ + status: "active", + section: name, + msg: "Preparing environment...", + }); + yield handler(Object.assign({}, this.commonParams(handler), { force, status, logEntry: envLogEntry })); + envLogEntry.setSuccess("Configured"); + output[name] = true; + } + return output; + }); + } + cleanupEnvironment({ pluginName }) { + return __awaiter(this, void 0, void 0, function* () { + const handlers = this.garden.getActionHandlers("cleanupEnvironment", pluginName); + yield Bluebird.each(lodash_1.values(handlers), h => h(Object.assign({}, this.commonParams(h)))); + return this.getEnvironmentStatus({ pluginName }); + }); + } + getSecret(params) { + return __awaiter(this, void 0, void 0, function* () { + const { pluginName } = params; + return this.callActionHandler({ actionType: "getSecret", pluginName, params: lodash_1.omit(params, ["pluginName"]) }); + }); + } + setSecret(params) { + return __awaiter(this, void 0, void 0, function* () { + const { pluginName } = params; + return this.callActionHandler({ actionType: "setSecret", pluginName, params: lodash_1.omit(params, ["pluginName"]) }); + }); + } + deleteSecret(params) { + return __awaiter(this, void 0, void 0, function* () { + const { pluginName } = params; + return this.callActionHandler({ actionType: "deleteSecret", pluginName, params: lodash_1.omit(params, ["pluginName"]) }); + }); + } + //endregion + //=========================================================================== + //region Module Actions + //=========================================================================== + getBuildStatus(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ + params, + actionType: "getBuildStatus", + defaultHandler: () => __awaiter(this, void 0, void 0, function* () { return ({ ready: false }); }), + }); + }); + } + build(params) { + return __awaiter(this, void 0, void 0, function* () { + yield this.garden.buildDir.syncDependencyProducts(params.module); + return this.callModuleHandler({ params, actionType: "build" }); + }); + } + pushModule(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ params, actionType: "pushModule", defaultHandler: dummyPushHandler }); + }); + } + publishModule(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ params, actionType: "publishModule", defaultHandler: dummyPublishHandler }); + }); + } + runModule(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ params, actionType: "runModule" }); + }); + } + testModule(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ params, actionType: "testModule" }); + }); + } + getTestResult(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callModuleHandler({ + params, + actionType: "getTestResult", + defaultHandler: () => __awaiter(this, void 0, void 0, function* () { return null; }), + }); + }); + } + //endregion + //=========================================================================== + //region Service Actions + //=========================================================================== + getServiceStatus(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ params, actionType: "getServiceStatus" }); + }); + } + deployService(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ params, actionType: "deployService" }); + }); + } + deleteService(params) { + return __awaiter(this, void 0, void 0, function* () { + const logEntry = this.garden.log.info({ + section: params.service.name, + msg: "Deleting...", + status: "active", + }); + return this.callServiceHandler({ + params: Object.assign({}, params, { logEntry }), + actionType: "deleteService", + defaultHandler: dummyDeleteServiceHandler, + }); + }); + } + getServiceOutputs(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ + params, + actionType: "getServiceOutputs", + defaultHandler: () => __awaiter(this, void 0, void 0, function* () { return ({}); }), + }); + }); + } + execInService(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ params, actionType: "execInService" }); + }); + } + getServiceLogs(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ params, actionType: "getServiceLogs", defaultHandler: dummyLogStreamer }); + }); + } + runService(params) { + return __awaiter(this, void 0, void 0, function* () { + return this.callServiceHandler({ params, actionType: "runService" }); + }); + } + //endregion + //=========================================================================== + //region Helper Methods + //=========================================================================== + getStatus() { + return __awaiter(this, void 0, void 0, function* () { + const envStatus = yield this.getEnvironmentStatus({}); + const services = lodash_1.keyBy(yield this.garden.getServices(), "name"); + const serviceStatus = yield Bluebird.props(lodash_1.mapValues(services, (service) => __awaiter(this, void 0, void 0, function* () { + const dependencies = yield this.garden.getServices(service.config.dependencies); + const runtimeContext = yield service_1.prepareRuntimeContext(this.garden, service.module, dependencies); + return this.getServiceStatus({ service, runtimeContext }); + }))); + return { + providers: envStatus, + services: serviceStatus, + }; + }); + } + deployServices({ serviceNames, force = false, forceBuild = false }) { + return __awaiter(this, void 0, void 0, function* () { + const services = yield this.garden.getServices(serviceNames); + return process_1.processServices({ + services, + garden: this.garden, + watch: false, + handler: (module) => __awaiter(this, void 0, void 0, function* () { + return deploy_1.getDeployTasks({ + garden: this.garden, + module, + serviceNames, + force, + forceBuild, + includeDependants: false, + }); + }), + }); + }); + } + //endregion + // TODO: find a nicer way to do this (like a type-safe wrapper function) + commonParams(handler, logEntry) { + return { + ctx: plugin_context_1.createPluginContext(this.garden, handler["pluginName"]), + // TODO: find a better way for handlers to log during execution + logEntry, + }; + } + callActionHandler({ params, actionType, pluginName, defaultHandler }) { + return __awaiter(this, void 0, void 0, function* () { + const handler = this.garden.getActionHandler({ + actionType, + pluginName, + defaultHandler, + }); + const handlerParams = Object.assign({}, this.commonParams(handler), params); + return handler(handlerParams); + }); + } + callModuleHandler({ params, actionType, defaultHandler }) { + return __awaiter(this, void 0, void 0, function* () { + // the type system is messing me up here, not sure why I need the any cast... - j.e. + const { module, pluginName } = params; + const handler = yield this.garden.getModuleActionHandler({ + moduleType: module.type, + actionType, + pluginName, + defaultHandler, + }); + const handlerParams = Object.assign({}, this.commonParams(handler), lodash_1.omit(params, ["module"]), { module: lodash_1.omit(module, ["_ConfigType"]) }); + // TODO: figure out why this doesn't compile without the function cast + return handler(handlerParams); + }); + } + callServiceHandler({ params, actionType, defaultHandler }) { + return __awaiter(this, void 0, void 0, function* () { + const { service } = params; + const module = service.module; + const handler = yield this.garden.getModuleActionHandler({ + moduleType: module.type, + actionType, + pluginName: params.pluginName, + defaultHandler, + }); + // TODO: figure out why this doesn't compile without the casts + const deps = yield this.garden.getServices(service.config.dependencies); + const runtimeContext = (params.runtimeContext || (yield service_1.prepareRuntimeContext(this.garden, module, deps))); + const handlerParams = Object.assign({}, this.commonParams(handler), params, { module, + runtimeContext }); + return handler(handlerParams); + }); + } +} +exports.ActionHelper = ActionHelper; +const dummyLogStreamer = ({ service, logEntry }) => __awaiter(this, void 0, void 0, function* () { + logEntry && logEntry.warn({ + section: service.name, + msg: chalk_1.default.yellow(`No handler for log retrieval available for module type ${service.module.type}`), + }); + return {}; +}); +const dummyPushHandler = () => __awaiter(this, void 0, void 0, function* () { + return { pushed: false }; +}); +const dummyPublishHandler = ({ module }) => __awaiter(this, void 0, void 0, function* () { + return { + message: chalk_1.default.yellow(`No publish handler available for module type ${module.type}`), + published: false, + }; +}); +const dummyDeleteServiceHandler = ({ module, logEntry }) => __awaiter(this, void 0, void 0, function* () { + const msg = `No delete service handler available for module type ${module.type}`; + logEntry && logEntry.setError(msg); + return {}; +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFFLE9BQU8sRUFBRSxRQUFRLEVBQXdCLEVBQUUsRUFBRTtJQUM3RSxRQUFRLElBQUksUUFBUSxDQUFDLElBQUksQ0FBQztRQUN4QixPQUFPLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDckIsR0FBRyxFQUFFLGVBQUssQ0FBQyxNQUFNLENBQUMsMERBQTBELE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUM7S0FDbkcsQ0FBQyxDQUFBO0lBQ0YsT0FBTyxFQUFFLENBQUE7QUFDWCxDQUFDLENBQUEsQ0FBQTtBQUVELE1BQU0sZ0JBQWdCLEdBQUcsR0FBUyxFQUFFO0lBQ2xDLE9BQU8sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUE7QUFDMUIsQ0FBQyxDQUFBLENBQUE7QUFFRCxNQUFNLG1CQUFtQixHQUFHLENBQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFO0lBQy9DLE9BQU87UUFDTCxPQUFPLEVBQUUsZUFBSyxDQUFDLE1BQU0sQ0FBQyxnREFBZ0QsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDO1FBQ3BGLFNBQVMsRUFBRSxLQUFLO0tBQ2pCLENBQUE7QUFDSCxDQUFDLENBQUEsQ0FBQTtBQUVELE1BQU0seUJBQXlCLEdBQUcsQ0FBTyxFQUFFLE1BQU0sRUFBRSxRQUFRLEVBQXVCLEVBQUUsRUFBRTtJQUNwRixNQUFNLEdBQUcsR0FBRyx1REFBdUQsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ2hGLFFBQVEsSUFBSSxRQUFRLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQ2xDLE9BQU8sRUFBRSxDQUFBO0FBQ1gsQ0FBQyxDQUFBLENBQUEiLCJmaWxlIjoiYWN0aW9ucy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgQmx1ZWJpcmQgPSByZXF1aXJlKFwiYmx1ZWJpcmRcIilcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4vZ2FyZGVuXCJcbmltcG9ydCB7IFByaW1pdGl2ZU1hcCB9IGZyb20gXCIuL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7IE1vZHVsZUFjdGlvbnMsIFNlcnZpY2VBY3Rpb25zLCBQbHVnaW5BY3Rpb25zIH0gZnJvbSBcIi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQge1xuICBCdWlsZFJlc3VsdCxcbiAgQnVpbGRTdGF0dXMsXG4gIERlbGV0ZVNlY3JldFJlc3VsdCxcbiAgRW52aXJvbm1lbnRTdGF0dXNNYXAsXG4gIEV4ZWNJblNlcnZpY2VSZXN1bHQsXG4gIEdldFNlY3JldFJlc3VsdCxcbiAgR2V0U2VydmljZUxvZ3NSZXN1bHQsXG4gIE1vZHVsZUFjdGlvbk91dHB1dHMsXG4gIFB1c2hSZXN1bHQsXG4gIFJ1blJlc3VsdCxcbiAgU2VydmljZUFjdGlvbk91dHB1dHMsXG4gIFNldFNlY3JldFJlc3VsdCxcbiAgVGVzdFJlc3VsdCxcbiAgUGx1Z2luQWN0aW9uT3V0cHV0cyxcbiAgUHVibGlzaFJlc3VsdCxcbn0gZnJvbSBcIi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IHtcbiAgQnVpbGRNb2R1bGVQYXJhbXMsXG4gIERlbGV0ZVNlY3JldFBhcmFtcyxcbiAgRGVwbG95U2VydmljZVBhcmFtcyxcbiAgRGVsZXRlU2VydmljZVBhcmFtcyxcbiAgRXhlY0luU2VydmljZVBhcmFtcyxcbiAgR2V0U2VjcmV0UGFyYW1zLFxuICBHZXRCdWlsZFN0YXR1c1BhcmFtcyxcbiAgR2V0U2VydmljZUxvZ3NQYXJhbXMsXG4gIEdldFNlcnZpY2VPdXRwdXRzUGFyYW1zLFxuICBHZXRTZXJ2aWNlU3RhdHVzUGFyYW1zLFxuICBHZXRUZXN0UmVzdWx0UGFyYW1zLFxuICBNb2R1bGVBY3Rpb25QYXJhbXMsXG4gIFBsdWdpbkFjdGlvbkNvbnRleHRQYXJhbXMsXG4gIFBsdWdpbkFjdGlvblBhcmFtcyxcbiAgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSxcbiAgUGx1Z2luU2VydmljZUFjdGlvblBhcmFtc0Jhc2UsXG4gIFB1c2hNb2R1bGVQYXJhbXMsXG4gIFJ1bk1vZHVsZVBhcmFtcyxcbiAgUnVuU2VydmljZVBhcmFtcyxcbiAgU2VydmljZUFjdGlvblBhcmFtcyxcbiAgU2V0U2VjcmV0UGFyYW1zLFxuICBUZXN0TW9kdWxlUGFyYW1zLFxuICBHZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtcyxcbiAgUGx1Z2luTW9kdWxlQWN0aW9uUGFyYW1zQmFzZSxcbiAgUHVibGlzaE1vZHVsZVBhcmFtcyxcbn0gZnJvbSBcIi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQge1xuICBTZXJ2aWNlLFxuICBTZXJ2aWNlU3RhdHVzLFxuICBwcmVwYXJlUnVudGltZUNvbnRleHQsXG59IGZyb20gXCIuL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHsgbWFwVmFsdWVzLCB2YWx1ZXMsIGtleUJ5LCBvbWl0IH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyBPbWl0IH0gZnJvbSBcIi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IFJ1bnRpbWVDb250ZXh0IH0gZnJvbSBcIi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBwcm9jZXNzU2VydmljZXMsIFByb2Nlc3NSZXN1bHRzIH0gZnJvbSBcIi4vcHJvY2Vzc1wiXG5pbXBvcnQgeyBnZXREZXBsb3lUYXNrcyB9IGZyb20gXCIuL3Rhc2tzL2RlcGxveVwiXG5pbXBvcnQgeyBMb2dFbnRyeSB9IGZyb20gXCIuL2xvZ2dlci9sb2ctZW50cnlcIlxuaW1wb3J0IHsgY3JlYXRlUGx1Z2luQ29udGV4dCB9IGZyb20gXCIuL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7IENsZWFudXBFbnZpcm9ubWVudFBhcmFtcyB9IGZyb20gXCIuL3R5cGVzL3BsdWdpbi9wYXJhbXNcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4vZXhjZXB0aW9uc1wiXG5cbnR5cGUgVHlwZUd1YXJkID0ge1xuICByZWFkb25seSBbUCBpbiBrZXlvZiAoUGx1Z2luQWN0aW9uUGFyYW1zIHwgTW9kdWxlQWN0aW9uUGFyYW1zPGFueT4pXTogKC4uLmFyZ3M6IGFueVtdKSA9PiBQcm9taXNlPGFueT5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb250ZXh0U3RhdHVzIHtcbiAgcHJvdmlkZXJzOiBFbnZpcm9ubWVudFN0YXR1c01hcFxuICBzZXJ2aWNlczogeyBbbmFtZTogc3RyaW5nXTogU2VydmljZVN0YXR1cyB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVwbG95U2VydmljZXNQYXJhbXMge1xuICBzZXJ2aWNlTmFtZXM/OiBzdHJpbmdbXSxcbiAgZm9yY2U/OiBib29sZWFuXG4gIGZvcmNlQnVpbGQ/OiBib29sZWFuXG59XG5cbi8vIGF2b2lkIGhhdmluZyB0byBzcGVjaWZ5IGNvbW1vbiBwYXJhbXMgb24gZWFjaCBhY3Rpb24gaGVscGVyIGNhbGxcbnR5cGUgQWN0aW9uSGVscGVyUGFyYW1zPFQgZXh0ZW5kcyBQbHVnaW5BY3Rpb25QYXJhbXNCYXNlPiA9XG4gIE9taXQ8VCwga2V5b2YgUGx1Z2luQWN0aW9uQ29udGV4dFBhcmFtcz4gJiB7IHBsdWdpbk5hbWU/OiBzdHJpbmcgfVxudHlwZSBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8VCBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U+ID1cbiAgT21pdDxULCBrZXlvZiBQbHVnaW5BY3Rpb25Db250ZXh0UGFyYW1zPiAmIHsgcGx1Z2luTmFtZT86IHN0cmluZyB9XG4vLyBhZGRpdGlvbmFsbHkgbWFrZSBydW50aW1lQ29udGV4dCBwYXJhbSBvcHRpb25hbFxudHlwZSBTZXJ2aWNlQWN0aW9uSGVscGVyUGFyYW1zPFQgZXh0ZW5kcyBQbHVnaW5TZXJ2aWNlQWN0aW9uUGFyYW1zQmFzZT4gPVxuICBPbWl0PFQsIFwibW9kdWxlXCIgfCBcInJ1bnRpbWVDb250ZXh0XCIgfCBrZXlvZiBQbHVnaW5BY3Rpb25Db250ZXh0UGFyYW1zPlxuICAmIHsgcnVudGltZUNvbnRleHQ/OiBSdW50aW1lQ29udGV4dCwgcGx1Z2luTmFtZT86IHN0cmluZyB9XG5cbnR5cGUgUmVxdWlyZVBsdWdpbk5hbWU8VD4gPSBUICYgeyBwbHVnaW5OYW1lOiBzdHJpbmcgfVxuXG5leHBvcnQgY2xhc3MgQWN0aW9uSGVscGVyIGltcGxlbWVudHMgVHlwZUd1YXJkIHtcbiAgY29uc3RydWN0b3IocHJpdmF0ZSBnYXJkZW46IEdhcmRlbikgeyB9XG5cbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy9yZWdpb24gRW52aXJvbm1lbnQgQWN0aW9uc1xuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGFzeW5jIGdldEVudmlyb25tZW50U3RhdHVzKFxuICAgIHsgcGx1Z2luTmFtZSB9OiBBY3Rpb25IZWxwZXJQYXJhbXM8R2V0RW52aXJvbm1lbnRTdGF0dXNQYXJhbXM+LFxuICApOiBQcm9taXNlPEVudmlyb25tZW50U3RhdHVzTWFwPiB7XG4gICAgY29uc3QgaGFuZGxlcnMgPSB0aGlzLmdhcmRlbi5nZXRBY3Rpb25IYW5kbGVycyhcImdldEVudmlyb25tZW50U3RhdHVzXCIsIHBsdWdpbk5hbWUpXG4gICAgcmV0dXJuIEJsdWViaXJkLnByb3BzKG1hcFZhbHVlcyhoYW5kbGVycywgaCA9PiBoKHsgLi4udGhpcy5jb21tb25QYXJhbXMoaCkgfSkpKVxuICB9XG5cbiAgLyoqXG4gICAqIENoZWNrcyBlbnZpcm9ubWVudCBzdGF0dXMgYW5kIGNhbGxzIHByZXBhcmVFbnZpcm9ubWVudCBmb3IgZWFjaCBwcm92aWRlciB0aGF0IGlzbid0IGZsYWdnZWQgYXMgcmVhZHkuXG4gICAqXG4gICAqIElmIGFueSBvZiB0aGUgZ2V0RW52aXJvbm1lbnRTdGF0dXMgaGFuZGxlcnMgcmV0dXJucyBuZWVkVXNlcklucHV0PXRydWUsIHRoaXMgdGhyb3dzIGFuZCBndWlkZXMgdGhlIHVzZXIgdG9cbiAgICogcnVuIGBnYXJkZW4gaW5pdGBcbiAgICovXG4gIGFzeW5jIHByZXBhcmVFbnZpcm9ubWVudChcbiAgICB7IGZvcmNlID0gZmFsc2UsIHBsdWdpbk5hbWUsIGxvZ0VudHJ5LCBhbGxvd1VzZXJJbnB1dCA9IGZhbHNlIH06XG4gICAgICB7IGZvcmNlPzogYm9vbGVhbiwgcGx1Z2luTmFtZT86IHN0cmluZywgbG9nRW50cnk/OiBMb2dFbnRyeSwgYWxsb3dVc2VySW5wdXQ/OiBib29sZWFuIH0sXG4gICkge1xuICAgIGNvbnN0IGhhbmRsZXJzID0gdGhpcy5nYXJkZW4uZ2V0QWN0aW9uSGFuZGxlcnMoXCJwcmVwYXJlRW52aXJvbm1lbnRcIiwgcGx1Z2luTmFtZSlcbiAgICBjb25zdCBzdGF0dXNlcyA9IGF3YWl0IHRoaXMuZ2V0RW52aXJvbm1lbnRTdGF0dXMoeyBwbHVnaW5OYW1lIH0pXG5cbiAgICBjb25zdCBuZWVkVXNlcklucHV0ID0gT2JqZWN0LmVudHJpZXMoc3RhdHVzZXMpXG4gICAgICAubWFwKChbbmFtZSwgc3RhdHVzXSkgPT4gKHsgLi4uc3RhdHVzLCBuYW1lIH0pKVxuICAgICAgLmZpbHRlcihzdGF0dXMgPT4gc3RhdHVzLm5lZWRVc2VySW5wdXQgPT09IHRydWUpXG5cbiAgICBpZiAoIWFsbG93VXNlcklucHV0ICYmIG5lZWRVc2VySW5wdXQubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbmFtZXMgPSBuZWVkVXNlcklucHV0Lm1hcChzID0+IHMubmFtZSkuam9pbihcIiwgXCIpXG4gICAgICBjb25zdCBtc2dQcmVmaXggPSBuZWVkVXNlcklucHV0Lmxlbmd0aCA9PT0gMVxuICAgICAgICA/IGBQbHVnaW4gJHtuYW1lc30gaGFzIGJlZW4gdXBkYXRlZCBvciBoYXNuJ3QgYmVlbiBjb25maWd1cmVkLCBhbmQgcmVxdWlyZXMgdXNlciBpbnB1dC5gXG4gICAgICAgIDogYFBsdWdpbnMgJHtuYW1lc30gaGF2ZSBiZWVuIHVwZGF0ZWQgb3IgaGF2ZW4ndCBiZWVuIGNvbmZpZ3VyZWQsIGFuZCByZXF1aXJlIHVzZXIgaW5wdXQuYFxuXG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgICBgJHttc2dQcmVmaXh9LiBQbGVhc2UgcnVuIFxcYGdhcmRlbiBpbml0XFxgIGFuZCB0aGVuIHJlLXJ1biB0aGlzIGNvbW1hbmQuYCxcbiAgICAgICAgeyBzdGF0dXNlcyB9LFxuICAgICAgKVxuICAgIH1cblxuICAgIGNvbnN0IG91dHB1dCA9IHt9XG5cbiAgICAvLyBzZXF1ZW50aWFsbHkgZ28gdGhyb3VnaCB0aGUgcHJlcGFyYXRpb24gc3RlcHMsIHRvIGFsbG93IHBsdWdpbnMgdG8gcmVxdWVzdCB1c2VyIGlucHV0XG4gICAgZm9yIChjb25zdCBbbmFtZSwgaGFuZGxlcl0gb2YgT2JqZWN0LmVudHJpZXMoaGFuZGxlcnMpKSB7XG4gICAgICBjb25zdCBzdGF0dXMgPSBzdGF0dXNlc1tuYW1lXSB8fCB7IHJlYWR5OiBmYWxzZSB9XG5cbiAgICAgIGlmIChzdGF0dXMucmVhZHkgJiYgIWZvcmNlKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGVudkxvZ0VudHJ5ID0gKGxvZ0VudHJ5IHx8IHRoaXMuZ2FyZGVuLmxvZykuaW5mbyh7XG4gICAgICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgICAgICAgc2VjdGlvbjogbmFtZSxcbiAgICAgICAgbXNnOiBcIlByZXBhcmluZyBlbnZpcm9ubWVudC4uLlwiLFxuICAgICAgfSlcblxuICAgICAgYXdhaXQgaGFuZGxlcih7IC4uLnRoaXMuY29tbW9uUGFyYW1zKGhhbmRsZXIpLCBmb3JjZSwgc3RhdHVzLCBsb2dFbnRyeTogZW52TG9nRW50cnkgfSlcblxuICAgICAgZW52TG9nRW50cnkuc2V0U3VjY2VzcyhcIkNvbmZpZ3VyZWRcIilcblxuICAgICAgb3V0cHV0W25hbWVdID0gdHJ1ZVxuICAgIH1cblxuICAgIHJldHVybiBvdXRwdXRcbiAgfVxuXG4gIGFzeW5jIGNsZWFudXBFbnZpcm9ubWVudChcbiAgICB7IHBsdWdpbk5hbWUgfTogQWN0aW9uSGVscGVyUGFyYW1zPENsZWFudXBFbnZpcm9ubWVudFBhcmFtcz4sXG4gICk6IFByb21pc2U8RW52aXJvbm1lbnRTdGF0dXNNYXA+IHtcbiAgICBjb25zdCBoYW5kbGVycyA9IHRoaXMuZ2FyZGVuLmdldEFjdGlvbkhhbmRsZXJzKFwiY2xlYW51cEVudmlyb25tZW50XCIsIHBsdWdpbk5hbWUpXG4gICAgYXdhaXQgQmx1ZWJpcmQuZWFjaCh2YWx1ZXMoaGFuZGxlcnMpLCBoID0+IGgoeyAuLi50aGlzLmNvbW1vblBhcmFtcyhoKSB9KSlcbiAgICByZXR1cm4gdGhpcy5nZXRFbnZpcm9ubWVudFN0YXR1cyh7IHBsdWdpbk5hbWUgfSlcbiAgfVxuXG4gIGFzeW5jIGdldFNlY3JldChwYXJhbXM6IFJlcXVpcmVQbHVnaW5OYW1lPEFjdGlvbkhlbHBlclBhcmFtczxHZXRTZWNyZXRQYXJhbXM+Pik6IFByb21pc2U8R2V0U2VjcmV0UmVzdWx0PiB7XG4gICAgY29uc3QgeyBwbHVnaW5OYW1lIH0gPSBwYXJhbXNcbiAgICByZXR1cm4gdGhpcy5jYWxsQWN0aW9uSGFuZGxlcih7IGFjdGlvblR5cGU6IFwiZ2V0U2VjcmV0XCIsIHBsdWdpbk5hbWUsIHBhcmFtczogb21pdChwYXJhbXMsIFtcInBsdWdpbk5hbWVcIl0pIH0pXG4gIH1cblxuICBhc3luYyBzZXRTZWNyZXQocGFyYW1zOiBSZXF1aXJlUGx1Z2luTmFtZTxBY3Rpb25IZWxwZXJQYXJhbXM8U2V0U2VjcmV0UGFyYW1zPj4pOiBQcm9taXNlPFNldFNlY3JldFJlc3VsdD4ge1xuICAgIGNvbnN0IHsgcGx1Z2luTmFtZSB9ID0gcGFyYW1zXG4gICAgcmV0dXJuIHRoaXMuY2FsbEFjdGlvbkhhbmRsZXIoeyBhY3Rpb25UeXBlOiBcInNldFNlY3JldFwiLCBwbHVnaW5OYW1lLCBwYXJhbXM6IG9taXQocGFyYW1zLCBbXCJwbHVnaW5OYW1lXCJdKSB9KVxuICB9XG5cbiAgYXN5bmMgZGVsZXRlU2VjcmV0KHBhcmFtczogUmVxdWlyZVBsdWdpbk5hbWU8QWN0aW9uSGVscGVyUGFyYW1zPERlbGV0ZVNlY3JldFBhcmFtcz4+KTogUHJvbWlzZTxEZWxldGVTZWNyZXRSZXN1bHQ+IHtcbiAgICBjb25zdCB7IHBsdWdpbk5hbWUgfSA9IHBhcmFtc1xuICAgIHJldHVybiB0aGlzLmNhbGxBY3Rpb25IYW5kbGVyKHsgYWN0aW9uVHlwZTogXCJkZWxldGVTZWNyZXRcIiwgcGx1Z2luTmFtZSwgcGFyYW1zOiBvbWl0KHBhcmFtcywgW1wicGx1Z2luTmFtZVwiXSkgfSlcbiAgfVxuXG4gIC8vZW5kcmVnaW9uXG5cbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cbiAgLy9yZWdpb24gTW9kdWxlIEFjdGlvbnNcbiAgLy89PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT1cblxuICBhc3luYyBnZXRCdWlsZFN0YXR1czxUIGV4dGVuZHMgTW9kdWxlPihcbiAgICBwYXJhbXM6IE1vZHVsZUFjdGlvbkhlbHBlclBhcmFtczxHZXRCdWlsZFN0YXR1c1BhcmFtczxUPj4sXG4gICk6IFByb21pc2U8QnVpbGRTdGF0dXM+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsTW9kdWxlSGFuZGxlcih7XG4gICAgICBwYXJhbXMsXG4gICAgICBhY3Rpb25UeXBlOiBcImdldEJ1aWxkU3RhdHVzXCIsXG4gICAgICBkZWZhdWx0SGFuZGxlcjogYXN5bmMgKCkgPT4gKHsgcmVhZHk6IGZhbHNlIH0pLFxuICAgIH0pXG4gIH1cblxuICBhc3luYyBidWlsZDxUIGV4dGVuZHMgTW9kdWxlPihwYXJhbXM6IE1vZHVsZUFjdGlvbkhlbHBlclBhcmFtczxCdWlsZE1vZHVsZVBhcmFtczxUPj4pOiBQcm9taXNlPEJ1aWxkUmVzdWx0PiB7XG4gICAgYXdhaXQgdGhpcy5nYXJkZW4uYnVpbGREaXIuc3luY0RlcGVuZGVuY3lQcm9kdWN0cyhwYXJhbXMubW9kdWxlKVxuICAgIHJldHVybiB0aGlzLmNhbGxNb2R1bGVIYW5kbGVyKHsgcGFyYW1zLCBhY3Rpb25UeXBlOiBcImJ1aWxkXCIgfSlcbiAgfVxuXG4gIGFzeW5jIHB1c2hNb2R1bGU8VCBleHRlbmRzIE1vZHVsZT4ocGFyYW1zOiBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8UHVzaE1vZHVsZVBhcmFtczxUPj4pOiBQcm9taXNlPFB1c2hSZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsTW9kdWxlSGFuZGxlcih7IHBhcmFtcywgYWN0aW9uVHlwZTogXCJwdXNoTW9kdWxlXCIsIGRlZmF1bHRIYW5kbGVyOiBkdW1teVB1c2hIYW5kbGVyIH0pXG4gIH1cblxuICBhc3luYyBwdWJsaXNoTW9kdWxlPFQgZXh0ZW5kcyBNb2R1bGU+KFxuICAgIHBhcmFtczogTW9kdWxlQWN0aW9uSGVscGVyUGFyYW1zPFB1Ymxpc2hNb2R1bGVQYXJhbXM8VD4+LFxuICApOiBQcm9taXNlPFB1Ymxpc2hSZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsTW9kdWxlSGFuZGxlcih7IHBhcmFtcywgYWN0aW9uVHlwZTogXCJwdWJsaXNoTW9kdWxlXCIsIGRlZmF1bHRIYW5kbGVyOiBkdW1teVB1Ymxpc2hIYW5kbGVyIH0pXG4gIH1cblxuICBhc3luYyBydW5Nb2R1bGU8VCBleHRlbmRzIE1vZHVsZT4ocGFyYW1zOiBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8UnVuTW9kdWxlUGFyYW1zPFQ+Pik6IFByb21pc2U8UnVuUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbE1vZHVsZUhhbmRsZXIoeyBwYXJhbXMsIGFjdGlvblR5cGU6IFwicnVuTW9kdWxlXCIgfSlcbiAgfVxuXG4gIGFzeW5jIHRlc3RNb2R1bGU8VCBleHRlbmRzIE1vZHVsZT4ocGFyYW1zOiBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8VGVzdE1vZHVsZVBhcmFtczxUPj4pOiBQcm9taXNlPFRlc3RSZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsTW9kdWxlSGFuZGxlcih7IHBhcmFtcywgYWN0aW9uVHlwZTogXCJ0ZXN0TW9kdWxlXCIgfSlcbiAgfVxuXG4gIGFzeW5jIGdldFRlc3RSZXN1bHQ8VCBleHRlbmRzIE1vZHVsZT4oXG4gICAgcGFyYW1zOiBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8R2V0VGVzdFJlc3VsdFBhcmFtczxUPj4sXG4gICk6IFByb21pc2U8VGVzdFJlc3VsdCB8IG51bGw+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsTW9kdWxlSGFuZGxlcih7XG4gICAgICBwYXJhbXMsXG4gICAgICBhY3Rpb25UeXBlOiBcImdldFRlc3RSZXN1bHRcIixcbiAgICAgIGRlZmF1bHRIYW5kbGVyOiBhc3luYyAoKSA9PiBudWxsLFxuICAgIH0pXG4gIH1cblxuICAvL2VuZHJlZ2lvblxuXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vcmVnaW9uIFNlcnZpY2UgQWN0aW9uc1xuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuXG4gIGFzeW5jIGdldFNlcnZpY2VTdGF0dXMocGFyYW1zOiBTZXJ2aWNlQWN0aW9uSGVscGVyUGFyYW1zPEdldFNlcnZpY2VTdGF0dXNQYXJhbXM+KTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbFNlcnZpY2VIYW5kbGVyKHsgcGFyYW1zLCBhY3Rpb25UeXBlOiBcImdldFNlcnZpY2VTdGF0dXNcIiB9KVxuICB9XG5cbiAgYXN5bmMgZGVwbG95U2VydmljZShwYXJhbXM6IFNlcnZpY2VBY3Rpb25IZWxwZXJQYXJhbXM8RGVwbG95U2VydmljZVBhcmFtcz4pOiBQcm9taXNlPFNlcnZpY2VTdGF0dXM+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsU2VydmljZUhhbmRsZXIoeyBwYXJhbXMsIGFjdGlvblR5cGU6IFwiZGVwbG95U2VydmljZVwiIH0pXG4gIH1cblxuICBhc3luYyBkZWxldGVTZXJ2aWNlKHBhcmFtczogU2VydmljZUFjdGlvbkhlbHBlclBhcmFtczxEZWxldGVTZXJ2aWNlUGFyYW1zPik6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICAgIGNvbnN0IGxvZ0VudHJ5ID0gdGhpcy5nYXJkZW4ubG9nLmluZm8oe1xuICAgICAgc2VjdGlvbjogcGFyYW1zLnNlcnZpY2UubmFtZSxcbiAgICAgIG1zZzogXCJEZWxldGluZy4uLlwiLFxuICAgICAgc3RhdHVzOiBcImFjdGl2ZVwiLFxuICAgIH0pXG4gICAgcmV0dXJuIHRoaXMuY2FsbFNlcnZpY2VIYW5kbGVyKHtcbiAgICAgIHBhcmFtczogeyAuLi5wYXJhbXMsIGxvZ0VudHJ5IH0sXG4gICAgICBhY3Rpb25UeXBlOiBcImRlbGV0ZVNlcnZpY2VcIixcbiAgICAgIGRlZmF1bHRIYW5kbGVyOiBkdW1teURlbGV0ZVNlcnZpY2VIYW5kbGVyLFxuICAgIH0pXG4gIH1cblxuICBhc3luYyBnZXRTZXJ2aWNlT3V0cHV0cyhwYXJhbXM6IFNlcnZpY2VBY3Rpb25IZWxwZXJQYXJhbXM8R2V0U2VydmljZU91dHB1dHNQYXJhbXM+KTogUHJvbWlzZTxQcmltaXRpdmVNYXA+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsU2VydmljZUhhbmRsZXIoe1xuICAgICAgcGFyYW1zLFxuICAgICAgYWN0aW9uVHlwZTogXCJnZXRTZXJ2aWNlT3V0cHV0c1wiLFxuICAgICAgZGVmYXVsdEhhbmRsZXI6IGFzeW5jICgpID0+ICh7fSksXG4gICAgfSlcbiAgfVxuXG4gIGFzeW5jIGV4ZWNJblNlcnZpY2UocGFyYW1zOiBTZXJ2aWNlQWN0aW9uSGVscGVyUGFyYW1zPEV4ZWNJblNlcnZpY2VQYXJhbXM+KTogUHJvbWlzZTxFeGVjSW5TZXJ2aWNlUmVzdWx0PiB7XG4gICAgcmV0dXJuIHRoaXMuY2FsbFNlcnZpY2VIYW5kbGVyKHsgcGFyYW1zLCBhY3Rpb25UeXBlOiBcImV4ZWNJblNlcnZpY2VcIiB9KVxuICB9XG5cbiAgYXN5bmMgZ2V0U2VydmljZUxvZ3MocGFyYW1zOiBTZXJ2aWNlQWN0aW9uSGVscGVyUGFyYW1zPEdldFNlcnZpY2VMb2dzUGFyYW1zPik6IFByb21pc2U8R2V0U2VydmljZUxvZ3NSZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsU2VydmljZUhhbmRsZXIoeyBwYXJhbXMsIGFjdGlvblR5cGU6IFwiZ2V0U2VydmljZUxvZ3NcIiwgZGVmYXVsdEhhbmRsZXI6IGR1bW15TG9nU3RyZWFtZXIgfSlcbiAgfVxuXG4gIGFzeW5jIHJ1blNlcnZpY2UocGFyYW1zOiBTZXJ2aWNlQWN0aW9uSGVscGVyUGFyYW1zPFJ1blNlcnZpY2VQYXJhbXM+KTogUHJvbWlzZTxSdW5SZXN1bHQ+IHtcbiAgICByZXR1cm4gdGhpcy5jYWxsU2VydmljZUhhbmRsZXIoeyBwYXJhbXMsIGFjdGlvblR5cGU6IFwicnVuU2VydmljZVwiIH0pXG4gIH1cblxuICAvL2VuZHJlZ2lvblxuXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG4gIC8vcmVnaW9uIEhlbHBlciBNZXRob2RzXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgYXN5bmMgZ2V0U3RhdHVzKCk6IFByb21pc2U8Q29udGV4dFN0YXR1cz4ge1xuICAgIGNvbnN0IGVudlN0YXR1czogRW52aXJvbm1lbnRTdGF0dXNNYXAgPSBhd2FpdCB0aGlzLmdldEVudmlyb25tZW50U3RhdHVzKHt9KVxuICAgIGNvbnN0IHNlcnZpY2VzID0ga2V5QnkoYXdhaXQgdGhpcy5nYXJkZW4uZ2V0U2VydmljZXMoKSwgXCJuYW1lXCIpXG5cbiAgICBjb25zdCBzZXJ2aWNlU3RhdHVzID0gYXdhaXQgQmx1ZWJpcmQucHJvcHMobWFwVmFsdWVzKHNlcnZpY2VzLCBhc3luYyAoc2VydmljZTogU2VydmljZSkgPT4ge1xuICAgICAgY29uc3QgZGVwZW5kZW5jaWVzID0gYXdhaXQgdGhpcy5nYXJkZW4uZ2V0U2VydmljZXMoc2VydmljZS5jb25maWcuZGVwZW5kZW5jaWVzKVxuICAgICAgY29uc3QgcnVudGltZUNvbnRleHQgPSBhd2FpdCBwcmVwYXJlUnVudGltZUNvbnRleHQodGhpcy5nYXJkZW4sIHNlcnZpY2UubW9kdWxlLCBkZXBlbmRlbmNpZXMpXG4gICAgICByZXR1cm4gdGhpcy5nZXRTZXJ2aWNlU3RhdHVzKHsgc2VydmljZSwgcnVudGltZUNvbnRleHQgfSlcbiAgICB9KSlcblxuICAgIHJldHVybiB7XG4gICAgICBwcm92aWRlcnM6IGVudlN0YXR1cyxcbiAgICAgIHNlcnZpY2VzOiBzZXJ2aWNlU3RhdHVzLFxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGRlcGxveVNlcnZpY2VzKFxuICAgIHsgc2VydmljZU5hbWVzLCBmb3JjZSA9IGZhbHNlLCBmb3JjZUJ1aWxkID0gZmFsc2UgfTogRGVwbG95U2VydmljZXNQYXJhbXMsXG4gICk6IFByb21pc2U8UHJvY2Vzc1Jlc3VsdHM+IHtcbiAgICBjb25zdCBzZXJ2aWNlcyA9IGF3YWl0IHRoaXMuZ2FyZGVuLmdldFNlcnZpY2VzKHNlcnZpY2VOYW1lcylcblxuICAgIHJldHVybiBwcm9jZXNzU2VydmljZXMoe1xuICAgICAgc2VydmljZXMsXG4gICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgd2F0Y2g6IGZhbHNlLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKG1vZHVsZSkgPT4gZ2V0RGVwbG95VGFza3Moe1xuICAgICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgICBtb2R1bGUsXG4gICAgICAgIHNlcnZpY2VOYW1lcyxcbiAgICAgICAgZm9yY2UsXG4gICAgICAgIGZvcmNlQnVpbGQsXG4gICAgICAgIGluY2x1ZGVEZXBlbmRhbnRzOiBmYWxzZSxcbiAgICAgIH0pLFxuICAgIH0pXG4gIH1cblxuICAvL2VuZHJlZ2lvblxuXG4gIC8vIFRPRE86IGZpbmQgYSBuaWNlciB3YXkgdG8gZG8gdGhpcyAobGlrZSBhIHR5cGUtc2FmZSB3cmFwcGVyIGZ1bmN0aW9uKVxuICBwcml2YXRlIGNvbW1vblBhcmFtcyhoYW5kbGVyLCBsb2dFbnRyeT86IExvZ0VudHJ5KTogUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSB7XG4gICAgcmV0dXJuIHtcbiAgICAgIGN0eDogY3JlYXRlUGx1Z2luQ29udGV4dCh0aGlzLmdhcmRlbiwgaGFuZGxlcltcInBsdWdpbk5hbWVcIl0pLFxuICAgICAgLy8gVE9ETzogZmluZCBhIGJldHRlciB3YXkgZm9yIGhhbmRsZXJzIHRvIGxvZyBkdXJpbmcgZXhlY3V0aW9uXG4gICAgICBsb2dFbnRyeSxcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGxBY3Rpb25IYW5kbGVyPFQgZXh0ZW5kcyBrZXlvZiBQbHVnaW5BY3Rpb25zPihcbiAgICB7IHBhcmFtcywgYWN0aW9uVHlwZSwgcGx1Z2luTmFtZSwgZGVmYXVsdEhhbmRsZXIgfTpcbiAgICAgIHtcbiAgICAgICAgcGFyYW1zOiBBY3Rpb25IZWxwZXJQYXJhbXM8UGx1Z2luQWN0aW9uUGFyYW1zW1RdPixcbiAgICAgICAgYWN0aW9uVHlwZTogVCxcbiAgICAgICAgcGx1Z2luTmFtZT86IHN0cmluZyxcbiAgICAgICAgZGVmYXVsdEhhbmRsZXI/OiBQbHVnaW5BY3Rpb25zW1RdLFxuICAgICAgfSxcbiAgKTogUHJvbWlzZTxQbHVnaW5BY3Rpb25PdXRwdXRzW1RdPiB7XG4gICAgY29uc3QgaGFuZGxlciA9IHRoaXMuZ2FyZGVuLmdldEFjdGlvbkhhbmRsZXIoe1xuICAgICAgYWN0aW9uVHlwZSxcbiAgICAgIHBsdWdpbk5hbWUsXG4gICAgICBkZWZhdWx0SGFuZGxlcixcbiAgICB9KVxuICAgIGNvbnN0IGhhbmRsZXJQYXJhbXM6IFBsdWdpbkFjdGlvblBhcmFtc1tUXSA9IHtcbiAgICAgIC4uLnRoaXMuY29tbW9uUGFyYW1zKGhhbmRsZXIpLFxuICAgICAgLi4uPG9iamVjdD5wYXJhbXMsXG4gICAgfVxuICAgIHJldHVybiAoPEZ1bmN0aW9uPmhhbmRsZXIpKGhhbmRsZXJQYXJhbXMpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGxNb2R1bGVIYW5kbGVyPFQgZXh0ZW5kcyBrZXlvZiBPbWl0PE1vZHVsZUFjdGlvbnMsIFwiZGVzY3JpYmVUeXBlXCIgfCBcInZhbGlkYXRlXCI+PihcbiAgICB7IHBhcmFtcywgYWN0aW9uVHlwZSwgZGVmYXVsdEhhbmRsZXIgfTpcbiAgICAgIHsgcGFyYW1zOiBNb2R1bGVBY3Rpb25IZWxwZXJQYXJhbXM8TW9kdWxlQWN0aW9uUGFyYW1zW1RdPiwgYWN0aW9uVHlwZTogVCwgZGVmYXVsdEhhbmRsZXI/OiBNb2R1bGVBY3Rpb25zW1RdIH0sXG4gICk6IFByb21pc2U8TW9kdWxlQWN0aW9uT3V0cHV0c1tUXT4ge1xuICAgIC8vIHRoZSB0eXBlIHN5c3RlbSBpcyBtZXNzaW5nIG1lIHVwIGhlcmUsIG5vdCBzdXJlIHdoeSBJIG5lZWQgdGhlIGFueSBjYXN0Li4uIC0gai5lLlxuICAgIGNvbnN0IHsgbW9kdWxlLCBwbHVnaW5OYW1lIH0gPSA8YW55PnBhcmFtc1xuICAgIGNvbnN0IGhhbmRsZXIgPSBhd2FpdCB0aGlzLmdhcmRlbi5nZXRNb2R1bGVBY3Rpb25IYW5kbGVyKHtcbiAgICAgIG1vZHVsZVR5cGU6IG1vZHVsZS50eXBlLFxuICAgICAgYWN0aW9uVHlwZSxcbiAgICAgIHBsdWdpbk5hbWUsXG4gICAgICBkZWZhdWx0SGFuZGxlcixcbiAgICB9KVxuICAgIGNvbnN0IGhhbmRsZXJQYXJhbXM6IGFueSA9IHtcbiAgICAgIC4uLnRoaXMuY29tbW9uUGFyYW1zKGhhbmRsZXIpLFxuICAgICAgLi4ub21pdCg8b2JqZWN0PnBhcmFtcywgW1wibW9kdWxlXCJdKSxcbiAgICAgIG1vZHVsZTogb21pdChtb2R1bGUsIFtcIl9Db25maWdUeXBlXCJdKSxcbiAgICB9XG4gICAgLy8gVE9ETzogZmlndXJlIG91dCB3aHkgdGhpcyBkb2Vzbid0IGNvbXBpbGUgd2l0aG91dCB0aGUgZnVuY3Rpb24gY2FzdFxuICAgIHJldHVybiAoPEZ1bmN0aW9uPmhhbmRsZXIpKGhhbmRsZXJQYXJhbXMpXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGNhbGxTZXJ2aWNlSGFuZGxlcjxUIGV4dGVuZHMga2V5b2YgU2VydmljZUFjdGlvbnM+KFxuICAgIHsgcGFyYW1zLCBhY3Rpb25UeXBlLCBkZWZhdWx0SGFuZGxlciB9OlxuICAgICAgeyBwYXJhbXM6IFNlcnZpY2VBY3Rpb25IZWxwZXJQYXJhbXM8U2VydmljZUFjdGlvblBhcmFtc1tUXT4sIGFjdGlvblR5cGU6IFQsIGRlZmF1bHRIYW5kbGVyPzogU2VydmljZUFjdGlvbnNbVF0gfSxcbiAgKTogUHJvbWlzZTxTZXJ2aWNlQWN0aW9uT3V0cHV0c1tUXT4ge1xuICAgIGNvbnN0IHsgc2VydmljZSB9ID0gPGFueT5wYXJhbXNcbiAgICBjb25zdCBtb2R1bGUgPSBzZXJ2aWNlLm1vZHVsZVxuXG4gICAgY29uc3QgaGFuZGxlciA9IGF3YWl0IHRoaXMuZ2FyZGVuLmdldE1vZHVsZUFjdGlvbkhhbmRsZXIoe1xuICAgICAgbW9kdWxlVHlwZTogbW9kdWxlLnR5cGUsXG4gICAgICBhY3Rpb25UeXBlLFxuICAgICAgcGx1Z2luTmFtZTogcGFyYW1zLnBsdWdpbk5hbWUsXG4gICAgICBkZWZhdWx0SGFuZGxlcixcbiAgICB9KVxuXG4gICAgLy8gVE9ETzogZmlndXJlIG91dCB3aHkgdGhpcyBkb2Vzbid0IGNvbXBpbGUgd2l0aG91dCB0aGUgY2FzdHNcbiAgICBjb25zdCBkZXBzID0gYXdhaXQgdGhpcy5nYXJkZW4uZ2V0U2VydmljZXMoc2VydmljZS5jb25maWcuZGVwZW5kZW5jaWVzKVxuICAgIGNvbnN0IHJ1bnRpbWVDb250ZXh0ID0gKCg8YW55PnBhcmFtcykucnVudGltZUNvbnRleHQgfHwgYXdhaXQgcHJlcGFyZVJ1bnRpbWVDb250ZXh0KHRoaXMuZ2FyZGVuLCBtb2R1bGUsIGRlcHMpKVxuXG4gICAgY29uc3QgaGFuZGxlclBhcmFtczogYW55ID0ge1xuICAgICAgLi4udGhpcy5jb21tb25QYXJhbXMoaGFuZGxlciksXG4gICAgICAuLi48b2JqZWN0PnBhcmFtcyxcbiAgICAgIG1vZHVsZSxcbiAgICAgIHJ1bnRpbWVDb250ZXh0LFxuICAgIH1cblxuICAgIHJldHVybiAoPEZ1bmN0aW9uPmhhbmRsZXIpKGhhbmRsZXJQYXJhbXMpXG4gIH1cbn1cblxuY29uc3QgZHVtbXlMb2dTdHJlYW1lciA9IGFzeW5jICh7IHNlcnZpY2UsIGxvZ0VudHJ5IH06IEdldFNlcnZpY2VMb2dzUGFyYW1zKSA9PiB7XG4gIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5Lndhcm4oe1xuICAgIHNlY3Rpb246IHNlcnZpY2UubmFtZSxcbiAgICBtc2c6IGNoYWxrLnllbGxvdyhgTm8gaGFuZGxlciBmb3IgbG9nIHJldHJpZXZhbCBhdmFpbGFibGUgZm9yIG1vZHVsZSB0eXBlICR7c2VydmljZS5tb2R1bGUudHlwZX1gKSxcbiAgfSlcbiAgcmV0dXJuIHt9XG59XG5cbmNvbnN0IGR1bW15UHVzaEhhbmRsZXIgPSBhc3luYyAoKSA9PiB7XG4gIHJldHVybiB7IHB1c2hlZDogZmFsc2UgfVxufVxuXG5jb25zdCBkdW1teVB1Ymxpc2hIYW5kbGVyID0gYXN5bmMgKHsgbW9kdWxlIH0pID0+IHtcbiAgcmV0dXJuIHtcbiAgICBtZXNzYWdlOiBjaGFsay55ZWxsb3coYE5vIHB1Ymxpc2ggaGFuZGxlciBhdmFpbGFibGUgZm9yIG1vZHVsZSB0eXBlICR7bW9kdWxlLnR5cGV9YCksXG4gICAgcHVibGlzaGVkOiBmYWxzZSxcbiAgfVxufVxuXG5jb25zdCBkdW1teURlbGV0ZVNlcnZpY2VIYW5kbGVyID0gYXN5bmMgKHsgbW9kdWxlLCBsb2dFbnRyeSB9OiBEZWxldGVTZXJ2aWNlUGFyYW1zKSA9PiB7XG4gIGNvbnN0IG1zZyA9IGBObyBkZWxldGUgc2VydmljZSBoYW5kbGVyIGF2YWlsYWJsZSBmb3IgbW9kdWxlIHR5cGUgJHttb2R1bGUudHlwZX1gXG4gIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LnNldEVycm9yKG1zZylcbiAgcmV0dXJuIHt9XG59XG4iXX0= diff --git a/garden-service/build/build-dir.d.ts b/garden-service/build/build-dir.d.ts new file mode 100644 index 00000000000..0630809de39 --- /dev/null +++ b/garden-service/build/build-dir.d.ts @@ -0,0 +1,13 @@ +import { Module } from "./types/module"; +export declare class BuildDir { + private projectRoot; + buildDirPath: string; + constructor(projectRoot: string, buildDirPath: string); + static factory(projectRoot: string): Promise; + syncFromSrc(module: Module): Promise; + syncDependencyProducts(module: Module): Promise; + clear(): Promise; + buildPath(moduleName: string): Promise; + private sync; +} +//# sourceMappingURL=build-dir.d.ts.map \ No newline at end of file diff --git a/garden-service/build/build-dir.js b/garden-service/build/build-dir.js new file mode 100644 index 00000000000..26899f1dadd --- /dev/null +++ b/garden-service/build/build-dir.js @@ -0,0 +1,110 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const bluebird_1 = require("bluebird"); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const constants_1 = require("./constants"); +const exceptions_1 = require("./exceptions"); +const module_1 = require("./types/module"); +const lodash_1 = require("lodash"); +const execa = require("execa"); +const os_1 = require("os"); +const util_1 = require("./util/util"); +// Lazily construct a directory of modules inside which all build steps are performed. +const buildDirRelPath = path_1.join(constants_1.GARDEN_DIR_NAME, "build"); +class BuildDir { + constructor(projectRoot, buildDirPath) { + this.projectRoot = projectRoot; + this.buildDirPath = buildDirPath; + } + static factory(projectRoot) { + return __awaiter(this, void 0, void 0, function* () { + const buildDirPath = path_1.join(projectRoot, buildDirRelPath); + yield fs_extra_1.ensureDir(buildDirPath); + return new BuildDir(projectRoot, buildDirPath); + }); + } + syncFromSrc(module) { + return __awaiter(this, void 0, void 0, function* () { + yield this.sync(path_1.resolve(this.projectRoot, module.path) + path_1.sep, yield this.buildPath(module.name)); + }); + } + syncDependencyProducts(module) { + return __awaiter(this, void 0, void 0, function* () { + yield this.syncFromSrc(module); + const buildPath = yield this.buildPath(module.name); + const buildDependencies = yield module.build.dependencies; + const dependencyConfigs = module.build.dependencies || []; + yield bluebird_1.map(lodash_1.zip(buildDependencies, dependencyConfigs), ([sourceModule, depConfig]) => __awaiter(this, void 0, void 0, function* () { + if (!sourceModule || !depConfig || !depConfig.copy) { + return; + } + const sourceBuildPath = yield this.buildPath(module_1.getModuleKey(sourceModule.name, sourceModule.plugin)); + // Sync to the module's top-level dir by default. + yield bluebird_1.map(depConfig.copy, (copy) => { + if (path_1.isAbsolute(copy.source)) { + throw new exceptions_1.ConfigurationError(`Source path in build dependency copy spec must be a relative path`, { + copySpec: copy, + }); + } + if (path_1.isAbsolute(copy.target)) { + throw new exceptions_1.ConfigurationError(`Target path in build dependency copy spec must be a relative path`, { + copySpec: copy, + }); + } + const sourcePath = path_1.join(sourceBuildPath, copy.source); + const destinationPath = path_1.join(buildPath, copy.target); + return this.sync(sourcePath, destinationPath); + }); + })); + }); + } + clear() { + return __awaiter(this, void 0, void 0, function* () { + yield fs_extra_1.emptyDir(this.buildDirPath); + }); + } + buildPath(moduleName) { + return __awaiter(this, void 0, void 0, function* () { + const path = path_1.resolve(this.buildDirPath, moduleName); + yield fs_extra_1.ensureDir(path); + return path; + }); + } + sync(sourcePath, destinationPath) { + return __awaiter(this, void 0, void 0, function* () { + const destinationDir = path_1.parse(destinationPath).dir; + yield fs_extra_1.ensureDir(destinationDir); + if (os_1.platform() === "win32") { + // this is so that the cygwin-based rsync client can deal with the paths + sourcePath = util_1.toCygwinPath(sourcePath); + destinationPath = util_1.toCygwinPath(destinationPath); + } + // the correct way to copy all contents of a folder is using a trailing slash and not a wildcard + sourcePath = stripWildcard(sourcePath); + destinationPath = stripWildcard(destinationPath); + yield execa("rsync", ["-rptgo", sourcePath, destinationPath]); + }); + } +} +exports.BuildDir = BuildDir; +function stripWildcard(path) { + return path.endsWith("/*") ? path.slice(0, -1) : path; +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFDLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFBO0FBQ3ZELENBQUMiLCJmaWxlIjoiYnVpbGQtZGlyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IG1hcCBhcyBibHVlYmlyZE1hcCB9IGZyb20gXCJibHVlYmlyZFwiXG5pbXBvcnQge1xuICBpc0Fic29sdXRlLFxuICBqb2luLFxuICBwYXJzZSxcbiAgcmVzb2x2ZSxcbiAgc2VwLFxufSBmcm9tIFwicGF0aFwiXG5pbXBvcnQge1xuICBlbXB0eURpcixcbiAgZW5zdXJlRGlyLFxufSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgR0FSREVOX0RJUl9OQU1FIH0gZnJvbSBcIi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IENvbmZpZ3VyYXRpb25FcnJvciB9IGZyb20gXCIuL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHtcbiAgQnVpbGRDb3B5U3BlYyxcbiAgTW9kdWxlLFxuICBnZXRNb2R1bGVLZXksXG59IGZyb20gXCIuL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyB6aXAgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCAqIGFzIGV4ZWNhIGZyb20gXCJleGVjYVwiXG5pbXBvcnQgeyBwbGF0Zm9ybSB9IGZyb20gXCJvc1wiXG5pbXBvcnQgeyB0b0N5Z3dpblBhdGggfSBmcm9tIFwiLi91dGlsL3V0aWxcIlxuXG4vLyBMYXppbHkgY29uc3RydWN0IGEgZGlyZWN0b3J5IG9mIG1vZHVsZXMgaW5zaWRlIHdoaWNoIGFsbCBidWlsZCBzdGVwcyBhcmUgcGVyZm9ybWVkLlxuXG5jb25zdCBidWlsZERpclJlbFBhdGggPSBqb2luKEdBUkRFTl9ESVJfTkFNRSwgXCJidWlsZFwiKVxuXG5leHBvcnQgY2xhc3MgQnVpbGREaXIge1xuICBjb25zdHJ1Y3Rvcihwcml2YXRlIHByb2plY3RSb290OiBzdHJpbmcsIHB1YmxpYyBidWlsZERpclBhdGg6IHN0cmluZykgeyB9XG5cbiAgc3RhdGljIGFzeW5jIGZhY3RvcnkocHJvamVjdFJvb3Q6IHN0cmluZykge1xuICAgIGNvbnN0IGJ1aWxkRGlyUGF0aCA9IGpvaW4ocHJvamVjdFJvb3QsIGJ1aWxkRGlyUmVsUGF0aClcbiAgICBhd2FpdCBlbnN1cmVEaXIoYnVpbGREaXJQYXRoKVxuICAgIHJldHVybiBuZXcgQnVpbGREaXIocHJvamVjdFJvb3QsIGJ1aWxkRGlyUGF0aClcbiAgfVxuXG4gIGFzeW5jIHN5bmNGcm9tU3JjKG1vZHVsZTogTW9kdWxlKSB7XG4gICAgYXdhaXQgdGhpcy5zeW5jKFxuICAgICAgcmVzb2x2ZSh0aGlzLnByb2plY3RSb290LCBtb2R1bGUucGF0aCkgKyBzZXAsXG4gICAgICBhd2FpdCB0aGlzLmJ1aWxkUGF0aChtb2R1bGUubmFtZSksXG4gICAgKVxuICB9XG5cbiAgYXN5bmMgc3luY0RlcGVuZGVuY3lQcm9kdWN0cyhtb2R1bGU6IE1vZHVsZSkge1xuICAgIGF3YWl0IHRoaXMuc3luY0Zyb21TcmMobW9kdWxlKVxuICAgIGNvbnN0IGJ1aWxkUGF0aCA9IGF3YWl0IHRoaXMuYnVpbGRQYXRoKG1vZHVsZS5uYW1lKVxuICAgIGNvbnN0IGJ1aWxkRGVwZW5kZW5jaWVzID0gYXdhaXQgbW9kdWxlLmJ1aWxkLmRlcGVuZGVuY2llc1xuICAgIGNvbnN0IGRlcGVuZGVuY3lDb25maWdzID0gbW9kdWxlLmJ1aWxkLmRlcGVuZGVuY2llcyB8fCBbXVxuXG4gICAgYXdhaXQgYmx1ZWJpcmRNYXAoemlwKGJ1aWxkRGVwZW5kZW5jaWVzLCBkZXBlbmRlbmN5Q29uZmlncyksIGFzeW5jIChbc291cmNlTW9kdWxlLCBkZXBDb25maWddKSA9PiB7XG4gICAgICBpZiAoIXNvdXJjZU1vZHVsZSB8fCAhZGVwQ29uZmlnIHx8ICFkZXBDb25maWcuY29weSkge1xuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3Qgc291cmNlQnVpbGRQYXRoID0gYXdhaXQgdGhpcy5idWlsZFBhdGgoZ2V0TW9kdWxlS2V5KHNvdXJjZU1vZHVsZS5uYW1lLCBzb3VyY2VNb2R1bGUucGx1Z2luKSlcblxuICAgICAgLy8gU3luYyB0byB0aGUgbW9kdWxlJ3MgdG9wLWxldmVsIGRpciBieSBkZWZhdWx0LlxuICAgICAgYXdhaXQgYmx1ZWJpcmRNYXAoZGVwQ29uZmlnLmNvcHksIChjb3B5OiBCdWlsZENvcHlTcGVjKSA9PiB7XG4gICAgICAgIGlmIChpc0Fic29sdXRlKGNvcHkuc291cmNlKSkge1xuICAgICAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoYFNvdXJjZSBwYXRoIGluIGJ1aWxkIGRlcGVuZGVuY3kgY29weSBzcGVjIG11c3QgYmUgYSByZWxhdGl2ZSBwYXRoYCwge1xuICAgICAgICAgICAgY29weVNwZWM6IGNvcHksXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChpc0Fic29sdXRlKGNvcHkudGFyZ2V0KSkge1xuICAgICAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoYFRhcmdldCBwYXRoIGluIGJ1aWxkIGRlcGVuZGVuY3kgY29weSBzcGVjIG11c3QgYmUgYSByZWxhdGl2ZSBwYXRoYCwge1xuICAgICAgICAgICAgY29weVNwZWM6IGNvcHksXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IHNvdXJjZVBhdGggPSBqb2luKHNvdXJjZUJ1aWxkUGF0aCwgY29weS5zb3VyY2UpXG4gICAgICAgIGNvbnN0IGRlc3RpbmF0aW9uUGF0aCA9IGpvaW4oYnVpbGRQYXRoLCBjb3B5LnRhcmdldClcbiAgICAgICAgcmV0dXJuIHRoaXMuc3luYyhzb3VyY2VQYXRoLCBkZXN0aW5hdGlvblBhdGgpXG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICBhc3luYyBjbGVhcigpIHtcbiAgICBhd2FpdCBlbXB0eURpcih0aGlzLmJ1aWxkRGlyUGF0aClcbiAgfVxuXG4gIGFzeW5jIGJ1aWxkUGF0aChtb2R1bGVOYW1lOiBzdHJpbmcpOiBQcm9taXNlPHN0cmluZz4ge1xuICAgIGNvbnN0IHBhdGggPSByZXNvbHZlKHRoaXMuYnVpbGREaXJQYXRoLCBtb2R1bGVOYW1lKVxuICAgIGF3YWl0IGVuc3VyZURpcihwYXRoKVxuICAgIHJldHVybiBwYXRoXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIHN5bmMoc291cmNlUGF0aDogc3RyaW5nLCBkZXN0aW5hdGlvblBhdGg6IHN0cmluZyk6IFByb21pc2U8dm9pZD4ge1xuICAgIGNvbnN0IGRlc3RpbmF0aW9uRGlyID0gcGFyc2UoZGVzdGluYXRpb25QYXRoKS5kaXJcbiAgICBhd2FpdCBlbnN1cmVEaXIoZGVzdGluYXRpb25EaXIpXG5cbiAgICBpZiAocGxhdGZvcm0oKSA9PT0gXCJ3aW4zMlwiKSB7XG4gICAgICAvLyB0aGlzIGlzIHNvIHRoYXQgdGhlIGN5Z3dpbi1iYXNlZCByc3luYyBjbGllbnQgY2FuIGRlYWwgd2l0aCB0aGUgcGF0aHNcbiAgICAgIHNvdXJjZVBhdGggPSB0b0N5Z3dpblBhdGgoc291cmNlUGF0aClcbiAgICAgIGRlc3RpbmF0aW9uUGF0aCA9IHRvQ3lnd2luUGF0aChkZXN0aW5hdGlvblBhdGgpXG4gICAgfVxuXG4gICAgLy8gdGhlIGNvcnJlY3Qgd2F5IHRvIGNvcHkgYWxsIGNvbnRlbnRzIG9mIGEgZm9sZGVyIGlzIHVzaW5nIGEgdHJhaWxpbmcgc2xhc2ggYW5kIG5vdCBhIHdpbGRjYXJkXG4gICAgc291cmNlUGF0aCA9IHN0cmlwV2lsZGNhcmQoc291cmNlUGF0aClcbiAgICBkZXN0aW5hdGlvblBhdGggPSBzdHJpcFdpbGRjYXJkKGRlc3RpbmF0aW9uUGF0aClcblxuICAgIGF3YWl0IGV4ZWNhKFwicnN5bmNcIiwgW1wiLXJwdGdvXCIsIHNvdXJjZVBhdGgsIGRlc3RpbmF0aW9uUGF0aF0pXG4gIH1cbn1cblxuZnVuY3Rpb24gc3RyaXBXaWxkY2FyZChwYXRoOiBzdHJpbmcpIHtcbiAgcmV0dXJuIHBhdGguZW5kc1dpdGgoXCIvKlwiKSA/IHBhdGguc2xpY2UoMCwgLTEpIDogcGF0aFxufVxuIl19 diff --git a/garden-service/build/cache.d.ts b/garden-service/build/cache.d.ts new file mode 100644 index 00000000000..6ff4412c029 --- /dev/null +++ b/garden-service/build/cache.d.ts @@ -0,0 +1,68 @@ +export declare type CacheKey = string[]; +export declare type CacheContext = string[]; +export declare type CurriedKey = string; +export declare type CacheValue = string | number | boolean | null | object; +export declare type CacheValues = Map; +/** + * A simple in-memory cache that additionally indexes keys in a tree by a seperate context key, so that keys + * can be invalidated based on surrounding context. + * + * For example, we can cache the version of a directory path, and then invalidate every cached key under a + * parent path: + * + * ``` + * const cache = new TreeCache() + * + * # The context parameter (last parameter) here is the path to the module source + * cache.set(["modules", "my-module-a"], module, ["modules", "module-path-a"]) + * cache.set(["modules", "my-module-b"], module, ["modules", "module-path-b"]) + * + * # Invalidates the cache for module-a + * cache.invalidate(["modules", "module-path-a"]) + * + * # Also invalidates the cache for module-a + * cache.invalidateUp(["modules", "module-path-a", "subdirectory"]) + * + * # Invalidates the cache for both modules + * cache.invalidateDown(["modules"]) + * ``` + * + * This is useful, for example, when listening for filesystem events to make sure cached items stay in + * sync after making changes to sources. + * + * A single cache entry can also have multiple invalidation contexts, which is helpful when a cache key + * can be invalidated by changes to multiple contexts (say for a module version, which should also be + * invalidated when dependencies are updated). + * + */ +export declare class TreeCache { + private readonly cache; + private readonly contextTree; + constructor(); + set(key: CacheKey, value: CacheValue, ...contexts: CacheContext[]): void; + get(key: CacheKey): CacheValue | undefined; + getOrThrow(key: CacheKey): CacheValue; + getByContext(context: CacheContext): CacheValues; + /** + * Delete a specific entry from the cache. + */ + delete(key: CacheKey): void; + /** + * Invalidates all cache entries whose context equals `context` + */ + invalidate(context: CacheContext): void; + /** + * Invalidates all cache entries where the given `context` starts with the entries' context + * (i.e. the whole path from the tree root down to the context leaf) + */ + invalidateUp(context: CacheContext): void; + /** + * Invalidates all cache entries whose context _starts_ with the given `context` + * (i.e. the context node and the whole tree below it) + */ + invalidateDown(context: CacheContext): void; + private getNode; + private clearNode; +} +export declare function pathToCacheContext(path: string): CacheContext; +//# sourceMappingURL=cache.d.ts.map \ No newline at end of file diff --git a/garden-service/build/cache.js b/garden-service/build/cache.js new file mode 100644 index 00000000000..e71b3e1a31f --- /dev/null +++ b/garden-service/build/cache.js @@ -0,0 +1,213 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const exceptions_1 = require("./exceptions"); +/** + * A simple in-memory cache that additionally indexes keys in a tree by a seperate context key, so that keys + * can be invalidated based on surrounding context. + * + * For example, we can cache the version of a directory path, and then invalidate every cached key under a + * parent path: + * + * ``` + * const cache = new TreeCache() + * + * # The context parameter (last parameter) here is the path to the module source + * cache.set(["modules", "my-module-a"], module, ["modules", "module-path-a"]) + * cache.set(["modules", "my-module-b"], module, ["modules", "module-path-b"]) + * + * # Invalidates the cache for module-a + * cache.invalidate(["modules", "module-path-a"]) + * + * # Also invalidates the cache for module-a + * cache.invalidateUp(["modules", "module-path-a", "subdirectory"]) + * + * # Invalidates the cache for both modules + * cache.invalidateDown(["modules"]) + * ``` + * + * This is useful, for example, when listening for filesystem events to make sure cached items stay in + * sync after making changes to sources. + * + * A single cache entry can also have multiple invalidation contexts, which is helpful when a cache key + * can be invalidated by changes to multiple contexts (say for a module version, which should also be + * invalidated when dependencies are updated). + * + */ +class TreeCache { + constructor() { + this.cache = new Map(); + this.contextTree = makeContextNode([]); + } + set(key, value, ...contexts) { + if (key.length === 0) { + throw new exceptions_1.ParameterError(`Cache key must have at least one part`, { key, contexts }); + } + if (contexts.length === 0) { + throw new exceptions_1.ParameterError(`Must specify at least one context`, { key, contexts }); + } + const curriedKey = curry(key); + let entry = this.cache.get(curriedKey); + if (entry === undefined) { + entry = { key, value, contexts: {} }; + this.cache.set(curriedKey, entry); + } + else { + // merge with the existing entry + entry.value = value; + } + contexts.forEach(c => entry.contexts[curry(c)] = c); + for (const context of Object.values(contexts)) { + let node = this.contextTree; + if (context.length === 0) { + throw new exceptions_1.ParameterError(`Context key must have at least one part`, { key, context }); + } + const contextKey = []; + for (const part of context) { + contextKey.push(part); + if (node.children[part]) { + node = node.children[part]; + } + else { + node = node.children[part] = makeContextNode(contextKey); + } + } + node.entries.add(curriedKey); + } + } + get(key) { + const entry = this.cache.get(curry(key)); + return entry ? entry.value : undefined; + } + getOrThrow(key) { + const value = this.get(key); + if (value === undefined) { + throw new exceptions_1.NotFoundError(`Could not find key ${key} in cache`, { key }); + } + return value; + } + getByContext(context) { + let pairs = []; + const node = this.getNode(context); + if (node) { + pairs = Array.from(node.entries).map(curriedKey => { + const entry = this.cache.get(curriedKey); + if (!entry) { + throw new exceptions_1.InternalError(`Invalid reference found in cache: ${curriedKey}`, { curriedKey }); + } + return [entry.key, entry.value]; + }); + } + return new Map(pairs); + } + /** + * Delete a specific entry from the cache. + */ + delete(key) { + const curriedKey = curry(key); + const entry = this.cache.get(curriedKey); + if (entry === undefined) { + return; + } + this.cache.delete(curriedKey); + // clear the entry from its contexts + for (const context of Object.values(entry.contexts)) { + const node = this.getNode(context); + node && node.entries.delete(curriedKey); + } + } + /** + * Invalidates all cache entries whose context equals `context` + */ + invalidate(context) { + const node = this.getNode(context); + if (node) { + // clear all cache entries on the node + this.clearNode(node, false); + } + } + /** + * Invalidates all cache entries where the given `context` starts with the entries' context + * (i.e. the whole path from the tree root down to the context leaf) + */ + invalidateUp(context) { + let node = this.contextTree; + for (const part of context) { + node = node.children[part]; + if (!node) { + break; + } + this.clearNode(node, false); + } + } + /** + * Invalidates all cache entries whose context _starts_ with the given `context` + * (i.e. the context node and the whole tree below it) + */ + invalidateDown(context) { + const node = this.getNode(context); + if (node) { + // clear all cache entries in the node and recursively through all child nodes + this.clearNode(node, true); + } + } + getNode(context) { + let node = this.contextTree; + for (const part of context) { + node = node.children[part]; + if (!node) { + // no cache keys under the given context + return; + } + } + return node; + } + clearNode(node, clearChildNodes) { + for (const curriedKey of node.entries) { + const entry = this.cache.get(curriedKey); + if (entry === undefined) { + return; + } + // also clear the invalidated entry from its other contexts + for (const context of Object.values(entry.contexts)) { + if (!lodash_1.isEqual(context, node.key)) { + const otherNode = this.getNode(context); + otherNode && otherNode.entries.delete(curriedKey); + } + } + this.cache.delete(curriedKey); + } + node.entries = new Set(); + if (clearChildNodes) { + for (const child of Object.values(node.children)) { + this.clearNode(child, true); + } + } + } +} +exports.TreeCache = TreeCache; +function makeContextNode(key) { + return { + key, + children: {}, + entries: new Set(), + }; +} +function curry(key) { + return JSON.stringify(key); +} +function pathToCacheContext(path) { + const parsed = path_1.parse(path_1.normalize(path)); + return ["path", ...parsed.dir.split(path_1.sep)]; +} +exports.pathToCacheContext = pathToCacheContext; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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SSxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsRUFBRTtnQkFDaEQsSUFBSSxDQUFDLFNBQVMsQ0FBQyxLQUFLLEVBQUUsSUFBSSxDQUFDLENBQUE7YUFDNUI7U0FDRjtJQUNILENBQUM7Q0FDRjtBQTVMRCw4QkE0TEM7QUFFRCxTQUFTLGVBQWUsQ0FBQyxHQUFpQjtJQUN4QyxPQUFPO1FBQ0wsR0FBRztRQUNILFFBQVEsRUFBRSxFQUFFO1FBQ1osT0FBTyxFQUFFLElBQUksR0FBRyxFQUFjO0tBQy9CLENBQUE7QUFDSCxDQUFDO0FBRUQsU0FBUyxLQUFLLENBQUMsR0FBNEI7SUFDekMsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0FBQzVCLENBQUM7QUFFRCxTQUFnQixrQkFBa0IsQ0FBQyxJQUFZO0lBQzdDLE1BQU0sTUFBTSxHQUFHLFlBQUssQ0FBQyxnQkFBUyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUE7SUFDckMsT0FBTyxDQUFDLE1BQU0sRUFBRSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLFVBQUcsQ0FBQyxDQUFDLENBQUE7QUFDM0MsQ0FBQztBQUhELGdEQUdDIiwiZmlsZSI6ImNhY2hlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIGlzRXF1YWwsXG59IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHtcbiAgbm9ybWFsaXplLFxuICBwYXJzZSxcbiAgc2VwLFxufSBmcm9tIFwicGF0aFwiXG5pbXBvcnQge1xuICBJbnRlcm5hbEVycm9yLFxuICBOb3RGb3VuZEVycm9yLFxuICBQYXJhbWV0ZXJFcnJvcixcbn0gZnJvbSBcIi4vZXhjZXB0aW9uc1wiXG5cbmV4cG9ydCB0eXBlIENhY2hlS2V5ID0gc3RyaW5nW11cbmV4cG9ydCB0eXBlIENhY2hlQ29udGV4dCA9IHN0cmluZ1tdXG5leHBvcnQgdHlwZSBDdXJyaWVkS2V5ID0gc3RyaW5nXG5cbmV4cG9ydCB0eXBlIENhY2hlVmFsdWUgPSBzdHJpbmcgfCBudW1iZXIgfCBib29sZWFuIHwgbnVsbCB8IG9iamVjdFxuZXhwb3J0IHR5cGUgQ2FjaGVWYWx1ZXMgPSBNYXA8Q2FjaGVLZXksIENhY2hlVmFsdWU+XG5cbmludGVyZmFjZSBDYWNoZUVudHJ5IHtcbiAga2V5OiBDYWNoZUtleVxuICB2YWx1ZTogQ2FjaGVWYWx1ZVxuICBjb250ZXh0czogeyBbY3VycmllZENvbnRleHQ6IHN0cmluZ106IENhY2hlQ29udGV4dCB9XG59XG5cbnR5cGUgQ2FjaGVFbnRyaWVzID0gTWFwPEN1cnJpZWRLZXksIENhY2hlRW50cnk+XG5cbmludGVyZmFjZSBDb250ZXh0Tm9kZSB7XG4gIGtleTogQ2FjaGVDb250ZXh0XG4gIGNoaWxkcmVuOiB7IFtjb250ZXh0UGFydDogc3RyaW5nXTogQ29udGV4dE5vZGUgfVxuICBlbnRyaWVzOiBTZXQ8Q3VycmllZEtleT5cbn1cblxuLyoqXG4gKiAgQSBzaW1wbGUgaW4tbWVtb3J5IGNhY2hlIHRoYXQgYWRkaXRpb25hbGx5IGluZGV4ZXMga2V5cyBpbiBhIHRyZWUgYnkgYSBzZXBlcmF0ZSBjb250ZXh0IGtleSwgc28gdGhhdCBrZXlzXG4gKiAgY2FuIGJlIGludmFsaWRhdGVkIGJhc2VkIG9uIHN1cnJvdW5kaW5nIGNvbnRleHQuXG4gKlxuICogIEZvciBleGFtcGxlLCB3ZSBjYW4gY2FjaGUgdGhlIHZlcnNpb24gb2YgYSBkaXJlY3RvcnkgcGF0aCwgYW5kIHRoZW4gaW52YWxpZGF0ZSBldmVyeSBjYWNoZWQga2V5IHVuZGVyIGFcbiAqICBwYXJlbnQgcGF0aDpcbiAqXG4gKiAgYGBgXG4gKiAgY29uc3QgY2FjaGUgPSBuZXcgVHJlZUNhY2hlKClcbiAqXG4gKiAgIyBUaGUgY29udGV4dCBwYXJhbWV0ZXIgKGxhc3QgcGFyYW1ldGVyKSBoZXJlIGlzIHRoZSBwYXRoIHRvIHRoZSBtb2R1bGUgc291cmNlXG4gKiAgY2FjaGUuc2V0KFtcIm1vZHVsZXNcIiwgXCJteS1tb2R1bGUtYVwiXSwgbW9kdWxlLCBbXCJtb2R1bGVzXCIsIFwibW9kdWxlLXBhdGgtYVwiXSlcbiAqICBjYWNoZS5zZXQoW1wibW9kdWxlc1wiLCBcIm15LW1vZHVsZS1iXCJdLCBtb2R1bGUsIFtcIm1vZHVsZXNcIiwgXCJtb2R1bGUtcGF0aC1iXCJdKVxuICpcbiAqICAjIEludmFsaWRhdGVzIHRoZSBjYWNoZSBmb3IgbW9kdWxlLWFcbiAqICBjYWNoZS5pbnZhbGlkYXRlKFtcIm1vZHVsZXNcIiwgXCJtb2R1bGUtcGF0aC1hXCJdKVxuICpcbiAqICAjIEFsc28gaW52YWxpZGF0ZXMgdGhlIGNhY2hlIGZvciBtb2R1bGUtYVxuICogIGNhY2hlLmludmFsaWRhdGVVcChbXCJtb2R1bGVzXCIsIFwibW9kdWxlLXBhdGgtYVwiLCBcInN1YmRpcmVjdG9yeVwiXSlcbiAqXG4gKiAgIyBJbnZhbGlkYXRlcyB0aGUgY2FjaGUgZm9yIGJvdGggbW9kdWxlc1xuICogIGNhY2hlLmludmFsaWRhdGVEb3duKFtcIm1vZHVsZXNcIl0pXG4gKiAgYGBgXG4gKlxuICogIFRoaXMgaXMgdXNlZnVsLCBmb3IgZXhhbXBsZSwgd2hlbiBsaXN0ZW5pbmcgZm9yIGZpbGVzeXN0ZW0gZXZlbnRzIHRvIG1ha2Ugc3VyZSBjYWNoZWQgaXRlbXMgc3RheSBpblxuICogIHN5bmMgYWZ0ZXIgbWFraW5nIGNoYW5nZXMgdG8gc291cmNlcy5cbiAqXG4gKiAgQSBzaW5nbGUgY2FjaGUgZW50cnkgY2FuIGFsc28gaGF2ZSBtdWx0aXBsZSBpbnZhbGlkYXRpb24gY29udGV4dHMsIHdoaWNoIGlzIGhlbHBmdWwgd2hlbiBhIGNhY2hlIGtleVxuICogIGNhbiBiZSBpbnZhbGlkYXRlZCBieSBjaGFuZ2VzIHRvIG11bHRpcGxlIGNvbnRleHRzIChzYXkgZm9yIGEgbW9kdWxlIHZlcnNpb24sIHdoaWNoIHNob3VsZCBhbHNvIGJlXG4gKiAgaW52YWxpZGF0ZWQgd2hlbiBkZXBlbmRlbmNpZXMgYXJlIHVwZGF0ZWQpLlxuICpcbiAqL1xuZXhwb3J0IGNsYXNzIFRyZWVDYWNoZSB7XG4gIHByaXZhdGUgcmVhZG9ubHkgY2FjaGU6IENhY2hlRW50cmllc1xuICBwcml2YXRlIHJlYWRvbmx5IGNvbnRleHRUcmVlOiBDb250ZXh0Tm9kZVxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuY2FjaGUgPSBuZXcgTWFwPEN1cnJpZWRLZXksIENhY2hlRW50cnk+KClcbiAgICB0aGlzLmNvbnRleHRUcmVlID0gbWFrZUNvbnRleHROb2RlKFtdKVxuICB9XG5cbiAgc2V0KGtleTogQ2FjaGVLZXksIHZhbHVlOiBDYWNoZVZhbHVlLCAuLi5jb250ZXh0czogQ2FjaGVDb250ZXh0W10pIHtcbiAgICBpZiAoa2V5Lmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBDYWNoZSBrZXkgbXVzdCBoYXZlIGF0IGxlYXN0IG9uZSBwYXJ0YCwgeyBrZXksIGNvbnRleHRzIH0pXG4gICAgfVxuXG4gICAgaWYgKGNvbnRleHRzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBNdXN0IHNwZWNpZnkgYXQgbGVhc3Qgb25lIGNvbnRleHRgLCB7IGtleSwgY29udGV4dHMgfSlcbiAgICB9XG5cbiAgICBjb25zdCBjdXJyaWVkS2V5ID0gY3Vycnkoa2V5KVxuICAgIGxldCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGN1cnJpZWRLZXkpXG5cbiAgICBpZiAoZW50cnkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgZW50cnkgPSB7IGtleSwgdmFsdWUsIGNvbnRleHRzOiB7fSB9XG4gICAgICB0aGlzLmNhY2hlLnNldChjdXJyaWVkS2V5LCBlbnRyeSlcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gbWVyZ2Ugd2l0aCB0aGUgZXhpc3RpbmcgZW50cnlcbiAgICAgIGVudHJ5LnZhbHVlID0gdmFsdWVcbiAgICB9XG5cbiAgICBjb250ZXh0cy5mb3JFYWNoKGMgPT4gZW50cnkhLmNvbnRleHRzW2N1cnJ5KGMpXSA9IGMpXG5cbiAgICBmb3IgKGNvbnN0IGNvbnRleHQgb2YgT2JqZWN0LnZhbHVlcyhjb250ZXh0cykpIHtcbiAgICAgIGxldCBub2RlID0gdGhpcy5jb250ZXh0VHJlZVxuXG4gICAgICBpZiAoY29udGV4dC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBDb250ZXh0IGtleSBtdXN0IGhhdmUgYXQgbGVhc3Qgb25lIHBhcnRgLCB7IGtleSwgY29udGV4dCB9KVxuICAgICAgfVxuXG4gICAgICBjb25zdCBjb250ZXh0S2V5OiBDYWNoZUNvbnRleHQgPSBbXVxuXG4gICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgY29udGV4dCkge1xuICAgICAgICBjb250ZXh0S2V5LnB1c2gocGFydClcblxuICAgICAgICBpZiAobm9kZS5jaGlsZHJlbltwYXJ0XSkge1xuICAgICAgICAgIG5vZGUgPSBub2RlLmNoaWxkcmVuW3BhcnRdXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bcGFydF0gPSBtYWtlQ29udGV4dE5vZGUoY29udGV4dEtleSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBub2RlLmVudHJpZXMuYWRkKGN1cnJpZWRLZXkpXG4gICAgfVxuICB9XG5cbiAgZ2V0KGtleTogQ2FjaGVLZXkpOiBDYWNoZVZhbHVlIHwgdW5kZWZpbmVkIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGN1cnJ5KGtleSkpXG4gICAgcmV0dXJuIGVudHJ5ID8gZW50cnkudmFsdWUgOiB1bmRlZmluZWRcbiAgfVxuXG4gIGdldE9yVGhyb3coa2V5OiBDYWNoZUtleSk6IENhY2hlVmFsdWUge1xuICAgIGNvbnN0IHZhbHVlID0gdGhpcy5nZXQoa2V5KVxuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihgQ291bGQgbm90IGZpbmQga2V5ICR7a2V5fSBpbiBjYWNoZWAsIHsga2V5IH0pXG4gICAgfVxuICAgIHJldHVybiB2YWx1ZVxuICB9XG5cbiAgZ2V0QnlDb250ZXh0KGNvbnRleHQ6IENhY2hlQ29udGV4dCk6IENhY2hlVmFsdWVzIHtcbiAgICBsZXQgcGFpcnM6IFtDYWNoZUtleSwgQ2FjaGVWYWx1ZV1bXSA9IFtdXG5cbiAgICBjb25zdCBub2RlID0gdGhpcy5nZXROb2RlKGNvbnRleHQpXG5cbiAgICBpZiAobm9kZSkge1xuICAgICAgcGFpcnMgPSBBcnJheS5mcm9tKG5vZGUuZW50cmllcykubWFwKGN1cnJpZWRLZXkgPT4ge1xuICAgICAgICBjb25zdCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGN1cnJpZWRLZXkpXG4gICAgICAgIGlmICghZW50cnkpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihgSW52YWxpZCByZWZlcmVuY2UgZm91bmQgaW4gY2FjaGU6ICR7Y3VycmllZEtleX1gLCB7IGN1cnJpZWRLZXkgfSlcbiAgICAgICAgfVxuICAgICAgICByZXR1cm4gPFtDYWNoZUtleSwgQ2FjaGVWYWx1ZV0+W2VudHJ5LmtleSwgZW50cnkudmFsdWVdXG4gICAgICB9KVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgTWFwPENhY2hlS2V5LCBDYWNoZVZhbHVlPihwYWlycylcbiAgfVxuXG4gIC8qKlxuICAgKiBEZWxldGUgYSBzcGVjaWZpYyBlbnRyeSBmcm9tIHRoZSBjYWNoZS5cbiAgICovXG4gIGRlbGV0ZShrZXk6IENhY2hlS2V5KSB7XG4gICAgY29uc3QgY3VycmllZEtleSA9IGN1cnJ5KGtleSlcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGN1cnJpZWRLZXkpXG5cbiAgICBpZiAoZW50cnkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgcmV0dXJuXG4gICAgfVxuXG4gICAgdGhpcy5jYWNoZS5kZWxldGUoY3VycmllZEtleSlcblxuICAgIC8vIGNsZWFyIHRoZSBlbnRyeSBmcm9tIGl0cyBjb250ZXh0c1xuICAgIGZvciAoY29uc3QgY29udGV4dCBvZiBPYmplY3QudmFsdWVzKGVudHJ5LmNvbnRleHRzKSkge1xuICAgICAgY29uc3Qgbm9kZSA9IHRoaXMuZ2V0Tm9kZShjb250ZXh0KVxuICAgICAgbm9kZSAmJiBub2RlLmVudHJpZXMuZGVsZXRlKGN1cnJpZWRLZXkpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEludmFsaWRhdGVzIGFsbCBjYWNoZSBlbnRyaWVzIHdob3NlIGNvbnRleHQgZXF1YWxzIGBjb250ZXh0YFxuICAgKi9cbiAgaW52YWxpZGF0ZShjb250ZXh0OiBDYWNoZUNvbnRleHQpIHtcbiAgICBjb25zdCBub2RlID0gdGhpcy5nZXROb2RlKGNvbnRleHQpXG5cbiAgICBpZiAobm9kZSkge1xuICAgICAgLy8gY2xlYXIgYWxsIGNhY2hlIGVudHJpZXMgb24gdGhlIG5vZGVcbiAgICAgIHRoaXMuY2xlYXJOb2RlKG5vZGUsIGZhbHNlKVxuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBJbnZhbGlkYXRlcyBhbGwgY2FjaGUgZW50cmllcyB3aGVyZSB0aGUgZ2l2ZW4gYGNvbnRleHRgIHN0YXJ0cyB3aXRoIHRoZSBlbnRyaWVzJyBjb250ZXh0XG4gICAqIChpLmUuIHRoZSB3aG9sZSBwYXRoIGZyb20gdGhlIHRyZWUgcm9vdCBkb3duIHRvIHRoZSBjb250ZXh0IGxlYWYpXG4gICAqL1xuICBpbnZhbGlkYXRlVXAoY29udGV4dDogQ2FjaGVDb250ZXh0KSB7XG4gICAgbGV0IG5vZGUgPSB0aGlzLmNvbnRleHRUcmVlXG5cbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgY29udGV4dCkge1xuICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bcGFydF1cbiAgICAgIGlmICghbm9kZSkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgICAgdGhpcy5jbGVhck5vZGUobm9kZSwgZmFsc2UpXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEludmFsaWRhdGVzIGFsbCBjYWNoZSBlbnRyaWVzIHdob3NlIGNvbnRleHQgX3N0YXJ0c18gd2l0aCB0aGUgZ2l2ZW4gYGNvbnRleHRgXG4gICAqIChpLmUuIHRoZSBjb250ZXh0IG5vZGUgYW5kIHRoZSB3aG9sZSB0cmVlIGJlbG93IGl0KVxuICAgKi9cbiAgaW52YWxpZGF0ZURvd24oY29udGV4dDogQ2FjaGVDb250ZXh0KSB7XG4gICAgY29uc3Qgbm9kZSA9IHRoaXMuZ2V0Tm9kZShjb250ZXh0KVxuXG4gICAgaWYgKG5vZGUpIHtcbiAgICAgIC8vIGNsZWFyIGFsbCBjYWNoZSBlbnRyaWVzIGluIHRoZSBub2RlIGFuZCByZWN1cnNpdmVseSB0aHJvdWdoIGFsbCBjaGlsZCBub2Rlc1xuICAgICAgdGhpcy5jbGVhck5vZGUobm9kZSwgdHJ1ZSlcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldE5vZGUoY29udGV4dDogQ2FjaGVDb250ZXh0KSB7XG4gICAgbGV0IG5vZGUgPSB0aGlzLmNvbnRleHRUcmVlXG5cbiAgICBmb3IgKGNvbnN0IHBhcnQgb2YgY29udGV4dCkge1xuICAgICAgbm9kZSA9IG5vZGUuY2hpbGRyZW5bcGFydF1cblxuICAgICAgaWYgKCFub2RlKSB7XG4gICAgICAgIC8vIG5vIGNhY2hlIGtleXMgdW5kZXIgdGhlIGdpdmVuIGNvbnRleHRcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgcmV0dXJuIG5vZGVcbiAgfVxuXG4gIHByaXZhdGUgY2xlYXJOb2RlKG5vZGU6IENvbnRleHROb2RlLCBjbGVhckNoaWxkTm9kZXM6IGJvb2xlYW4pIHtcbiAgICBmb3IgKGNvbnN0IGN1cnJpZWRLZXkgb2Ygbm9kZS5lbnRyaWVzKSB7XG4gICAgICBjb25zdCBlbnRyeSA9IHRoaXMuY2FjaGUuZ2V0KGN1cnJpZWRLZXkpXG5cbiAgICAgIGlmIChlbnRyeSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICAvLyBhbHNvIGNsZWFyIHRoZSBpbnZhbGlkYXRlZCBlbnRyeSBmcm9tIGl0cyBvdGhlciBjb250ZXh0c1xuICAgICAgZm9yIChjb25zdCBjb250ZXh0IG9mIE9iamVjdC52YWx1ZXMoZW50cnkuY29udGV4dHMpKSB7XG4gICAgICAgIGlmICghaXNFcXVhbChjb250ZXh0LCBub2RlLmtleSkpIHtcbiAgICAgICAgICBjb25zdCBvdGhlck5vZGUgPSB0aGlzLmdldE5vZGUoY29udGV4dClcbiAgICAgICAgICBvdGhlck5vZGUgJiYgb3RoZXJOb2RlLmVudHJpZXMuZGVsZXRlKGN1cnJpZWRLZXkpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgdGhpcy5jYWNoZS5kZWxldGUoY3VycmllZEtleSlcbiAgICB9XG5cbiAgICBub2RlLmVudHJpZXMgPSBuZXcgU2V0PEN1cnJpZWRLZXk+KClcblxuICAgIGlmIChjbGVhckNoaWxkTm9kZXMpIHtcbiAgICAgIGZvciAoY29uc3QgY2hpbGQgb2YgT2JqZWN0LnZhbHVlcyhub2RlLmNoaWxkcmVuKSkge1xuICAgICAgICB0aGlzLmNsZWFyTm9kZShjaGlsZCwgdHJ1ZSlcbiAgICAgIH1cbiAgICB9XG4gIH1cbn1cblxuZnVuY3Rpb24gbWFrZUNvbnRleHROb2RlKGtleTogQ2FjaGVDb250ZXh0KTogQ29udGV4dE5vZGUge1xuICByZXR1cm4ge1xuICAgIGtleSxcbiAgICBjaGlsZHJlbjoge30sXG4gICAgZW50cmllczogbmV3IFNldDxDdXJyaWVkS2V5PigpLFxuICB9XG59XG5cbmZ1bmN0aW9uIGN1cnJ5KGtleTogQ2FjaGVLZXkgfCBDYWNoZUNvbnRleHQpIHtcbiAgcmV0dXJuIEpTT04uc3RyaW5naWZ5KGtleSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHBhdGhUb0NhY2hlQ29udGV4dChwYXRoOiBzdHJpbmcpOiBDYWNoZUNvbnRleHQge1xuICBjb25zdCBwYXJzZWQgPSBwYXJzZShub3JtYWxpemUocGF0aCkpXG4gIHJldHVybiBbXCJwYXRoXCIsIC4uLnBhcnNlZC5kaXIuc3BsaXQoc2VwKV1cbn1cbiJdfQ== diff --git a/garden-service/build/cli/cli.d.ts b/garden-service/build/cli/cli.d.ts new file mode 100644 index 00000000000..fd6d91b967c --- /dev/null +++ b/garden-service/build/cli/cli.d.ts @@ -0,0 +1,28 @@ +import { BooleanParameter, Command, ChoicesParameter, Parameter, StringParameter, EnvironmentOption } from "../commands/base"; +import { GardenError } from "../exceptions"; +import { GardenConfig } from "../config/base"; +export declare const MOCK_CONFIG: GardenConfig; +export declare const GLOBAL_OPTIONS: { + root: StringParameter; + silent: BooleanParameter; + env: EnvironmentOption; + loglevel: ChoicesParameter; + output: ChoicesParameter; +}; +export interface ParseResults { + argv: any; + code: number; + errors: (GardenError | Error)[]; +} +export declare class GardenCli { + program: any; + commands: { + [key: string]: Command; + }; + constructor(); + addGlobalOption(key: string, option: Parameter): void; + addCommand(command: Command, program: any): void; + parse(): Promise; +} +export declare function run(): Promise; +//# sourceMappingURL=cli.d.ts.map \ No newline at end of file diff --git a/garden-service/build/cli/cli.js b/garden-service/build/cli/cli.js new file mode 100644 index 00000000000..17eeb036b22 --- /dev/null +++ b/garden-service/build/cli/cli.js @@ -0,0 +1,281 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const sywac = require("sywac"); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const js_yaml_1 = require("js-yaml"); +const commands_1 = require("../commands/commands"); +const stringify = require("json-stringify-safe"); +const util_1 = require("../util/util"); +const base_1 = require("../commands/base"); +const exceptions_1 = require("../exceptions"); +const garden_1 = require("../garden"); +const logger_1 = require("../logger/logger"); +const log_node_1 = require("../logger/log-node"); +const basic_terminal_writer_1 = require("../logger/writers/basic-terminal-writer"); +const fancy_terminal_writer_1 = require("../logger/writers/fancy-terminal-writer"); +const file_writer_1 = require("../logger/writers/file-writer"); +const helpers_1 = require("./helpers"); +const project_1 = require("../config/project"); +const constants_1 = require("../constants"); +const OUTPUT_RENDERERS = { + json: (data) => { + return stringify(data, null, 2); + }, + yaml: (data) => { + return js_yaml_1.safeDump(data, { noRefs: true, skipInvalid: true }); + }, +}; +const logLevelKeys = util_1.getEnumKeys(log_node_1.LogLevel); +// Allow string or numeric log levels +const logLevelChoices = [...logLevelKeys, ...lodash_1.range(logLevelKeys.length).map(String)]; +const getLogLevelFromArg = (level) => { + const lvl = parseInt(level, 10); + if (lvl) { + return lvl; + } + return log_node_1.LogLevel[level]; +}; +// For initializing garden without a project config +exports.MOCK_CONFIG = { + version: "0", + dirname: "/", + path: process.cwd(), + project: { + name: "mock-project", + defaultEnvironment: "local", + environments: project_1.defaultEnvironments, + environmentDefaults: { + providers: [ + { + name: "local-kubernetes", + }, + ], + variables: {}, + }, + }, +}; +exports.GLOBAL_OPTIONS = { + root: new base_1.StringParameter({ + alias: "r", + help: "Override project root directory (defaults to working directory).", + defaultValue: process.cwd(), + }), + silent: new base_1.BooleanParameter({ + alias: "s", + help: "Suppress log output.", + defaultValue: false, + }), + env: new base_1.EnvironmentOption(), + loglevel: new base_1.ChoicesParameter({ + alias: "l", + choices: logLevelChoices, + help: "Set logger level. Values can be either string or numeric and are prioritized from 0 to 5 " + + "(highest to lowest) as follows: error: 0, warn: 1, info: 2, verbose: 3, debug: 4, silly: 5", + hints: "[enum] [default: info] [error || 0, warn || 1, info || 2, verbose || 3, debug || 4, silly || 5]", + defaultValue: log_node_1.LogLevel[log_node_1.LogLevel.info], + }), + output: new base_1.ChoicesParameter({ + alias: "o", + choices: Object.keys(OUTPUT_RENDERERS), + help: "Output command result in specified format (note: disables progress logging).", + }), +}; +const GLOBAL_OPTIONS_GROUP_NAME = "Global options"; +const DEFAULT_CLI_LOGGER_TYPE = logger_1.LoggerType.fancy; +class GardenCli { + constructor() { + this.commands = {}; + const version = require("../../package.json").version; + this.program = sywac + .help("-h, --help", { + group: GLOBAL_OPTIONS_GROUP_NAME, + implicitCommand: false, + }) + .version("-v, --version", { + version, + group: GLOBAL_OPTIONS_GROUP_NAME, + implicitCommand: false, + }) + .showHelpByDefault() + .check((argv, _ctx) => { + // NOTE: Need to mutate argv! + lodash_1.merge(argv, helpers_1.falsifyConflictingParams(argv, exports.GLOBAL_OPTIONS)); + }) + .style(helpers_1.styleConfig); + const commands = commands_1.coreCommands; + const globalOptions = Object.entries(exports.GLOBAL_OPTIONS); + commands.forEach(command => this.addCommand(command, this.program)); + globalOptions.forEach(([key, opt]) => this.addGlobalOption(key, opt)); + } + addGlobalOption(key, option) { + this.program.option(helpers_1.getOptionSynopsis(key, option), Object.assign({}, helpers_1.prepareOptionConfig(option), { group: GLOBAL_OPTIONS_GROUP_NAME })); + } + addCommand(command, program) { + const fullName = command.getFullName(); + if (this.commands[fullName]) { + // For now we don't allow multiple definitions of the same command. We may want to revisit this later. + throw new exceptions_1.PluginError(`Multiple definitions of command "${fullName}"`, {}); + } + this.commands[fullName] = command; + const { arguments: args = {}, loggerType = DEFAULT_CLI_LOGGER_TYPE, options = {}, subCommands, } = command; + const argKeys = helpers_1.getKeys(args); + const optKeys = helpers_1.getKeys(options); + const globalKeys = helpers_1.getKeys(exports.GLOBAL_OPTIONS); + const dupKeys = lodash_1.intersection(optKeys, globalKeys); + if (dupKeys.length > 0) { + throw new exceptions_1.PluginError(`Global option(s) ${dupKeys.join(" ")} cannot be redefined`, {}); + } + const action = (argv, cliContext) => __awaiter(this, void 0, void 0, function* () { + // Sywac returns positional args and options in a single object which we separate into args and opts + const parsedArgs = helpers_1.filterByKeys(argv, argKeys); + const parsedOpts = helpers_1.filterByKeys(argv, optKeys.concat(globalKeys)); + const root = path_1.resolve(process.cwd(), parsedOpts.root); + const { env, loglevel, silent, output } = parsedOpts; + // Init logger + const level = getLogLevelFromArg(loglevel); + let writers = []; + if (!silent && !output && loggerType !== logger_1.LoggerType.quiet) { + if (loggerType === logger_1.LoggerType.fancy) { + writers.push(new fancy_terminal_writer_1.FancyTerminalWriter()); + } + else if (loggerType === logger_1.LoggerType.basic) { + writers.push(new basic_terminal_writer_1.BasicTerminalWriter()); + } + } + const logger = logger_1.Logger.initialize({ level, writers }); + let garden; + let result; + do { + const contextOpts = { env, logger }; + if (command.noProject) { + contextOpts.config = exports.MOCK_CONFIG; + } + garden = yield garden_1.Garden.factory(root, contextOpts); + // TODO: enforce that commands always output DeepPrimitiveMap + result = yield command.action({ + garden, + args: parsedArgs, + opts: parsedOpts, + }); + } while (result.restartRequired); + // We attach the action result to cli context so that we can process it in the parse method + cliContext.details.result = result; + }); + // Command specific positional args and options are set inside the builder function + const setup = parser => { + subCommands.forEach(subCommandCls => this.addCommand(new subCommandCls(command), parser)); + argKeys.forEach(key => parser.positional(helpers_1.getArgSynopsis(key, args[key]), helpers_1.prepareArgConfig(args[key]))); + optKeys.forEach(key => parser.option(helpers_1.getOptionSynopsis(key, options[key]), helpers_1.prepareOptionConfig(options[key]))); + // We only check for invalid flags for the last command since it might contain flags that + // the parent is unaware of, thus causing the check to fail for the parent + if (subCommands.length < 1) { + parser.check(helpers_1.failOnInvalidOptions); + } + return parser; + }; + const commandConfig = { + setup, + aliases: command.alias, + desc: command.help, + run: action, + }; + program.command(command.name, commandConfig); + } + parse() { + return __awaiter(this, void 0, void 0, function* () { + const parseResult = yield this.program.parse(); + const { argv, details, errors, output: cliOutput } = parseResult; + const { result: commandResult } = details; + const { output } = argv; + let { code } = parseResult; + let logger; + // Note: Circumvents an issue where the process exits before the output is fully flushed. + // Needed for output renderers and Winston (see: https://github.com/winstonjs/winston/issues/228) + const waitForOutputFlush = () => util_1.sleep(100); + // Logger might not have been initialised if process exits early + try { + logger = logger_1.getLogger(); + } + catch (_) { + logger = logger_1.Logger.initialize({ + level: log_node_1.LogLevel.info, + writers: [new basic_terminal_writer_1.BasicTerminalWriter()], + }); + } + // --help or --version options were called so we log the cli output and exit + if (cliOutput && errors.length < 1) { + logger.stop(); + console.log(cliOutput); + // fix issue where sywac returns exit code 0 even when a command doesn't exist + if (!argv.h && !argv.help) { + code = 1; + } + process.exit(code); + } + const gardenErrors = errors + .map(exceptions_1.toGardenError) + .concat((commandResult && commandResult.errors) || []); + // --output option set + if (output) { + const renderer = OUTPUT_RENDERERS[output]; + if (gardenErrors.length > 0) { + console.error(renderer({ success: false, errors: gardenErrors })); + } + else { + console.log(renderer(Object.assign({ success: true }, commandResult))); + } + yield waitForOutputFlush(); + } + if (gardenErrors.length > 0) { + gardenErrors.forEach(error => logger.error({ + msg: error.message, + error, + })); + if (logger.writers.find(w => w instanceof file_writer_1.FileWriter)) { + logger.info(`\nSee ${constants_1.ERROR_LOG_FILENAME} for detailed error message`); + yield waitForOutputFlush(); + } + code = 1; + } + logger.stop(); + return { argv, code, errors }; + }); + } +} +exports.GardenCli = GardenCli; +function run() { + return __awaiter(this, void 0, void 0, function* () { + let code; + try { + const cli = new GardenCli(); + const result = yield cli.parse(); + code = result.code; + } + catch (err) { + console.log(err); + code = 1; + } + finally { + util_1.shutdown(code); + } + }); +} +exports.run = run; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQyxNQUFNLEdBQUcsQ0FBQyxFQUFFO2dCQUMzQixZQUFZLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQztvQkFDekMsR0FBRyxFQUFFLEtBQUssQ0FBQyxPQUFPO29CQUNsQixLQUFLO2lCQUNOLENBQUMsQ0FBQyxDQUFBO2dCQUVILElBQUksTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLFlBQVksd0JBQVUsQ0FBQyxFQUFFO29CQUNyRCxNQUFNLENBQUMsSUFBSSxDQUFDLFNBQVMsOEJBQWtCLDZCQUE2QixDQUFDLENBQUE7b0JBQ3JFLE1BQU0sa0JBQWtCLEVBQUUsQ0FBQTtpQkFDM0I7Z0JBRUQsSUFBSSxHQUFHLENBQUMsQ0FBQTthQUNUO1lBRUQsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO1lBQ2IsT0FBTyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUE7UUFDL0IsQ0FBQztLQUFBO0NBRUY7QUFwTUQsOEJBb01DO0FBRUQsU0FBc0IsR0FBRzs7UUFDdkIsSUFBSSxJQUFJLENBQUE7UUFDUixJQUFJO1lBQ0YsTUFBTSxHQUFHLEdBQUcsSUFBSSxTQUFTLEVBQUUsQ0FBQTtZQUMzQixNQUFNLE1BQU0sR0FBRyxNQUFNLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQTtZQUNoQyxJQUFJLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQTtTQUNuQjtRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osT0FBTyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUNoQixJQUFJLEdBQUcsQ0FBQyxDQUFBO1NBQ1Q7Z0JBQVM7WUFDUixlQUFRLENBQUMsSUFBSSxDQUFDLENBQUE7U0FDZjtJQUNILENBQUM7Q0FBQTtBQVpELGtCQVlDIiwiZmlsZSI6ImNsaS9jbGkuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgc3l3YWMgZnJvbSBcInN5d2FjXCJcbmltcG9ydCB7IG1lcmdlLCBpbnRlcnNlY3Rpb24sIHJhbmdlIH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHsgc2FmZUR1bXAgfSBmcm9tIFwianMteWFtbFwiXG5pbXBvcnQgeyBjb3JlQ29tbWFuZHMgfSBmcm9tIFwiLi4vY29tbWFuZHMvY29tbWFuZHNcIlxuaW1wb3J0IHN0cmluZ2lmeSA9IHJlcXVpcmUoXCJqc29uLXN0cmluZ2lmeS1zYWZlXCIpXG5cbmltcG9ydCB7IERlZXBQcmltaXRpdmVNYXAgfSBmcm9tIFwiLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQge1xuICBnZXRFbnVtS2V5cyxcbiAgc2h1dGRvd24sXG4gIHNsZWVwLFxufSBmcm9tIFwiLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7XG4gIEJvb2xlYW5QYXJhbWV0ZXIsXG4gIENvbW1hbmQsXG4gIENob2ljZXNQYXJhbWV0ZXIsXG4gIFBhcmFtZXRlcixcbiAgU3RyaW5nUGFyYW1ldGVyLFxuICBFbnZpcm9ubWVudE9wdGlvbixcbiAgQ29tbWFuZFJlc3VsdCxcbn0gZnJvbSBcIi4uL2NvbW1hbmRzL2Jhc2VcIlxuaW1wb3J0IHtcbiAgR2FyZGVuRXJyb3IsXG4gIFBsdWdpbkVycm9yLFxuICB0b0dhcmRlbkVycm9yLFxufSBmcm9tIFwiLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBHYXJkZW4sIENvbnRleHRPcHRzIH0gZnJvbSBcIi4uL2dhcmRlblwiXG5cbmltcG9ydCB7IExvZ2dlciwgTG9nZ2VyVHlwZSwgZ2V0TG9nZ2VyIH0gZnJvbSBcIi4uL2xvZ2dlci9sb2dnZXJcIlxuaW1wb3J0IHsgTG9nTGV2ZWwgfSBmcm9tIFwiLi4vbG9nZ2VyL2xvZy1ub2RlXCJcbmltcG9ydCB7IEJhc2ljVGVybWluYWxXcml0ZXIgfSBmcm9tIFwiLi4vbG9nZ2VyL3dyaXRlcnMvYmFzaWMtdGVybWluYWwtd3JpdGVyXCJcbmltcG9ydCB7IEZhbmN5VGVybWluYWxXcml0ZXIgfSBmcm9tIFwiLi4vbG9nZ2VyL3dyaXRlcnMvZmFuY3ktdGVybWluYWwtd3JpdGVyXCJcbmltcG9ydCB7IEZpbGVXcml0ZXIgfSBmcm9tIFwiLi4vbG9nZ2VyL3dyaXRlcnMvZmlsZS13cml0ZXJcIlxuaW1wb3J0IHsgV3JpdGVyIH0gZnJvbSBcIi4uL2xvZ2dlci93cml0ZXJzL2Jhc2VcIlxuXG5pbXBvcnQge1xuICBmYWxzaWZ5Q29uZmxpY3RpbmdQYXJhbXMsXG4gIGZhaWxPbkludmFsaWRPcHRpb25zLFxuICBnZXRBcmdTeW5vcHNpcyxcbiAgZ2V0S2V5cyxcbiAgZ2V0T3B0aW9uU3lub3BzaXMsXG4gIGZpbHRlckJ5S2V5cyxcbiAgcHJlcGFyZUFyZ0NvbmZpZyxcbiAgcHJlcGFyZU9wdGlvbkNvbmZpZyxcbiAgc3R5bGVDb25maWcsXG59IGZyb20gXCIuL2hlbHBlcnNcIlxuaW1wb3J0IHsgR2FyZGVuQ29uZmlnIH0gZnJvbSBcIi4uL2NvbmZpZy9iYXNlXCJcbmltcG9ydCB7IGRlZmF1bHRFbnZpcm9ubWVudHMgfSBmcm9tIFwiLi4vY29uZmlnL3Byb2plY3RcIlxuaW1wb3J0IHsgRVJST1JfTE9HX0ZJTEVOQU1FIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiXG5cbmNvbnN0IE9VVFBVVF9SRU5ERVJFUlMgPSB7XG4gIGpzb246IChkYXRhOiBEZWVwUHJpbWl0aXZlTWFwKSA9PiB7XG4gICAgcmV0dXJuIHN0cmluZ2lmeShkYXRhLCBudWxsLCAyKVxuICB9LFxuICB5YW1sOiAoZGF0YTogRGVlcFByaW1pdGl2ZU1hcCkgPT4ge1xuICAgIHJldHVybiBzYWZlRHVtcChkYXRhLCB7IG5vUmVmczogdHJ1ZSwgc2tpcEludmFsaWQ6IHRydWUgfSlcbiAgfSxcbn1cblxuY29uc3QgbG9nTGV2ZWxLZXlzID0gZ2V0RW51bUtleXMoTG9nTGV2ZWwpXG4vLyBBbGxvdyBzdHJpbmcgb3IgbnVtZXJpYyBsb2cgbGV2ZWxzXG5jb25zdCBsb2dMZXZlbENob2ljZXMgPSBbLi4ubG9nTGV2ZWxLZXlzLCAuLi5yYW5nZShsb2dMZXZlbEtleXMubGVuZ3RoKS5tYXAoU3RyaW5nKV1cblxuY29uc3QgZ2V0TG9nTGV2ZWxGcm9tQXJnID0gKGxldmVsOiBzdHJpbmcpID0+IHtcbiAgY29uc3QgbHZsID0gcGFyc2VJbnQobGV2ZWwsIDEwKVxuICBpZiAobHZsKSB7XG4gICAgcmV0dXJuIGx2bFxuICB9XG4gIHJldHVybiBMb2dMZXZlbFtsZXZlbF1cbn1cblxuLy8gRm9yIGluaXRpYWxpemluZyBnYXJkZW4gd2l0aG91dCBhIHByb2plY3QgY29uZmlnXG5leHBvcnQgY29uc3QgTU9DS19DT05GSUc6IEdhcmRlbkNvbmZpZyA9IHtcbiAgdmVyc2lvbjogXCIwXCIsXG4gIGRpcm5hbWU6IFwiL1wiLFxuICBwYXRoOiBwcm9jZXNzLmN3ZCgpLFxuICBwcm9qZWN0OiB7XG4gICAgbmFtZTogXCJtb2NrLXByb2plY3RcIixcbiAgICBkZWZhdWx0RW52aXJvbm1lbnQ6IFwibG9jYWxcIixcbiAgICBlbnZpcm9ubWVudHM6IGRlZmF1bHRFbnZpcm9ubWVudHMsXG4gICAgZW52aXJvbm1lbnREZWZhdWx0czoge1xuICAgICAgcHJvdmlkZXJzOiBbXG4gICAgICAgIHtcbiAgICAgICAgICBuYW1lOiBcImxvY2FsLWt1YmVybmV0ZXNcIixcbiAgICAgICAgfSxcbiAgICAgIF0sXG4gICAgICB2YXJpYWJsZXM6IHt9LFxuICAgIH0sXG4gIH0sXG59XG5cbmV4cG9ydCBjb25zdCBHTE9CQUxfT1BUSU9OUyA9IHtcbiAgcm9vdDogbmV3IFN0cmluZ1BhcmFtZXRlcih7XG4gICAgYWxpYXM6IFwiclwiLFxuICAgIGhlbHA6IFwiT3ZlcnJpZGUgcHJvamVjdCByb290IGRpcmVjdG9yeSAoZGVmYXVsdHMgdG8gd29ya2luZyBkaXJlY3RvcnkpLlwiLFxuICAgIGRlZmF1bHRWYWx1ZTogcHJvY2Vzcy5jd2QoKSxcbiAgfSksXG4gIHNpbGVudDogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoe1xuICAgIGFsaWFzOiBcInNcIixcbiAgICBoZWxwOiBcIlN1cHByZXNzIGxvZyBvdXRwdXQuXCIsXG4gICAgZGVmYXVsdFZhbHVlOiBmYWxzZSxcbiAgfSksXG4gIGVudjogbmV3IEVudmlyb25tZW50T3B0aW9uKCksXG4gIGxvZ2xldmVsOiBuZXcgQ2hvaWNlc1BhcmFtZXRlcih7XG4gICAgYWxpYXM6IFwibFwiLFxuICAgIGNob2ljZXM6IGxvZ0xldmVsQ2hvaWNlcyxcbiAgICBoZWxwOlxuICAgICAgXCJTZXQgbG9nZ2VyIGxldmVsLiBWYWx1ZXMgY2FuIGJlIGVpdGhlciBzdHJpbmcgb3IgbnVtZXJpYyBhbmQgYXJlIHByaW9yaXRpemVkIGZyb20gMCB0byA1IFwiICtcbiAgICAgIFwiKGhpZ2hlc3QgdG8gbG93ZXN0KSBhcyBmb2xsb3dzOiBlcnJvcjogMCwgd2FybjogMSwgaW5mbzogMiwgdmVyYm9zZTogMywgZGVidWc6IDQsIHNpbGx5OiA1XCIsXG4gICAgaGludHM6XG4gICAgICBcIltlbnVtXSBbZGVmYXVsdDogaW5mb10gW2Vycm9yIHx8IDAsIHdhcm4gfHwgMSwgaW5mbyB8fCAyLCB2ZXJib3NlIHx8IDMsIGRlYnVnIHx8IDQsIHNpbGx5IHx8IDVdXCIsXG4gICAgZGVmYXVsdFZhbHVlOiBMb2dMZXZlbFtMb2dMZXZlbC5pbmZvXSxcbiAgfSksXG4gIG91dHB1dDogbmV3IENob2ljZXNQYXJhbWV0ZXIoe1xuICAgIGFsaWFzOiBcIm9cIixcbiAgICBjaG9pY2VzOiBPYmplY3Qua2V5cyhPVVRQVVRfUkVOREVSRVJTKSxcbiAgICBoZWxwOiBcIk91dHB1dCBjb21tYW5kIHJlc3VsdCBpbiBzcGVjaWZpZWQgZm9ybWF0IChub3RlOiBkaXNhYmxlcyBwcm9ncmVzcyBsb2dnaW5nKS5cIixcbiAgfSksXG59XG5jb25zdCBHTE9CQUxfT1BUSU9OU19HUk9VUF9OQU1FID0gXCJHbG9iYWwgb3B0aW9uc1wiXG5jb25zdCBERUZBVUxUX0NMSV9MT0dHRVJfVFlQRSA9IExvZ2dlclR5cGUuZmFuY3lcblxuZXhwb3J0IGludGVyZmFjZSBQYXJzZVJlc3VsdHMge1xuICBhcmd2OiBhbnlcbiAgY29kZTogbnVtYmVyXG4gIGVycm9yczogKEdhcmRlbkVycm9yIHwgRXJyb3IpW11cbn1cblxuaW50ZXJmYWNlIFN5d2FjUGFyc2VSZXN1bHRzIGV4dGVuZHMgUGFyc2VSZXN1bHRzIHtcbiAgb3V0cHV0OiBzdHJpbmdcbiAgZGV0YWlsczogeyBsb2dnZXI6IExvZ2dlciwgcmVzdWx0PzogQ29tbWFuZFJlc3VsdCB9XG59XG5cbmV4cG9ydCBjbGFzcyBHYXJkZW5DbGkge1xuICBwcm9ncmFtOiBhbnlcbiAgY29tbWFuZHM6IHsgW2tleTogc3RyaW5nXTogQ29tbWFuZCB9ID0ge31cblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCB2ZXJzaW9uID0gcmVxdWlyZShcIi4uLy4uL3BhY2thZ2UuanNvblwiKS52ZXJzaW9uXG4gICAgdGhpcy5wcm9ncmFtID0gc3l3YWNcbiAgICAgIC5oZWxwKFwiLWgsIC0taGVscFwiLCB7XG4gICAgICAgIGdyb3VwOiBHTE9CQUxfT1BUSU9OU19HUk9VUF9OQU1FLFxuICAgICAgICBpbXBsaWNpdENvbW1hbmQ6IGZhbHNlLFxuICAgICAgfSlcbiAgICAgIC52ZXJzaW9uKFwiLXYsIC0tdmVyc2lvblwiLCB7XG4gICAgICAgIHZlcnNpb24sXG4gICAgICAgIGdyb3VwOiBHTE9CQUxfT1BUSU9OU19HUk9VUF9OQU1FLFxuICAgICAgICBpbXBsaWNpdENvbW1hbmQ6IGZhbHNlLFxuICAgICAgfSlcbiAgICAgIC5zaG93SGVscEJ5RGVmYXVsdCgpXG4gICAgICAuY2hlY2soKGFyZ3YsIF9jdHgpID0+IHtcbiAgICAgICAgLy8gTk9URTogTmVlZCB0byBtdXRhdGUgYXJndiFcbiAgICAgICAgbWVyZ2UoYXJndiwgZmFsc2lmeUNvbmZsaWN0aW5nUGFyYW1zKGFyZ3YsIEdMT0JBTF9PUFRJT05TKSlcbiAgICAgIH0pXG4gICAgICAuc3R5bGUoc3R5bGVDb25maWcpXG5cbiAgICBjb25zdCBjb21tYW5kcyA9IGNvcmVDb21tYW5kc1xuXG4gICAgY29uc3QgZ2xvYmFsT3B0aW9ucyA9IE9iamVjdC5lbnRyaWVzKEdMT0JBTF9PUFRJT05TKVxuXG4gICAgY29tbWFuZHMuZm9yRWFjaChjb21tYW5kID0+IHRoaXMuYWRkQ29tbWFuZChjb21tYW5kLCB0aGlzLnByb2dyYW0pKVxuICAgIGdsb2JhbE9wdGlvbnMuZm9yRWFjaCgoW2tleSwgb3B0XSkgPT4gdGhpcy5hZGRHbG9iYWxPcHRpb24oa2V5LCBvcHQpKVxuICB9XG5cbiAgYWRkR2xvYmFsT3B0aW9uKGtleTogc3RyaW5nLCBvcHRpb246IFBhcmFtZXRlcjxhbnk+KTogdm9pZCB7XG4gICAgdGhpcy5wcm9ncmFtLm9wdGlvbihnZXRPcHRpb25TeW5vcHNpcyhrZXksIG9wdGlvbiksIHtcbiAgICAgIC4uLnByZXBhcmVPcHRpb25Db25maWcob3B0aW9uKSxcbiAgICAgIGdyb3VwOiBHTE9CQUxfT1BUSU9OU19HUk9VUF9OQU1FLFxuICAgIH0pXG4gIH1cblxuICBhZGRDb21tYW5kKGNvbW1hbmQ6IENvbW1hbmQsIHByb2dyYW0pOiB2b2lkIHtcbiAgICBjb25zdCBmdWxsTmFtZSA9IGNvbW1hbmQuZ2V0RnVsbE5hbWUoKVxuXG4gICAgaWYgKHRoaXMuY29tbWFuZHNbZnVsbE5hbWVdKSB7XG4gICAgICAvLyBGb3Igbm93IHdlIGRvbid0IGFsbG93IG11bHRpcGxlIGRlZmluaXRpb25zIG9mIHRoZSBzYW1lIGNvbW1hbmQuIFdlIG1heSB3YW50IHRvIHJldmlzaXQgdGhpcyBsYXRlci5cbiAgICAgIHRocm93IG5ldyBQbHVnaW5FcnJvcihgTXVsdGlwbGUgZGVmaW5pdGlvbnMgb2YgY29tbWFuZCBcIiR7ZnVsbE5hbWV9XCJgLCB7fSlcbiAgICB9XG5cbiAgICB0aGlzLmNvbW1hbmRzW2Z1bGxOYW1lXSA9IGNvbW1hbmRcblxuICAgIGNvbnN0IHtcbiAgICAgIGFyZ3VtZW50czogYXJncyA9IHt9LFxuICAgICAgbG9nZ2VyVHlwZSA9IERFRkFVTFRfQ0xJX0xPR0dFUl9UWVBFLFxuICAgICAgb3B0aW9ucyA9IHt9LFxuICAgICAgc3ViQ29tbWFuZHMsXG4gICAgfSA9IGNvbW1hbmRcblxuICAgIGNvbnN0IGFyZ0tleXMgPSBnZXRLZXlzKGFyZ3MpXG4gICAgY29uc3Qgb3B0S2V5cyA9IGdldEtleXMob3B0aW9ucylcbiAgICBjb25zdCBnbG9iYWxLZXlzID0gZ2V0S2V5cyhHTE9CQUxfT1BUSU9OUylcbiAgICBjb25zdCBkdXBLZXlzOiBzdHJpbmdbXSA9IGludGVyc2VjdGlvbihvcHRLZXlzLCBnbG9iYWxLZXlzKVxuXG4gICAgaWYgKGR1cEtleXMubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IFBsdWdpbkVycm9yKGBHbG9iYWwgb3B0aW9uKHMpICR7ZHVwS2V5cy5qb2luKFwiIFwiKX0gY2Fubm90IGJlIHJlZGVmaW5lZGAsIHt9KVxuICAgIH1cblxuICAgIGNvbnN0IGFjdGlvbiA9IGFzeW5jIChhcmd2LCBjbGlDb250ZXh0KSA9PiB7XG4gICAgICAvLyBTeXdhYyByZXR1cm5zIHBvc2l0aW9uYWwgYXJncyBhbmQgb3B0aW9ucyBpbiBhIHNpbmdsZSBvYmplY3Qgd2hpY2ggd2Ugc2VwYXJhdGUgaW50byBhcmdzIGFuZCBvcHRzXG4gICAgICBjb25zdCBwYXJzZWRBcmdzID0gZmlsdGVyQnlLZXlzKGFyZ3YsIGFyZ0tleXMpXG4gICAgICBjb25zdCBwYXJzZWRPcHRzID0gZmlsdGVyQnlLZXlzKGFyZ3YsIG9wdEtleXMuY29uY2F0KGdsb2JhbEtleXMpKVxuICAgICAgY29uc3Qgcm9vdCA9IHJlc29sdmUocHJvY2Vzcy5jd2QoKSwgcGFyc2VkT3B0cy5yb290KVxuICAgICAgY29uc3QgeyBlbnYsIGxvZ2xldmVsLCBzaWxlbnQsIG91dHB1dCB9ID0gcGFyc2VkT3B0c1xuXG4gICAgICAvLyBJbml0IGxvZ2dlclxuICAgICAgY29uc3QgbGV2ZWwgPSBnZXRMb2dMZXZlbEZyb21BcmcobG9nbGV2ZWwpXG4gICAgICBsZXQgd3JpdGVyczogV3JpdGVyW10gPSBbXVxuXG4gICAgICBpZiAoIXNpbGVudCAmJiAhb3V0cHV0ICYmIGxvZ2dlclR5cGUgIT09IExvZ2dlclR5cGUucXVpZXQpIHtcbiAgICAgICAgaWYgKGxvZ2dlclR5cGUgPT09IExvZ2dlclR5cGUuZmFuY3kpIHtcbiAgICAgICAgICB3cml0ZXJzLnB1c2gobmV3IEZhbmN5VGVybWluYWxXcml0ZXIoKSlcbiAgICAgICAgfSBlbHNlIGlmIChsb2dnZXJUeXBlID09PSBMb2dnZXJUeXBlLmJhc2ljKSB7XG4gICAgICAgICAgd3JpdGVycy5wdXNoKG5ldyBCYXNpY1Rlcm1pbmFsV3JpdGVyKCkpXG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY29uc3QgbG9nZ2VyID0gTG9nZ2VyLmluaXRpYWxpemUoeyBsZXZlbCwgd3JpdGVycyB9KVxuICAgICAgbGV0IGdhcmRlbjogR2FyZGVuXG4gICAgICBsZXQgcmVzdWx0XG4gICAgICBkbyB7XG4gICAgICAgIGNvbnN0IGNvbnRleHRPcHRzOiBDb250ZXh0T3B0cyA9IHsgZW52LCBsb2dnZXIgfVxuICAgICAgICBpZiAoY29tbWFuZC5ub1Byb2plY3QpIHtcbiAgICAgICAgICBjb250ZXh0T3B0cy5jb25maWcgPSBNT0NLX0NPTkZJR1xuICAgICAgICB9XG4gICAgICAgIGdhcmRlbiA9IGF3YWl0IEdhcmRlbi5mYWN0b3J5KHJvb3QsIGNvbnRleHRPcHRzKVxuICAgICAgICAvLyBUT0RPOiBlbmZvcmNlIHRoYXQgY29tbWFuZHMgYWx3YXlzIG91dHB1dCBEZWVwUHJpbWl0aXZlTWFwXG4gICAgICAgIHJlc3VsdCA9IGF3YWl0IGNvbW1hbmQuYWN0aW9uKHtcbiAgICAgICAgICBnYXJkZW4sXG4gICAgICAgICAgYXJnczogcGFyc2VkQXJncyxcbiAgICAgICAgICBvcHRzOiBwYXJzZWRPcHRzLFxuICAgICAgICB9KVxuICAgICAgfSB3aGlsZSAocmVzdWx0LnJlc3RhcnRSZXF1aXJlZClcblxuICAgICAgLy8gV2UgYXR0YWNoIHRoZSBhY3Rpb24gcmVzdWx0IHRvIGNsaSBjb250ZXh0IHNvIHRoYXQgd2UgY2FuIHByb2Nlc3MgaXQgaW4gdGhlIHBhcnNlIG1ldGhvZFxuICAgICAgY2xpQ29udGV4dC5kZXRhaWxzLnJlc3VsdCA9IHJlc3VsdFxuICAgIH1cblxuICAgIC8vIENvbW1hbmQgc3BlY2lmaWMgcG9zaXRpb25hbCBhcmdzIGFuZCBvcHRpb25zIGFyZSBzZXQgaW5zaWRlIHRoZSBidWlsZGVyIGZ1bmN0aW9uXG4gICAgY29uc3Qgc2V0dXAgPSBwYXJzZXIgPT4ge1xuICAgICAgc3ViQ29tbWFuZHMuZm9yRWFjaChzdWJDb21tYW5kQ2xzID0+IHRoaXMuYWRkQ29tbWFuZChuZXcgc3ViQ29tbWFuZENscyhjb21tYW5kKSwgcGFyc2VyKSlcbiAgICAgIGFyZ0tleXMuZm9yRWFjaChrZXkgPT4gcGFyc2VyLnBvc2l0aW9uYWwoZ2V0QXJnU3lub3BzaXMoa2V5LCBhcmdzW2tleV0pLCBwcmVwYXJlQXJnQ29uZmlnKGFyZ3Nba2V5XSkpKVxuICAgICAgb3B0S2V5cy5mb3JFYWNoKGtleSA9PiBwYXJzZXIub3B0aW9uKGdldE9wdGlvblN5bm9wc2lzKGtleSwgb3B0aW9uc1trZXldKSwgcHJlcGFyZU9wdGlvbkNvbmZpZyhvcHRpb25zW2tleV0pKSlcblxuICAgICAgLy8gV2Ugb25seSBjaGVjayBmb3IgaW52YWxpZCBmbGFncyBmb3IgdGhlIGxhc3QgY29tbWFuZCBzaW5jZSBpdCBtaWdodCBjb250YWluIGZsYWdzIHRoYXRcbiAgICAgIC8vIHRoZSBwYXJlbnQgaXMgdW5hd2FyZSBvZiwgdGh1cyBjYXVzaW5nIHRoZSBjaGVjayB0byBmYWlsIGZvciB0aGUgcGFyZW50XG4gICAgICBpZiAoc3ViQ29tbWFuZHMubGVuZ3RoIDwgMSkge1xuICAgICAgICBwYXJzZXIuY2hlY2soZmFpbE9uSW52YWxpZE9wdGlvbnMpXG4gICAgICB9XG4gICAgICByZXR1cm4gcGFyc2VyXG4gICAgfVxuXG4gICAgY29uc3QgY29tbWFuZENvbmZpZyA9IHtcbiAgICAgIHNldHVwLFxuICAgICAgYWxpYXNlczogY29tbWFuZC5hbGlhcyxcbiAgICAgIGRlc2M6IGNvbW1hbmQuaGVscCxcbiAgICAgIHJ1bjogYWN0aW9uLFxuICAgIH1cblxuICAgIHByb2dyYW0uY29tbWFuZChjb21tYW5kLm5hbWUsIGNvbW1hbmRDb25maWcpXG4gIH1cblxuICBhc3luYyBwYXJzZSgpOiBQcm9taXNlPFBhcnNlUmVzdWx0cz4ge1xuICAgIGNvbnN0IHBhcnNlUmVzdWx0OiBTeXdhY1BhcnNlUmVzdWx0cyA9IGF3YWl0IHRoaXMucHJvZ3JhbS5wYXJzZSgpXG4gICAgY29uc3QgeyBhcmd2LCBkZXRhaWxzLCBlcnJvcnMsIG91dHB1dDogY2xpT3V0cHV0IH0gPSBwYXJzZVJlc3VsdFxuICAgIGNvbnN0IHsgcmVzdWx0OiBjb21tYW5kUmVzdWx0IH0gPSBkZXRhaWxzXG4gICAgY29uc3QgeyBvdXRwdXQgfSA9IGFyZ3ZcbiAgICBsZXQgeyBjb2RlIH0gPSBwYXJzZVJlc3VsdFxuICAgIGxldCBsb2dnZXI6IExvZ2dlclxuXG4gICAgLy8gTm90ZTogQ2lyY3VtdmVudHMgYW4gaXNzdWUgd2hlcmUgdGhlIHByb2Nlc3MgZXhpdHMgYmVmb3JlIHRoZSBvdXRwdXQgaXMgZnVsbHkgZmx1c2hlZC5cbiAgICAvLyBOZWVkZWQgZm9yIG91dHB1dCByZW5kZXJlcnMgYW5kIFdpbnN0b24gKHNlZTogaHR0cHM6Ly9naXRodWIuY29tL3dpbnN0b25qcy93aW5zdG9uL2lzc3Vlcy8yMjgpXG4gICAgY29uc3Qgd2FpdEZvck91dHB1dEZsdXNoID0gKCkgPT4gc2xlZXAoMTAwKVxuXG4gICAgLy8gTG9nZ2VyIG1pZ2h0IG5vdCBoYXZlIGJlZW4gaW5pdGlhbGlzZWQgaWYgcHJvY2VzcyBleGl0cyBlYXJseVxuICAgIHRyeSB7XG4gICAgICBsb2dnZXIgPSBnZXRMb2dnZXIoKVxuICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIGxvZ2dlciA9IExvZ2dlci5pbml0aWFsaXplKHtcbiAgICAgICAgbGV2ZWw6IExvZ0xldmVsLmluZm8sXG4gICAgICAgIHdyaXRlcnM6IFtuZXcgQmFzaWNUZXJtaW5hbFdyaXRlcigpXSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgLy8gLS1oZWxwIG9yIC0tdmVyc2lvbiBvcHRpb25zIHdlcmUgY2FsbGVkIHNvIHdlIGxvZyB0aGUgY2xpIG91dHB1dCBhbmQgZXhpdFxuICAgIGlmIChjbGlPdXRwdXQgJiYgZXJyb3JzLmxlbmd0aCA8IDEpIHtcbiAgICAgIGxvZ2dlci5zdG9wKClcbiAgICAgIGNvbnNvbGUubG9nKGNsaU91dHB1dClcblxuICAgICAgLy8gZml4IGlzc3VlIHdoZXJlIHN5d2FjIHJldHVybnMgZXhpdCBjb2RlIDAgZXZlbiB3aGVuIGEgY29tbWFuZCBkb2Vzbid0IGV4aXN0XG4gICAgICBpZiAoIWFyZ3YuaCAmJiAhYXJndi5oZWxwKSB7XG4gICAgICAgIGNvZGUgPSAxXG4gICAgICB9XG5cbiAgICAgIHByb2Nlc3MuZXhpdChjb2RlKVxuICAgIH1cblxuICAgIGNvbnN0IGdhcmRlbkVycm9yczogR2FyZGVuRXJyb3JbXSA9IGVycm9yc1xuICAgICAgLm1hcCh0b0dhcmRlbkVycm9yKVxuICAgICAgLmNvbmNhdCgoY29tbWFuZFJlc3VsdCAmJiBjb21tYW5kUmVzdWx0LmVycm9ycykgfHwgW10pXG5cbiAgICAvLyAtLW91dHB1dCBvcHRpb24gc2V0XG4gICAgaWYgKG91dHB1dCkge1xuICAgICAgY29uc3QgcmVuZGVyZXIgPSBPVVRQVVRfUkVOREVSRVJTW291dHB1dF1cbiAgICAgIGlmIChnYXJkZW5FcnJvcnMubGVuZ3RoID4gMCkge1xuICAgICAgICBjb25zb2xlLmVycm9yKHJlbmRlcmVyKHsgc3VjY2VzczogZmFsc2UsIGVycm9yczogZ2FyZGVuRXJyb3JzIH0pKVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc29sZS5sb2cocmVuZGVyZXIoeyBzdWNjZXNzOiB0cnVlLCAuLi5jb21tYW5kUmVzdWx0IH0pKVxuICAgICAgfVxuICAgICAgYXdhaXQgd2FpdEZvck91dHB1dEZsdXNoKClcbiAgICB9XG5cbiAgICBpZiAoZ2FyZGVuRXJyb3JzLmxlbmd0aCA+IDApIHtcbiAgICAgIGdhcmRlbkVycm9ycy5mb3JFYWNoKGVycm9yID0+IGxvZ2dlci5lcnJvcih7XG4gICAgICAgIG1zZzogZXJyb3IubWVzc2FnZSxcbiAgICAgICAgZXJyb3IsXG4gICAgICB9KSlcblxuICAgICAgaWYgKGxvZ2dlci53cml0ZXJzLmZpbmQodyA9PiB3IGluc3RhbmNlb2YgRmlsZVdyaXRlcikpIHtcbiAgICAgICAgbG9nZ2VyLmluZm8oYFxcblNlZSAke0VSUk9SX0xPR19GSUxFTkFNRX0gZm9yIGRldGFpbGVkIGVycm9yIG1lc3NhZ2VgKVxuICAgICAgICBhd2FpdCB3YWl0Rm9yT3V0cHV0Rmx1c2goKVxuICAgICAgfVxuXG4gICAgICBjb2RlID0gMVxuICAgIH1cblxuICAgIGxvZ2dlci5zdG9wKClcbiAgICByZXR1cm4geyBhcmd2LCBjb2RlLCBlcnJvcnMgfVxuICB9XG5cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJ1bigpOiBQcm9taXNlPHZvaWQ+IHtcbiAgbGV0IGNvZGVcbiAgdHJ5IHtcbiAgICBjb25zdCBjbGkgPSBuZXcgR2FyZGVuQ2xpKClcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBjbGkucGFyc2UoKVxuICAgIGNvZGUgPSByZXN1bHQuY29kZVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBjb25zb2xlLmxvZyhlcnIpXG4gICAgY29kZSA9IDFcbiAgfSBmaW5hbGx5IHtcbiAgICBzaHV0ZG93bihjb2RlKVxuICB9XG59XG4iXX0= diff --git a/garden-service/build/cli/helpers.d.ts b/garden-service/build/cli/helpers.d.ts new file mode 100644 index 00000000000..a993a259090 --- /dev/null +++ b/garden-service/build/cli/helpers.d.ts @@ -0,0 +1,45 @@ +import { ParameterValues, Parameter } from "../commands/base"; +export declare const styleConfig: { + usagePrefix: (str: any) => string; + usageCommandPlaceholder: (str: any) => string; + usagePositionals: (str: any) => string; + usageArgsPlaceholder: (str: any) => string; + usageOptionsPlaceholder: (str: any) => string; + group: (str: string) => string; + flags: (str: any, _type: any) => string; + hints: (str: any) => string; + groupError: (str: any) => string; + flagsError: (str: any) => string; + descError: (str: any) => string; + hintsError: (str: any) => string; + messages: (str: any) => string; +}; +export declare const getKeys: (obj: any) => string[]; +export declare const filterByKeys: (obj: any, keys: string[]) => any; +export declare type FalsifiedParams = { + [key: string]: false; +}; +/** + * Returns the params that need to be overridden set to false + */ +export declare function falsifyConflictingParams(argv: any, params: ParameterValues): FalsifiedParams; +export declare function getOptionSynopsis(key: string, { alias }: Parameter): string; +export declare function getArgSynopsis(key: string, param: Parameter): string; +export declare function prepareArgConfig(param: Parameter): { + desc: string; + params: SywacOptionConfig[]; +}; +export interface SywacOptionConfig { + desc: string | string[]; + type: string; + defaultValue?: any; + coerce?: Function; + choices?: any[]; + required?: boolean; + hints?: string; + strict: true; + mustExist: true; +} +export declare function prepareOptionConfig(param: Parameter): SywacOptionConfig; +export declare function failOnInvalidOptions(argv: any, ctx: any): void; +//# sourceMappingURL=helpers.d.ts.map \ No newline at end of file diff --git a/garden-service/build/cli/helpers.js b/garden-service/build/cli/helpers.js new file mode 100644 index 00000000000..821aa57bdf9 --- /dev/null +++ b/garden-service/build/cli/helpers.js @@ -0,0 +1,133 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const lodash_1 = require("lodash"); +const exceptions_1 = require("../exceptions"); +// Parameter types T which map between the Parameter class and the Sywac cli library. +// In case we add types that aren't supported natively by Sywac, see: http://sywac.io/docs/sync-config.html#custom +const VALID_PARAMETER_TYPES = ["boolean", "number", "choice", "string", "array:string", "path", "array:path"]; +exports.styleConfig = { + usagePrefix: str => (` +${chalk_1.default.bold(str.slice(0, 5).toUpperCase())} + ${chalk_1.default.italic(str.slice(7))}`), + usageCommandPlaceholder: str => chalk_1.default.blue(str), + usagePositionals: str => chalk_1.default.magenta(str), + usageArgsPlaceholder: str => chalk_1.default.magenta(str), + usageOptionsPlaceholder: str => chalk_1.default.yellow(str), + group: (str) => { + const cleaned = str.endsWith(":") ? str.slice(0, -1) : str; + return chalk_1.default.bold(cleaned.toUpperCase()); + }, + flags: (str, _type) => { + const style = str.startsWith("-") ? chalk_1.default.green : chalk_1.default.magenta; + return style(str); + }, + hints: str => chalk_1.default.gray(str), + groupError: str => chalk_1.default.red.bold(str), + flagsError: str => chalk_1.default.red.bold(str), + descError: str => chalk_1.default.yellow.bold(str), + hintsError: str => chalk_1.default.red(str), + messages: str => chalk_1.default.red.bold(str), +}; +// Helper functions +exports.getKeys = (obj) => Object.keys(obj || {}); +exports.filterByKeys = (obj, keys) => { + return keys.reduce((memo, key) => { + if (obj[key]) { + memo[key] = obj[key]; + } + return memo; + }, {}); +}; +/** + * Returns the params that need to be overridden set to false + */ +function falsifyConflictingParams(argv, params) { + return lodash_1.reduce(argv, (acc, val, key) => { + const param = params[key]; + const overrides = (param || {}).overrides || []; + // argv always contains the "_" key which is irrelevant here + if (key === "_" || !param || !val || !(overrides.length > 0)) { + return acc; + } + const withAliases = overrides.reduce((_, keyToOverride) => { + if (!params[keyToOverride]) { + throw new exceptions_1.InternalError(`Cannot override non-existing parameter: ${keyToOverride}`, { + keyToOverride, + availableKeys: Object.keys(params), + }); + } + return [keyToOverride, ...params[keyToOverride].alias]; + }, []); + withAliases.forEach(keyToOverride => acc[keyToOverride] = false); + return acc; + }, {}); +} +exports.falsifyConflictingParams = falsifyConflictingParams; +// Sywac specific transformers and helpers +function getOptionSynopsis(key, { alias }) { + if (alias && alias.length > 1) { + throw new exceptions_1.InternalError("Option aliases can only be a single character", { + optionName: key, + alias, + }); + } + return alias ? `-${alias}, --${key}` : `--${key}`; +} +exports.getOptionSynopsis = getOptionSynopsis; +function getArgSynopsis(key, param) { + return param.required ? `<${key}>` : `[${key}]`; +} +exports.getArgSynopsis = getArgSynopsis; +function prepareArgConfig(param) { + return { + desc: param.help, + params: [prepareOptionConfig(param)], + }; +} +exports.prepareArgConfig = prepareArgConfig; +function prepareOptionConfig(param) { + const { coerce, defaultValue, help: desc, hints, required, type, } = param; + if (!VALID_PARAMETER_TYPES.includes(type)) { + throw new exceptions_1.InternalError(`Invalid parameter type for cli: ${type}`, { + type, + validParameterTypes: VALID_PARAMETER_TYPES, + }); + } + let config = { + coerce, + defaultValue, + desc, + required, + type, + hints, + strict: true, + mustExist: true, + }; + if (type === "choice") { + config.type = "enum"; + config.choices = param.choices; + } + return config; +} +exports.prepareOptionConfig = prepareOptionConfig; +function failOnInvalidOptions(argv, ctx) { + const validOptions = lodash_1.flatten(ctx.details.types + .filter(t => t.datatype !== "command") + .map(t => t.aliases)); + const receivedOptions = Object.keys(argv); + const invalid = lodash_1.difference(receivedOptions, validOptions); + if (invalid.length > 0) { + ctx.cliMessage(`Received invalid flag(s): ${invalid.join(", ")}`); + } +} +exports.failOnInvalidOptions = failOnInvalidOptions; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUMsNkJBQTZCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO0tBQ2xFO0FBQ0gsQ0FBQztBQVhELG9EQVdDIiwiZmlsZSI6ImNsaS9oZWxwZXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgZGlmZmVyZW5jZSwgZmxhdHRlbiwgcmVkdWNlIH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQge1xuICBDaG9pY2VzUGFyYW1ldGVyLFxuICBQYXJhbWV0ZXJWYWx1ZXMsXG4gIFBhcmFtZXRlcixcbn0gZnJvbSBcIi4uL2NvbW1hbmRzL2Jhc2VcIlxuaW1wb3J0IHtcbiAgSW50ZXJuYWxFcnJvcixcbn0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuXG4vLyBQYXJhbWV0ZXIgdHlwZXMgVCB3aGljaCBtYXAgYmV0d2VlbiB0aGUgUGFyYW1ldGVyPFQ+IGNsYXNzIGFuZCB0aGUgU3l3YWMgY2xpIGxpYnJhcnkuXG4vLyBJbiBjYXNlIHdlIGFkZCB0eXBlcyB0aGF0IGFyZW4ndCBzdXBwb3J0ZWQgbmF0aXZlbHkgYnkgU3l3YWMsIHNlZTogaHR0cDovL3N5d2FjLmlvL2RvY3Mvc3luYy1jb25maWcuaHRtbCNjdXN0b21cbmNvbnN0IFZBTElEX1BBUkFNRVRFUl9UWVBFUyA9IFtcImJvb2xlYW5cIiwgXCJudW1iZXJcIiwgXCJjaG9pY2VcIiwgXCJzdHJpbmdcIiwgXCJhcnJheTpzdHJpbmdcIiwgXCJwYXRoXCIsIFwiYXJyYXk6cGF0aFwiXVxuXG5leHBvcnQgY29uc3Qgc3R5bGVDb25maWcgPSB7XG4gIHVzYWdlUHJlZml4OiBzdHIgPT4gKFxuICAgIGBcbiR7Y2hhbGsuYm9sZChzdHIuc2xpY2UoMCwgNSkudG9VcHBlckNhc2UoKSl9XG4gICR7Y2hhbGsuaXRhbGljKHN0ci5zbGljZSg3KSl9YFxuICApLFxuICB1c2FnZUNvbW1hbmRQbGFjZWhvbGRlcjogc3RyID0+IGNoYWxrLmJsdWUoc3RyKSxcbiAgdXNhZ2VQb3NpdGlvbmFsczogc3RyID0+IGNoYWxrLm1hZ2VudGEoc3RyKSxcbiAgdXNhZ2VBcmdzUGxhY2Vob2xkZXI6IHN0ciA9PiBjaGFsay5tYWdlbnRhKHN0ciksXG4gIHVzYWdlT3B0aW9uc1BsYWNlaG9sZGVyOiBzdHIgPT4gY2hhbGsueWVsbG93KHN0ciksXG4gIGdyb3VwOiAoc3RyOiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCBjbGVhbmVkID0gc3RyLmVuZHNXaXRoKFwiOlwiKSA/IHN0ci5zbGljZSgwLCAtMSkgOiBzdHJcbiAgICByZXR1cm4gY2hhbGsuYm9sZChjbGVhbmVkLnRvVXBwZXJDYXNlKCkpXG4gIH0sXG4gIGZsYWdzOiAoc3RyLCBfdHlwZSkgPT4ge1xuICAgIGNvbnN0IHN0eWxlID0gc3RyLnN0YXJ0c1dpdGgoXCItXCIpID8gY2hhbGsuZ3JlZW4gOiBjaGFsay5tYWdlbnRhXG4gICAgcmV0dXJuIHN0eWxlKHN0cilcbiAgfSxcbiAgaGludHM6IHN0ciA9PiBjaGFsay5ncmF5KHN0ciksXG4gIGdyb3VwRXJyb3I6IHN0ciA9PiBjaGFsay5yZWQuYm9sZChzdHIpLFxuICBmbGFnc0Vycm9yOiBzdHIgPT4gY2hhbGsucmVkLmJvbGQoc3RyKSxcbiAgZGVzY0Vycm9yOiBzdHIgPT4gY2hhbGsueWVsbG93LmJvbGQoc3RyKSxcbiAgaGludHNFcnJvcjogc3RyID0+IGNoYWxrLnJlZChzdHIpLFxuICBtZXNzYWdlczogc3RyID0+IGNoYWxrLnJlZC5ib2xkKHN0ciksIC8vIHRoZXNlIGFyZSBlcnJvciBtZXNzYWdlc1xufVxuXG4vLyBIZWxwZXIgZnVuY3Rpb25zXG5leHBvcnQgY29uc3QgZ2V0S2V5cyA9IChvYmopOiBzdHJpbmdbXSA9PiBPYmplY3Qua2V5cyhvYmogfHwge30pXG5leHBvcnQgY29uc3QgZmlsdGVyQnlLZXlzID0gKG9iajogYW55LCBrZXlzOiBzdHJpbmdbXSk6IGFueSA9PiB7XG4gIHJldHVybiBrZXlzLnJlZHVjZSgobWVtbywga2V5KSA9PiB7XG4gICAgaWYgKG9ialtrZXldKSB7XG4gICAgICBtZW1vW2tleV0gPSBvYmpba2V5XVxuICAgIH1cbiAgICByZXR1cm4gbWVtb1xuICB9LCB7fSlcbn1cblxuZXhwb3J0IHR5cGUgRmFsc2lmaWVkUGFyYW1zID0geyBba2V5OiBzdHJpbmddOiBmYWxzZSB9XG5cbi8qKlxuICogUmV0dXJucyB0aGUgcGFyYW1zIHRoYXQgbmVlZCB0byBiZSBvdmVycmlkZGVuIHNldCB0byBmYWxzZVxuICovXG5leHBvcnQgZnVuY3Rpb24gZmFsc2lmeUNvbmZsaWN0aW5nUGFyYW1zKGFyZ3YsIHBhcmFtczogUGFyYW1ldGVyVmFsdWVzPGFueT4pOiBGYWxzaWZpZWRQYXJhbXMge1xuICByZXR1cm4gcmVkdWNlKGFyZ3YsIChhY2M6IHt9LCB2YWw6IGFueSwga2V5OiBzdHJpbmcpID0+IHtcbiAgICBjb25zdCBwYXJhbSA9IHBhcmFtc1trZXldXG4gICAgY29uc3Qgb3ZlcnJpZGVzID0gKHBhcmFtIHx8IHt9KS5vdmVycmlkZXMgfHwgW11cbiAgICAvLyBhcmd2IGFsd2F5cyBjb250YWlucyB0aGUgXCJfXCIga2V5IHdoaWNoIGlzIGlycmVsZXZhbnQgaGVyZVxuICAgIGlmIChrZXkgPT09IFwiX1wiIHx8ICFwYXJhbSB8fCAhdmFsIHx8ICEob3ZlcnJpZGVzLmxlbmd0aCA+IDApKSB7XG4gICAgICByZXR1cm4gYWNjXG4gICAgfVxuICAgIGNvbnN0IHdpdGhBbGlhc2VzID0gb3ZlcnJpZGVzLnJlZHVjZSgoXywga2V5VG9PdmVycmlkZTogc3RyaW5nKTogc3RyaW5nW10gPT4ge1xuICAgICAgaWYgKCFwYXJhbXNba2V5VG9PdmVycmlkZV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYENhbm5vdCBvdmVycmlkZSBub24tZXhpc3RpbmcgcGFyYW1ldGVyOiAke2tleVRvT3ZlcnJpZGV9YCwge1xuICAgICAgICAgIGtleVRvT3ZlcnJpZGUsXG4gICAgICAgICAgYXZhaWxhYmxlS2V5czogT2JqZWN0LmtleXMocGFyYW1zKSxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIHJldHVybiBba2V5VG9PdmVycmlkZSwgLi4ucGFyYW1zW2tleVRvT3ZlcnJpZGVdLmFsaWFzXVxuICAgIH0sIFtdKVxuXG4gICAgd2l0aEFsaWFzZXMuZm9yRWFjaChrZXlUb092ZXJyaWRlID0+IGFjY1trZXlUb092ZXJyaWRlXSA9IGZhbHNlKVxuICAgIHJldHVybiBhY2NcbiAgfSwge30pXG59XG5cbi8vIFN5d2FjIHNwZWNpZmljIHRyYW5zZm9ybWVycyBhbmQgaGVscGVyc1xuZXhwb3J0IGZ1bmN0aW9uIGdldE9wdGlvblN5bm9wc2lzKGtleTogc3RyaW5nLCB7IGFsaWFzIH06IFBhcmFtZXRlcjxhbnk+KTogc3RyaW5nIHtcbiAgaWYgKGFsaWFzICYmIGFsaWFzLmxlbmd0aCA+IDEpIHtcbiAgICB0aHJvdyBuZXcgSW50ZXJuYWxFcnJvcihcIk9wdGlvbiBhbGlhc2VzIGNhbiBvbmx5IGJlIGEgc2luZ2xlIGNoYXJhY3RlclwiLCB7XG4gICAgICBvcHRpb25OYW1lOiBrZXksXG4gICAgICBhbGlhcyxcbiAgICB9KVxuICB9XG4gIHJldHVybiBhbGlhcyA/IGAtJHthbGlhc30sIC0tJHtrZXl9YCA6IGAtLSR7a2V5fWBcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEFyZ1N5bm9wc2lzKGtleTogc3RyaW5nLCBwYXJhbTogUGFyYW1ldGVyPGFueT4pIHtcbiAgcmV0dXJuIHBhcmFtLnJlcXVpcmVkID8gYDwke2tleX0+YCA6IGBbJHtrZXl9XWBcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVBcmdDb25maWcocGFyYW06IFBhcmFtZXRlcjxhbnk+KSB7XG4gIHJldHVybiB7XG4gICAgZGVzYzogcGFyYW0uaGVscCxcbiAgICBwYXJhbXM6IFtwcmVwYXJlT3B0aW9uQ29uZmlnKHBhcmFtKV0sXG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTeXdhY09wdGlvbkNvbmZpZyB7XG4gIGRlc2M6IHN0cmluZyB8IHN0cmluZ1tdXG4gIHR5cGU6IHN0cmluZ1xuICBkZWZhdWx0VmFsdWU/OiBhbnlcbiAgY29lcmNlPzogRnVuY3Rpb25cbiAgY2hvaWNlcz86IGFueVtdXG4gIHJlcXVpcmVkPzogYm9vbGVhblxuICBoaW50cz86IHN0cmluZ1xuICBzdHJpY3Q6IHRydWVcbiAgbXVzdEV4aXN0OiB0cnVlIC8vIEZvciBwYXJhbWV0ZXJzIG9mIHBhdGggdHlwZVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcHJlcGFyZU9wdGlvbkNvbmZpZyhwYXJhbTogUGFyYW1ldGVyPGFueT4pOiBTeXdhY09wdGlvbkNvbmZpZyB7XG4gIGNvbnN0IHtcbiAgICBjb2VyY2UsXG4gICAgZGVmYXVsdFZhbHVlLFxuICAgIGhlbHA6IGRlc2MsXG4gICAgaGludHMsXG4gICAgcmVxdWlyZWQsXG4gICAgdHlwZSxcbiAgfSA9IHBhcmFtXG4gIGlmICghVkFMSURfUEFSQU1FVEVSX1RZUEVTLmluY2x1ZGVzKHR5cGUpKSB7XG4gICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoYEludmFsaWQgcGFyYW1ldGVyIHR5cGUgZm9yIGNsaTogJHt0eXBlfWAsIHtcbiAgICAgIHR5cGUsXG4gICAgICB2YWxpZFBhcmFtZXRlclR5cGVzOiBWQUxJRF9QQVJBTUVURVJfVFlQRVMsXG4gICAgfSlcbiAgfVxuICBsZXQgY29uZmlnOiBTeXdhY09wdGlvbkNvbmZpZyA9IHtcbiAgICBjb2VyY2UsXG4gICAgZGVmYXVsdFZhbHVlLFxuICAgIGRlc2MsXG4gICAgcmVxdWlyZWQsXG4gICAgdHlwZSxcbiAgICBoaW50cyxcbiAgICBzdHJpY3Q6IHRydWUsXG4gICAgbXVzdEV4aXN0OiB0cnVlLCAvLyBGb3IgcGFyYW1ldGVycyBvZiBwYXRoIHR5cGVcbiAgfVxuICBpZiAodHlwZSA9PT0gXCJjaG9pY2VcIikge1xuICAgIGNvbmZpZy50eXBlID0gXCJlbnVtXCJcbiAgICBjb25maWcuY2hvaWNlcyA9ICg8Q2hvaWNlc1BhcmFtZXRlcj5wYXJhbSkuY2hvaWNlc1xuICB9XG4gIHJldHVybiBjb25maWdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZhaWxPbkludmFsaWRPcHRpb25zKGFyZ3YsIGN0eCkge1xuICBjb25zdCB2YWxpZE9wdGlvbnMgPSBmbGF0dGVuKFxuICAgIGN0eC5kZXRhaWxzLnR5cGVzXG4gICAgICAuZmlsdGVyKHQgPT4gdC5kYXRhdHlwZSAhPT0gXCJjb21tYW5kXCIpXG4gICAgICAubWFwKHQgPT4gdC5hbGlhc2VzKSxcbiAgKVxuICBjb25zdCByZWNlaXZlZE9wdGlvbnMgPSBPYmplY3Qua2V5cyhhcmd2KVxuICBjb25zdCBpbnZhbGlkID0gZGlmZmVyZW5jZShyZWNlaXZlZE9wdGlvbnMsIHZhbGlkT3B0aW9ucylcbiAgaWYgKGludmFsaWQubGVuZ3RoID4gMCkge1xuICAgIGN0eC5jbGlNZXNzYWdlKGBSZWNlaXZlZCBpbnZhbGlkIGZsYWcocyk6ICR7aW52YWxpZC5qb2luKFwiLCBcIil9YClcbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/base.d.ts b/garden-service/build/commands/base.d.ts new file mode 100644 index 00000000000..b3565509889 --- /dev/null +++ b/garden-service/build/commands/base.d.ts @@ -0,0 +1,156 @@ +import { GardenError } from "../exceptions"; +import { TaskResults } from "../task-graph"; +import { LoggerType } from "../logger/logger"; +import { ProcessResults } from "../process"; +import { Garden } from "../garden"; +export declare class ValidationError extends Error { +} +export interface ParameterConstructor { + help: string; + required?: boolean; + alias?: string; + defaultValue?: T; + valueName?: string; + hints?: string; + overrides?: string[]; +} +export declare abstract class Parameter { + abstract type: string; + _valueType: T; + defaultValue: T | undefined; + help: string; + required: boolean; + alias?: string; + hints?: string; + valueName: string; + overrides: string[]; + constructor({ help, required, alias, defaultValue, valueName, overrides, hints }: ParameterConstructor); + coerce(input: T): T | undefined; + abstract validate(input: string): T; + autoComplete(): Promise; +} +export declare class StringParameter extends Parameter { + type: string; + validate(input: string): string; +} +export declare class StringOption extends Parameter { + type: string; + validate(input?: string): string | undefined; +} +export declare class StringsParameter extends Parameter { + type: string; + coerce(input: string[]): string[] | undefined; + validate(input: string): string[]; +} +export declare class PathParameter extends Parameter { + type: string; + validate(input: string): string; +} +export declare class PathsParameter extends Parameter { + type: string; + validate(input: string): string[]; +} +export declare class NumberParameter extends Parameter { + type: string; + validate(input: string): number; +} +export interface ChoicesConstructor extends ParameterConstructor { + choices: string[]; +} +export declare class ChoicesParameter extends Parameter { + type: string; + choices: string[]; + constructor(args: ChoicesConstructor); + validate(input: string): string; + autoComplete(): Promise; +} +export declare class BooleanParameter extends Parameter { + type: string; + validate(input: any): boolean; +} +export declare class EnvironmentOption extends StringParameter { + constructor({ help }?: { + help?: string | undefined; + }); +} +export declare type Parameters = { + [key: string]: Parameter; +}; +export declare type ParameterValues = { + [P in keyof T]: T[P]["_valueType"]; +}; +export interface CommandConstructor { + new (parent?: Command): Command; +} +export interface CommandResult { + result?: T; + restartRequired?: boolean; + errors?: GardenError[]; +} +export interface CommandParams { + args: ParameterValues; + opts: ParameterValues; + garden: Garden; +} +export declare abstract class Command { + private parent?; + abstract name: string; + abstract help: string; + description?: string; + alias?: string; + loggerType?: LoggerType; + arguments?: T; + options?: U; + noProject: boolean; + subCommands: CommandConstructor[]; + constructor(parent?: Command<{}, {}> | undefined); + getFullName(): any; + describe(): { + name: string; + fullName: any; + help: string; + description: string | undefined; + arguments: { + type: string; + _valueType: any; + defaultValue: any; + help: string; + required: boolean; + alias?: string | undefined; + hints?: string | undefined; + valueName: string; + overrides: string[]; + name: string; + usageName: string; + }[] | undefined; + options: { + type: string; + _valueType: any; + defaultValue: any; + help: string; + required: boolean; + alias?: string | undefined; + hints?: string | undefined; + valueName: string; + overrides: string[]; + name: string; + usageName: string; + }[] | undefined; + }; + abstract action(params: CommandParams): Promise; +} +export declare function handleTaskResults(garden: Garden, taskType: string, results: ProcessResults): Promise>; +export declare function describeParameters(args?: Parameters): { + type: string; + _valueType: any; + defaultValue: any; + help: string; + required: boolean; + alias?: string | undefined; + hints?: string | undefined; + valueName: string; + overrides: string[]; + name: string; + usageName: string; +}[] | undefined; +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/base.js b/garden-service/build/commands/base.js new file mode 100644 index 00000000000..8115cef9c83 --- /dev/null +++ b/garden-service/build/commands/base.js @@ -0,0 +1,210 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const exceptions_1 = require("../exceptions"); +class ValidationError extends Error { +} +exports.ValidationError = ValidationError; +class Parameter { + constructor({ help, required, alias, defaultValue, valueName, overrides, hints }) { + this.help = help; + this.required = required || false; + this.alias = alias; + this.hints = hints; + this.defaultValue = defaultValue; + this.valueName = valueName || "_valueType"; + this.overrides = overrides || []; + } + coerce(input) { + return input; + } + autoComplete() { + return __awaiter(this, void 0, void 0, function* () { + return []; + }); + } +} +exports.Parameter = Parameter; +class StringParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "string"; + } + validate(input) { + return input; + } +} +exports.StringParameter = StringParameter; +// Separating this from StringParameter for now because we can't set the output type based on the required flag +// FIXME: Maybe use a Required type to enforce presence, rather that an option flag? +class StringOption extends Parameter { + constructor() { + super(...arguments); + this.type = "string"; + } + validate(input) { + return input; + } +} +exports.StringOption = StringOption; +class StringsParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "array:string"; + } + // Sywac returns [undefined] if input is empty so we coerce that into undefined. + // This only applies to optional parameters since Sywac would throw if input is empty for a required parameter. + coerce(input) { + const filtered = input.filter(i => !!i); + if (filtered.length < 1) { + return undefined; + } + return filtered; + } + validate(input) { + return input.split(","); + } +} +exports.StringsParameter = StringsParameter; +class PathParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "path"; + } + validate(input) { + return input; + } +} +exports.PathParameter = PathParameter; +class PathsParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "array:path"; + } + validate(input) { + return input.split(","); + } +} +exports.PathsParameter = PathsParameter; +class NumberParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "number"; + } + validate(input) { + try { + return parseInt(input, 10); + } + catch (_a) { + throw new ValidationError(`Could not parse "${input}" as number`); + } + } +} +exports.NumberParameter = NumberParameter; +class ChoicesParameter extends Parameter { + constructor(args) { + super(args); + this.type = "choice"; + this.choices = args.choices; + } + validate(input) { + if (this.choices.includes(input)) { + return input; + } + else { + throw new ValidationError(`"${input}" is not a valid argument`); + } + } + autoComplete() { + return __awaiter(this, void 0, void 0, function* () { + return this.choices; + }); + } +} +exports.ChoicesParameter = ChoicesParameter; +class BooleanParameter extends Parameter { + constructor() { + super(...arguments); + this.type = "boolean"; + } + validate(input) { + return !!input; + } +} +exports.BooleanParameter = BooleanParameter; +// TODO: maybe this should be a global option? +class EnvironmentOption extends StringParameter { + constructor({ help = "The environment (and optionally namespace) to work against" } = {}) { + super({ + help, + required: false, + alias: "e", + }); + } +} +exports.EnvironmentOption = EnvironmentOption; +class Command { + constructor(parent) { + this.parent = parent; + this.noProject = false; + this.subCommands = []; + } + getFullName() { + return !!this.parent ? `${this.parent.getFullName()} ${this.name}` : this.name; + } + describe() { + const { name, help, description } = this; + return { + name, + fullName: this.getFullName(), + help, + description, + arguments: describeParameters(this.arguments), + options: describeParameters(this.options), + }; + } +} +exports.Command = Command; +function handleTaskResults(garden, taskType, results) { + return __awaiter(this, void 0, void 0, function* () { + const failed = Object.values(results.taskResults).filter(r => !!r.error).length; + if (failed) { + const error = new exceptions_1.RuntimeError(`${failed} ${taskType} task(s) failed!`, { + results, + }); + return { errors: [error] }; + } + garden.log.info(""); + if (!results.restartRequired) { + garden.log.header({ emoji: "heavy_check_mark", command: `Done!` }); + } + return { + result: results.taskResults, + restartRequired: results.restartRequired, + }; + }); +} +exports.handleTaskResults = handleTaskResults; +function describeParameters(args) { + if (!args) { + return; + } + return Object.entries(args).map(([argName, arg]) => (Object.assign({ name: argName, usageName: arg.required ? `<${argName}>` : `[${argName}]` }, arg))); +} +exports.describeParameters = describeParameters; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFBO1FBQ25CLElBQUksQ0FBQyxPQUFPLENBQUMsZUFBZSxFQUFFO1lBQzVCLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSyxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO1NBQ25FO1FBQ0QsT0FBTztZQUNMLE1BQU0sRUFBRSxPQUFPLENBQUMsV0FBVztZQUMzQixlQUFlLEVBQUUsT0FBTyxDQUFDLGVBQWU7U0FDekMsQ0FBQTtJQUNILENBQUM7Q0FBQTtBQXBCRCw4Q0FvQkM7QUFFRCxTQUFnQixrQkFBa0IsQ0FBQyxJQUFpQjtJQUNsRCxJQUFJLENBQUMsSUFBSSxFQUFFO1FBQUUsT0FBTTtLQUFFO0lBQ3JCLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxHQUFHLENBQUMsRUFBRSxFQUFFLENBQUMsaUJBQ2xELElBQUksRUFBRSxPQUFPLEVBQ2IsU0FBUyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksT0FBTyxHQUFHLElBQ3RELEdBQUcsRUFDTixDQUFDLENBQUE7QUFDTCxDQUFDO0FBUEQsZ0RBT0MiLCJmaWxlIjoiY29tbWFuZHMvYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQge1xuICBHYXJkZW5FcnJvcixcbiAgUnVudGltZUVycm9yLFxufSBmcm9tIFwiLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBUYXNrUmVzdWx0cyB9IGZyb20gXCIuLi90YXNrLWdyYXBoXCJcbmltcG9ydCB7IExvZ2dlclR5cGUgfSBmcm9tIFwiLi4vbG9nZ2VyL2xvZ2dlclwiXG5pbXBvcnQgeyBQcm9jZXNzUmVzdWx0cyB9IGZyb20gXCIuLi9wcm9jZXNzXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuXG5leHBvcnQgY2xhc3MgVmFsaWRhdGlvbkVycm9yIGV4dGVuZHMgRXJyb3IgeyB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGFyYW1ldGVyQ29uc3RydWN0b3I8VD4ge1xuICBoZWxwOiBzdHJpbmcsXG4gIHJlcXVpcmVkPzogYm9vbGVhbixcbiAgYWxpYXM/OiBzdHJpbmcsXG4gIGRlZmF1bHRWYWx1ZT86IFQsXG4gIHZhbHVlTmFtZT86IHN0cmluZyxcbiAgaGludHM/OiBzdHJpbmcsXG4gIG92ZXJyaWRlcz86IHN0cmluZ1tdLFxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUGFyYW1ldGVyPFQ+IHtcbiAgYWJzdHJhY3QgdHlwZTogc3RyaW5nXG5cbiAgX3ZhbHVlVHlwZTogVFxuXG4gIGRlZmF1bHRWYWx1ZTogVCB8IHVuZGVmaW5lZFxuICBoZWxwOiBzdHJpbmdcbiAgcmVxdWlyZWQ6IGJvb2xlYW5cbiAgYWxpYXM/OiBzdHJpbmdcbiAgaGludHM/OiBzdHJpbmdcbiAgdmFsdWVOYW1lOiBzdHJpbmdcbiAgb3ZlcnJpZGVzOiBzdHJpbmdbXVxuXG4gIGNvbnN0cnVjdG9yKHsgaGVscCwgcmVxdWlyZWQsIGFsaWFzLCBkZWZhdWx0VmFsdWUsIHZhbHVlTmFtZSwgb3ZlcnJpZGVzLCBoaW50cyB9OiBQYXJhbWV0ZXJDb25zdHJ1Y3RvcjxUPikge1xuICAgIHRoaXMuaGVscCA9IGhlbHBcbiAgICB0aGlzLnJlcXVpcmVkID0gcmVxdWlyZWQgfHwgZmFsc2VcbiAgICB0aGlzLmFsaWFzID0gYWxpYXNcbiAgICB0aGlzLmhpbnRzID0gaGludHNcbiAgICB0aGlzLmRlZmF1bHRWYWx1ZSA9IGRlZmF1bHRWYWx1ZVxuICAgIHRoaXMudmFsdWVOYW1lID0gdmFsdWVOYW1lIHx8IFwiX3ZhbHVlVHlwZVwiXG4gICAgdGhpcy5vdmVycmlkZXMgPSBvdmVycmlkZXMgfHwgW11cbiAgfVxuXG4gIGNvZXJjZShpbnB1dDogVCk6IFQgfCB1bmRlZmluZWQge1xuICAgIHJldHVybiBpbnB1dFxuICB9XG5cbiAgYWJzdHJhY3QgdmFsaWRhdGUoaW5wdXQ6IHN0cmluZyk6IFRcblxuICBhc3luYyBhdXRvQ29tcGxldGUoKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICAgIHJldHVybiBbXVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBTdHJpbmdQYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXI8c3RyaW5nPiB7XG4gIHR5cGUgPSBcInN0cmluZ1wiXG5cbiAgdmFsaWRhdGUoaW5wdXQ6IHN0cmluZykge1xuICAgIHJldHVybiBpbnB1dFxuICB9XG59XG5cbi8vIFNlcGFyYXRpbmcgdGhpcyBmcm9tIFN0cmluZ1BhcmFtZXRlciBmb3Igbm93IGJlY2F1c2Ugd2UgY2FuJ3Qgc2V0IHRoZSBvdXRwdXQgdHlwZSBiYXNlZCBvbiB0aGUgcmVxdWlyZWQgZmxhZ1xuLy8gRklYTUU6IE1heWJlIHVzZSBhIFJlcXVpcmVkPFBhcmFtZXRlcj4gdHlwZSB0byBlbmZvcmNlIHByZXNlbmNlLCByYXRoZXIgdGhhdCBhbiBvcHRpb24gZmxhZz9cbmV4cG9ydCBjbGFzcyBTdHJpbmdPcHRpb24gZXh0ZW5kcyBQYXJhbWV0ZXI8c3RyaW5nIHwgdW5kZWZpbmVkPiB7XG4gIHR5cGUgPSBcInN0cmluZ1wiXG5cbiAgdmFsaWRhdGUoaW5wdXQ/OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gaW5wdXRcbiAgfVxufVxuXG5leHBvcnQgY2xhc3MgU3RyaW5nc1BhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlcjxzdHJpbmdbXSB8IHVuZGVmaW5lZD4ge1xuICB0eXBlID0gXCJhcnJheTpzdHJpbmdcIlxuXG4gIC8vIFN5d2FjIHJldHVybnMgW3VuZGVmaW5lZF0gaWYgaW5wdXQgaXMgZW1wdHkgc28gd2UgY29lcmNlIHRoYXQgaW50byB1bmRlZmluZWQuXG4gIC8vIFRoaXMgb25seSBhcHBsaWVzIHRvIG9wdGlvbmFsIHBhcmFtZXRlcnMgc2luY2UgU3l3YWMgd291bGQgdGhyb3cgaWYgaW5wdXQgaXMgZW1wdHkgZm9yIGEgcmVxdWlyZWQgcGFyYW1ldGVyLlxuICBjb2VyY2UoaW5wdXQ6IHN0cmluZ1tdKSB7XG4gICAgY29uc3QgZmlsdGVyZWQgPSBpbnB1dC5maWx0ZXIoaSA9PiAhIWkpXG4gICAgaWYgKGZpbHRlcmVkLmxlbmd0aCA8IDEpIHtcbiAgICAgIHJldHVybiB1bmRlZmluZWRcbiAgICB9XG4gICAgcmV0dXJuIGZpbHRlcmVkXG4gIH1cblxuICB2YWxpZGF0ZShpbnB1dDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGlucHV0LnNwbGl0KFwiLFwiKVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBQYXRoUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyPHN0cmluZz4ge1xuICB0eXBlID0gXCJwYXRoXCJcblxuICB2YWxpZGF0ZShpbnB1dDogc3RyaW5nKSB7XG4gICAgcmV0dXJuIGlucHV0XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIFBhdGhzUGFyYW1ldGVyIGV4dGVuZHMgUGFyYW1ldGVyPHN0cmluZ1tdPiB7XG4gIHR5cGUgPSBcImFycmF5OnBhdGhcIlxuXG4gIHZhbGlkYXRlKGlucHV0OiBzdHJpbmcpIHtcbiAgICByZXR1cm4gaW5wdXQuc3BsaXQoXCIsXCIpXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIE51bWJlclBhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlcjxudW1iZXI+IHtcbiAgdHlwZSA9IFwibnVtYmVyXCJcblxuICB2YWxpZGF0ZShpbnB1dDogc3RyaW5nKSB7XG4gICAgdHJ5IHtcbiAgICAgIHJldHVybiBwYXJzZUludChpbnB1dCwgMTApXG4gICAgfSBjYXRjaCB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGBDb3VsZCBub3QgcGFyc2UgXCIke2lucHV0fVwiIGFzIG51bWJlcmApXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2hvaWNlc0NvbnN0cnVjdG9yIGV4dGVuZHMgUGFyYW1ldGVyQ29uc3RydWN0b3I8c3RyaW5nPiB7XG4gIGNob2ljZXM6IHN0cmluZ1tdLFxufVxuXG5leHBvcnQgY2xhc3MgQ2hvaWNlc1BhcmFtZXRlciBleHRlbmRzIFBhcmFtZXRlcjxzdHJpbmc+IHtcbiAgdHlwZSA9IFwiY2hvaWNlXCJcbiAgY2hvaWNlczogc3RyaW5nW11cblxuICBjb25zdHJ1Y3RvcihhcmdzOiBDaG9pY2VzQ29uc3RydWN0b3IpIHtcbiAgICBzdXBlcihhcmdzKVxuXG4gICAgdGhpcy5jaG9pY2VzID0gYXJncy5jaG9pY2VzXG4gIH1cblxuICB2YWxpZGF0ZShpbnB1dDogc3RyaW5nKSB7XG4gICAgaWYgKHRoaXMuY2hvaWNlcy5pbmNsdWRlcyhpbnB1dCkpIHtcbiAgICAgIHJldHVybiBpbnB1dFxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgVmFsaWRhdGlvbkVycm9yKGBcIiR7aW5wdXR9XCIgaXMgbm90IGEgdmFsaWQgYXJndW1lbnRgKVxuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGF1dG9Db21wbGV0ZSgpIHtcbiAgICByZXR1cm4gdGhpcy5jaG9pY2VzXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEJvb2xlYW5QYXJhbWV0ZXIgZXh0ZW5kcyBQYXJhbWV0ZXI8Ym9vbGVhbj4ge1xuICB0eXBlID0gXCJib29sZWFuXCJcblxuICB2YWxpZGF0ZShpbnB1dDogYW55KSB7XG4gICAgcmV0dXJuICEhaW5wdXRcbiAgfVxufVxuXG4vLyBUT0RPOiBtYXliZSB0aGlzIHNob3VsZCBiZSBhIGdsb2JhbCBvcHRpb24/XG5leHBvcnQgY2xhc3MgRW52aXJvbm1lbnRPcHRpb24gZXh0ZW5kcyBTdHJpbmdQYXJhbWV0ZXIge1xuICBjb25zdHJ1Y3Rvcih7IGhlbHAgPSBcIlRoZSBlbnZpcm9ubWVudCAoYW5kIG9wdGlvbmFsbHkgbmFtZXNwYWNlKSB0byB3b3JrIGFnYWluc3RcIiB9ID0ge30pIHtcbiAgICBzdXBlcih7XG4gICAgICBoZWxwLFxuICAgICAgcmVxdWlyZWQ6IGZhbHNlLFxuICAgICAgYWxpYXM6IFwiZVwiLFxuICAgIH0pXG4gIH1cbn1cblxuZXhwb3J0IHR5cGUgUGFyYW1ldGVycyA9IHsgW2tleTogc3RyaW5nXTogUGFyYW1ldGVyPGFueT4gfVxuZXhwb3J0IHR5cGUgUGFyYW1ldGVyVmFsdWVzPFQgZXh0ZW5kcyBQYXJhbWV0ZXJzPiA9IHsgW1AgaW4ga2V5b2YgVF06IFRbUF1bXCJfdmFsdWVUeXBlXCJdIH1cblxuZXhwb3J0IGludGVyZmFjZSBDb21tYW5kQ29uc3RydWN0b3Ige1xuICBuZXcocGFyZW50PzogQ29tbWFuZCk6IENvbW1hbmRcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21tYW5kUmVzdWx0PFQgPSBhbnk+IHtcbiAgcmVzdWx0PzogVFxuICByZXN0YXJ0UmVxdWlyZWQ/OiBib29sZWFuXG4gIGVycm9ycz86IEdhcmRlbkVycm9yW11cbn1cblxuZXhwb3J0IGludGVyZmFjZSBDb21tYW5kUGFyYW1zPFQgZXh0ZW5kcyBQYXJhbWV0ZXJzID0ge30sIFUgZXh0ZW5kcyBQYXJhbWV0ZXJzID0ge30+IHtcbiAgYXJnczogUGFyYW1ldGVyVmFsdWVzPFQ+XG4gIG9wdHM6IFBhcmFtZXRlclZhbHVlczxVPlxuICBnYXJkZW46IEdhcmRlblxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ29tbWFuZDxUIGV4dGVuZHMgUGFyYW1ldGVycyA9IHt9LCBVIGV4dGVuZHMgUGFyYW1ldGVycyA9IHt9PiB7XG4gIGFic3RyYWN0IG5hbWU6IHN0cmluZ1xuICBhYnN0cmFjdCBoZWxwOiBzdHJpbmdcblxuICBkZXNjcmlwdGlvbj86IHN0cmluZ1xuXG4gIGFsaWFzPzogc3RyaW5nXG4gIGxvZ2dlclR5cGU/OiBMb2dnZXJUeXBlXG5cbiAgYXJndW1lbnRzPzogVFxuICBvcHRpb25zPzogVVxuXG4gIG5vUHJvamVjdDogYm9vbGVhbiA9IGZhbHNlXG4gIHN1YkNvbW1hbmRzOiBDb21tYW5kQ29uc3RydWN0b3JbXSA9IFtdXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBwYXJlbnQ/OiBDb21tYW5kKSB7IH1cblxuICBnZXRGdWxsTmFtZSgpIHtcbiAgICByZXR1cm4gISF0aGlzLnBhcmVudCA/IGAke3RoaXMucGFyZW50LmdldEZ1bGxOYW1lKCl9ICR7dGhpcy5uYW1lfWAgOiB0aGlzLm5hbWVcbiAgfVxuXG4gIGRlc2NyaWJlKCkge1xuICAgIGNvbnN0IHsgbmFtZSwgaGVscCwgZGVzY3JpcHRpb24gfSA9IHRoaXNcblxuICAgIHJldHVybiB7XG4gICAgICBuYW1lLFxuICAgICAgZnVsbE5hbWU6IHRoaXMuZ2V0RnVsbE5hbWUoKSxcbiAgICAgIGhlbHAsXG4gICAgICBkZXNjcmlwdGlvbixcbiAgICAgIGFyZ3VtZW50czogZGVzY3JpYmVQYXJhbWV0ZXJzKHRoaXMuYXJndW1lbnRzKSxcbiAgICAgIG9wdGlvbnM6IGRlc2NyaWJlUGFyYW1ldGVycyh0aGlzLm9wdGlvbnMpLFxuICAgIH1cbiAgfVxuXG4gIC8vIE5vdGU6IER1ZSB0byBhIGN1cnJlbnQgVFMgbGltaXRhdGlvbiAoYXBwYXJlbnRseSBjb3ZlcmVkIGJ5IGh0dHBzOi8vZ2l0aHViLmNvbS9NaWNyb3NvZnQvVHlwZVNjcmlwdC9pc3N1ZXMvNzAxMSksXG4gIC8vIHN1YmNsYXNzIGltcGxlbWVudGF0aW9ucyBuZWVkIHRvIGV4cGxpY2l0bHkgc2V0IHRoZSB0eXBlcyBpbiB0aGUgaW1wbGVtZW50ZWQgZnVuY3Rpb24gc2lnbmF0dXJlLiBTbyBmb3Igbm93IHdlXG4gIC8vIGNhbid0IGVuZm9yY2UgdGhlIHR5cGVzIG9mIGBhcmdzYCBhbmQgYG9wdHNgIGF1dG9tYXRpY2FsbHkgYXQgdGhlIGFic3RyYWN0IGNsYXNzIGxldmVsIGFuZCBoYXZlIHRvIHNwZWNpZnlcbiAgLy8gdGhlIHR5cGVzIGV4cGxpY2l0bHkgb24gdGhlIHN1YmNsYXNzZWQgbWV0aG9kcy5cbiAgYWJzdHJhY3QgYXN5bmMgYWN0aW9uKHBhcmFtczogQ29tbWFuZFBhcmFtczxULCBVPik6IFByb21pc2U8Q29tbWFuZFJlc3VsdD5cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGhhbmRsZVRhc2tSZXN1bHRzKFxuICBnYXJkZW46IEdhcmRlbiwgdGFza1R5cGU6IHN0cmluZywgcmVzdWx0czogUHJvY2Vzc1Jlc3VsdHMsXG4pOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8VGFza1Jlc3VsdHM+PiB7XG4gIGNvbnN0IGZhaWxlZCA9IE9iamVjdC52YWx1ZXMocmVzdWx0cy50YXNrUmVzdWx0cykuZmlsdGVyKHIgPT4gISFyLmVycm9yKS5sZW5ndGhcblxuICBpZiAoZmFpbGVkKSB7XG4gICAgY29uc3QgZXJyb3IgPSBuZXcgUnVudGltZUVycm9yKGAke2ZhaWxlZH0gJHt0YXNrVHlwZX0gdGFzayhzKSBmYWlsZWQhYCwge1xuICAgICAgcmVzdWx0cyxcbiAgICB9KVxuICAgIHJldHVybiB7IGVycm9yczogW2Vycm9yXSB9XG4gIH1cblxuICBnYXJkZW4ubG9nLmluZm8oXCJcIilcbiAgaWYgKCFyZXN1bHRzLnJlc3RhcnRSZXF1aXJlZCkge1xuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwiaGVhdnlfY2hlY2tfbWFya1wiLCBjb21tYW5kOiBgRG9uZSFgIH0pXG4gIH1cbiAgcmV0dXJuIHtcbiAgICByZXN1bHQ6IHJlc3VsdHMudGFza1Jlc3VsdHMsXG4gICAgcmVzdGFydFJlcXVpcmVkOiByZXN1bHRzLnJlc3RhcnRSZXF1aXJlZCxcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzY3JpYmVQYXJhbWV0ZXJzKGFyZ3M/OiBQYXJhbWV0ZXJzKSB7XG4gIGlmICghYXJncykgeyByZXR1cm4gfVxuICByZXR1cm4gT2JqZWN0LmVudHJpZXMoYXJncykubWFwKChbYXJnTmFtZSwgYXJnXSkgPT4gKHtcbiAgICBuYW1lOiBhcmdOYW1lLFxuICAgIHVzYWdlTmFtZTogYXJnLnJlcXVpcmVkID8gYDwke2FyZ05hbWV9PmAgOiBgWyR7YXJnTmFtZX1dYCxcbiAgICAuLi5hcmcsXG4gIH0pKVxufVxuIl19 diff --git a/garden-service/build/commands/build.d.ts b/garden-service/build/commands/build.d.ts new file mode 100644 index 00000000000..812edf1cb5a --- /dev/null +++ b/garden-service/build/commands/build.d.ts @@ -0,0 +1,26 @@ +import { BooleanParameter, Command, CommandResult, CommandParams, StringsParameter } from "./base"; +import { TaskResults } from "../task-graph"; +declare const buildArguments: { + module: StringsParameter; +}; +declare const buildOptions: { + force: BooleanParameter; + watch: BooleanParameter; +}; +declare type BuildArguments = typeof buildArguments; +declare type BuildOptions = typeof buildOptions; +export declare class BuildCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + module: StringsParameter; + }; + options: { + force: BooleanParameter; + watch: BooleanParameter; + }; + action({ args, opts, garden }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=build.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/build.js b/garden-service/build/commands/build.js new file mode 100644 index 00000000000..f541c92c617 --- /dev/null +++ b/garden-service/build/commands/build.js @@ -0,0 +1,75 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const build_1 = require("../tasks/build"); +const dedent = require("dedent"); +const process_1 = require("../process"); +const watch_1 = require("../watch"); +const buildArguments = { + module: new base_1.StringsParameter({ + help: "Specify module(s) to build. Use comma separator to specify multiple modules.", + }), +}; +const buildOptions = { + force: new base_1.BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new base_1.BooleanParameter({ help: "Watch for changes in module(s) and auto-build.", alias: "w" }), +}; +class BuildCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "build"; + this.help = "Build your modules."; + this.description = dedent ` + Builds all or specified modules, taking into account build dependency order. + Optionally stays running and automatically builds modules if their source (or their dependencies' sources) change. + + Examples: + + garden build # build all modules in the project + garden build my-module # only build my-module + garden build --force # force rebuild of modules + garden build --watch # watch for changes to code + `; + this.arguments = buildArguments; + this.options = buildOptions; + } + action({ args, opts, garden }) { + return __awaiter(this, void 0, void 0, function* () { + yield garden.clearBuilds(); + const autoReloadDependants = yield watch_1.computeAutoReloadDependants(garden); + const modules = yield garden.getModules(args.module); + const moduleNames = modules.map(m => m.name); + garden.log.header({ emoji: "hammer", command: "Build" }); + const results = yield process_1.processModules({ + garden, + modules, + watch: opts.watch, + handler: (module) => __awaiter(this, void 0, void 0, function* () { return [new build_1.BuildTask({ garden, module, force: opts.force })]; }), + changeHandler: (module) => __awaiter(this, void 0, void 0, function* () { + return (yield watch_1.withDependants(garden, [module], autoReloadDependants)) + .filter(m => moduleNames.includes(m.name)) + .map(m => new build_1.BuildTask({ garden, module: m, force: true })); + }), + }); + return base_1.handleTaskResults(garden, "build", results); + }); + } +} +exports.BuildCommand = BuildCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2J1aWxkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxpQ0FPZTtBQUNmLDBDQUEwQztBQUUxQyxpQ0FBaUM7QUFDakMsd0NBQTJDO0FBQzNDLG9DQUFzRTtBQUd0RSxNQUFNLGNBQWMsR0FBRztJQUNyQixNQUFNLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUMzQixJQUFJLEVBQUUsOEVBQThFO0tBQ3JGLENBQUM7Q0FDSCxDQUFBO0FBRUQsTUFBTSxZQUFZLEdBQUc7SUFDbkIsS0FBSyxFQUFFLElBQUksdUJBQWdCLENBQUMsRUFBRSxJQUFJLEVBQUUsNkJBQTZCLEVBQUUsQ0FBQztJQUNwRSxLQUFLLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSxnREFBZ0QsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7Q0FDcEcsQ0FBQTtBQUtELE1BQWEsWUFBYSxTQUFRLGNBQXFDO0lBQXZFOztRQUNFLFNBQUksR0FBRyxPQUFPLENBQUE7UUFDZCxTQUFJLEdBQUcscUJBQXFCLENBQUE7UUFFNUIsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7Ozs7R0FVbkIsQ0FBQTtRQUVELGNBQVMsR0FBRyxjQUFjLENBQUE7UUFDMUIsWUFBTyxHQUFHLFlBQVksQ0FBQTtJQTRCeEIsQ0FBQztJQTFCTyxNQUFNLENBQ1YsRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sRUFBK0M7O1lBR25FLE1BQU0sTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFBO1lBRTFCLE1BQU0sb0JBQW9CLEdBQUcsTUFBTSxtQ0FBMkIsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUN0RSxNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBQ3BELE1BQU0sV0FBVyxHQUFHLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFNUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFBO1lBRXhELE1BQU0sT0FBTyxHQUFHLE1BQU0sd0JBQWMsQ0FBQztnQkFDbkMsTUFBTTtnQkFDTixPQUFPO2dCQUNQLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSztnQkFDakIsT0FBTyxFQUFFLENBQU8sTUFBTSxFQUFFLEVBQUUsZ0RBQUMsT0FBQSxDQUFDLElBQUksaUJBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUEsR0FBQTtnQkFDakYsYUFBYSxFQUFFLENBQU8sTUFBYyxFQUFFLEVBQUU7b0JBQ3RDLE9BQU8sQ0FBQyxNQUFNLHNCQUFjLENBQUMsTUFBTSxFQUFFLENBQUMsTUFBTSxDQUFDLEVBQUUsb0JBQW9CLENBQUMsQ0FBQzt5QkFDbEUsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7eUJBQ3pDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLElBQUksaUJBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsQ0FBQyxFQUFFLEtBQUssRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUE7Z0JBQ2hFLENBQUMsQ0FBQTthQUNGLENBQUMsQ0FBQTtZQUVGLE9BQU8sd0JBQWlCLENBQUMsTUFBTSxFQUFFLE9BQU8sRUFBRSxPQUFPLENBQUMsQ0FBQTtRQUNwRCxDQUFDO0tBQUE7Q0FDRjtBQTdDRCxvQ0E2Q0MiLCJmaWxlIjoiY29tbWFuZHMvYnVpbGQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHtcbiAgQm9vbGVhblBhcmFtZXRlcixcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgaGFuZGxlVGFza1Jlc3VsdHMsXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHsgQnVpbGRUYXNrIH0gZnJvbSBcIi4uL3Rhc2tzL2J1aWxkXCJcbmltcG9ydCB7IFRhc2tSZXN1bHRzIH0gZnJvbSBcIi4uL3Rhc2stZ3JhcGhcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcbmltcG9ydCB7IHByb2Nlc3NNb2R1bGVzIH0gZnJvbSBcIi4uL3Byb2Nlc3NcIlxuaW1wb3J0IHsgY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzLCB3aXRoRGVwZW5kYW50cyB9IGZyb20gXCIuLi93YXRjaFwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcblxuY29uc3QgYnVpbGRBcmd1bWVudHMgPSB7XG4gIG1vZHVsZTogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiU3BlY2lmeSBtb2R1bGUocykgdG8gYnVpbGQuIFVzZSBjb21tYSBzZXBhcmF0b3IgdG8gc3BlY2lmeSBtdWx0aXBsZSBtb2R1bGVzLlwiLFxuICB9KSxcbn1cblxuY29uc3QgYnVpbGRPcHRpb25zID0ge1xuICBmb3JjZTogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoeyBoZWxwOiBcIkZvcmNlIHJlYnVpbGQgb2YgbW9kdWxlKHMpLlwiIH0pLFxuICB3YXRjaDogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoeyBoZWxwOiBcIldhdGNoIGZvciBjaGFuZ2VzIGluIG1vZHVsZShzKSBhbmQgYXV0by1idWlsZC5cIiwgYWxpYXM6IFwid1wiIH0pLFxufVxuXG50eXBlIEJ1aWxkQXJndW1lbnRzID0gdHlwZW9mIGJ1aWxkQXJndW1lbnRzXG50eXBlIEJ1aWxkT3B0aW9ucyA9IHR5cGVvZiBidWlsZE9wdGlvbnNcblxuZXhwb3J0IGNsYXNzIEJ1aWxkQ29tbWFuZCBleHRlbmRzIENvbW1hbmQ8QnVpbGRBcmd1bWVudHMsIEJ1aWxkT3B0aW9ucz4ge1xuICBuYW1lID0gXCJidWlsZFwiXG4gIGhlbHAgPSBcIkJ1aWxkIHlvdXIgbW9kdWxlcy5cIlxuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIEJ1aWxkcyBhbGwgb3Igc3BlY2lmaWVkIG1vZHVsZXMsIHRha2luZyBpbnRvIGFjY291bnQgYnVpbGQgZGVwZW5kZW5jeSBvcmRlci5cbiAgICBPcHRpb25hbGx5IHN0YXlzIHJ1bm5pbmcgYW5kIGF1dG9tYXRpY2FsbHkgYnVpbGRzIG1vZHVsZXMgaWYgdGhlaXIgc291cmNlIChvciB0aGVpciBkZXBlbmRlbmNpZXMnIHNvdXJjZXMpIGNoYW5nZS5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBidWlsZCAgICAgICAgICAgICMgYnVpbGQgYWxsIG1vZHVsZXMgaW4gdGhlIHByb2plY3RcbiAgICAgICAgZ2FyZGVuIGJ1aWxkIG15LW1vZHVsZSAgIyBvbmx5IGJ1aWxkIG15LW1vZHVsZVxuICAgICAgICBnYXJkZW4gYnVpbGQgLS1mb3JjZSAgICAjIGZvcmNlIHJlYnVpbGQgb2YgbW9kdWxlc1xuICAgICAgICBnYXJkZW4gYnVpbGQgLS13YXRjaCAgICAjIHdhdGNoIGZvciBjaGFuZ2VzIHRvIGNvZGVcbiAgYFxuXG4gIGFyZ3VtZW50cyA9IGJ1aWxkQXJndW1lbnRzXG4gIG9wdGlvbnMgPSBidWlsZE9wdGlvbnNcblxuICBhc3luYyBhY3Rpb24oXG4gICAgeyBhcmdzLCBvcHRzLCBnYXJkZW4gfTogQ29tbWFuZFBhcmFtczxCdWlsZEFyZ3VtZW50cywgQnVpbGRPcHRpb25zPixcbiAgKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFRhc2tSZXN1bHRzPj4ge1xuXG4gICAgYXdhaXQgZ2FyZGVuLmNsZWFyQnVpbGRzKClcblxuICAgIGNvbnN0IGF1dG9SZWxvYWREZXBlbmRhbnRzID0gYXdhaXQgY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzKGdhcmRlbilcbiAgICBjb25zdCBtb2R1bGVzID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZXMoYXJncy5tb2R1bGUpXG4gICAgY29uc3QgbW9kdWxlTmFtZXMgPSBtb2R1bGVzLm1hcChtID0+IG0ubmFtZSlcblxuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwiaGFtbWVyXCIsIGNvbW1hbmQ6IFwiQnVpbGRcIiB9KVxuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHByb2Nlc3NNb2R1bGVzKHtcbiAgICAgIGdhcmRlbixcbiAgICAgIG1vZHVsZXMsXG4gICAgICB3YXRjaDogb3B0cy53YXRjaCxcbiAgICAgIGhhbmRsZXI6IGFzeW5jIChtb2R1bGUpID0+IFtuZXcgQnVpbGRUYXNrKHsgZ2FyZGVuLCBtb2R1bGUsIGZvcmNlOiBvcHRzLmZvcmNlIH0pXSxcbiAgICAgIGNoYW5nZUhhbmRsZXI6IGFzeW5jIChtb2R1bGU6IE1vZHVsZSkgPT4ge1xuICAgICAgICByZXR1cm4gKGF3YWl0IHdpdGhEZXBlbmRhbnRzKGdhcmRlbiwgW21vZHVsZV0sIGF1dG9SZWxvYWREZXBlbmRhbnRzKSlcbiAgICAgICAgICAuZmlsdGVyKG0gPT4gbW9kdWxlTmFtZXMuaW5jbHVkZXMobS5uYW1lKSlcbiAgICAgICAgICAubWFwKG0gPT4gbmV3IEJ1aWxkVGFzayh7IGdhcmRlbiwgbW9kdWxlOiBtLCBmb3JjZTogdHJ1ZSB9KSlcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIHJldHVybiBoYW5kbGVUYXNrUmVzdWx0cyhnYXJkZW4sIFwiYnVpbGRcIiwgcmVzdWx0cylcbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/call.d.ts b/garden-service/build/commands/call.d.ts new file mode 100644 index 00000000000..9f8af097c49 --- /dev/null +++ b/garden-service/build/commands/call.d.ts @@ -0,0 +1,16 @@ +import { Command, CommandResult, CommandParams, StringParameter } from "./base"; +declare const callArgs: { + serviceAndPath: StringParameter; +}; +declare type Args = typeof callArgs; +export declare class CallCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + serviceAndPath: StringParameter; + }; + action({ garden, args }: CommandParams): Promise; +} +export {}; +//# sourceMappingURL=call.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/call.js b/garden-service/build/commands/call.js new file mode 100644 index 00000000000..dda9ed23f70 --- /dev/null +++ b/garden-service/build/commands/call.js @@ -0,0 +1,155 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const url_1 = require("url"); +const axios_1 = require("axios"); +const chalk_1 = require("chalk"); +const util_1 = require("util"); +const base_1 = require("./base"); +const util_2 = require("../util/util"); +const exceptions_1 = require("../exceptions"); +const lodash_1 = require("lodash"); +const service_1 = require("../types/service"); +const dedent = require("dedent"); +const callArgs = { + serviceAndPath: new base_1.StringParameter({ + help: "The name of the service(s) to call followed by the ingress path (e.g. my-container/somepath).", + required: true, + }), +}; +class CallCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "call"; + this.help = "Call a service ingress endpoint."; + this.description = dedent ` + This command resolves the deployed ingress endpoint for the given service and path, calls the given endpoint and + outputs the result. + + Examples: + + garden call my-container + garden call my-container/some-path + + Note: Currently only supports simple GET requests for HTTP/HTTPS ingresses. + `; + this.arguments = callArgs; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + let [serviceName, path] = util_2.splitFirst(args.serviceAndPath, "/"); + // TODO: better error when service doesn't exist + const service = yield garden.getService(serviceName); + const status = yield garden.actions.getServiceStatus({ service }); + if (status.state !== "ready") { + throw new exceptions_1.RuntimeError(`Service ${service.name} is not running`, { + serviceName: service.name, + status, + }); + } + if (!status.ingresses) { + throw new exceptions_1.ParameterError(`Service ${service.name} has no active ingresses`, { + serviceName: service.name, + serviceStatus: status, + }); + } + // find the correct endpoint to call + let matchedIngress = null; + let matchedPath; + // we can't easily support raw TCP or UDP in a command like this + const ingresses = status.ingresses.filter(e => e.protocol === "http" || e.protocol === "https"); + if (!path) { + // if no path is specified and there's a root endpoint (path === "/") we use that + const rootIngress = lodash_1.find(ingresses, e => e.path === "/"); + if (rootIngress) { + matchedIngress = rootIngress; + matchedPath = "/"; + } + else { + // if there's no root endpoint, pick the first endpoint + matchedIngress = ingresses[0]; + matchedPath = ingresses[0].path; + } + path = matchedPath; + } + else { + path = "/" + path; + for (const ingress of status.ingresses) { + if (ingress.path) { + if (path.startsWith(ingress.path) && (!matchedPath || ingress.path.length > matchedPath.length)) { + matchedIngress = ingress; + matchedPath = ingress.path; + } + } + else if (!matchedPath) { + matchedIngress = ingress; + } + } + } + if (!matchedIngress) { + throw new exceptions_1.ParameterError(`Service ${service.name} does not have an HTTP/HTTPS ingress at ${path}`, { + serviceName: service.name, + path, + availableIngresses: status.ingresses, + }); + } + const url = url_1.resolve(service_1.getIngressUrl(matchedIngress), path || matchedPath); + // TODO: support POST requests with request body + const method = "get"; + const entry = garden.log.info({ + msg: chalk_1.default.cyan(`Sending ${matchedIngress.protocol.toUpperCase()} GET request to `) + url + "\n", + status: "active", + }); + // this is to accept self-signed certs + process.env.NODE_TLS_REJECT_UNAUTHORIZED = "0"; + const req = axios_1.default({ + method, + url, + headers: { + host: matchedIngress.hostname, + }, + }); + // TODO: add verbose and debug logging (request/response headers etc.) + let res; + try { + res = yield req; + entry.setSuccess(); + garden.log.info(chalk_1.default.green(`${res.status} ${res.statusText}\n`)); + } + catch (err) { + res = err.response; + entry.setError(); + const error = res ? `${res.status} ${res.statusText}` : err.message; + garden.log.info(chalk_1.default.red(error + "\n")); + return {}; + } + const resStr = util_1.isObject(res.data) ? JSON.stringify(res.data, null, 2) : res.data; + res.data && garden.log.info(chalk_1.default.white(resStr) + "\n"); + return { + result: { + serviceName, + path, + url, + response: lodash_1.pick(res, ["status", "statusText", "headers", "data"]), + }, + }; + }); + } +} +exports.CallCommand = CallCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQyxHQUFHLElBQUksQ0FBQyxDQUFBO1lBRXZELE9BQU87Z0JBQ0wsTUFBTSxFQUFFO29CQUNOLFdBQVc7b0JBQ1gsSUFBSTtvQkFDSixHQUFHO29CQUNILFFBQVEsRUFBRSxhQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsUUFBUSxFQUFFLFlBQVksRUFBRSxTQUFTLEVBQUUsTUFBTSxDQUFDLENBQUM7aUJBQ2pFO2FBQ0YsQ0FBQTtRQUNILENBQUM7S0FBQTtDQUNGO0FBcElELGtDQW9JQyIsImZpbGUiOiJjb21tYW5kcy9jYWxsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwidXJsXCJcbmltcG9ydCBBeGlvcyBmcm9tIFwiYXhpb3NcIlxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5pbXBvcnQgeyBpc09iamVjdCB9IGZyb20gXCJ1dGlsXCJcbmltcG9ydCB7XG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIFN0cmluZ1BhcmFtZXRlcixcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgeyBzcGxpdEZpcnN0IH0gZnJvbSBcIi4uL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBQYXJhbWV0ZXJFcnJvciwgUnVudGltZUVycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgcGljaywgZmluZCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgU2VydmljZUluZ3Jlc3MsIGdldEluZ3Jlc3NVcmwgfSBmcm9tIFwiLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5jb25zdCBjYWxsQXJncyA9IHtcbiAgc2VydmljZUFuZFBhdGg6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2UocykgdG8gY2FsbCBmb2xsb3dlZCBieSB0aGUgaW5ncmVzcyBwYXRoIChlLmcuIG15LWNvbnRhaW5lci9zb21lcGF0aCkuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgY2FsbEFyZ3NcblxuZXhwb3J0IGNsYXNzIENhbGxDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzPiB7XG4gIG5hbWUgPSBcImNhbGxcIlxuICBoZWxwID0gXCJDYWxsIGEgc2VydmljZSBpbmdyZXNzIGVuZHBvaW50LlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgVGhpcyBjb21tYW5kIHJlc29sdmVzIHRoZSBkZXBsb3llZCBpbmdyZXNzIGVuZHBvaW50IGZvciB0aGUgZ2l2ZW4gc2VydmljZSBhbmQgcGF0aCwgY2FsbHMgdGhlIGdpdmVuIGVuZHBvaW50IGFuZFxuICAgIG91dHB1dHMgdGhlIHJlc3VsdC5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBjYWxsIG15LWNvbnRhaW5lclxuICAgICAgICBnYXJkZW4gY2FsbCBteS1jb250YWluZXIvc29tZS1wYXRoXG5cbiAgICBOb3RlOiBDdXJyZW50bHkgb25seSBzdXBwb3J0cyBzaW1wbGUgR0VUIHJlcXVlc3RzIGZvciBIVFRQL0hUVFBTIGluZ3Jlc3Nlcy5cbiAgYFxuXG4gIGFyZ3VtZW50cyA9IGNhbGxBcmdzXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuLCBhcmdzIH06IENvbW1hbmRQYXJhbXM8QXJncz4pOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ+IHtcbiAgICBsZXQgW3NlcnZpY2VOYW1lLCBwYXRoXSA9IHNwbGl0Rmlyc3QoYXJncy5zZXJ2aWNlQW5kUGF0aCwgXCIvXCIpXG5cbiAgICAvLyBUT0RPOiBiZXR0ZXIgZXJyb3Igd2hlbiBzZXJ2aWNlIGRvZXNuJ3QgZXhpc3RcbiAgICBjb25zdCBzZXJ2aWNlID0gYXdhaXQgZ2FyZGVuLmdldFNlcnZpY2Uoc2VydmljZU5hbWUpXG4gICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgZ2FyZGVuLmFjdGlvbnMuZ2V0U2VydmljZVN0YXR1cyh7IHNlcnZpY2UgfSlcblxuICAgIGlmIChzdGF0dXMuc3RhdGUgIT09IFwicmVhZHlcIikge1xuICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihgU2VydmljZSAke3NlcnZpY2UubmFtZX0gaXMgbm90IHJ1bm5pbmdgLCB7XG4gICAgICAgIHNlcnZpY2VOYW1lOiBzZXJ2aWNlLm5hbWUsXG4gICAgICAgIHN0YXR1cyxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgaWYgKCFzdGF0dXMuaW5ncmVzc2VzKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IoYFNlcnZpY2UgJHtzZXJ2aWNlLm5hbWV9IGhhcyBubyBhY3RpdmUgaW5ncmVzc2VzYCwge1xuICAgICAgICBzZXJ2aWNlTmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgICBzZXJ2aWNlU3RhdHVzOiBzdGF0dXMsXG4gICAgICB9KVxuICAgIH1cblxuICAgIC8vIGZpbmQgdGhlIGNvcnJlY3QgZW5kcG9pbnQgdG8gY2FsbFxuICAgIGxldCBtYXRjaGVkSW5ncmVzczogU2VydmljZUluZ3Jlc3MgfCBudWxsID0gbnVsbFxuICAgIGxldCBtYXRjaGVkUGF0aFxuXG4gICAgLy8gd2UgY2FuJ3QgZWFzaWx5IHN1cHBvcnQgcmF3IFRDUCBvciBVRFAgaW4gYSBjb21tYW5kIGxpa2UgdGhpc1xuICAgIGNvbnN0IGluZ3Jlc3NlcyA9IHN0YXR1cy5pbmdyZXNzZXMuZmlsdGVyKGUgPT4gZS5wcm90b2NvbCA9PT0gXCJodHRwXCIgfHwgZS5wcm90b2NvbCA9PT0gXCJodHRwc1wiKVxuXG4gICAgaWYgKCFwYXRoKSB7XG4gICAgICAvLyBpZiBubyBwYXRoIGlzIHNwZWNpZmllZCBhbmQgdGhlcmUncyBhIHJvb3QgZW5kcG9pbnQgKHBhdGggPT09IFwiL1wiKSB3ZSB1c2UgdGhhdFxuICAgICAgY29uc3Qgcm9vdEluZ3Jlc3MgPSA8U2VydmljZUluZ3Jlc3M+ZmluZChpbmdyZXNzZXMsIGUgPT4gZS5wYXRoID09PSBcIi9cIilcblxuICAgICAgaWYgKHJvb3RJbmdyZXNzKSB7XG4gICAgICAgIG1hdGNoZWRJbmdyZXNzID0gcm9vdEluZ3Jlc3NcbiAgICAgICAgbWF0Y2hlZFBhdGggPSBcIi9cIlxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaWYgdGhlcmUncyBubyByb290IGVuZHBvaW50LCBwaWNrIHRoZSBmaXJzdCBlbmRwb2ludFxuICAgICAgICBtYXRjaGVkSW5ncmVzcyA9IGluZ3Jlc3Nlc1swXVxuICAgICAgICBtYXRjaGVkUGF0aCA9IGluZ3Jlc3Nlc1swXS5wYXRoXG4gICAgICB9XG5cbiAgICAgIHBhdGggPSBtYXRjaGVkUGF0aFxuXG4gICAgfSBlbHNlIHtcbiAgICAgIHBhdGggPSBcIi9cIiArIHBhdGhcblxuICAgICAgZm9yIChjb25zdCBpbmdyZXNzIG9mIHN0YXR1cy5pbmdyZXNzZXMpIHtcbiAgICAgICAgaWYgKGluZ3Jlc3MucGF0aCkge1xuICAgICAgICAgIGlmIChwYXRoLnN0YXJ0c1dpdGgoaW5ncmVzcy5wYXRoKSAmJiAoIW1hdGNoZWRQYXRoIHx8IGluZ3Jlc3MucGF0aC5sZW5ndGggPiBtYXRjaGVkUGF0aC5sZW5ndGgpKSB7XG4gICAgICAgICAgICBtYXRjaGVkSW5ncmVzcyA9IGluZ3Jlc3NcbiAgICAgICAgICAgIG1hdGNoZWRQYXRoID0gaW5ncmVzcy5wYXRoXG4gICAgICAgICAgfVxuICAgICAgICB9IGVsc2UgaWYgKCFtYXRjaGVkUGF0aCkge1xuICAgICAgICAgIG1hdGNoZWRJbmdyZXNzID0gaW5ncmVzc1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKCFtYXRjaGVkSW5ncmVzcykge1xuICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBTZXJ2aWNlICR7c2VydmljZS5uYW1lfSBkb2VzIG5vdCBoYXZlIGFuIEhUVFAvSFRUUFMgaW5ncmVzcyBhdCAke3BhdGh9YCwge1xuICAgICAgICBzZXJ2aWNlTmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgICBwYXRoLFxuICAgICAgICBhdmFpbGFibGVJbmdyZXNzZXM6IHN0YXR1cy5pbmdyZXNzZXMsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGNvbnN0IHVybCA9IHJlc29sdmUoZ2V0SW5ncmVzc1VybChtYXRjaGVkSW5ncmVzcyksIHBhdGggfHwgbWF0Y2hlZFBhdGgpXG4gICAgLy8gVE9ETzogc3VwcG9ydCBQT1NUIHJlcXVlc3RzIHdpdGggcmVxdWVzdCBib2R5XG4gICAgY29uc3QgbWV0aG9kID0gXCJnZXRcIlxuXG4gICAgY29uc3QgZW50cnkgPSBnYXJkZW4ubG9nLmluZm8oe1xuICAgICAgbXNnOiBjaGFsay5jeWFuKGBTZW5kaW5nICR7bWF0Y2hlZEluZ3Jlc3MucHJvdG9jb2wudG9VcHBlckNhc2UoKX0gR0VUIHJlcXVlc3QgdG8gYCkgKyB1cmwgKyBcIlxcblwiLFxuICAgICAgc3RhdHVzOiBcImFjdGl2ZVwiLFxuICAgIH0pXG5cbiAgICAvLyB0aGlzIGlzIHRvIGFjY2VwdCBzZWxmLXNpZ25lZCBjZXJ0c1xuICAgIHByb2Nlc3MuZW52Lk5PREVfVExTX1JFSkVDVF9VTkFVVEhPUklaRUQgPSBcIjBcIlxuXG4gICAgY29uc3QgcmVxID0gQXhpb3Moe1xuICAgICAgbWV0aG9kLFxuICAgICAgdXJsLFxuICAgICAgaGVhZGVyczoge1xuICAgICAgICBob3N0OiBtYXRjaGVkSW5ncmVzcy5ob3N0bmFtZSxcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIC8vIFRPRE86IGFkZCB2ZXJib3NlIGFuZCBkZWJ1ZyBsb2dnaW5nIChyZXF1ZXN0L3Jlc3BvbnNlIGhlYWRlcnMgZXRjLilcbiAgICBsZXQgcmVzXG5cbiAgICB0cnkge1xuICAgICAgcmVzID0gYXdhaXQgcmVxXG4gICAgICBlbnRyeS5zZXRTdWNjZXNzKClcbiAgICAgIGdhcmRlbi5sb2cuaW5mbyhjaGFsay5ncmVlbihgJHtyZXMuc3RhdHVzfSAke3Jlcy5zdGF0dXNUZXh0fVxcbmApKVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgcmVzID0gZXJyLnJlc3BvbnNlXG4gICAgICBlbnRyeS5zZXRFcnJvcigpXG4gICAgICBjb25zdCBlcnJvciA9IHJlcyA/IGAke3Jlcy5zdGF0dXN9ICR7cmVzLnN0YXR1c1RleHR9YCA6IGVyci5tZXNzYWdlXG4gICAgICBnYXJkZW4ubG9nLmluZm8oY2hhbGsucmVkKGVycm9yICsgXCJcXG5cIikpXG4gICAgICByZXR1cm4ge31cbiAgICB9XG5cbiAgICBjb25zdCByZXNTdHIgPSBpc09iamVjdChyZXMuZGF0YSkgPyBKU09OLnN0cmluZ2lmeShyZXMuZGF0YSwgbnVsbCwgMikgOiByZXMuZGF0YVxuXG4gICAgcmVzLmRhdGEgJiYgZ2FyZGVuLmxvZy5pbmZvKGNoYWxrLndoaXRlKHJlc1N0cikgKyBcIlxcblwiKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdDoge1xuICAgICAgICBzZXJ2aWNlTmFtZSxcbiAgICAgICAgcGF0aCxcbiAgICAgICAgdXJsLFxuICAgICAgICByZXNwb25zZTogcGljayhyZXMsIFtcInN0YXR1c1wiLCBcInN0YXR1c1RleHRcIiwgXCJoZWFkZXJzXCIsIFwiZGF0YVwiXSksXG4gICAgICB9LFxuICAgIH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/commands.d.ts b/garden-service/build/commands/commands.d.ts new file mode 100644 index 00000000000..2af1247a565 --- /dev/null +++ b/garden-service/build/commands/commands.d.ts @@ -0,0 +1,3 @@ +import { Command } from "./base"; +export declare const coreCommands: Command[]; +//# sourceMappingURL=commands.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/commands.js b/garden-service/build/commands/commands.js new file mode 100644 index 00000000000..7f2af8082ab --- /dev/null +++ b/garden-service/build/commands/commands.js @@ -0,0 +1,51 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const build_1 = require("./build"); +const create_1 = require("./create/create"); +const call_1 = require("./call"); +const init_1 = require("./init"); +const delete_1 = require("./delete"); +const deploy_1 = require("./deploy"); +const dev_1 = require("./dev"); +const get_1 = require("./get"); +const link_1 = require("./link/link"); +const logs_1 = require("./logs"); +const publish_1 = require("./publish"); +const run_1 = require("./run/run"); +const scan_1 = require("./scan"); +const set_1 = require("./set"); +const test_1 = require("./test"); +const unlink_1 = require("./unlink/unlink"); +const update_remote_1 = require("./update-remote/update-remote"); +const validate_1 = require("./validate"); +const exec_1 = require("./exec"); +exports.coreCommands = [ + new build_1.BuildCommand(), + new call_1.CallCommand(), + new create_1.CreateCommand(), + new delete_1.DeleteCommand(), + new deploy_1.DeployCommand(), + new dev_1.DevCommand(), + new exec_1.ExecCommand(), + new get_1.GetCommand(), + new init_1.InitCommand(), + new link_1.LinkCommand(), + new logs_1.LogsCommand(), + new publish_1.PublishCommand(), + new run_1.RunCommand(), + new scan_1.ScanCommand(), + new set_1.SetCommand(), + new test_1.TestCommand(), + new unlink_1.UnlinkCommand(), + new update_remote_1.UpdateRemoteCommand(), + new validate_1.ValidateCommand(), +]; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NvbW1hbmRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBR0gsbUNBQXNDO0FBQ3RDLDRDQUErQztBQUMvQyxpQ0FBb0M7QUFDcEMsaUNBQW9DO0FBQ3BDLHFDQUF3QztBQUN4QyxxQ0FBd0M7QUFDeEMsK0JBQWtDO0FBQ2xDLCtCQUFrQztBQUNsQyxzQ0FBeUM7QUFDekMsaUNBQW9DO0FBQ3BDLHVDQUEwQztBQUMxQyxtQ0FBc0M7QUFDdEMsaUNBQW9DO0FBQ3BDLCtCQUFrQztBQUNsQyxpQ0FBb0M7QUFDcEMsNENBQStDO0FBQy9DLGlFQUFtRTtBQUNuRSx5Q0FBNEM7QUFDNUMsaUNBQW9DO0FBRXZCLFFBQUEsWUFBWSxHQUFjO0lBQ3JDLElBQUksb0JBQVksRUFBRTtJQUNsQixJQUFJLGtCQUFXLEVBQUU7SUFDakIsSUFBSSxzQkFBYSxFQUFFO0lBQ25CLElBQUksc0JBQWEsRUFBRTtJQUNuQixJQUFJLHNCQUFhLEVBQUU7SUFDbkIsSUFBSSxnQkFBVSxFQUFFO0lBQ2hCLElBQUksa0JBQVcsRUFBRTtJQUNqQixJQUFJLGdCQUFVLEVBQUU7SUFDaEIsSUFBSSxrQkFBVyxFQUFFO0lBQ2pCLElBQUksa0JBQVcsRUFBRTtJQUNqQixJQUFJLGtCQUFXLEVBQUU7SUFDakIsSUFBSSx3QkFBYyxFQUFFO0lBQ3BCLElBQUksZ0JBQVUsRUFBRTtJQUNoQixJQUFJLGtCQUFXLEVBQUU7SUFDakIsSUFBSSxnQkFBVSxFQUFFO0lBQ2hCLElBQUksa0JBQVcsRUFBRTtJQUNqQixJQUFJLHNCQUFhLEVBQUU7SUFDbkIsSUFBSSxtQ0FBbUIsRUFBRTtJQUN6QixJQUFJLDBCQUFlLEVBQUU7Q0FDdEIsQ0FBQSIsImZpbGUiOiJjb21tYW5kcy9jb21tYW5kcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgeyBCdWlsZENvbW1hbmQgfSBmcm9tIFwiLi9idWlsZFwiXG5pbXBvcnQgeyBDcmVhdGVDb21tYW5kIH0gZnJvbSBcIi4vY3JlYXRlL2NyZWF0ZVwiXG5pbXBvcnQgeyBDYWxsQ29tbWFuZCB9IGZyb20gXCIuL2NhbGxcIlxuaW1wb3J0IHsgSW5pdENvbW1hbmQgfSBmcm9tIFwiLi9pbml0XCJcbmltcG9ydCB7IERlbGV0ZUNvbW1hbmQgfSBmcm9tIFwiLi9kZWxldGVcIlxuaW1wb3J0IHsgRGVwbG95Q29tbWFuZCB9IGZyb20gXCIuL2RlcGxveVwiXG5pbXBvcnQgeyBEZXZDb21tYW5kIH0gZnJvbSBcIi4vZGV2XCJcbmltcG9ydCB7IEdldENvbW1hbmQgfSBmcm9tIFwiLi9nZXRcIlxuaW1wb3J0IHsgTGlua0NvbW1hbmQgfSBmcm9tIFwiLi9saW5rL2xpbmtcIlxuaW1wb3J0IHsgTG9nc0NvbW1hbmQgfSBmcm9tIFwiLi9sb2dzXCJcbmltcG9ydCB7IFB1Ymxpc2hDb21tYW5kIH0gZnJvbSBcIi4vcHVibGlzaFwiXG5pbXBvcnQgeyBSdW5Db21tYW5kIH0gZnJvbSBcIi4vcnVuL3J1blwiXG5pbXBvcnQgeyBTY2FuQ29tbWFuZCB9IGZyb20gXCIuL3NjYW5cIlxuaW1wb3J0IHsgU2V0Q29tbWFuZCB9IGZyb20gXCIuL3NldFwiXG5pbXBvcnQgeyBUZXN0Q29tbWFuZCB9IGZyb20gXCIuL3Rlc3RcIlxuaW1wb3J0IHsgVW5saW5rQ29tbWFuZCB9IGZyb20gXCIuL3VubGluay91bmxpbmtcIlxuaW1wb3J0IHsgVXBkYXRlUmVtb3RlQ29tbWFuZCB9IGZyb20gXCIuL3VwZGF0ZS1yZW1vdGUvdXBkYXRlLXJlbW90ZVwiXG5pbXBvcnQgeyBWYWxpZGF0ZUNvbW1hbmQgfSBmcm9tIFwiLi92YWxpZGF0ZVwiXG5pbXBvcnQgeyBFeGVjQ29tbWFuZCB9IGZyb20gXCIuL2V4ZWNcIlxuXG5leHBvcnQgY29uc3QgY29yZUNvbW1hbmRzOiBDb21tYW5kW10gPSBbXG4gIG5ldyBCdWlsZENvbW1hbmQoKSxcbiAgbmV3IENhbGxDb21tYW5kKCksXG4gIG5ldyBDcmVhdGVDb21tYW5kKCksXG4gIG5ldyBEZWxldGVDb21tYW5kKCksXG4gIG5ldyBEZXBsb3lDb21tYW5kKCksXG4gIG5ldyBEZXZDb21tYW5kKCksXG4gIG5ldyBFeGVjQ29tbWFuZCgpLFxuICBuZXcgR2V0Q29tbWFuZCgpLFxuICBuZXcgSW5pdENvbW1hbmQoKSxcbiAgbmV3IExpbmtDb21tYW5kKCksXG4gIG5ldyBMb2dzQ29tbWFuZCgpLFxuICBuZXcgUHVibGlzaENvbW1hbmQoKSxcbiAgbmV3IFJ1bkNvbW1hbmQoKSxcbiAgbmV3IFNjYW5Db21tYW5kKCksXG4gIG5ldyBTZXRDb21tYW5kKCksXG4gIG5ldyBUZXN0Q29tbWFuZCgpLFxuICBuZXcgVW5saW5rQ29tbWFuZCgpLFxuICBuZXcgVXBkYXRlUmVtb3RlQ29tbWFuZCgpLFxuICBuZXcgVmFsaWRhdGVDb21tYW5kKCksXG5dXG4iXX0= diff --git a/garden-service/build/commands/create/config-templates.d.ts b/garden-service/build/commands/create/config-templates.d.ts new file mode 100644 index 00000000000..c402cce39df --- /dev/null +++ b/garden-service/build/commands/create/config-templates.d.ts @@ -0,0 +1,43 @@ +import * as Joi from "joi"; +import { DeepPartial } from "../../util/util"; +import { ContainerModuleSpec } from "../../plugins/container"; +import { GcfModuleSpec } from "../../plugins/google/google-cloud-functions"; +import { ProjectConfig } from "../../config/project"; +import { BaseModuleSpec, ModuleConfig } from "../../config/module"; +/** + * Ideally there would be some mechanism to discover available module types, + * and for plugins to expose a minimal config for the given type along with + * a list of providers per environment, rather than hard coding these values. + * + * Alternatively, consider co-locating the templates with the plugins. + */ +export declare const MODULE_PROVIDER_MAP: { + container: string; + "google-cloud-function": string; + "npm-package": string; +}; +export declare const availableModuleTypes: ("container" | "npm-package" | "google-cloud-function")[]; +export declare type ModuleType = keyof typeof MODULE_PROVIDER_MAP; +export declare const moduleSchema: Joi.ObjectSchema; +export interface ConfigOpts { + name: string; + path: string; + config: { + module: Partial; + } | Partial; +} +export interface ModuleConfigOpts extends ConfigOpts { + type: ModuleType; + config: { + module: Partial; + }; +} +export interface ProjectConfigOpts extends ConfigOpts { + config: Partial; +} +export declare function containerTemplate(moduleName: string): DeepPartial; +export declare function googleCloudFunctionTemplate(moduleName: string): DeepPartial; +export declare function npmPackageTemplate(_moduleName: string): any; +export declare const projectTemplate: (name: string, moduleTypes: ("container" | "npm-package" | "google-cloud-function")[]) => Partial; +export declare const moduleTemplate: (name: string, type: "container" | "npm-package" | "google-cloud-function") => Partial; +//# sourceMappingURL=config-templates.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/config-templates.js b/garden-service/build/commands/create/config-templates.js new file mode 100644 index 00000000000..50dc11bd291 --- /dev/null +++ b/garden-service/build/commands/create/config-templates.js @@ -0,0 +1,81 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const Joi = require("joi"); +const module_1 = require("../../config/module"); +/** + * Ideally there would be some mechanism to discover available module types, + * and for plugins to expose a minimal config for the given type along with + * a list of providers per environment, rather than hard coding these values. + * + * Alternatively, consider co-locating the templates with the plugins. + */ +exports.MODULE_PROVIDER_MAP = { + container: "local-kubernetes", + "google-cloud-function": "local-google-cloud-functions", + "npm-package": "npm-package", +}; +exports.availableModuleTypes = Object.keys(exports.MODULE_PROVIDER_MAP); +exports.moduleSchema = Joi.object().keys({ + module: module_1.baseModuleSpecSchema, +}); +const noCase = (str) => str.replace(/-|_/g, " "); +const titleize = (str) => lodash_1.capitalize(noCase(str)); +function containerTemplate(moduleName) { + return { + services: [ + { + name: `${moduleName}-service`, + ports: [{ + name: "http", + containerPort: 8080, + }], + ingresses: [{ + path: "/", + port: "http", + }], + }, + ], + }; +} +exports.containerTemplate = containerTemplate; +function googleCloudFunctionTemplate(moduleName) { + return { + functions: [{ + name: `${moduleName}-google-cloud-function`, + entrypoint: lodash_1.camelCase(`${moduleName}-google-cloud-function`), + }], + }; +} +exports.googleCloudFunctionTemplate = googleCloudFunctionTemplate; +function npmPackageTemplate(_moduleName) { + return {}; +} +exports.npmPackageTemplate = npmPackageTemplate; +exports.projectTemplate = (name, moduleTypes) => { + const providers = lodash_1.uniq(moduleTypes).map(type => ({ name: exports.MODULE_PROVIDER_MAP[type] })); + return { + name, + environments: [ + { + name: "local", + providers, + variables: {}, + }, + ], + }; +}; +exports.moduleTemplate = (name, type) => ({ + name, + type, + description: `${titleize(name)} ${noCase(type)}`, +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9jb25maWctdGVtcGxhdGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBRUgsbUNBQW9EO0FBQ3BELDJCQUEwQjtBQU0xQixnREFBd0Y7QUFFeEY7Ozs7OztHQU1HO0FBQ1UsUUFBQSxtQkFBbUIsR0FBRztJQUNqQyxTQUFTLEVBQUUsa0JBQWtCO0lBQzdCLHVCQUF1QixFQUFFLDhCQUE4QjtJQUN2RCxhQUFhLEVBQUUsYUFBYTtDQUM3QixDQUFBO0FBRVksUUFBQSxvQkFBb0IsR0FBaUIsTUFBTSxDQUFDLElBQUksQ0FBQywyQkFBbUIsQ0FBQyxDQUFBO0FBSXJFLFFBQUEsWUFBWSxHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxJQUFJLENBQUM7SUFDNUMsTUFBTSxFQUFFLDZCQUFvQjtDQUM3QixDQUFDLENBQUE7QUFpQkYsTUFBTSxNQUFNLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsTUFBTSxFQUFFLEdBQUcsQ0FBQyxDQUFBO0FBQ3hELE1BQU0sUUFBUSxHQUFHLENBQUMsR0FBVyxFQUFFLEVBQUUsQ0FBQyxtQkFBVSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFBO0FBRXpELFNBQWdCLGlCQUFpQixDQUFDLFVBQWtCO0lBQ2xELE9BQU87UUFDTCxRQUFRLEVBQUU7WUFDUjtnQkFDRSxJQUFJLEVBQUUsR0FBRyxVQUFVLFVBQVU7Z0JBQzdCLEtBQUssRUFBRSxDQUFDO3dCQUNOLElBQUksRUFBRSxNQUFNO3dCQUNaLGFBQWEsRUFBRSxJQUFJO3FCQUNwQixDQUFDO2dCQUNGLFNBQVMsRUFBRSxDQUFDO3dCQUNWLElBQUksRUFBRSxHQUFHO3dCQUNULElBQUksRUFBRSxNQUFNO3FCQUNiLENBQUM7YUFDSDtTQUNGO0tBQ0YsQ0FBQTtBQUNILENBQUM7QUFoQkQsOENBZ0JDO0FBRUQsU0FBZ0IsMkJBQTJCLENBQUMsVUFBa0I7SUFDNUQsT0FBTztRQUNMLFNBQVMsRUFBRSxDQUFDO2dCQUNWLElBQUksRUFBRSxHQUFHLFVBQVUsd0JBQXdCO2dCQUMzQyxVQUFVLEVBQUUsa0JBQVMsQ0FBQyxHQUFHLFVBQVUsd0JBQXdCLENBQUM7YUFDN0QsQ0FBQztLQUNILENBQUE7QUFDSCxDQUFDO0FBUEQsa0VBT0M7QUFFRCxTQUFnQixrQkFBa0IsQ0FBQyxXQUFtQjtJQUNwRCxPQUFPLEVBQUUsQ0FBQTtBQUNYLENBQUM7QUFGRCxnREFFQztBQUVZLFFBQUEsZUFBZSxHQUFHLENBQUMsSUFBWSxFQUFFLFdBQXlCLEVBQTBCLEVBQUU7SUFDakcsTUFBTSxTQUFTLEdBQUcsYUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsMkJBQW1CLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUE7SUFDdEYsT0FBTztRQUNMLElBQUk7UUFDSixZQUFZLEVBQUU7WUFDWjtnQkFDRSxJQUFJLEVBQUUsT0FBTztnQkFDYixTQUFTO2dCQUNULFNBQVMsRUFBRSxFQUFFO2FBQ2Q7U0FDRjtLQUNGLENBQUE7QUFDSCxDQUFDLENBQUE7QUFFWSxRQUFBLGNBQWMsR0FBRyxDQUFDLElBQVksRUFBRSxJQUFnQixFQUEyQixFQUFFLENBQUMsQ0FBQztJQUMxRixJQUFJO0lBQ0osSUFBSTtJQUNKLFdBQVcsRUFBRSxHQUFHLFFBQVEsQ0FBQyxJQUFJLENBQUMsSUFBSSxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7Q0FDakQsQ0FBQyxDQUFBIiwiZmlsZSI6ImNvbW1hbmRzL2NyZWF0ZS9jb25maWctdGVtcGxhdGVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGNhcGl0YWxpemUsIGNhbWVsQ2FzZSwgdW5pcSB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuXG5pbXBvcnQgeyBEZWVwUGFydGlhbCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgQ29udGFpbmVyTW9kdWxlU3BlYyB9IGZyb20gXCIuLi8uLi9wbHVnaW5zL2NvbnRhaW5lclwiXG5pbXBvcnQgeyBHY2ZNb2R1bGVTcGVjIH0gZnJvbSBcIi4uLy4uL3BsdWdpbnMvZ29vZ2xlL2dvb2dsZS1jbG91ZC1mdW5jdGlvbnNcIlxuaW1wb3J0IHsgUHJvamVjdENvbmZpZyB9IGZyb20gXCIuLi8uLi9jb25maWcvcHJvamVjdFwiXG5pbXBvcnQgeyBCYXNlTW9kdWxlU3BlYywgTW9kdWxlQ29uZmlnLCBiYXNlTW9kdWxlU3BlY1NjaGVtYSB9IGZyb20gXCIuLi8uLi9jb25maWcvbW9kdWxlXCJcblxuLyoqXG4gKiBJZGVhbGx5IHRoZXJlIHdvdWxkIGJlIHNvbWUgbWVjaGFuaXNtIHRvIGRpc2NvdmVyIGF2YWlsYWJsZSBtb2R1bGUgdHlwZXMsXG4gKiBhbmQgZm9yIHBsdWdpbnMgdG8gZXhwb3NlIGEgbWluaW1hbCBjb25maWcgZm9yIHRoZSBnaXZlbiB0eXBlIGFsb25nIHdpdGhcbiAqIGEgbGlzdCBvZiBwcm92aWRlcnMgcGVyIGVudmlyb25tZW50LCByYXRoZXIgdGhhbiBoYXJkIGNvZGluZyB0aGVzZSB2YWx1ZXMuXG4gKlxuICogQWx0ZXJuYXRpdmVseSwgY29uc2lkZXIgY28tbG9jYXRpbmcgdGhlIHRlbXBsYXRlcyB3aXRoIHRoZSBwbHVnaW5zLlxuICovXG5leHBvcnQgY29uc3QgTU9EVUxFX1BST1ZJREVSX01BUCA9IHtcbiAgY29udGFpbmVyOiBcImxvY2FsLWt1YmVybmV0ZXNcIixcbiAgXCJnb29nbGUtY2xvdWQtZnVuY3Rpb25cIjogXCJsb2NhbC1nb29nbGUtY2xvdWQtZnVuY3Rpb25zXCIsXG4gIFwibnBtLXBhY2thZ2VcIjogXCJucG0tcGFja2FnZVwiLFxufVxuXG5leHBvcnQgY29uc3QgYXZhaWxhYmxlTW9kdWxlVHlwZXMgPSA8TW9kdWxlVHlwZVtdPk9iamVjdC5rZXlzKE1PRFVMRV9QUk9WSURFUl9NQVApXG5cbmV4cG9ydCB0eXBlIE1vZHVsZVR5cGUgPSBrZXlvZiB0eXBlb2YgTU9EVUxFX1BST1ZJREVSX01BUFxuXG5leHBvcnQgY29uc3QgbW9kdWxlU2NoZW1hID0gSm9pLm9iamVjdCgpLmtleXMoe1xuICBtb2R1bGU6IGJhc2VNb2R1bGVTcGVjU2NoZW1hLFxufSlcblxuZXhwb3J0IGludGVyZmFjZSBDb25maWdPcHRzIHtcbiAgbmFtZTogc3RyaW5nXG4gIHBhdGg6IHN0cmluZ1xuICBjb25maWc6IHsgbW9kdWxlOiBQYXJ0aWFsPE1vZHVsZUNvbmZpZz4gfSB8IFBhcnRpYWw8UHJvamVjdENvbmZpZz5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb2R1bGVDb25maWdPcHRzIGV4dGVuZHMgQ29uZmlnT3B0cyB7XG4gIHR5cGU6IE1vZHVsZVR5cGVcbiAgY29uZmlnOiB7IG1vZHVsZTogUGFydGlhbDxNb2R1bGVDb25maWc+IH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9qZWN0Q29uZmlnT3B0cyBleHRlbmRzIENvbmZpZ09wdHMge1xuICBjb25maWc6IFBhcnRpYWw8UHJvamVjdENvbmZpZz5cbn1cblxuY29uc3Qgbm9DYXNlID0gKHN0cjogc3RyaW5nKSA9PiBzdHIucmVwbGFjZSgvLXxfL2csIFwiIFwiKVxuY29uc3QgdGl0bGVpemUgPSAoc3RyOiBzdHJpbmcpID0+IGNhcGl0YWxpemUobm9DYXNlKHN0cikpXG5cbmV4cG9ydCBmdW5jdGlvbiBjb250YWluZXJUZW1wbGF0ZShtb2R1bGVOYW1lOiBzdHJpbmcpOiBEZWVwUGFydGlhbDxDb250YWluZXJNb2R1bGVTcGVjPiB7XG4gIHJldHVybiB7XG4gICAgc2VydmljZXM6IFtcbiAgICAgIHtcbiAgICAgICAgbmFtZTogYCR7bW9kdWxlTmFtZX0tc2VydmljZWAsXG4gICAgICAgIHBvcnRzOiBbe1xuICAgICAgICAgIG5hbWU6IFwiaHR0cFwiLFxuICAgICAgICAgIGNvbnRhaW5lclBvcnQ6IDgwODAsXG4gICAgICAgIH1dLFxuICAgICAgICBpbmdyZXNzZXM6IFt7XG4gICAgICAgICAgcGF0aDogXCIvXCIsXG4gICAgICAgICAgcG9ydDogXCJodHRwXCIsXG4gICAgICAgIH1dLFxuICAgICAgfSxcbiAgICBdLFxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnb29nbGVDbG91ZEZ1bmN0aW9uVGVtcGxhdGUobW9kdWxlTmFtZTogc3RyaW5nKTogRGVlcFBhcnRpYWw8R2NmTW9kdWxlU3BlYz4ge1xuICByZXR1cm4ge1xuICAgIGZ1bmN0aW9uczogW3tcbiAgICAgIG5hbWU6IGAke21vZHVsZU5hbWV9LWdvb2dsZS1jbG91ZC1mdW5jdGlvbmAsXG4gICAgICBlbnRyeXBvaW50OiBjYW1lbENhc2UoYCR7bW9kdWxlTmFtZX0tZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uYCksXG4gICAgfV0sXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIG5wbVBhY2thZ2VUZW1wbGF0ZShfbW9kdWxlTmFtZTogc3RyaW5nKTogYW55IHtcbiAgcmV0dXJuIHt9XG59XG5cbmV4cG9ydCBjb25zdCBwcm9qZWN0VGVtcGxhdGUgPSAobmFtZTogc3RyaW5nLCBtb2R1bGVUeXBlczogTW9kdWxlVHlwZVtdKTogUGFydGlhbDxQcm9qZWN0Q29uZmlnPiA9PiB7XG4gIGNvbnN0IHByb3ZpZGVycyA9IHVuaXEobW9kdWxlVHlwZXMpLm1hcCh0eXBlID0+ICh7IG5hbWU6IE1PRFVMRV9QUk9WSURFUl9NQVBbdHlwZV0gfSkpXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICBlbnZpcm9ubWVudHM6IFtcbiAgICAgIHtcbiAgICAgICAgbmFtZTogXCJsb2NhbFwiLFxuICAgICAgICBwcm92aWRlcnMsXG4gICAgICAgIHZhcmlhYmxlczoge30sXG4gICAgICB9LFxuICAgIF0sXG4gIH1cbn1cblxuZXhwb3J0IGNvbnN0IG1vZHVsZVRlbXBsYXRlID0gKG5hbWU6IHN0cmluZywgdHlwZTogTW9kdWxlVHlwZSk6IFBhcnRpYWw8QmFzZU1vZHVsZVNwZWM+ID0+ICh7XG4gIG5hbWUsXG4gIHR5cGUsXG4gIGRlc2NyaXB0aW9uOiBgJHt0aXRsZWl6ZShuYW1lKX0gJHtub0Nhc2UodHlwZSl9YCxcbn0pXG4iXX0= diff --git a/garden-service/build/commands/create/create.d.ts b/garden-service/build/commands/create/create.d.ts new file mode 100644 index 00000000000..3664a416f24 --- /dev/null +++ b/garden-service/build/commands/create/create.d.ts @@ -0,0 +1,11 @@ +import { Command } from "../base"; +import { CreateProjectCommand } from "./project"; +import { CreateModuleCommand } from "./module"; +export declare class CreateCommand extends Command { + name: string; + alias: string; + help: string; + subCommands: (typeof CreateProjectCommand | typeof CreateModuleCommand)[]; + action(): Promise<{}>; +} +//# sourceMappingURL=create.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/create.js b/garden-service/build/commands/create/create.js new file mode 100644 index 00000000000..a34f8f9461b --- /dev/null +++ b/garden-service/build/commands/create/create.js @@ -0,0 +1,38 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("../base"); +const project_1 = require("./project"); +const module_1 = require("./module"); +class CreateCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "create"; + this.alias = "r"; + this.help = "Create a new project or add a new module"; + this.subCommands = [ + project_1.CreateProjectCommand, + module_1.CreateModuleCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.CreateCommand = CreateCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9jcmVhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGtDQUFpQztBQUNqQyx1Q0FBZ0Q7QUFDaEQscUNBQThDO0FBRTlDLE1BQWEsYUFBYyxTQUFRLGNBQU87SUFBMUM7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFVBQUssR0FBRyxHQUFHLENBQUE7UUFDWCxTQUFJLEdBQUcsMENBQTBDLENBQUE7UUFFakQsZ0JBQVcsR0FBRztZQUNaLDhCQUFvQjtZQUNwQiw0QkFBbUI7U0FDcEIsQ0FBQTtJQUdILENBQUM7SUFETyxNQUFNOzhEQUFLLE9BQU8sRUFBRSxDQUFBLENBQUMsQ0FBQztLQUFBO0NBQzdCO0FBWEQsc0NBV0MiLCJmaWxlIjoiY29tbWFuZHMvY3JlYXRlL2NyZWF0ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgQ3JlYXRlUHJvamVjdENvbW1hbmQgfSBmcm9tIFwiLi9wcm9qZWN0XCJcbmltcG9ydCB7IENyZWF0ZU1vZHVsZUNvbW1hbmQgfSBmcm9tIFwiLi9tb2R1bGVcIlxuXG5leHBvcnQgY2xhc3MgQ3JlYXRlQ29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBuYW1lID0gXCJjcmVhdGVcIlxuICBhbGlhcyA9IFwiclwiXG4gIGhlbHAgPSBcIkNyZWF0ZSBhIG5ldyBwcm9qZWN0IG9yIGFkZCBhIG5ldyBtb2R1bGVcIlxuXG4gIHN1YkNvbW1hbmRzID0gW1xuICAgIENyZWF0ZVByb2plY3RDb21tYW5kLFxuICAgIENyZWF0ZU1vZHVsZUNvbW1hbmQsXG4gIF1cblxuICBhc3luYyBhY3Rpb24oKSB7IHJldHVybiB7fSB9XG59XG4iXX0= diff --git a/garden-service/build/commands/create/helpers.d.ts b/garden-service/build/commands/create/helpers.d.ts new file mode 100644 index 00000000000..e1a40b51d20 --- /dev/null +++ b/garden-service/build/commands/create/helpers.d.ts @@ -0,0 +1,6 @@ +import * as Joi from "joi"; +import { ModuleConfigOpts, ModuleType, ConfigOpts } from "./config-templates"; +import { LogNode } from "../../logger/log-node"; +export declare function prepareNewModuleConfig(name: string, type: ModuleType, path: string): ModuleConfigOpts; +export declare function dumpConfig(configOpts: ConfigOpts, schema: Joi.Schema, logger: LogNode): Promise; +//# sourceMappingURL=helpers.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/helpers.js b/garden-service/build/commands/create/helpers.js new file mode 100644 index 00000000000..db429dba13b --- /dev/null +++ b/garden-service/build/commands/create/helpers.js @@ -0,0 +1,65 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const config_templates_1 = require("./config-templates"); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const common_1 = require("../../config/common"); +const util_1 = require("../../util/util"); +const constants_1 = require("../../constants"); +function prepareNewModuleConfig(name, type, path) { + const moduleTypeTemplate = { + container: config_templates_1.containerTemplate, + "google-cloud-function": config_templates_1.googleCloudFunctionTemplate, + "npm-package": config_templates_1.npmPackageTemplate, + }[type]; + return { + name, + type, + path, + config: { + module: Object.assign({}, config_templates_1.moduleTemplate(name, type), moduleTypeTemplate(name)), + }, + }; +} +exports.prepareNewModuleConfig = prepareNewModuleConfig; +function dumpConfig(configOpts, schema, logger) { + return __awaiter(this, void 0, void 0, function* () { + const { config, name, path } = configOpts; + const yamlPath = path_1.join(path, constants_1.MODULE_CONFIG_FILENAME); + const task = logger.info({ + msg: `Writing config for ${name}`, + status: "active", + }); + if (yield fs_extra_1.pathExists(yamlPath)) { + task.setWarn({ msg: `Garden config file already exists at path, skipping`, append: true }); + return; + } + try { + common_1.validate(config, schema); + yield util_1.dumpYaml(yamlPath, config); + task.setSuccess(); + } + catch (err) { + task.setError({ msg: `Generated config is invalid, skipping`, append: true }); + throw err; + } + }); +} +exports.dumpConfig = dumpConfig; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9oZWxwZXJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFHSCx5REFRMkI7QUFDM0IsK0JBQTJCO0FBQzNCLHVDQUFxQztBQUNyQyxnREFBOEM7QUFDOUMsMENBQTBDO0FBQzFDLCtDQUF3RDtBQUd4RCxTQUFnQixzQkFBc0IsQ0FBQyxJQUFZLEVBQUUsSUFBZ0IsRUFBRSxJQUFZO0lBQ2pGLE1BQU0sa0JBQWtCLEdBQUc7UUFDekIsU0FBUyxFQUFFLG9DQUFpQjtRQUM1Qix1QkFBdUIsRUFBRSw4Q0FBMkI7UUFDcEQsYUFBYSxFQUFFLHFDQUFrQjtLQUNsQyxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ1AsT0FBTztRQUNMLElBQUk7UUFDSixJQUFJO1FBQ0osSUFBSTtRQUNKLE1BQU0sRUFBRTtZQUNOLE1BQU0sb0JBQ0QsaUNBQWMsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLEVBQzFCLGtCQUFrQixDQUFDLElBQUksQ0FBQyxDQUM1QjtTQUNGO0tBQ0YsQ0FBQTtBQUNILENBQUM7QUFqQkQsd0RBaUJDO0FBRUQsU0FBc0IsVUFBVSxDQUFDLFVBQXNCLEVBQUUsTUFBa0IsRUFBRSxNQUFlOztRQUMxRixNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsR0FBRyxVQUFVLENBQUE7UUFDekMsTUFBTSxRQUFRLEdBQUcsV0FBSSxDQUFDLElBQUksRUFBRSxrQ0FBc0IsQ0FBQyxDQUFBO1FBQ25ELE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUM7WUFDdkIsR0FBRyxFQUFFLHNCQUFzQixJQUFJLEVBQUU7WUFDakMsTUFBTSxFQUFFLFFBQVE7U0FDakIsQ0FBQyxDQUFBO1FBRUYsSUFBSSxNQUFNLHFCQUFVLENBQUMsUUFBUSxDQUFDLEVBQUU7WUFDOUIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxFQUFFLEdBQUcsRUFBRSxxREFBcUQsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtZQUMxRixPQUFNO1NBQ1A7UUFFRCxJQUFJO1lBQ0YsaUJBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7WUFDeEIsTUFBTSxlQUFRLENBQUMsUUFBUSxFQUFFLE1BQU0sQ0FBQyxDQUFBO1lBQ2hDLElBQUksQ0FBQyxVQUFVLEVBQUUsQ0FBQTtTQUNsQjtRQUFDLE9BQU8sR0FBRyxFQUFFO1lBQ1osSUFBSSxDQUFDLFFBQVEsQ0FBQyxFQUFFLEdBQUcsRUFBRSx1Q0FBdUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtZQUM3RSxNQUFNLEdBQUcsQ0FBQTtTQUNWO0lBQ0gsQ0FBQztDQUFBO0FBckJELGdDQXFCQyIsImZpbGUiOiJjb21tYW5kcy9jcmVhdGUvaGVscGVycy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQge1xuICBjb250YWluZXJUZW1wbGF0ZSxcbiAgZ29vZ2xlQ2xvdWRGdW5jdGlvblRlbXBsYXRlLFxuICBucG1QYWNrYWdlVGVtcGxhdGUsXG4gIE1vZHVsZUNvbmZpZ09wdHMsXG4gIE1vZHVsZVR5cGUsXG4gIG1vZHVsZVRlbXBsYXRlLFxuICBDb25maWdPcHRzLFxufSBmcm9tIFwiLi9jb25maWctdGVtcGxhdGVzXCJcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBwYXRoRXhpc3RzIH0gZnJvbSBcImZzLWV4dHJhXCJcbmltcG9ydCB7IHZhbGlkYXRlIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgZHVtcFlhbWwgfSBmcm9tIFwiLi4vLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IE1PRFVMRV9DT05GSUdfRklMRU5BTUUgfSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IExvZ05vZGUgfSBmcm9tIFwiLi4vLi4vbG9nZ2VyL2xvZy1ub2RlXCJcblxuZXhwb3J0IGZ1bmN0aW9uIHByZXBhcmVOZXdNb2R1bGVDb25maWcobmFtZTogc3RyaW5nLCB0eXBlOiBNb2R1bGVUeXBlLCBwYXRoOiBzdHJpbmcpOiBNb2R1bGVDb25maWdPcHRzIHtcbiAgY29uc3QgbW9kdWxlVHlwZVRlbXBsYXRlID0ge1xuICAgIGNvbnRhaW5lcjogY29udGFpbmVyVGVtcGxhdGUsXG4gICAgXCJnb29nbGUtY2xvdWQtZnVuY3Rpb25cIjogZ29vZ2xlQ2xvdWRGdW5jdGlvblRlbXBsYXRlLFxuICAgIFwibnBtLXBhY2thZ2VcIjogbnBtUGFja2FnZVRlbXBsYXRlLFxuICB9W3R5cGVdXG4gIHJldHVybiB7XG4gICAgbmFtZSxcbiAgICB0eXBlLFxuICAgIHBhdGgsXG4gICAgY29uZmlnOiB7XG4gICAgICBtb2R1bGU6IHtcbiAgICAgICAgLi4ubW9kdWxlVGVtcGxhdGUobmFtZSwgdHlwZSksXG4gICAgICAgIC4uLm1vZHVsZVR5cGVUZW1wbGF0ZShuYW1lKSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZHVtcENvbmZpZyhjb25maWdPcHRzOiBDb25maWdPcHRzLCBzY2hlbWE6IEpvaS5TY2hlbWEsIGxvZ2dlcjogTG9nTm9kZSkge1xuICBjb25zdCB7IGNvbmZpZywgbmFtZSwgcGF0aCB9ID0gY29uZmlnT3B0c1xuICBjb25zdCB5YW1sUGF0aCA9IGpvaW4ocGF0aCwgTU9EVUxFX0NPTkZJR19GSUxFTkFNRSlcbiAgY29uc3QgdGFzayA9IGxvZ2dlci5pbmZvKHtcbiAgICBtc2c6IGBXcml0aW5nIGNvbmZpZyBmb3IgJHtuYW1lfWAsXG4gICAgc3RhdHVzOiBcImFjdGl2ZVwiLFxuICB9KVxuXG4gIGlmIChhd2FpdCBwYXRoRXhpc3RzKHlhbWxQYXRoKSkge1xuICAgIHRhc2suc2V0V2Fybih7IG1zZzogYEdhcmRlbiBjb25maWcgZmlsZSBhbHJlYWR5IGV4aXN0cyBhdCBwYXRoLCBza2lwcGluZ2AsIGFwcGVuZDogdHJ1ZSB9KVxuICAgIHJldHVyblxuICB9XG5cbiAgdHJ5IHtcbiAgICB2YWxpZGF0ZShjb25maWcsIHNjaGVtYSlcbiAgICBhd2FpdCBkdW1wWWFtbCh5YW1sUGF0aCwgY29uZmlnKVxuICAgIHRhc2suc2V0U3VjY2VzcygpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHRhc2suc2V0RXJyb3IoeyBtc2c6IGBHZW5lcmF0ZWQgY29uZmlnIGlzIGludmFsaWQsIHNraXBwaW5nYCwgYXBwZW5kOiB0cnVlIH0pXG4gICAgdGhyb3cgZXJyXG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/create/module.d.ts b/garden-service/build/commands/create/module.d.ts new file mode 100644 index 00000000000..0c254266e9b --- /dev/null +++ b/garden-service/build/commands/create/module.d.ts @@ -0,0 +1,33 @@ +import { Command, CommandResult, StringParameter, ChoicesParameter, CommandParams } from "../base"; +import { ModuleConfigOpts } from "./config-templates"; +declare const createModuleOptions: { + name: StringParameter; + type: ChoicesParameter; +}; +declare const createModuleArguments: { + "module-dir": StringParameter; +}; +declare type Args = typeof createModuleArguments; +declare type Opts = typeof createModuleOptions; +interface CreateModuleResult extends CommandResult { + result: { + module?: ModuleConfigOpts; + }; +} +export declare class CreateModuleCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + noProject: boolean; + arguments: { + "module-dir": StringParameter; + }; + options: { + name: StringParameter; + type: ChoicesParameter; + }; + action({ garden, args, opts }: CommandParams): Promise; +} +export {}; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/module.js b/garden-service/build/commands/create/module.js new file mode 100644 index 00000000000..7732a805cc2 --- /dev/null +++ b/garden-service/build/commands/create/module.js @@ -0,0 +1,103 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const dedent = require("dedent"); +const base_1 = require("../base"); +const exceptions_1 = require("../../exceptions"); +const config_templates_1 = require("./config-templates"); +const helpers_1 = require("./helpers"); +const prompts_1 = require("./prompts"); +const common_1 = require("../../config/common"); +const fs_extra_1 = require("fs-extra"); +const createModuleOptions = { + name: new base_1.StringParameter({ + help: "Assigns a custom name to the module. (Defaults to name of the current directory.)", + }), + type: new base_1.ChoicesParameter({ + help: "Type of module.", + choices: config_templates_1.availableModuleTypes, + }), +}; +const createModuleArguments = { + "module-dir": new base_1.StringParameter({ + help: "Directory of the module. (Defaults to current directory.)", + }), +}; +class CreateModuleCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "module"; + this.alias = "m"; + this.help = "Creates a new Garden module."; + this.description = dedent ` + Creates a new Garden module of the given type + + Examples: + + garden create module # creates a new module in the current directory (module name defaults to directory name) + garden create module my-module # creates a new module in my-module directory + garden create module --type=container # creates a new container module + garden create module --name=my-module # creates a new module in current directory and names it my-module + `; + this.noProject = true; + this.arguments = createModuleArguments; + this.options = createModuleOptions; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + let errors = []; + const moduleRoot = path_1.join(garden.projectRoot, (args["module-dir"] || "").trim()); + const moduleName = common_1.validate(opts.name || path_1.basename(moduleRoot), common_1.joiIdentifier(), { context: "module name" }); + yield fs_extra_1.ensureDir(moduleRoot); + garden.log.header({ emoji: "house_with_garden", command: "create" }); + garden.log.info(`Initializing new module ${moduleName}`); + let type; + if (opts.type) { + // Type passed as parameter + type = opts.type; + if (!config_templates_1.availableModuleTypes.includes(type)) { + throw new exceptions_1.ParameterError("Module type not available", {}); + } + } + else { + // Prompt for type + garden.log.info("---------"); + garden.log.stop(); + type = (yield prompts_1.prompts.addConfigForModule(moduleName)).type; + garden.log.info("---------"); + if (!type) { + return { result: {} }; + } + } + const module = helpers_1.prepareNewModuleConfig(moduleName, type, moduleRoot); + try { + yield helpers_1.dumpConfig(module, config_templates_1.moduleSchema, garden.log); + } + catch (err) { + errors.push(err); + } + return { + result: { module }, + errors, + }; + }); + } +} +exports.CreateModuleCommand = CreateModuleCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILCtCQUFxQztBQUNyQyxpQ0FBaUM7QUFFakMsa0NBTWdCO0FBQ2hCLGlEQUFrRTtBQUNsRSx5REFBcUc7QUFDckcsdUNBR2tCO0FBQ2xCLHVDQUFtQztBQUNuQyxnREFBNkQ7QUFDN0QsdUNBQW9DO0FBRXBDLE1BQU0sbUJBQW1CLEdBQUc7SUFDMUIsSUFBSSxFQUFFLElBQUksc0JBQWUsQ0FBQztRQUN4QixJQUFJLEVBQUUsbUZBQW1GO0tBQzFGLENBQUM7SUFDRixJQUFJLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUN6QixJQUFJLEVBQUUsaUJBQWlCO1FBQ3ZCLE9BQU8sRUFBRSx1Q0FBb0I7S0FDOUIsQ0FBQztDQUNILENBQUE7QUFFRCxNQUFNLHFCQUFxQixHQUFHO0lBQzVCLFlBQVksRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDaEMsSUFBSSxFQUFFLDJEQUEyRDtLQUNsRSxDQUFDO0NBQ0gsQ0FBQTtBQVdELE1BQWEsbUJBQW9CLFNBQVEsY0FBbUI7SUFBNUQ7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFVBQUssR0FBRyxHQUFHLENBQUE7UUFDWCxTQUFJLEdBQUcsOEJBQThCLENBQUE7UUFFckMsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7OztHQVNuQixDQUFBO1FBRUQsY0FBUyxHQUFHLElBQUksQ0FBQTtRQUNoQixjQUFTLEdBQUcscUJBQXFCLENBQUE7UUFDakMsWUFBTyxHQUFHLG1CQUFtQixDQUFBO0lBK0MvQixDQUFDO0lBN0NPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUE2Qjs7WUFDNUQsSUFBSSxNQUFNLEdBQXNCLEVBQUUsQ0FBQTtZQUVsQyxNQUFNLFVBQVUsR0FBRyxXQUFJLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxDQUFDLElBQUksQ0FBQyxZQUFZLENBQUMsSUFBSSxFQUFFLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO1lBQzlFLE1BQU0sVUFBVSxHQUFHLGlCQUFRLENBQ3pCLElBQUksQ0FBQyxJQUFJLElBQUksZUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUNqQyxzQkFBYSxFQUFFLEVBQ2YsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLENBQzNCLENBQUE7WUFFRCxNQUFNLG9CQUFTLENBQUMsVUFBVSxDQUFDLENBQUE7WUFFM0IsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7WUFDcEUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsMkJBQTJCLFVBQVUsRUFBRSxDQUFDLENBQUE7WUFFeEQsSUFBSSxJQUFnQixDQUFBO1lBRXBCLElBQUksSUFBSSxDQUFDLElBQUksRUFBRTtnQkFDYiwyQkFBMkI7Z0JBQzNCLElBQUksR0FBZSxJQUFJLENBQUMsSUFBSSxDQUFBO2dCQUM1QixJQUFJLENBQUMsdUNBQW9CLENBQUMsUUFBUSxDQUFDLElBQUksQ0FBQyxFQUFFO29CQUN4QyxNQUFNLElBQUksMkJBQWMsQ0FBQywyQkFBMkIsRUFBRSxFQUFFLENBQUMsQ0FBQTtpQkFDMUQ7YUFDRjtpQkFBTTtnQkFDTCxrQkFBa0I7Z0JBQ2xCLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUM1QixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxDQUFBO2dCQUNqQixJQUFJLEdBQUcsQ0FBQyxNQUFNLGlCQUFPLENBQUMsa0JBQWtCLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7Z0JBQzFELE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO2dCQUM1QixJQUFJLENBQUMsSUFBSSxFQUFFO29CQUNULE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUE7aUJBQ3RCO2FBQ0Y7WUFFRCxNQUFNLE1BQU0sR0FBRyxnQ0FBc0IsQ0FBQyxVQUFVLEVBQUUsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFBO1lBQ25FLElBQUk7Z0JBQ0YsTUFBTSxvQkFBVSxDQUFDLE1BQU0sRUFBRSwrQkFBWSxFQUFFLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTthQUNuRDtZQUFDLE9BQU8sR0FBRyxFQUFFO2dCQUNaLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7YUFDakI7WUFDRCxPQUFPO2dCQUNMLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRTtnQkFDbEIsTUFBTTthQUNQLENBQUE7UUFDSCxDQUFDO0tBQUE7Q0FDRjtBQWpFRCxrREFpRUMiLCJmaWxlIjoiY29tbWFuZHMvY3JlYXRlL21vZHVsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBiYXNlbmFtZSwgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5cbmltcG9ydCB7XG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIFN0cmluZ1BhcmFtZXRlcixcbiAgQ2hvaWNlc1BhcmFtZXRlcixcbiAgQ29tbWFuZFBhcmFtcyxcbn0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgUGFyYW1ldGVyRXJyb3IsIEdhcmRlbkJhc2VFcnJvciB9IGZyb20gXCIuLi8uLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IGF2YWlsYWJsZU1vZHVsZVR5cGVzLCBNb2R1bGVUeXBlLCBtb2R1bGVTY2hlbWEsIE1vZHVsZUNvbmZpZ09wdHMgfSBmcm9tIFwiLi9jb25maWctdGVtcGxhdGVzXCJcbmltcG9ydCB7XG4gIHByZXBhcmVOZXdNb2R1bGVDb25maWcsXG4gIGR1bXBDb25maWcsXG59IGZyb20gXCIuL2hlbHBlcnNcIlxuaW1wb3J0IHsgcHJvbXB0cyB9IGZyb20gXCIuL3Byb21wdHNcIlxuaW1wb3J0IHsgdmFsaWRhdGUsIGpvaUlkZW50aWZpZXIgfSBmcm9tIFwiLi4vLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBlbnN1cmVEaXIgfSBmcm9tIFwiZnMtZXh0cmFcIlxuXG5jb25zdCBjcmVhdGVNb2R1bGVPcHRpb25zID0ge1xuICBuYW1lOiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIkFzc2lnbnMgYSBjdXN0b20gbmFtZSB0byB0aGUgbW9kdWxlLiAoRGVmYXVsdHMgdG8gbmFtZSBvZiB0aGUgY3VycmVudCBkaXJlY3RvcnkuKVwiLFxuICB9KSxcbiAgdHlwZTogbmV3IENob2ljZXNQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVHlwZSBvZiBtb2R1bGUuXCIsXG4gICAgY2hvaWNlczogYXZhaWxhYmxlTW9kdWxlVHlwZXMsXG4gIH0pLFxufVxuXG5jb25zdCBjcmVhdGVNb2R1bGVBcmd1bWVudHMgPSB7XG4gIFwibW9kdWxlLWRpclwiOiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIkRpcmVjdG9yeSBvZiB0aGUgbW9kdWxlLiAoRGVmYXVsdHMgdG8gY3VycmVudCBkaXJlY3RvcnkuKVwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIGNyZWF0ZU1vZHVsZUFyZ3VtZW50c1xudHlwZSBPcHRzID0gdHlwZW9mIGNyZWF0ZU1vZHVsZU9wdGlvbnNcblxuaW50ZXJmYWNlIENyZWF0ZU1vZHVsZVJlc3VsdCBleHRlbmRzIENvbW1hbmRSZXN1bHQge1xuICByZXN1bHQ6IHtcbiAgICBtb2R1bGU/OiBNb2R1bGVDb25maWdPcHRzLFxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBDcmVhdGVNb2R1bGVDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzLCBPcHRzPiB7XG4gIG5hbWUgPSBcIm1vZHVsZVwiXG4gIGFsaWFzID0gXCJtXCJcbiAgaGVscCA9IFwiQ3JlYXRlcyBhIG5ldyBHYXJkZW4gbW9kdWxlLlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgQ3JlYXRlcyBhIG5ldyBHYXJkZW4gbW9kdWxlIG9mIHRoZSBnaXZlbiB0eXBlXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gY3JlYXRlIG1vZHVsZSAjIGNyZWF0ZXMgYSBuZXcgbW9kdWxlIGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeSAobW9kdWxlIG5hbWUgZGVmYXVsdHMgdG8gZGlyZWN0b3J5IG5hbWUpXG4gICAgICAgIGdhcmRlbiBjcmVhdGUgbW9kdWxlIG15LW1vZHVsZSAjIGNyZWF0ZXMgYSBuZXcgbW9kdWxlIGluIG15LW1vZHVsZSBkaXJlY3RvcnlcbiAgICAgICAgZ2FyZGVuIGNyZWF0ZSBtb2R1bGUgLS10eXBlPWNvbnRhaW5lciAjIGNyZWF0ZXMgYSBuZXcgY29udGFpbmVyIG1vZHVsZVxuICAgICAgICBnYXJkZW4gY3JlYXRlIG1vZHVsZSAtLW5hbWU9bXktbW9kdWxlICMgY3JlYXRlcyBhIG5ldyBtb2R1bGUgaW4gY3VycmVudCBkaXJlY3RvcnkgYW5kIG5hbWVzIGl0IG15LW1vZHVsZVxuICBgXG5cbiAgbm9Qcm9qZWN0ID0gdHJ1ZVxuICBhcmd1bWVudHMgPSBjcmVhdGVNb2R1bGVBcmd1bWVudHNcbiAgb3B0aW9ucyA9IGNyZWF0ZU1vZHVsZU9wdGlvbnNcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4sIGFyZ3MsIG9wdHMgfTogQ29tbWFuZFBhcmFtczxBcmdzLCBPcHRzPik6IFByb21pc2U8Q3JlYXRlTW9kdWxlUmVzdWx0PiB7XG4gICAgbGV0IGVycm9yczogR2FyZGVuQmFzZUVycm9yW10gPSBbXVxuXG4gICAgY29uc3QgbW9kdWxlUm9vdCA9IGpvaW4oZ2FyZGVuLnByb2plY3RSb290LCAoYXJnc1tcIm1vZHVsZS1kaXJcIl0gfHwgXCJcIikudHJpbSgpKVxuICAgIGNvbnN0IG1vZHVsZU5hbWUgPSB2YWxpZGF0ZShcbiAgICAgIG9wdHMubmFtZSB8fCBiYXNlbmFtZShtb2R1bGVSb290KSxcbiAgICAgIGpvaUlkZW50aWZpZXIoKSxcbiAgICAgIHsgY29udGV4dDogXCJtb2R1bGUgbmFtZVwiIH0sXG4gICAgKVxuXG4gICAgYXdhaXQgZW5zdXJlRGlyKG1vZHVsZVJvb3QpXG5cbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7IGVtb2ppOiBcImhvdXNlX3dpdGhfZ2FyZGVuXCIsIGNvbW1hbmQ6IFwiY3JlYXRlXCIgfSlcbiAgICBnYXJkZW4ubG9nLmluZm8oYEluaXRpYWxpemluZyBuZXcgbW9kdWxlICR7bW9kdWxlTmFtZX1gKVxuXG4gICAgbGV0IHR5cGU6IE1vZHVsZVR5cGVcblxuICAgIGlmIChvcHRzLnR5cGUpIHtcbiAgICAgIC8vIFR5cGUgcGFzc2VkIGFzIHBhcmFtZXRlclxuICAgICAgdHlwZSA9IDxNb2R1bGVUeXBlPm9wdHMudHlwZVxuICAgICAgaWYgKCFhdmFpbGFibGVNb2R1bGVUeXBlcy5pbmNsdWRlcyh0eXBlKSkge1xuICAgICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IoXCJNb2R1bGUgdHlwZSBub3QgYXZhaWxhYmxlXCIsIHt9KVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBQcm9tcHQgZm9yIHR5cGVcbiAgICAgIGdhcmRlbi5sb2cuaW5mbyhcIi0tLS0tLS0tLVwiKVxuICAgICAgZ2FyZGVuLmxvZy5zdG9wKClcbiAgICAgIHR5cGUgPSAoYXdhaXQgcHJvbXB0cy5hZGRDb25maWdGb3JNb2R1bGUobW9kdWxlTmFtZSkpLnR5cGVcbiAgICAgIGdhcmRlbi5sb2cuaW5mbyhcIi0tLS0tLS0tLVwiKVxuICAgICAgaWYgKCF0eXBlKSB7XG4gICAgICAgIHJldHVybiB7IHJlc3VsdDoge30gfVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IG1vZHVsZSA9IHByZXBhcmVOZXdNb2R1bGVDb25maWcobW9kdWxlTmFtZSwgdHlwZSwgbW9kdWxlUm9vdClcbiAgICB0cnkge1xuICAgICAgYXdhaXQgZHVtcENvbmZpZyhtb2R1bGUsIG1vZHVsZVNjaGVtYSwgZ2FyZGVuLmxvZylcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGVycm9ycy5wdXNoKGVycilcbiAgICB9XG4gICAgcmV0dXJuIHtcbiAgICAgIHJlc3VsdDogeyBtb2R1bGUgfSxcbiAgICAgIGVycm9ycyxcbiAgICB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/create/project.d.ts b/garden-service/build/commands/create/project.d.ts new file mode 100644 index 00000000000..5d049665c62 --- /dev/null +++ b/garden-service/build/commands/create/project.d.ts @@ -0,0 +1,34 @@ +import { Command, CommandParams, CommandResult, StringParameter, PathsParameter } from "../base"; +import { ModuleConfigOpts, ProjectConfigOpts } from "./config-templates"; +declare const createProjectOptions: { + "module-dirs": PathsParameter; + name: StringParameter; +}; +declare const createProjectArguments: { + "project-dir": StringParameter; +}; +declare type Args = typeof createProjectArguments; +declare type Opts = typeof createProjectOptions; +interface CreateProjectResult extends CommandResult { + result: { + projectConfig: ProjectConfigOpts; + moduleConfigs: ModuleConfigOpts[]; + }; +} +export declare class CreateProjectCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + noProject: boolean; + arguments: { + "project-dir": StringParameter; + }; + options: { + "module-dirs": PathsParameter; + name: StringParameter; + }; + action({ garden, args, opts }: CommandParams): Promise; +} +export {}; +//# sourceMappingURL=project.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/project.js b/garden-service/build/commands/create/project.js new file mode 100644 index 00000000000..80a8107d11a --- /dev/null +++ b/garden-service/build/commands/create/project.js @@ -0,0 +1,143 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const Bluebird = require("bluebird"); +const dedent = require("dedent"); +const terminalLink = require("terminal-link"); +const base_1 = require("../base"); +const helpers_1 = require("./helpers"); +const prompts_1 = require("./prompts"); +const config_templates_1 = require("./config-templates"); +const util_1 = require("../../util/util"); +const common_1 = require("../../config/common"); +const project_1 = require("../../config/project"); +const createProjectOptions = { + "module-dirs": new base_1.PathsParameter({ + help: "Relative path to modules directory. Use comma as a separator to specify multiple directories", + }), + name: new base_1.StringParameter({ + help: "Assigns a custom name to the project. (Defaults to name of the current directory.)", + }), +}; +const createProjectArguments = { + "project-dir": new base_1.StringParameter({ + help: "Directory of the project. (Defaults to current directory.)", + }), +}; +const flatten = (acc, val) => acc.concat(val); +class CreateProjectCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "project"; + this.alias = "p"; + this.help = "Creates a new Garden project."; + this.description = dedent ` + The 'create project' command walks the user through setting up a new Garden project and + generates scaffolding based on user input. + + Examples: + + garden create project # creates a new Garden project in the current directory (project name defaults to + directory name) + garden create project my-project # creates a new Garden project in my-project directory + garden create project --module-dirs=path/to/modules1,path/to/modules2 + # creates a new Garden project and looks for pre-existing modules in the modules1 and modules2 directories + garden create project --name my-project + # creates a new Garden project in the current directory and names it my-project + `; + this.noProject = true; + this.arguments = createProjectArguments; + this.options = createProjectOptions; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + let moduleConfigs = []; + let errors = []; + const projectRoot = args["project-dir"] ? path_1.join(garden.projectRoot, args["project-dir"].trim()) : garden.projectRoot; + const moduleParentDirs = yield Bluebird.map(opts["module-dirs"] || [], (dir) => path_1.resolve(projectRoot, dir)); + const projectName = common_1.validate(opts.name || path_1.basename(projectRoot), common_1.joiIdentifier(), { context: "project name" }); + yield fs_extra_1.ensureDir(projectRoot); + garden.log.header({ emoji: "house_with_garden", command: "create" }); + garden.log.info(`Initializing new Garden project ${projectName}`); + garden.log.info("---------"); + // Stop logger while prompting + garden.log.stop(); + if (moduleParentDirs.length > 0) { + // If module-dirs option provided we scan for modules in the parent dir(s) and add them one by one + moduleConfigs = (yield Bluebird.mapSeries(moduleParentDirs, (parentDir) => __awaiter(this, void 0, void 0, function* () { + const moduleNames = yield util_1.getChildDirNames(parentDir); + return Bluebird.reduce(moduleNames, (acc, moduleName) => __awaiter(this, void 0, void 0, function* () { + const { type } = yield prompts_1.prompts.addConfigForModule(moduleName); + if (type) { + acc.push(helpers_1.prepareNewModuleConfig(moduleName, type, path_1.join(parentDir, moduleName))); + } + return acc; + }), []); + }))) + .reduce(flatten, []) + .filter(m => m); + } + else { + // Otherwise we prompt the user for modules to add + moduleConfigs = (yield prompts_1.prompts.repeatAddModule()) + .map(({ name, type }) => helpers_1.prepareNewModuleConfig(name, type, path_1.join(projectRoot, name))); + } + garden.log.info("---------"); + const taskLog = garden.log.info({ msg: "Setting up project", status: "active" }); + for (const module of moduleConfigs) { + yield fs_extra_1.ensureDir(module.path); + try { + yield helpers_1.dumpConfig(module, config_templates_1.moduleSchema, garden.log); + } + catch (err) { + errors.push(err); + } + } + const projectConfig = { + path: projectRoot, + name: projectName, + config: config_templates_1.projectTemplate(projectName, moduleConfigs.map(module => module.type)), + }; + try { + yield helpers_1.dumpConfig(projectConfig, project_1.projectSchema, garden.log); + } + catch (err) { + errors.push(err); + } + if (errors.length === 0) { + taskLog.setSuccess(); + } + else { + taskLog.setWarn({ msg: "Finished with errors", append: true }); + } + const docs = terminalLink("docs", "https://docs.garden.io"); + garden.log.info(`Project created! Be sure to check out our ${docs} for how to get sarted!`); + return { + result: { + moduleConfigs, + projectConfig, + }, + errors, + }; + }); + } +} +exports.CreateProjectCommand = CreateProjectCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9wcm9qZWN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCwrQkFBOEM7QUFDOUMsdUNBQW9DO0FBQ3BDLHFDQUFxQztBQUNyQyxpQ0FBaUM7QUFDakMsOENBQThDO0FBRTlDLGtDQU1nQjtBQUVoQix1Q0FHa0I7QUFDbEIsdUNBQW1DO0FBQ25DLHlEQUsyQjtBQUMzQiwwQ0FBa0Q7QUFDbEQsZ0RBQTZEO0FBQzdELGtEQUFvRDtBQUVwRCxNQUFNLG9CQUFvQixHQUFHO0lBQzNCLGFBQWEsRUFBRSxJQUFJLHFCQUFjLENBQUM7UUFDaEMsSUFBSSxFQUFFLDhGQUE4RjtLQUNyRyxDQUFDO0lBQ0YsSUFBSSxFQUFFLElBQUksc0JBQWUsQ0FBQztRQUN4QixJQUFJLEVBQUUsb0ZBQW9GO0tBQzNGLENBQUM7Q0FDSCxDQUFBO0FBRUQsTUFBTSxzQkFBc0IsR0FBRztJQUM3QixhQUFhLEVBQUUsSUFBSSxzQkFBZSxDQUFDO1FBQ2pDLElBQUksRUFBRSw0REFBNEQ7S0FDbkUsQ0FBQztDQUNILENBQUE7QUFLRCxNQUFNLE9BQU8sR0FBRyxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUE7QUFTN0MsTUFBYSxvQkFBcUIsU0FBUSxjQUFtQjtJQUE3RDs7UUFDRSxTQUFJLEdBQUcsU0FBUyxDQUFBO1FBQ2hCLFVBQUssR0FBRyxHQUFHLENBQUE7UUFDWCxTQUFJLEdBQUcsK0JBQStCLENBQUE7UUFFdEMsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7Ozs7Ozs7R0FhbkIsQ0FBQTtRQUVELGNBQVMsR0FBRyxJQUFJLENBQUE7UUFDaEIsY0FBUyxHQUFHLHNCQUFzQixDQUFBO1FBQ2xDLFlBQU8sR0FBRyxvQkFBb0IsQ0FBQTtJQW9GaEMsQ0FBQztJQWxGTyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFB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eUIsQ0FBQyxDQUFBO1lBRTNGLE9BQU87Z0JBQ0wsTUFBTSxFQUFFO29CQUNOLGFBQWE7b0JBQ2IsYUFBYTtpQkFDZDtnQkFDRCxNQUFNO2FBQ1AsQ0FBQTtRQUNILENBQUM7S0FBQTtDQUNGO0FBMUdELG9EQTBHQyIsImZpbGUiOiJjb21tYW5kcy9jcmVhdGUvcHJvamVjdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyByZXNvbHZlLCBqb2luLCBiYXNlbmFtZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IGVuc3VyZURpciB9IGZyb20gXCJmcy1leHRyYVwiXG5pbXBvcnQgQmx1ZWJpcmQgPSByZXF1aXJlKFwiYmx1ZWJpcmRcIilcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgdGVybWluYWxMaW5rID0gcmVxdWlyZShcInRlcm1pbmFsLWxpbmtcIilcblxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgU3RyaW5nUGFyYW1ldGVyLFxuICBQYXRoc1BhcmFtZXRlcixcbn0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgR2FyZGVuQmFzZUVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHtcbiAgcHJlcGFyZU5ld01vZHVsZUNvbmZpZyxcbiAgZHVtcENvbmZpZyxcbn0gZnJvbSBcIi4vaGVscGVyc1wiXG5pbXBvcnQgeyBwcm9tcHRzIH0gZnJvbSBcIi4vcHJvbXB0c1wiXG5pbXBvcnQge1xuICBwcm9qZWN0VGVtcGxhdGUsXG4gIE1vZHVsZUNvbmZpZ09wdHMsXG4gIFByb2plY3RDb25maWdPcHRzLFxuICBtb2R1bGVTY2hlbWEsXG59IGZyb20gXCIuL2NvbmZpZy10ZW1wbGF0ZXNcIlxuaW1wb3J0IHsgZ2V0Q2hpbGREaXJOYW1lcyB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgdmFsaWRhdGUsIGpvaUlkZW50aWZpZXIgfSBmcm9tIFwiLi4vLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBwcm9qZWN0U2NoZW1hIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9wcm9qZWN0XCJcblxuY29uc3QgY3JlYXRlUHJvamVjdE9wdGlvbnMgPSB7XG4gIFwibW9kdWxlLWRpcnNcIjogbmV3IFBhdGhzUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIlJlbGF0aXZlIHBhdGggdG8gbW9kdWxlcyBkaXJlY3RvcnkuIFVzZSBjb21tYSBhcyBhIHNlcGFyYXRvciB0byBzcGVjaWZ5IG11bHRpcGxlIGRpcmVjdG9yaWVzXCIsXG4gIH0pLFxuICBuYW1lOiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIkFzc2lnbnMgYSBjdXN0b20gbmFtZSB0byB0aGUgcHJvamVjdC4gKERlZmF1bHRzIHRvIG5hbWUgb2YgdGhlIGN1cnJlbnQgZGlyZWN0b3J5LilcIixcbiAgfSksXG59XG5cbmNvbnN0IGNyZWF0ZVByb2plY3RBcmd1bWVudHMgPSB7XG4gIFwicHJvamVjdC1kaXJcIjogbmV3IFN0cmluZ1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJEaXJlY3Rvcnkgb2YgdGhlIHByb2plY3QuIChEZWZhdWx0cyB0byBjdXJyZW50IGRpcmVjdG9yeS4pXCIsXG4gIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgY3JlYXRlUHJvamVjdEFyZ3VtZW50c1xudHlwZSBPcHRzID0gdHlwZW9mIGNyZWF0ZVByb2plY3RPcHRpb25zXG5cbmNvbnN0IGZsYXR0ZW4gPSAoYWNjLCB2YWwpID0+IGFjYy5jb25jYXQodmFsKVxuXG5pbnRlcmZhY2UgQ3JlYXRlUHJvamVjdFJlc3VsdCBleHRlbmRzIENvbW1hbmRSZXN1bHQge1xuICByZXN1bHQ6IHtcbiAgICBwcm9qZWN0Q29uZmlnOiBQcm9qZWN0Q29uZmlnT3B0cyxcbiAgICBtb2R1bGVDb25maWdzOiBNb2R1bGVDb25maWdPcHRzW10sXG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIENyZWF0ZVByb2plY3RDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzLCBPcHRzPiB7XG4gIG5hbWUgPSBcInByb2plY3RcIlxuICBhbGlhcyA9IFwicFwiXG4gIGhlbHAgPSBcIkNyZWF0ZXMgYSBuZXcgR2FyZGVuIHByb2plY3QuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBUaGUgJ2NyZWF0ZSBwcm9qZWN0JyBjb21tYW5kIHdhbGtzIHRoZSB1c2VyIHRocm91Z2ggc2V0dGluZyB1cCBhIG5ldyBHYXJkZW4gcHJvamVjdCBhbmRcbiAgICBnZW5lcmF0ZXMgc2NhZmZvbGRpbmcgYmFzZWQgb24gdXNlciBpbnB1dC5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBjcmVhdGUgcHJvamVjdCAjIGNyZWF0ZXMgYSBuZXcgR2FyZGVuIHByb2plY3QgaW4gdGhlIGN1cnJlbnQgZGlyZWN0b3J5IChwcm9qZWN0IG5hbWUgZGVmYXVsdHMgdG9cbiAgICAgICAgZGlyZWN0b3J5IG5hbWUpXG4gICAgICAgIGdhcmRlbiBjcmVhdGUgcHJvamVjdCBteS1wcm9qZWN0ICMgY3JlYXRlcyBhIG5ldyBHYXJkZW4gcHJvamVjdCBpbiBteS1wcm9qZWN0IGRpcmVjdG9yeVxuICAgICAgICBnYXJkZW4gY3JlYXRlIHByb2plY3QgLS1tb2R1bGUtZGlycz1wYXRoL3RvL21vZHVsZXMxLHBhdGgvdG8vbW9kdWxlczJcbiAgICAgICAgIyBjcmVhdGVzIGEgbmV3IEdhcmRlbiBwcm9qZWN0IGFuZCBsb29rcyBmb3IgcHJlLWV4aXN0aW5nIG1vZHVsZXMgaW4gdGhlIG1vZHVsZXMxIGFuZCBtb2R1bGVzMiBkaXJlY3Rvcmllc1xuICAgICAgICBnYXJkZW4gY3JlYXRlIHByb2plY3QgLS1uYW1lIG15LXByb2plY3RcbiAgICAgICAgIyBjcmVhdGVzIGEgbmV3IEdhcmRlbiBwcm9qZWN0IGluIHRoZSBjdXJyZW50IGRpcmVjdG9yeSBhbmQgbmFtZXMgaXQgbXktcHJvamVjdFxuICBgXG5cbiAgbm9Qcm9qZWN0ID0gdHJ1ZVxuICBhcmd1bWVudHMgPSBjcmVhdGVQcm9qZWN0QXJndW1lbnRzXG4gIG9wdGlvbnMgPSBjcmVhdGVQcm9qZWN0T3B0aW9uc1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDcmVhdGVQcm9qZWN0UmVzdWx0PiB7XG4gICAgbGV0IG1vZHVsZUNvbmZpZ3M6IE1vZHVsZUNvbmZpZ09wdHNbXSA9IFtdXG4gICAgbGV0IGVycm9yczogR2FyZGVuQmFzZUVycm9yW10gPSBbXVxuXG4gICAgY29uc3QgcHJvamVjdFJvb3QgPSBhcmdzW1wicHJvamVjdC1kaXJcIl0gPyBqb2luKGdhcmRlbi5wcm9qZWN0Um9vdCwgYXJnc1tcInByb2plY3QtZGlyXCJdLnRyaW0oKSkgOiBnYXJkZW4ucHJvamVjdFJvb3RcbiAgICBjb25zdCBtb2R1bGVQYXJlbnREaXJzID0gYXdhaXQgQmx1ZWJpcmQubWFwKG9wdHNbXCJtb2R1bGUtZGlyc1wiXSB8fCBbXSwgKGRpcjogc3RyaW5nKSA9PiByZXNvbHZlKHByb2plY3RSb290LCBkaXIpKVxuICAgIGNvbnN0IHByb2plY3ROYW1lID0gdmFsaWRhdGUoXG4gICAgICBvcHRzLm5hbWUgfHwgYmFzZW5hbWUocHJvamVjdFJvb3QpLFxuICAgICAgam9pSWRlbnRpZmllcigpLFxuICAgICAgeyBjb250ZXh0OiBcInByb2plY3QgbmFtZVwiIH0sXG4gICAgKVxuXG4gICAgYXdhaXQgZW5zdXJlRGlyKHByb2plY3RSb290KVxuXG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJob3VzZV93aXRoX2dhcmRlblwiLCBjb21tYW5kOiBcImNyZWF0ZVwiIH0pXG4gICAgZ2FyZGVuLmxvZy5pbmZvKGBJbml0aWFsaXppbmcgbmV3IEdhcmRlbiBwcm9qZWN0ICR7cHJvamVjdE5hbWV9YClcbiAgICBnYXJkZW4ubG9nLmluZm8oXCItLS0tLS0tLS1cIilcbiAgICAvLyBTdG9wIGxvZ2dlciB3aGlsZSBwcm9tcHRpbmdcbiAgICBnYXJkZW4ubG9nLnN0b3AoKVxuXG4gICAgaWYgKG1vZHVsZVBhcmVudERpcnMubGVuZ3RoID4gMCkge1xuICAgICAgLy8gSWYgbW9kdWxlLWRpcnMgb3B0aW9uIHByb3ZpZGVkIHdlIHNjYW4gZm9yIG1vZHVsZXMgaW4gdGhlIHBhcmVudCBkaXIocykgYW5kIGFkZCB0aGVtIG9uZSBieSBvbmVcbiAgICAgIG1vZHVsZUNvbmZpZ3MgPSAoYXdhaXQgQmx1ZWJpcmQubWFwU2VyaWVzKG1vZHVsZVBhcmVudERpcnMsIGFzeW5jIHBhcmVudERpciA9PiB7XG4gICAgICAgIGNvbnN0IG1vZHVsZU5hbWVzID0gYXdhaXQgZ2V0Q2hpbGREaXJOYW1lcyhwYXJlbnREaXIpXG5cbiAgICAgICAgcmV0dXJuIEJsdWViaXJkLnJlZHVjZShtb2R1bGVOYW1lcywgYXN5bmMgKGFjYzogTW9kdWxlQ29uZmlnT3B0c1tdLCBtb2R1bGVOYW1lOiBzdHJpbmcpID0+IHtcbiAgICAgICAgICBjb25zdCB7IHR5cGUgfSA9IGF3YWl0IHByb21wdHMuYWRkQ29uZmlnRm9yTW9kdWxlKG1vZHVsZU5hbWUpXG4gICAgICAgICAgaWYgKHR5cGUpIHtcbiAgICAgICAgICAgIGFjYy5wdXNoKHByZXBhcmVOZXdNb2R1bGVDb25maWcobW9kdWxlTmFtZSwgdHlwZSwgam9pbihwYXJlbnREaXIsIG1vZHVsZU5hbWUpKSlcbiAgICAgICAgICB9XG4gICAgICAgICAgcmV0dXJuIGFjY1xuICAgICAgICB9LCBbXSlcbiAgICAgIH0pKVxuICAgICAgICAucmVkdWNlKGZsYXR0ZW4sIFtdKVxuICAgICAgICAuZmlsdGVyKG0gPT4gbSlcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gT3RoZXJ3aXNlIHdlIHByb21wdCB0aGUgdXNlciBmb3IgbW9kdWxlcyB0byBhZGRcbiAgICAgIG1vZHVsZUNvbmZpZ3MgPSAoYXdhaXQgcHJvbXB0cy5yZXBlYXRBZGRNb2R1bGUoKSlcbiAgICAgICAgLm1hcCgoeyBuYW1lLCB0eXBlIH0pID0+IHByZXBhcmVOZXdNb2R1bGVDb25maWcobmFtZSwgdHlwZSwgam9pbihwcm9qZWN0Um9vdCwgbmFtZSkpKVxuICAgIH1cblxuICAgIGdhcmRlbi5sb2cuaW5mbyhcIi0tLS0tLS0tLVwiKVxuICAgIGNvbnN0IHRhc2tMb2cgPSBnYXJkZW4ubG9nLmluZm8oeyBtc2c6IFwiU2V0dGluZyB1cCBwcm9qZWN0XCIsIHN0YXR1czogXCJhY3RpdmVcIiB9KVxuXG4gICAgZm9yIChjb25zdCBtb2R1bGUgb2YgbW9kdWxlQ29uZmlncykge1xuICAgICAgYXdhaXQgZW5zdXJlRGlyKG1vZHVsZS5wYXRoKVxuICAgICAgdHJ5IHtcbiAgICAgICAgYXdhaXQgZHVtcENvbmZpZyhtb2R1bGUsIG1vZHVsZVNjaGVtYSwgZ2FyZGVuLmxvZylcbiAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICBlcnJvcnMucHVzaChlcnIpXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgcHJvamVjdENvbmZpZzogUHJvamVjdENvbmZpZ09wdHMgPSB7XG4gICAgICBwYXRoOiBwcm9qZWN0Um9vdCxcbiAgICAgIG5hbWU6IHByb2plY3ROYW1lLFxuICAgICAgY29uZmlnOiBwcm9qZWN0VGVtcGxhdGUocHJvamVjdE5hbWUsIG1vZHVsZUNvbmZpZ3MubWFwKG1vZHVsZSA9PiBtb2R1bGUudHlwZSkpLFxuICAgIH1cblxuICAgIHRyeSB7XG4gICAgICBhd2FpdCBkdW1wQ29uZmlnKHByb2plY3RDb25maWcsIHByb2plY3RTY2hlbWEsIGdhcmRlbi5sb2cpXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBlcnJvcnMucHVzaChlcnIpXG4gICAgfVxuXG4gICAgaWYgKGVycm9ycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRhc2tMb2cuc2V0U3VjY2VzcygpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRhc2tMb2cuc2V0V2Fybih7IG1zZzogXCJGaW5pc2hlZCB3aXRoIGVycm9yc1wiLCBhcHBlbmQ6IHRydWUgfSlcbiAgICB9XG5cbiAgICBjb25zdCBkb2NzID0gdGVybWluYWxMaW5rKFwiZG9jc1wiLCBcImh0dHBzOi8vZG9jcy5nYXJkZW4uaW9cIilcbiAgICBnYXJkZW4ubG9nLmluZm8oYFByb2plY3QgY3JlYXRlZCEgQmUgc3VyZSB0byBjaGVjayBvdXQgb3VyICR7ZG9jc30gZm9yIGhvdyB0byBnZXQgc2FydGVkIWApXG5cbiAgICByZXR1cm4ge1xuICAgICAgcmVzdWx0OiB7XG4gICAgICAgIG1vZHVsZUNvbmZpZ3MsXG4gICAgICAgIHByb2plY3RDb25maWcsXG4gICAgICB9LFxuICAgICAgZXJyb3JzLFxuICAgIH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/create/prompts.d.ts b/garden-service/build/commands/create/prompts.d.ts new file mode 100644 index 00000000000..c31c7685612 --- /dev/null +++ b/garden-service/build/commands/create/prompts.d.ts @@ -0,0 +1,19 @@ +import * as inquirer from "inquirer"; +import { ModuleType } from "./config-templates"; +export interface ModuleTypeChoice extends inquirer.objects.ChoiceOption { + value: ModuleType; +} +export interface ModuleTypeMap { + type: ModuleType; +} +export interface ModuleTypeAndName extends ModuleTypeMap { + name: string; +} +export interface Prompts { + addConfigForModule: (...args: any[]) => Promise; + addModule: (...args: any[]) => Promise; + repeatAddModule: (...args: any[]) => Promise; +} +export declare function repeatAddModule(): Promise; +export declare const prompts: Prompts; +//# sourceMappingURL=prompts.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/create/prompts.js b/garden-service/build/commands/create/prompts.js new file mode 100644 index 00000000000..13de190d867 --- /dev/null +++ b/garden-service/build/commands/create/prompts.js @@ -0,0 +1,121 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const inquirer = require("inquirer"); +const Joi = require("joi"); +const chalk_1 = require("chalk"); +const common_1 = require("../../config/common"); +const moduleTypeChoices = [ + { + name: "container", + value: "container", + }, + { + name: `google-cloud-function (${chalk_1.default.red.italic("experimental")})`, + value: "google-cloud-function", + }, + { + name: `npm package (${chalk_1.default.red.italic("experimental")})`, + value: "npm-package", + }, +]; +// Create config for an existing module +function addConfigForModule(dir) { + return __awaiter(this, void 0, void 0, function* () { + const qNames = { + ADD_MODULE: "addModule", + TYPE: "type", + }; + const questions = [ + { + name: qNames.ADD_MODULE, + message: `Add module config for ${chalk_1.default.italic(dir)}?`, + type: "confirm", + }, + { + name: qNames.TYPE, + message: "Module type", + choices: moduleTypeChoices, + when: ans => ans[qNames.ADD_MODULE], + type: "list", + }, + ]; + return yield inquirer.prompt(questions); + }); +} +// Create a new module with config +function addModule(addModuleMessage) { + return __awaiter(this, void 0, void 0, function* () { + const qNames = { + ADD_MODULE: "addModule", + NAME: "name", + TYPE: "type", + }; + const questions = [ + { + name: qNames.ADD_MODULE, + message: addModuleMessage, + type: "confirm", + }, + { + name: qNames.NAME, + message: "Enter module name", + type: "input", + validate: input => { + try { + Joi.attempt(input.trim(), common_1.joiIdentifier()); + } + catch (err) { + return `Invalid module name, please try again\nError: ${err.message}`; + } + return true; + }, + filter: input => input.trim(), + when: ans => ans[qNames.ADD_MODULE], + }, + { + name: qNames.TYPE, + message: "Module type", + choices: moduleTypeChoices, + when: ans => ans[qNames.NAME], + type: "list", + }, + ]; + return yield inquirer.prompt(questions); + }); +} +function repeatAddModule() { + return __awaiter(this, void 0, void 0, function* () { + let modules = []; + let addModuleMessage = "Would you like to add a module to your project?"; + let ans = yield addModule(addModuleMessage); + while (ans.type) { + modules.push({ name: ans.name, type: ans.type }); + addModuleMessage = `Add another module? (current modules: ${modules.map(m => m.name).join(", ")})`; + ans = yield addModule(addModuleMessage); + } + return modules; + }); +} +exports.repeatAddModule = repeatAddModule; +exports.prompts = { + addConfigForModule, + addModule, + repeatAddModule, +}; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2NyZWF0ZS9wcm9tcHRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxxQ0FBb0M7QUFDcEMsMkJBQTBCO0FBQzFCLGlDQUF5QjtBQUV6QixnREFBbUQ7QUFxQm5ELE1BQU0saUJBQWlCLEdBQXVCO0lBQzVDO1FBQ0UsSUFBSSxFQUFFLFdBQVc7UUFDakIsS0FBSyxFQUFFLFdBQVc7S0FDbkI7SUFDRDtRQUNFLElBQUksRUFBRSwwQkFBMEIsZUFBSyxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUc7UUFDbkUsS0FBSyxFQUFFLHVCQUF1QjtLQUMvQjtJQUNEO1FBQ0UsSUFBSSxFQUFFLGdCQUFnQixlQUFLLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxjQUFjLENBQUMsR0FBRztRQUN6RCxLQUFLLEVBQUUsYUFBYTtLQUNyQjtDQUNGLENBQUE7QUFFRCx1Q0FBdUM7QUFDdkMsU0FBZSxrQkFBa0IsQ0FBQyxHQUFXOztRQUMzQyxNQUFNLE1BQU0sR0FBRztZQUNiLFVBQVUsRUFBRSxXQUFXO1lBQ3ZCLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQTtRQUNELE1BQU0sU0FBUyxHQUF1QjtZQUNwQztnQkFDRSxJQUFJLEVBQUUsTUFBTSxDQUFDLFVBQVU7Z0JBQ3ZCLE9BQU8sRUFBRSx5QkFBeUIsZUFBSyxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsR0FBRztnQkFDdEQsSUFBSSxFQUFFLFNBQVM7YUFDaEI7WUFDRDtnQkFDRSxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7Z0JBQ2pCLE9BQU8sRUFBRSxhQUFhO2dCQUN0QixPQUFPLEVBQUUsaUJBQWlCO2dCQUMxQixJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQztnQkFDbkMsSUFBSSxFQUFFLE1BQU07YUFDYjtTQUNGLENBQUE7UUFDRCxPQUFPLE1BQU0sUUFBUSxDQUFDLE1BQU0sQ0FBQyxTQUFTLENBQWtCLENBQUE7SUFDMUQsQ0FBQztDQUFBO0FBRUQsa0NBQWtDO0FBQ2xDLFNBQWUsU0FBUyxDQUFDLGdCQUF3Qjs7UUFDL0MsTUFBTSxNQUFNLEdBQUc7WUFDYixVQUFVLEVBQUUsV0FBVztZQUN2QixJQUFJLEVBQUUsTUFBTTtZQUNaLElBQUksRUFBRSxNQUFNO1NBQ2IsQ0FBQTtRQUNELE1BQU0sU0FBUyxHQUF1QjtZQUNwQztnQkFDRSxJQUFJLEVBQUUsTUFBTSxDQUFDLFVBQVU7Z0JBQ3ZCLE9BQU8sRUFBRSxnQkFBZ0I7Z0JBQ3pCLElBQUksRUFBRSxTQUFTO2FBQ2hCO1lBQ0Q7Z0JBQ0UsSUFBSSxFQUFFLE1BQU0sQ0FBQyxJQUFJO2dCQUNqQixPQUFPLEVBQUUsbUJBQW1CO2dCQUM1QixJQUFJLEVBQUUsT0FBTztnQkFDYixRQUFRLEVBQUUsS0FBSyxDQUFDLEVBQUU7b0JBQ2hCLElBQUk7d0JBQ0YsR0FBRyxDQUFDLE9BQU8sQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFLEVBQUUsc0JBQWEsRUFBRSxDQUFDLENBQUE7cUJBQzNDO29CQUFDLE9BQU8sR0FBRyxFQUFFO3dCQUNaLE9BQU8saURBQWlELEdBQUcsQ0FBQyxPQUFPLEVBQUUsQ0FBQTtxQkFDdEU7b0JBQ0QsT0FBTyxJQUFJLENBQUE7Z0JBQ2IsQ0FBQztnQkFDRCxNQUFNLEVBQUUsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxFQUFFO2dCQUM3QixJQUFJLEVBQUUsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLFVBQVUsQ0FBQzthQUNwQztZQUNEO2dCQUNFLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtnQkFDakIsT0FBTyxFQUFFLGFBQWE7Z0JBQ3RCLE9BQU8sRUFBRSxpQkFBaUI7Z0JBQzFCLElBQUksRUFBRSxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDO2dCQUM3QixJQUFJLEVBQUUsTUFBTTthQUNiO1NBQ0YsQ0FBQTtRQUNELE9BQU8sTUFBTSxRQUFRLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBc0IsQ0FBQTtJQUM5RCxDQUFDO0NBQUE7QUFFRCxTQUFzQixlQUFlOztRQUNuQyxJQUFJLE9BQU8sR0FBd0IsRUFBRSxDQUFBO1FBQ3JDLElBQUksZ0JBQWdCLEdBQUcsaURBQWlELENBQUE7UUFDeEUsSUFBSSxHQUFHLEdBQUcsTUFBTSxTQUFTLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtRQUUzQyxPQUFPLEdBQUcsQ0FBQyxJQUFJLEVBQUU7WUFDZixPQUFPLENBQUMsSUFBSSxDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO1lBQ2hELGdCQUFnQixHQUFHLHlDQUF5QyxPQUFPLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFBO1lBQ2xHLEdBQUcsR0FBRyxNQUFNLFNBQVMsQ0FBQyxnQkFBZ0IsQ0FBQyxDQUFBO1NBQ3hDO1FBQ0QsT0FBTyxPQUFPLENBQUE7SUFDaEIsQ0FBQztDQUFBO0FBWEQsMENBV0M7QUFFWSxRQUFBLE9BQU8sR0FBWTtJQUM5QixrQkFBa0I7SUFDbEIsU0FBUztJQUNULGVBQWU7Q0FDaEIsQ0FBQSIsImZpbGUiOiJjb21tYW5kcy9jcmVhdGUvcHJvbXB0cy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBpbnF1aXJlciBmcm9tIFwiaW5xdWlyZXJcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5cbmltcG9ydCB7IGpvaUlkZW50aWZpZXIgfSBmcm9tIFwiLi4vLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBNb2R1bGVUeXBlIH0gZnJvbSBcIi4vY29uZmlnLXRlbXBsYXRlc1wiXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlVHlwZUNob2ljZSBleHRlbmRzIGlucXVpcmVyLm9iamVjdHMuQ2hvaWNlT3B0aW9uIHtcbiAgdmFsdWU6IE1vZHVsZVR5cGVcbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb2R1bGVUeXBlTWFwIHtcbiAgdHlwZTogTW9kdWxlVHlwZVxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vZHVsZVR5cGVBbmROYW1lIGV4dGVuZHMgTW9kdWxlVHlwZU1hcCB7XG4gIG5hbWU6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb21wdHMge1xuICBhZGRDb25maWdGb3JNb2R1bGU6ICguLi5hcmdzOiBhbnlbXSkgPT4gUHJvbWlzZTxNb2R1bGVUeXBlTWFwPlxuICBhZGRNb2R1bGU6ICguLi5hcmdzOiBhbnlbXSkgPT4gUHJvbWlzZTxNb2R1bGVUeXBlQW5kTmFtZT5cbiAgcmVwZWF0QWRkTW9kdWxlOiAoLi4uYXJnczogYW55W10pID0+IFByb21pc2U8TW9kdWxlVHlwZUFuZE5hbWVbXT5cbn1cblxuY29uc3QgbW9kdWxlVHlwZUNob2ljZXM6IE1vZHVsZVR5cGVDaG9pY2VbXSA9IFtcbiAge1xuICAgIG5hbWU6IFwiY29udGFpbmVyXCIsXG4gICAgdmFsdWU6IFwiY29udGFpbmVyXCIsXG4gIH0sXG4gIHtcbiAgICBuYW1lOiBgZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uICgke2NoYWxrLnJlZC5pdGFsaWMoXCJleHBlcmltZW50YWxcIil9KWAsXG4gICAgdmFsdWU6IFwiZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uXCIsXG4gIH0sXG4gIHtcbiAgICBuYW1lOiBgbnBtIHBhY2thZ2UgKCR7Y2hhbGsucmVkLml0YWxpYyhcImV4cGVyaW1lbnRhbFwiKX0pYCxcbiAgICB2YWx1ZTogXCJucG0tcGFja2FnZVwiLFxuICB9LFxuXVxuXG4vLyBDcmVhdGUgY29uZmlnIGZvciBhbiBleGlzdGluZyBtb2R1bGVcbmFzeW5jIGZ1bmN0aW9uIGFkZENvbmZpZ0Zvck1vZHVsZShkaXI6IHN0cmluZyk6IFByb21pc2U8TW9kdWxlVHlwZU1hcD4ge1xuICBjb25zdCBxTmFtZXMgPSB7XG4gICAgQUREX01PRFVMRTogXCJhZGRNb2R1bGVcIixcbiAgICBUWVBFOiBcInR5cGVcIixcbiAgfVxuICBjb25zdCBxdWVzdGlvbnM6IGlucXVpcmVyLlF1ZXN0aW9ucyA9IFtcbiAgICB7XG4gICAgICBuYW1lOiBxTmFtZXMuQUREX01PRFVMRSxcbiAgICAgIG1lc3NhZ2U6IGBBZGQgbW9kdWxlIGNvbmZpZyBmb3IgJHtjaGFsay5pdGFsaWMoZGlyKX0/YCxcbiAgICAgIHR5cGU6IFwiY29uZmlybVwiLFxuICAgIH0sXG4gICAge1xuICAgICAgbmFtZTogcU5hbWVzLlRZUEUsXG4gICAgICBtZXNzYWdlOiBcIk1vZHVsZSB0eXBlXCIsXG4gICAgICBjaG9pY2VzOiBtb2R1bGVUeXBlQ2hvaWNlcyxcbiAgICAgIHdoZW46IGFucyA9PiBhbnNbcU5hbWVzLkFERF9NT0RVTEVdLFxuICAgICAgdHlwZTogXCJsaXN0XCIsXG4gICAgfSxcbiAgXVxuICByZXR1cm4gYXdhaXQgaW5xdWlyZXIucHJvbXB0KHF1ZXN0aW9ucykgYXMgTW9kdWxlVHlwZU1hcFxufVxuXG4vLyBDcmVhdGUgYSBuZXcgbW9kdWxlIHdpdGggY29uZmlnXG5hc3luYyBmdW5jdGlvbiBhZGRNb2R1bGUoYWRkTW9kdWxlTWVzc2FnZTogc3RyaW5nKTogUHJvbWlzZTxNb2R1bGVUeXBlQW5kTmFtZT4ge1xuICBjb25zdCBxTmFtZXMgPSB7XG4gICAgQUREX01PRFVMRTogXCJhZGRNb2R1bGVcIixcbiAgICBOQU1FOiBcIm5hbWVcIixcbiAgICBUWVBFOiBcInR5cGVcIixcbiAgfVxuICBjb25zdCBxdWVzdGlvbnM6IGlucXVpcmVyLlF1ZXN0aW9ucyA9IFtcbiAgICB7XG4gICAgICBuYW1lOiBxTmFtZXMuQUREX01PRFVMRSxcbiAgICAgIG1lc3NhZ2U6IGFkZE1vZHVsZU1lc3NhZ2UsXG4gICAgICB0eXBlOiBcImNvbmZpcm1cIixcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6IHFOYW1lcy5OQU1FLFxuICAgICAgbWVzc2FnZTogXCJFbnRlciBtb2R1bGUgbmFtZVwiLFxuICAgICAgdHlwZTogXCJpbnB1dFwiLFxuICAgICAgdmFsaWRhdGU6IGlucHV0ID0+IHtcbiAgICAgICAgdHJ5IHtcbiAgICAgICAgICBKb2kuYXR0ZW1wdChpbnB1dC50cmltKCksIGpvaUlkZW50aWZpZXIoKSlcbiAgICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgICAgcmV0dXJuIGBJbnZhbGlkIG1vZHVsZSBuYW1lLCBwbGVhc2UgdHJ5IGFnYWluXFxuRXJyb3I6ICR7ZXJyLm1lc3NhZ2V9YFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiB0cnVlXG4gICAgICB9LFxuICAgICAgZmlsdGVyOiBpbnB1dCA9PiBpbnB1dC50cmltKCksXG4gICAgICB3aGVuOiBhbnMgPT4gYW5zW3FOYW1lcy5BRERfTU9EVUxFXSxcbiAgICB9LFxuICAgIHtcbiAgICAgIG5hbWU6IHFOYW1lcy5UWVBFLFxuICAgICAgbWVzc2FnZTogXCJNb2R1bGUgdHlwZVwiLFxuICAgICAgY2hvaWNlczogbW9kdWxlVHlwZUNob2ljZXMsXG4gICAgICB3aGVuOiBhbnMgPT4gYW5zW3FOYW1lcy5OQU1FXSxcbiAgICAgIHR5cGU6IFwibGlzdFwiLFxuICAgIH0sXG4gIF1cbiAgcmV0dXJuIGF3YWl0IGlucXVpcmVyLnByb21wdChxdWVzdGlvbnMpIGFzIE1vZHVsZVR5cGVBbmROYW1lXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXBlYXRBZGRNb2R1bGUoKTogUHJvbWlzZTxNb2R1bGVUeXBlQW5kTmFtZVtdPiB7XG4gIGxldCBtb2R1bGVzOiBNb2R1bGVUeXBlQW5kTmFtZVtdID0gW11cbiAgbGV0IGFkZE1vZHVsZU1lc3NhZ2UgPSBcIldvdWxkIHlvdSBsaWtlIHRvIGFkZCBhIG1vZHVsZSB0byB5b3VyIHByb2plY3Q/XCJcbiAgbGV0IGFucyA9IGF3YWl0IGFkZE1vZHVsZShhZGRNb2R1bGVNZXNzYWdlKVxuXG4gIHdoaWxlIChhbnMudHlwZSkge1xuICAgIG1vZHVsZXMucHVzaCh7IG5hbWU6IGFucy5uYW1lLCB0eXBlOiBhbnMudHlwZSB9KVxuICAgIGFkZE1vZHVsZU1lc3NhZ2UgPSBgQWRkIGFub3RoZXIgbW9kdWxlPyAoY3VycmVudCBtb2R1bGVzOiAke21vZHVsZXMubWFwKG0gPT4gbS5uYW1lKS5qb2luKFwiLCBcIil9KWBcbiAgICBhbnMgPSBhd2FpdCBhZGRNb2R1bGUoYWRkTW9kdWxlTWVzc2FnZSlcbiAgfVxuICByZXR1cm4gbW9kdWxlc1xufVxuXG5leHBvcnQgY29uc3QgcHJvbXB0czogUHJvbXB0cyA9IHtcbiAgYWRkQ29uZmlnRm9yTW9kdWxlLFxuICBhZGRNb2R1bGUsXG4gIHJlcGVhdEFkZE1vZHVsZSxcbn1cbiJdfQ== diff --git a/garden-service/build/commands/delete.d.ts b/garden-service/build/commands/delete.d.ts new file mode 100644 index 00000000000..e00120fa5cb --- /dev/null +++ b/garden-service/build/commands/delete.d.ts @@ -0,0 +1,46 @@ +import { DeleteSecretResult, EnvironmentStatusMap } from "../types/plugin/outputs"; +import { Command, CommandResult, CommandParams, StringParameter, StringsParameter } from "./base"; +export declare class DeleteCommand extends Command { + name: string; + alias: string; + help: string; + subCommands: (typeof DeleteSecretCommand | typeof DeleteEnvironmentCommand | typeof DeleteServiceCommand)[]; + action(): Promise<{}>; +} +declare const deleteSecretArgs: { + provider: StringParameter; + key: StringParameter; +}; +declare type DeleteSecretArgs = typeof deleteSecretArgs; +export declare class DeleteSecretCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + provider: StringParameter; + key: StringParameter; + }; + action({ garden, args }: CommandParams): Promise>; +} +export declare class DeleteEnvironmentCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + action({ garden }: CommandParams): Promise>; +} +declare const deleteServiceArgs: { + service: StringsParameter; +}; +declare type DeleteServiceArgs = typeof deleteServiceArgs; +export declare class DeleteServiceCommand extends Command { + name: string; + help: string; + arguments: { + service: StringsParameter; + }; + description: string; + action({ garden, args }: CommandParams): Promise; +} +export {}; +//# sourceMappingURL=delete.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/delete.js b/garden-service/build/commands/delete.js new file mode 100644 index 00000000000..2007378b1af --- /dev/null +++ b/garden-service/build/commands/delete.js @@ -0,0 +1,145 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const base_1 = require("./base"); +const exceptions_1 = require("../exceptions"); +const dedent = require("dedent"); +class DeleteCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "delete"; + this.alias = "del"; + this.help = "Delete configuration or objects."; + this.subCommands = [ + DeleteSecretCommand, + DeleteEnvironmentCommand, + DeleteServiceCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.DeleteCommand = DeleteCommand; +const deleteSecretArgs = { + provider: new base_1.StringParameter({ + help: "The name of the provider to remove the secret from.", + required: true, + }), + key: new base_1.StringParameter({ + help: "The key of the configuration variable. Separate with dots to get a nested key (e.g. key.nested).", + required: true, + }), +}; +class DeleteSecretCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "secret"; + this.help = "Delete a secret from the environment."; + this.description = dedent ` + Returns with an error if the provided key could not be found by the provider. + + Examples: + + garden delete secret kubernetes somekey + garden del secret local-kubernetes some-other-key + `; + this.arguments = deleteSecretArgs; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + const key = args.key; + const result = yield garden.actions.deleteSecret({ pluginName: args.provider, key }); + if (result.found) { + garden.log.info(`Deleted config key ${args.key}`); + } + else { + throw new exceptions_1.NotFoundError(`Could not find config key ${args.key}`, { key }); + } + return { result }; + }); + } +} +exports.DeleteSecretCommand = DeleteSecretCommand; +class DeleteEnvironmentCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "environment"; + this.alias = "env"; + this.help = "Deletes a running environment."; + this.description = dedent ` + This will trigger providers to clear up any deployments in a Garden environment and reset it. + When you then run \`garden init\`, the environment will be reconfigured. + + This can be useful if you find the environment to be in an inconsistent state, or need/want to free up + resources. + `; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + const { name } = garden.environment; + garden.log.header({ emoji: "skull_and_crossbones", command: `Deleting ${name} environment` }); + const result = yield garden.actions.cleanupEnvironment({}); + garden.log.finish(); + return { result }; + }); + } +} +exports.DeleteEnvironmentCommand = DeleteEnvironmentCommand; +const deleteServiceArgs = { + service: new base_1.StringsParameter({ + help: "The name of the service(s) to delete. Use comma as separator to specify multiple services.", + required: true, + }), +}; +class DeleteServiceCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "service"; + this.help = "Deletes a running service."; + this.arguments = deleteServiceArgs; + this.description = dedent ` + Deletes (i.e. un-deploys) the specified services. Note that this command does not take into account any + services depending on the deleted service, and might therefore leave the project in an unstable state. + Running \`garden deploy\` will re-deploy any missing services. + + Examples: + + garden delete service my-service # deletes my-service + `; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + const services = yield garden.getServices(args.service); + if (services.length === 0) { + garden.log.warn({ msg: "No services found. Aborting." }); + return { result: {} }; + } + garden.log.header({ emoji: "skull_and_crossbones", command: `Delete service` }); + const result = {}; + yield Bluebird.map(services, (service) => __awaiter(this, void 0, void 0, function* () { + result[service.name] = yield garden.actions.deleteService({ service }); + })); + garden.log.finish(); + return { result }; + }); + } +} +exports.DeleteServiceCommand = DeleteServiceCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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TSxFQUFFLENBQUE7UUFDbkIsQ0FBQztLQUFBO0NBQ0Y7QUFsQ0Qsb0RBa0NDIiwiZmlsZSI6ImNvbW1hbmRzL2RlbGV0ZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuaW1wb3J0IHtcbiAgRGVsZXRlU2VjcmV0UmVzdWx0LFxuICBFbnZpcm9ubWVudFN0YXR1c01hcCxcbn0gZnJvbSBcIi4uL3R5cGVzL3BsdWdpbi9vdXRwdXRzXCJcbmltcG9ydCB7XG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIFN0cmluZ1BhcmFtZXRlcixcbiAgU3RyaW5nc1BhcmFtZXRlcixcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgeyBOb3RGb3VuZEVycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcbmltcG9ydCB7IFNlcnZpY2VTdGF0dXMgfSBmcm9tIFwiLi4vdHlwZXMvc2VydmljZVwiXG5cbmV4cG9ydCBjbGFzcyBEZWxldGVDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIG5hbWUgPSBcImRlbGV0ZVwiXG4gIGFsaWFzID0gXCJkZWxcIlxuICBoZWxwID0gXCJEZWxldGUgY29uZmlndXJhdGlvbiBvciBvYmplY3RzLlwiXG5cbiAgc3ViQ29tbWFuZHMgPSBbXG4gICAgRGVsZXRlU2VjcmV0Q29tbWFuZCxcbiAgICBEZWxldGVFbnZpcm9ubWVudENvbW1hbmQsXG4gICAgRGVsZXRlU2VydmljZUNvbW1hbmQsXG4gIF1cblxuICBhc3luYyBhY3Rpb24oKSB7IHJldHVybiB7fSB9XG59XG5cbmNvbnN0IGRlbGV0ZVNlY3JldEFyZ3MgPSB7XG4gIHByb3ZpZGVyOiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIlRoZSBuYW1lIG9mIHRoZSBwcm92aWRlciB0byByZW1vdmUgdGhlIHNlY3JldCBmcm9tLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbiAga2V5OiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIlRoZSBrZXkgb2YgdGhlIGNvbmZpZ3VyYXRpb24gdmFyaWFibGUuIFNlcGFyYXRlIHdpdGggZG90cyB0byBnZXQgYSBuZXN0ZWQga2V5IChlLmcuIGtleS5uZXN0ZWQpLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbn1cblxudHlwZSBEZWxldGVTZWNyZXRBcmdzID0gdHlwZW9mIGRlbGV0ZVNlY3JldEFyZ3NcblxuZXhwb3J0IGNsYXNzIERlbGV0ZVNlY3JldENvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPHR5cGVvZiBkZWxldGVTZWNyZXRBcmdzPiB7XG4gIG5hbWUgPSBcInNlY3JldFwiXG4gIGhlbHAgPSBcIkRlbGV0ZSBhIHNlY3JldCBmcm9tIHRoZSBlbnZpcm9ubWVudC5cIlxuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIFJldHVybnMgd2l0aCBhbiBlcnJvciBpZiB0aGUgcHJvdmlkZWQga2V5IGNvdWxkIG5vdCBiZSBmb3VuZCBieSB0aGUgcHJvdmlkZXIuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gZGVsZXRlIHNlY3JldCBrdWJlcm5ldGVzIHNvbWVrZXlcbiAgICAgICAgZ2FyZGVuIGRlbCBzZWNyZXQgbG9jYWwta3ViZXJuZXRlcyBzb21lLW90aGVyLWtleVxuICBgXG5cbiAgYXJndW1lbnRzID0gZGVsZXRlU2VjcmV0QXJnc1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncyB9OiBDb21tYW5kUGFyYW1zPERlbGV0ZVNlY3JldEFyZ3M+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PERlbGV0ZVNlY3JldFJlc3VsdD4+IHtcbiAgICBjb25zdCBrZXkgPSBhcmdzLmtleSFcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnYXJkZW4uYWN0aW9ucy5kZWxldGVTZWNyZXQoeyBwbHVnaW5OYW1lOiBhcmdzLnByb3ZpZGVyISwga2V5IH0pXG5cbiAgICBpZiAocmVzdWx0LmZvdW5kKSB7XG4gICAgICBnYXJkZW4ubG9nLmluZm8oYERlbGV0ZWQgY29uZmlnIGtleSAke2FyZ3Mua2V5fWApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBOb3RGb3VuZEVycm9yKGBDb3VsZCBub3QgZmluZCBjb25maWcga2V5ICR7YXJncy5rZXl9YCwgeyBrZXkgfSlcbiAgICB9XG5cbiAgICByZXR1cm4geyByZXN1bHQgfVxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBEZWxldGVFbnZpcm9ubWVudENvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwiZW52aXJvbm1lbnRcIlxuICBhbGlhcyA9IFwiZW52XCJcbiAgaGVscCA9IFwiRGVsZXRlcyBhIHJ1bm5pbmcgZW52aXJvbm1lbnQuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBUaGlzIHdpbGwgdHJpZ2dlciBwcm92aWRlcnMgdG8gY2xlYXIgdXAgYW55IGRlcGxveW1lbnRzIGluIGEgR2FyZGVuIGVudmlyb25tZW50IGFuZCByZXNldCBpdC5cbiAgICBXaGVuIHlvdSB0aGVuIHJ1biBcXGBnYXJkZW4gaW5pdFxcYCwgdGhlIGVudmlyb25tZW50IHdpbGwgYmUgcmVjb25maWd1cmVkLlxuXG4gICAgVGhpcyBjYW4gYmUgdXNlZnVsIGlmIHlvdSBmaW5kIHRoZSBlbnZpcm9ubWVudCB0byBiZSBpbiBhbiBpbmNvbnNpc3RlbnQgc3RhdGUsIG9yIG5lZWQvd2FudCB0byBmcmVlIHVwXG4gICAgcmVzb3VyY2VzLlxuICBgXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuIH06IENvbW1hbmRQYXJhbXMpOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8RW52aXJvbm1lbnRTdGF0dXNNYXA+PiB7XG4gICAgY29uc3QgeyBuYW1lIH0gPSBnYXJkZW4uZW52aXJvbm1lbnRcbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7IGVtb2ppOiBcInNrdWxsX2FuZF9jcm9zc2JvbmVzXCIsIGNvbW1hbmQ6IGBEZWxldGluZyAke25hbWV9IGVudmlyb25tZW50YCB9KVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2FyZGVuLmFjdGlvbnMuY2xlYW51cEVudmlyb25tZW50KHt9KVxuXG4gICAgZ2FyZGVuLmxvZy5maW5pc2goKVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuXG5jb25zdCBkZWxldGVTZXJ2aWNlQXJncyA9IHtcbiAgc2VydmljZTogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2UocykgdG8gZGVsZXRlLiBVc2UgY29tbWEgYXMgc2VwYXJhdG9yIHRvIHNwZWNpZnkgbXVsdGlwbGUgc2VydmljZXMuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxudHlwZSBEZWxldGVTZXJ2aWNlQXJncyA9IHR5cGVvZiBkZWxldGVTZXJ2aWNlQXJnc1xuXG5leHBvcnQgY2xhc3MgRGVsZXRlU2VydmljZUNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwic2VydmljZVwiXG4gIGhlbHAgPSBcIkRlbGV0ZXMgYSBydW5uaW5nIHNlcnZpY2UuXCJcbiAgYXJndW1lbnRzID0gZGVsZXRlU2VydmljZUFyZ3NcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBEZWxldGVzIChpLmUuIHVuLWRlcGxveXMpIHRoZSBzcGVjaWZpZWQgc2VydmljZXMuIE5vdGUgdGhhdCB0aGlzIGNvbW1hbmQgZG9lcyBub3QgdGFrZSBpbnRvIGFjY291bnQgYW55XG4gICAgc2VydmljZXMgZGVwZW5kaW5nIG9uIHRoZSBkZWxldGVkIHNlcnZpY2UsIGFuZCBtaWdodCB0aGVyZWZvcmUgbGVhdmUgdGhlIHByb2plY3QgaW4gYW4gdW5zdGFibGUgc3RhdGUuXG4gICAgUnVubmluZyBcXGBnYXJkZW4gZGVwbG95XFxgIHdpbGwgcmUtZGVwbG95IGFueSBtaXNzaW5nIHNlcnZpY2VzLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIGRlbGV0ZSBzZXJ2aWNlIG15LXNlcnZpY2UgIyBkZWxldGVzIG15LXNlcnZpY2VcbiAgYFxuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncyB9OiBDb21tYW5kUGFyYW1zPERlbGV0ZVNlcnZpY2VBcmdzPik6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgZ2FyZGVuLmdldFNlcnZpY2VzKGFyZ3Muc2VydmljZSlcblxuICAgIGlmIChzZXJ2aWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGdhcmRlbi5sb2cud2Fybih7IG1zZzogXCJObyBzZXJ2aWNlcyBmb3VuZC4gQWJvcnRpbmcuXCIgfSlcbiAgICAgIHJldHVybiB7IHJlc3VsdDoge30gfVxuICAgIH1cblxuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwic2t1bGxfYW5kX2Nyb3NzYm9uZXNcIiwgY29tbWFuZDogYERlbGV0ZSBzZXJ2aWNlYCB9KVxuXG4gICAgY29uc3QgcmVzdWx0OiB7IFtrZXk6IHN0cmluZ106IFNlcnZpY2VTdGF0dXMgfSA9IHt9XG5cbiAgICBhd2FpdCBCbHVlYmlyZC5tYXAoc2VydmljZXMsIGFzeW5jIHNlcnZpY2UgPT4ge1xuICAgICAgcmVzdWx0W3NlcnZpY2UubmFtZV0gPSBhd2FpdCBnYXJkZW4uYWN0aW9ucy5kZWxldGVTZXJ2aWNlKHsgc2VydmljZSB9KVxuICAgIH0pXG5cbiAgICBnYXJkZW4ubG9nLmZpbmlzaCgpXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/deploy.d.ts b/garden-service/build/commands/deploy.d.ts new file mode 100644 index 00000000000..0a41ba26a08 --- /dev/null +++ b/garden-service/build/commands/deploy.d.ts @@ -0,0 +1,28 @@ +import { BooleanParameter, Command, CommandParams, CommandResult, StringsParameter } from "./base"; +import { TaskResults } from "../task-graph"; +declare const deployArgs: { + service: StringsParameter; +}; +declare const deployOpts: { + force: BooleanParameter; + "force-build": BooleanParameter; + watch: BooleanParameter; +}; +declare type Args = typeof deployArgs; +declare type Opts = typeof deployOpts; +export declare class DeployCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + service: StringsParameter; + }; + options: { + force: BooleanParameter; + "force-build": BooleanParameter; + watch: BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=deploy.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/deploy.js b/garden-service/build/commands/deploy.js new file mode 100644 index 00000000000..1596e95e3e7 --- /dev/null +++ b/garden-service/build/commands/deploy.js @@ -0,0 +1,98 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const deploy_1 = require("../tasks/deploy"); +const process_1 = require("../process"); +const util_1 = require("../util/util"); +const deployArgs = { + service: new base_1.StringsParameter({ + help: "The name of the service(s) to deploy (skip to deploy all services). " + + "Use comma as separator to specify multiple services.", + }), +}; +const deployOpts = { + force: new base_1.BooleanParameter({ help: "Force redeploy of service(s)." }), + "force-build": new base_1.BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new base_1.BooleanParameter({ help: "Watch for changes in module(s) and auto-deploy.", alias: "w" }), +}; +class DeployCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "deploy"; + this.help = "Deploy service(s) to your environment."; + this.description = ` + Deploys all or specified services, taking into account service dependency order. + Also builds modules and dependencies if needed. + + Optionally stays running and automatically re-builds and re-deploys services if their module source + (or their dependencies' sources) change. + + Examples: + + garden deploy # deploy all modules in the project + garden deploy my-service # only deploy my-service + garden deploy --force # force re-deploy of modules, even if they're already deployed + garden deploy --watch # watch for changes to code + garden deploy --env stage # deploy your services to an environment called stage + `; + this.arguments = deployArgs; + this.options = deployOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const services = yield garden.getServices(args.service); + const serviceNames = util_1.getNames(services); + if (services.length === 0) { + garden.log.warn({ msg: "No services found. Aborting." }); + return { result: {} }; + } + garden.log.header({ emoji: "rocket", command: "Deploy" }); + // TODO: make this a task + yield garden.actions.prepareEnvironment({}); + const results = yield process_1.processServices({ + garden, + services, + watch: opts.watch, + handler: (module) => __awaiter(this, void 0, void 0, function* () { + return deploy_1.getDeployTasks({ + garden, + module, + serviceNames, + force: opts.force, + forceBuild: opts["force-build"], + includeDependants: false, + }); + }), + changeHandler: (module) => __awaiter(this, void 0, void 0, function* () { + return deploy_1.getDeployTasks({ + garden, + module, + serviceNames, + force: true, + forceBuild: true, + includeDependants: true, + }); + }), + }); + return base_1.handleTaskResults(garden, "deploy", results); + }); + } +} +exports.DeployCommand = DeployCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2RlcGxveS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsaUNBT2U7QUFDZiw0Q0FBZ0Q7QUFFaEQsd0NBQTRDO0FBQzVDLHVDQUF1QztBQUV2QyxNQUFNLFVBQVUsR0FBRztJQUNqQixPQUFPLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUM1QixJQUFJLEVBQUUsc0VBQXNFO1lBQzFFLHNEQUFzRDtLQUN6RCxDQUFDO0NBQ0gsQ0FBQTtBQUVELE1BQU0sVUFBVSxHQUFHO0lBQ2pCLEtBQUssRUFBRSxJQUFJLHVCQUFnQixDQUFDLEVBQUUsSUFBSSxFQUFFLCtCQUErQixFQUFFLENBQUM7SUFDdEUsYUFBYSxFQUFFLElBQUksdUJBQWdCLENBQUMsRUFBRSxJQUFJLEVBQUUsNkJBQTZCLEVBQUUsQ0FBQztJQUM1RSxLQUFLLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSxpREFBaUQsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7Q0FDckcsQ0FBQTtBQUtELE1BQWEsYUFBYyxTQUFRLGNBQW1CO0lBQXREOztRQUNFLFNBQUksR0FBRyxRQUFRLENBQUE7UUFDZixTQUFJLEdBQUcsd0NBQXdDLENBQUE7UUFFL0MsZ0JBQVcsR0FBRzs7Ozs7Ozs7Ozs7Ozs7R0FjYixDQUFBO1FBRUQsY0FBUyxHQUFHLFVBQVUsQ0FBQTtRQUN0QixZQUFPLEdBQUcsVUFBVSxDQUFBO0lBd0N0QixDQUFDO0lBdENPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUE2Qjs7WUFDNUQsTUFBTSxRQUFRLEdBQUcsTUFBTSxNQUFNLENBQUMsV0FBVyxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsQ0FBQTtZQUN2RCxNQUFNLFlBQVksR0FBRyxlQUFRLENBQUMsUUFBUSxDQUFDLENBQUE7WUFFdkMsSUFBSSxRQUFRLENBQUMsTUFBTSxLQUFLLENBQUMsRUFBRTtnQkFDekIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxHQUFHLEVBQUUsOEJBQThCLEVBQUUsQ0FBQyxDQUFBO2dCQUN4RCxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFBO2FBQ3RCO1lBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsUUFBUSxFQUFFLE9BQU8sRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFBO1lBRXpELHlCQUF5QjtZQUN6QixNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsRUFBRSxDQUFDLENBQUE7WUFFM0MsTUFBTSxPQUFPLEdBQUcsTUFBTSx5QkFBZSxDQUFDO2dCQUNwQyxNQUFNO2dCQUNOLFFBQVE7Z0JBQ1IsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLO2dCQUNqQixPQUFPLEVBQUUsQ0FBTyxNQUFNLEVBQUUsRUFBRTtvQkFBQyxPQUFBLHVCQUFjLENBQUM7d0JBQ3hDLE1BQU07d0JBQ04sTUFBTTt3QkFDTixZQUFZO3dCQUNaLEtBQUssRUFBRSxJQUFJLENBQUMsS0FBSzt3QkFDakIsVUFBVSxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUM7d0JBQy9CLGlCQUFpQixFQUFFLEtBQUs7cUJBQ3pCLENBQUMsQ0FBQTtrQkFBQTtnQkFDRixhQUFhLEVBQUUsQ0FBTyxNQUFNLEVBQUUsRUFBRTtvQkFBQyxPQUFBLHVCQUFjLENBQUM7d0JBQzlDLE1BQU07d0JBQ04sTUFBTTt3QkFDTixZQUFZO3dCQUNaLEtBQUssRUFBRSxJQUFJO3dCQUNYLFVBQVUsRUFBRSxJQUFJO3dCQUNoQixpQkFBaUIsRUFBRSxJQUFJO3FCQUN4QixDQUFDLENBQUE7a0JBQUE7YUFDSCxDQUFDLENBQUE7WUFFRixPQUFPLHdCQUFpQixDQUFDLE1BQU0sRUFBRSxRQUFRLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDckQsQ0FBQztLQUFBO0NBQ0Y7QUE3REQsc0NBNkRDIiwiZmlsZSI6ImNvbW1hbmRzL2RlcGxveS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQge1xuICBCb29sZWFuUGFyYW1ldGVyLFxuICBDb21tYW5kLFxuICBDb21tYW5kUGFyYW1zLFxuICBDb21tYW5kUmVzdWx0LFxuICBoYW5kbGVUYXNrUmVzdWx0cyxcbiAgU3RyaW5nc1BhcmFtZXRlcixcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgeyBnZXREZXBsb3lUYXNrcyB9IGZyb20gXCIuLi90YXNrcy9kZXBsb3lcIlxuaW1wb3J0IHsgVGFza1Jlc3VsdHMgfSBmcm9tIFwiLi4vdGFzay1ncmFwaFwiXG5pbXBvcnQgeyBwcm9jZXNzU2VydmljZXMgfSBmcm9tIFwiLi4vcHJvY2Vzc1wiXG5pbXBvcnQgeyBnZXROYW1lcyB9IGZyb20gXCIuLi91dGlsL3V0aWxcIlxuXG5jb25zdCBkZXBsb3lBcmdzID0ge1xuICBzZXJ2aWNlOiBuZXcgU3RyaW5nc1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJUaGUgbmFtZSBvZiB0aGUgc2VydmljZShzKSB0byBkZXBsb3kgKHNraXAgdG8gZGVwbG95IGFsbCBzZXJ2aWNlcykuIFwiICtcbiAgICAgIFwiVXNlIGNvbW1hIGFzIHNlcGFyYXRvciB0byBzcGVjaWZ5IG11bHRpcGxlIHNlcnZpY2VzLlwiLFxuICB9KSxcbn1cblxuY29uc3QgZGVwbG95T3B0cyA9IHtcbiAgZm9yY2U6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJGb3JjZSByZWRlcGxveSBvZiBzZXJ2aWNlKHMpLlwiIH0pLFxuICBcImZvcmNlLWJ1aWxkXCI6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJGb3JjZSByZWJ1aWxkIG9mIG1vZHVsZShzKS5cIiB9KSxcbiAgd2F0Y2g6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJXYXRjaCBmb3IgY2hhbmdlcyBpbiBtb2R1bGUocykgYW5kIGF1dG8tZGVwbG95LlwiLCBhbGlhczogXCJ3XCIgfSksXG59XG5cbnR5cGUgQXJncyA9IHR5cGVvZiBkZXBsb3lBcmdzXG50eXBlIE9wdHMgPSB0eXBlb2YgZGVwbG95T3B0c1xuXG5leHBvcnQgY2xhc3MgRGVwbG95Q29tbWFuZCBleHRlbmRzIENvbW1hbmQ8QXJncywgT3B0cz4ge1xuICBuYW1lID0gXCJkZXBsb3lcIlxuICBoZWxwID0gXCJEZXBsb3kgc2VydmljZShzKSB0byB5b3VyIGVudmlyb25tZW50LlwiXG5cbiAgZGVzY3JpcHRpb24gPSBgXG4gICAgRGVwbG95cyBhbGwgb3Igc3BlY2lmaWVkIHNlcnZpY2VzLCB0YWtpbmcgaW50byBhY2NvdW50IHNlcnZpY2UgZGVwZW5kZW5jeSBvcmRlci5cbiAgICBBbHNvIGJ1aWxkcyBtb2R1bGVzIGFuZCBkZXBlbmRlbmNpZXMgaWYgbmVlZGVkLlxuXG4gICAgT3B0aW9uYWxseSBzdGF5cyBydW5uaW5nIGFuZCBhdXRvbWF0aWNhbGx5IHJlLWJ1aWxkcyBhbmQgcmUtZGVwbG95cyBzZXJ2aWNlcyBpZiB0aGVpciBtb2R1bGUgc291cmNlXG4gICAgKG9yIHRoZWlyIGRlcGVuZGVuY2llcycgc291cmNlcykgY2hhbmdlLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIGRlcGxveSAgICAgICAgICAgICAgIyBkZXBsb3kgYWxsIG1vZHVsZXMgaW4gdGhlIHByb2plY3RcbiAgICAgICAgZ2FyZGVuIGRlcGxveSBteS1zZXJ2aWNlICAgIyBvbmx5IGRlcGxveSBteS1zZXJ2aWNlXG4gICAgICAgIGdhcmRlbiBkZXBsb3kgLS1mb3JjZSAgICAgICMgZm9yY2UgcmUtZGVwbG95IG9mIG1vZHVsZXMsIGV2ZW4gaWYgdGhleSdyZSBhbHJlYWR5IGRlcGxveWVkXG4gICAgICAgIGdhcmRlbiBkZXBsb3kgLS13YXRjaCAgICAgICMgd2F0Y2ggZm9yIGNoYW5nZXMgdG8gY29kZVxuICAgICAgICBnYXJkZW4gZGVwbG95IC0tZW52IHN0YWdlICAjIGRlcGxveSB5b3VyIHNlcnZpY2VzIHRvIGFuIGVudmlyb25tZW50IGNhbGxlZCBzdGFnZVxuICBgXG5cbiAgYXJndW1lbnRzID0gZGVwbG95QXJnc1xuICBvcHRpb25zID0gZGVwbG95T3B0c1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFRhc2tSZXN1bHRzPj4ge1xuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgZ2FyZGVuLmdldFNlcnZpY2VzKGFyZ3Muc2VydmljZSlcbiAgICBjb25zdCBzZXJ2aWNlTmFtZXMgPSBnZXROYW1lcyhzZXJ2aWNlcylcblxuICAgIGlmIChzZXJ2aWNlcy5sZW5ndGggPT09IDApIHtcbiAgICAgIGdhcmRlbi5sb2cud2Fybih7IG1zZzogXCJObyBzZXJ2aWNlcyBmb3VuZC4gQWJvcnRpbmcuXCIgfSlcbiAgICAgIHJldHVybiB7IHJlc3VsdDoge30gfVxuICAgIH1cblxuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwicm9ja2V0XCIsIGNvbW1hbmQ6IFwiRGVwbG95XCIgfSlcblxuICAgIC8vIFRPRE86IG1ha2UgdGhpcyBhIHRhc2tcbiAgICBhd2FpdCBnYXJkZW4uYWN0aW9ucy5wcmVwYXJlRW52aXJvbm1lbnQoe30pXG5cbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgcHJvY2Vzc1NlcnZpY2VzKHtcbiAgICAgIGdhcmRlbixcbiAgICAgIHNlcnZpY2VzLFxuICAgICAgd2F0Y2g6IG9wdHMud2F0Y2gsXG4gICAgICBoYW5kbGVyOiBhc3luYyAobW9kdWxlKSA9PiBnZXREZXBsb3lUYXNrcyh7XG4gICAgICAgIGdhcmRlbixcbiAgICAgICAgbW9kdWxlLFxuICAgICAgICBzZXJ2aWNlTmFtZXMsXG4gICAgICAgIGZvcmNlOiBvcHRzLmZvcmNlLFxuICAgICAgICBmb3JjZUJ1aWxkOiBvcHRzW1wiZm9yY2UtYnVpbGRcIl0sXG4gICAgICAgIGluY2x1ZGVEZXBlbmRhbnRzOiBmYWxzZSxcbiAgICAgIH0pLFxuICAgICAgY2hhbmdlSGFuZGxlcjogYXN5bmMgKG1vZHVsZSkgPT4gZ2V0RGVwbG95VGFza3Moe1xuICAgICAgICBnYXJkZW4sXG4gICAgICAgIG1vZHVsZSxcbiAgICAgICAgc2VydmljZU5hbWVzLFxuICAgICAgICBmb3JjZTogdHJ1ZSxcbiAgICAgICAgZm9yY2VCdWlsZDogdHJ1ZSxcbiAgICAgICAgaW5jbHVkZURlcGVuZGFudHM6IHRydWUsXG4gICAgICB9KSxcbiAgICB9KVxuXG4gICAgcmV0dXJuIGhhbmRsZVRhc2tSZXN1bHRzKGdhcmRlbiwgXCJkZXBsb3lcIiwgcmVzdWx0cylcbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/dev.d.ts b/garden-service/build/commands/dev.d.ts new file mode 100644 index 00000000000..4d1dbc941cc --- /dev/null +++ b/garden-service/build/commands/dev.d.ts @@ -0,0 +1,8 @@ +import { Command, CommandResult, CommandParams } from "./base"; +export declare class DevCommand extends Command { + name: string; + help: string; + description: string; + action({ garden }: CommandParams): Promise; +} +//# sourceMappingURL=dev.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/dev.js b/garden-service/build/commands/dev.js new file mode 100644 index 00000000000..a9adf3743a3 --- /dev/null +++ b/garden-service/build/commands/dev.js @@ -0,0 +1,108 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const lodash_1 = require("lodash"); +const moment = require("moment"); +const path_1 = require("path"); +const build_1 = require("../tasks/build"); +const base_1 = require("./base"); +const constants_1 = require("../constants"); +const process_1 = require("../process"); +const fs_extra_1 = require("fs-extra"); +const test_1 = require("./test"); +const watch_1 = require("../watch"); +const deploy_1 = require("../tasks/deploy"); +const ansiBannerPath = path_1.join(constants_1.STATIC_DIR, "garden-banner-2.txt"); +// TODO: allow limiting to certain modules and/or services +class DevCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "dev"; + this.help = "Starts the garden development console."; + this.description = ` + The Garden dev console is a combination of the \`build\`, \`deploy\` and \`test\` commands. + It builds, deploys and tests all your modules and services, and re-builds, re-deploys and re-tests + as you modify the code. + + Examples: + + garden dev + `; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + // print ANSI banner image + const data = yield fs_extra_1.readFile(ansiBannerPath); + console.log(data.toString()); + garden.log.info(chalk_1.default.gray.italic(`\nGood ${getGreetingTime()}! Let's get your environment wired up...\n`)); + yield garden.actions.prepareEnvironment({}); + const autoReloadDependants = yield watch_1.computeAutoReloadDependants(garden); + const modules = yield garden.getModules(); + if (modules.length === 0) { + if (modules.length === 0) { + garden.log.info({ msg: "No modules found in project." }); + } + garden.log.info({ msg: "Aborting..." }); + return {}; + } + const tasksForModule = (watch) => { + return (module) => __awaiter(this, void 0, void 0, function* () { + const testModules = watch + ? (yield watch_1.withDependants(garden, [module], autoReloadDependants)) + : [module]; + const testTasks = lodash_1.flatten(yield Bluebird.map(testModules, m => test_1.getTestTasks({ garden, module: m }))); + const deployTasks = yield deploy_1.getDeployTasks({ + garden, module, force: watch, forceBuild: watch, includeDependants: watch, + }); + const tasks = testTasks.concat(deployTasks); + if (tasks.length === 0) { + return [new build_1.BuildTask({ garden, module, force: watch })]; + } + else { + return tasks; + } + }); + }; + yield process_1.processModules({ + garden, + modules, + watch: true, + handler: tasksForModule(false), + changeHandler: tasksForModule(true), + }); + return {}; + }); + } +} +exports.DevCommand = DevCommand; +function getGreetingTime() { + const m = moment(); + const currentHour = parseFloat(m.format("HH")); + if (currentHour >= 17) { + return "evening"; + } + else if (currentHour >= 12) { + return "afternoon"; + } + else { + return "morning"; + } +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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RSxNQUFNLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUMsQ0FBQTtxQkFDekQ7eUJBQU07d0JBQ0wsT0FBTyxLQUFLLENBQUE7cUJBQ2I7Z0JBQ0gsQ0FBQyxDQUFBLENBQUE7WUFFSCxDQUFDLENBQUE7WUFFRCxNQUFNLHdCQUFjLENBQUM7Z0JBQ25CLE1BQU07Z0JBQ04sT0FBTztnQkFDUCxLQUFLLEVBQUUsSUFBSTtnQkFDWCxPQUFPLEVBQUUsY0FBYyxDQUFDLEtBQUssQ0FBQztnQkFDOUIsYUFBYSxFQUFFLGNBQWMsQ0FBQyxJQUFJLENBQUM7YUFDcEMsQ0FBQyxDQUFBO1lBRUYsT0FBTyxFQUFFLENBQUE7UUFDWCxDQUFDO0tBQUE7Q0FDRjtBQXBFRCxnQ0FvRUM7QUFFRCxTQUFTLGVBQWU7SUFDdEIsTUFBTSxDQUFDLEdBQUcsTUFBTSxFQUFFLENBQUE7SUFFbEIsTUFBTSxXQUFXLEdBQUcsVUFBVSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUU5QyxJQUFJLFdBQVcsSUFBSSxFQUFFLEVBQUU7UUFDckIsT0FBTyxTQUFTLENBQUE7S0FDakI7U0FBTSxJQUFJLFdBQVcsSUFBSSxFQUFFLEVBQUU7UUFDNUIsT0FBTyxXQUFXLENBQUE7S0FDbkI7U0FBTTtRQUNMLE9BQU8sU0FBUyxDQUFBO0tBQ2pCO0FBQ0gsQ0FBQyIsImZpbGUiOiJjb21tYW5kcy9kZXYuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgZmxhdHRlbiB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IG1vbWVudCA9IHJlcXVpcmUoXCJtb21lbnRcIilcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5cbmltcG9ydCB7IEJ1aWxkVGFzayB9IGZyb20gXCIuLi90YXNrcy9idWlsZFwiXG5pbXBvcnQgeyBUYXNrIH0gZnJvbSBcIi4uL3Rhc2tzL2Jhc2VcIlxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgQ29tbWFuZFBhcmFtcyxcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgeyBTVEFUSUNfRElSIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiXG5pbXBvcnQgeyBwcm9jZXNzTW9kdWxlcyB9IGZyb20gXCIuLi9wcm9jZXNzXCJcbmltcG9ydCB7IHJlYWRGaWxlIH0gZnJvbSBcImZzLWV4dHJhXCJcbmltcG9ydCB7IE1vZHVsZSB9IGZyb20gXCIuLi90eXBlcy9tb2R1bGVcIlxuaW1wb3J0IHsgZ2V0VGVzdFRhc2tzIH0gZnJvbSBcIi4vdGVzdFwiXG5pbXBvcnQgeyBjb21wdXRlQXV0b1JlbG9hZERlcGVuZGFudHMsIHdpdGhEZXBlbmRhbnRzIH0gZnJvbSBcIi4uL3dhdGNoXCJcbmltcG9ydCB7IGdldERlcGxveVRhc2tzIH0gZnJvbSBcIi4uL3Rhc2tzL2RlcGxveVwiXG5cbmNvbnN0IGFuc2lCYW5uZXJQYXRoID0gam9pbihTVEFUSUNfRElSLCBcImdhcmRlbi1iYW5uZXItMi50eHRcIilcblxuLy8gVE9ETzogYWxsb3cgbGltaXRpbmcgdG8gY2VydGFpbiBtb2R1bGVzIGFuZC9vciBzZXJ2aWNlc1xuZXhwb3J0IGNsYXNzIERldkNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwiZGV2XCJcbiAgaGVscCA9IFwiU3RhcnRzIHRoZSBnYXJkZW4gZGV2ZWxvcG1lbnQgY29uc29sZS5cIlxuXG4gIGRlc2NyaXB0aW9uID0gYFxuICAgIFRoZSBHYXJkZW4gZGV2IGNvbnNvbGUgaXMgYSBjb21iaW5hdGlvbiBvZiB0aGUgXFxgYnVpbGRcXGAsIFxcYGRlcGxveVxcYCBhbmQgXFxgdGVzdFxcYCBjb21tYW5kcy5cbiAgICBJdCBidWlsZHMsIGRlcGxveXMgYW5kIHRlc3RzIGFsbCB5b3VyIG1vZHVsZXMgYW5kIHNlcnZpY2VzLCBhbmQgcmUtYnVpbGRzLCByZS1kZXBsb3lzIGFuZCByZS10ZXN0c1xuICAgIGFzIHlvdSBtb2RpZnkgdGhlIGNvZGUuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gZGV2XG4gIGBcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4gfTogQ29tbWFuZFBhcmFtcyk6IFByb21pc2U8Q29tbWFuZFJlc3VsdD4ge1xuICAgIC8vIHByaW50IEFOU0kgYmFubmVyIGltYWdlXG4gICAgY29uc3QgZGF0YSA9IGF3YWl0IHJlYWRGaWxlKGFuc2lCYW5uZXJQYXRoKVxuICAgIGNvbnNvbGUubG9nKGRhdGEudG9TdHJpbmcoKSlcblxuICAgIGdhcmRlbi5sb2cuaW5mbyhjaGFsay5ncmF5Lml0YWxpYyhgXFxuR29vZCAke2dldEdyZWV0aW5nVGltZSgpfSEgTGV0J3MgZ2V0IHlvdXIgZW52aXJvbm1lbnQgd2lyZWQgdXAuLi5cXG5gKSlcblxuICAgIGF3YWl0IGdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7fSlcblxuICAgIGNvbnN0IGF1dG9SZWxvYWREZXBlbmRhbnRzID0gYXdhaXQgY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzKGdhcmRlbilcbiAgICBjb25zdCBtb2R1bGVzID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZXMoKVxuXG4gICAgaWYgKG1vZHVsZXMubGVuZ3RoID09PSAwKSB7XG4gICAgICBpZiAobW9kdWxlcy5sZW5ndGggPT09IDApIHtcbiAgICAgICAgZ2FyZGVuLmxvZy5pbmZvKHsgbXNnOiBcIk5vIG1vZHVsZXMgZm91bmQgaW4gcHJvamVjdC5cIiB9KVxuICAgICAgfVxuICAgICAgZ2FyZGVuLmxvZy5pbmZvKHsgbXNnOiBcIkFib3J0aW5nLi4uXCIgfSlcbiAgICAgIHJldHVybiB7fVxuICAgIH1cblxuICAgIGNvbnN0IHRhc2tzRm9yTW9kdWxlID0gKHdhdGNoOiBib29sZWFuKSA9PiB7XG4gICAgICByZXR1cm4gYXN5bmMgKG1vZHVsZTogTW9kdWxlKSA9PiB7XG5cbiAgICAgICAgY29uc3QgdGVzdE1vZHVsZXM6IE1vZHVsZVtdID0gd2F0Y2hcbiAgICAgICAgICA/IChhd2FpdCB3aXRoRGVwZW5kYW50cyhnYXJkZW4sIFttb2R1bGVdLCBhdXRvUmVsb2FkRGVwZW5kYW50cykpXG4gICAgICAgICAgOiBbbW9kdWxlXVxuXG4gICAgICAgIGNvbnN0IHRlc3RUYXNrczogVGFza1tdID0gZmxhdHRlbihhd2FpdCBCbHVlYmlyZC5tYXAoXG4gICAgICAgICAgdGVzdE1vZHVsZXMsIG0gPT4gZ2V0VGVzdFRhc2tzKHsgZ2FyZGVuLCBtb2R1bGU6IG0gfSkpKVxuXG4gICAgICAgIGNvbnN0IGRlcGxveVRhc2tzID0gYXdhaXQgZ2V0RGVwbG95VGFza3Moe1xuICAgICAgICAgIGdhcmRlbiwgbW9kdWxlLCBmb3JjZTogd2F0Y2gsIGZvcmNlQnVpbGQ6IHdhdGNoLCBpbmNsdWRlRGVwZW5kYW50czogd2F0Y2gsXG4gICAgICAgIH0pXG4gICAgICAgIGNvbnN0IHRhc2tzID0gdGVzdFRhc2tzLmNvbmNhdChkZXBsb3lUYXNrcylcblxuICAgICAgICBpZiAodGFza3MubGVuZ3RoID09PSAwKSB7XG4gICAgICAgICAgcmV0dXJuIFtuZXcgQnVpbGRUYXNrKHsgZ2FyZGVuLCBtb2R1bGUsIGZvcmNlOiB3YXRjaCB9KV1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICByZXR1cm4gdGFza3NcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgfVxuXG4gICAgYXdhaXQgcHJvY2Vzc01vZHVsZXMoe1xuICAgICAgZ2FyZGVuLFxuICAgICAgbW9kdWxlcyxcbiAgICAgIHdhdGNoOiB0cnVlLFxuICAgICAgaGFuZGxlcjogdGFza3NGb3JNb2R1bGUoZmFsc2UpLFxuICAgICAgY2hhbmdlSGFuZGxlcjogdGFza3NGb3JNb2R1bGUodHJ1ZSksXG4gICAgfSlcblxuICAgIHJldHVybiB7fVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEdyZWV0aW5nVGltZSgpIHtcbiAgY29uc3QgbSA9IG1vbWVudCgpXG5cbiAgY29uc3QgY3VycmVudEhvdXIgPSBwYXJzZUZsb2F0KG0uZm9ybWF0KFwiSEhcIikpXG5cbiAgaWYgKGN1cnJlbnRIb3VyID49IDE3KSB7XG4gICAgcmV0dXJuIFwiZXZlbmluZ1wiXG4gIH0gZWxzZSBpZiAoY3VycmVudEhvdXIgPj0gMTIpIHtcbiAgICByZXR1cm4gXCJhZnRlcm5vb25cIlxuICB9IGVsc2Uge1xuICAgIHJldHVybiBcIm1vcm5pbmdcIlxuICB9XG59XG4iXX0= diff --git a/garden-service/build/commands/exec.d.ts b/garden-service/build/commands/exec.d.ts new file mode 100644 index 00000000000..73afacb3cdc --- /dev/null +++ b/garden-service/build/commands/exec.d.ts @@ -0,0 +1,23 @@ +import { LoggerType } from "../logger/logger"; +import { ExecInServiceResult } from "../types/plugin/outputs"; +import { Command, CommandResult, CommandParams, StringParameter, StringsParameter } from "./base"; +declare const runArgs: { + service: StringParameter; + command: StringsParameter; +}; +declare type Args = typeof runArgs; +export declare class ExecCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + arguments: { + service: StringParameter; + command: StringsParameter; + }; + options: {}; + loggerType: LoggerType; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=exec.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/exec.js b/garden-service/build/commands/exec.js new file mode 100644 index 00000000000..7f4ae693c34 --- /dev/null +++ b/garden-service/build/commands/exec.js @@ -0,0 +1,74 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const logger_1 = require("../logger/logger"); +const base_1 = require("./base"); +const dedent = require("dedent"); +const runArgs = { + service: new base_1.StringParameter({ + help: "The service to exec the command in.", + required: true, + }), + command: new base_1.StringsParameter({ + help: "The command to run.", + required: true, + }), +}; +const runOpts = { +// interactive: new BooleanParameter({ +// help: "Set to false to skip interactive mode and just output the command result", +// defaultValue: true, +// }), +}; +class ExecCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "exec"; + this.alias = "e"; + this.help = "Executes a command (such as an interactive shell) in a running service."; + this.description = dedent ` + Finds an active container for a deployed service and executes the given command within the container. + Supports interactive shells. + + _NOTE: This command may not be supported for all module types._ + + Examples: + + garden exec my-service /bin/sh # runs a shell in the my-service container + `; + this.arguments = runArgs; + this.options = runOpts; + this.loggerType = logger_1.LoggerType.basic; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + const serviceName = args.service; + const command = args.command || []; + garden.log.header({ + emoji: "runner", + command: `Running command ${chalk_1.default.cyan(command.join(" "))} in service ${chalk_1.default.cyan(serviceName)}`, + }); + const service = yield garden.getService(serviceName); + const result = yield garden.actions.execInService({ service, command }); + return { result }; + }); + } +} +exports.ExecCommand = ExecCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2V4ZWMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUF5QjtBQUN6Qiw2Q0FBNkM7QUFFN0MsaUNBTWU7QUFDZixpQ0FBaUM7QUFFakMsTUFBTSxPQUFPLEdBQUc7SUFDZCxPQUFPLEVBQUUsSUFBSSxzQkFBZSxDQUFDO1FBQzNCLElBQUksRUFBRSxxQ0FBcUM7UUFDM0MsUUFBUSxFQUFFLElBQUk7S0FDZixDQUFDO0lBQ0YsT0FBTyxFQUFFLElBQUksdUJBQWdCLENBQUM7UUFDNUIsSUFBSSxFQUFFLHFCQUFxQjtRQUMzQixRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7Q0FDSCxDQUFBO0FBRUQsTUFBTSxPQUFPLEdBQUc7QUFDZCxzQ0FBc0M7QUFDdEMsc0ZBQXNGO0FBQ3RGLHdCQUF3QjtBQUN4QixNQUFNO0NBQ1AsQ0FBQTtBQUlELE1BQWEsV0FBWSxTQUFRLGNBQWE7SUFBOUM7O1FBQ0UsU0FBSSxHQUFHLE1BQU0sQ0FBQTtRQUNiLFVBQUssR0FBRyxHQUFHLENBQUE7UUFDWCxTQUFJLEdBQUcseUVBQXlFLENBQUE7UUFFaEYsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7OztHQVNuQixDQUFBO1FBRUQsY0FBUyxHQUFHLE9BQU8sQ0FBQTtRQUNuQixZQUFPLEdBQUcsT0FBTyxDQUFBO1FBQ2pCLGVBQVUsR0FBRyxtQkFBVSxDQUFDLEtBQUssQ0FBQTtJQWdCL0IsQ0FBQztJQWRPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQXVCOztZQUNoRCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFBO1lBQ2hDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxPQUFPLElBQUksRUFBRSxDQUFBO1lBRWxDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO2dCQUNoQixLQUFLLEVBQUUsUUFBUTtnQkFDZixPQUFPLEVBQUUsbUJBQW1CLGVBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQyxlQUFlLGVBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLEVBQUU7YUFDbEcsQ0FBQyxDQUFBO1lBRUYsTUFBTSxPQUFPLEdBQUcsTUFBTSxNQUFNLENBQUMsVUFBVSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1lBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxhQUFhLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtZQUV2RSxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUE7UUFDbkIsQ0FBQztLQUFBO0NBQ0Y7QUFsQ0Qsa0NBa0NDIiwiZmlsZSI6ImNvbW1hbmRzL2V4ZWMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5pbXBvcnQgeyBMb2dnZXJUeXBlIH0gZnJvbSBcIi4uL2xvZ2dlci9sb2dnZXJcIlxuaW1wb3J0IHsgRXhlY0luU2VydmljZVJlc3VsdCB9IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQge1xuICBDb21tYW5kLFxuICBDb21tYW5kUmVzdWx0LFxuICBDb21tYW5kUGFyYW1zLFxuICBTdHJpbmdQYXJhbWV0ZXIsXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcblxuY29uc3QgcnVuQXJncyA9IHtcbiAgc2VydmljZTogbmV3IFN0cmluZ1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJUaGUgc2VydmljZSB0byBleGVjIHRoZSBjb21tYW5kIGluLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbiAgY29tbWFuZDogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIGNvbW1hbmQgdG8gcnVuLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbn1cblxuY29uc3QgcnVuT3B0cyA9IHtcbiAgLy8gaW50ZXJhY3RpdmU6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHtcbiAgLy8gICBoZWxwOiBcIlNldCB0byBmYWxzZSB0byBza2lwIGludGVyYWN0aXZlIG1vZGUgYW5kIGp1c3Qgb3V0cHV0IHRoZSBjb21tYW5kIHJlc3VsdFwiLFxuICAvLyAgIGRlZmF1bHRWYWx1ZTogdHJ1ZSxcbiAgLy8gfSksXG59XG5cbnR5cGUgQXJncyA9IHR5cGVvZiBydW5BcmdzXG5cbmV4cG9ydCBjbGFzcyBFeGVjQ29tbWFuZCBleHRlbmRzIENvbW1hbmQ8QXJncz4ge1xuICBuYW1lID0gXCJleGVjXCJcbiAgYWxpYXMgPSBcImVcIlxuICBoZWxwID0gXCJFeGVjdXRlcyBhIGNvbW1hbmQgKHN1Y2ggYXMgYW4gaW50ZXJhY3RpdmUgc2hlbGwpIGluIGEgcnVubmluZyBzZXJ2aWNlLlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgRmluZHMgYW4gYWN0aXZlIGNvbnRhaW5lciBmb3IgYSBkZXBsb3llZCBzZXJ2aWNlIGFuZCBleGVjdXRlcyB0aGUgZ2l2ZW4gY29tbWFuZCB3aXRoaW4gdGhlIGNvbnRhaW5lci5cbiAgICBTdXBwb3J0cyBpbnRlcmFjdGl2ZSBzaGVsbHMuXG5cbiAgICBfTk9URTogVGhpcyBjb21tYW5kIG1heSBub3QgYmUgc3VwcG9ydGVkIGZvciBhbGwgbW9kdWxlIHR5cGVzLl9cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgICBnYXJkZW4gZXhlYyBteS1zZXJ2aWNlIC9iaW4vc2ggICAjIHJ1bnMgYSBzaGVsbCBpbiB0aGUgbXktc2VydmljZSBjb250YWluZXJcbiAgYFxuXG4gIGFyZ3VtZW50cyA9IHJ1bkFyZ3NcbiAgb3B0aW9ucyA9IHJ1bk9wdHNcbiAgbG9nZ2VyVHlwZSA9IExvZ2dlclR5cGUuYmFzaWNcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4sIGFyZ3MgfTogQ29tbWFuZFBhcmFtczxBcmdzPik6IFByb21pc2U8Q29tbWFuZFJlc3VsdDxFeGVjSW5TZXJ2aWNlUmVzdWx0Pj4ge1xuICAgIGNvbnN0IHNlcnZpY2VOYW1lID0gYXJncy5zZXJ2aWNlXG4gICAgY29uc3QgY29tbWFuZCA9IGFyZ3MuY29tbWFuZCB8fCBbXVxuXG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoe1xuICAgICAgZW1vamk6IFwicnVubmVyXCIsXG4gICAgICBjb21tYW5kOiBgUnVubmluZyBjb21tYW5kICR7Y2hhbGsuY3lhbihjb21tYW5kLmpvaW4oXCIgXCIpKX0gaW4gc2VydmljZSAke2NoYWxrLmN5YW4oc2VydmljZU5hbWUpfWAsXG4gICAgfSlcblxuICAgIGNvbnN0IHNlcnZpY2UgPSBhd2FpdCBnYXJkZW4uZ2V0U2VydmljZShzZXJ2aWNlTmFtZSlcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnYXJkZW4uYWN0aW9ucy5leGVjSW5TZXJ2aWNlKHsgc2VydmljZSwgY29tbWFuZCB9KVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/get.d.ts b/garden-service/build/commands/get.d.ts new file mode 100644 index 00000000000..99e845a6389 --- /dev/null +++ b/garden-service/build/commands/get.d.ts @@ -0,0 +1,30 @@ +import { Command, CommandResult, CommandParams, StringParameter } from "./base"; +import { ContextStatus } from "../actions"; +export declare class GetCommand extends Command { + name: string; + help: string; + subCommands: (typeof GetSecretCommand | typeof GetStatusCommand)[]; + action(): Promise<{}>; +} +declare const getSecretArgs: { + provider: StringParameter; + key: StringParameter; +}; +declare type GetArgs = typeof getSecretArgs; +export declare class GetSecretCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + provider: StringParameter; + key: StringParameter; + }; + action({ garden, args }: CommandParams): Promise; +} +export declare class GetStatusCommand extends Command { + name: string; + help: string; + action({ garden }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=get.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/get.js b/garden-service/build/commands/get.js new file mode 100644 index 00000000000..755ce1befb6 --- /dev/null +++ b/garden-service/build/commands/get.js @@ -0,0 +1,95 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const yaml = require("js-yaml"); +const exceptions_1 = require("../exceptions"); +const util_1 = require("../util/util"); +const base_1 = require("./base"); +const dedent = require("dedent"); +class GetCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "get"; + this.help = "Retrieve and output data and objects, e.g. secrets, status info etc."; + this.subCommands = [ + GetSecretCommand, + GetStatusCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.GetCommand = GetCommand; +const getSecretArgs = { + provider: new base_1.StringParameter({ + help: "The name of the provider to read the secret from.", + required: true, + }), + key: new base_1.StringParameter({ + help: "The key of the configuration variable.", + required: true, + }), +}; +// TODO: allow omitting key to return all configs +class GetSecretCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "secret"; + this.help = "Get a secret from the environment."; + this.description = dedent ` + Returns with an error if the provided key could not be found. + + Examples: + + garden get secret kubernetes somekey + garden get secret local-kubernetes some-other-key + `; + this.arguments = getSecretArgs; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + const key = args.key; + const { value } = yield garden.actions.getSecret({ pluginName: args.provider, key }); + if (value === null || value === undefined) { + throw new exceptions_1.NotFoundError(`Could not find config key ${key}`, { key }); + } + garden.log.info(value); + return { [key]: value }; + }); + } +} +exports.GetSecretCommand = GetSecretCommand; +class GetStatusCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "status"; + this.help = "Outputs the status of your environment."; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + const status = yield garden.actions.getStatus(); + const yamlStatus = yaml.safeDump(status, { noRefs: true, skipInvalid: true }); + // TODO: do a nicer print of this by default and add --yaml/--json options (maybe globally) for exporting + garden.log.info(util_1.highlightYaml(yamlStatus)); + return { result: status }; + }); + } +} +exports.GetStatusCommand = GetStatusCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2dldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsZ0NBQStCO0FBQy9CLDhDQUE2QztBQUM3Qyx1Q0FBNEM7QUFDNUMsaUNBS2U7QUFDZixpQ0FBaUM7QUFHakMsTUFBYSxVQUFXLFNBQVEsY0FBTztJQUF2Qzs7UUFDRSxTQUFJLEdBQUcsS0FBSyxDQUFBO1FBQ1osU0FBSSxHQUFHLHNFQUFzRSxDQUFBO1FBRTdFLGdCQUFXLEdBQUc7WUFDWixnQkFBZ0I7WUFDaEIsZ0JBQWdCO1NBQ2pCLENBQUE7SUFHSCxDQUFDO0lBRE8sTUFBTTs4REFBSyxPQUFPLEVBQUUsQ0FBQSxDQUFDLENBQUM7S0FBQTtDQUM3QjtBQVZELGdDQVVDO0FBRUQsTUFBTSxhQUFhLEdBQUc7SUFDcEIsUUFBUSxFQUFFLElBQUksc0JBQWUsQ0FBQztRQUM1QixJQUFJLEVBQUUsbURBQW1EO1FBQ3pELFFBQVEsRUFBRSxJQUFJO0tBQ2YsQ0FBQztJQUNGLEdBQUcsRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDdkIsSUFBSSxFQUFFLHdDQUF3QztRQUM5QyxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7Q0FDSCxDQUFBO0FBSUQsaURBQWlEO0FBRWpELE1BQWEsZ0JBQWlCLFNBQVEsY0FBNkI7SUFBbkU7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFNBQUksR0FBRyxvQ0FBb0MsQ0FBQTtRQUUzQyxnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7OztHQU9uQixDQUFBO1FBRUQsY0FBUyxHQUFHLGFBQWEsQ0FBQTtJQWMzQixDQUFDO0lBWk8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBMEI7O1lBQ25ELE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxHQUFHLENBQUE7WUFDcEIsTUFBTSxFQUFFLEtBQUssRUFBRSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFBO1lBRXBGLElBQUksS0FBSyxLQUFLLElBQUksSUFBSSxLQUFLLEtBQUssU0FBUyxFQUFFO2dCQUN6QyxNQUFNLElBQUksMEJBQWEsQ0FBQyw2QkFBNkIsR0FBRyxFQUFFLEVBQUUsRUFBRSxHQUFHLEVBQUUsQ0FBQyxDQUFBO2FBQ3JFO1lBRUQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLENBQUE7WUFFdEIsT0FBTyxFQUFFLENBQUMsR0FBRyxDQUFDLEVBQUUsS0FBSyxFQUFFLENBQUE7UUFDekIsQ0FBQztLQUFBO0NBQ0Y7QUEzQkQsNENBMkJDO0FBRUQsTUFBYSxnQkFBaUIsU0FBUSxjQUFPO0lBQTdDOztRQUNFLFNBQUksR0FBRyxRQUFRLENBQUE7UUFDZixTQUFJLEdBQUcseUNBQXlDLENBQUE7SUFXbEQsQ0FBQztJQVRPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBaUI7O1lBQ3BDLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLEVBQUUsQ0FBQTtZQUMvQyxNQUFNLFVBQVUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDLE1BQU0sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7WUFFN0UseUdBQXlHO1lBQ3pHLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLG9CQUFhLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQTtZQUUxQyxPQUFPLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxDQUFBO1FBQzNCLENBQUM7S0FBQTtDQUNGO0FBYkQsNENBYUMiLCJmaWxlIjoiY29tbWFuZHMvZ2V0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIHlhbWwgZnJvbSBcImpzLXlhbWxcIlxuaW1wb3J0IHsgTm90Rm91bmRFcnJvciB9IGZyb20gXCIuLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IGhpZ2hsaWdodFlhbWwgfSBmcm9tIFwiLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7XG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIFN0cmluZ1BhcmFtZXRlcixcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuaW1wb3J0IHsgQ29udGV4dFN0YXR1cyB9IGZyb20gXCIuLi9hY3Rpb25zXCJcblxuZXhwb3J0IGNsYXNzIEdldENvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwiZ2V0XCJcbiAgaGVscCA9IFwiUmV0cmlldmUgYW5kIG91dHB1dCBkYXRhIGFuZCBvYmplY3RzLCBlLmcuIHNlY3JldHMsIHN0YXR1cyBpbmZvIGV0Yy5cIlxuXG4gIHN1YkNvbW1hbmRzID0gW1xuICAgIEdldFNlY3JldENvbW1hbmQsXG4gICAgR2V0U3RhdHVzQ29tbWFuZCxcbiAgXVxuXG4gIGFzeW5jIGFjdGlvbigpIHsgcmV0dXJuIHt9IH1cbn1cblxuY29uc3QgZ2V0U2VjcmV0QXJncyA9IHtcbiAgcHJvdmlkZXI6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIHRvIHJlYWQgdGhlIHNlY3JldCBmcm9tLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbiAga2V5OiBuZXcgU3RyaW5nUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIlRoZSBrZXkgb2YgdGhlIGNvbmZpZ3VyYXRpb24gdmFyaWFibGUuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG50eXBlIEdldEFyZ3MgPSB0eXBlb2YgZ2V0U2VjcmV0QXJnc1xuXG4vLyBUT0RPOiBhbGxvdyBvbWl0dGluZyBrZXkgdG8gcmV0dXJuIGFsbCBjb25maWdzXG5cbmV4cG9ydCBjbGFzcyBHZXRTZWNyZXRDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDx0eXBlb2YgZ2V0U2VjcmV0QXJncz4ge1xuICBuYW1lID0gXCJzZWNyZXRcIlxuICBoZWxwID0gXCJHZXQgYSBzZWNyZXQgZnJvbSB0aGUgZW52aXJvbm1lbnQuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBSZXR1cm5zIHdpdGggYW4gZXJyb3IgaWYgdGhlIHByb3ZpZGVkIGtleSBjb3VsZCBub3QgYmUgZm91bmQuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gZ2V0IHNlY3JldCBrdWJlcm5ldGVzIHNvbWVrZXlcbiAgICAgICAgZ2FyZGVuIGdldCBzZWNyZXQgbG9jYWwta3ViZXJuZXRlcyBzb21lLW90aGVyLWtleVxuICBgXG5cbiAgYXJndW1lbnRzID0gZ2V0U2VjcmV0QXJnc1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncyB9OiBDb21tYW5kUGFyYW1zPEdldEFyZ3M+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PiB7XG4gICAgY29uc3Qga2V5ID0gYXJncy5rZXlcbiAgICBjb25zdCB7IHZhbHVlIH0gPSBhd2FpdCBnYXJkZW4uYWN0aW9ucy5nZXRTZWNyZXQoeyBwbHVnaW5OYW1lOiBhcmdzLnByb3ZpZGVyLCBrZXkgfSlcblxuICAgIGlmICh2YWx1ZSA9PT0gbnVsbCB8fCB2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihgQ291bGQgbm90IGZpbmQgY29uZmlnIGtleSAke2tleX1gLCB7IGtleSB9KVxuICAgIH1cblxuICAgIGdhcmRlbi5sb2cuaW5mbyh2YWx1ZSlcblxuICAgIHJldHVybiB7IFtrZXldOiB2YWx1ZSB9XG4gIH1cbn1cblxuZXhwb3J0IGNsYXNzIEdldFN0YXR1c0NvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwic3RhdHVzXCJcbiAgaGVscCA9IFwiT3V0cHV0cyB0aGUgc3RhdHVzIG9mIHlvdXIgZW52aXJvbm1lbnQuXCJcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4gfTogQ29tbWFuZFBhcmFtcyk6IFByb21pc2U8Q29tbWFuZFJlc3VsdDxDb250ZXh0U3RhdHVzPj4ge1xuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGdhcmRlbi5hY3Rpb25zLmdldFN0YXR1cygpXG4gICAgY29uc3QgeWFtbFN0YXR1cyA9IHlhbWwuc2FmZUR1bXAoc3RhdHVzLCB7IG5vUmVmczogdHJ1ZSwgc2tpcEludmFsaWQ6IHRydWUgfSlcblxuICAgIC8vIFRPRE86IGRvIGEgbmljZXIgcHJpbnQgb2YgdGhpcyBieSBkZWZhdWx0IGFuZCBhZGQgLS15YW1sLy0tanNvbiBvcHRpb25zIChtYXliZSBnbG9iYWxseSkgZm9yIGV4cG9ydGluZ1xuICAgIGdhcmRlbi5sb2cuaW5mbyhoaWdobGlnaHRZYW1sKHlhbWxTdGF0dXMpKVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBzdGF0dXMgfVxuICB9XG59XG4iXX0= diff --git a/garden-service/build/commands/init.d.ts b/garden-service/build/commands/init.d.ts new file mode 100644 index 00000000000..b4072fb01c0 --- /dev/null +++ b/garden-service/build/commands/init.d.ts @@ -0,0 +1,16 @@ +import { BooleanParameter, Command, CommandResult, CommandParams } from "./base"; +declare const initOpts: { + force: BooleanParameter; +}; +declare type Opts = typeof initOpts; +export declare class InitCommand extends Command { + name: string; + help: string; + description: string; + options: { + force: BooleanParameter; + }; + action({ garden, opts }: CommandParams<{}, Opts>): Promise>; +} +export {}; +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/init.js b/garden-service/build/commands/init.js new file mode 100644 index 00000000000..9dc68dd3f59 --- /dev/null +++ b/garden-service/build/commands/init.js @@ -0,0 +1,52 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const dedent = require("dedent"); +const initOpts = { + force: new base_1.BooleanParameter({ help: "Force initalization of environment, ignoring the environment status check." }), +}; +class InitCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "init"; + this.help = "Initialize system, environment or other runtime components."; + this.description = dedent ` + This command needs to be run before first deploying a Garden project, and occasionally after updating Garden, + plugins or project configuration. + + Examples: + + garden init + garden init --force # runs the init flows even if status checks report that the environment is ready + `; + this.options = initOpts; + } + action({ garden, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const { name } = garden.environment; + garden.log.header({ emoji: "gear", command: `Initializing ${name} environment` }); + yield garden.actions.prepareEnvironment({ force: opts.force, allowUserInput: true }); + garden.log.info(""); + garden.log.header({ emoji: "heavy_check_mark", command: `Done!` }); + return { result: {} }; + }); + } +} +exports.InitCommand = InitCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2luaXQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUtlO0FBQ2YsaUNBQWlDO0FBRWpDLE1BQU0sUUFBUSxHQUFHO0lBQ2YsS0FBSyxFQUFFLElBQUksdUJBQWdCLENBQUMsRUFBRSxJQUFJLEVBQUUsNEVBQTRFLEVBQUUsQ0FBQztDQUNwSCxDQUFBO0FBSUQsTUFBYSxXQUFZLFNBQVEsY0FBTztJQUF4Qzs7UUFDRSxTQUFJLEdBQUcsTUFBTSxDQUFBO1FBQ2IsU0FBSSxHQUFHLDZEQUE2RCxDQUFBO1FBRXBFLGdCQUFXLEdBQUcsTUFBTSxDQUFBOzs7Ozs7OztHQVFuQixDQUFBO1FBRUQsWUFBTyxHQUFHLFFBQVEsQ0FBQTtJQWFwQixDQUFDO0lBWE8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBMkI7O1lBQ3BELE1BQU0sRUFBRSxJQUFJLEVBQUUsR0FBRyxNQUFNLENBQUMsV0FBVyxDQUFBO1lBQ25DLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxPQUFPLEVBQUUsZ0JBQWdCLElBQUksY0FBYyxFQUFFLENBQUMsQ0FBQTtZQUVqRixNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsa0JBQWtCLENBQUMsRUFBRSxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUssRUFBRSxjQUFjLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtZQUVwRixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUNuQixNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtZQUVsRSxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRSxDQUFBO1FBQ3ZCLENBQUM7S0FBQTtDQUNGO0FBM0JELGtDQTJCQyIsImZpbGUiOiJjb21tYW5kcy9pbml0LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIEJvb2xlYW5QYXJhbWV0ZXIsXG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIENvbW1hbmRQYXJhbXMsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcblxuY29uc3QgaW5pdE9wdHMgPSB7XG4gIGZvcmNlOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7IGhlbHA6IFwiRm9yY2UgaW5pdGFsaXphdGlvbiBvZiBlbnZpcm9ubWVudCwgaWdub3JpbmcgdGhlIGVudmlyb25tZW50IHN0YXR1cyBjaGVjay5cIiB9KSxcbn1cblxudHlwZSBPcHRzID0gdHlwZW9mIGluaXRPcHRzXG5cbmV4cG9ydCBjbGFzcyBJbml0Q29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBuYW1lID0gXCJpbml0XCJcbiAgaGVscCA9IFwiSW5pdGlhbGl6ZSBzeXN0ZW0sIGVudmlyb25tZW50IG9yIG90aGVyIHJ1bnRpbWUgY29tcG9uZW50cy5cIlxuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIFRoaXMgY29tbWFuZCBuZWVkcyB0byBiZSBydW4gYmVmb3JlIGZpcnN0IGRlcGxveWluZyBhIEdhcmRlbiBwcm9qZWN0LCBhbmQgb2NjYXNpb25hbGx5IGFmdGVyIHVwZGF0aW5nIEdhcmRlbixcbiAgICBwbHVnaW5zIG9yIHByb2plY3QgY29uZmlndXJhdGlvbi5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBpbml0XG4gICAgICAgIGdhcmRlbiBpbml0IC0tZm9yY2UgICAjIHJ1bnMgdGhlIGluaXQgZmxvd3MgZXZlbiBpZiBzdGF0dXMgY2hlY2tzIHJlcG9ydCB0aGF0IHRoZSBlbnZpcm9ubWVudCBpcyByZWFkeVxuICBgXG5cbiAgb3B0aW9ucyA9IGluaXRPcHRzXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuLCBvcHRzIH06IENvbW1hbmRQYXJhbXM8e30sIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PHt9Pj4ge1xuICAgIGNvbnN0IHsgbmFtZSB9ID0gZ2FyZGVuLmVudmlyb25tZW50XG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJnZWFyXCIsIGNvbW1hbmQ6IGBJbml0aWFsaXppbmcgJHtuYW1lfSBlbnZpcm9ubWVudGAgfSlcblxuICAgIGF3YWl0IGdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7IGZvcmNlOiBvcHRzLmZvcmNlLCBhbGxvd1VzZXJJbnB1dDogdHJ1ZSB9KVxuXG4gICAgZ2FyZGVuLmxvZy5pbmZvKFwiXCIpXG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJoZWF2eV9jaGVja19tYXJrXCIsIGNvbW1hbmQ6IGBEb25lIWAgfSlcblxuICAgIHJldHVybiB7IHJlc3VsdDoge30gfVxuICB9XG59XG4iXX0= diff --git a/garden-service/build/commands/link/link.d.ts b/garden-service/build/commands/link/link.d.ts new file mode 100644 index 00000000000..566ee5ec305 --- /dev/null +++ b/garden-service/build/commands/link/link.d.ts @@ -0,0 +1,10 @@ +import { Command } from "../base"; +import { LinkSourceCommand } from "./source"; +import { LinkModuleCommand } from "./module"; +export declare class LinkCommand extends Command { + name: string; + help: string; + subCommands: (typeof LinkSourceCommand | typeof LinkModuleCommand)[]; + action(): Promise<{}>; +} +//# sourceMappingURL=link.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/link/link.js b/garden-service/build/commands/link/link.js new file mode 100644 index 00000000000..6e7cbffd171 --- /dev/null +++ b/garden-service/build/commands/link/link.js @@ -0,0 +1,37 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("../base"); +const source_1 = require("./source"); +const module_1 = require("./module"); +class LinkCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "link"; + this.help = "Link a remote source or module to a local path"; + this.subCommands = [ + source_1.LinkSourceCommand, + module_1.LinkModuleCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.LinkCommand = LinkCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2xpbmsvbGluay50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsa0NBQWlDO0FBQ2pDLHFDQUE0QztBQUM1QyxxQ0FBNEM7QUFFNUMsTUFBYSxXQUFZLFNBQVEsY0FBTztJQUF4Qzs7UUFDRSxTQUFJLEdBQUcsTUFBTSxDQUFBO1FBQ2IsU0FBSSxHQUFHLGdEQUFnRCxDQUFBO1FBRXZELGdCQUFXLEdBQUc7WUFDWiwwQkFBaUI7WUFDakIsMEJBQWlCO1NBQ2xCLENBQUE7SUFHSCxDQUFDO0lBRE8sTUFBTTs4REFBSyxPQUFPLEVBQUUsQ0FBQSxDQUFDLENBQUM7S0FBQTtDQUM3QjtBQVZELGtDQVVDIiwiZmlsZSI6ImNvbW1hbmRzL2xpbmsvbGluay5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBDb21tYW5kIH0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgTGlua1NvdXJjZUNvbW1hbmQgfSBmcm9tIFwiLi9zb3VyY2VcIlxuaW1wb3J0IHsgTGlua01vZHVsZUNvbW1hbmQgfSBmcm9tIFwiLi9tb2R1bGVcIlxuXG5leHBvcnQgY2xhc3MgTGlua0NvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwibGlua1wiXG4gIGhlbHAgPSBcIkxpbmsgYSByZW1vdGUgc291cmNlIG9yIG1vZHVsZSB0byBhIGxvY2FsIHBhdGhcIlxuXG4gIHN1YkNvbW1hbmRzID0gW1xuICAgIExpbmtTb3VyY2VDb21tYW5kLFxuICAgIExpbmtNb2R1bGVDb21tYW5kLFxuICBdXG5cbiAgYXN5bmMgYWN0aW9uKCkgeyByZXR1cm4ge30gfVxufVxuIl19 diff --git a/garden-service/build/commands/link/module.d.ts b/garden-service/build/commands/link/module.d.ts new file mode 100644 index 00000000000..bcf442b9f16 --- /dev/null +++ b/garden-service/build/commands/link/module.d.ts @@ -0,0 +1,19 @@ +import { Command, CommandResult, StringParameter, PathParameter, CommandParams } from "../base"; +import { LinkedSource } from "../../config-store"; +declare const linkModuleArguments: { + module: StringParameter; + path: PathParameter; +}; +declare type Args = typeof linkModuleArguments; +export declare class LinkModuleCommand extends Command { + name: string; + help: string; + arguments: { + module: StringParameter; + path: PathParameter; + }; + description: string; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/link/module.js b/garden-service/build/commands/link/module.js new file mode 100644 index 00000000000..5b04f010d6f --- /dev/null +++ b/garden-service/build/commands/link/module.js @@ -0,0 +1,78 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const dedent = require("dedent"); +const chalk_1 = require("chalk"); +const exceptions_1 = require("../../exceptions"); +const base_1 = require("../base"); +const ext_source_util_1 = require("../../util/ext-source-util"); +const linkModuleArguments = { + module: new base_1.StringParameter({ + help: "Name of the module to link.", + required: true, + }), + path: new base_1.PathParameter({ + help: "Path to the local directory that containes the module.", + required: true, + }), +}; +class LinkModuleCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "module"; + this.help = "Link a module to a local directory."; + this.arguments = linkModuleArguments; + this.description = dedent ` + After linking a remote module, Garden will read the source from the module's local directory instead of from + the remote URL. Garden can only link modules that have a remote source, + i.e. modules that specifiy a repositoryUrl in their garden.yml config file. + + Examples: + + garden link module my-module path/to/my-module # links my-module to its local version at the given path + `; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "link", command: "link module" }); + const sourceType = "module"; + const { module: moduleName, path } = args; + const moduleToLink = yield garden.getModule(moduleName); + const isRemote = [moduleToLink].filter(ext_source_util_1.hasRemoteSource)[0]; + if (!isRemote) { + const modulesWithRemoteSource = (yield garden.getModules()).filter(ext_source_util_1.hasRemoteSource).sort(); + throw new exceptions_1.ParameterError(`Expected module(s) ${chalk_1.default.underline(moduleName)} to have a remote source.` + + ` Did you mean to use the "link source" command?`, { + modulesWithRemoteSource, + input: module, + }); + } + const absPath = path_1.resolve(garden.projectRoot, path); + const linkedModuleSources = yield ext_source_util_1.addLinkedSources({ + garden, + sourceType, + sources: [{ name: moduleName, path: absPath }], + }); + garden.log.info(`Linked module ${moduleName}`); + return { result: linkedModuleSources }; + }); + } +} +exports.LinkModuleCommand = LinkModuleCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2xpbmsvbW9kdWxlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCwrQkFBOEI7QUFDOUIsaUNBQWlDO0FBQ2pDLGlDQUF5QjtBQUV6QixpREFBaUQ7QUFDakQsa0NBTWdCO0FBSWhCLGdFQUdtQztBQUVuQyxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLE1BQU0sRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDMUIsSUFBSSxFQUFFLDZCQUE2QjtRQUNuQyxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7SUFDRixJQUFJLEVBQUUsSUFBSSxvQkFBYSxDQUFDO1FBQ3RCLElBQUksRUFBRSx3REFBd0Q7UUFDOUQsUUFBUSxFQUFFLElBQUk7S0FDZixDQUFDO0NBQ0gsQ0FBQTtBQUlELE1BQWEsaUJBQWtCLFNBQVEsY0FBYTtJQUFwRDs7UUFDRSxTQUFJLEdBQUcsUUFBUSxDQUFBO1FBQ2YsU0FBSSxHQUFHLHFDQUFxQyxDQUFBO1FBQzVDLGNBQVMsR0FBRyxtQkFBbUIsQ0FBQTtRQUUvQixnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7Ozs7R0FRbkIsQ0FBQTtJQW9DSCxDQUFDO0lBbENPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQXVCOztZQUNoRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUE7WUFFNUQsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFBO1lBRTNCLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQTtZQUN6QyxNQUFNLFlBQVksR0FBRyxNQUFNLE1BQU0sQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUE7WUFFdkQsTUFBTSxRQUFRLEdBQUcsQ0FBQyxZQUFZLENBQUMsQ0FBQyxNQUFNLENBQUMsaUNBQWUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBQzFELElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2IsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLE1BQU0sTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLGlDQUFlLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtnQkFFMUYsTUFBTSxJQUFJLDJCQUFjLENBQ3RCLHNCQUFzQixlQUFLLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQywyQkFBMkI7b0JBQzVFLGlEQUFpRCxFQUNqRDtvQkFDRSx1QkFBdUI7b0JBQ3ZCLEtBQUssRUFBRSxNQUFNO2lCQUNkLENBQ0YsQ0FBQTthQUNGO1lBRUQsTUFBTSxPQUFPLEdBQUcsY0FBTyxDQUFDLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDakQsTUFBTSxtQkFBbUIsR0FBRyxNQUFNLGtDQUFnQixDQUFDO2dCQUNqRCxNQUFNO2dCQUNOLFVBQVU7Z0JBQ1YsT0FBTyxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxPQUFPLEVBQUUsQ0FBQzthQUMvQyxDQUFDLENBQUE7WUFFRixNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsVUFBVSxFQUFFLENBQUMsQ0FBQTtZQUU5QyxPQUFPLEVBQUUsTUFBTSxFQUFFLG1CQUFtQixFQUFFLENBQUE7UUFFeEMsQ0FBQztLQUFBO0NBQ0Y7QUFqREQsOENBaURDIiwiZmlsZSI6ImNvbW1hbmRzL2xpbmsvbW9kdWxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5cbmltcG9ydCB7IFBhcmFtZXRlckVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgU3RyaW5nUGFyYW1ldGVyLFxuICBQYXRoUGFyYW1ldGVyLFxuICBDb21tYW5kUGFyYW1zLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQge1xuICBMaW5rZWRTb3VyY2UsXG59IGZyb20gXCIuLi8uLi9jb25maWctc3RvcmVcIlxuaW1wb3J0IHtcbiAgYWRkTGlua2VkU291cmNlcyxcbiAgaGFzUmVtb3RlU291cmNlLFxufSBmcm9tIFwiLi4vLi4vdXRpbC9leHQtc291cmNlLXV0aWxcIlxuXG5jb25zdCBsaW5rTW9kdWxlQXJndW1lbnRzID0ge1xuICBtb2R1bGU6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiTmFtZSBvZiB0aGUgbW9kdWxlIHRvIGxpbmsuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxuICBwYXRoOiBuZXcgUGF0aFBhcmFtZXRlcih7XG4gICAgaGVscDogXCJQYXRoIHRvIHRoZSBsb2NhbCBkaXJlY3RvcnkgdGhhdCBjb250YWluZXMgdGhlIG1vZHVsZS5cIixcbiAgICByZXF1aXJlZDogdHJ1ZSxcbiAgfSksXG59XG5cbnR5cGUgQXJncyA9IHR5cGVvZiBsaW5rTW9kdWxlQXJndW1lbnRzXG5cbmV4cG9ydCBjbGFzcyBMaW5rTW9kdWxlQ29tbWFuZCBleHRlbmRzIENvbW1hbmQ8QXJncz4ge1xuICBuYW1lID0gXCJtb2R1bGVcIlxuICBoZWxwID0gXCJMaW5rIGEgbW9kdWxlIHRvIGEgbG9jYWwgZGlyZWN0b3J5LlwiXG4gIGFyZ3VtZW50cyA9IGxpbmtNb2R1bGVBcmd1bWVudHNcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBBZnRlciBsaW5raW5nIGEgcmVtb3RlIG1vZHVsZSwgR2FyZGVuIHdpbGwgcmVhZCB0aGUgc291cmNlIGZyb20gdGhlIG1vZHVsZSdzIGxvY2FsIGRpcmVjdG9yeSBpbnN0ZWFkIG9mIGZyb21cbiAgICB0aGUgcmVtb3RlIFVSTC4gR2FyZGVuIGNhbiBvbmx5IGxpbmsgbW9kdWxlcyB0aGF0IGhhdmUgYSByZW1vdGUgc291cmNlLFxuICAgIGkuZS4gbW9kdWxlcyB0aGF0IHNwZWNpZml5IGEgcmVwb3NpdG9yeVVybCBpbiB0aGVpciBnYXJkZW4ueW1sIGNvbmZpZyBmaWxlLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIGxpbmsgbW9kdWxlIG15LW1vZHVsZSBwYXRoL3RvL215LW1vZHVsZSAjIGxpbmtzIG15LW1vZHVsZSB0byBpdHMgbG9jYWwgdmVyc2lvbiBhdCB0aGUgZ2l2ZW4gcGF0aFxuICBgXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuLCBhcmdzIH06IENvbW1hbmRQYXJhbXM8QXJncz4pOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8TGlua2VkU291cmNlW10+PiB7XG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJsaW5rXCIsIGNvbW1hbmQ6IFwibGluayBtb2R1bGVcIiB9KVxuXG4gICAgY29uc3Qgc291cmNlVHlwZSA9IFwibW9kdWxlXCJcblxuICAgIGNvbnN0IHsgbW9kdWxlOiBtb2R1bGVOYW1lLCBwYXRoIH0gPSBhcmdzXG4gICAgY29uc3QgbW9kdWxlVG9MaW5rID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZShtb2R1bGVOYW1lKVxuXG4gICAgY29uc3QgaXNSZW1vdGUgPSBbbW9kdWxlVG9MaW5rXS5maWx0ZXIoaGFzUmVtb3RlU291cmNlKVswXVxuICAgIGlmICghaXNSZW1vdGUpIHtcbiAgICAgIGNvbnN0IG1vZHVsZXNXaXRoUmVtb3RlU291cmNlID0gKGF3YWl0IGdhcmRlbi5nZXRNb2R1bGVzKCkpLmZpbHRlcihoYXNSZW1vdGVTb3VyY2UpLnNvcnQoKVxuXG4gICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IoXG4gICAgICAgIGBFeHBlY3RlZCBtb2R1bGUocykgJHtjaGFsay51bmRlcmxpbmUobW9kdWxlTmFtZSl9IHRvIGhhdmUgYSByZW1vdGUgc291cmNlLmAgK1xuICAgICAgICBgIERpZCB5b3UgbWVhbiB0byB1c2UgdGhlIFwibGluayBzb3VyY2VcIiBjb21tYW5kP2AsXG4gICAgICAgIHtcbiAgICAgICAgICBtb2R1bGVzV2l0aFJlbW90ZVNvdXJjZSxcbiAgICAgICAgICBpbnB1dDogbW9kdWxlLFxuICAgICAgICB9LFxuICAgICAgKVxuICAgIH1cblxuICAgIGNvbnN0IGFic1BhdGggPSByZXNvbHZlKGdhcmRlbi5wcm9qZWN0Um9vdCwgcGF0aClcbiAgICBjb25zdCBsaW5rZWRNb2R1bGVTb3VyY2VzID0gYXdhaXQgYWRkTGlua2VkU291cmNlcyh7XG4gICAgICBnYXJkZW4sXG4gICAgICBzb3VyY2VUeXBlLFxuICAgICAgc291cmNlczogW3sgbmFtZTogbW9kdWxlTmFtZSwgcGF0aDogYWJzUGF0aCB9XSxcbiAgICB9KVxuXG4gICAgZ2FyZGVuLmxvZy5pbmZvKGBMaW5rZWQgbW9kdWxlICR7bW9kdWxlTmFtZX1gKVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBsaW5rZWRNb2R1bGVTb3VyY2VzIH1cblxuICB9XG59XG4iXX0= diff --git a/garden-service/build/commands/link/source.d.ts b/garden-service/build/commands/link/source.d.ts new file mode 100644 index 00000000000..d236c1a7cd6 --- /dev/null +++ b/garden-service/build/commands/link/source.d.ts @@ -0,0 +1,20 @@ +import { Command, CommandResult, StringParameter, PathParameter } from "../base"; +import { LinkedSource } from "../../config-store"; +import { CommandParams } from "../base"; +declare const linkSourceArguments: { + source: StringParameter; + path: PathParameter; +}; +declare type Args = typeof linkSourceArguments; +export declare class LinkSourceCommand extends Command { + name: string; + help: string; + arguments: { + source: StringParameter; + path: PathParameter; + }; + description: string; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=source.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/link/source.js b/garden-service/build/commands/link/source.js new file mode 100644 index 00000000000..3f977c768b9 --- /dev/null +++ b/garden-service/build/commands/link/source.js @@ -0,0 +1,77 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const dedent = require("dedent"); +const chalk_1 = require("chalk"); +const exceptions_1 = require("../../exceptions"); +const base_1 = require("../base"); +const ext_source_util_1 = require("../../util/ext-source-util"); +const linkSourceArguments = { + source: new base_1.StringParameter({ + help: "Name of the source to link as declared in the project config.", + required: true, + }), + path: new base_1.PathParameter({ + help: "Path to the local directory that containes the source.", + required: true, + }), +}; +class LinkSourceCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "source"; + this.help = "Link a remote source to a local directory."; + this.arguments = linkSourceArguments; + this.description = dedent ` + After linking a remote source, Garden will read it from its local directory instead of + from the remote URL. Garden can only link remote sources that have been declared in the project + level garden.yml config. + + Examples: + + garden link source my-source path/to/my-source # links my-source to its local version at the given path + `; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "link", command: "link source" }); + const sourceType = "project"; + const { source: sourceName, path } = args; + const projectSourceToLink = garden.projectSources.find(src => src.name === sourceName); + if (!projectSourceToLink) { + const availableRemoteSources = garden.projectSources.map(s => s.name).sort(); + throw new exceptions_1.ParameterError(`Remote source ${chalk_1.default.underline(sourceName)} not found in project config.` + + ` Did you mean to use the "link module" command?`, { + availableRemoteSources, + input: sourceName, + }); + } + const absPath = path_1.resolve(garden.projectRoot, path); + const linkedProjectSources = yield ext_source_util_1.addLinkedSources({ + garden, + sourceType, + sources: [{ name: sourceName, path: absPath }], + }); + garden.log.info(`Linked source ${sourceName}`); + return { result: linkedProjectSources }; + }); + } +} +exports.LinkSourceCommand = LinkSourceCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2xpbmsvc291cmNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCwrQkFBOEI7QUFDOUIsaUNBQWlDO0FBQ2pDLGlDQUF5QjtBQUV6QixpREFBaUQ7QUFDakQsa0NBS2dCO0FBQ2hCLGdFQUE2RDtBQUk3RCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLE1BQU0sRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDMUIsSUFBSSxFQUFFLCtEQUErRDtRQUNyRSxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7SUFDRixJQUFJLEVBQUUsSUFBSSxvQkFBYSxDQUFDO1FBQ3RCLElBQUksRUFBRSx3REFBd0Q7UUFDOUQsUUFBUSxFQUFFLElBQUk7S0FDZixDQUFDO0NBQ0gsQ0FBQTtBQUlELE1BQWEsaUJBQWtCLFNBQVEsY0FBYTtJQUFwRDs7UUFDRSxTQUFJLEdBQUcsUUFBUSxDQUFBO1FBQ2YsU0FBSSxHQUFHLDRDQUE0QyxDQUFBO1FBQ25ELGNBQVMsR0FBRyxtQkFBbUIsQ0FBQTtRQUUvQixnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7Ozs7R0FRbkIsQ0FBQTtJQW1DSCxDQUFDO0lBakNPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQXVCOztZQUNoRCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUE7WUFFNUQsTUFBTSxVQUFVLEdBQUcsU0FBUyxDQUFBO1lBRTVCLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxHQUFHLElBQUksQ0FBQTtZQUN6QyxNQUFNLG1CQUFtQixHQUFHLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxDQUFDLElBQUksS0FBSyxVQUFVLENBQUMsQ0FBQTtZQUV0RixJQUFJLENBQUMsbUJBQW1CLEVBQUU7Z0JBQ3hCLE1BQU0sc0JBQXNCLEdBQUcsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsSUFBSSxFQUFFLENBQUE7Z0JBRTVFLE1BQU0sSUFBSSwyQkFBYyxDQUN0QixpQkFBaUIsZUFBSyxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsK0JBQStCO29CQUMzRSxpREFBaUQsRUFDakQ7b0JBQ0Usc0JBQXNCO29CQUN0QixLQUFLLEVBQUUsVUFBVTtpQkFDbEIsQ0FDRixDQUFBO2FBQ0Y7WUFFRCxNQUFNLE9BQU8sR0FBRyxjQUFPLENBQUMsTUFBTSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUVqRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0sa0NBQWdCLENBQUM7Z0JBQ2xELE1BQU07Z0JBQ04sVUFBVTtnQkFDVixPQUFPLEVBQUUsQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUFDO2FBQy9DLENBQUMsQ0FBQTtZQUVGLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGlCQUFpQixVQUFVLEVBQUUsQ0FBQyxDQUFBO1lBRTlDLE9BQU8sRUFBRSxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQTtRQUN6QyxDQUFDO0tBQUE7Q0FDRjtBQWhERCw4Q0FnREMiLCJmaWxlIjoiY29tbWFuZHMvbGluay9zb3VyY2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcblxuaW1wb3J0IHsgUGFyYW1ldGVyRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQge1xuICBDb21tYW5kLFxuICBDb21tYW5kUmVzdWx0LFxuICBTdHJpbmdQYXJhbWV0ZXIsXG4gIFBhdGhQYXJhbWV0ZXIsXG59IGZyb20gXCIuLi9iYXNlXCJcbmltcG9ydCB7IGFkZExpbmtlZFNvdXJjZXMgfSBmcm9tIFwiLi4vLi4vdXRpbC9leHQtc291cmNlLXV0aWxcIlxuaW1wb3J0IHsgTGlua2VkU291cmNlIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy1zdG9yZVwiXG5pbXBvcnQgeyBDb21tYW5kUGFyYW1zIH0gZnJvbSBcIi4uL2Jhc2VcIlxuXG5jb25zdCBsaW5rU291cmNlQXJndW1lbnRzID0ge1xuICBzb3VyY2U6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiTmFtZSBvZiB0aGUgc291cmNlIHRvIGxpbmsgYXMgZGVjbGFyZWQgaW4gdGhlIHByb2plY3QgY29uZmlnLlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbiAgcGF0aDogbmV3IFBhdGhQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiUGF0aCB0byB0aGUgbG9jYWwgZGlyZWN0b3J5IHRoYXQgY29udGFpbmVzIHRoZSBzb3VyY2UuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgbGlua1NvdXJjZUFyZ3VtZW50c1xuXG5leHBvcnQgY2xhc3MgTGlua1NvdXJjZUNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPEFyZ3M+IHtcbiAgbmFtZSA9IFwic291cmNlXCJcbiAgaGVscCA9IFwiTGluayBhIHJlbW90ZSBzb3VyY2UgdG8gYSBsb2NhbCBkaXJlY3RvcnkuXCJcbiAgYXJndW1lbnRzID0gbGlua1NvdXJjZUFyZ3VtZW50c1xuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIEFmdGVyIGxpbmtpbmcgYSByZW1vdGUgc291cmNlLCBHYXJkZW4gd2lsbCByZWFkIGl0IGZyb20gaXRzIGxvY2FsIGRpcmVjdG9yeSBpbnN0ZWFkIG9mXG4gICAgZnJvbSB0aGUgcmVtb3RlIFVSTC4gR2FyZGVuIGNhbiBvbmx5IGxpbmsgcmVtb3RlIHNvdXJjZXMgdGhhdCBoYXZlIGJlZW4gZGVjbGFyZWQgaW4gdGhlIHByb2plY3RcbiAgICBsZXZlbCBnYXJkZW4ueW1sIGNvbmZpZy5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBsaW5rIHNvdXJjZSBteS1zb3VyY2UgcGF0aC90by9teS1zb3VyY2UgIyBsaW5rcyBteS1zb3VyY2UgdG8gaXRzIGxvY2FsIHZlcnNpb24gYXQgdGhlIGdpdmVuIHBhdGhcbiAgYFxuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncyB9OiBDb21tYW5kUGFyYW1zPEFyZ3M+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PExpbmtlZFNvdXJjZVtdPj4ge1xuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwibGlua1wiLCBjb21tYW5kOiBcImxpbmsgc291cmNlXCIgfSlcblxuICAgIGNvbnN0IHNvdXJjZVR5cGUgPSBcInByb2plY3RcIlxuXG4gICAgY29uc3QgeyBzb3VyY2U6IHNvdXJjZU5hbWUsIHBhdGggfSA9IGFyZ3NcbiAgICBjb25zdCBwcm9qZWN0U291cmNlVG9MaW5rID0gZ2FyZGVuLnByb2plY3RTb3VyY2VzLmZpbmQoc3JjID0+IHNyYy5uYW1lID09PSBzb3VyY2VOYW1lKVxuXG4gICAgaWYgKCFwcm9qZWN0U291cmNlVG9MaW5rKSB7XG4gICAgICBjb25zdCBhdmFpbGFibGVSZW1vdGVTb3VyY2VzID0gZ2FyZGVuLnByb2plY3RTb3VyY2VzLm1hcChzID0+IHMubmFtZSkuc29ydCgpXG5cbiAgICAgIHRocm93IG5ldyBQYXJhbWV0ZXJFcnJvcihcbiAgICAgICAgYFJlbW90ZSBzb3VyY2UgJHtjaGFsay51bmRlcmxpbmUoc291cmNlTmFtZSl9IG5vdCBmb3VuZCBpbiBwcm9qZWN0IGNvbmZpZy5gICtcbiAgICAgICAgYCBEaWQgeW91IG1lYW4gdG8gdXNlIHRoZSBcImxpbmsgbW9kdWxlXCIgY29tbWFuZD9gLFxuICAgICAgICB7XG4gICAgICAgICAgYXZhaWxhYmxlUmVtb3RlU291cmNlcyxcbiAgICAgICAgICBpbnB1dDogc291cmNlTmFtZSxcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9XG5cbiAgICBjb25zdCBhYnNQYXRoID0gcmVzb2x2ZShnYXJkZW4ucHJvamVjdFJvb3QsIHBhdGgpXG5cbiAgICBjb25zdCBsaW5rZWRQcm9qZWN0U291cmNlcyA9IGF3YWl0IGFkZExpbmtlZFNvdXJjZXMoe1xuICAgICAgZ2FyZGVuLFxuICAgICAgc291cmNlVHlwZSxcbiAgICAgIHNvdXJjZXM6IFt7IG5hbWU6IHNvdXJjZU5hbWUsIHBhdGg6IGFic1BhdGggfV0sXG4gICAgfSlcblxuICAgIGdhcmRlbi5sb2cuaW5mbyhgTGlua2VkIHNvdXJjZSAke3NvdXJjZU5hbWV9YClcblxuICAgIHJldHVybiB7IHJlc3VsdDogbGlua2VkUHJvamVjdFNvdXJjZXMgfVxuICB9XG59XG4iXX0= diff --git a/garden-service/build/commands/logs.d.ts b/garden-service/build/commands/logs.d.ts new file mode 100644 index 00000000000..25751a86fee --- /dev/null +++ b/garden-service/build/commands/logs.d.ts @@ -0,0 +1,26 @@ +import { BooleanParameter, Command, CommandResult, CommandParams, StringsParameter } from "./base"; +import { ServiceLogEntry } from "../types/plugin/outputs"; +import { LoggerType } from "../logger/logger"; +declare const logsArgs: { + service: StringsParameter; +}; +declare const logsOpts: { + tail: BooleanParameter; +}; +declare type Args = typeof logsArgs; +declare type Opts = typeof logsOpts; +export declare class LogsCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + service: StringsParameter; + }; + options: { + tail: BooleanParameter; + }; + loggerType: LoggerType; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=logs.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/logs.js b/garden-service/build/commands/logs.js new file mode 100644 index 00000000000..bbd42ece155 --- /dev/null +++ b/garden-service/build/commands/logs.js @@ -0,0 +1,87 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const chalk_1 = require("chalk"); +const Bluebird = require("bluebird"); +const ts_stream_1 = require("ts-stream"); +const logger_1 = require("../logger/logger"); +const dedent = require("dedent"); +const logsArgs = { + service: new base_1.StringsParameter({ + help: "The name of the service(s) to logs (skip to logs all services). " + + "Use comma as separator to specify multiple services.", + }), +}; +const logsOpts = { + tail: new base_1.BooleanParameter({ help: "Continuously stream new logs from the service(s).", alias: "t" }), +}; +class LogsCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "logs"; + this.help = "Retrieves the most recent logs for the specified service(s)."; + this.description = dedent ` + Outputs logs for all or specified services, and optionally waits for news logs to come in. + + Examples: + + garden logs # prints latest logs from all services + garden logs my-service # prints latest logs for my-service + garden logs -t # keeps running and streams all incoming logs to the console + `; + this.arguments = logsArgs; + this.options = logsOpts; + this.loggerType = logger_1.LoggerType.basic; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const tail = opts.tail; + const services = yield garden.getServices(args.service); + const result = []; + const stream = new ts_stream_1.default(); + // TODO: use basic logger (no need for fancy stuff here, just causes flickering) + void stream.forEach((entry) => { + // TODO: color each service differently for easier visual parsing + let timestamp = " "; + // bad timestamp values can cause crash if not caught + if (entry.timestamp) { + try { + timestamp = entry.timestamp.toISOString(); + } + catch (_a) { } + } + garden.log.info({ + section: entry.serviceName, + msg: [timestamp, chalk_1.default.white(entry.msg)], + }); + if (!tail) { + result.push(entry); + } + }); + // NOTE: This will work differently when we have Elasticsearch set up for logging, but is + // quite servicable for now. + yield Bluebird.map(services, (service) => __awaiter(this, void 0, void 0, function* () { + yield garden.actions.getServiceLogs({ service, stream, tail }); + })); + return { result }; + }); + } +} +exports.LogsCommand = LogsCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL2xvZ3MudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQU1lO0FBQ2YsaUNBQXlCO0FBRXpCLHFDQUFxQztBQUVyQyx5Q0FBOEI7QUFDOUIsNkNBQTZDO0FBQzdDLGlDQUFpQztBQUVqQyxNQUFNLFFBQVEsR0FBRztJQUNmLE9BQU8sRUFBRSxJQUFJLHVCQUFnQixDQUFDO1FBQzVCLElBQUksRUFBRSxrRUFBa0U7WUFDdEUsc0RBQXNEO0tBQ3pELENBQUM7Q0FDSCxDQUFBO0FBRUQsTUFBTSxRQUFRLEdBQUc7SUFDZixJQUFJLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSxtREFBbUQsRUFBRSxLQUFLLEVBQUUsR0FBRyxFQUFFLENBQUM7Q0FHdEcsQ0FBQTtBQUtELE1BQWEsV0FBWSxTQUFRLGNBQW1CO0lBQXBEOztRQUNFLFNBQUksR0FBRyxNQUFNLENBQUE7UUFDYixTQUFJLEdBQUcsOERBQThELENBQUE7UUFFckUsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7O0dBUW5CLENBQUE7UUFFRCxjQUFTLEdBQUcsUUFBUSxDQUFBO1FBQ3BCLFlBQU8sR0FBRyxRQUFRLENBQUE7UUFDbEIsZUFBVSxHQUFHLG1CQUFVLENBQUMsS0FBSyxDQUFBO0lBdUMvQixDQUFDO0lBckNPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUE2Qjs7WUFDNUQsTUFBTSxJQUFJLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQTtZQUN0QixNQUFNLFFBQVEsR0FBRyxNQUFNLE1BQU0sQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBRXZELE1BQU0sTUFBTSxHQUFzQixFQUFFLENBQUE7WUFDcEMsTUFBTSxNQUFNLEdBQUcsSUFBSSxtQkFBTSxFQUFtQixDQUFBO1lBRTVDLGdGQUFnRjtZQUNoRixLQUFLLE1BQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRTtnQkFDNUIsaUVBQWlFO2dCQUNqRSxJQUFJLFNBQVMsR0FBRywwQkFBMEIsQ0FBQTtnQkFFMUMscURBQXFEO2dCQUNyRCxJQUFJLEtBQUssQ0FBQyxTQUFTLEVBQUU7b0JBQ25CLElBQUk7d0JBQ0YsU0FBUyxHQUFHLEtBQUssQ0FBQyxTQUFTLENBQUMsV0FBVyxFQUFFLENBQUE7cUJBQzFDO29CQUFDLFdBQU0sR0FBRztpQkFDWjtnQkFFRCxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztvQkFDZCxPQUFPLEVBQUUsS0FBSyxDQUFDLFdBQVc7b0JBQzFCLEdBQUcsRUFBRSxDQUFDLFNBQVMsRUFBRSxlQUFLLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztpQkFDekMsQ0FBQyxDQUFBO2dCQUVGLElBQUksQ0FBQyxJQUFJLEVBQUU7b0JBQ1QsTUFBTSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUMsQ0FBQTtpQkFDbkI7WUFDSCxDQUFDLENBQUMsQ0FBQTtZQUVGLHlGQUF5RjtZQUN6RixrQ0FBa0M7WUFDbEMsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDLFFBQVEsRUFBRSxDQUFPLE9BQXFCLEVBQUUsRUFBRTtnQkFDM0QsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTtZQUNoRSxDQUFDLENBQUEsQ0FBQyxDQUFBO1lBRUYsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFBO1FBQ25CLENBQUM7S0FBQTtDQUNGO0FBdkRELGtDQXVEQyIsImZpbGUiOiJjb21tYW5kcy9sb2dzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIEJvb2xlYW5QYXJhbWV0ZXIsXG4gIENvbW1hbmQsXG4gIENvbW1hbmRSZXN1bHQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5pbXBvcnQgeyBTZXJ2aWNlTG9nRW50cnkgfSBmcm9tIFwiLi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IEJsdWViaXJkID0gcmVxdWlyZShcImJsdWViaXJkXCIpXG5pbXBvcnQgeyBTZXJ2aWNlIH0gZnJvbSBcIi4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IFN0cmVhbSBmcm9tIFwidHMtc3RyZWFtXCJcbmltcG9ydCB7IExvZ2dlclR5cGUgfSBmcm9tIFwiLi4vbG9nZ2VyL2xvZ2dlclwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5jb25zdCBsb2dzQXJncyA9IHtcbiAgc2VydmljZTogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHNlcnZpY2UocykgdG8gbG9ncyAoc2tpcCB0byBsb2dzIGFsbCBzZXJ2aWNlcykuIFwiICtcbiAgICAgIFwiVXNlIGNvbW1hIGFzIHNlcGFyYXRvciB0byBzcGVjaWZ5IG11bHRpcGxlIHNlcnZpY2VzLlwiLFxuICB9KSxcbn1cblxuY29uc3QgbG9nc09wdHMgPSB7XG4gIHRhaWw6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJDb250aW51b3VzbHkgc3RyZWFtIG5ldyBsb2dzIGZyb20gdGhlIHNlcnZpY2UocykuXCIsIGFsaWFzOiBcInRcIiB9KSxcbiAgLy8gVE9ET1xuICAvLyBzaW5jZTogbmV3IE1vbWVudFBhcmFtZXRlcih7IGhlbHA6IFwiUmV0cmlldmUgbG9ncyBmcm9tIHRoZSBzcGVjaWZpZWQgcG9pbnQgb253YXJkc1wiIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgbG9nc0FyZ3NcbnR5cGUgT3B0cyA9IHR5cGVvZiBsb2dzT3B0c1xuXG5leHBvcnQgY2xhc3MgTG9nc0NvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPEFyZ3MsIE9wdHM+IHtcbiAgbmFtZSA9IFwibG9nc1wiXG4gIGhlbHAgPSBcIlJldHJpZXZlcyB0aGUgbW9zdCByZWNlbnQgbG9ncyBmb3IgdGhlIHNwZWNpZmllZCBzZXJ2aWNlKHMpLlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgT3V0cHV0cyBsb2dzIGZvciBhbGwgb3Igc3BlY2lmaWVkIHNlcnZpY2VzLCBhbmQgb3B0aW9uYWxseSB3YWl0cyBmb3IgbmV3cyBsb2dzIHRvIGNvbWUgaW4uXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gbG9ncyAgICAgICAgICAgICAgICMgcHJpbnRzIGxhdGVzdCBsb2dzIGZyb20gYWxsIHNlcnZpY2VzXG4gICAgICAgIGdhcmRlbiBsb2dzIG15LXNlcnZpY2UgICAgIyBwcmludHMgbGF0ZXN0IGxvZ3MgZm9yIG15LXNlcnZpY2VcbiAgICAgICAgZ2FyZGVuIGxvZ3MgLXQgICAgICAgICAgICAjIGtlZXBzIHJ1bm5pbmcgYW5kIHN0cmVhbXMgYWxsIGluY29taW5nIGxvZ3MgdG8gdGhlIGNvbnNvbGVcbiAgYFxuXG4gIGFyZ3VtZW50cyA9IGxvZ3NBcmdzXG4gIG9wdGlvbnMgPSBsb2dzT3B0c1xuICBsb2dnZXJUeXBlID0gTG9nZ2VyVHlwZS5iYXNpY1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFNlcnZpY2VMb2dFbnRyeVtdPj4ge1xuICAgIGNvbnN0IHRhaWwgPSBvcHRzLnRhaWxcbiAgICBjb25zdCBzZXJ2aWNlcyA9IGF3YWl0IGdhcmRlbi5nZXRTZXJ2aWNlcyhhcmdzLnNlcnZpY2UpXG5cbiAgICBjb25zdCByZXN1bHQ6IFNlcnZpY2VMb2dFbnRyeVtdID0gW11cbiAgICBjb25zdCBzdHJlYW0gPSBuZXcgU3RyZWFtPFNlcnZpY2VMb2dFbnRyeT4oKVxuXG4gICAgLy8gVE9ETzogdXNlIGJhc2ljIGxvZ2dlciAobm8gbmVlZCBmb3IgZmFuY3kgc3R1ZmYgaGVyZSwganVzdCBjYXVzZXMgZmxpY2tlcmluZylcbiAgICB2b2lkIHN0cmVhbS5mb3JFYWNoKChlbnRyeSkgPT4ge1xuICAgICAgLy8gVE9ETzogY29sb3IgZWFjaCBzZXJ2aWNlIGRpZmZlcmVudGx5IGZvciBlYXNpZXIgdmlzdWFsIHBhcnNpbmdcbiAgICAgIGxldCB0aW1lc3RhbXAgPSBcIiAgICAgICAgICAgICAgICAgICAgICAgIFwiXG5cbiAgICAgIC8vIGJhZCB0aW1lc3RhbXAgdmFsdWVzIGNhbiBjYXVzZSBjcmFzaCBpZiBub3QgY2F1Z2h0XG4gICAgICBpZiAoZW50cnkudGltZXN0YW1wKSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgdGltZXN0YW1wID0gZW50cnkudGltZXN0YW1wLnRvSVNPU3RyaW5nKClcbiAgICAgICAgfSBjYXRjaCB7IH1cbiAgICAgIH1cblxuICAgICAgZ2FyZGVuLmxvZy5pbmZvKHtcbiAgICAgICAgc2VjdGlvbjogZW50cnkuc2VydmljZU5hbWUsXG4gICAgICAgIG1zZzogW3RpbWVzdGFtcCwgY2hhbGsud2hpdGUoZW50cnkubXNnKV0sXG4gICAgICB9KVxuXG4gICAgICBpZiAoIXRhaWwpIHtcbiAgICAgICAgcmVzdWx0LnB1c2goZW50cnkpXG4gICAgICB9XG4gICAgfSlcblxuICAgIC8vIE5PVEU6IFRoaXMgd2lsbCB3b3JrIGRpZmZlcmVudGx5IHdoZW4gd2UgaGF2ZSBFbGFzdGljc2VhcmNoIHNldCB1cCBmb3IgbG9nZ2luZywgYnV0IGlzXG4gICAgLy8gICAgICAgcXVpdGUgc2VydmljYWJsZSBmb3Igbm93LlxuICAgIGF3YWl0IEJsdWViaXJkLm1hcChzZXJ2aWNlcywgYXN5bmMgKHNlcnZpY2U6IFNlcnZpY2U8YW55PikgPT4ge1xuICAgICAgYXdhaXQgZ2FyZGVuLmFjdGlvbnMuZ2V0U2VydmljZUxvZ3MoeyBzZXJ2aWNlLCBzdHJlYW0sIHRhaWwgfSlcbiAgICB9KVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/publish.d.ts b/garden-service/build/commands/publish.d.ts new file mode 100644 index 00000000000..1e360cc3fb5 --- /dev/null +++ b/garden-service/build/commands/publish.d.ts @@ -0,0 +1,29 @@ +import { BooleanParameter, Command, CommandParams, CommandResult, StringsParameter } from "./base"; +import { Module } from "../types/module"; +import { TaskResults } from "../task-graph"; +import { Garden } from "../garden"; +declare const publishArgs: { + module: StringsParameter; +}; +declare const publishOpts: { + "force-build": BooleanParameter; + "allow-dirty": BooleanParameter; +}; +declare type Args = typeof publishArgs; +declare type Opts = typeof publishOpts; +export declare class PublishCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + module: StringsParameter; + }; + options: { + "force-build": BooleanParameter; + "allow-dirty": BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export declare function publishModules(garden: Garden, modules: Module[], forceBuild: boolean, allowDirty: boolean): Promise; +export {}; +//# sourceMappingURL=publish.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/publish.js b/garden-service/build/commands/publish.js new file mode 100644 index 00000000000..f0793a7d5ab --- /dev/null +++ b/garden-service/build/commands/publish.js @@ -0,0 +1,81 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const publish_1 = require("../tasks/publish"); +const exceptions_1 = require("../exceptions"); +const dedent = require("dedent"); +const publishArgs = { + module: new base_1.StringsParameter({ + help: "The name of the module(s) to publish (skip to publish all modules). " + + "Use comma as separator to specify multiple modules.", + }), +}; +const publishOpts = { + "force-build": new base_1.BooleanParameter({ + help: "Force rebuild of module(s) before publishing.", + }), + "allow-dirty": new base_1.BooleanParameter({ + help: "Allow publishing dirty builds (with untracked/uncommitted changes).", + }), +}; +class PublishCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "publish"; + this.help = "Build and publish module(s) to a remote registry."; + this.description = dedent ` + Publishes built module artifacts for all or specified modules. + Also builds modules and dependencies if needed. + + Examples: + + garden publish # publish artifacts for all modules in the project + garden publish my-container # only publish my-container + garden publish --force-build # force re-build of modules before publishing artifacts + garden publish --allow-dirty # allow publishing dirty builds (which by default triggers error) + `; + this.arguments = publishArgs; + this.options = publishOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "rocket", command: "Publish modules" }); + const modules = yield garden.getModules(args.module); + const results = yield publishModules(garden, modules, !!opts["force-build"], !!opts["allow-dirty"]); + return base_1.handleTaskResults(garden, "publish", { taskResults: results }); + }); + } +} +exports.PublishCommand = PublishCommand; +function publishModules(garden, modules, forceBuild, allowDirty) { + return __awaiter(this, void 0, void 0, function* () { + for (const module of modules) { + const version = module.version; + if (version.dirtyTimestamp && !allowDirty) { + throw new exceptions_1.RuntimeError(`Module ${module.name} has uncommitted changes. ` + + `Please commit them, clean the module's source tree or set the --allow-dirty flag to override.`, { moduleName: module.name, version }); + } + const task = new publish_1.PublishTask({ garden, module, forceBuild }); + yield garden.addTask(task); + } + return yield garden.processTasks(); + }); +} +exports.publishModules = publishModules; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3B1Ymxpc2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQU9lO0FBRWYsOENBQThDO0FBQzlDLDhDQUE0QztBQUc1QyxpQ0FBaUM7QUFFakMsTUFBTSxXQUFXLEdBQUc7SUFDbEIsTUFBTSxFQUFFLElBQUksdUJBQWdCLENBQUM7UUFDM0IsSUFBSSxFQUFFLHNFQUFzRTtZQUMxRSxxREFBcUQ7S0FDeEQsQ0FBQztDQUNILENBQUE7QUFFRCxNQUFNLFdBQVcsR0FBRztJQUNsQixhQUFhLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUNsQyxJQUFJLEVBQUUsK0NBQStDO0tBQ3RELENBQUM7SUFDRixhQUFhLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUNsQyxJQUFJLEVBQUUscUVBQXFFO0tBQzVFLENBQUM7Q0FDSCxDQUFBO0FBS0QsTUFBYSxjQUFlLFNBQVEsY0FBbUI7SUFBdkQ7O1FBQ0UsU0FBSSxHQUFHLFNBQVMsQ0FBQTtRQUNoQixTQUFJLEdBQUcsbURBQW1ELENBQUE7UUFFMUQsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7Ozs7R0FVbkIsQ0FBQTtRQUVELGNBQVMsR0FBRyxXQUFXLENBQUE7UUFDdkIsWUFBTyxHQUFHLFdBQVcsQ0FBQTtJQVd2QixDQUFDO0lBVE8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQTZCOztZQUM1RCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLGlCQUFpQixFQUFFLENBQUMsQ0FBQTtZQUVsRSxNQUFNLE9BQU8sR0FBRyxNQUFNLE1BQU0sQ0FBQyxVQUFVLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1lBRXBELE1BQU0sT0FBTyxHQUFHLE1BQU0sY0FBYyxDQUFDLE1BQU0sRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUE7WUFFbkcsT0FBTyx3QkFBaUIsQ0FBQyxNQUFNLEVBQUUsU0FBUyxFQUFFLEVBQUUsV0FBVyxFQUFFLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFDdkUsQ0FBQztLQUFBO0NBQ0Y7QUE1QkQsd0NBNEJDO0FBRUQsU0FBc0IsY0FBYyxDQUNsQyxNQUFjLEVBQ2QsT0FBc0IsRUFDdEIsVUFBbUIsRUFDbkIsVUFBbUI7O1FBRW5CLEtBQUssTUFBTSxNQUFNLElBQUksT0FBTyxFQUFFO1lBQzVCLE1BQU0sT0FBTyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUE7WUFFOUIsSUFBSSxPQUFPLENBQUMsY0FBYyxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUN6QyxNQUFNLElBQUkseUJBQVksQ0FDcEIsVUFBVSxNQUFNLENBQUMsSUFBSSw0QkFBNEI7b0JBQ2pELCtGQUErRixFQUMvRixFQUFFLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSSxFQUFFLE9BQU8sRUFBRSxDQUNyQyxDQUFBO2FBQ0Y7WUFFRCxNQUFNLElBQUksR0FBRyxJQUFJLHFCQUFXLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUE7WUFDNUQsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxDQUFBO1NBQzNCO1FBRUQsT0FBTyxNQUFNLE1BQU0sQ0FBQyxZQUFZLEVBQUUsQ0FBQTtJQUNwQyxDQUFDO0NBQUE7QUF0QkQsd0NBc0JDIiwiZmlsZSI6ImNvbW1hbmRzL3B1Ymxpc2guanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHtcbiAgQm9vbGVhblBhcmFtZXRlcixcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgaGFuZGxlVGFza1Jlc3VsdHMsXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBQdWJsaXNoVGFzayB9IGZyb20gXCIuLi90YXNrcy9wdWJsaXNoXCJcbmltcG9ydCB7IFJ1bnRpbWVFcnJvciB9IGZyb20gXCIuLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IFRhc2tSZXN1bHRzIH0gZnJvbSBcIi4uL3Rhc2stZ3JhcGhcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4uL2dhcmRlblwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5jb25zdCBwdWJsaXNoQXJncyA9IHtcbiAgbW9kdWxlOiBuZXcgU3RyaW5nc1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJUaGUgbmFtZSBvZiB0aGUgbW9kdWxlKHMpIHRvIHB1Ymxpc2ggKHNraXAgdG8gcHVibGlzaCBhbGwgbW9kdWxlcykuIFwiICtcbiAgICAgIFwiVXNlIGNvbW1hIGFzIHNlcGFyYXRvciB0byBzcGVjaWZ5IG11bHRpcGxlIG1vZHVsZXMuXCIsXG4gIH0pLFxufVxuXG5jb25zdCBwdWJsaXNoT3B0cyA9IHtcbiAgXCJmb3JjZS1idWlsZFwiOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7XG4gICAgaGVscDogXCJGb3JjZSByZWJ1aWxkIG9mIG1vZHVsZShzKSBiZWZvcmUgcHVibGlzaGluZy5cIixcbiAgfSksXG4gIFwiYWxsb3ctZGlydHlcIjogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiQWxsb3cgcHVibGlzaGluZyBkaXJ0eSBidWlsZHMgKHdpdGggdW50cmFja2VkL3VuY29tbWl0dGVkIGNoYW5nZXMpLlwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIHB1Ymxpc2hBcmdzXG50eXBlIE9wdHMgPSB0eXBlb2YgcHVibGlzaE9wdHNcblxuZXhwb3J0IGNsYXNzIFB1Ymxpc2hDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzLCBPcHRzPiB7XG4gIG5hbWUgPSBcInB1Ymxpc2hcIlxuICBoZWxwID0gXCJCdWlsZCBhbmQgcHVibGlzaCBtb2R1bGUocykgdG8gYSByZW1vdGUgcmVnaXN0cnkuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBQdWJsaXNoZXMgYnVpbHQgbW9kdWxlIGFydGlmYWN0cyBmb3IgYWxsIG9yIHNwZWNpZmllZCBtb2R1bGVzLlxuICAgIEFsc28gYnVpbGRzIG1vZHVsZXMgYW5kIGRlcGVuZGVuY2llcyBpZiBuZWVkZWQuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gcHVibGlzaCAgICAgICAgICAgICAgICAjIHB1Ymxpc2ggYXJ0aWZhY3RzIGZvciBhbGwgbW9kdWxlcyBpbiB0aGUgcHJvamVjdFxuICAgICAgICBnYXJkZW4gcHVibGlzaCBteS1jb250YWluZXIgICAjIG9ubHkgcHVibGlzaCBteS1jb250YWluZXJcbiAgICAgICAgZ2FyZGVuIHB1Ymxpc2ggLS1mb3JjZS1idWlsZCAgIyBmb3JjZSByZS1idWlsZCBvZiBtb2R1bGVzIGJlZm9yZSBwdWJsaXNoaW5nIGFydGlmYWN0c1xuICAgICAgICBnYXJkZW4gcHVibGlzaCAtLWFsbG93LWRpcnR5ICAjIGFsbG93IHB1Ymxpc2hpbmcgZGlydHkgYnVpbGRzICh3aGljaCBieSBkZWZhdWx0IHRyaWdnZXJzIGVycm9yKVxuICBgXG5cbiAgYXJndW1lbnRzID0gcHVibGlzaEFyZ3NcbiAgb3B0aW9ucyA9IHB1Ymxpc2hPcHRzXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuLCBhcmdzLCBvcHRzIH06IENvbW1hbmRQYXJhbXM8QXJncywgT3B0cz4pOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8VGFza1Jlc3VsdHM+PiB7XG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJyb2NrZXRcIiwgY29tbWFuZDogXCJQdWJsaXNoIG1vZHVsZXNcIiB9KVxuXG4gICAgY29uc3QgbW9kdWxlcyA9IGF3YWl0IGdhcmRlbi5nZXRNb2R1bGVzKGFyZ3MubW9kdWxlKVxuXG4gICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IHB1Ymxpc2hNb2R1bGVzKGdhcmRlbiwgbW9kdWxlcywgISFvcHRzW1wiZm9yY2UtYnVpbGRcIl0sICEhb3B0c1tcImFsbG93LWRpcnR5XCJdKVxuXG4gICAgcmV0dXJuIGhhbmRsZVRhc2tSZXN1bHRzKGdhcmRlbiwgXCJwdWJsaXNoXCIsIHsgdGFza1Jlc3VsdHM6IHJlc3VsdHMgfSlcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHVibGlzaE1vZHVsZXMoXG4gIGdhcmRlbjogR2FyZGVuLFxuICBtb2R1bGVzOiBNb2R1bGU8YW55PltdLFxuICBmb3JjZUJ1aWxkOiBib29sZWFuLFxuICBhbGxvd0RpcnR5OiBib29sZWFuLFxuKTogUHJvbWlzZTxUYXNrUmVzdWx0cz4ge1xuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBtb2R1bGVzKSB7XG4gICAgY29uc3QgdmVyc2lvbiA9IG1vZHVsZS52ZXJzaW9uXG5cbiAgICBpZiAodmVyc2lvbi5kaXJ0eVRpbWVzdGFtcCAmJiAhYWxsb3dEaXJ0eSkge1xuICAgICAgdGhyb3cgbmV3IFJ1bnRpbWVFcnJvcihcbiAgICAgICAgYE1vZHVsZSAke21vZHVsZS5uYW1lfSBoYXMgdW5jb21taXR0ZWQgY2hhbmdlcy4gYCArXG4gICAgICAgIGBQbGVhc2UgY29tbWl0IHRoZW0sIGNsZWFuIHRoZSBtb2R1bGUncyBzb3VyY2UgdHJlZSBvciBzZXQgdGhlIC0tYWxsb3ctZGlydHkgZmxhZyB0byBvdmVycmlkZS5gLFxuICAgICAgICB7IG1vZHVsZU5hbWU6IG1vZHVsZS5uYW1lLCB2ZXJzaW9uIH0sXG4gICAgICApXG4gICAgfVxuXG4gICAgY29uc3QgdGFzayA9IG5ldyBQdWJsaXNoVGFzayh7IGdhcmRlbiwgbW9kdWxlLCBmb3JjZUJ1aWxkIH0pXG4gICAgYXdhaXQgZ2FyZGVuLmFkZFRhc2sodGFzaylcbiAgfVxuXG4gIHJldHVybiBhd2FpdCBnYXJkZW4ucHJvY2Vzc1Rhc2tzKClcbn1cbiJdfQ== diff --git a/garden-service/build/commands/run/module.d.ts b/garden-service/build/commands/run/module.d.ts new file mode 100644 index 00000000000..427e2d0f3cc --- /dev/null +++ b/garden-service/build/commands/run/module.d.ts @@ -0,0 +1,29 @@ +import { RunResult } from "../../types/plugin/outputs"; +import { BooleanParameter, Command, CommandParams, StringParameter, CommandResult, StringsParameter } from "../base"; +declare const runArgs: { + module: StringParameter; + command: StringsParameter; +}; +declare const runOpts: { + interactive: BooleanParameter; + "force-build": BooleanParameter; +}; +declare type Args = typeof runArgs; +declare type Opts = typeof runOpts; +export declare class RunModuleCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + arguments: { + module: StringParameter; + command: StringsParameter; + }; + options: { + interactive: BooleanParameter; + "force-build": BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/run/module.js b/garden-service/build/commands/run/module.js new file mode 100644 index 00000000000..ca0cae47cbe --- /dev/null +++ b/garden-service/build/commands/run/module.js @@ -0,0 +1,97 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const build_1 = require("../../tasks/build"); +const base_1 = require("../base"); +const lodash_1 = require("lodash"); +const run_1 = require("./run"); +const dedent = require("dedent"); +const service_1 = require("../../types/service"); +const runArgs = { + module: new base_1.StringParameter({ + help: "The name of the module to run.", + required: true, + }), + // TODO: make this a variadic arg + command: new base_1.StringsParameter({ + help: "The command to run in the module.", + }), +}; +const runOpts = { + // TODO: we could provide specific parameters like this by adding commands for specific modules, via plugins + //entrypoint: new StringParameter({ help: "Override default entrypoint in module" }), + interactive: new base_1.BooleanParameter({ + help: "Set to false to skip interactive mode and just output the command result.", + defaultValue: true, + }), + "force-build": new base_1.BooleanParameter({ help: "Force rebuild of module before running." }), +}; +class RunModuleCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "module"; + this.alias = "m"; + this.help = "Run an ad-hoc instance of a module."; + this.description = dedent ` + This is useful for debugging or ad-hoc experimentation with modules. + + Examples: + + garden run module my-container # run an ad-hoc instance of a my-container container and attach to it + garden run module my-container /bin/sh # run an interactive shell in a new my-container container + garden run module my-container --i=false /some/script # execute a script in my-container and return the output + `; + this.arguments = runArgs; + this.options = runOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const moduleName = args.module; + const module = yield garden.getModule(moduleName); + const msg = args.command + ? `Running command ${chalk_1.default.white(args.command.join(" "))} in module ${chalk_1.default.white(moduleName)}` + : `Running module ${chalk_1.default.white(moduleName)}`; + garden.log.header({ + emoji: "runner", + command: msg, + }); + yield garden.actions.prepareEnvironment({}); + const buildTask = new build_1.BuildTask({ garden, module, force: opts["force-build"] }); + yield garden.addTask(buildTask); + yield garden.processTasks(); + const command = args.command || []; + // combine all dependencies for all services in the module, to be sure we have all the context we need + const depNames = lodash_1.uniq(lodash_1.flatten(module.serviceConfigs.map(s => s.dependencies))); + const deps = yield garden.getServices(depNames); + const runtimeContext = yield service_1.prepareRuntimeContext(garden, module, deps); + run_1.printRuntimeContext(garden, runtimeContext); + garden.log.info(""); + const result = yield garden.actions.runModule({ + module, + command, + runtimeContext, + silent: false, + interactive: opts.interactive, + }); + return { result }; + }); + } +} +exports.RunModuleCommand = RunModuleCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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LEdBQUcsTUFBTSwrQkFBcUIsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO1lBRXhFLHlCQUFtQixDQUFDLE1BQU0sRUFBRSxjQUFjLENBQUMsQ0FBQTtZQUUzQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUVuQixNQUFNLE1BQU0sR0FBRyxNQUFNLE1BQU0sQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDO2dCQUM1QyxNQUFNO2dCQUNOLE9BQU87Z0JBQ1AsY0FBYztnQkFDZCxNQUFNLEVBQUUsS0FBSztnQkFDYixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7YUFDOUIsQ0FBQyxDQUFBO1lBRUYsT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFBO1FBQ25CLENBQUM7S0FBQTtDQUNGO0FBM0RELDRDQTJEQyIsImZpbGUiOiJjb21tYW5kcy9ydW4vbW9kdWxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgQnVpbGRUYXNrIH0gZnJvbSBcIi4uLy4uL3Rhc2tzL2J1aWxkXCJcbmltcG9ydCB7IFJ1blJlc3VsdCB9IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQge1xuICBCb29sZWFuUGFyYW1ldGVyLFxuICBDb21tYW5kLFxuICBDb21tYW5kUGFyYW1zLFxuICBTdHJpbmdQYXJhbWV0ZXIsXG4gIENvbW1hbmRSZXN1bHQsXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuLi9iYXNlXCJcbmltcG9ydCB7XG4gIHVuaXEsXG4gIGZsYXR0ZW4sXG59IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgcHJpbnRSdW50aW1lQ29udGV4dCB9IGZyb20gXCIuL3J1blwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuaW1wb3J0IHsgcHJlcGFyZVJ1bnRpbWVDb250ZXh0IH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuXG5jb25zdCBydW5BcmdzID0ge1xuICBtb2R1bGU6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIG1vZHVsZSB0byBydW4uXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxuICAvLyBUT0RPOiBtYWtlIHRoaXMgYSB2YXJpYWRpYyBhcmdcbiAgY29tbWFuZDogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIGNvbW1hbmQgdG8gcnVuIGluIHRoZSBtb2R1bGUuXCIsXG4gIH0pLFxufVxuXG5jb25zdCBydW5PcHRzID0ge1xuICAvLyBUT0RPOiB3ZSBjb3VsZCBwcm92aWRlIHNwZWNpZmljIHBhcmFtZXRlcnMgbGlrZSB0aGlzIGJ5IGFkZGluZyBjb21tYW5kcyBmb3Igc3BlY2lmaWMgbW9kdWxlcywgdmlhIHBsdWdpbnNcbiAgLy9lbnRyeXBvaW50OiBuZXcgU3RyaW5nUGFyYW1ldGVyKHsgaGVscDogXCJPdmVycmlkZSBkZWZhdWx0IGVudHJ5cG9pbnQgaW4gbW9kdWxlXCIgfSksXG4gIGludGVyYWN0aXZlOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7XG4gICAgaGVscDogXCJTZXQgdG8gZmFsc2UgdG8gc2tpcCBpbnRlcmFjdGl2ZSBtb2RlIGFuZCBqdXN0IG91dHB1dCB0aGUgY29tbWFuZCByZXN1bHQuXCIsXG4gICAgZGVmYXVsdFZhbHVlOiB0cnVlLFxuICB9KSxcbiAgXCJmb3JjZS1idWlsZFwiOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7IGhlbHA6IFwiRm9yY2UgcmVidWlsZCBvZiBtb2R1bGUgYmVmb3JlIHJ1bm5pbmcuXCIgfSksXG59XG5cbnR5cGUgQXJncyA9IHR5cGVvZiBydW5BcmdzXG50eXBlIE9wdHMgPSB0eXBlb2YgcnVuT3B0c1xuXG5leHBvcnQgY2xhc3MgUnVuTW9kdWxlQ29tbWFuZCBleHRlbmRzIENvbW1hbmQ8QXJncywgT3B0cz4ge1xuICBuYW1lID0gXCJtb2R1bGVcIlxuICBhbGlhcyA9IFwibVwiXG4gIGhlbHAgPSBcIlJ1biBhbiBhZC1ob2MgaW5zdGFuY2Ugb2YgYSBtb2R1bGUuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBUaGlzIGlzIHVzZWZ1bCBmb3IgZGVidWdnaW5nIG9yIGFkLWhvYyBleHBlcmltZW50YXRpb24gd2l0aCBtb2R1bGVzLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIHJ1biBtb2R1bGUgbXktY29udGFpbmVyICAgICAgICAgICAjIHJ1biBhbiBhZC1ob2MgaW5zdGFuY2Ugb2YgYSBteS1jb250YWluZXIgY29udGFpbmVyIGFuZCBhdHRhY2ggdG8gaXRcbiAgICAgICAgZ2FyZGVuIHJ1biBtb2R1bGUgbXktY29udGFpbmVyIC9iaW4vc2ggICAjIHJ1biBhbiBpbnRlcmFjdGl2ZSBzaGVsbCBpbiBhIG5ldyBteS1jb250YWluZXIgY29udGFpbmVyXG4gICAgICAgIGdhcmRlbiBydW4gbW9kdWxlIG15LWNvbnRhaW5lciAtLWk9ZmFsc2UgL3NvbWUvc2NyaXB0ICAjIGV4ZWN1dGUgYSBzY3JpcHQgaW4gbXktY29udGFpbmVyIGFuZCByZXR1cm4gdGhlIG91dHB1dFxuICBgXG5cbiAgYXJndW1lbnRzID0gcnVuQXJnc1xuICBvcHRpb25zID0gcnVuT3B0c1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFJ1blJlc3VsdD4+IHtcbiAgICBjb25zdCBtb2R1bGVOYW1lID0gYXJncy5tb2R1bGVcbiAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlKG1vZHVsZU5hbWUpXG5cbiAgICBjb25zdCBtc2cgPSBhcmdzLmNvbW1hbmRcbiAgICAgID8gYFJ1bm5pbmcgY29tbWFuZCAke2NoYWxrLndoaXRlKGFyZ3MuY29tbWFuZC5qb2luKFwiIFwiKSl9IGluIG1vZHVsZSAke2NoYWxrLndoaXRlKG1vZHVsZU5hbWUpfWBcbiAgICAgIDogYFJ1bm5pbmcgbW9kdWxlICR7Y2hhbGsud2hpdGUobW9kdWxlTmFtZSl9YFxuXG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoe1xuICAgICAgZW1vamk6IFwicnVubmVyXCIsXG4gICAgICBjb21tYW5kOiBtc2csXG4gICAgfSlcblxuICAgIGF3YWl0IGdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7fSlcblxuICAgIGNvbnN0IGJ1aWxkVGFzayA9IG5ldyBCdWlsZFRhc2soeyBnYXJkZW4sIG1vZHVsZSwgZm9yY2U6IG9wdHNbXCJmb3JjZS1idWlsZFwiXSB9KVxuICAgIGF3YWl0IGdhcmRlbi5hZGRUYXNrKGJ1aWxkVGFzaylcbiAgICBhd2FpdCBnYXJkZW4ucHJvY2Vzc1Rhc2tzKClcblxuICAgIGNvbnN0IGNvbW1hbmQgPSBhcmdzLmNvbW1hbmQgfHwgW11cblxuICAgIC8vIGNvbWJpbmUgYWxsIGRlcGVuZGVuY2llcyBmb3IgYWxsIHNlcnZpY2VzIGluIHRoZSBtb2R1bGUsIHRvIGJlIHN1cmUgd2UgaGF2ZSBhbGwgdGhlIGNvbnRleHQgd2UgbmVlZFxuICAgIGNvbnN0IGRlcE5hbWVzID0gdW5pcShmbGF0dGVuKG1vZHVsZS5zZXJ2aWNlQ29uZmlncy5tYXAocyA9PiBzLmRlcGVuZGVuY2llcykpKVxuICAgIGNvbnN0IGRlcHMgPSBhd2FpdCBnYXJkZW4uZ2V0U2VydmljZXMoZGVwTmFtZXMpXG5cbiAgICBjb25zdCBydW50aW1lQ29udGV4dCA9IGF3YWl0IHByZXBhcmVSdW50aW1lQ29udGV4dChnYXJkZW4sIG1vZHVsZSwgZGVwcylcblxuICAgIHByaW50UnVudGltZUNvbnRleHQoZ2FyZGVuLCBydW50aW1lQ29udGV4dClcblxuICAgIGdhcmRlbi5sb2cuaW5mbyhcIlwiKVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2FyZGVuLmFjdGlvbnMucnVuTW9kdWxlKHtcbiAgICAgIG1vZHVsZSxcbiAgICAgIGNvbW1hbmQsXG4gICAgICBydW50aW1lQ29udGV4dCxcbiAgICAgIHNpbGVudDogZmFsc2UsXG4gICAgICBpbnRlcmFjdGl2ZTogb3B0cy5pbnRlcmFjdGl2ZSxcbiAgICB9KVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/run/run.d.ts b/garden-service/build/commands/run/run.d.ts new file mode 100644 index 00000000000..2b6b62bdd21 --- /dev/null +++ b/garden-service/build/commands/run/run.d.ts @@ -0,0 +1,15 @@ +import { RuntimeContext } from "../../types/service"; +import { Command } from "../base"; +import { RunModuleCommand } from "./module"; +import { RunServiceCommand } from "./service"; +import { RunTestCommand } from "./test"; +import { Garden } from "../../garden"; +export declare class RunCommand extends Command { + name: string; + alias: string; + help: string; + subCommands: (typeof RunModuleCommand | typeof RunServiceCommand | typeof RunTestCommand)[]; + action(): Promise<{}>; +} +export declare function printRuntimeContext(garden: Garden, runtimeContext: RuntimeContext): void; +//# sourceMappingURL=run.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/run/run.js b/garden-service/build/commands/run/run.js new file mode 100644 index 00000000000..6e0307f6c8b --- /dev/null +++ b/garden-service/build/commands/run/run.js @@ -0,0 +1,51 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const js_yaml_1 = require("js-yaml"); +const util_1 = require("../../util/util"); +const base_1 = require("../base"); +const module_1 = require("./module"); +const service_1 = require("./service"); +const test_1 = require("./test"); +class RunCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "run"; + this.alias = "r"; + this.help = "Run ad-hoc instances of your modules, services and tests"; + this.subCommands = [ + module_1.RunModuleCommand, + service_1.RunServiceCommand, + test_1.RunTestCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.RunCommand = RunCommand; +function printRuntimeContext(garden, runtimeContext) { + garden.log.verbose("-----------------------------------\n"); + garden.log.verbose("Environment variables:"); + garden.log.verbose(util_1.highlightYaml(js_yaml_1.safeDump(runtimeContext.envVars))); + garden.log.verbose("Dependencies:"); + garden.log.verbose(util_1.highlightYaml(js_yaml_1.safeDump(runtimeContext.dependencies))); + garden.log.verbose("-----------------------------------\n"); +} +exports.printRuntimeContext = printRuntimeContext; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3J1bi9ydW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILHFDQUFrQztBQUVsQywwQ0FBK0M7QUFDL0Msa0NBQWlDO0FBQ2pDLHFDQUEyQztBQUMzQyx1Q0FBNkM7QUFDN0MsaUNBQXVDO0FBR3ZDLE1BQWEsVUFBVyxTQUFRLGNBQU87SUFBdkM7O1FBQ0UsU0FBSSxHQUFHLEtBQUssQ0FBQTtRQUNaLFVBQUssR0FBRyxHQUFHLENBQUE7UUFDWCxTQUFJLEdBQUcsMERBQTBELENBQUE7UUFFakUsZ0JBQVcsR0FBRztZQUNaLHlCQUFnQjtZQUNoQiwyQkFBaUI7WUFDakIscUJBQWM7U0FDZixDQUFBO0lBR0gsQ0FBQztJQURPLE1BQU07OERBQUssT0FBTyxFQUFFLENBQUEsQ0FBQyxDQUFDO0tBQUE7Q0FDN0I7QUFaRCxnQ0FZQztBQUVELFNBQWdCLG1CQUFtQixDQUFDLE1BQWMsRUFBRSxjQUE4QjtJQUNoRixNQUFNLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyx1Q0FBdUMsQ0FBQyxDQUFBO0lBQzNELE1BQU0sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLHdCQUF3QixDQUFDLENBQUE7SUFDNUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsb0JBQWEsQ0FBQyxrQkFBUSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDbkUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsZUFBZSxDQUFDLENBQUE7SUFDbkMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsb0JBQWEsQ0FBQyxrQkFBUSxDQUFDLGNBQWMsQ0FBQyxZQUFZLENBQUMsQ0FBQyxDQUFDLENBQUE7SUFDeEUsTUFBTSxDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsdUNBQXVDLENBQUMsQ0FBQTtBQUM3RCxDQUFDO0FBUEQsa0RBT0MiLCJmaWxlIjoiY29tbWFuZHMvcnVuL3J1bi5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBzYWZlRHVtcCB9IGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCB7IFJ1bnRpbWVDb250ZXh0IH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHsgaGlnaGxpZ2h0WWFtbCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgQ29tbWFuZCB9IGZyb20gXCIuLi9iYXNlXCJcbmltcG9ydCB7IFJ1bk1vZHVsZUNvbW1hbmQgfSBmcm9tIFwiLi9tb2R1bGVcIlxuaW1wb3J0IHsgUnVuU2VydmljZUNvbW1hbmQgfSBmcm9tIFwiLi9zZXJ2aWNlXCJcbmltcG9ydCB7IFJ1blRlc3RDb21tYW5kIH0gZnJvbSBcIi4vdGVzdFwiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vLi4vZ2FyZGVuXCJcblxuZXhwb3J0IGNsYXNzIFJ1bkNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwicnVuXCJcbiAgYWxpYXMgPSBcInJcIlxuICBoZWxwID0gXCJSdW4gYWQtaG9jIGluc3RhbmNlcyBvZiB5b3VyIG1vZHVsZXMsIHNlcnZpY2VzIGFuZCB0ZXN0c1wiXG5cbiAgc3ViQ29tbWFuZHMgPSBbXG4gICAgUnVuTW9kdWxlQ29tbWFuZCxcbiAgICBSdW5TZXJ2aWNlQ29tbWFuZCxcbiAgICBSdW5UZXN0Q29tbWFuZCxcbiAgXVxuXG4gIGFzeW5jIGFjdGlvbigpIHsgcmV0dXJuIHt9IH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHByaW50UnVudGltZUNvbnRleHQoZ2FyZGVuOiBHYXJkZW4sIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dCkge1xuICBnYXJkZW4ubG9nLnZlcmJvc2UoXCItLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLVxcblwiKVxuICBnYXJkZW4ubG9nLnZlcmJvc2UoXCJFbnZpcm9ubWVudCB2YXJpYWJsZXM6XCIpXG4gIGdhcmRlbi5sb2cudmVyYm9zZShoaWdobGlnaHRZYW1sKHNhZmVEdW1wKHJ1bnRpbWVDb250ZXh0LmVudlZhcnMpKSlcbiAgZ2FyZGVuLmxvZy52ZXJib3NlKFwiRGVwZW5kZW5jaWVzOlwiKVxuICBnYXJkZW4ubG9nLnZlcmJvc2UoaGlnaGxpZ2h0WWFtbChzYWZlRHVtcChydW50aW1lQ29udGV4dC5kZXBlbmRlbmNpZXMpKSlcbiAgZ2FyZGVuLmxvZy52ZXJib3NlKFwiLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cXG5cIilcbn1cbiJdfQ== diff --git a/garden-service/build/commands/run/service.d.ts b/garden-service/build/commands/run/service.d.ts new file mode 100644 index 00000000000..6858913a3db --- /dev/null +++ b/garden-service/build/commands/run/service.d.ts @@ -0,0 +1,25 @@ +import { RunResult } from "../../types/plugin/outputs"; +import { BooleanParameter, Command, CommandParams, CommandResult, StringParameter } from "../base"; +declare const runArgs: { + service: StringParameter; +}; +declare const runOpts: { + "force-build": BooleanParameter; +}; +declare type Args = typeof runArgs; +declare type Opts = typeof runOpts; +export declare class RunServiceCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + arguments: { + service: StringParameter; + }; + options: { + "force-build": BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=service.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/run/service.js b/garden-service/build/commands/run/service.js new file mode 100644 index 00000000000..85c51a9ab45 --- /dev/null +++ b/garden-service/build/commands/run/service.js @@ -0,0 +1,72 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const build_1 = require("../../tasks/build"); +const base_1 = require("../base"); +const run_1 = require("./run"); +const dedent = require("dedent"); +const service_1 = require("../../types/service"); +const runArgs = { + service: new base_1.StringParameter({ + help: "The service to run", + required: true, + }), +}; +const runOpts = { + "force-build": new base_1.BooleanParameter({ help: "Force rebuild of module" }), +}; +class RunServiceCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "service"; + this.alias = "s"; + this.help = "Run an ad-hoc instance of the specified service"; + this.description = dedent ` + This can be useful for debugging or ad-hoc experimentation with services. + + Examples: + + garden run service my-service # run an ad-hoc instance of a my-service and attach to it + `; + this.arguments = runArgs; + this.options = runOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const serviceName = args.service; + const service = yield garden.getService(serviceName); + const module = service.module; + garden.log.header({ + emoji: "runner", + command: `Running service ${chalk_1.default.cyan(serviceName)} in module ${chalk_1.default.cyan(module.name)}`, + }); + yield garden.actions.prepareEnvironment({}); + const buildTask = new build_1.BuildTask({ garden, module, force: opts["force-build"] }); + yield garden.addTask(buildTask); + yield garden.processTasks(); + const dependencies = yield garden.getServices(module.serviceDependencyNames); + const runtimeContext = yield service_1.prepareRuntimeContext(garden, module, dependencies); + run_1.printRuntimeContext(garden, runtimeContext); + const result = yield garden.actions.runService({ service, runtimeContext, silent: false, interactive: true }); + return { result }; + }); + } +} +exports.RunServiceCommand = RunServiceCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3J1bi9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxpQ0FBeUI7QUFDekIsNkNBQTZDO0FBRTdDLGtDQU1nQjtBQUNoQiwrQkFBMkM7QUFDM0MsaUNBQWlDO0FBQ2pDLGlEQUEyRDtBQUUzRCxNQUFNLE9BQU8sR0FBRztJQUNkLE9BQU8sRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDM0IsSUFBSSxFQUFFLG9CQUFvQjtRQUMxQixRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7Q0FDSCxDQUFBO0FBRUQsTUFBTSxPQUFPLEdBQUc7SUFDZCxhQUFhLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQyxFQUFFLElBQUksRUFBRSx5QkFBeUIsRUFBRSxDQUFDO0NBQ3pFLENBQUE7QUFLRCxNQUFhLGlCQUFrQixTQUFRLGNBQW1CO0lBQTFEOztRQUNFLFNBQUksR0FBRyxTQUFTLENBQUE7UUFDaEIsVUFBSyxHQUFHLEdBQUcsQ0FBQTtRQUNYLFNBQUksR0FBRyxpREFBaUQsQ0FBQTtRQUV4RCxnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7O0dBTW5CLENBQUE7UUFFRCxjQUFTLEdBQUcsT0FBTyxDQUFBO1FBQ25CLFlBQU8sR0FBRyxPQUFPLENBQUE7SUEyQm5CLENBQUM7SUF6Qk8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQTZCOztZQUM1RCxNQUFNLFdBQVcsR0FBRyxJQUFJLENBQUMsT0FBTyxDQUFBO1lBQ2hDLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQTtZQUNwRCxNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsTUFBTSxDQUFBO1lBRTdCLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDO2dCQUNoQixLQUFLLEVBQUUsUUFBUTtnQkFDZixPQUFPLEVBQUUsbUJBQW1CLGVBQUssQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLGNBQWMsZUFBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUU7YUFDM0YsQ0FBQyxDQUFBO1lBRUYsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsQ0FBQyxDQUFBO1lBRTNDLE1BQU0sU0FBUyxHQUFHLElBQUksaUJBQVMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLENBQUE7WUFDL0UsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxDQUFBO1lBQy9CLE1BQU0sTUFBTSxDQUFDLFlBQVksRUFBRSxDQUFBO1lBRTNCLE1BQU0sWUFBWSxHQUFHLE1BQU0sTUFBTSxDQUFDLFdBQVcsQ0FBQyxNQUFNLENBQUMsc0JBQXNCLENBQUMsQ0FBQTtZQUM1RSxNQUFNLGNBQWMsR0FBRyxNQUFNLCtCQUFxQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFFaEYseUJBQW1CLENBQUMsTUFBTSxFQUFFLGNBQWMsQ0FBQyxDQUFBO1lBRTNDLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxVQUFVLENBQUMsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7WUFFN0csT0FBTyxFQUFFLE1BQU0sRUFBRSxDQUFBO1FBQ25CLENBQUM7S0FBQTtDQUNGO0FBekNELDhDQXlDQyIsImZpbGUiOiJjb21tYW5kcy9ydW4vc2VydmljZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcbmltcG9ydCB7IEJ1aWxkVGFzayB9IGZyb20gXCIuLi8uLi90YXNrcy9idWlsZFwiXG5pbXBvcnQgeyBSdW5SZXN1bHQgfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IHtcbiAgQm9vbGVhblBhcmFtZXRlcixcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgU3RyaW5nUGFyYW1ldGVyLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyBwcmludFJ1bnRpbWVDb250ZXh0IH0gZnJvbSBcIi4vcnVuXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgeyBwcmVwYXJlUnVudGltZUNvbnRleHQgfSBmcm9tIFwiLi4vLi4vdHlwZXMvc2VydmljZVwiXG5cbmNvbnN0IHJ1bkFyZ3MgPSB7XG4gIHNlcnZpY2U6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIHNlcnZpY2UgdG8gcnVuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG5jb25zdCBydW5PcHRzID0ge1xuICBcImZvcmNlLWJ1aWxkXCI6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJGb3JjZSByZWJ1aWxkIG9mIG1vZHVsZVwiIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgcnVuQXJnc1xudHlwZSBPcHRzID0gdHlwZW9mIHJ1bk9wdHNcblxuZXhwb3J0IGNsYXNzIFJ1blNlcnZpY2VDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzLCBPcHRzPiB7XG4gIG5hbWUgPSBcInNlcnZpY2VcIlxuICBhbGlhcyA9IFwic1wiXG4gIGhlbHAgPSBcIlJ1biBhbiBhZC1ob2MgaW5zdGFuY2Ugb2YgdGhlIHNwZWNpZmllZCBzZXJ2aWNlXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBUaGlzIGNhbiBiZSB1c2VmdWwgZm9yIGRlYnVnZ2luZyBvciBhZC1ob2MgZXhwZXJpbWVudGF0aW9uIHdpdGggc2VydmljZXMuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gcnVuIHNlcnZpY2UgbXktc2VydmljZSAgICMgcnVuIGFuIGFkLWhvYyBpbnN0YW5jZSBvZiBhIG15LXNlcnZpY2UgYW5kIGF0dGFjaCB0byBpdFxuICBgXG5cbiAgYXJndW1lbnRzID0gcnVuQXJnc1xuICBvcHRpb25zID0gcnVuT3B0c1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFJ1blJlc3VsdD4+IHtcbiAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IGFyZ3Muc2VydmljZVxuICAgIGNvbnN0IHNlcnZpY2UgPSBhd2FpdCBnYXJkZW4uZ2V0U2VydmljZShzZXJ2aWNlTmFtZSlcbiAgICBjb25zdCBtb2R1bGUgPSBzZXJ2aWNlLm1vZHVsZVxuXG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoe1xuICAgICAgZW1vamk6IFwicnVubmVyXCIsXG4gICAgICBjb21tYW5kOiBgUnVubmluZyBzZXJ2aWNlICR7Y2hhbGsuY3lhbihzZXJ2aWNlTmFtZSl9IGluIG1vZHVsZSAke2NoYWxrLmN5YW4obW9kdWxlLm5hbWUpfWAsXG4gICAgfSlcblxuICAgIGF3YWl0IGdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7fSlcblxuICAgIGNvbnN0IGJ1aWxkVGFzayA9IG5ldyBCdWlsZFRhc2soeyBnYXJkZW4sIG1vZHVsZSwgZm9yY2U6IG9wdHNbXCJmb3JjZS1idWlsZFwiXSB9KVxuICAgIGF3YWl0IGdhcmRlbi5hZGRUYXNrKGJ1aWxkVGFzaylcbiAgICBhd2FpdCBnYXJkZW4ucHJvY2Vzc1Rhc2tzKClcblxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IGF3YWl0IGdhcmRlbi5nZXRTZXJ2aWNlcyhtb2R1bGUuc2VydmljZURlcGVuZGVuY3lOYW1lcylcbiAgICBjb25zdCBydW50aW1lQ29udGV4dCA9IGF3YWl0IHByZXBhcmVSdW50aW1lQ29udGV4dChnYXJkZW4sIG1vZHVsZSwgZGVwZW5kZW5jaWVzKVxuXG4gICAgcHJpbnRSdW50aW1lQ29udGV4dChnYXJkZW4sIHJ1bnRpbWVDb250ZXh0KVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2FyZGVuLmFjdGlvbnMucnVuU2VydmljZSh7IHNlcnZpY2UsIHJ1bnRpbWVDb250ZXh0LCBzaWxlbnQ6IGZhbHNlLCBpbnRlcmFjdGl2ZTogdHJ1ZSB9KVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/run/test.d.ts b/garden-service/build/commands/run/test.d.ts new file mode 100644 index 00000000000..50d309f237b --- /dev/null +++ b/garden-service/build/commands/run/test.d.ts @@ -0,0 +1,29 @@ +import { RunResult } from "../../types/plugin/outputs"; +import { BooleanParameter, Command, CommandParams, CommandResult, StringParameter } from "../base"; +declare const runArgs: { + module: StringParameter; + test: StringParameter; +}; +declare const runOpts: { + interactive: BooleanParameter; + "force-build": BooleanParameter; +}; +declare type Args = typeof runArgs; +declare type Opts = typeof runOpts; +export declare class RunTestCommand extends Command { + name: string; + alias: string; + help: string; + description: string; + arguments: { + module: StringParameter; + test: StringParameter; + }; + options: { + interactive: BooleanParameter; + "force-build": BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=test.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/run/test.js b/garden-service/build/commands/run/test.js new file mode 100644 index 00000000000..5c6e8dfe74d --- /dev/null +++ b/garden-service/build/commands/run/test.js @@ -0,0 +1,98 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const exceptions_1 = require("../../exceptions"); +const build_1 = require("../../tasks/build"); +const util_1 = require("../../util/util"); +const base_1 = require("../base"); +const run_1 = require("./run"); +const dedent = require("dedent"); +const service_1 = require("../../types/service"); +const runArgs = { + module: new base_1.StringParameter({ + help: "The name of the module to run.", + required: true, + }), + test: new base_1.StringParameter({ + help: "The name of the test to run in the module.", + required: true, + }), +}; +const runOpts = { + interactive: new base_1.BooleanParameter({ + help: "Set to false to skip interactive mode and just output the command result.", + defaultValue: true, + }), + "force-build": new base_1.BooleanParameter({ help: "Force rebuild of module before running." }), +}; +class RunTestCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "test"; + this.alias = "t"; + this.help = "Run the specified module test."; + this.description = dedent ` + This can be useful for debugging tests, particularly integration/end-to-end tests. + + Examples: + + garden run test my-module integ # run the test named 'integ' in my-module + garden run test my-module integ --i=false # do not attach to the test run, just output results when completed + `; + this.arguments = runArgs; + this.options = runOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const moduleName = args.module; + const testName = args.test; + const module = yield garden.getModule(moduleName); + const testConfig = util_1.findByName(module.testConfigs, testName); + if (!testConfig) { + throw new exceptions_1.ParameterError(`Could not find test "${testName}" in module ${moduleName}`, { + moduleName, + testName, + availableTests: util_1.getNames(module.testConfigs), + }); + } + garden.log.header({ + emoji: "runner", + command: `Running test ${chalk_1.default.cyan(testName)} in module ${chalk_1.default.cyan(moduleName)}`, + }); + yield garden.actions.prepareEnvironment({}); + const buildTask = new build_1.BuildTask({ garden, module, force: opts["force-build"] }); + yield garden.addTask(buildTask); + yield garden.processTasks(); + const interactive = opts.interactive; + const deps = yield garden.getServices(testConfig.dependencies); + const runtimeContext = yield service_1.prepareRuntimeContext(garden, module, deps); + run_1.printRuntimeContext(garden, runtimeContext); + const result = yield garden.actions.testModule({ + module, + interactive, + runtimeContext, + silent: false, + testConfig, + }); + return { result }; + }); + } +} +exports.RunTestCommand = RunTestCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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TUFBTSxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUV4RSx5QkFBbUIsQ0FBQyxNQUFNLEVBQUUsY0FBYyxDQUFDLENBQUE7WUFFM0MsTUFBTSxNQUFNLEdBQUcsTUFBTSxNQUFNLENBQUMsT0FBTyxDQUFDLFVBQVUsQ0FBQztnQkFDN0MsTUFBTTtnQkFDTixXQUFXO2dCQUNYLGNBQWM7Z0JBQ2QsTUFBTSxFQUFFLEtBQUs7Z0JBQ2IsVUFBVTthQUNYLENBQUMsQ0FBQTtZQUVGLE9BQU8sRUFBRSxNQUFNLEVBQUUsQ0FBQTtRQUNuQixDQUFDO0tBQUE7Q0FDRjtBQTNERCx3Q0EyREMiLCJmaWxlIjoiY29tbWFuZHMvcnVuL3Rlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5pbXBvcnQgeyBQYXJhbWV0ZXJFcnJvciB9IGZyb20gXCIuLi8uLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IEJ1aWxkVGFzayB9IGZyb20gXCIuLi8uLi90YXNrcy9idWlsZFwiXG5pbXBvcnQgeyBSdW5SZXN1bHQgfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IHtcbiAgZmluZEJ5TmFtZSxcbiAgZ2V0TmFtZXMsXG59IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHtcbiAgQm9vbGVhblBhcmFtZXRlcixcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgU3RyaW5nUGFyYW1ldGVyLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyBwcmludFJ1bnRpbWVDb250ZXh0IH0gZnJvbSBcIi4vcnVuXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgeyBwcmVwYXJlUnVudGltZUNvbnRleHQgfSBmcm9tIFwiLi4vLi4vdHlwZXMvc2VydmljZVwiXG5cbmNvbnN0IHJ1bkFyZ3MgPSB7XG4gIG1vZHVsZTogbmV3IFN0cmluZ1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJUaGUgbmFtZSBvZiB0aGUgbW9kdWxlIHRvIHJ1bi5cIixcbiAgICByZXF1aXJlZDogdHJ1ZSxcbiAgfSksXG4gIHRlc3Q6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHRlc3QgdG8gcnVuIGluIHRoZSBtb2R1bGUuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG5jb25zdCBydW5PcHRzID0ge1xuICBpbnRlcmFjdGl2ZTogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiU2V0IHRvIGZhbHNlIHRvIHNraXAgaW50ZXJhY3RpdmUgbW9kZSBhbmQganVzdCBvdXRwdXQgdGhlIGNvbW1hbmQgcmVzdWx0LlwiLFxuICAgIGRlZmF1bHRWYWx1ZTogdHJ1ZSxcbiAgfSksXG4gIFwiZm9yY2UtYnVpbGRcIjogbmV3IEJvb2xlYW5QYXJhbWV0ZXIoeyBoZWxwOiBcIkZvcmNlIHJlYnVpbGQgb2YgbW9kdWxlIGJlZm9yZSBydW5uaW5nLlwiIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgcnVuQXJnc1xudHlwZSBPcHRzID0gdHlwZW9mIHJ1bk9wdHNcblxuZXhwb3J0IGNsYXNzIFJ1blRlc3RDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzLCBPcHRzPiB7XG4gIG5hbWUgPSBcInRlc3RcIlxuICBhbGlhcyA9IFwidFwiXG4gIGhlbHAgPSBcIlJ1biB0aGUgc3BlY2lmaWVkIG1vZHVsZSB0ZXN0LlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgVGhpcyBjYW4gYmUgdXNlZnVsIGZvciBkZWJ1Z2dpbmcgdGVzdHMsIHBhcnRpY3VsYXJseSBpbnRlZ3JhdGlvbi9lbmQtdG8tZW5kIHRlc3RzLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIHJ1biB0ZXN0IG15LW1vZHVsZSBpbnRlZyAgICAgICAgICAgICMgcnVuIHRoZSB0ZXN0IG5hbWVkICdpbnRlZycgaW4gbXktbW9kdWxlXG4gICAgICAgIGdhcmRlbiBydW4gdGVzdCBteS1tb2R1bGUgaW50ZWcgLS1pPWZhbHNlICAjIGRvIG5vdCBhdHRhY2ggdG8gdGhlIHRlc3QgcnVuLCBqdXN0IG91dHB1dCByZXN1bHRzIHdoZW4gY29tcGxldGVkXG4gIGBcblxuICBhcmd1bWVudHMgPSBydW5BcmdzXG4gIG9wdGlvbnMgPSBydW5PcHRzXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuLCBhcmdzLCBvcHRzIH06IENvbW1hbmRQYXJhbXM8QXJncywgT3B0cz4pOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8UnVuUmVzdWx0Pj4ge1xuICAgIGNvbnN0IG1vZHVsZU5hbWUgPSBhcmdzLm1vZHVsZVxuICAgIGNvbnN0IHRlc3ROYW1lID0gYXJncy50ZXN0XG4gICAgY29uc3QgbW9kdWxlID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZShtb2R1bGVOYW1lKVxuXG4gICAgY29uc3QgdGVzdENvbmZpZyA9IGZpbmRCeU5hbWUobW9kdWxlLnRlc3RDb25maWdzLCB0ZXN0TmFtZSlcblxuICAgIGlmICghdGVzdENvbmZpZykge1xuICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBDb3VsZCBub3QgZmluZCB0ZXN0IFwiJHt0ZXN0TmFtZX1cIiBpbiBtb2R1bGUgJHttb2R1bGVOYW1lfWAsIHtcbiAgICAgICAgbW9kdWxlTmFtZSxcbiAgICAgICAgdGVzdE5hbWUsXG4gICAgICAgIGF2YWlsYWJsZVRlc3RzOiBnZXROYW1lcyhtb2R1bGUudGVzdENvbmZpZ3MpLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7XG4gICAgICBlbW9qaTogXCJydW5uZXJcIixcbiAgICAgIGNvbW1hbmQ6IGBSdW5uaW5nIHRlc3QgJHtjaGFsay5jeWFuKHRlc3ROYW1lKX0gaW4gbW9kdWxlICR7Y2hhbGsuY3lhbihtb2R1bGVOYW1lKX1gLFxuICAgIH0pXG5cbiAgICBhd2FpdCBnYXJkZW4uYWN0aW9ucy5wcmVwYXJlRW52aXJvbm1lbnQoe30pXG5cbiAgICBjb25zdCBidWlsZFRhc2sgPSBuZXcgQnVpbGRUYXNrKHsgZ2FyZGVuLCBtb2R1bGUsIGZvcmNlOiBvcHRzW1wiZm9yY2UtYnVpbGRcIl0gfSlcbiAgICBhd2FpdCBnYXJkZW4uYWRkVGFzayhidWlsZFRhc2spXG4gICAgYXdhaXQgZ2FyZGVuLnByb2Nlc3NUYXNrcygpXG5cbiAgICBjb25zdCBpbnRlcmFjdGl2ZSA9IG9wdHMuaW50ZXJhY3RpdmVcbiAgICBjb25zdCBkZXBzID0gYXdhaXQgZ2FyZGVuLmdldFNlcnZpY2VzKHRlc3RDb25maWcuZGVwZW5kZW5jaWVzKVxuICAgIGNvbnN0IHJ1bnRpbWVDb250ZXh0ID0gYXdhaXQgcHJlcGFyZVJ1bnRpbWVDb250ZXh0KGdhcmRlbiwgbW9kdWxlLCBkZXBzKVxuXG4gICAgcHJpbnRSdW50aW1lQ29udGV4dChnYXJkZW4sIHJ1bnRpbWVDb250ZXh0KVxuXG4gICAgY29uc3QgcmVzdWx0ID0gYXdhaXQgZ2FyZGVuLmFjdGlvbnMudGVzdE1vZHVsZSh7XG4gICAgICBtb2R1bGUsXG4gICAgICBpbnRlcmFjdGl2ZSxcbiAgICAgIHJ1bnRpbWVDb250ZXh0LFxuICAgICAgc2lsZW50OiBmYWxzZSxcbiAgICAgIHRlc3RDb25maWcsXG4gICAgfSlcblxuICAgIHJldHVybiB7IHJlc3VsdCB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/scan.d.ts b/garden-service/build/commands/scan.d.ts new file mode 100644 index 00000000000..ab19af30eaa --- /dev/null +++ b/garden-service/build/commands/scan.d.ts @@ -0,0 +1,8 @@ +import { DeepPrimitiveMap } from "../config/common"; +import { Command, CommandParams, CommandResult } from "./base"; +export declare class ScanCommand extends Command { + name: string; + help: string; + action({ garden }: CommandParams): Promise>; +} +//# sourceMappingURL=scan.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/scan.js b/garden-service/build/commands/scan.js new file mode 100644 index 00000000000..0745a5ecbb6 --- /dev/null +++ b/garden-service/build/commands/scan.js @@ -0,0 +1,49 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const js_yaml_1 = require("js-yaml"); +const util_1 = require("../util/util"); +const base_1 = require("./base"); +const lodash_1 = require("lodash"); +class ScanCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "scan"; + this.help = "Scans your project and outputs an overview of all modules."; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + const modules = (yield garden.getModules()) + .map(m => { + m.services.forEach(s => delete s.module); + return lodash_1.omit(m, ["_ConfigType", "cacheContext", "serviceConfigs", "serviceNames"]); + }); + const output = { modules }; + const shortOutput = { + modules: modules.map(m => { + m.services.map(s => delete s.spec); + return lodash_1.omit(m, ["spec"]); + }), + }; + garden.log.info(util_1.highlightYaml(js_yaml_1.safeDump(shortOutput, { noRefs: true, skipInvalid: true, sortKeys: true }))); + return { result: output }; + }); + } +} +exports.ScanCommand = ScanCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3NjYW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILHFDQUFrQztBQUVsQyx1Q0FBNEM7QUFDNUMsaUNBSWU7QUFDZixtQ0FBNkI7QUFFN0IsTUFBYSxXQUFZLFNBQVEsY0FBTztJQUF4Qzs7UUFDRSxTQUFJLEdBQUcsTUFBTSxDQUFBO1FBQ2IsU0FBSSxHQUFHLDREQUE0RCxDQUFBO0lBc0JyRSxDQUFDO0lBcEJPLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBaUI7O1lBQ3BDLE1BQU0sT0FBTyxHQUFHLENBQUMsTUFBTSxNQUFNLENBQUMsVUFBVSxFQUFFLENBQUM7aUJBQ3hDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtnQkFDUCxDQUFDLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUN4QyxPQUFPLGFBQUksQ0FBQyxDQUFDLEVBQUUsQ0FBQyxhQUFhLEVBQUUsY0FBYyxFQUFFLGdCQUFnQixFQUFFLGNBQWMsQ0FBQyxDQUFDLENBQUE7WUFDbkYsQ0FBQyxDQUFDLENBQUE7WUFFSixNQUFNLE1BQU0sR0FBRyxFQUFFLE9BQU8sRUFBRSxDQUFBO1lBRTFCLE1BQU0sV0FBVyxHQUFHO2dCQUNsQixPQUFPLEVBQUUsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTtvQkFDdkIsQ0FBQyxDQUFDLFFBQVMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDbkMsT0FBTyxhQUFJLENBQUMsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQTtnQkFDMUIsQ0FBQyxDQUFDO2FBQ0gsQ0FBQTtZQUVELE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLG9CQUFhLENBQUMsa0JBQVEsQ0FBQyxXQUFXLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxJQUFJLEVBQUUsUUFBUSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1lBRTFHLE9BQU8sRUFBRSxNQUFNLEVBQXlCLE1BQU0sRUFBRSxDQUFBO1FBQ2xELENBQUM7S0FBQTtDQUNGO0FBeEJELGtDQXdCQyIsImZpbGUiOiJjb21tYW5kcy9zY2FuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IHNhZmVEdW1wIH0gZnJvbSBcImpzLXlhbWxcIlxuaW1wb3J0IHsgRGVlcFByaW1pdGl2ZU1hcCB9IGZyb20gXCIuLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IGhpZ2hsaWdodFlhbWwgfSBmcm9tIFwiLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7XG4gIENvbW1hbmQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIENvbW1hbmRSZXN1bHQsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHsgb21pdCB9IGZyb20gXCJsb2Rhc2hcIlxuXG5leHBvcnQgY2xhc3MgU2NhbkNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kIHtcbiAgbmFtZSA9IFwic2NhblwiXG4gIGhlbHAgPSBcIlNjYW5zIHlvdXIgcHJvamVjdCBhbmQgb3V0cHV0cyBhbiBvdmVydmlldyBvZiBhbGwgbW9kdWxlcy5cIlxuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiB9OiBDb21tYW5kUGFyYW1zKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PERlZXBQcmltaXRpdmVNYXA+PiB7XG4gICAgY29uc3QgbW9kdWxlcyA9IChhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlcygpKVxuICAgICAgLm1hcChtID0+IHtcbiAgICAgICAgbS5zZXJ2aWNlcy5mb3JFYWNoKHMgPT4gZGVsZXRlIHMubW9kdWxlKVxuICAgICAgICByZXR1cm4gb21pdChtLCBbXCJfQ29uZmlnVHlwZVwiLCBcImNhY2hlQ29udGV4dFwiLCBcInNlcnZpY2VDb25maWdzXCIsIFwic2VydmljZU5hbWVzXCJdKVxuICAgICAgfSlcblxuICAgIGNvbnN0IG91dHB1dCA9IHsgbW9kdWxlcyB9XG5cbiAgICBjb25zdCBzaG9ydE91dHB1dCA9IHtcbiAgICAgIG1vZHVsZXM6IG1vZHVsZXMubWFwKG0gPT4ge1xuICAgICAgICBtLnNlcnZpY2VzIS5tYXAocyA9PiBkZWxldGUgcy5zcGVjKVxuICAgICAgICByZXR1cm4gb21pdChtLCBbXCJzcGVjXCJdKVxuICAgICAgfSksXG4gICAgfVxuXG4gICAgZ2FyZGVuLmxvZy5pbmZvKGhpZ2hsaWdodFlhbWwoc2FmZUR1bXAoc2hvcnRPdXRwdXQsIHsgbm9SZWZzOiB0cnVlLCBza2lwSW52YWxpZDogdHJ1ZSwgc29ydEtleXM6IHRydWUgfSkpKVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiA8RGVlcFByaW1pdGl2ZU1hcD48YW55Pm91dHB1dCB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/set.d.ts b/garden-service/build/commands/set.d.ts new file mode 100644 index 00000000000..5869ad745b6 --- /dev/null +++ b/garden-service/build/commands/set.d.ts @@ -0,0 +1,27 @@ +import { SetSecretResult } from "../types/plugin/outputs"; +import { Command, CommandResult, CommandParams, StringParameter } from "./base"; +export declare class SetCommand extends Command { + name: string; + help: string; + subCommands: (typeof SetSecretCommand)[]; + action(): Promise<{}>; +} +declare const setSecretArgs: { + provider: StringParameter; + key: StringParameter; + value: StringParameter; +}; +declare type SetArgs = typeof setSecretArgs; +export declare class SetSecretCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + provider: StringParameter; + key: StringParameter; + value: StringParameter; + }; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=set.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/set.js b/garden-service/build/commands/set.js new file mode 100644 index 00000000000..8ac4de3fd9b --- /dev/null +++ b/garden-service/build/commands/set.js @@ -0,0 +1,79 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const dedent = require("dedent"); +class SetCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "set"; + this.help = "Set or modify data, e.g. secrets."; + this.subCommands = [ + SetSecretCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.SetCommand = SetCommand; +const setSecretArgs = { + provider: new base_1.StringParameter({ + help: "The name of the provider to store the secret with.", + required: true, + }), + key: new base_1.StringParameter({ + help: "A unique identifier for the secret.", + required: true, + }), + value: new base_1.StringParameter({ + help: "The value of the secret.", + required: true, + }), +}; +// TODO: allow storing data from files +class SetSecretCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "secret"; + this.help = "Set a secret value for a provider in an environment."; + this.description = dedent ` + These secrets are handled by each provider, and may for example be exposed as environment + variables for services or mounted as files, depending on how the provider is implemented + and configured. + + _Note: The value is currently always stored as a string._ + + Examples: + + garden set secret kubernetes somekey myvalue + garden set secret local-kubernets somekey myvalue + `; + this.arguments = setSecretArgs; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + const key = args.key; + const result = yield garden.actions.setSecret({ pluginName: args.provider, key, value: args.value }); + garden.log.info(`Set config key ${args.key}`); + return { result }; + }); + } +} +exports.SetSecretCommand = SetSecretCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3NldC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBR0gsaUNBS2U7QUFDZixpQ0FBaUM7QUFFakMsTUFBYSxVQUFXLFNBQVEsY0FBTztJQUF2Qzs7UUFDRSxTQUFJLEdBQUcsS0FBSyxDQUFBO1FBQ1osU0FBSSxHQUFHLG1DQUFtQyxDQUFBO1FBRTFDLGdCQUFXLEdBQUc7WUFDWixnQkFBZ0I7U0FDakIsQ0FBQTtJQUdILENBQUM7SUFETyxNQUFNOzhEQUFLLE9BQU8sRUFBRSxDQUFBLENBQUMsQ0FBQztLQUFBO0NBQzdCO0FBVEQsZ0NBU0M7QUFFRCxNQUFNLGFBQWEsR0FBRztJQUNwQixRQUFRLEVBQUUsSUFBSSxzQkFBZSxDQUFDO1FBQzVCLElBQUksRUFBRSxvREFBb0Q7UUFDMUQsUUFBUSxFQUFFLElBQUk7S0FDZixDQUFDO0lBQ0YsR0FBRyxFQUFFLElBQUksc0JBQWUsQ0FBQztRQUN2QixJQUFJLEVBQUUscUNBQXFDO1FBQzNDLFFBQVEsRUFBRSxJQUFJO0tBQ2YsQ0FBQztJQUNGLEtBQUssRUFBRSxJQUFJLHNCQUFlLENBQUM7UUFDekIsSUFBSSxFQUFFLDBCQUEwQjtRQUNoQyxRQUFRLEVBQUUsSUFBSTtLQUNmLENBQUM7Q0FDSCxDQUFBO0FBSUQsc0NBQXNDO0FBRXRDLE1BQWEsZ0JBQWlCLFNBQVEsY0FBNkI7SUFBbkU7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFNBQUksR0FBRyxzREFBc0QsQ0FBQTtRQUU3RCxnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7Ozs7Ozs7R0FXbkIsQ0FBQTtRQUVELGNBQVMsR0FBRyxhQUFhLENBQUE7SUFRM0IsQ0FBQztJQU5PLE1BQU0sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQTBCOztZQUNuRCxNQUFNLEdBQUcsR0FBRyxJQUFJLENBQUMsR0FBRyxDQUFBO1lBQ3BCLE1BQU0sTUFBTSxHQUFHLE1BQU0sTUFBTSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxDQUFDLFFBQVEsRUFBRSxHQUFHLEVBQUUsS0FBSyxFQUFFLElBQUksQ0FBQyxLQUFLLEVBQUUsQ0FBQyxDQUFBO1lBQ3BHLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLGtCQUFrQixJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsQ0FBQTtZQUM3QyxPQUFPLEVBQUUsTUFBTSxFQUFFLENBQUE7UUFDbkIsQ0FBQztLQUFBO0NBQ0Y7QUF6QkQsNENBeUJDIiwiZmlsZSI6ImNvbW1hbmRzL3NldC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBTZXRTZWNyZXRSZXN1bHQgfSBmcm9tIFwiLi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgU3RyaW5nUGFyYW1ldGVyLFxufSBmcm9tIFwiLi9iYXNlXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5cbmV4cG9ydCBjbGFzcyBTZXRDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIG5hbWUgPSBcInNldFwiXG4gIGhlbHAgPSBcIlNldCBvciBtb2RpZnkgZGF0YSwgZS5nLiBzZWNyZXRzLlwiXG5cbiAgc3ViQ29tbWFuZHMgPSBbXG4gICAgU2V0U2VjcmV0Q29tbWFuZCxcbiAgXVxuXG4gIGFzeW5jIGFjdGlvbigpIHsgcmV0dXJuIHt9IH1cbn1cblxuY29uc3Qgc2V0U2VjcmV0QXJncyA9IHtcbiAgcHJvdmlkZXI6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIHRvIHN0b3JlIHRoZSBzZWNyZXQgd2l0aC5cIixcbiAgICByZXF1aXJlZDogdHJ1ZSxcbiAgfSksXG4gIGtleTogbmV3IFN0cmluZ1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGUgc2VjcmV0LlwiLFxuICAgIHJlcXVpcmVkOiB0cnVlLFxuICB9KSxcbiAgdmFsdWU6IG5ldyBTdHJpbmdQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiVGhlIHZhbHVlIG9mIHRoZSBzZWNyZXQuXCIsXG4gICAgcmVxdWlyZWQ6IHRydWUsXG4gIH0pLFxufVxuXG50eXBlIFNldEFyZ3MgPSB0eXBlb2Ygc2V0U2VjcmV0QXJnc1xuXG4vLyBUT0RPOiBhbGxvdyBzdG9yaW5nIGRhdGEgZnJvbSBmaWxlc1xuXG5leHBvcnQgY2xhc3MgU2V0U2VjcmV0Q29tbWFuZCBleHRlbmRzIENvbW1hbmQ8dHlwZW9mIHNldFNlY3JldEFyZ3M+IHtcbiAgbmFtZSA9IFwic2VjcmV0XCJcbiAgaGVscCA9IFwiU2V0IGEgc2VjcmV0IHZhbHVlIGZvciBhIHByb3ZpZGVyIGluIGFuIGVudmlyb25tZW50LlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgVGhlc2Ugc2VjcmV0cyBhcmUgaGFuZGxlZCBieSBlYWNoIHByb3ZpZGVyLCBhbmQgbWF5IGZvciBleGFtcGxlIGJlIGV4cG9zZWQgYXMgZW52aXJvbm1lbnRcbiAgICB2YXJpYWJsZXMgZm9yIHNlcnZpY2VzIG9yIG1vdW50ZWQgYXMgZmlsZXMsIGRlcGVuZGluZyBvbiBob3cgdGhlIHByb3ZpZGVyIGlzIGltcGxlbWVudGVkXG4gICAgYW5kIGNvbmZpZ3VyZWQuXG5cbiAgICBfTm90ZTogVGhlIHZhbHVlIGlzIGN1cnJlbnRseSBhbHdheXMgc3RvcmVkIGFzIGEgc3RyaW5nLl9cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiBzZXQgc2VjcmV0IGt1YmVybmV0ZXMgc29tZWtleSBteXZhbHVlXG4gICAgICAgIGdhcmRlbiBzZXQgc2VjcmV0IGxvY2FsLWt1YmVybmV0cyBzb21la2V5IG15dmFsdWVcbiAgYFxuXG4gIGFyZ3VtZW50cyA9IHNldFNlY3JldEFyZ3NcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4sIGFyZ3MgfTogQ29tbWFuZFBhcmFtczxTZXRBcmdzPik6IFByb21pc2U8Q29tbWFuZFJlc3VsdDxTZXRTZWNyZXRSZXN1bHQ+PiB7XG4gICAgY29uc3Qga2V5ID0gYXJncy5rZXlcbiAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBnYXJkZW4uYWN0aW9ucy5zZXRTZWNyZXQoeyBwbHVnaW5OYW1lOiBhcmdzLnByb3ZpZGVyLCBrZXksIHZhbHVlOiBhcmdzLnZhbHVlIH0pXG4gICAgZ2FyZGVuLmxvZy5pbmZvKGBTZXQgY29uZmlnIGtleSAke2FyZ3Mua2V5fWApXG4gICAgcmV0dXJuIHsgcmVzdWx0IH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/test.d.ts b/garden-service/build/commands/test.d.ts new file mode 100644 index 00000000000..a69727ac4e4 --- /dev/null +++ b/garden-service/build/commands/test.d.ts @@ -0,0 +1,40 @@ +import { BooleanParameter, Command, CommandParams, CommandResult, StringOption, StringsParameter } from "./base"; +import { TaskResults } from "../task-graph"; +import { Module } from "../types/module"; +import { TestTask } from "../tasks/test"; +import { Garden } from "../garden"; +declare const testArgs: { + module: StringsParameter; +}; +declare const testOpts: { + name: StringOption; + force: BooleanParameter; + "force-build": BooleanParameter; + watch: BooleanParameter; +}; +declare type Args = typeof testArgs; +declare type Opts = typeof testOpts; +export declare class TestCommand extends Command { + name: string; + help: string; + description: string; + arguments: { + module: StringsParameter; + }; + options: { + name: StringOption; + force: BooleanParameter; + "force-build": BooleanParameter; + watch: BooleanParameter; + }; + action({ garden, args, opts }: CommandParams): Promise>; +} +export declare function getTestTasks({ garden, module, name, force, forceBuild }: { + garden: Garden; + module: Module; + name?: string; + force?: boolean; + forceBuild?: boolean; +}): Promise; +export {}; +//# sourceMappingURL=test.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/test.js b/garden-service/build/commands/test.js new file mode 100644 index 00000000000..97a65cbe7b7 --- /dev/null +++ b/garden-service/build/commands/test.js @@ -0,0 +1,116 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const lodash_1 = require("lodash"); +const base_1 = require("./base"); +const process_1 = require("../process"); +const test_1 = require("../tasks/test"); +const watch_1 = require("../watch"); +const testArgs = { + module: new base_1.StringsParameter({ + help: "The name of the module(s) to deploy (skip to test all modules). " + + "Use comma as separator to specify multiple modules.", + }), +}; +const testOpts = { + name: new base_1.StringOption({ + help: "Only run tests with the specfied name (e.g. unit or integ).", + alias: "n", + }), + force: new base_1.BooleanParameter({ help: "Force re-test of module(s).", alias: "f" }), + "force-build": new base_1.BooleanParameter({ help: "Force rebuild of module(s)." }), + watch: new base_1.BooleanParameter({ help: "Watch for changes in module(s) and auto-test.", alias: "w" }), +}; +class TestCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "test"; + this.help = "Test all or specified modules."; + this.description = ` + Runs all or specified tests defined in the project. Also builds modules and dependencies, + and deploy service dependencies if needed. + + Optionally stays running and automatically re-runs tests if their module source + (or their dependencies' sources) change. + + Examples: + + garden test # run all tests in the project + garden test my-module # run all tests in the my-module module + garden test -n integ # run all tests with the name 'integ' in the project + garden test --force # force tests to be re-run, even if they're already run successfully + garden test --watch # watch for changes to code + `; + this.arguments = testArgs; + this.options = testOpts; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + const autoReloadDependants = yield watch_1.computeAutoReloadDependants(garden); + let modules; + if (args.module) { + modules = yield watch_1.withDependants(garden, yield garden.getModules(args.module), autoReloadDependants); + } + else { + // All modules are included in this case, so there's no need to compute dependants. + modules = yield garden.getModules(); + } + garden.log.header({ + emoji: "thermometer", + command: `Running tests`, + }); + yield garden.actions.prepareEnvironment({}); + const name = opts.name; + const force = opts.force; + const forceBuild = opts["force-build"]; + const results = yield process_1.processModules({ + garden, + modules, + watch: opts.watch, + handler: (module) => __awaiter(this, void 0, void 0, function* () { return getTestTasks({ garden, module, name, force, forceBuild }); }), + changeHandler: (module) => __awaiter(this, void 0, void 0, function* () { + const modulesToProcess = yield watch_1.withDependants(garden, [module], autoReloadDependants); + return lodash_1.flatten(yield Bluebird.map(modulesToProcess, m => getTestTasks({ garden, module: m, name, force, forceBuild }))); + }), + }); + return base_1.handleTaskResults(garden, "test", results); + }); + } +} +exports.TestCommand = TestCommand; +function getTestTasks({ garden, module, name, force = false, forceBuild = false }) { + return __awaiter(this, void 0, void 0, function* () { + const tasks = []; + for (const test of module.testConfigs) { + if (name && test.name !== name) { + continue; + } + tasks.push(test_1.TestTask.factory({ + garden, + force, + forceBuild, + testConfig: test, + module, + })); + } + return Bluebird.all(tasks); + }); +} +exports.getTestTasks = getTestTasks; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFPLENBQUMsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUMvQixnQkFBZ0IsRUFDaEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxZQUFZLENBQUMsRUFBRSxNQUFNLEVBQUUsTUFBTSxFQUFFLENBQUMsRUFBRSxJQUFJLEVBQUUsS0FBSyxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO2dCQUN2RSxDQUFDLENBQUE7YUFDRixDQUFDLENBQUE7WUFFRixPQUFPLHdCQUFpQixDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDbkQsQ0FBQztLQUFBO0NBQ0Y7QUEzREQsa0NBMkRDO0FBRUQsU0FBc0IsWUFBWSxDQUNoQyxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEtBQUssR0FBRyxLQUFLLEVBQUUsVUFBVSxHQUFHLEtBQUssRUFDaUM7O1FBRTFGLE1BQU0sS0FBSyxHQUF3QixFQUFFLENBQUE7UUFFckMsS0FBSyxNQUFNLElBQUksSUFBSSxNQUFNLENBQUMsV0FBVyxFQUFFO1lBQ3JDLElBQUksSUFBSSxJQUFJLElBQUksQ0FBQyxJQUFJLEtBQUssSUFBSSxFQUFFO2dCQUM5QixTQUFRO2FBQ1Q7WUFDRCxLQUFLLENBQUMsSUFBSSxDQUFDLGVBQVEsQ0FBQyxPQUFPLENBQUM7Z0JBQzFCLE1BQU07Z0JBQ04sS0FBSztnQkFDTCxVQUFVO2dCQUNWLFVBQVUsRUFBRSxJQUFJO2dCQUNoQixNQUFNO2FBQ1AsQ0FBQyxDQUFDLENBQUE7U0FDSjtRQUVELE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxLQUFLLENBQUMsQ0FBQTtJQUM1QixDQUFDO0NBQUE7QUFwQkQsb0NBb0JDIiwiZmlsZSI6ImNvbW1hbmRzL3Rlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7XG4gIEJvb2xlYW5QYXJhbWV0ZXIsXG4gIENvbW1hbmQsXG4gIENvbW1hbmRQYXJhbXMsXG4gIENvbW1hbmRSZXN1bHQsXG4gIGhhbmRsZVRhc2tSZXN1bHRzLFxuICBTdHJpbmdPcHRpb24sXG4gIFN0cmluZ3NQYXJhbWV0ZXIsXG59IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHsgVGFza1Jlc3VsdHMgfSBmcm9tIFwiLi4vdGFzay1ncmFwaFwiXG5pbXBvcnQgeyBwcm9jZXNzTW9kdWxlcyB9IGZyb20gXCIuLi9wcm9jZXNzXCJcbmltcG9ydCB7IE1vZHVsZSB9IGZyb20gXCIuLi90eXBlcy9tb2R1bGVcIlxuaW1wb3J0IHsgVGVzdFRhc2sgfSBmcm9tIFwiLi4vdGFza3MvdGVzdFwiXG5pbXBvcnQgeyBjb21wdXRlQXV0b1JlbG9hZERlcGVuZGFudHMsIHdpdGhEZXBlbmRhbnRzIH0gZnJvbSBcIi4uL3dhdGNoXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuXG5jb25zdCB0ZXN0QXJncyA9IHtcbiAgbW9kdWxlOiBuZXcgU3RyaW5nc1BhcmFtZXRlcih7XG4gICAgaGVscDogXCJUaGUgbmFtZSBvZiB0aGUgbW9kdWxlKHMpIHRvIGRlcGxveSAoc2tpcCB0byB0ZXN0IGFsbCBtb2R1bGVzKS4gXCIgK1xuICAgICAgXCJVc2UgY29tbWEgYXMgc2VwYXJhdG9yIHRvIHNwZWNpZnkgbXVsdGlwbGUgbW9kdWxlcy5cIixcbiAgfSksXG59XG5cbmNvbnN0IHRlc3RPcHRzID0ge1xuICBuYW1lOiBuZXcgU3RyaW5nT3B0aW9uKHtcbiAgICBoZWxwOiBcIk9ubHkgcnVuIHRlc3RzIHdpdGggdGhlIHNwZWNmaWVkIG5hbWUgKGUuZy4gdW5pdCBvciBpbnRlZykuXCIsXG4gICAgYWxpYXM6IFwiblwiLFxuICB9KSxcbiAgZm9yY2U6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJGb3JjZSByZS10ZXN0IG9mIG1vZHVsZShzKS5cIiwgYWxpYXM6IFwiZlwiIH0pLFxuICBcImZvcmNlLWJ1aWxkXCI6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJGb3JjZSByZWJ1aWxkIG9mIG1vZHVsZShzKS5cIiB9KSxcbiAgd2F0Y2g6IG5ldyBCb29sZWFuUGFyYW1ldGVyKHsgaGVscDogXCJXYXRjaCBmb3IgY2hhbmdlcyBpbiBtb2R1bGUocykgYW5kIGF1dG8tdGVzdC5cIiwgYWxpYXM6IFwid1wiIH0pLFxufVxuXG50eXBlIEFyZ3MgPSB0eXBlb2YgdGVzdEFyZ3NcbnR5cGUgT3B0cyA9IHR5cGVvZiB0ZXN0T3B0c1xuXG5leHBvcnQgY2xhc3MgVGVzdENvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPEFyZ3MsIE9wdHM+IHtcbiAgbmFtZSA9IFwidGVzdFwiXG4gIGhlbHAgPSBcIlRlc3QgYWxsIG9yIHNwZWNpZmllZCBtb2R1bGVzLlwiXG5cbiAgZGVzY3JpcHRpb24gPSBgXG4gICAgUnVucyBhbGwgb3Igc3BlY2lmaWVkIHRlc3RzIGRlZmluZWQgaW4gdGhlIHByb2plY3QuIEFsc28gYnVpbGRzIG1vZHVsZXMgYW5kIGRlcGVuZGVuY2llcyxcbiAgICBhbmQgZGVwbG95IHNlcnZpY2UgZGVwZW5kZW5jaWVzIGlmIG5lZWRlZC5cblxuICAgIE9wdGlvbmFsbHkgc3RheXMgcnVubmluZyBhbmQgYXV0b21hdGljYWxseSByZS1ydW5zIHRlc3RzIGlmIHRoZWlyIG1vZHVsZSBzb3VyY2VcbiAgICAob3IgdGhlaXIgZGVwZW5kZW5jaWVzJyBzb3VyY2VzKSBjaGFuZ2UuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gdGVzdCAgICAgICAgICAgICAgIyBydW4gYWxsIHRlc3RzIGluIHRoZSBwcm9qZWN0XG4gICAgICAgIGdhcmRlbiB0ZXN0IG15LW1vZHVsZSAgICAjIHJ1biBhbGwgdGVzdHMgaW4gdGhlIG15LW1vZHVsZSBtb2R1bGVcbiAgICAgICAgZ2FyZGVuIHRlc3QgLW4gaW50ZWcgICAgICMgcnVuIGFsbCB0ZXN0cyB3aXRoIHRoZSBuYW1lICdpbnRlZycgaW4gdGhlIHByb2plY3RcbiAgICAgICAgZ2FyZGVuIHRlc3QgLS1mb3JjZSAgICAgICMgZm9yY2UgdGVzdHMgdG8gYmUgcmUtcnVuLCBldmVuIGlmIHRoZXkncmUgYWxyZWFkeSBydW4gc3VjY2Vzc2Z1bGx5XG4gICAgICAgIGdhcmRlbiB0ZXN0IC0td2F0Y2ggICAgICAjIHdhdGNoIGZvciBjaGFuZ2VzIHRvIGNvZGVcbiAgYFxuXG4gIGFyZ3VtZW50cyA9IHRlc3RBcmdzXG4gIG9wdGlvbnMgPSB0ZXN0T3B0c1xuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFRhc2tSZXN1bHRzPj4ge1xuICAgIGNvbnN0IGF1dG9SZWxvYWREZXBlbmRhbnRzID0gYXdhaXQgY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzKGdhcmRlbilcbiAgICBsZXQgbW9kdWxlczogTW9kdWxlW11cbiAgICBpZiAoYXJncy5tb2R1bGUpIHtcbiAgICAgIG1vZHVsZXMgPSBhd2FpdCB3aXRoRGVwZW5kYW50cyhnYXJkZW4sIGF3YWl0IGdhcmRlbi5nZXRNb2R1bGVzKGFyZ3MubW9kdWxlKSwgYXV0b1JlbG9hZERlcGVuZGFudHMpXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIEFsbCBtb2R1bGVzIGFyZSBpbmNsdWRlZCBpbiB0aGlzIGNhc2UsIHNvIHRoZXJlJ3Mgbm8gbmVlZCB0byBjb21wdXRlIGRlcGVuZGFudHMuXG4gICAgICBtb2R1bGVzID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZXMoKVxuICAgIH1cblxuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHtcbiAgICAgIGVtb2ppOiBcInRoZXJtb21ldGVyXCIsXG4gICAgICBjb21tYW5kOiBgUnVubmluZyB0ZXN0c2AsXG4gICAgfSlcblxuICAgIGF3YWl0IGdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7fSlcblxuICAgIGNvbnN0IG5hbWUgPSBvcHRzLm5hbWVcbiAgICBjb25zdCBmb3JjZSA9IG9wdHMuZm9yY2VcbiAgICBjb25zdCBmb3JjZUJ1aWxkID0gb3B0c1tcImZvcmNlLWJ1aWxkXCJdXG5cbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgcHJvY2Vzc01vZHVsZXMoe1xuICAgICAgZ2FyZGVuLFxuICAgICAgbW9kdWxlcyxcbiAgICAgIHdhdGNoOiBvcHRzLndhdGNoLFxuICAgICAgaGFuZGxlcjogYXN5bmMgKG1vZHVsZSkgPT4gZ2V0VGVzdFRhc2tzKHsgZ2FyZGVuLCBtb2R1bGUsIG5hbWUsIGZvcmNlLCBmb3JjZUJ1aWxkIH0pLFxuICAgICAgY2hhbmdlSGFuZGxlcjogYXN5bmMgKG1vZHVsZSkgPT4ge1xuICAgICAgICBjb25zdCBtb2R1bGVzVG9Qcm9jZXNzID0gYXdhaXQgd2l0aERlcGVuZGFudHMoZ2FyZGVuLCBbbW9kdWxlXSwgYXV0b1JlbG9hZERlcGVuZGFudHMpXG4gICAgICAgIHJldHVybiBmbGF0dGVuKGF3YWl0IEJsdWViaXJkLm1hcChcbiAgICAgICAgICBtb2R1bGVzVG9Qcm9jZXNzLFxuICAgICAgICAgIG0gPT4gZ2V0VGVzdFRhc2tzKHsgZ2FyZGVuLCBtb2R1bGU6IG0sIG5hbWUsIGZvcmNlLCBmb3JjZUJ1aWxkIH0pKSlcbiAgICAgIH0sXG4gICAgfSlcblxuICAgIHJldHVybiBoYW5kbGVUYXNrUmVzdWx0cyhnYXJkZW4sIFwidGVzdFwiLCByZXN1bHRzKVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRUZXN0VGFza3MoXG4gIHsgZ2FyZGVuLCBtb2R1bGUsIG5hbWUsIGZvcmNlID0gZmFsc2UsIGZvcmNlQnVpbGQgPSBmYWxzZSB9OlxuICAgIHsgZ2FyZGVuOiBHYXJkZW4sIG1vZHVsZTogTW9kdWxlLCBuYW1lPzogc3RyaW5nLCBmb3JjZT86IGJvb2xlYW4sIGZvcmNlQnVpbGQ/OiBib29sZWFuIH0sXG4pIHtcbiAgY29uc3QgdGFza3M6IFByb21pc2U8VGVzdFRhc2s+W10gPSBbXVxuXG4gIGZvciAoY29uc3QgdGVzdCBvZiBtb2R1bGUudGVzdENvbmZpZ3MpIHtcbiAgICBpZiAobmFtZSAmJiB0ZXN0Lm5hbWUgIT09IG5hbWUpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIHRhc2tzLnB1c2goVGVzdFRhc2suZmFjdG9yeSh7XG4gICAgICBnYXJkZW4sXG4gICAgICBmb3JjZSxcbiAgICAgIGZvcmNlQnVpbGQsXG4gICAgICB0ZXN0Q29uZmlnOiB0ZXN0LFxuICAgICAgbW9kdWxlLFxuICAgIH0pKVxuICB9XG5cbiAgcmV0dXJuIEJsdWViaXJkLmFsbCh0YXNrcylcbn1cbiJdfQ== diff --git a/garden-service/build/commands/unlink/module.d.ts b/garden-service/build/commands/unlink/module.d.ts new file mode 100644 index 00000000000..1db71e2e0c4 --- /dev/null +++ b/garden-service/build/commands/unlink/module.d.ts @@ -0,0 +1,24 @@ +import { Command, CommandResult, StringsParameter, BooleanParameter, CommandParams } from "../base"; +import { LinkedSource } from "../../config-store"; +declare const unlinkModuleArguments: { + module: StringsParameter; +}; +declare const unlinkModuleOptions: { + all: BooleanParameter; +}; +declare type Args = typeof unlinkModuleArguments; +declare type Opts = typeof unlinkModuleOptions; +export declare class UnlinkModuleCommand extends Command { + name: string; + help: string; + arguments: { + module: StringsParameter; + }; + options: { + all: BooleanParameter; + }; + description: string; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/unlink/module.js b/garden-service/build/commands/unlink/module.js new file mode 100644 index 00000000000..f8ed03cf747 --- /dev/null +++ b/garden-service/build/commands/unlink/module.js @@ -0,0 +1,68 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const dedent = require("dedent"); +const base_1 = require("../base"); +const ext_source_util_1 = require("../../util/ext-source-util"); +const config_store_1 = require("../../config-store"); +const unlinkModuleArguments = { + module: new base_1.StringsParameter({ + help: "Name of the module(s) to unlink. Use comma separator to specify multiple modules.", + }), +}; +const unlinkModuleOptions = { + all: new base_1.BooleanParameter({ + help: "Unlink all modules.", + alias: "a", + }), +}; +class UnlinkModuleCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "module"; + this.help = "Unlink a previously linked remote module from its local directory."; + this.arguments = unlinkModuleArguments; + this.options = unlinkModuleOptions; + this.description = dedent ` + After unlinking a remote module, Garden will go back to reading the module's source from + its remote URL instead of its local directory. + + Examples: + + garden unlink module my-module # unlinks my-module + garden unlink module --all # unlink all modules + `; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "chains", command: "unlink module" }); + const sourceType = "module"; + const { module = [] } = args; + if (opts.all) { + yield garden.localConfigStore.set([config_store_1.localConfigKeys.linkedModuleSources], []); + garden.log.info("Unlinked all modules"); + return { result: [] }; + } + const linkedModuleSources = yield ext_source_util_1.removeLinkedSources({ garden, sourceType, names: module }); + garden.log.info(`Unlinked module(s) ${module}`); + return { result: linkedModuleSources }; + }); + } +} +exports.UnlinkModuleCommand = UnlinkModuleCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VubGluay9tb2R1bGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUFpQztBQUVqQyxrQ0FNZ0I7QUFDaEIsZ0VBQWdFO0FBQ2hFLHFEQUcyQjtBQUUzQixNQUFNLHFCQUFxQixHQUFHO0lBQzVCLE1BQU0sRUFBRSxJQUFJLHVCQUFnQixDQUFDO1FBQzNCLElBQUksRUFBRSxtRkFBbUY7S0FDMUYsQ0FBQztDQUNILENBQUE7QUFFRCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEdBQUcsRUFBRSxJQUFJLHVCQUFnQixDQUFDO1FBQ3hCLElBQUksRUFBRSxxQkFBcUI7UUFDM0IsS0FBSyxFQUFFLEdBQUc7S0FDWCxDQUFDO0NBQ0gsQ0FBQTtBQUtELE1BQWEsbUJBQW9CLFNBQVEsY0FBbUI7SUFBNUQ7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFNBQUksR0FBRyxvRUFBb0UsQ0FBQTtRQUMzRSxjQUFTLEdBQUcscUJBQXFCLENBQUE7UUFDakMsWUFBTyxHQUFHLG1CQUFtQixDQUFBO1FBRTdCLGdCQUFXLEdBQUcsTUFBTSxDQUFBOzs7Ozs7OztHQVFuQixDQUFBO0lBcUJILENBQUM7SUFuQk8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQTZCOztZQUM1RCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUE7WUFFaEUsTUFBTSxVQUFVLEdBQUcsUUFBUSxDQUFBO1lBRTNCLE1BQU0sRUFBRSxNQUFNLEdBQUcsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFBO1lBRTVCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDWixNQUFNLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyw4QkFBZSxDQUFDLG1CQUFtQixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7Z0JBQzVFLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUE7Z0JBQ3ZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUE7YUFDdEI7WUFFRCxNQUFNLG1CQUFtQixHQUFHLE1BQU0scUNBQW1CLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBRTVGLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLHNCQUFzQixNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBRS9DLE9BQU8sRUFBRSxNQUFNLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQTtRQUN4QyxDQUFDO0tBQUE7Q0FDRjtBQW5DRCxrREFtQ0MiLCJmaWxlIjoiY29tbWFuZHMvdW5saW5rL21vZHVsZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5pbXBvcnQge1xuICBDb21tYW5kLFxuICBDb21tYW5kUmVzdWx0LFxuICBTdHJpbmdzUGFyYW1ldGVyLFxuICBCb29sZWFuUGFyYW1ldGVyLFxuICBDb21tYW5kUGFyYW1zLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyByZW1vdmVMaW5rZWRTb3VyY2VzIH0gZnJvbSBcIi4uLy4uL3V0aWwvZXh0LXNvdXJjZS11dGlsXCJcbmltcG9ydCB7XG4gIGxvY2FsQ29uZmlnS2V5cyxcbiAgTGlua2VkU291cmNlLFxufSBmcm9tIFwiLi4vLi4vY29uZmlnLXN0b3JlXCJcblxuY29uc3QgdW5saW5rTW9kdWxlQXJndW1lbnRzID0ge1xuICBtb2R1bGU6IG5ldyBTdHJpbmdzUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIk5hbWUgb2YgdGhlIG1vZHVsZShzKSB0byB1bmxpbmsuIFVzZSBjb21tYSBzZXBhcmF0b3IgdG8gc3BlY2lmeSBtdWx0aXBsZSBtb2R1bGVzLlwiLFxuICB9KSxcbn1cblxuY29uc3QgdW5saW5rTW9kdWxlT3B0aW9ucyA9IHtcbiAgYWxsOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7XG4gICAgaGVscDogXCJVbmxpbmsgYWxsIG1vZHVsZXMuXCIsXG4gICAgYWxpYXM6IFwiYVwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIHVubGlua01vZHVsZUFyZ3VtZW50c1xudHlwZSBPcHRzID0gdHlwZW9mIHVubGlua01vZHVsZU9wdGlvbnNcblxuZXhwb3J0IGNsYXNzIFVubGlua01vZHVsZUNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPEFyZ3MsIE9wdHM+IHtcbiAgbmFtZSA9IFwibW9kdWxlXCJcbiAgaGVscCA9IFwiVW5saW5rIGEgcHJldmlvdXNseSBsaW5rZWQgcmVtb3RlIG1vZHVsZSBmcm9tIGl0cyBsb2NhbCBkaXJlY3RvcnkuXCJcbiAgYXJndW1lbnRzID0gdW5saW5rTW9kdWxlQXJndW1lbnRzXG4gIG9wdGlvbnMgPSB1bmxpbmtNb2R1bGVPcHRpb25zXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgQWZ0ZXIgdW5saW5raW5nIGEgcmVtb3RlIG1vZHVsZSwgR2FyZGVuIHdpbGwgZ28gYmFjayB0byByZWFkaW5nIHRoZSBtb2R1bGUncyBzb3VyY2UgZnJvbVxuICAgIGl0cyByZW1vdGUgVVJMIGluc3RlYWQgb2YgaXRzIGxvY2FsIGRpcmVjdG9yeS5cblxuICAgIEV4YW1wbGVzOlxuXG4gICAgICAgIGdhcmRlbiB1bmxpbmsgbW9kdWxlIG15LW1vZHVsZSAjIHVubGlua3MgbXktbW9kdWxlXG4gICAgICAgIGdhcmRlbiB1bmxpbmsgbW9kdWxlIC0tYWxsICMgdW5saW5rIGFsbCBtb2R1bGVzXG4gIGBcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4sIGFyZ3MsIG9wdHMgfTogQ29tbWFuZFBhcmFtczxBcmdzLCBPcHRzPik6IFByb21pc2U8Q29tbWFuZFJlc3VsdDxMaW5rZWRTb3VyY2VbXT4+IHtcbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7IGVtb2ppOiBcImNoYWluc1wiLCBjb21tYW5kOiBcInVubGluayBtb2R1bGVcIiB9KVxuXG4gICAgY29uc3Qgc291cmNlVHlwZSA9IFwibW9kdWxlXCJcblxuICAgIGNvbnN0IHsgbW9kdWxlID0gW10gfSA9IGFyZ3NcblxuICAgIGlmIChvcHRzLmFsbCkge1xuICAgICAgYXdhaXQgZ2FyZGVuLmxvY2FsQ29uZmlnU3RvcmUuc2V0KFtsb2NhbENvbmZpZ0tleXMubGlua2VkTW9kdWxlU291cmNlc10sIFtdKVxuICAgICAgZ2FyZGVuLmxvZy5pbmZvKFwiVW5saW5rZWQgYWxsIG1vZHVsZXNcIilcbiAgICAgIHJldHVybiB7IHJlc3VsdDogW10gfVxuICAgIH1cblxuICAgIGNvbnN0IGxpbmtlZE1vZHVsZVNvdXJjZXMgPSBhd2FpdCByZW1vdmVMaW5rZWRTb3VyY2VzKHsgZ2FyZGVuLCBzb3VyY2VUeXBlLCBuYW1lczogbW9kdWxlIH0pXG5cbiAgICBnYXJkZW4ubG9nLmluZm8oYFVubGlua2VkIG1vZHVsZShzKSAke21vZHVsZX1gKVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBsaW5rZWRNb2R1bGVTb3VyY2VzIH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/unlink/source.d.ts b/garden-service/build/commands/unlink/source.d.ts new file mode 100644 index 00000000000..5754eb7ef11 --- /dev/null +++ b/garden-service/build/commands/unlink/source.d.ts @@ -0,0 +1,24 @@ +import { Command, CommandResult, StringsParameter, BooleanParameter, CommandParams } from "../base"; +import { LinkedSource } from "../../config-store"; +declare const unlinkSourceArguments: { + source: StringsParameter; +}; +declare const unlinkSourceOptions: { + all: BooleanParameter; +}; +declare type Args = typeof unlinkSourceArguments; +declare type Opts = typeof unlinkSourceOptions; +export declare class UnlinkSourceCommand extends Command { + name: string; + help: string; + arguments: { + source: StringsParameter; + }; + options: { + all: BooleanParameter; + }; + description: string; + action({ garden, args, opts }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=source.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/unlink/source.js b/garden-service/build/commands/unlink/source.js new file mode 100644 index 00000000000..e28d7b0823e --- /dev/null +++ b/garden-service/build/commands/unlink/source.js @@ -0,0 +1,68 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const dedent = require("dedent"); +const base_1 = require("../base"); +const ext_source_util_1 = require("../../util/ext-source-util"); +const config_store_1 = require("../../config-store"); +const unlinkSourceArguments = { + source: new base_1.StringsParameter({ + help: "Name of the source(s) to unlink. Use comma separator to specify multiple sources.", + }), +}; +const unlinkSourceOptions = { + all: new base_1.BooleanParameter({ + help: "Unlink all sources.", + alias: "a", + }), +}; +class UnlinkSourceCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "source"; + this.help = "Unlink a previously linked remote source from its local directory."; + this.arguments = unlinkSourceArguments; + this.options = unlinkSourceOptions; + this.description = dedent ` + After unlinking a remote source, Garden will go back to reading it from its remote URL instead + of its local directory. + + Examples: + + garden unlink source my-source # unlinks my-source + garden unlink source --all # unlinks all sources + `; + } + action({ garden, args, opts }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "chains", command: "unlink source" }); + const sourceType = "project"; + const { source = [] } = args; + if (opts.all) { + yield garden.localConfigStore.set([config_store_1.localConfigKeys.linkedProjectSources], []); + garden.log.info("Unlinked all sources"); + return { result: [] }; + } + const linkedProjectSources = yield ext_source_util_1.removeLinkedSources({ garden, sourceType, names: source }); + garden.log.info(`Unlinked source(s) ${source}`); + return { result: linkedProjectSources }; + }); + } +} +exports.UnlinkSourceCommand = UnlinkSourceCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VubGluay9zb3VyY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUFpQztBQUVqQyxrQ0FNZ0I7QUFDaEIsZ0VBQWdFO0FBQ2hFLHFEQUcyQjtBQUUzQixNQUFNLHFCQUFxQixHQUFHO0lBQzVCLE1BQU0sRUFBRSxJQUFJLHVCQUFnQixDQUFDO1FBQzNCLElBQUksRUFBRSxtRkFBbUY7S0FDMUYsQ0FBQztDQUNILENBQUE7QUFFRCxNQUFNLG1CQUFtQixHQUFHO0lBQzFCLEdBQUcsRUFBRSxJQUFJLHVCQUFnQixDQUFDO1FBQ3hCLElBQUksRUFBRSxxQkFBcUI7UUFDM0IsS0FBSyxFQUFFLEdBQUc7S0FDWCxDQUFDO0NBQ0gsQ0FBQTtBQUtELE1BQWEsbUJBQW9CLFNBQVEsY0FBbUI7SUFBNUQ7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFNBQUksR0FBRyxvRUFBb0UsQ0FBQTtRQUMzRSxjQUFTLEdBQUcscUJBQXFCLENBQUE7UUFDakMsWUFBTyxHQUFHLG1CQUFtQixDQUFBO1FBRTdCLGdCQUFXLEdBQUcsTUFBTSxDQUFBOzs7Ozs7OztHQVFuQixDQUFBO0lBcUJILENBQUM7SUFuQk8sTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxJQUFJLEVBQTZCOztZQUM1RCxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLGVBQWUsRUFBRSxDQUFDLENBQUE7WUFFaEUsTUFBTSxVQUFVLEdBQUcsU0FBUyxDQUFBO1lBRTVCLE1BQU0sRUFBRSxNQUFNLEdBQUcsRUFBRSxFQUFFLEdBQUcsSUFBSSxDQUFBO1lBRTVCLElBQUksSUFBSSxDQUFDLEdBQUcsRUFBRTtnQkFDWixNQUFNLE1BQU0sQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLENBQUMsQ0FBQyw4QkFBZSxDQUFDLG9CQUFvQixDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUE7Z0JBQzdFLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLHNCQUFzQixDQUFDLENBQUE7Z0JBQ3ZDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRSxFQUFFLENBQUE7YUFDdEI7WUFFRCxNQUFNLG9CQUFvQixHQUFHLE1BQU0scUNBQW1CLENBQUMsRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBRTdGLE1BQU0sQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLHNCQUFzQixNQUFNLEVBQUUsQ0FBQyxDQUFBO1lBRS9DLE9BQU8sRUFBRSxNQUFNLEVBQUUsb0JBQW9CLEVBQUUsQ0FBQTtRQUN6QyxDQUFDO0tBQUE7Q0FDRjtBQW5DRCxrREFtQ0MiLCJmaWxlIjoiY29tbWFuZHMvdW5saW5rL3NvdXJjZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5pbXBvcnQge1xuICBDb21tYW5kLFxuICBDb21tYW5kUmVzdWx0LFxuICBTdHJpbmdzUGFyYW1ldGVyLFxuICBCb29sZWFuUGFyYW1ldGVyLFxuICBDb21tYW5kUGFyYW1zLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyByZW1vdmVMaW5rZWRTb3VyY2VzIH0gZnJvbSBcIi4uLy4uL3V0aWwvZXh0LXNvdXJjZS11dGlsXCJcbmltcG9ydCB7XG4gIGxvY2FsQ29uZmlnS2V5cyxcbiAgTGlua2VkU291cmNlLFxufSBmcm9tIFwiLi4vLi4vY29uZmlnLXN0b3JlXCJcblxuY29uc3QgdW5saW5rU291cmNlQXJndW1lbnRzID0ge1xuICBzb3VyY2U6IG5ldyBTdHJpbmdzUGFyYW1ldGVyKHtcbiAgICBoZWxwOiBcIk5hbWUgb2YgdGhlIHNvdXJjZShzKSB0byB1bmxpbmsuIFVzZSBjb21tYSBzZXBhcmF0b3IgdG8gc3BlY2lmeSBtdWx0aXBsZSBzb3VyY2VzLlwiLFxuICB9KSxcbn1cblxuY29uc3QgdW5saW5rU291cmNlT3B0aW9ucyA9IHtcbiAgYWxsOiBuZXcgQm9vbGVhblBhcmFtZXRlcih7XG4gICAgaGVscDogXCJVbmxpbmsgYWxsIHNvdXJjZXMuXCIsXG4gICAgYWxpYXM6IFwiYVwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIHVubGlua1NvdXJjZUFyZ3VtZW50c1xudHlwZSBPcHRzID0gdHlwZW9mIHVubGlua1NvdXJjZU9wdGlvbnNcblxuZXhwb3J0IGNsYXNzIFVubGlua1NvdXJjZUNvbW1hbmQgZXh0ZW5kcyBDb21tYW5kPEFyZ3MsIE9wdHM+IHtcbiAgbmFtZSA9IFwic291cmNlXCJcbiAgaGVscCA9IFwiVW5saW5rIGEgcHJldmlvdXNseSBsaW5rZWQgcmVtb3RlIHNvdXJjZSBmcm9tIGl0cyBsb2NhbCBkaXJlY3RvcnkuXCJcbiAgYXJndW1lbnRzID0gdW5saW5rU291cmNlQXJndW1lbnRzXG4gIG9wdGlvbnMgPSB1bmxpbmtTb3VyY2VPcHRpb25zXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgQWZ0ZXIgdW5saW5raW5nIGEgcmVtb3RlIHNvdXJjZSwgR2FyZGVuIHdpbGwgZ28gYmFjayB0byByZWFkaW5nIGl0IGZyb20gaXRzIHJlbW90ZSBVUkwgaW5zdGVhZFxuICAgIG9mIGl0cyBsb2NhbCBkaXJlY3RvcnkuXG5cbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gdW5saW5rIHNvdXJjZSBteS1zb3VyY2UgIyB1bmxpbmtzIG15LXNvdXJjZVxuICAgICAgICBnYXJkZW4gdW5saW5rIHNvdXJjZSAtLWFsbCAjIHVubGlua3MgYWxsIHNvdXJjZXNcbiAgYFxuXG4gIGFzeW5jIGFjdGlvbih7IGdhcmRlbiwgYXJncywgb3B0cyB9OiBDb21tYW5kUGFyYW1zPEFyZ3MsIE9wdHM+KTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PExpbmtlZFNvdXJjZVtdPj4ge1xuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwiY2hhaW5zXCIsIGNvbW1hbmQ6IFwidW5saW5rIHNvdXJjZVwiIH0pXG5cbiAgICBjb25zdCBzb3VyY2VUeXBlID0gXCJwcm9qZWN0XCJcblxuICAgIGNvbnN0IHsgc291cmNlID0gW10gfSA9IGFyZ3NcblxuICAgIGlmIChvcHRzLmFsbCkge1xuICAgICAgYXdhaXQgZ2FyZGVuLmxvY2FsQ29uZmlnU3RvcmUuc2V0KFtsb2NhbENvbmZpZ0tleXMubGlua2VkUHJvamVjdFNvdXJjZXNdLCBbXSlcbiAgICAgIGdhcmRlbi5sb2cuaW5mbyhcIlVubGlua2VkIGFsbCBzb3VyY2VzXCIpXG4gICAgICByZXR1cm4geyByZXN1bHQ6IFtdIH1cbiAgICB9XG5cbiAgICBjb25zdCBsaW5rZWRQcm9qZWN0U291cmNlcyA9IGF3YWl0IHJlbW92ZUxpbmtlZFNvdXJjZXMoeyBnYXJkZW4sIHNvdXJjZVR5cGUsIG5hbWVzOiBzb3VyY2UgfSlcblxuICAgIGdhcmRlbi5sb2cuaW5mbyhgVW5saW5rZWQgc291cmNlKHMpICR7c291cmNlfWApXG5cbiAgICByZXR1cm4geyByZXN1bHQ6IGxpbmtlZFByb2plY3RTb3VyY2VzIH1cbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/unlink/unlink.d.ts b/garden-service/build/commands/unlink/unlink.d.ts new file mode 100644 index 00000000000..08d3d05b22a --- /dev/null +++ b/garden-service/build/commands/unlink/unlink.d.ts @@ -0,0 +1,10 @@ +import { Command } from "../base"; +import { UnlinkSourceCommand } from "./source"; +import { UnlinkModuleCommand } from "./module"; +export declare class UnlinkCommand extends Command { + name: string; + help: string; + subCommands: (typeof UnlinkSourceCommand | typeof UnlinkModuleCommand)[]; + action(): Promise<{}>; +} +//# sourceMappingURL=unlink.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/unlink/unlink.js b/garden-service/build/commands/unlink/unlink.js new file mode 100644 index 00000000000..600e4156b56 --- /dev/null +++ b/garden-service/build/commands/unlink/unlink.js @@ -0,0 +1,37 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("../base"); +const source_1 = require("./source"); +const module_1 = require("./module"); +class UnlinkCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "unlink"; + this.help = "Unlink a remote source or module from its local path"; + this.subCommands = [ + source_1.UnlinkSourceCommand, + module_1.UnlinkModuleCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.UnlinkCommand = UnlinkCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VubGluay91bmxpbmsudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGtDQUFpQztBQUNqQyxxQ0FBOEM7QUFDOUMscUNBQThDO0FBRTlDLE1BQWEsYUFBYyxTQUFRLGNBQU87SUFBMUM7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtRQUNmLFNBQUksR0FBRyxzREFBc0QsQ0FBQTtRQUU3RCxnQkFBVyxHQUFHO1lBQ1osNEJBQW1CO1lBQ25CLDRCQUFtQjtTQUNwQixDQUFBO0lBR0gsQ0FBQztJQURPLE1BQU07OERBQUssT0FBTyxFQUFFLENBQUEsQ0FBQyxDQUFDO0tBQUE7Q0FDN0I7QUFWRCxzQ0FVQyIsImZpbGUiOiJjb21tYW5kcy91bmxpbmsvdW5saW5rLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyBVbmxpbmtTb3VyY2VDb21tYW5kIH0gZnJvbSBcIi4vc291cmNlXCJcbmltcG9ydCB7IFVubGlua01vZHVsZUNvbW1hbmQgfSBmcm9tIFwiLi9tb2R1bGVcIlxuXG5leHBvcnQgY2xhc3MgVW5saW5rQ29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBuYW1lID0gXCJ1bmxpbmtcIlxuICBoZWxwID0gXCJVbmxpbmsgYSByZW1vdGUgc291cmNlIG9yIG1vZHVsZSBmcm9tIGl0cyBsb2NhbCBwYXRoXCJcblxuICBzdWJDb21tYW5kcyA9IFtcbiAgICBVbmxpbmtTb3VyY2VDb21tYW5kLFxuICAgIFVubGlua01vZHVsZUNvbW1hbmQsXG4gIF1cblxuICBhc3luYyBhY3Rpb24oKSB7IHJldHVybiB7fSB9XG59XG4iXX0= diff --git a/garden-service/build/commands/update-remote/all.d.ts b/garden-service/build/commands/update-remote/all.d.ts new file mode 100644 index 00000000000..22c849e8630 --- /dev/null +++ b/garden-service/build/commands/update-remote/all.d.ts @@ -0,0 +1,13 @@ +import { Command, CommandResult, CommandParams } from "../base"; +import { SourceConfig } from "../../config/project"; +export interface UpdateRemoteAllResult { + projectSources: SourceConfig[]; + moduleSources: SourceConfig[]; +} +export declare class UpdateRemoteAllCommand extends Command { + name: string; + help: string; + description: string; + action({ garden }: CommandParams): Promise>; +} +//# sourceMappingURL=all.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/update-remote/all.js b/garden-service/build/commands/update-remote/all.js new file mode 100644 index 00000000000..992ec3c069c --- /dev/null +++ b/garden-service/build/commands/update-remote/all.js @@ -0,0 +1,46 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const dedent = require("dedent"); +const base_1 = require("../base"); +const sources_1 = require("./sources"); +const modules_1 = require("./modules"); +class UpdateRemoteAllCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "all"; + this.help = "Update all remote sources and modules."; + this.description = dedent ` + Examples: + + garden update-remote all # update all remote sources and modules in the project + `; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "hammer_and_wrench", command: "update-remote all" }); + const sourcesCmd = new sources_1.UpdateRemoteSourcesCommand(); + const modulesCmd = new modules_1.UpdateRemoteModulesCommand(); + const { result: projectSources } = yield sourcesCmd.action({ garden, args: { source: undefined }, opts: {} }); + const { result: moduleSources } = yield modulesCmd.action({ garden, args: { module: undefined }, opts: {} }); + return { result: { projectSources: projectSources, moduleSources: moduleSources } }; + }); + } +} +exports.UpdateRemoteAllCommand = UpdateRemoteAllCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VwZGF0ZS1yZW1vdGUvYWxsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxpQ0FBaUM7QUFFakMsa0NBSWdCO0FBQ2hCLHVDQUFzRDtBQUN0RCx1Q0FBc0Q7QUFRdEQsTUFBYSxzQkFBdUIsU0FBUSxjQUFPO0lBQW5EOztRQUNFLFNBQUksR0FBRyxLQUFLLENBQUE7UUFDWixTQUFJLEdBQUcsd0NBQXdDLENBQUE7UUFFL0MsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7R0FJbkIsQ0FBQTtJQWNILENBQUM7SUFaTyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQWlCOztZQUVwQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxtQkFBbUIsRUFBRSxPQUFPLEVBQUUsbUJBQW1CLEVBQUUsQ0FBQyxDQUFBO1lBRS9FLE1BQU0sVUFBVSxHQUFHLElBQUksb0NBQTBCLEVBQUUsQ0FBQTtZQUNuRCxNQUFNLFVBQVUsR0FBRyxJQUFJLG9DQUEwQixFQUFFLENBQUE7WUFFbkQsTUFBTSxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsR0FBRyxNQUFNLFVBQVUsQ0FBQyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLEVBQUUsTUFBTSxFQUFFLFNBQVMsRUFBRSxFQUFFLElBQUksRUFBRSxFQUFFLEVBQUUsQ0FBQyxDQUFBO1lBQzdHLE1BQU0sRUFBRSxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsTUFBTSxVQUFVLENBQUMsTUFBTSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxFQUFFLE1BQU0sRUFBRSxTQUFTLEVBQUUsRUFBRSxJQUFJLEVBQUUsRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUU1RyxPQUFPLEVBQUUsTUFBTSxFQUFFLEVBQUUsY0FBYyxFQUFFLGNBQWUsRUFBRSxhQUFhLEVBQUUsYUFBYyxFQUFFLEVBQUUsQ0FBQTtRQUN2RixDQUFDO0tBQUE7Q0FDRjtBQXRCRCx3REFzQkMiLCJmaWxlIjoiY29tbWFuZHMvdXBkYXRlLXJlbW90ZS9hbGwuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcblxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFJlc3VsdCxcbiAgQ29tbWFuZFBhcmFtcyxcbn0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgVXBkYXRlUmVtb3RlU291cmNlc0NvbW1hbmQgfSBmcm9tIFwiLi9zb3VyY2VzXCJcbmltcG9ydCB7IFVwZGF0ZVJlbW90ZU1vZHVsZXNDb21tYW5kIH0gZnJvbSBcIi4vbW9kdWxlc1wiXG5pbXBvcnQgeyBTb3VyY2VDb25maWcgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3Byb2plY3RcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFVwZGF0ZVJlbW90ZUFsbFJlc3VsdCB7XG4gIHByb2plY3RTb3VyY2VzOiBTb3VyY2VDb25maWdbXSxcbiAgbW9kdWxlU291cmNlczogU291cmNlQ29uZmlnW10sXG59XG5cbmV4cG9ydCBjbGFzcyBVcGRhdGVSZW1vdGVBbGxDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIG5hbWUgPSBcImFsbFwiXG4gIGhlbHAgPSBcIlVwZGF0ZSBhbGwgcmVtb3RlIHNvdXJjZXMgYW5kIG1vZHVsZXMuXCJcblxuICBkZXNjcmlwdGlvbiA9IGRlZGVudGBcbiAgICBFeGFtcGxlczpcblxuICAgICAgICBnYXJkZW4gdXBkYXRlLXJlbW90ZSBhbGwgIyB1cGRhdGUgYWxsIHJlbW90ZSBzb3VyY2VzIGFuZCBtb2R1bGVzIGluIHRoZSBwcm9qZWN0XG4gIGBcblxuICBhc3luYyBhY3Rpb24oeyBnYXJkZW4gfTogQ29tbWFuZFBhcmFtcyk6IFByb21pc2U8Q29tbWFuZFJlc3VsdDxVcGRhdGVSZW1vdGVBbGxSZXN1bHQ+PiB7XG5cbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7IGVtb2ppOiBcImhhbW1lcl9hbmRfd3JlbmNoXCIsIGNvbW1hbmQ6IFwidXBkYXRlLXJlbW90ZSBhbGxcIiB9KVxuXG4gICAgY29uc3Qgc291cmNlc0NtZCA9IG5ldyBVcGRhdGVSZW1vdGVTb3VyY2VzQ29tbWFuZCgpXG4gICAgY29uc3QgbW9kdWxlc0NtZCA9IG5ldyBVcGRhdGVSZW1vdGVNb2R1bGVzQ29tbWFuZCgpXG5cbiAgICBjb25zdCB7IHJlc3VsdDogcHJvamVjdFNvdXJjZXMgfSA9IGF3YWl0IHNvdXJjZXNDbWQuYWN0aW9uKHsgZ2FyZGVuLCBhcmdzOiB7IHNvdXJjZTogdW5kZWZpbmVkIH0sIG9wdHM6IHt9IH0pXG4gICAgY29uc3QgeyByZXN1bHQ6IG1vZHVsZVNvdXJjZXMgfSA9IGF3YWl0IG1vZHVsZXNDbWQuYWN0aW9uKHsgZ2FyZGVuLCBhcmdzOiB7IG1vZHVsZTogdW5kZWZpbmVkIH0sIG9wdHM6IHt9IH0pXG5cbiAgICByZXR1cm4geyByZXN1bHQ6IHsgcHJvamVjdFNvdXJjZXM6IHByb2plY3RTb3VyY2VzISwgbW9kdWxlU291cmNlczogbW9kdWxlU291cmNlcyEgfSB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/update-remote/helpers.d.ts b/garden-service/build/commands/update-remote/helpers.d.ts new file mode 100644 index 00000000000..5804896d96a --- /dev/null +++ b/garden-service/build/commands/update-remote/helpers.d.ts @@ -0,0 +1,8 @@ +import { ExternalSourceType } from "../../util/ext-source-util"; +import { SourceConfig } from "../../config/project"; +export declare function pruneRemoteSources({ projectRoot, sources, type }: { + projectRoot: string; + sources: SourceConfig[]; + type: ExternalSourceType; +}): Promise; +//# sourceMappingURL=helpers.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/update-remote/helpers.js b/garden-service/build/commands/update-remote/helpers.js new file mode 100644 index 00000000000..80709ad8767 --- /dev/null +++ b/garden-service/build/commands/update-remote/helpers.js @@ -0,0 +1,41 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const util_1 = require("../../util/util"); +const ext_source_util_1 = require("../../util/ext-source-util"); +function pruneRemoteSources({ projectRoot, sources, type }) { + return __awaiter(this, void 0, void 0, function* () { + const remoteSourcesPath = path_1.join(projectRoot, ext_source_util_1.getRemoteSourcesDirname(type)); + if (!(yield fs_extra_1.pathExists(remoteSourcesPath))) { + return; + } + const sourceNames = sources + .map(({ name, repositoryUrl: url }) => ext_source_util_1.getRemoteSourcePath({ name, url, sourceType: type })) + .map(srcPath => path_1.basename(srcPath)); + const currentRemoteSources = yield util_1.getChildDirNames(remoteSourcesPath); + const staleRemoteSources = lodash_1.difference(currentRemoteSources, sourceNames); + for (const dirName of staleRemoteSources) { + yield fs_extra_1.remove(path_1.join(remoteSourcesPath, dirName)); + } + }); +} +exports.pruneRemoteSources = pruneRemoteSources; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VwZGF0ZS1yZW1vdGUvaGVscGVycy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsbUNBQW1DO0FBQ25DLCtCQUFxQztBQUNyQyx1Q0FBNkM7QUFFN0MsMENBQWtEO0FBQ2xELGdFQUltQztBQUduQyxTQUFzQixrQkFBa0IsQ0FBQyxFQUFFLFdBQVcsRUFBRSxPQUFPLEVBQUUsSUFBSSxFQUlwRTs7UUFDQyxNQUFNLGlCQUFpQixHQUFHLFdBQUksQ0FBQyxXQUFXLEVBQUUseUNBQXVCLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtRQUUxRSxJQUFJLENBQUMsQ0FBQyxNQUFNLHFCQUFVLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxFQUFFO1lBQzFDLE9BQU07U0FDUDtRQUVELE1BQU0sV0FBVyxHQUFHLE9BQU87YUFDeEIsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsYUFBYSxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsQ0FBQyxxQ0FBbUIsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUM7YUFDM0YsR0FBRyxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUMsZUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7UUFFcEMsTUFBTSxvQkFBb0IsR0FBRyxNQUFNLHVCQUFnQixDQUFDLGlCQUFpQixDQUFDLENBQUE7UUFDdEUsTUFBTSxrQkFBa0IsR0FBRyxtQkFBVSxDQUFDLG9CQUFvQixFQUFFLFdBQVcsQ0FBQyxDQUFBO1FBRXhFLEtBQUssTUFBTSxPQUFPLElBQUksa0JBQWtCLEVBQUU7WUFDeEMsTUFBTSxpQkFBTSxDQUFDLFdBQUksQ0FBQyxpQkFBaUIsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFBO1NBQy9DO0lBQ0gsQ0FBQztDQUFBO0FBckJELGdEQXFCQyIsImZpbGUiOiJjb21tYW5kcy91cGRhdGUtcmVtb3RlL2hlbHBlcnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgZGlmZmVyZW5jZSB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgam9pbiwgYmFzZW5hbWUgfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyByZW1vdmUsIHBhdGhFeGlzdHMgfSBmcm9tIFwiZnMtZXh0cmFcIlxuXG5pbXBvcnQgeyBnZXRDaGlsZERpck5hbWVzIH0gZnJvbSBcIi4uLy4uL3V0aWwvdXRpbFwiXG5pbXBvcnQge1xuICBFeHRlcm5hbFNvdXJjZVR5cGUsXG4gIGdldFJlbW90ZVNvdXJjZXNEaXJuYW1lLFxuICBnZXRSZW1vdGVTb3VyY2VQYXRoLFxufSBmcm9tIFwiLi4vLi4vdXRpbC9leHQtc291cmNlLXV0aWxcIlxuaW1wb3J0IHsgU291cmNlQ29uZmlnIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9wcm9qZWN0XCJcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBydW5lUmVtb3RlU291cmNlcyh7IHByb2plY3RSb290LCBzb3VyY2VzLCB0eXBlIH06IHtcbiAgcHJvamVjdFJvb3Q6IHN0cmluZyxcbiAgc291cmNlczogU291cmNlQ29uZmlnW10sXG4gIHR5cGU6IEV4dGVybmFsU291cmNlVHlwZSxcbn0pIHtcbiAgY29uc3QgcmVtb3RlU291cmNlc1BhdGggPSBqb2luKHByb2plY3RSb290LCBnZXRSZW1vdGVTb3VyY2VzRGlybmFtZSh0eXBlKSlcblxuICBpZiAoIShhd2FpdCBwYXRoRXhpc3RzKHJlbW90ZVNvdXJjZXNQYXRoKSkpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIGNvbnN0IHNvdXJjZU5hbWVzID0gc291cmNlc1xuICAgIC5tYXAoKHsgbmFtZSwgcmVwb3NpdG9yeVVybDogdXJsIH0pID0+IGdldFJlbW90ZVNvdXJjZVBhdGgoeyBuYW1lLCB1cmwsIHNvdXJjZVR5cGU6IHR5cGUgfSkpXG4gICAgLm1hcChzcmNQYXRoID0+IGJhc2VuYW1lKHNyY1BhdGgpKVxuXG4gIGNvbnN0IGN1cnJlbnRSZW1vdGVTb3VyY2VzID0gYXdhaXQgZ2V0Q2hpbGREaXJOYW1lcyhyZW1vdGVTb3VyY2VzUGF0aClcbiAgY29uc3Qgc3RhbGVSZW1vdGVTb3VyY2VzID0gZGlmZmVyZW5jZShjdXJyZW50UmVtb3RlU291cmNlcywgc291cmNlTmFtZXMpXG5cbiAgZm9yIChjb25zdCBkaXJOYW1lIG9mIHN0YWxlUmVtb3RlU291cmNlcykge1xuICAgIGF3YWl0IHJlbW92ZShqb2luKHJlbW90ZVNvdXJjZXNQYXRoLCBkaXJOYW1lKSlcbiAgfVxufVxuIl19 diff --git a/garden-service/build/commands/update-remote/modules.d.ts b/garden-service/build/commands/update-remote/modules.d.ts new file mode 100644 index 00000000000..17ad7e6e4e1 --- /dev/null +++ b/garden-service/build/commands/update-remote/modules.d.ts @@ -0,0 +1,17 @@ +import { Command, StringsParameter, CommandResult, CommandParams } from "../base"; +import { SourceConfig } from "../../config/project"; +declare const updateRemoteModulesArguments: { + module: StringsParameter; +}; +declare type Args = typeof updateRemoteModulesArguments; +export declare class UpdateRemoteModulesCommand extends Command { + name: string; + help: string; + arguments: { + module: StringsParameter; + }; + description: string; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=modules.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/update-remote/modules.js b/garden-service/build/commands/update-remote/modules.js new file mode 100644 index 00000000000..53bd6298153 --- /dev/null +++ b/garden-service/build/commands/update-remote/modules.js @@ -0,0 +1,75 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const dedent = require("dedent"); +const chalk_1 = require("chalk"); +const base_1 = require("../base"); +const exceptions_1 = require("../../exceptions"); +const helpers_1 = require("./helpers"); +const ext_source_util_1 = require("../../util/ext-source-util"); +const updateRemoteModulesArguments = { + module: new base_1.StringsParameter({ + help: "Name of the remote module(s) to update. Use comma separator to specify multiple modules.", + }), +}; +class UpdateRemoteModulesCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "modules"; + this.help = "Update remote modules."; + this.arguments = updateRemoteModulesArguments; + this.description = dedent ` + Remote modules are modules that have a repositoryUrl field + in their garden.yml config that points to a remote repository. + + Examples: + + garden update-remote modules # update all remote modules in the project + garden update-remote modules my-module # update remote module my-module + `; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "hammer_and_wrench", command: "update-remote modules" }); + const { module } = args; + const modules = yield garden.getModules(module); + const moduleSources = modules + .filter(ext_source_util_1.hasRemoteSource) + .filter(src => module ? module.includes(src.name) : true); + const names = moduleSources.map(src => src.name); + const diff = lodash_1.difference(module, names); + if (diff.length > 0) { + const modulesWithRemoteSource = (yield garden.getModules()).filter(ext_source_util_1.hasRemoteSource).sort(); + throw new exceptions_1.ParameterError(`Expected module(s) ${chalk_1.default.underline(diff.join(","))} to have a remote source.`, { + modulesWithRemoteSource, + input: module ? module.sort() : undefined, + }); + } + // TODO Update remotes in parallel. Currently not possible since updating might + // trigger a username and password prompt from git. + for (const { name, repositoryUrl } of moduleSources) { + yield garden.vcs.updateRemoteSource({ name, url: repositoryUrl, sourceType: "module", logEntry: garden.log }); + } + yield helpers_1.pruneRemoteSources({ projectRoot: garden.projectRoot, type: "module", sources: moduleSources }); + return { result: moduleSources }; + }); + } +} +exports.UpdateRemoteModulesCommand = UpdateRemoteModulesCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VwZGF0ZS1yZW1vdGUvbW9kdWxlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsbUNBQW1DO0FBQ25DLGlDQUFpQztBQUNqQyxpQ0FBeUI7QUFFekIsa0NBS2dCO0FBRWhCLGlEQUFpRDtBQUNqRCx1Q0FBOEM7QUFDOUMsZ0VBQTREO0FBRTVELE1BQU0sNEJBQTRCLEdBQUc7SUFDbkMsTUFBTSxFQUFFLElBQUksdUJBQWdCLENBQUM7UUFDM0IsSUFBSSxFQUFFLDBGQUEwRjtLQUNqRyxDQUFDO0NBQ0gsQ0FBQTtBQUlELE1BQWEsMEJBQTJCLFNBQVEsY0FBYTtJQUE3RDs7UUFDRSxTQUFJLEdBQUcsU0FBUyxDQUFBO1FBQ2hCLFNBQUksR0FBRyx3QkFBd0IsQ0FBQTtRQUMvQixjQUFTLEdBQUcsNEJBQTRCLENBQUE7UUFFeEMsZ0JBQVcsR0FBRyxNQUFNLENBQUE7Ozs7Ozs7O0dBUW5CLENBQUE7SUF1Q0gsQ0FBQztJQXJDTyxNQUFNLENBQ1YsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUF1Qjs7WUFFckMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsRUFBRSxLQUFLLEVBQUUsbUJBQW1CLEVBQUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLENBQUMsQ0FBQTtZQUVuRixNQUFNLEVBQUUsTUFBTSxFQUFFLEdBQUcsSUFBSSxDQUFBO1lBQ3ZCLE1BQU0sT0FBTyxHQUFHLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUUvQyxNQUFNLGFBQWEsR0FBbUIsT0FBTztpQkFDMUMsTUFBTSxDQUFDLGlDQUFlLENBQUM7aUJBQ3ZCLE1BQU0sQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFBO1lBRTNELE1BQU0sS0FBSyxHQUFHLGFBQWEsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFaEQsTUFBTSxJQUFJLEdBQUcsbUJBQVUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDbkIsTUFBTSx1QkFBdUIsR0FBRyxDQUFDLE1BQU0sTUFBTSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUMsTUFBTSxDQUFDLGlDQUFlLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQTtnQkFFMUYsTUFBTSxJQUFJLDJCQUFjLENBQ3RCLHNCQUFzQixlQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsMkJBQTJCLEVBQ2hGO29CQUNFLHVCQUF1QjtvQkFDdkIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxTQUFTO2lCQUMxQyxDQUNGLENBQUE7YUFDRjtZQUVELCtFQUErRTtZQUMvRSxtREFBbUQ7WUFDbkQsS0FBSyxNQUFNLEVBQUUsSUFBSSxFQUFFLGFBQWEsRUFBRSxJQUFJLGFBQWEsRUFBRTtnQkFDbkQsTUFBTSxNQUFNLENBQUMsR0FBRyxDQUFDLGtCQUFrQixDQUFDLEVBQUUsSUFBSSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLFFBQVEsRUFBRSxRQUFRLEVBQUUsTUFBTSxDQUFDLEdBQUcsRUFBRSxDQUFDLENBQUE7YUFDOUc7WUFFRCxNQUFNLDRCQUFrQixDQUFDLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXLEVBQUUsSUFBSSxFQUFFLFFBQVEsRUFBRSxPQUFPLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQTtZQUVyRyxPQUFPLEVBQUUsTUFBTSxFQUFFLGFBQWEsRUFBRSxDQUFBO1FBQ2xDLENBQUM7S0FBQTtDQUNGO0FBcERELGdFQW9EQyIsImZpbGUiOiJjb21tYW5kcy91cGRhdGUtcmVtb3RlL21vZHVsZXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgZGlmZmVyZW5jZSB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuXG5pbXBvcnQge1xuICBDb21tYW5kLFxuICBTdHJpbmdzUGFyYW1ldGVyLFxuICBDb21tYW5kUmVzdWx0LFxuICBDb21tYW5kUGFyYW1zLFxufSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyBTb3VyY2VDb25maWcgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3Byb2plY3RcIlxuaW1wb3J0IHsgUGFyYW1ldGVyRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBwcnVuZVJlbW90ZVNvdXJjZXMgfSBmcm9tIFwiLi9oZWxwZXJzXCJcbmltcG9ydCB7IGhhc1JlbW90ZVNvdXJjZSB9IGZyb20gXCIuLi8uLi91dGlsL2V4dC1zb3VyY2UtdXRpbFwiXG5cbmNvbnN0IHVwZGF0ZVJlbW90ZU1vZHVsZXNBcmd1bWVudHMgPSB7XG4gIG1vZHVsZTogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiTmFtZSBvZiB0aGUgcmVtb3RlIG1vZHVsZShzKSB0byB1cGRhdGUuIFVzZSBjb21tYSBzZXBhcmF0b3IgdG8gc3BlY2lmeSBtdWx0aXBsZSBtb2R1bGVzLlwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIHVwZGF0ZVJlbW90ZU1vZHVsZXNBcmd1bWVudHNcblxuZXhwb3J0IGNsYXNzIFVwZGF0ZVJlbW90ZU1vZHVsZXNDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzPiB7XG4gIG5hbWUgPSBcIm1vZHVsZXNcIlxuICBoZWxwID0gXCJVcGRhdGUgcmVtb3RlIG1vZHVsZXMuXCJcbiAgYXJndW1lbnRzID0gdXBkYXRlUmVtb3RlTW9kdWxlc0FyZ3VtZW50c1xuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIFJlbW90ZSBtb2R1bGVzIGFyZSBtb2R1bGVzIHRoYXQgaGF2ZSBhIHJlcG9zaXRvcnlVcmwgZmllbGRcbiAgICBpbiB0aGVpciBnYXJkZW4ueW1sIGNvbmZpZyB0aGF0IHBvaW50cyB0byBhIHJlbW90ZSByZXBvc2l0b3J5LlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIHVwZGF0ZS1yZW1vdGUgbW9kdWxlcyAgICAgICAgICAgICMgdXBkYXRlIGFsbCByZW1vdGUgbW9kdWxlcyBpbiB0aGUgcHJvamVjdFxuICAgICAgICBnYXJkZW4gdXBkYXRlLXJlbW90ZSBtb2R1bGVzIG15LW1vZHVsZSAgIyB1cGRhdGUgcmVtb3RlIG1vZHVsZSBteS1tb2R1bGVcbiAgYFxuXG4gIGFzeW5jIGFjdGlvbihcbiAgICB7IGdhcmRlbiwgYXJncyB9OiBDb21tYW5kUGFyYW1zPEFyZ3M+LFxuICApOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ8U291cmNlQ29uZmlnW10+PiB7XG4gICAgZ2FyZGVuLmxvZy5oZWFkZXIoeyBlbW9qaTogXCJoYW1tZXJfYW5kX3dyZW5jaFwiLCBjb21tYW5kOiBcInVwZGF0ZS1yZW1vdGUgbW9kdWxlc1wiIH0pXG5cbiAgICBjb25zdCB7IG1vZHVsZSB9ID0gYXJnc1xuICAgIGNvbnN0IG1vZHVsZXMgPSBhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlcyhtb2R1bGUpXG5cbiAgICBjb25zdCBtb2R1bGVTb3VyY2VzID0gPFNvdXJjZUNvbmZpZ1tdPm1vZHVsZXNcbiAgICAgIC5maWx0ZXIoaGFzUmVtb3RlU291cmNlKVxuICAgICAgLmZpbHRlcihzcmMgPT4gbW9kdWxlID8gbW9kdWxlLmluY2x1ZGVzKHNyYy5uYW1lKSA6IHRydWUpXG5cbiAgICBjb25zdCBuYW1lcyA9IG1vZHVsZVNvdXJjZXMubWFwKHNyYyA9PiBzcmMubmFtZSlcblxuICAgIGNvbnN0IGRpZmYgPSBkaWZmZXJlbmNlKG1vZHVsZSwgbmFtZXMpXG4gICAgaWYgKGRpZmYubGVuZ3RoID4gMCkge1xuICAgICAgY29uc3QgbW9kdWxlc1dpdGhSZW1vdGVTb3VyY2UgPSAoYXdhaXQgZ2FyZGVuLmdldE1vZHVsZXMoKSkuZmlsdGVyKGhhc1JlbW90ZVNvdXJjZSkuc29ydCgpXG5cbiAgICAgIHRocm93IG5ldyBQYXJhbWV0ZXJFcnJvcihcbiAgICAgICAgYEV4cGVjdGVkIG1vZHVsZShzKSAke2NoYWxrLnVuZGVybGluZShkaWZmLmpvaW4oXCIsXCIpKX0gdG8gaGF2ZSBhIHJlbW90ZSBzb3VyY2UuYCxcbiAgICAgICAge1xuICAgICAgICAgIG1vZHVsZXNXaXRoUmVtb3RlU291cmNlLFxuICAgICAgICAgIGlucHV0OiBtb2R1bGUgPyBtb2R1bGUuc29ydCgpIDogdW5kZWZpbmVkLFxuICAgICAgICB9LFxuICAgICAgKVxuICAgIH1cblxuICAgIC8vIFRPRE8gVXBkYXRlIHJlbW90ZXMgaW4gcGFyYWxsZWwuIEN1cnJlbnRseSBub3QgcG9zc2libGUgc2luY2UgdXBkYXRpbmcgbWlnaHRcbiAgICAvLyB0cmlnZ2VyIGEgdXNlcm5hbWUgYW5kIHBhc3N3b3JkIHByb21wdCBmcm9tIGdpdC5cbiAgICBmb3IgKGNvbnN0IHsgbmFtZSwgcmVwb3NpdG9yeVVybCB9IG9mIG1vZHVsZVNvdXJjZXMpIHtcbiAgICAgIGF3YWl0IGdhcmRlbi52Y3MudXBkYXRlUmVtb3RlU291cmNlKHsgbmFtZSwgdXJsOiByZXBvc2l0b3J5VXJsLCBzb3VyY2VUeXBlOiBcIm1vZHVsZVwiLCBsb2dFbnRyeTogZ2FyZGVuLmxvZyB9KVxuICAgIH1cblxuICAgIGF3YWl0IHBydW5lUmVtb3RlU291cmNlcyh7IHByb2plY3RSb290OiBnYXJkZW4ucHJvamVjdFJvb3QsIHR5cGU6IFwibW9kdWxlXCIsIHNvdXJjZXM6IG1vZHVsZVNvdXJjZXMgfSlcblxuICAgIHJldHVybiB7IHJlc3VsdDogbW9kdWxlU291cmNlcyB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/update-remote/sources.d.ts b/garden-service/build/commands/update-remote/sources.d.ts new file mode 100644 index 00000000000..01f37f74312 --- /dev/null +++ b/garden-service/build/commands/update-remote/sources.d.ts @@ -0,0 +1,17 @@ +import { Command, StringsParameter, CommandResult, CommandParams } from "../base"; +import { SourceConfig } from "../../config/project"; +declare const updateRemoteSourcesArguments: { + source: StringsParameter; +}; +declare type Args = typeof updateRemoteSourcesArguments; +export declare class UpdateRemoteSourcesCommand extends Command { + name: string; + help: string; + arguments: { + source: StringsParameter; + }; + description: string; + action({ garden, args }: CommandParams): Promise>; +} +export {}; +//# sourceMappingURL=sources.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/update-remote/sources.js b/garden-service/build/commands/update-remote/sources.js new file mode 100644 index 00000000000..2b6b36c08de --- /dev/null +++ b/garden-service/build/commands/update-remote/sources.js @@ -0,0 +1,71 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const dedent = require("dedent"); +const chalk_1 = require("chalk"); +const base_1 = require("../base"); +const exceptions_1 = require("../../exceptions"); +const helpers_1 = require("./helpers"); +const updateRemoteSourcesArguments = { + source: new base_1.StringsParameter({ + help: "Name of the remote source(s) to update. Use comma separator to specify multiple sources.", + }), +}; +class UpdateRemoteSourcesCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "sources"; + this.help = "Update remote sources."; + this.arguments = updateRemoteSourcesArguments; + this.description = dedent ` + Update the remote sources declared in the project config. + + Examples: + + garden update-remote sources # update all remote sources in the project config + garden update-remote sources my-source # update remote source my-source + `; + } + action({ garden, args }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "hammer_and_wrench", command: "update-remote sources" }); + const { source } = args; + const projectSources = garden.projectSources + .filter(src => source ? source.includes(src.name) : true); + const names = projectSources.map(src => src.name); + // TODO: Make external modules a cli type to avoid validation repetition + const diff = lodash_1.difference(source, names); + if (diff.length > 0) { + throw new exceptions_1.ParameterError(`Expected source(s) ${chalk_1.default.underline(diff.join(","))} to be specified in the project garden.yml config.`, { + remoteSources: garden.projectSources.map(s => s.name).sort(), + input: source ? source.sort() : undefined, + }); + } + // TODO Update remotes in parallel. Currently not possible since updating might + // trigger a username and password prompt from git. + for (const { name, repositoryUrl } of projectSources) { + yield garden.vcs.updateRemoteSource({ name, url: repositoryUrl, sourceType: "project", logEntry: garden.log }); + } + yield helpers_1.pruneRemoteSources({ projectRoot: garden.projectRoot, type: "project", sources: projectSources }); + return { result: projectSources }; + }); + } +} +exports.UpdateRemoteSourcesCommand = UpdateRemoteSourcesCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VwZGF0ZS1yZW1vdGUvc291cmNlcy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsbUNBQW1DO0FBQ25DLGlDQUFpQztBQUNqQyxpQ0FBeUI7QUFFekIsa0NBS2dCO0FBQ2hCLGlEQUFpRDtBQUNqRCx1Q0FBOEM7QUFHOUMsTUFBTSw0QkFBNEIsR0FBRztJQUNuQyxNQUFNLEVBQUUsSUFBSSx1QkFBZ0IsQ0FBQztRQUMzQixJQUFJLEVBQUUsMEZBQTBGO0tBQ2pHLENBQUM7Q0FDSCxDQUFBO0FBSUQsTUFBYSwwQkFBMkIsU0FBUSxjQUFhO0lBQTdEOztRQUNFLFNBQUksR0FBRyxTQUFTLENBQUE7UUFDaEIsU0FBSSxHQUFHLHdCQUF3QixDQUFBO1FBQy9CLGNBQVMsR0FBRyw0QkFBNEIsQ0FBQTtRQUV4QyxnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7Ozs7OztHQU9uQixDQUFBO0lBb0NILENBQUM7SUFsQ08sTUFBTSxDQUNWLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBdUI7O1lBRXJDLE1BQU0sQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLEVBQUUsS0FBSyxFQUFFLG1CQUFtQixFQUFFLE9BQU8sRUFBRSx1QkFBdUIsRUFBRSxDQUFDLENBQUE7WUFFbkYsTUFBTSxFQUFFLE1BQU0sRUFBRSxHQUFHLElBQUksQ0FBQTtZQUV2QixNQUFNLGNBQWMsR0FBRyxNQUFNLENBQUMsY0FBYztpQkFDekMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUE7WUFFM0QsTUFBTSxLQUFLLEdBQUcsY0FBYyxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsQ0FBQTtZQUVqRCx3RUFBd0U7WUFDeEUsTUFBTSxJQUFJLEdBQUcsbUJBQVUsQ0FBQyxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDdEMsSUFBSSxJQUFJLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtnQkFDbkIsTUFBTSxJQUFJLDJCQUFjLENBQ3RCLHNCQUFzQixlQUFLLENBQUMsU0FBUyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsb0RBQW9ELEVBQ3pHO29CQUNFLGFBQWEsRUFBRSxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLEVBQUU7b0JBQzVELEtBQUssRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUztpQkFDMUMsQ0FDRixDQUFBO2FBQ0Y7WUFFRCwrRUFBK0U7WUFDL0UsbURBQW1EO1lBQ25ELEtBQUssTUFBTSxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsSUFBSSxjQUFjLEVBQUU7Z0JBQ3BELE1BQU0sTUFBTSxDQUFDLEdBQUcsQ0FBQyxrQkFBa0IsQ0FBQyxFQUFFLElBQUksRUFBRSxHQUFHLEVBQUUsYUFBYSxFQUFFLFVBQVUsRUFBRSxTQUFTLEVBQUUsUUFBUSxFQUFFLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO2FBQy9HO1lBRUQsTUFBTSw0QkFBa0IsQ0FBQyxFQUFFLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVyxFQUFFLElBQUksRUFBRSxTQUFTLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUE7WUFFdkcsT0FBTyxFQUFFLE1BQU0sRUFBRSxjQUFjLEVBQUUsQ0FBQTtRQUNuQyxDQUFDO0tBQUE7Q0FDRjtBQWhERCxnRUFnREMiLCJmaWxlIjoiY29tbWFuZHMvdXBkYXRlLXJlbW90ZS9zb3VyY2VzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGRpZmZlcmVuY2UgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcblxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgU3RyaW5nc1BhcmFtZXRlcixcbiAgQ29tbWFuZFJlc3VsdCxcbiAgQ29tbWFuZFBhcmFtcyxcbn0gZnJvbSBcIi4uL2Jhc2VcIlxuaW1wb3J0IHsgUGFyYW1ldGVyRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBwcnVuZVJlbW90ZVNvdXJjZXMgfSBmcm9tIFwiLi9oZWxwZXJzXCJcbmltcG9ydCB7IFNvdXJjZUNvbmZpZyB9IGZyb20gXCIuLi8uLi9jb25maWcvcHJvamVjdFwiXG5cbmNvbnN0IHVwZGF0ZVJlbW90ZVNvdXJjZXNBcmd1bWVudHMgPSB7XG4gIHNvdXJjZTogbmV3IFN0cmluZ3NQYXJhbWV0ZXIoe1xuICAgIGhlbHA6IFwiTmFtZSBvZiB0aGUgcmVtb3RlIHNvdXJjZShzKSB0byB1cGRhdGUuIFVzZSBjb21tYSBzZXBhcmF0b3IgdG8gc3BlY2lmeSBtdWx0aXBsZSBzb3VyY2VzLlwiLFxuICB9KSxcbn1cblxudHlwZSBBcmdzID0gdHlwZW9mIHVwZGF0ZVJlbW90ZVNvdXJjZXNBcmd1bWVudHNcblxuZXhwb3J0IGNsYXNzIFVwZGF0ZVJlbW90ZVNvdXJjZXNDb21tYW5kIGV4dGVuZHMgQ29tbWFuZDxBcmdzPiB7XG4gIG5hbWUgPSBcInNvdXJjZXNcIlxuICBoZWxwID0gXCJVcGRhdGUgcmVtb3RlIHNvdXJjZXMuXCJcbiAgYXJndW1lbnRzID0gdXBkYXRlUmVtb3RlU291cmNlc0FyZ3VtZW50c1xuXG4gIGRlc2NyaXB0aW9uID0gZGVkZW50YFxuICAgIFVwZGF0ZSB0aGUgcmVtb3RlIHNvdXJjZXMgZGVjbGFyZWQgaW4gdGhlIHByb2plY3QgY29uZmlnLlxuXG4gICAgRXhhbXBsZXM6XG5cbiAgICAgICAgZ2FyZGVuIHVwZGF0ZS1yZW1vdGUgc291cmNlcyAgICAgICAgICAgICMgdXBkYXRlIGFsbCByZW1vdGUgc291cmNlcyBpbiB0aGUgcHJvamVjdCBjb25maWdcbiAgICAgICAgZ2FyZGVuIHVwZGF0ZS1yZW1vdGUgc291cmNlcyBteS1zb3VyY2UgICMgdXBkYXRlIHJlbW90ZSBzb3VyY2UgbXktc291cmNlXG4gIGBcblxuICBhc3luYyBhY3Rpb24oXG4gICAgeyBnYXJkZW4sIGFyZ3MgfTogQ29tbWFuZFBhcmFtczxBcmdzPixcbiAgKTogUHJvbWlzZTxDb21tYW5kUmVzdWx0PFNvdXJjZUNvbmZpZ1tdPj4ge1xuICAgIGdhcmRlbi5sb2cuaGVhZGVyKHsgZW1vamk6IFwiaGFtbWVyX2FuZF93cmVuY2hcIiwgY29tbWFuZDogXCJ1cGRhdGUtcmVtb3RlIHNvdXJjZXNcIiB9KVxuXG4gICAgY29uc3QgeyBzb3VyY2UgfSA9IGFyZ3NcblxuICAgIGNvbnN0IHByb2plY3RTb3VyY2VzID0gZ2FyZGVuLnByb2plY3RTb3VyY2VzXG4gICAgICAuZmlsdGVyKHNyYyA9PiBzb3VyY2UgPyBzb3VyY2UuaW5jbHVkZXMoc3JjLm5hbWUpIDogdHJ1ZSlcblxuICAgIGNvbnN0IG5hbWVzID0gcHJvamVjdFNvdXJjZXMubWFwKHNyYyA9PiBzcmMubmFtZSlcblxuICAgIC8vIFRPRE86IE1ha2UgZXh0ZXJuYWwgbW9kdWxlcyBhIGNsaSB0eXBlIHRvIGF2b2lkIHZhbGlkYXRpb24gcmVwZXRpdGlvblxuICAgIGNvbnN0IGRpZmYgPSBkaWZmZXJlbmNlKHNvdXJjZSwgbmFtZXMpXG4gICAgaWYgKGRpZmYubGVuZ3RoID4gMCkge1xuICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKFxuICAgICAgICBgRXhwZWN0ZWQgc291cmNlKHMpICR7Y2hhbGsudW5kZXJsaW5lKGRpZmYuam9pbihcIixcIikpfSB0byBiZSBzcGVjaWZpZWQgaW4gdGhlIHByb2plY3QgZ2FyZGVuLnltbCBjb25maWcuYCxcbiAgICAgICAge1xuICAgICAgICAgIHJlbW90ZVNvdXJjZXM6IGdhcmRlbi5wcm9qZWN0U291cmNlcy5tYXAocyA9PiBzLm5hbWUpLnNvcnQoKSxcbiAgICAgICAgICBpbnB1dDogc291cmNlID8gc291cmNlLnNvcnQoKSA6IHVuZGVmaW5lZCxcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9XG5cbiAgICAvLyBUT0RPIFVwZGF0ZSByZW1vdGVzIGluIHBhcmFsbGVsLiBDdXJyZW50bHkgbm90IHBvc3NpYmxlIHNpbmNlIHVwZGF0aW5nIG1pZ2h0XG4gICAgLy8gdHJpZ2dlciBhIHVzZXJuYW1lIGFuZCBwYXNzd29yZCBwcm9tcHQgZnJvbSBnaXQuXG4gICAgZm9yIChjb25zdCB7IG5hbWUsIHJlcG9zaXRvcnlVcmwgfSBvZiBwcm9qZWN0U291cmNlcykge1xuICAgICAgYXdhaXQgZ2FyZGVuLnZjcy51cGRhdGVSZW1vdGVTb3VyY2UoeyBuYW1lLCB1cmw6IHJlcG9zaXRvcnlVcmwsIHNvdXJjZVR5cGU6IFwicHJvamVjdFwiLCBsb2dFbnRyeTogZ2FyZGVuLmxvZyB9KVxuICAgIH1cblxuICAgIGF3YWl0IHBydW5lUmVtb3RlU291cmNlcyh7IHByb2plY3RSb290OiBnYXJkZW4ucHJvamVjdFJvb3QsIHR5cGU6IFwicHJvamVjdFwiLCBzb3VyY2VzOiBwcm9qZWN0U291cmNlcyB9KVxuXG4gICAgcmV0dXJuIHsgcmVzdWx0OiBwcm9qZWN0U291cmNlcyB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/commands/update-remote/update-remote.d.ts b/garden-service/build/commands/update-remote/update-remote.d.ts new file mode 100644 index 00000000000..0c31ea61ee3 --- /dev/null +++ b/garden-service/build/commands/update-remote/update-remote.d.ts @@ -0,0 +1,11 @@ +import { Command } from "../base"; +import { UpdateRemoteSourcesCommand } from "./sources"; +import { UpdateRemoteModulesCommand } from "./modules"; +import { UpdateRemoteAllCommand } from "./all"; +export declare class UpdateRemoteCommand extends Command { + name: string; + help: string; + subCommands: (typeof UpdateRemoteSourcesCommand | typeof UpdateRemoteModulesCommand | typeof UpdateRemoteAllCommand)[]; + action(): Promise<{}>; +} +//# sourceMappingURL=update-remote.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/update-remote/update-remote.js b/garden-service/build/commands/update-remote/update-remote.js new file mode 100644 index 00000000000..861bb734fc4 --- /dev/null +++ b/garden-service/build/commands/update-remote/update-remote.js @@ -0,0 +1,39 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("../base"); +const sources_1 = require("./sources"); +const modules_1 = require("./modules"); +const all_1 = require("./all"); +class UpdateRemoteCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "update-remote"; + this.help = "Pulls the latest version of remote sources or modules from their repository"; + this.subCommands = [ + sources_1.UpdateRemoteSourcesCommand, + modules_1.UpdateRemoteModulesCommand, + all_1.UpdateRemoteAllCommand, + ]; + } + action() { + return __awaiter(this, void 0, void 0, function* () { return {}; }); + } +} +exports.UpdateRemoteCommand = UpdateRemoteCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3VwZGF0ZS1yZW1vdGUvdXBkYXRlLXJlbW90ZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsa0NBQWlDO0FBQ2pDLHVDQUFzRDtBQUN0RCx1Q0FBc0Q7QUFDdEQsK0JBQThDO0FBRTlDLE1BQWEsbUJBQW9CLFNBQVEsY0FBTztJQUFoRDs7UUFDRSxTQUFJLEdBQUcsZUFBZSxDQUFBO1FBQ3RCLFNBQUksR0FBRyw2RUFBNkUsQ0FBQTtRQUVwRixnQkFBVyxHQUFHO1lBQ1osb0NBQTBCO1lBQzFCLG9DQUEwQjtZQUMxQiw0QkFBc0I7U0FDdkIsQ0FBQTtJQUdILENBQUM7SUFETyxNQUFNOzhEQUFLLE9BQU8sRUFBRSxDQUFBLENBQUMsQ0FBQztLQUFBO0NBQzdCO0FBWEQsa0RBV0MiLCJmaWxlIjoiY29tbWFuZHMvdXBkYXRlLXJlbW90ZS91cGRhdGUtcmVtb3RlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IENvbW1hbmQgfSBmcm9tIFwiLi4vYmFzZVwiXG5pbXBvcnQgeyBVcGRhdGVSZW1vdGVTb3VyY2VzQ29tbWFuZCB9IGZyb20gXCIuL3NvdXJjZXNcIlxuaW1wb3J0IHsgVXBkYXRlUmVtb3RlTW9kdWxlc0NvbW1hbmQgfSBmcm9tIFwiLi9tb2R1bGVzXCJcbmltcG9ydCB7IFVwZGF0ZVJlbW90ZUFsbENvbW1hbmQgfSBmcm9tIFwiLi9hbGxcIlxuXG5leHBvcnQgY2xhc3MgVXBkYXRlUmVtb3RlQ29tbWFuZCBleHRlbmRzIENvbW1hbmQge1xuICBuYW1lID0gXCJ1cGRhdGUtcmVtb3RlXCJcbiAgaGVscCA9IFwiUHVsbHMgdGhlIGxhdGVzdCB2ZXJzaW9uIG9mIHJlbW90ZSBzb3VyY2VzIG9yIG1vZHVsZXMgZnJvbSB0aGVpciByZXBvc2l0b3J5XCJcblxuICBzdWJDb21tYW5kcyA9IFtcbiAgICBVcGRhdGVSZW1vdGVTb3VyY2VzQ29tbWFuZCxcbiAgICBVcGRhdGVSZW1vdGVNb2R1bGVzQ29tbWFuZCxcbiAgICBVcGRhdGVSZW1vdGVBbGxDb21tYW5kLFxuICBdXG5cbiAgYXN5bmMgYWN0aW9uKCkgeyByZXR1cm4ge30gfVxufVxuIl19 diff --git a/garden-service/build/commands/validate.d.ts b/garden-service/build/commands/validate.d.ts new file mode 100644 index 00000000000..eecb85ba8df --- /dev/null +++ b/garden-service/build/commands/validate.d.ts @@ -0,0 +1,8 @@ +import { Command, CommandParams, CommandResult } from "./base"; +export declare class ValidateCommand extends Command { + name: string; + help: string; + description: string; + action({ garden }: CommandParams): Promise; +} +//# sourceMappingURL=validate.d.ts.map \ No newline at end of file diff --git a/garden-service/build/commands/validate.js b/garden-service/build/commands/validate.js new file mode 100644 index 00000000000..ab6fbb09d50 --- /dev/null +++ b/garden-service/build/commands/validate.js @@ -0,0 +1,39 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const base_1 = require("./base"); +const dedent = require("dedent"); +class ValidateCommand extends base_1.Command { + constructor() { + super(...arguments); + this.name = "validate"; + this.help = "Check your garden configuration for errors."; + this.description = dedent ` + Throws an error and exits with code 1 if something's not right in your garden.yml files. + `; + } + action({ garden }) { + return __awaiter(this, void 0, void 0, function* () { + garden.log.header({ emoji: "heavy_check_mark", command: "validate" }); + yield garden.getModules(); + return {}; + }); + } +} +exports.ValidateCommand = ValidateCommand; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbW1hbmRzL3ZhbGlkYXRlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxpQ0FJZTtBQUNmLGlDQUFpQztBQUVqQyxNQUFhLGVBQWdCLFNBQVEsY0FBTztJQUE1Qzs7UUFDRSxTQUFJLEdBQUcsVUFBVSxDQUFBO1FBQ2pCLFNBQUksR0FBRyw2Q0FBNkMsQ0FBQTtRQUVwRCxnQkFBVyxHQUFHLE1BQU0sQ0FBQTs7R0FFbkIsQ0FBQTtJQVNILENBQUM7SUFQTyxNQUFNLENBQUMsRUFBRSxNQUFNLEVBQWlCOztZQUNwQyxNQUFNLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxFQUFFLEtBQUssRUFBRSxrQkFBa0IsRUFBRSxPQUFPLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQTtZQUVyRSxNQUFNLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQTtZQUV6QixPQUFPLEVBQUUsQ0FBQTtRQUNYLENBQUM7S0FBQTtDQUNGO0FBZkQsMENBZUMiLCJmaWxlIjoiY29tbWFuZHMvdmFsaWRhdGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHtcbiAgQ29tbWFuZCxcbiAgQ29tbWFuZFBhcmFtcyxcbiAgQ29tbWFuZFJlc3VsdCxcbn0gZnJvbSBcIi4vYmFzZVwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5leHBvcnQgY2xhc3MgVmFsaWRhdGVDb21tYW5kIGV4dGVuZHMgQ29tbWFuZCB7XG4gIG5hbWUgPSBcInZhbGlkYXRlXCJcbiAgaGVscCA9IFwiQ2hlY2sgeW91ciBnYXJkZW4gY29uZmlndXJhdGlvbiBmb3IgZXJyb3JzLlwiXG5cbiAgZGVzY3JpcHRpb24gPSBkZWRlbnRgXG4gICAgVGhyb3dzIGFuIGVycm9yIGFuZCBleGl0cyB3aXRoIGNvZGUgMSBpZiBzb21ldGhpbmcncyBub3QgcmlnaHQgaW4geW91ciBnYXJkZW4ueW1sIGZpbGVzLlxuICBgXG5cbiAgYXN5bmMgYWN0aW9uKHsgZ2FyZGVuIH06IENvbW1hbmRQYXJhbXMpOiBQcm9taXNlPENvbW1hbmRSZXN1bHQ+IHtcbiAgICBnYXJkZW4ubG9nLmhlYWRlcih7IGVtb2ppOiBcImhlYXZ5X2NoZWNrX21hcmtcIiwgY29tbWFuZDogXCJ2YWxpZGF0ZVwiIH0pXG5cbiAgICBhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlcygpXG5cbiAgICByZXR1cm4ge31cbiAgfVxufVxuIl19 diff --git a/garden-service/build/config-store.d.ts b/garden-service/build/config-store.d.ts new file mode 100644 index 00000000000..b19aa01ef34 --- /dev/null +++ b/garden-service/build/config-store.d.ts @@ -0,0 +1,52 @@ +import { Primitive } from "./config/common"; +export declare type ConfigValue = Primitive | Primitive[] | Object[]; +export declare type SetManyParam = { + keyPath: Array; + value: ConfigValue; +}[]; +export declare abstract class ConfigStore { + private config; + protected configPath: string; + constructor(projectPath: string); + abstract getConfigPath(projectPath: string): string; + abstract validate(config: any): T; + /** + * Would've been nice to allow something like: set(["path", "to", "valA", valA], ["path", "to", "valB", valB]...) + * but Typescript support is missing at the moment + */ + set(param: SetManyParam): any; + set(keyPath: string[], value: ConfigValue): any; + get(): Promise; + get(keyPath: string[]): Promise; + clear(): Promise; + delete(keyPath: string[]): Promise; + private getConfig; + private updateConfig; + private ensureConfigFile; + private loadConfig; + private saveConfig; + private throwKeyNotFound; +} +export interface KubernetesLocalConfig { + username?: string; + "previous-usernames"?: Array; +} +export interface LinkedSource { + name: string; + path: string; +} +export interface LocalConfig { + kubernetes?: KubernetesLocalConfig; + linkedModuleSources?: LinkedSource[]; + linkedProjectSources?: LinkedSource[]; +} +export declare const localConfigKeys: { + kubernetes: "kubernetes"; + linkedModuleSources: "linkedModuleSources"; + linkedProjectSources: "linkedProjectSources"; +}; +export declare class LocalConfigStore extends ConfigStore { + getConfigPath(projectPath: any): string; + validate(config: any): LocalConfig; +} +//# sourceMappingURL=config-store.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config-store.js b/garden-service/build/config-store.js new file mode 100644 index 00000000000..011ebc92acc --- /dev/null +++ b/garden-service/build/config-store.js @@ -0,0 +1,174 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const yaml = require("js-yaml"); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const lodash_1 = require("lodash"); +const common_1 = require("./config/common"); +const exceptions_1 = require("./exceptions"); +const util_1 = require("./util/util"); +const constants_1 = require("./constants"); +class ConfigStore { + constructor(projectPath) { + this.configPath = this.getConfigPath(projectPath); + this.config = null; + } + set(...args) { + return __awaiter(this, void 0, void 0, function* () { + let config = yield this.getConfig(); + let entries; + if (args.length === 1) { + entries = args[0]; + } + else { + entries = [{ keyPath: args[0], value: args[1] }]; + } + for (const { keyPath, value } of entries) { + config = this.updateConfig(config, keyPath, value); + } + yield this.saveConfig(config); + }); + } + get(keyPath) { + return __awaiter(this, void 0, void 0, function* () { + const config = yield this.getConfig(); + if (keyPath) { + const value = lodash_1.get(config, keyPath); + if (value === undefined) { + this.throwKeyNotFound(config, keyPath); + } + return value; + } + return config; + }); + } + clear() { + return __awaiter(this, void 0, void 0, function* () { + yield this.saveConfig({}); + }); + } + delete(keyPath) { + return __awaiter(this, void 0, void 0, function* () { + let config = yield this.getConfig(); + if (lodash_1.get(config, keyPath) === undefined) { + this.throwKeyNotFound(config, keyPath); + } + const success = lodash_1.unset(config, keyPath); + if (!success) { + throw new exceptions_1.LocalConfigError(`Unable to delete key ${keyPath.join(".")} in user config`, { + keyPath, + config, + }); + } + yield this.saveConfig(config); + }); + } + getConfig() { + return __awaiter(this, void 0, void 0, function* () { + if (!this.config) { + yield this.loadConfig(); + } + // Spreading does not work on generic types, see: https://github.com/Microsoft/TypeScript/issues/13557 + return Object.assign(this.config, {}); + }); + } + updateConfig(config, keyPath, value) { + let currentValue = config; + for (let i = 0; i < keyPath.length; i++) { + const k = keyPath[i]; + if (i === keyPath.length - 1) { + currentValue[k] = value; + } + else if (currentValue[k] === undefined) { + currentValue[k] = {}; + } + else if (!lodash_1.isPlainObject(currentValue[k])) { + const path = keyPath.slice(i + 1).join("."); + throw new exceptions_1.LocalConfigError(`Attempting to assign a nested key on non-object (current value at ${path}: ${currentValue[k]})`, { + currentValue: currentValue[k], + path, + }); + } + currentValue = currentValue[k]; + } + return config; + } + ensureConfigFile() { + return __awaiter(this, void 0, void 0, function* () { + yield fs_extra_1.ensureFile(this.configPath); + }); + } + loadConfig() { + return __awaiter(this, void 0, void 0, function* () { + yield this.ensureConfigFile(); + const config = (yield yaml.safeLoad((yield fs_extra_1.readFile(this.configPath)).toString())) || {}; + this.config = this.validate(config); + }); + } + saveConfig(config) { + return __awaiter(this, void 0, void 0, function* () { + this.config = null; + const validated = this.validate(config); + yield util_1.dumpYaml(this.configPath, validated); + this.config = validated; + }); + } + throwKeyNotFound(config, keyPath) { + throw new exceptions_1.LocalConfigError(`Could not find key ${keyPath.join(".")} in user config`, { + keyPath, + config, + }); + } +} +exports.ConfigStore = ConfigStore; +const kubernetesLocalConfigSchema = Joi.object() + .keys({ + username: common_1.joiIdentifier().allow("").optional(), + "previous-usernames": Joi.array().items(common_1.joiIdentifier()).optional(), +}) + .meta({ internal: true }); +const linkedSourceSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier(), + path: Joi.string(), +}) + .meta({ internal: true }); +const localConfigSchemaKeys = { + kubernetes: kubernetesLocalConfigSchema, + linkedModuleSources: common_1.joiArray(linkedSourceSchema), + linkedProjectSources: common_1.joiArray(linkedSourceSchema), +}; +exports.localConfigKeys = Object.keys(localConfigSchemaKeys).reduce((acc, key) => { + acc[key] = key; + return acc; +}, {}); +const localConfigSchema = Joi.object() + .keys(localConfigSchemaKeys) + .meta({ internal: true }); +class LocalConfigStore extends ConfigStore { + getConfigPath(projectPath) { + return path_1.resolve(projectPath, constants_1.GARDEN_DIR_NAME, constants_1.LOCAL_CONFIG_FILENAME); + } + validate(config) { + return common_1.validate(config, localConfigSchema, { context: this.configPath, ErrorClass: exceptions_1.LocalConfigError }); + } +} +exports.LocalConfigStore = LocalConfigStore; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUMzRCxDQUFBO0lBQ0gsQ0FBQztDQUVGO0FBZEQsNENBY0MiLCJmaWxlIjoiY29uZmlnLXN0b3JlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCAqIGFzIHlhbWwgZnJvbSBcImpzLXlhbWxcIlxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IGVuc3VyZUZpbGUsIHJlYWRGaWxlIH0gZnJvbSBcImZzLWV4dHJhXCJcbmltcG9ydCB7IGdldCwgaXNQbGFpbk9iamVjdCwgdW5zZXQgfSBmcm9tIFwibG9kYXNoXCJcblxuaW1wb3J0IHsgam9pSWRlbnRpZmllciwgUHJpbWl0aXZlLCB2YWxpZGF0ZSwgam9pQXJyYXkgfSBmcm9tIFwiLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IExvY2FsQ29uZmlnRXJyb3IgfSBmcm9tIFwiLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IGR1bXBZYW1sIH0gZnJvbSBcIi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IEdBUkRFTl9ESVJfTkFNRSwgTE9DQUxfQ09ORklHX0ZJTEVOQU1FIH0gZnJvbSBcIi4vY29uc3RhbnRzXCJcblxuZXhwb3J0IHR5cGUgQ29uZmlnVmFsdWUgPSBQcmltaXRpdmUgfCBQcmltaXRpdmVbXSB8IE9iamVjdFtdXG5cbmV4cG9ydCB0eXBlIFNldE1hbnlQYXJhbSA9IHsga2V5UGF0aDogQXJyYXk8c3RyaW5nPiwgdmFsdWU6IENvbmZpZ1ZhbHVlIH1bXVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ29uZmlnU3RvcmU8VCBleHRlbmRzIG9iamVjdCA9IGFueT4ge1xuICBwcml2YXRlIGNvbmZpZzogbnVsbCB8IFRcbiAgcHJvdGVjdGVkIGNvbmZpZ1BhdGg6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHByb2plY3RQYXRoOiBzdHJpbmcpIHtcbiAgICB0aGlzLmNvbmZpZ1BhdGggPSB0aGlzLmdldENvbmZpZ1BhdGgocHJvamVjdFBhdGgpXG4gICAgdGhpcy5jb25maWcgPSBudWxsXG4gIH1cblxuICBhYnN0cmFjdCBnZXRDb25maWdQYXRoKHByb2plY3RQYXRoOiBzdHJpbmcpOiBzdHJpbmdcbiAgYWJzdHJhY3QgdmFsaWRhdGUoY29uZmlnKTogVFxuXG4gIC8qKlxuICAgKiBXb3VsZCd2ZSBiZWVuIG5pY2UgdG8gYWxsb3cgc29tZXRoaW5nIGxpa2U6IHNldChbXCJwYXRoXCIsIFwidG9cIiwgXCJ2YWxBXCIsIHZhbEFdLCBbXCJwYXRoXCIsIFwidG9cIiwgXCJ2YWxCXCIsIHZhbEJdLi4uKVxuICAgKiBidXQgVHlwZXNjcmlwdCBzdXBwb3J0IGlzIG1pc3NpbmcgYXQgdGhlIG1vbWVudFxuICAgKi9cbiAgcHVibGljIGFzeW5jIHNldChwYXJhbTogU2V0TWFueVBhcmFtKVxuICBwdWJsaWMgYXN5bmMgc2V0KGtleVBhdGg6IHN0cmluZ1tdLCB2YWx1ZTogQ29uZmlnVmFsdWUpXG4gIHB1YmxpYyBhc3luYyBzZXQoLi4uYXJncykge1xuICAgIGxldCBjb25maWcgPSBhd2FpdCB0aGlzLmdldENvbmZpZygpXG4gICAgbGV0IGVudHJpZXM6IFNldE1hbnlQYXJhbVxuXG4gICAgaWYgKGFyZ3MubGVuZ3RoID09PSAxKSB7XG4gICAgICBlbnRyaWVzID0gYXJnc1swXVxuICAgIH0gZWxzZSB7XG4gICAgICBlbnRyaWVzID0gW3sga2V5UGF0aDogYXJnc1swXSwgdmFsdWU6IGFyZ3NbMV0gfV1cbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IHsga2V5UGF0aCwgdmFsdWUgfSBvZiBlbnRyaWVzKSB7XG4gICAgICBjb25maWcgPSB0aGlzLnVwZGF0ZUNvbmZpZyhjb25maWcsIGtleVBhdGgsIHZhbHVlKVxuICAgIH1cblxuICAgIGF3YWl0IHRoaXMuc2F2ZUNvbmZpZyhjb25maWcpXG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZ2V0KCk6IFByb21pc2U8VD5cbiAgcHVibGljIGFzeW5jIGdldChrZXlQYXRoOiBzdHJpbmdbXSk6IFByb21pc2U8T2JqZWN0IHwgQ29uZmlnVmFsdWU+XG4gIHB1YmxpYyBhc3luYyBnZXQoa2V5UGF0aD86IHN0cmluZ1tdKTogUHJvbWlzZTxPYmplY3QgfCBDb25maWdWYWx1ZT4ge1xuICAgIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHRoaXMuZ2V0Q29uZmlnKClcblxuICAgIGlmIChrZXlQYXRoKSB7XG4gICAgICBjb25zdCB2YWx1ZSA9IGdldChjb25maWcsIGtleVBhdGgpXG5cbiAgICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICAgIHRoaXMudGhyb3dLZXlOb3RGb3VuZChjb25maWcsIGtleVBhdGgpXG4gICAgICB9XG5cbiAgICAgIHJldHVybiB2YWx1ZVxuICAgIH1cblxuICAgIHJldHVybiBjb25maWdcbiAgfVxuXG4gIHB1YmxpYyBhc3luYyBjbGVhcigpIHtcbiAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoPFQ+e30pXG4gIH1cblxuICBwdWJsaWMgYXN5bmMgZGVsZXRlKGtleVBhdGg6IHN0cmluZ1tdKSB7XG4gICAgbGV0IGNvbmZpZyA9IGF3YWl0IHRoaXMuZ2V0Q29uZmlnKClcbiAgICBpZiAoZ2V0KGNvbmZpZywga2V5UGF0aCkgPT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy50aHJvd0tleU5vdEZvdW5kKGNvbmZpZywga2V5UGF0aClcbiAgICB9XG4gICAgY29uc3Qgc3VjY2VzcyA9IHVuc2V0KGNvbmZpZywga2V5UGF0aClcbiAgICBpZiAoIXN1Y2Nlc3MpIHtcbiAgICAgIHRocm93IG5ldyBMb2NhbENvbmZpZ0Vycm9yKGBVbmFibGUgdG8gZGVsZXRlIGtleSAke2tleVBhdGguam9pbihcIi5cIil9IGluIHVzZXIgY29uZmlnYCwge1xuICAgICAgICBrZXlQYXRoLFxuICAgICAgICBjb25maWcsXG4gICAgICB9KVxuICAgIH1cbiAgICBhd2FpdCB0aGlzLnNhdmVDb25maWcoY29uZmlnKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBnZXRDb25maWcoKTogUHJvbWlzZTxUPiB7XG4gICAgaWYgKCF0aGlzLmNvbmZpZykge1xuICAgICAgYXdhaXQgdGhpcy5sb2FkQ29uZmlnKClcbiAgICB9XG4gICAgLy8gU3ByZWFkaW5nIGRvZXMgbm90IHdvcmsgb24gZ2VuZXJpYyB0eXBlcywgc2VlOiBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L1R5cGVTY3JpcHQvaXNzdWVzLzEzNTU3XG4gICAgcmV0dXJuIE9iamVjdC5hc3NpZ24odGhpcy5jb25maWcsIHt9KVxuXG4gIH1cblxuICBwcml2YXRlIHVwZGF0ZUNvbmZpZyhjb25maWc6IFQsIGtleVBhdGg6IHN0cmluZ1tdLCB2YWx1ZTogQ29uZmlnVmFsdWUpOiBUIHtcbiAgICBsZXQgY3VycmVudFZhbHVlID0gY29uZmlnXG5cbiAgICBmb3IgKGxldCBpID0gMDsgaSA8IGtleVBhdGgubGVuZ3RoOyBpKyspIHtcbiAgICAgIGNvbnN0IGsgPSBrZXlQYXRoW2ldXG5cbiAgICAgIGlmIChpID09PSBrZXlQYXRoLmxlbmd0aCAtIDEpIHtcbiAgICAgICAgY3VycmVudFZhbHVlW2tdID0gdmFsdWVcbiAgICAgIH0gZWxzZSBpZiAoY3VycmVudFZhbHVlW2tdID09PSB1bmRlZmluZWQpIHtcbiAgICAgICAgY3VycmVudFZhbHVlW2tdID0ge31cbiAgICAgIH0gZWxzZSBpZiAoIWlzUGxhaW5PYmplY3QoY3VycmVudFZhbHVlW2tdKSkge1xuICAgICAgICBjb25zdCBwYXRoID0ga2V5UGF0aC5zbGljZShpICsgMSkuam9pbihcIi5cIilcblxuICAgICAgICB0aHJvdyBuZXcgTG9jYWxDb25maWdFcnJvcihcbiAgICAgICAgICBgQXR0ZW1wdGluZyB0byBhc3NpZ24gYSBuZXN0ZWQga2V5IG9uIG5vbi1vYmplY3QgKGN1cnJlbnQgdmFsdWUgYXQgJHtwYXRofTogJHtjdXJyZW50VmFsdWVba119KWAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgY3VycmVudFZhbHVlOiBjdXJyZW50VmFsdWVba10sXG4gICAgICAgICAgICBwYXRoLFxuICAgICAgICAgIH0sXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgY3VycmVudFZhbHVlID0gY3VycmVudFZhbHVlW2tdXG4gICAgfVxuICAgIHJldHVybiBjb25maWdcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZW5zdXJlQ29uZmlnRmlsZSgpIHtcbiAgICBhd2FpdCBlbnN1cmVGaWxlKHRoaXMuY29uZmlnUGF0aClcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZENvbmZpZygpIHtcbiAgICBhd2FpdCB0aGlzLmVuc3VyZUNvbmZpZ0ZpbGUoKVxuICAgIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHlhbWwuc2FmZUxvYWQoKGF3YWl0IHJlYWRGaWxlKHRoaXMuY29uZmlnUGF0aCkpLnRvU3RyaW5nKCkpIHx8IHt9XG5cbiAgICB0aGlzLmNvbmZpZyA9IHRoaXMudmFsaWRhdGUoY29uZmlnKVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBzYXZlQ29uZmlnKGNvbmZpZzogVCkge1xuICAgIHRoaXMuY29uZmlnID0gbnVsbFxuICAgIGNvbnN0IHZhbGlkYXRlZCA9IHRoaXMudmFsaWRhdGUoY29uZmlnKVxuICAgIGF3YWl0IGR1bXBZYW1sKHRoaXMuY29uZmlnUGF0aCwgdmFsaWRhdGVkKVxuICAgIHRoaXMuY29uZmlnID0gdmFsaWRhdGVkXG4gIH1cblxuICBwcml2YXRlIHRocm93S2V5Tm90Rm91bmQoY29uZmlnOiBULCBrZXlQYXRoOiBzdHJpbmdbXSkge1xuICAgIHRocm93IG5ldyBMb2NhbENvbmZpZ0Vycm9yKGBDb3VsZCBub3QgZmluZCBrZXkgJHtrZXlQYXRoLmpvaW4oXCIuXCIpfSBpbiB1c2VyIGNvbmZpZ2AsIHtcbiAgICAgIGtleVBhdGgsXG4gICAgICBjb25maWcsXG4gICAgfSlcbiAgfVxuXG59XG5cbi8vIFRPRE86IENhbWVsIGNhc2UgcHJldmlvdXMgdXNlcm5hbWVzXG5leHBvcnQgaW50ZXJmYWNlIEt1YmVybmV0ZXNMb2NhbENvbmZpZyB7XG4gIHVzZXJuYW1lPzogc3RyaW5nXG4gIFwicHJldmlvdXMtdXNlcm5hbWVzXCI/OiBBcnJheTxzdHJpbmc+XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTGlua2VkU291cmNlIHtcbiAgbmFtZTogc3RyaW5nXG4gIHBhdGg6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIExvY2FsQ29uZmlnIHtcbiAga3ViZXJuZXRlcz86IEt1YmVybmV0ZXNMb2NhbENvbmZpZ1xuICBsaW5rZWRNb2R1bGVTb3VyY2VzPzogTGlua2VkU291cmNlW10gLy8gVE9ETyBVc2UgS2V5ZWRTZXQgaW5zdGVhZCBvZiBhcnJheVxuICBsaW5rZWRQcm9qZWN0U291cmNlcz86IExpbmtlZFNvdXJjZVtdXG59XG5cbmNvbnN0IGt1YmVybmV0ZXNMb2NhbENvbmZpZ1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgdXNlcm5hbWU6IGpvaUlkZW50aWZpZXIoKS5hbGxvdyhcIlwiKS5vcHRpb25hbCgpLFxuICAgIFwicHJldmlvdXMtdXNlcm5hbWVzXCI6IEpvaS5hcnJheSgpLml0ZW1zKGpvaUlkZW50aWZpZXIoKSkub3B0aW9uYWwoKSxcbiAgfSlcbiAgLm1ldGEoeyBpbnRlcm5hbDogdHJ1ZSB9KVxuXG5jb25zdCBsaW5rZWRTb3VyY2VTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIG5hbWU6IGpvaUlkZW50aWZpZXIoKSxcbiAgICBwYXRoOiBKb2kuc3RyaW5nKCksXG4gIH0pXG4gIC5tZXRhKHsgaW50ZXJuYWw6IHRydWUgfSlcblxuY29uc3QgbG9jYWxDb25maWdTY2hlbWFLZXlzID0ge1xuICBrdWJlcm5ldGVzOiBrdWJlcm5ldGVzTG9jYWxDb25maWdTY2hlbWEsXG4gIGxpbmtlZE1vZHVsZVNvdXJjZXM6IGpvaUFycmF5KGxpbmtlZFNvdXJjZVNjaGVtYSksXG4gIGxpbmtlZFByb2plY3RTb3VyY2VzOiBqb2lBcnJheShsaW5rZWRTb3VyY2VTY2hlbWEpLFxufVxuXG5leHBvcnQgY29uc3QgbG9jYWxDb25maWdLZXlzID0gT2JqZWN0LmtleXMobG9jYWxDb25maWdTY2hlbWFLZXlzKS5yZWR1Y2UoKGFjYywga2V5KSA9PiB7XG4gIGFjY1trZXldID0ga2V5XG4gIHJldHVybiBhY2Ncbn0sIHt9KSBhcyB7IFtLIGluIGtleW9mIHR5cGVvZiBsb2NhbENvbmZpZ1NjaGVtYUtleXNdOiBLIH1cblxuY29uc3QgbG9jYWxDb25maWdTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMobG9jYWxDb25maWdTY2hlbWFLZXlzKVxuICAubWV0YSh7IGludGVybmFsOiB0cnVlIH0pXG5cbmV4cG9ydCBjbGFzcyBMb2NhbENvbmZpZ1N0b3JlIGV4dGVuZHMgQ29uZmlnU3RvcmU8TG9jYWxDb25maWc+IHtcblxuICBnZXRDb25maWdQYXRoKHByb2plY3RQYXRoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gcmVzb2x2ZShwcm9qZWN0UGF0aCwgR0FSREVOX0RJUl9OQU1FLCBMT0NBTF9DT05GSUdfRklMRU5BTUUpXG4gIH1cblxuICB2YWxpZGF0ZShjb25maWcpOiBMb2NhbENvbmZpZyB7XG4gICAgcmV0dXJuIHZhbGlkYXRlKFxuICAgICAgY29uZmlnLFxuICAgICAgbG9jYWxDb25maWdTY2hlbWEsXG4gICAgICB7IGNvbnRleHQ6IHRoaXMuY29uZmlnUGF0aCwgRXJyb3JDbGFzczogTG9jYWxDb25maWdFcnJvciB9LFxuICAgIClcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/config/base.d.ts b/garden-service/build/config/base.d.ts new file mode 100644 index 00000000000..b5fb1d37363 --- /dev/null +++ b/garden-service/build/config/base.d.ts @@ -0,0 +1,14 @@ +import { ModuleConfig } from "./module"; +import * as Joi from "joi"; +import { ProjectConfig } from "../config/project"; +export interface GardenConfig { + version: string; + dirname: string; + path: string; + module?: ModuleConfig; + project?: ProjectConfig; +} +export declare const configSchema: Joi.ObjectSchema; +export declare function loadConfig(projectRoot: string, path: string): Promise; +export declare function findProjectConfig(path: string): Promise; +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/base.js b/garden-service/build/config/base.js new file mode 100644 index 00000000000..146d95022a8 --- /dev/null +++ b/garden-service/build/config/base.js @@ -0,0 +1,146 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const util_1 = require("../util/util"); +const module_1 = require("./module"); +const common_1 = require("./common"); +const exceptions_1 = require("../exceptions"); +const Joi = require("joi"); +const yaml = require("js-yaml"); +const fs_extra_1 = require("fs-extra"); +const project_1 = require("../config/project"); +const lodash_1 = require("lodash"); +const CONFIG_FILENAME = "garden.yml"; +exports.configSchema = Joi.object() + .keys({ + // TODO: should this be called apiVersion? + version: Joi.string() + .default("0") + .only("0") + .description("The schema version of the config file (currently not used)."), + dirname: Joi.string().meta({ internal: true }), + path: Joi.string().meta({ internal: true }), + module: module_1.baseModuleSpecSchema, + project: project_1.projectSchema, +}) + .optionalKeys(["module", "project"]) + .required() + .description("The garden.yml config file."); +const baseModuleSchemaKeys = Object.keys(module_1.baseModuleSpecSchema.describe().children); +function loadConfig(projectRoot, path) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: nicer error messages when load/validation fails + const absPath = path_1.join(path, CONFIG_FILENAME); + let fileData; + let spec; + // loadConfig returns null if config file is not found in the given directory + try { + fileData = yield fs_extra_1.readFile(absPath); + } + catch (err) { + return undefined; + } + try { + spec = yaml.safeLoad(fileData) || {}; + } + catch (err) { + throw new exceptions_1.ConfigurationError(`Could not parse ${CONFIG_FILENAME} in directory ${path} as valid YAML`, err); + } + if (spec.module) { + /* + We allow specifying modules by name only as a shorthand: + + dependencies: + - foo-module + - name: foo-module // same as the above + */ + if (spec.module.build && spec.module.build.dependencies) { + spec.module.build.dependencies = spec.module.build.dependencies + .map(dep => (typeof dep) === "string" ? { name: dep } : dep); + } + } + const parsed = common_1.validate(spec, exports.configSchema, { context: path_1.relative(projectRoot, absPath) }); + const dirname = path_1.basename(path); + const project = parsed.project; + let moduleConfig = parsed.module; + if (project) { + // we include the default local environment unless explicitly overridden + for (const env of project_1.defaultEnvironments) { + if (!util_1.findByName(project.environments, env.name)) { + project.environments.push(env); + } + } + // the default environment is the first specified environment in the config, unless specified + const defaultEnvironment = project.defaultEnvironment; + if (defaultEnvironment === "") { + project.defaultEnvironment = project.environments[0].name; + } + else { + if (!util_1.findByName(project.environments, defaultEnvironment)) { + throw new exceptions_1.ConfigurationError(`The specified default environment ${defaultEnvironment} is not defined`, { + defaultEnvironment, + availableEnvironments: util_1.getNames(project.environments), + }); + } + } + } + if (moduleConfig) { + // Built-in keys are validated here and the rest are put into the `spec` field + moduleConfig = { + allowPublish: moduleConfig.allowPublish, + build: moduleConfig.build, + description: moduleConfig.description, + name: moduleConfig.name, + path, + repositoryUrl: moduleConfig.repositoryUrl, + serviceConfigs: [], + spec: lodash_1.omit(moduleConfig, baseModuleSchemaKeys), + testConfigs: [], + type: moduleConfig.type, + variables: moduleConfig.variables, + }; + } + return { + version: parsed.version, + dirname, + path, + module: moduleConfig, + project, + }; + }); +} +exports.loadConfig = loadConfig; +function findProjectConfig(path) { + return __awaiter(this, void 0, void 0, function* () { + let config; + let sepCount = path.split(path_1.sep).length - 1; + for (let i = 0; i < sepCount; i++) { + config = yield loadConfig(path, path); + if (!config || !config.project) { + path = path_1.resolve(path, ".."); + } + else if (config.project) { + return config; + } + } + return config; + }); +} +exports.findProjectConfig = findProjectConfig; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Y0FBYyxFQUFFLEVBQUU7Z0JBQ2xCLElBQUksRUFBRSxhQUFJLENBQUMsWUFBWSxFQUFFLG9CQUFvQixDQUFDO2dCQUM5QyxXQUFXLEVBQUUsRUFBRTtnQkFDZixJQUFJLEVBQUUsWUFBWSxDQUFDLElBQUk7Z0JBQ3ZCLFNBQVMsRUFBRSxZQUFZLENBQUMsU0FBUzthQUNsQyxDQUFBO1NBQ0Y7UUFFRCxPQUFPO1lBQ0wsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPO1lBQ3ZCLE9BQU87WUFDUCxJQUFJO1lBQ0osTUFBTSxFQUFFLFlBQVk7WUFDcEIsT0FBTztTQUNSLENBQUE7SUFDSCxDQUFDO0NBQUE7QUF0RkQsZ0NBc0ZDO0FBRUQsU0FBc0IsaUJBQWlCLENBQUMsSUFBWTs7UUFDbEQsSUFBSSxNQUFnQyxDQUFBO1FBRXBDLElBQUksUUFBUSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQUMsVUFBRyxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQTtRQUN6QyxLQUFLLElBQUksQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLEdBQUcsUUFBUSxFQUFFLENBQUMsRUFBRSxFQUFFO1lBQ2pDLE1BQU0sR0FBRyxNQUFNLFVBQVUsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDckMsSUFBSSxDQUFDLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLEVBQUU7Z0JBQzlCLElBQUksR0FBRyxjQUFPLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFBO2FBQzNCO2lCQUFNLElBQUksTUFBTSxDQUFDLE9BQU8sRUFBRTtnQkFDekIsT0FBTyxNQUFNLENBQUE7YUFDZDtTQUNGO1FBRUQsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0NBQUE7QUFkRCw4Q0FjQyIsImZpbGUiOiJjb25maWcvYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBqb2luLCByZWxhdGl2ZSwgYmFzZW5hbWUsIHNlcCwgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7XG4gIGZpbmRCeU5hbWUsXG4gIGdldE5hbWVzLFxufSBmcm9tIFwiLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IGJhc2VNb2R1bGVTcGVjU2NoZW1hLCBNb2R1bGVDb25maWcgfSBmcm9tIFwiLi9tb2R1bGVcIlxuaW1wb3J0IHsgdmFsaWRhdGUgfSBmcm9tIFwiLi9jb21tb25cIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0ICogYXMgeWFtbCBmcm9tIFwianMteWFtbFwiXG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gXCJmcy1leHRyYVwiXG5pbXBvcnQgeyBkZWZhdWx0RW52aXJvbm1lbnRzLCBQcm9qZWN0Q29uZmlnLCBwcm9qZWN0U2NoZW1hIH0gZnJvbSBcIi4uL2NvbmZpZy9wcm9qZWN0XCJcbmltcG9ydCB7IG9taXQgfSBmcm9tIFwibG9kYXNoXCJcblxuY29uc3QgQ09ORklHX0ZJTEVOQU1FID0gXCJnYXJkZW4ueW1sXCJcblxuZXhwb3J0IGludGVyZmFjZSBHYXJkZW5Db25maWcge1xuICB2ZXJzaW9uOiBzdHJpbmdcbiAgZGlybmFtZTogc3RyaW5nXG4gIHBhdGg6IHN0cmluZ1xuICBtb2R1bGU/OiBNb2R1bGVDb25maWdcbiAgcHJvamVjdD86IFByb2plY3RDb25maWdcbn1cblxuZXhwb3J0IGNvbnN0IGNvbmZpZ1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgLy8gVE9ETzogc2hvdWxkIHRoaXMgYmUgY2FsbGVkIGFwaVZlcnNpb24/XG4gICAgdmVyc2lvbjogSm9pLnN0cmluZygpXG4gICAgICAuZGVmYXVsdChcIjBcIilcbiAgICAgIC5vbmx5KFwiMFwiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHNjaGVtYSB2ZXJzaW9uIG9mIHRoZSBjb25maWcgZmlsZSAoY3VycmVudGx5IG5vdCB1c2VkKS5cIiksXG4gICAgZGlybmFtZTogSm9pLnN0cmluZygpLm1ldGEoeyBpbnRlcm5hbDogdHJ1ZSB9KSxcbiAgICBwYXRoOiBKb2kuc3RyaW5nKCkubWV0YSh7IGludGVybmFsOiB0cnVlIH0pLFxuICAgIG1vZHVsZTogYmFzZU1vZHVsZVNwZWNTY2hlbWEsXG4gICAgcHJvamVjdDogcHJvamVjdFNjaGVtYSxcbiAgfSlcbiAgLm9wdGlvbmFsS2V5cyhbXCJtb2R1bGVcIiwgXCJwcm9qZWN0XCJdKVxuICAucmVxdWlyZWQoKVxuICAuZGVzY3JpcHRpb24oXCJUaGUgZ2FyZGVuLnltbCBjb25maWcgZmlsZS5cIilcblxuY29uc3QgYmFzZU1vZHVsZVNjaGVtYUtleXMgPSBPYmplY3Qua2V5cyhiYXNlTW9kdWxlU3BlY1NjaGVtYS5kZXNjcmliZSgpLmNoaWxkcmVuKVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gbG9hZENvbmZpZyhwcm9qZWN0Um9vdDogc3RyaW5nLCBwYXRoOiBzdHJpbmcpOiBQcm9taXNlPEdhcmRlbkNvbmZpZyB8IHVuZGVmaW5lZD4ge1xuICAvLyBUT0RPOiBuaWNlciBlcnJvciBtZXNzYWdlcyB3aGVuIGxvYWQvdmFsaWRhdGlvbiBmYWlsc1xuICBjb25zdCBhYnNQYXRoID0gam9pbihwYXRoLCBDT05GSUdfRklMRU5BTUUpXG4gIGxldCBmaWxlRGF0YVxuICBsZXQgc3BlYzogYW55XG5cbiAgLy8gbG9hZENvbmZpZyByZXR1cm5zIG51bGwgaWYgY29uZmlnIGZpbGUgaXMgbm90IGZvdW5kIGluIHRoZSBnaXZlbiBkaXJlY3RvcnlcbiAgdHJ5IHtcbiAgICBmaWxlRGF0YSA9IGF3YWl0IHJlYWRGaWxlKGFic1BhdGgpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHJldHVybiB1bmRlZmluZWRcbiAgfVxuXG4gIHRyeSB7XG4gICAgc3BlYyA9IHlhbWwuc2FmZUxvYWQoZmlsZURhdGEpIHx8IHt9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoYENvdWxkIG5vdCBwYXJzZSAke0NPTkZJR19GSUxFTkFNRX0gaW4gZGlyZWN0b3J5ICR7cGF0aH0gYXMgdmFsaWQgWUFNTGAsIGVycilcbiAgfVxuXG4gIGlmIChzcGVjLm1vZHVsZSkge1xuICAgIC8qXG4gICAgICBXZSBhbGxvdyBzcGVjaWZ5aW5nIG1vZHVsZXMgYnkgbmFtZSBvbmx5IGFzIGEgc2hvcnRoYW5kOlxuXG4gICAgICAgIGRlcGVuZGVuY2llczpcbiAgICAgICAgICAtIGZvby1tb2R1bGVcbiAgICAgICAgICAtIG5hbWU6IGZvby1tb2R1bGUgLy8gc2FtZSBhcyB0aGUgYWJvdmVcbiAgICAgKi9cbiAgICBpZiAoc3BlYy5tb2R1bGUuYnVpbGQgJiYgc3BlYy5tb2R1bGUuYnVpbGQuZGVwZW5kZW5jaWVzKSB7XG4gICAgICBzcGVjLm1vZHVsZS5idWlsZC5kZXBlbmRlbmNpZXMgPSBzcGVjLm1vZHVsZS5idWlsZC5kZXBlbmRlbmNpZXNcbiAgICAgICAgLm1hcChkZXAgPT4gKHR5cGVvZiBkZXApID09PSBcInN0cmluZ1wiID8geyBuYW1lOiBkZXAgfSA6IGRlcClcbiAgICB9XG4gIH1cblxuICBjb25zdCBwYXJzZWQgPSA8R2FyZGVuQ29uZmlnPnZhbGlkYXRlKHNwZWMsIGNvbmZpZ1NjaGVtYSwgeyBjb250ZXh0OiByZWxhdGl2ZShwcm9qZWN0Um9vdCwgYWJzUGF0aCkgfSlcblxuICBjb25zdCBkaXJuYW1lID0gYmFzZW5hbWUocGF0aClcbiAgY29uc3QgcHJvamVjdCA9IHBhcnNlZC5wcm9qZWN0XG4gIGxldCBtb2R1bGVDb25maWcgPSBwYXJzZWQubW9kdWxlXG5cbiAgaWYgKHByb2plY3QpIHtcbiAgICAvLyB3ZSBpbmNsdWRlIHRoZSBkZWZhdWx0IGxvY2FsIGVudmlyb25tZW50IHVubGVzcyBleHBsaWNpdGx5IG92ZXJyaWRkZW5cbiAgICBmb3IgKGNvbnN0IGVudiBvZiBkZWZhdWx0RW52aXJvbm1lbnRzKSB7XG4gICAgICBpZiAoIWZpbmRCeU5hbWUocHJvamVjdC5lbnZpcm9ubWVudHMsIGVudi5uYW1lKSkge1xuICAgICAgICBwcm9qZWN0LmVudmlyb25tZW50cy5wdXNoKGVudilcbiAgICAgIH1cbiAgICB9XG5cbiAgICAvLyB0aGUgZGVmYXVsdCBlbnZpcm9ubWVudCBpcyB0aGUgZmlyc3Qgc3BlY2lmaWVkIGVudmlyb25tZW50IGluIHRoZSBjb25maWcsIHVubGVzcyBzcGVjaWZpZWRcbiAgICBjb25zdCBkZWZhdWx0RW52aXJvbm1lbnQgPSBwcm9qZWN0LmRlZmF1bHRFbnZpcm9ubWVudFxuXG4gICAgaWYgKGRlZmF1bHRFbnZpcm9ubWVudCA9PT0gXCJcIikge1xuICAgICAgcHJvamVjdC5kZWZhdWx0RW52aXJvbm1lbnQgPSBwcm9qZWN0LmVudmlyb25tZW50c1swXS5uYW1lXG4gICAgfSBlbHNlIHtcbiAgICAgIGlmICghZmluZEJ5TmFtZShwcm9qZWN0LmVudmlyb25tZW50cywgZGVmYXVsdEVudmlyb25tZW50KSkge1xuICAgICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKGBUaGUgc3BlY2lmaWVkIGRlZmF1bHQgZW52aXJvbm1lbnQgJHtkZWZhdWx0RW52aXJvbm1lbnR9IGlzIG5vdCBkZWZpbmVkYCwge1xuICAgICAgICAgIGRlZmF1bHRFbnZpcm9ubWVudCxcbiAgICAgICAgICBhdmFpbGFibGVFbnZpcm9ubWVudHM6IGdldE5hbWVzKHByb2plY3QuZW52aXJvbm1lbnRzKSxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAobW9kdWxlQ29uZmlnKSB7XG4gICAgLy8gQnVpbHQtaW4ga2V5cyBhcmUgdmFsaWRhdGVkIGhlcmUgYW5kIHRoZSByZXN0IGFyZSBwdXQgaW50byB0aGUgYHNwZWNgIGZpZWxkXG4gICAgbW9kdWxlQ29uZmlnID0ge1xuICAgICAgYWxsb3dQdWJsaXNoOiBtb2R1bGVDb25maWcuYWxsb3dQdWJsaXNoLFxuICAgICAgYnVpbGQ6IG1vZHVsZUNvbmZpZy5idWlsZCxcbiAgICAgIGRlc2NyaXB0aW9uOiBtb2R1bGVDb25maWcuZGVzY3JpcHRpb24sXG4gICAgICBuYW1lOiBtb2R1bGVDb25maWcubmFtZSxcbiAgICAgIHBhdGgsXG4gICAgICByZXBvc2l0b3J5VXJsOiBtb2R1bGVDb25maWcucmVwb3NpdG9yeVVybCxcbiAgICAgIHNlcnZpY2VDb25maWdzOiBbXSxcbiAgICAgIHNwZWM6IG9taXQobW9kdWxlQ29uZmlnLCBiYXNlTW9kdWxlU2NoZW1hS2V5cyksXG4gICAgICB0ZXN0Q29uZmlnczogW10sXG4gICAgICB0eXBlOiBtb2R1bGVDb25maWcudHlwZSxcbiAgICAgIHZhcmlhYmxlczogbW9kdWxlQ29uZmlnLnZhcmlhYmxlcyxcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge1xuICAgIHZlcnNpb246IHBhcnNlZC52ZXJzaW9uLFxuICAgIGRpcm5hbWUsXG4gICAgcGF0aCxcbiAgICBtb2R1bGU6IG1vZHVsZUNvbmZpZyxcbiAgICBwcm9qZWN0LFxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBmaW5kUHJvamVjdENvbmZpZyhwYXRoOiBzdHJpbmcpOiBQcm9taXNlPEdhcmRlbkNvbmZpZyB8IHVuZGVmaW5lZD4ge1xuICBsZXQgY29uZmlnOiBHYXJkZW5Db25maWcgfCB1bmRlZmluZWRcblxuICBsZXQgc2VwQ291bnQgPSBwYXRoLnNwbGl0KHNlcCkubGVuZ3RoIC0gMVxuICBmb3IgKGxldCBpID0gMDsgaSA8IHNlcENvdW50OyBpKyspIHtcbiAgICBjb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKHBhdGgsIHBhdGgpXG4gICAgaWYgKCFjb25maWcgfHwgIWNvbmZpZy5wcm9qZWN0KSB7XG4gICAgICBwYXRoID0gcmVzb2x2ZShwYXRoLCBcIi4uXCIpXG4gICAgfSBlbHNlIGlmIChjb25maWcucHJvamVjdCkge1xuICAgICAgcmV0dXJuIGNvbmZpZ1xuICAgIH1cbiAgfVxuXG4gIHJldHVybiBjb25maWdcbn1cbiJdfQ== diff --git a/garden-service/build/config/common.d.ts b/garden-service/build/config/common.d.ts new file mode 100644 index 00000000000..242e29a633e --- /dev/null +++ b/garden-service/build/config/common.d.ts @@ -0,0 +1,29 @@ +import { JoiObject } from "joi"; +import * as Joi from "joi"; +import { ConfigurationError, LocalConfigError } from "../exceptions"; +export declare type Primitive = string | number | boolean; +export interface PrimitiveMap { + [key: string]: Primitive; +} +export interface DeepPrimitiveMap { + [key: string]: Primitive | DeepPrimitiveMap; +} +export declare const enumToArray: (Enum: any) => string[]; +export declare const joiPrimitive: () => Joi.AlternativesSchema; +export declare const identifierRegex: RegExp; +export declare const envVarRegex: RegExp; +export declare const joiIdentifier: () => Joi.StringSchema; +export declare const joiStringMap: (valueSchema: JoiObject) => Joi.ObjectSchema; +export declare const joiIdentifierMap: (valueSchema: JoiObject) => Joi.ObjectSchema; +export declare const joiVariables: () => Joi.ObjectSchema; +export declare const joiEnvVarName: () => Joi.StringSchema; +export declare const joiEnvVars: () => Joi.ObjectSchema; +export declare const joiArray: (schema: any) => Joi.ArraySchema; +export declare const joiRepositoryUrl: () => Joi.StringSchema; +export declare function isPrimitive(value: any): boolean; +export interface ValidateOptions { + context?: string; + ErrorClass?: typeof ConfigurationError | typeof LocalConfigError; +} +export declare function validate(value: T, schema: Joi.Schema, { context, ErrorClass }?: ValidateOptions): T; +//# sourceMappingURL=common.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/common.js b/garden-service/build/config/common.js new file mode 100644 index 00000000000..b8de11c68d6 --- /dev/null +++ b/garden-service/build/config/common.js @@ -0,0 +1,129 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const uuid = require("uuid"); +const exceptions_1 = require("../exceptions"); +const chalk_1 = require("chalk"); +// export type ConfigWithSpec = { +// spec: Omit & Partial +// } +exports.enumToArray = Enum => Object.values(Enum).filter(k => typeof k === "string"); +exports.joiPrimitive = () => Joi.alternatives().try(Joi.number(), Joi.string(), Joi.boolean()) + .description("Number, string or boolean"); +exports.identifierRegex = /^[a-z][a-z0-9]*(-[a-z0-9]+)*$/; +exports.envVarRegex = /^(?!GARDEN)[A-Z_][A-Z0-9_]*$/; +exports.joiIdentifier = () => Joi.string() + .regex(exports.identifierRegex) + .max(63) + .description("Valid RFC1035/RFC1123 (DNS) label (may contain lowercase letters, numbers and dashes, must start with a letter, " + + "and cannot end with a dash) and additionally cannot contain consecutive dashes or be longer than 63 characters."); +exports.joiStringMap = (valueSchema) => Joi + .object().pattern(/.+/, valueSchema); +exports.joiIdentifierMap = (valueSchema) => Joi + .object().pattern(exports.identifierRegex, valueSchema) + .default(() => ({}), "{}") + .description("Key/value map, keys must be valid identifiers."); +exports.joiVariables = () => Joi + .object().pattern(/[\w\d]+/i, exports.joiPrimitive()) + .default(() => ({}), "{}") + .unknown(false) + .description("Key/value map, keys may contain letters and numbers, and values must be primitives."); +exports.joiEnvVarName = () => Joi + .string().regex(exports.envVarRegex) + .description("Valid POSIX environment variable name (may contain letters, numbers and underscores and must start with a " + + "letter). Must be uppercase, and must not start with `GARDEN`."); +exports.joiEnvVars = () => Joi + .object().pattern(exports.envVarRegex, exports.joiPrimitive()) + .default(() => ({}), "{}") + .unknown(false) + .description("Key/value map of environment variables. Keys must be valid POSIX environment variable names " + + "(must be uppercase, may not start with `GARDEN`) and values must be primitives."); +exports.joiArray = (schema) => Joi + .array().items(schema) + .default(() => [], "[]"); +exports.joiRepositoryUrl = () => Joi + .string() + .uri({ + // TODO Support other protocols? + scheme: [ + "git", + /git\+https?/, + "https", + "file", + ], +}) + .description("A remote respository URL. Currently only supports git servers. Use hash notation (#) to point to" + + " a specific branch or tag") + .example("# or git+https://github.com/organization/some-module.git#v2.0"); +function isPrimitive(value) { + return typeof value === "string" || typeof value === "number" || typeof value === "boolean"; +} +exports.isPrimitive = isPrimitive; +const joiPathPlaceholder = uuid.v4(); +const joiPathPlaceholderRegex = new RegExp(joiPathPlaceholder, "g"); +const joiOptions = { + abortEarly: false, + language: { + key: `key ${joiPathPlaceholder} `, + object: { + allowUnknown: `!!key "{{!child}}" is not allowed at path ${joiPathPlaceholder}`, + child: "!!\"{{!child}}\": {{reason}}", + xor: `!!object at ${joiPathPlaceholder} only allows one of {{peersWithLabels}}`, + }, + }, +}; +function validate(value, schema, { context = "", ErrorClass = exceptions_1.ConfigurationError } = {}) { + const result = schema.validate(value, joiOptions); + const error = result.error; + if (error) { + const description = schema.describe(); + const errorDetails = error.details.map((e) => { + // render the key path in a much nicer way + let renderedPath = "."; + if (e.path.length) { + renderedPath = ""; + let d = description; + for (const part of e.path) { + if (d.children && d.children[part]) { + renderedPath += "." + part; + d = d.children[part]; + } + else if (d.patterns) { + for (const p of d.patterns) { + if (part.match(new RegExp(p.regex.slice(1, -1)))) { + renderedPath += `[${part}]`; + d = p.rule; + break; + } + } + } + else { + renderedPath += `[${part}]`; + } + } + } + // a little hack to always use full key paths instead of just the label + e.message = e.message.replace(joiPathPlaceholderRegex, chalk_1.default.underline(renderedPath || ".")); + return e; + }); + const msgPrefix = context ? `Error validating ${context}` : "Validation error"; + const errorDescription = errorDetails.map(e => e.message).join(", "); + throw new ErrorClass(`${msgPrefix}: ${errorDescription}`, { + value, + context, + errorDescription, + errorDetails, + }); + } + return result.value; +} +exports.validate = validate; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUcsQ0FBQyxDQUFDLENBQUE7WUFFNUYsT0FBTyxDQUFDLENBQUE7UUFDVixDQUFDLENBQUMsQ0FBQTtRQUVGLE1BQU0sU0FBUyxHQUFHLE9BQU8sQ0FBQyxDQUFDLENBQUMsb0JBQW9CLE9BQU8sRUFBRSxDQUFDLENBQUMsQ0FBQyxrQkFBa0IsQ0FBQTtRQUM5RSxNQUFNLGdCQUFnQixHQUFHLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRXBFLE1BQU0sSUFBSSxVQUFVLENBQUMsR0FBRyxTQUFTLEtBQUssZ0JBQWdCLEVBQUUsRUFBRTtZQUN4RCxLQUFLO1lBQ0wsT0FBTztZQUNQLGdCQUFnQjtZQUNoQixZQUFZO1NBQ2IsQ0FBQyxDQUFBO0tBQ0g7SUFFRCxPQUFPLE1BQU0sQ0FBQyxLQUFLLENBQUE7QUFDckIsQ0FBQztBQXZERCw0QkF1REMiLCJmaWxlIjoiY29uZmlnL2NvbW1vbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBKb2lPYmplY3QgfSBmcm9tIFwiam9pXCJcbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCAqIGFzIHV1aWQgZnJvbSBcInV1aWRcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yLCBMb2NhbENvbmZpZ0Vycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5cbmV4cG9ydCB0eXBlIFByaW1pdGl2ZSA9IHN0cmluZyB8IG51bWJlciB8IGJvb2xlYW5cblxuZXhwb3J0IGludGVyZmFjZSBQcmltaXRpdmVNYXAgeyBba2V5OiBzdHJpbmddOiBQcmltaXRpdmUgfVxuZXhwb3J0IGludGVyZmFjZSBEZWVwUHJpbWl0aXZlTWFwIHsgW2tleTogc3RyaW5nXTogUHJpbWl0aXZlIHwgRGVlcFByaW1pdGl2ZU1hcCB9XG5cbi8vIGV4cG9ydCB0eXBlIENvbmZpZ1dpdGhTcGVjPFMgZXh0ZW5kcyBvYmplY3Q+ID0gPFQgZXh0ZW5kcyBTPntcbi8vICAgc3BlYzogT21pdDxULCBrZXlvZiBTPiAmIFBhcnRpYWw8Uz5cbi8vIH1cblxuZXhwb3J0IGNvbnN0IGVudW1Ub0FycmF5ID0gRW51bSA9PiAoXG4gIE9iamVjdC52YWx1ZXMoRW51bSkuZmlsdGVyKGsgPT4gdHlwZW9mIGsgPT09IFwic3RyaW5nXCIpIGFzIHN0cmluZ1tdXG4pXG5cbmV4cG9ydCBjb25zdCBqb2lQcmltaXRpdmUgPSAoKSA9PiBKb2kuYWx0ZXJuYXRpdmVzKCkudHJ5KEpvaS5udW1iZXIoKSwgSm9pLnN0cmluZygpLCBKb2kuYm9vbGVhbigpKVxuICAuZGVzY3JpcHRpb24oXCJOdW1iZXIsIHN0cmluZyBvciBib29sZWFuXCIpXG5cbmV4cG9ydCBjb25zdCBpZGVudGlmaWVyUmVnZXggPSAvXlthLXpdW2EtejAtOV0qKC1bYS16MC05XSspKiQvXG5leHBvcnQgY29uc3QgZW52VmFyUmVnZXggPSAvXig/IUdBUkRFTilbQS1aX11bQS1aMC05X10qJC9cblxuZXhwb3J0IGNvbnN0IGpvaUlkZW50aWZpZXIgPSAoKSA9PiBKb2kuc3RyaW5nKClcbiAgLnJlZ2V4KGlkZW50aWZpZXJSZWdleClcbiAgLm1heCg2MylcbiAgLmRlc2NyaXB0aW9uKFxuICAgIFwiVmFsaWQgUkZDMTAzNS9SRkMxMTIzIChETlMpIGxhYmVsIChtYXkgY29udGFpbiBsb3dlcmNhc2UgbGV0dGVycywgbnVtYmVycyBhbmQgZGFzaGVzLCBtdXN0IHN0YXJ0IHdpdGggYSBsZXR0ZXIsIFwiICtcbiAgICBcImFuZCBjYW5ub3QgZW5kIHdpdGggYSBkYXNoKSBhbmQgYWRkaXRpb25hbGx5IGNhbm5vdCBjb250YWluIGNvbnNlY3V0aXZlIGRhc2hlcyBvciBiZSBsb25nZXIgdGhhbiA2MyBjaGFyYWN0ZXJzLlwiLFxuICApXG5cbmV4cG9ydCBjb25zdCBqb2lTdHJpbmdNYXAgPSAodmFsdWVTY2hlbWE6IEpvaU9iamVjdCkgPT4gSm9pXG4gIC5vYmplY3QoKS5wYXR0ZXJuKC8uKy8sIHZhbHVlU2NoZW1hKVxuXG5leHBvcnQgY29uc3Qgam9pSWRlbnRpZmllck1hcCA9ICh2YWx1ZVNjaGVtYTogSm9pT2JqZWN0KSA9PiBKb2lcbiAgLm9iamVjdCgpLnBhdHRlcm4oaWRlbnRpZmllclJlZ2V4LCB2YWx1ZVNjaGVtYSlcbiAgLmRlZmF1bHQoKCkgPT4gKHt9KSwgXCJ7fVwiKVxuICAuZGVzY3JpcHRpb24oXCJLZXkvdmFsdWUgbWFwLCBrZXlzIG11c3QgYmUgdmFsaWQgaWRlbnRpZmllcnMuXCIpXG5cbmV4cG9ydCBjb25zdCBqb2lWYXJpYWJsZXMgPSAoKSA9PiBKb2lcbiAgLm9iamVjdCgpLnBhdHRlcm4oL1tcXHdcXGRdKy9pLCBqb2lQcmltaXRpdmUoKSlcbiAgLmRlZmF1bHQoKCkgPT4gKHt9KSwgXCJ7fVwiKVxuICAudW5rbm93bihmYWxzZSlcbiAgLmRlc2NyaXB0aW9uKFwiS2V5L3ZhbHVlIG1hcCwga2V5cyBtYXkgY29udGFpbiBsZXR0ZXJzIGFuZCBudW1iZXJzLCBhbmQgdmFsdWVzIG11c3QgYmUgcHJpbWl0aXZlcy5cIilcblxuZXhwb3J0IGNvbnN0IGpvaUVudlZhck5hbWUgPSAoKSA9PiBKb2lcbiAgLnN0cmluZygpLnJlZ2V4KGVudlZhclJlZ2V4KVxuICAuZGVzY3JpcHRpb24oXG4gICAgXCJWYWxpZCBQT1NJWCBlbnZpcm9ubWVudCB2YXJpYWJsZSBuYW1lIChtYXkgY29udGFpbiBsZXR0ZXJzLCBudW1iZXJzIGFuZCB1bmRlcnNjb3JlcyBhbmQgbXVzdCBzdGFydCB3aXRoIGEgXCIgK1xuICAgIFwibGV0dGVyKS4gTXVzdCBiZSB1cHBlcmNhc2UsIGFuZCBtdXN0IG5vdCBzdGFydCB3aXRoIGBHQVJERU5gLlwiLFxuICApXG5cbmV4cG9ydCBjb25zdCBqb2lFbnZWYXJzID0gKCkgPT4gSm9pXG4gIC5vYmplY3QoKS5wYXR0ZXJuKGVudlZhclJlZ2V4LCBqb2lQcmltaXRpdmUoKSlcbiAgLmRlZmF1bHQoKCkgPT4gKHt9KSwgXCJ7fVwiKVxuICAudW5rbm93bihmYWxzZSlcbiAgLmRlc2NyaXB0aW9uKFxuICAgIFwiS2V5L3ZhbHVlIG1hcCBvZiBlbnZpcm9ubWVudCB2YXJpYWJsZXMuIEtleXMgbXVzdCBiZSB2YWxpZCBQT1NJWCBlbnZpcm9ubWVudCB2YXJpYWJsZSBuYW1lcyBcIiArXG4gICAgXCIobXVzdCBiZSB1cHBlcmNhc2UsIG1heSBub3Qgc3RhcnQgd2l0aCBgR0FSREVOYCkgYW5kIHZhbHVlcyBtdXN0IGJlIHByaW1pdGl2ZXMuXCIsXG4gIClcblxuZXhwb3J0IGNvbnN0IGpvaUFycmF5ID0gKHNjaGVtYSkgPT4gSm9pXG4gIC5hcnJheSgpLml0ZW1zKHNjaGVtYSlcbiAgLmRlZmF1bHQoKCkgPT4gW10sIFwiW11cIilcblxuZXhwb3J0IGNvbnN0IGpvaVJlcG9zaXRvcnlVcmwgPSAoKSA9PiBKb2lcbiAgLnN0cmluZygpXG4gIC51cmkoe1xuICAgIC8vIFRPRE8gU3VwcG9ydCBvdGhlciBwcm90b2NvbHM/XG4gICAgc2NoZW1lOiBbXG4gICAgICBcImdpdFwiLFxuICAgICAgL2dpdFxcK2h0dHBzPy8sXG4gICAgICBcImh0dHBzXCIsXG4gICAgICBcImZpbGVcIixcbiAgICBdLFxuICB9KVxuICAuZGVzY3JpcHRpb24oXG4gICAgXCJBIHJlbW90ZSByZXNwb3NpdG9yeSBVUkwuIEN1cnJlbnRseSBvbmx5IHN1cHBvcnRzIGdpdCBzZXJ2ZXJzLiBVc2UgaGFzaCBub3RhdGlvbiAoIykgdG8gcG9pbnQgdG9cIiArXG4gICAgXCIgYSBzcGVjaWZpYyBicmFuY2ggb3IgdGFnXCIsXG4gIClcbiAgLmV4YW1wbGUoXCI8Z2l0IHJlbW90ZSB1cmw+IzxicmFuY2h8dGFnPiBvciBnaXQraHR0cHM6Ly9naXRodWIuY29tL29yZ2FuaXphdGlvbi9zb21lLW1vZHVsZS5naXQjdjIuMFwiKVxuXG5leHBvcnQgZnVuY3Rpb24gaXNQcmltaXRpdmUodmFsdWU6IGFueSkge1xuICByZXR1cm4gdHlwZW9mIHZhbHVlID09PSBcInN0cmluZ1wiIHx8IHR5cGVvZiB2YWx1ZSA9PT0gXCJudW1iZXJcIiB8fCB0eXBlb2YgdmFsdWUgPT09IFwiYm9vbGVhblwiXG59XG5cbmNvbnN0IGpvaVBhdGhQbGFjZWhvbGRlciA9IHV1aWQudjQoKVxuY29uc3Qgam9pUGF0aFBsYWNlaG9sZGVyUmVnZXggPSBuZXcgUmVnRXhwKGpvaVBhdGhQbGFjZWhvbGRlciwgXCJnXCIpXG5jb25zdCBqb2lPcHRpb25zID0ge1xuICBhYm9ydEVhcmx5OiBmYWxzZSxcbiAgbGFuZ3VhZ2U6IHtcbiAgICBrZXk6IGBrZXkgJHtqb2lQYXRoUGxhY2Vob2xkZXJ9IGAsXG4gICAgb2JqZWN0OiB7XG4gICAgICBhbGxvd1Vua25vd246IGAhIWtleSBcInt7IWNoaWxkfX1cIiBpcyBub3QgYWxsb3dlZCBhdCBwYXRoICR7am9pUGF0aFBsYWNlaG9sZGVyfWAsXG4gICAgICBjaGlsZDogXCIhIVxcXCJ7eyFjaGlsZH19XFxcIjoge3tyZWFzb259fVwiLFxuICAgICAgeG9yOiBgISFvYmplY3QgYXQgJHtqb2lQYXRoUGxhY2Vob2xkZXJ9IG9ubHkgYWxsb3dzIG9uZSBvZiB7e3BlZXJzV2l0aExhYmVsc319YCxcbiAgICB9LFxuICB9LFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRlT3B0aW9ucyB7XG4gIGNvbnRleHQ/OiBzdHJpbmdcbiAgRXJyb3JDbGFzcz86IHR5cGVvZiBDb25maWd1cmF0aW9uRXJyb3IgfCB0eXBlb2YgTG9jYWxDb25maWdFcnJvclxufVxuXG5leHBvcnQgZnVuY3Rpb24gdmFsaWRhdGU8VD4oXG4gIHZhbHVlOiBULFxuICBzY2hlbWE6IEpvaS5TY2hlbWEsXG4gIHsgY29udGV4dCA9IFwiXCIsIEVycm9yQ2xhc3MgPSBDb25maWd1cmF0aW9uRXJyb3IgfTogVmFsaWRhdGVPcHRpb25zID0ge30sXG4pOiBUIHtcbiAgY29uc3QgcmVzdWx0ID0gc2NoZW1hLnZhbGlkYXRlKHZhbHVlLCBqb2lPcHRpb25zKVxuICBjb25zdCBlcnJvciA9IHJlc3VsdC5lcnJvclxuXG4gIGlmIChlcnJvcikge1xuICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gc2NoZW1hLmRlc2NyaWJlKClcblxuICAgIGNvbnN0IGVycm9yRGV0YWlscyA9IGVycm9yLmRldGFpbHMubWFwKChlKSA9PiB7XG4gICAgICAvLyByZW5kZXIgdGhlIGtleSBwYXRoIGluIGEgbXVjaCBuaWNlciB3YXlcbiAgICAgIGxldCByZW5kZXJlZFBhdGggPSBcIi5cIlxuXG4gICAgICBpZiAoZS5wYXRoLmxlbmd0aCkge1xuICAgICAgICByZW5kZXJlZFBhdGggPSBcIlwiXG4gICAgICAgIGxldCBkID0gZGVzY3JpcHRpb25cblxuICAgICAgICBmb3IgKGNvbnN0IHBhcnQgb2YgZS5wYXRoKSB7XG4gICAgICAgICAgaWYgKGQuY2hpbGRyZW4gJiYgZC5jaGlsZHJlbltwYXJ0XSkge1xuICAgICAgICAgICAgcmVuZGVyZWRQYXRoICs9IFwiLlwiICsgcGFydFxuICAgICAgICAgICAgZCA9IGQuY2hpbGRyZW5bcGFydF1cbiAgICAgICAgICB9IGVsc2UgaWYgKGQucGF0dGVybnMpIHtcbiAgICAgICAgICAgIGZvciAoY29uc3QgcCBvZiBkLnBhdHRlcm5zKSB7XG4gICAgICAgICAgICAgIGlmIChwYXJ0Lm1hdGNoKG5ldyBSZWdFeHAocC5yZWdleC5zbGljZSgxLCAtMSkpKSkge1xuICAgICAgICAgICAgICAgIHJlbmRlcmVkUGF0aCArPSBgWyR7cGFydH1dYFxuICAgICAgICAgICAgICAgIGQgPSBwLnJ1bGVcbiAgICAgICAgICAgICAgICBicmVha1xuICAgICAgICAgICAgICB9XG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJlbmRlcmVkUGF0aCArPSBgWyR7cGFydH1dYFxuICAgICAgICAgIH1cbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBhIGxpdHRsZSBoYWNrIHRvIGFsd2F5cyB1c2UgZnVsbCBrZXkgcGF0aHMgaW5zdGVhZCBvZiBqdXN0IHRoZSBsYWJlbFxuICAgICAgZS5tZXNzYWdlID0gZS5tZXNzYWdlLnJlcGxhY2Uoam9pUGF0aFBsYWNlaG9sZGVyUmVnZXgsIGNoYWxrLnVuZGVybGluZShyZW5kZXJlZFBhdGggfHwgXCIuXCIpKVxuXG4gICAgICByZXR1cm4gZVxuICAgIH0pXG5cbiAgICBjb25zdCBtc2dQcmVmaXggPSBjb250ZXh0ID8gYEVycm9yIHZhbGlkYXRpbmcgJHtjb250ZXh0fWAgOiBcIlZhbGlkYXRpb24gZXJyb3JcIlxuICAgIGNvbnN0IGVycm9yRGVzY3JpcHRpb24gPSBlcnJvckRldGFpbHMubWFwKGUgPT4gZS5tZXNzYWdlKS5qb2luKFwiLCBcIilcblxuICAgIHRocm93IG5ldyBFcnJvckNsYXNzKGAke21zZ1ByZWZpeH06ICR7ZXJyb3JEZXNjcmlwdGlvbn1gLCB7XG4gICAgICB2YWx1ZSxcbiAgICAgIGNvbnRleHQsXG4gICAgICBlcnJvckRlc2NyaXB0aW9uLFxuICAgICAgZXJyb3JEZXRhaWxzLFxuICAgIH0pXG4gIH1cblxuICByZXR1cm4gcmVzdWx0LnZhbHVlXG59XG4iXX0= diff --git a/garden-service/build/config/config-context.d.ts b/garden-service/build/config/config-context.d.ts new file mode 100644 index 00000000000..67b29439af2 --- /dev/null +++ b/garden-service/build/config/config-context.d.ts @@ -0,0 +1,62 @@ +import { Module } from "../types/module"; +import { PrimitiveMap, Primitive } from "./common"; +import { Provider, Environment } from "./project"; +import { ModuleConfig } from "./module"; +import { Service } from "../types/service"; +import * as Joi from "joi"; +import { Garden } from "../garden"; +export declare type ContextKey = string[]; +export interface ContextResolveParams { + key: ContextKey; + nodePath: ContextKey; + stack?: string[]; +} +export declare function schema(joiSchema: Joi.Schema): (target: any, propName: any) => void; +export declare abstract class ConfigContext { + private readonly _rootContext; + private readonly _resolvedValues; + constructor(rootContext?: ConfigContext); + static getSchema(): Joi.ObjectSchema; + resolve({ key, nodePath, stack }: ContextResolveParams): Promise; +} +declare class LocalContext extends ConfigContext { + env: typeof process.env; + platform: string; + constructor(root: ConfigContext); +} +/** + * This context is available for template strings under the `project` key in configuration files. + */ +export declare class ProjectConfigContext extends ConfigContext { + local: LocalContext; + constructor(); +} +declare class EnvironmentContext extends ConfigContext { + name: string; + constructor(root: ConfigContext, name: string); +} +declare class ModuleContext extends ConfigContext { + path: string; + version: string; + buildPath: string; + constructor(root: ConfigContext, module: Module); +} +declare class ServiceContext extends ConfigContext { + outputs: PrimitiveMap; + version: string; + constructor(root: ConfigContext, service: Service, outputs: PrimitiveMap); +} +/** + * This context is available for template strings under the `module` key in configuration files. + * It is a superset of the context available under the `project` key. + */ +export declare class ModuleConfigContext extends ProjectConfigContext { + environment: EnvironmentContext; + modules: Map Promise>; + services: Map Promise>; + providers: Map; + variables: PrimitiveMap; + constructor(garden: Garden, environment: Environment, moduleConfigs: ModuleConfig[]); +} +export {}; +//# sourceMappingURL=config-context.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/config-context.js b/garden-service/build/config/config-context.js new file mode 100644 index 00000000000..5be6a5bedd9 --- /dev/null +++ b/garden-service/build/config/config-context.js @@ -0,0 +1,271 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) { + var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d; + if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc); + else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r; + return c > 3 && r && Object.defineProperty(target, key, r), r; +}; +var __metadata = (this && this.__metadata) || function (k, v) { + if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v); +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const common_1 = require("./common"); +const project_1 = require("./project"); +const exceptions_1 = require("../exceptions"); +const template_string_1 = require("../template-string"); +const Joi = require("joi"); +function schema(joiSchema) { + return (target, propName) => { + target.constructor._schemas = Object.assign({}, target.constructor._schemas || {}, { [propName]: joiSchema }); + }; +} +exports.schema = schema; +// Note: we're using classes here to be able to use decorators to describe each context node and key +class ConfigContext { + constructor(rootContext) { + this._rootContext = rootContext || this; + this._resolvedValues = {}; + } + static getSchema() { + const schemas = this._schemas; + return Joi.object().keys(schemas).required(); + } + resolve({ key, nodePath, stack }) { + return __awaiter(this, void 0, void 0, function* () { + const path = key.join("."); + const fullPath = nodePath.concat(key).join("."); + // if the key has previously been resolved, return it directly + const resolved = this._resolvedValues[path]; + if (resolved) { + return resolved; + } + stack = [...stack || []]; + if (stack.includes(fullPath)) { + throw new exceptions_1.ConfigurationError(`Circular reference detected when resolving key ${path} (${stack.join(" -> ")})`, { + nodePath, + fullPath, + stack, + }); + } + // keep track of which resolvers have been called, in order to detect circular references + let value = this; + for (let p = 0; p < key.length; p++) { + const nextKey = key[p]; + const lookupPath = key.slice(0, p + 1); + const remainder = key.slice(p + 1); + const nestedNodePath = nodePath.concat(lookupPath); + const stackEntry = nestedNodePath.join("."); + if (nextKey.startsWith("_")) { + value = undefined; + } + else { + value = value instanceof Map ? value.get(nextKey) : value[nextKey]; + } + if (typeof value === "function") { + // call the function to resolve the value, then continue + value = yield value(); + } + // handle nested contexts + if (value instanceof ConfigContext) { + const nestedKey = remainder; + stack.push(stackEntry); + value = yield value.resolve({ key: nestedKey, nodePath: nestedNodePath, stack }); + break; + } + // handle templated strings in context variables + if (lodash_1.isString(value)) { + stack.push(stackEntry); + value = yield template_string_1.resolveTemplateString(value, this._rootContext, stack); + } + if (value === undefined) { + break; + } + } + if (value === undefined) { + throw new exceptions_1.ConfigurationError(`Could not find key: ${path}`, { + nodePath, + fullPath, + stack, + }); + } + if (!common_1.isPrimitive(value)) { + throw new exceptions_1.ConfigurationError(`Config value at ${path} exists but is not a primitive (string, number or boolean)`, { + value, + path, + fullPath, + context, + }); + } + this._resolvedValues[path] = value; + return value; + }); + } +} +exports.ConfigContext = ConfigContext; +class LocalContext extends ConfigContext { + constructor(root) { + super(root); + this.env = process.env; + this.platform = process.platform; + } +} +__decorate([ + schema(common_1.joiStringMap(Joi.string()).description("A map of all local environment variables (see https://nodejs.org/api/process.html#process_process_env).")), + __metadata("design:type", Object) +], LocalContext.prototype, "env", void 0); +__decorate([ + schema(Joi.string() + .description("A string indicating the platform that the framework is running on " + + "(see https://nodejs.org/api/process.html#process_process_platform)") + .example("posix")), + __metadata("design:type", String) +], LocalContext.prototype, "platform", void 0); +/** + * This context is available for template strings under the `project` key in configuration files. + */ +class ProjectConfigContext extends ConfigContext { + constructor() { + super(); + this.local = new LocalContext(this); + } +} +__decorate([ + schema(LocalContext.getSchema()), + __metadata("design:type", LocalContext) +], ProjectConfigContext.prototype, "local", void 0); +exports.ProjectConfigContext = ProjectConfigContext; +class EnvironmentContext extends ConfigContext { + constructor(root, name) { + super(root); + this.name = name; + } +} +__decorate([ + schema(Joi.string() + .description("The name of the environment Garden is running against.") + .example("local")), + __metadata("design:type", String) +], EnvironmentContext.prototype, "name", void 0); +const exampleVersion = "v17ad4cb3fd"; +class ModuleContext extends ConfigContext { + constructor(root, module) { + super(root); + this.path = module.path; + this.version = module.version.versionString; + this.buildPath = module.buildPath; + } +} +__decorate([ + schema(Joi.string().description("The local path of the module.").example("/home/me/code/my-project/my-module")), + __metadata("design:type", String) +], ModuleContext.prototype, "path", void 0); +__decorate([ + schema(Joi.string().description("The current version of the module.").example(exampleVersion)), + __metadata("design:type", String) +], ModuleContext.prototype, "version", void 0); +__decorate([ + schema(Joi.string() + .description("The build path of the module.") + .example("/home/me/code/my-project/.garden/build/my-module")), + __metadata("design:type", String) +], ModuleContext.prototype, "buildPath", void 0); +const exampleOutputs = { ingress: "http://my-service/path/to/endpoint" }; +class ServiceContext extends ConfigContext { + // TODO: add ingresses + constructor(root, service, outputs) { + super(root); + this.outputs = outputs; + this.version = service.module.version.versionString; + } +} +__decorate([ + schema(common_1.joiIdentifierMap(common_1.joiPrimitive() + .description("The outputs defined by the service (see individual plugins for details).") + .example(exampleOutputs))), + __metadata("design:type", Object) +], ServiceContext.prototype, "outputs", void 0); +__decorate([ + schema(Joi.string().description("The current version of the service.").example(exampleVersion)), + __metadata("design:type", String) +], ServiceContext.prototype, "version", void 0); +/** + * This context is available for template strings under the `module` key in configuration files. + * It is a superset of the context available under the `project` key. + */ +class ModuleConfigContext extends ProjectConfigContext { + constructor(garden, environment, moduleConfigs) { + super(); + const _this = this; + this.environment = new EnvironmentContext(_this, environment.name); + this.modules = new Map(moduleConfigs.map((config) => [config.name, () => __awaiter(this, void 0, void 0, function* () { + const module = yield garden.getModule(config.name); + return new ModuleContext(_this, module); + })])); + const serviceNames = lodash_1.flatten(moduleConfigs.map(m => m.serviceConfigs)).map(s => s.name); + this.services = new Map(serviceNames.map((name) => [name, () => __awaiter(this, void 0, void 0, function* () { + const service = yield garden.getService(name); + const outputs = Object.assign({}, service.config.outputs, yield garden.actions.getServiceOutputs({ service })); + return new ServiceContext(_this, service, outputs); + })])); + this.providers = new Map(environment.providers.map(p => [p.name, p])); + // this.config = new SecretsContextNode(ctx) + this.variables = environment.variables; + } +} +__decorate([ + schema(EnvironmentContext.getSchema() + .description("Information about the environment that Garden is running against.")), + __metadata("design:type", EnvironmentContext) +], ModuleConfigContext.prototype, "environment", void 0); +__decorate([ + schema(common_1.joiIdentifierMap(ModuleContext.getSchema()) + .description("Retrieve information about modules that are defined in the project.") + .example({ "my-module": { path: "/home/me/code/my-project/my-module", version: exampleVersion } })), + __metadata("design:type", Map) +], ModuleConfigContext.prototype, "modules", void 0); +__decorate([ + schema(common_1.joiIdentifierMap(ServiceContext.getSchema()) + .description("Retrieve information about services that are defined in the project.") + .example({ "my-service": { outputs: exampleOutputs, version: exampleVersion } })), + __metadata("design:type", Map) +], ModuleConfigContext.prototype, "services", void 0); +__decorate([ + schema(common_1.joiIdentifierMap(project_1.providerConfigBaseSchema) + .description("A map of all configured plugins/providers for this environment and their configuration.") + .example({ kubernetes: { name: "local-kubernetes", context: "my-kube-context" } })), + __metadata("design:type", Map) +], ModuleConfigContext.prototype, "providers", void 0); +__decorate([ + schema(common_1.joiIdentifierMap(common_1.joiPrimitive()) + .description("A map of all variables defined in the project configuration.") + .example({ "team-name": "bananaramallama", "some-service-endpoint": "https://someservice.com/api/v2" })), + __metadata("design:type", Object) +], ModuleConfigContext.prototype, "variables", void 0); +exports.ModuleConfigContext = ModuleConfigContext; +// class RemoteConfigContext extends ConfigContext { +// constructor(private ctx: PluginContext) { +// super() +// } +// async resolve({ key }: ResolveParams) { +// const { value } = await this.ctx.getSecret({ key }) +// return value === null ? undefined : value +// } +// } + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbmZpZy9jb25maWctY29udGV4dC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7Ozs7Ozs7O0FBRUgsbUNBQTBDO0FBRTFDLHFDQUE2RztBQUM3Ryx1Q0FBMkU7QUFFM0UsOENBQWtEO0FBRWxELHdEQUEwRDtBQUMxRCwyQkFBMEI7QUFZMUIsU0FBZ0IsTUFBTSxDQUFDLFNBQXFCO0lBQzFDLE9BQU8sQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLEVBQUU7UUFDMUIsTUFBTSxDQUFDLFdBQVcsQ0FBQyxRQUFRLHFCQUFRLE1BQU0sQ0FBQyxXQUFXLENBQUMsUUFBUSxJQUFJLEVBQUUsSUFBRSxDQUFDLFFBQVEsQ0FBQyxFQUFFLFNBQVMsR0FBRSxDQUFBO0lBQy9GLENBQUMsQ0FBQTtBQUNILENBQUM7QUFKRCx3QkFJQztBQUVELG9HQUFvRztBQUNwRyxNQUFzQixhQUFhO0lBSWpDLFlBQVksV0FBMkI7UUFDckMsSUFBSSxDQUFDLFlBQVksR0FBRyxXQUFXLElBQUksSUFBSSxDQUFBO1FBQ3ZDLElBQUksQ0FBQyxlQUFlLEdBQUcsRUFBRSxDQUFBO0lBQzNCLENBQUM7SUFFRCxNQUFNLENBQUMsU0FBUztRQUNkLE1BQU0sT0FBTyxHQUFTLElBQUssQ0FBQyxRQUFRLENBQUE7UUFDcEMsT0FBTyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO0lBQzlDLENBQUM7SUFFSyxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEtBQUssRUFBd0I7O1lBQzFELE1BQU0sSUFBSSxHQUFHLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7WUFDMUIsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUE7WUFFL0MsOERBQThEO1lBQzlELE1B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T0FBTyxFQUFFLGNBQWMsRUFBRSxFQUFFLENBQUMsQ0FDckc7OEJBQ2UsR0FBRztvREFBc0M7QUFPekQ7SUFMQyxNQUFNLENBQ0wseUJBQWdCLENBQUMsY0FBYyxDQUFDLFNBQVMsRUFBRSxDQUFDO1NBQ3pDLFdBQVcsQ0FBQyxzRUFBc0UsQ0FBQztTQUNuRixPQUFPLENBQUMsRUFBRSxZQUFZLEVBQUUsRUFBRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsRUFBRSxDQUFDLENBQ25GOzhCQUNnQixHQUFHO3FEQUF1QztBQU8zRDtJQUxDLE1BQU0sQ0FDTCx5QkFBZ0IsQ0FBQyxrQ0FBd0IsQ0FBQztTQUN2QyxXQUFXLENBQUMseUZBQXlGLENBQUM7U0FDdEcsT0FBTyxDQUFDLEVBQUUsVUFBVSxFQUFFLEVBQUUsSUFBSSxFQUFFLGtCQUFrQixFQUFFLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxFQUFFLENBQUMsQ0FDckY7OEJBQ2lCLEdBQUc7c0RBQWtCO0FBYXZDO0lBTEMsTUFBTSxDQUNMLHlCQUFnQixDQUFDLHFCQUFZLEVBQUUsQ0FBQztTQUM3QixXQUFXLENBQUMsOERBQThELENBQUM7U0FDM0UsT0FBTyxDQUFDLEVBQUUsV0FBVyxFQUFFLGlCQUFpQixFQUFFLHVCQUF1QixFQUFFLGdDQUFnQyxFQUFFLENBQUMsQ0FDMUc7O3NEQUM2QjtBQXZDaEMsa0RBOEVDO0FBRUQsb0RBQW9EO0FBQ3BELDhDQUE4QztBQUM5QyxjQUFjO0FBQ2QsTUFBTTtBQUVOLDRDQUE0QztBQUM1QywwREFBMEQ7QUFDMUQsZ0RBQWdEO0FBQ2hELE1BQU07QUFDTixJQUFJIiwiZmlsZSI6ImNvbmZpZy9jb25maWctY29udGV4dC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBpc1N0cmluZywgZmxhdHRlbiB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBQcmltaXRpdmVNYXAsIGlzUHJpbWl0aXZlLCBQcmltaXRpdmUsIGpvaUlkZW50aWZpZXJNYXAsIGpvaVN0cmluZ01hcCwgam9pUHJpbWl0aXZlIH0gZnJvbSBcIi4vY29tbW9uXCJcbmltcG9ydCB7IFByb3ZpZGVyLCBFbnZpcm9ubWVudCwgcHJvdmlkZXJDb25maWdCYXNlU2NoZW1hIH0gZnJvbSBcIi4vcHJvamVjdFwiXG5pbXBvcnQgeyBNb2R1bGVDb25maWcgfSBmcm9tIFwiLi9tb2R1bGVcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgU2VydmljZSB9IGZyb20gXCIuLi90eXBlcy9zZXJ2aWNlXCJcbmltcG9ydCB7IHJlc29sdmVUZW1wbGF0ZVN0cmluZyB9IGZyb20gXCIuLi90ZW1wbGF0ZS1zdHJpbmdcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4uL2dhcmRlblwiXG5cbmV4cG9ydCB0eXBlIENvbnRleHRLZXkgPSBzdHJpbmdbXVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRleHRSZXNvbHZlUGFyYW1zIHtcbiAga2V5OiBDb250ZXh0S2V5XG4gIG5vZGVQYXRoOiBDb250ZXh0S2V5XG4gIC8vIGEgbGlzdCBvZiBwcmV2aW91c2x5IHJlc29sdmVkIHBhdGhzLCB1c2VkIHRvIGRldGVjdCBjaXJjdWxhciByZWZlcmVuY2VzXG4gIHN0YWNrPzogc3RyaW5nW11cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHNjaGVtYShqb2lTY2hlbWE6IEpvaS5TY2hlbWEpIHtcbiAgcmV0dXJuICh0YXJnZXQsIHByb3BOYW1lKSA9PiB7XG4gICAgdGFyZ2V0LmNvbnN0cnVjdG9yLl9zY2hlbWFzID0geyAuLi50YXJnZXQuY29uc3RydWN0b3IuX3NjaGVtYXMgfHwge30sIFtwcm9wTmFtZV06IGpvaVNjaGVtYSB9XG4gIH1cbn1cblxuLy8gTm90ZTogd2UncmUgdXNpbmcgY2xhc3NlcyBoZXJlIHRvIGJlIGFibGUgdG8gdXNlIGRlY29yYXRvcnMgdG8gZGVzY3JpYmUgZWFjaCBjb250ZXh0IG5vZGUgYW5kIGtleVxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIENvbmZpZ0NvbnRleHQge1xuICBwcml2YXRlIHJlYWRvbmx5IF9yb290Q29udGV4dDogQ29uZmlnQ29udGV4dFxuICBwcml2YXRlIHJlYWRvbmx5IF9yZXNvbHZlZFZhbHVlczogeyBbcGF0aDogc3RyaW5nXTogc3RyaW5nIH1cblxuICBjb25zdHJ1Y3Rvcihyb290Q29udGV4dD86IENvbmZpZ0NvbnRleHQpIHtcbiAgICB0aGlzLl9yb290Q29udGV4dCA9IHJvb3RDb250ZXh0IHx8IHRoaXNcbiAgICB0aGlzLl9yZXNvbHZlZFZhbHVlcyA9IHt9XG4gIH1cblxuICBzdGF0aWMgZ2V0U2NoZW1hKCkge1xuICAgIGNvbnN0IHNjaGVtYXMgPSAoPGFueT50aGlzKS5fc2NoZW1hc1xuICAgIHJldHVybiBKb2kub2JqZWN0KCkua2V5cyhzY2hlbWFzKS5yZXF1aXJlZCgpXG4gIH1cblxuICBhc3luYyByZXNvbHZlKHsga2V5LCBub2RlUGF0aCwgc3RhY2sgfTogQ29udGV4dFJlc29sdmVQYXJhbXMpOiBQcm9taXNlPFByaW1pdGl2ZT4ge1xuICAgIGNvbnN0IHBhdGggPSBrZXkuam9pbihcIi5cIilcbiAgICBjb25zdCBmdWxsUGF0aCA9IG5vZGVQYXRoLmNvbmNhdChrZXkpLmpvaW4oXCIuXCIpXG5cbiAgICAvLyBpZiB0aGUga2V5IGhhcyBwcmV2aW91c2x5IGJlZW4gcmVzb2x2ZWQsIHJldHVybiBpdCBkaXJlY3RseVxuICAgIGNvbnN0IHJlc29sdmVkID0gdGhpcy5fcmVzb2x2ZWRWYWx1ZXNbcGF0aF1cblxuICAgIGlmIChyZXNvbHZlZCkge1xuICAgICAgcmV0dXJuIHJlc29sdmVkXG4gICAgfVxuXG4gICAgc3RhY2sgPSBbLi4uc3RhY2sgfHwgW11dXG5cbiAgICBpZiAoc3RhY2suaW5jbHVkZXMoZnVsbFBhdGgpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgICBgQ2lyY3VsYXIgcmVmZXJlbmNlIGRldGVjdGVkIHdoZW4gcmVzb2x2aW5nIGtleSAke3BhdGh9ICgke3N0YWNrLmpvaW4oXCIgLT4gXCIpfSlgLFxuICAgICAgICB7XG4gICAgICAgICAgbm9kZVBhdGgsXG4gICAgICAgICAgZnVsbFBhdGgsXG4gICAgICAgICAgc3RhY2ssXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgfVxuXG4gICAgLy8ga2VlcCB0cmFjayBvZiB3aGljaCByZXNvbHZlcnMgaGF2ZSBiZWVuIGNhbGxlZCwgaW4gb3JkZXIgdG8gZGV0ZWN0IGNpcmN1bGFyIHJlZmVyZW5jZXNcbiAgICBsZXQgdmFsdWU6IGFueSA9IHRoaXNcblxuICAgIGZvciAobGV0IHAgPSAwOyBwIDwga2V5Lmxlbmd0aDsgcCsrKSB7XG4gICAgICBjb25zdCBuZXh0S2V5ID0ga2V5W3BdXG4gICAgICBjb25zdCBsb29rdXBQYXRoID0ga2V5LnNsaWNlKDAsIHAgKyAxKVxuICAgICAgY29uc3QgcmVtYWluZGVyID0ga2V5LnNsaWNlKHAgKyAxKVxuICAgICAgY29uc3QgbmVzdGVkTm9kZVBhdGggPSBub2RlUGF0aC5jb25jYXQobG9va3VwUGF0aClcbiAgICAgIGNvbnN0IHN0YWNrRW50cnkgPSBuZXN0ZWROb2RlUGF0aC5qb2luKFwiLlwiKVxuXG4gICAgICBpZiAobmV4dEtleS5zdGFydHNXaXRoKFwiX1wiKSkge1xuICAgICAgICB2YWx1ZSA9IHVuZGVmaW5lZFxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdmFsdWUgPSB2YWx1ZSBpbnN0YW5jZW9mIE1hcCA/IHZhbHVlLmdldChuZXh0S2V5KSA6IHZhbHVlW25leHRLZXldXG4gICAgICB9XG5cbiAgICAgIGlmICh0eXBlb2YgdmFsdWUgPT09IFwiZnVuY3Rpb25cIikge1xuICAgICAgICAvLyBjYWxsIHRoZSBmdW5jdGlvbiB0byByZXNvbHZlIHRoZSB2YWx1ZSwgdGhlbiBjb250aW51ZVxuICAgICAgICB2YWx1ZSA9IGF3YWl0IHZhbHVlKClcbiAgICAgIH1cblxuICAgICAgLy8gaGFuZGxlIG5lc3RlZCBjb250ZXh0c1xuICAgICAgaWYgKHZhbHVlIGluc3RhbmNlb2YgQ29uZmlnQ29udGV4dCkge1xuICAgICAgICBjb25zdCBuZXN0ZWRLZXkgPSByZW1haW5kZXJcbiAgICAgICAgc3RhY2sucHVzaChzdGFja0VudHJ5KVxuICAgICAgICB2YWx1ZSA9IGF3YWl0IHZhbHVlLnJlc29sdmUoeyBrZXk6IG5lc3RlZEtleSwgbm9kZVBhdGg6IG5lc3RlZE5vZGVQYXRoLCBzdGFjayB9KVxuICAgICAgICBicmVha1xuICAgICAgfVxuXG4gICAgICAvLyBoYW5kbGUgdGVtcGxhdGVkIHN0cmluZ3MgaW4gY29udGV4dCB2YXJpYWJsZXNcbiAgICAgIGlmIChpc1N0cmluZyh2YWx1ZSkpIHtcbiAgICAgICAgc3RhY2sucHVzaChzdGFja0VudHJ5KVxuICAgICAgICB2YWx1ZSA9IGF3YWl0IHJlc29sdmVUZW1wbGF0ZVN0cmluZyh2YWx1ZSwgdGhpcy5fcm9vdENvbnRleHQsIHN0YWNrKVxuICAgICAgfVxuXG4gICAgICBpZiAodmFsdWUgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBicmVha1xuICAgICAgfVxuICAgIH1cblxuICAgIGlmICh2YWx1ZSA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKGBDb3VsZCBub3QgZmluZCBrZXk6ICR7cGF0aH1gLCB7XG4gICAgICAgIG5vZGVQYXRoLFxuICAgICAgICBmdWxsUGF0aCxcbiAgICAgICAgc3RhY2ssXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmICghaXNQcmltaXRpdmUodmFsdWUpKSB7XG4gICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgICBgQ29uZmlnIHZhbHVlIGF0ICR7cGF0aH0gZXhpc3RzIGJ1dCBpcyBub3QgYSBwcmltaXRpdmUgKHN0cmluZywgbnVtYmVyIG9yIGJvb2xlYW4pYCxcbiAgICAgICAge1xuICAgICAgICAgIHZhbHVlLFxuICAgICAgICAgIHBhdGgsXG4gICAgICAgICAgZnVsbFBhdGgsXG4gICAgICAgICAgY29udGV4dCxcbiAgICAgICAgfSxcbiAgICAgIClcbiAgICB9XG5cbiAgICB0aGlzLl9yZXNvbHZlZFZhbHVlc1twYXRoXSA9IHZhbHVlXG4gICAgcmV0dXJuIHZhbHVlXG4gIH1cbn1cblxuY2xhc3MgTG9jYWxDb250ZXh0IGV4dGVuZHMgQ29uZmlnQ29udGV4dCB7XG4gIEBzY2hlbWEoXG4gICAgam9pU3RyaW5nTWFwKEpvaS5zdHJpbmcoKSkuZGVzY3JpcHRpb24oXG4gICAgICBcIkEgbWFwIG9mIGFsbCBsb2NhbCBlbnZpcm9ubWVudCB2YXJpYWJsZXMgKHNlZSBodHRwczovL25vZGVqcy5vcmcvYXBpL3Byb2Nlc3MuaHRtbCNwcm9jZXNzX3Byb2Nlc3NfZW52KS5cIixcbiAgICApLFxuICApXG4gIHB1YmxpYyBlbnY6IHR5cGVvZiBwcm9jZXNzLmVudlxuXG4gIEBzY2hlbWEoXG4gICAgSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiQSBzdHJpbmcgaW5kaWNhdGluZyB0aGUgcGxhdGZvcm0gdGhhdCB0aGUgZnJhbWV3b3JrIGlzIHJ1bm5pbmcgb24gXCIgK1xuICAgICAgICBcIihzZWUgaHR0cHM6Ly9ub2RlanMub3JnL2FwaS9wcm9jZXNzLmh0bWwjcHJvY2Vzc19wcm9jZXNzX3BsYXRmb3JtKVwiLFxuICAgICAgKVxuICAgICAgLmV4YW1wbGUoXCJwb3NpeFwiKSxcbiAgKVxuICBwdWJsaWMgcGxhdGZvcm06IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHJvb3Q6IENvbmZpZ0NvbnRleHQpIHtcbiAgICBzdXBlcihyb290KVxuICAgIHRoaXMuZW52ID0gcHJvY2Vzcy5lbnZcbiAgICB0aGlzLnBsYXRmb3JtID0gcHJvY2Vzcy5wbGF0Zm9ybVxuICB9XG59XG5cbi8qKlxuICogVGhpcyBjb250ZXh0IGlzIGF2YWlsYWJsZSBmb3IgdGVtcGxhdGUgc3RyaW5ncyB1bmRlciB0aGUgYHByb2plY3RgIGtleSBpbiBjb25maWd1cmF0aW9uIGZpbGVzLlxuICovXG5leHBvcnQgY2xhc3MgUHJvamVjdENvbmZpZ0NvbnRleHQgZXh0ZW5kcyBDb25maWdDb250ZXh0IHtcbiAgQHNjaGVtYShMb2NhbENvbnRleHQuZ2V0U2NoZW1hKCkpXG4gIHB1YmxpYyBsb2NhbDogTG9jYWxDb250ZXh0XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgc3VwZXIoKVxuICAgIHRoaXMubG9jYWwgPSBuZXcgTG9jYWxDb250ZXh0KHRoaXMpXG4gIH1cbn1cblxuY2xhc3MgRW52aXJvbm1lbnRDb250ZXh0IGV4dGVuZHMgQ29uZmlnQ29udGV4dCB7XG4gIEBzY2hlbWEoXG4gICAgSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZSBvZiB0aGUgZW52aXJvbm1lbnQgR2FyZGVuIGlzIHJ1bm5pbmcgYWdhaW5zdC5cIilcbiAgICAgIC5leGFtcGxlKFwibG9jYWxcIiksXG4gIClcbiAgcHVibGljIG5hbWU6IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHJvb3Q6IENvbmZpZ0NvbnRleHQsIG5hbWU6IHN0cmluZykge1xuICAgIHN1cGVyKHJvb3QpXG4gICAgdGhpcy5uYW1lID0gbmFtZVxuICB9XG59XG5cbmNvbnN0IGV4YW1wbGVWZXJzaW9uID0gXCJ2MTdhZDRjYjNmZFwiXG5cbmNsYXNzIE1vZHVsZUNvbnRleHQgZXh0ZW5kcyBDb25maWdDb250ZXh0IHtcbiAgQHNjaGVtYShKb2kuc3RyaW5nKCkuZGVzY3JpcHRpb24oXCJUaGUgbG9jYWwgcGF0aCBvZiB0aGUgbW9kdWxlLlwiKS5leGFtcGxlKFwiL2hvbWUvbWUvY29kZS9teS1wcm9qZWN0L215LW1vZHVsZVwiKSlcbiAgcHVibGljIHBhdGg6IHN0cmluZ1xuXG4gIEBzY2hlbWEoSm9pLnN0cmluZygpLmRlc2NyaXB0aW9uKFwiVGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgbW9kdWxlLlwiKS5leGFtcGxlKGV4YW1wbGVWZXJzaW9uKSlcbiAgcHVibGljIHZlcnNpb246IHN0cmluZ1xuXG4gIEBzY2hlbWEoXG4gICAgSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgYnVpbGQgcGF0aCBvZiB0aGUgbW9kdWxlLlwiKVxuICAgICAgLmV4YW1wbGUoXCIvaG9tZS9tZS9jb2RlL215LXByb2plY3QvLmdhcmRlbi9idWlsZC9teS1tb2R1bGVcIiksXG4gIClcbiAgcHVibGljIGJ1aWxkUGF0aDogc3RyaW5nXG5cbiAgY29uc3RydWN0b3Iocm9vdDogQ29uZmlnQ29udGV4dCwgbW9kdWxlOiBNb2R1bGUpIHtcbiAgICBzdXBlcihyb290KVxuICAgIHRoaXMucGF0aCA9IG1vZHVsZS5wYXRoXG4gICAgdGhpcy52ZXJzaW9uID0gbW9kdWxlLnZlcnNpb24udmVyc2lvblN0cmluZ1xuICAgIHRoaXMuYnVpbGRQYXRoID0gbW9kdWxlLmJ1aWxkUGF0aFxuICB9XG59XG5cbmNvbnN0IGV4YW1wbGVPdXRwdXRzID0geyBpbmdyZXNzOiBcImh0dHA6Ly9teS1zZXJ2aWNlL3BhdGgvdG8vZW5kcG9pbnRcIiB9XG5cbmNsYXNzIFNlcnZpY2VDb250ZXh0IGV4dGVuZHMgQ29uZmlnQ29udGV4dCB7XG4gIEBzY2hlbWEoXG4gICAgam9pSWRlbnRpZmllck1hcChqb2lQcmltaXRpdmUoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG91dHB1dHMgZGVmaW5lZCBieSB0aGUgc2VydmljZSAoc2VlIGluZGl2aWR1YWwgcGx1Z2lucyBmb3IgZGV0YWlscykuXCIpXG4gICAgICAuZXhhbXBsZShleGFtcGxlT3V0cHV0cyksXG4gICAgKSlcbiAgcHVibGljIG91dHB1dHM6IFByaW1pdGl2ZU1hcFxuXG4gIEBzY2hlbWEoSm9pLnN0cmluZygpLmRlc2NyaXB0aW9uKFwiVGhlIGN1cnJlbnQgdmVyc2lvbiBvZiB0aGUgc2VydmljZS5cIikuZXhhbXBsZShleGFtcGxlVmVyc2lvbikpXG4gIHB1YmxpYyB2ZXJzaW9uOiBzdHJpbmdcblxuICAvLyBUT0RPOiBhZGQgaW5ncmVzc2VzXG5cbiAgY29uc3RydWN0b3Iocm9vdDogQ29uZmlnQ29udGV4dCwgc2VydmljZTogU2VydmljZSwgb3V0cHV0czogUHJpbWl0aXZlTWFwKSB7XG4gICAgc3VwZXIocm9vdClcbiAgICB0aGlzLm91dHB1dHMgPSBvdXRwdXRzXG4gICAgdGhpcy52ZXJzaW9uID0gc2VydmljZS5tb2R1bGUudmVyc2lvbi52ZXJzaW9uU3RyaW5nXG4gIH1cbn1cblxuLyoqXG4gKiBUaGlzIGNvbnRleHQgaXMgYXZhaWxhYmxlIGZvciB0ZW1wbGF0ZSBzdHJpbmdzIHVuZGVyIHRoZSBgbW9kdWxlYCBrZXkgaW4gY29uZmlndXJhdGlvbiBmaWxlcy5cbiAqIEl0IGlzIGEgc3VwZXJzZXQgb2YgdGhlIGNvbnRleHQgYXZhaWxhYmxlIHVuZGVyIHRoZSBgcHJvamVjdGAga2V5LlxuICovXG5leHBvcnQgY2xhc3MgTW9kdWxlQ29uZmlnQ29udGV4dCBleHRlbmRzIFByb2plY3RDb25maWdDb250ZXh0IHtcbiAgQHNjaGVtYShcbiAgICBFbnZpcm9ubWVudENvbnRleHQuZ2V0U2NoZW1hKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIkluZm9ybWF0aW9uIGFib3V0IHRoZSBlbnZpcm9ubWVudCB0aGF0IEdhcmRlbiBpcyBydW5uaW5nIGFnYWluc3QuXCIpLFxuICApXG4gIHB1YmxpYyBlbnZpcm9ubWVudDogRW52aXJvbm1lbnRDb250ZXh0XG5cbiAgQHNjaGVtYShcbiAgICBqb2lJZGVudGlmaWVyTWFwKE1vZHVsZUNvbnRleHQuZ2V0U2NoZW1hKCkpXG4gICAgICAuZGVzY3JpcHRpb24oXCJSZXRyaWV2ZSBpbmZvcm1hdGlvbiBhYm91dCBtb2R1bGVzIHRoYXQgYXJlIGRlZmluZWQgaW4gdGhlIHByb2plY3QuXCIpXG4gICAgICAuZXhhbXBsZSh7IFwibXktbW9kdWxlXCI6IHsgcGF0aDogXCIvaG9tZS9tZS9jb2RlL215LXByb2plY3QvbXktbW9kdWxlXCIsIHZlcnNpb246IGV4YW1wbGVWZXJzaW9uIH0gfSksXG4gIClcbiAgcHVibGljIG1vZHVsZXM6IE1hcDxzdHJpbmcsICgpID0+IFByb21pc2U8TW9kdWxlQ29udGV4dD4+XG5cbiAgQHNjaGVtYShcbiAgICBqb2lJZGVudGlmaWVyTWFwKFNlcnZpY2VDb250ZXh0LmdldFNjaGVtYSgpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiUmV0cmlldmUgaW5mb3JtYXRpb24gYWJvdXQgc2VydmljZXMgdGhhdCBhcmUgZGVmaW5lZCBpbiB0aGUgcHJvamVjdC5cIilcbiAgICAgIC5leGFtcGxlKHsgXCJteS1zZXJ2aWNlXCI6IHsgb3V0cHV0czogZXhhbXBsZU91dHB1dHMsIHZlcnNpb246IGV4YW1wbGVWZXJzaW9uIH0gfSksXG4gIClcbiAgcHVibGljIHNlcnZpY2VzOiBNYXA8c3RyaW5nLCAoKSA9PiBQcm9taXNlPFNlcnZpY2VDb250ZXh0Pj5cblxuICBAc2NoZW1hKFxuICAgIGpvaUlkZW50aWZpZXJNYXAocHJvdmlkZXJDb25maWdCYXNlU2NoZW1hKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSBtYXAgb2YgYWxsIGNvbmZpZ3VyZWQgcGx1Z2lucy9wcm92aWRlcnMgZm9yIHRoaXMgZW52aXJvbm1lbnQgYW5kIHRoZWlyIGNvbmZpZ3VyYXRpb24uXCIpXG4gICAgICAuZXhhbXBsZSh7IGt1YmVybmV0ZXM6IHsgbmFtZTogXCJsb2NhbC1rdWJlcm5ldGVzXCIsIGNvbnRleHQ6IFwibXkta3ViZS1jb250ZXh0XCIgfSB9KSxcbiAgKVxuICBwdWJsaWMgcHJvdmlkZXJzOiBNYXA8c3RyaW5nLCBQcm92aWRlcj5cblxuICAvLyBOT1RFOiBUaGlzIGhhcyBzb21lIG5lZ2F0aXZlIHBlcmZvcm1hbmNlIGltcGxpY2F0aW9ucyBhbmQgbWF5IG5vdCBiZSBzb21ldGhpbmcgd2Ugd2FudCB0byBzdXBwb3J0LFxuICAvLyAgICAgICBzbyBJJ20gZGlzYWJsaW5nIHRoaXMgZmVhdHVyZSBmb3Igbm93LlxuICAvL1xuICAvLyBAZGVzY3JpcHRpb24oXCJVc2UgdGhpcyB0byBsb29rIHVwIHZhbHVlcyB0aGF0IGFyZSBjb25maWd1cmVkIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlwiKVxuICAvLyBwdWJsaWMgY29uZmlnOiBSZW1vdGVDb25maWdDb250ZXh0XG5cbiAgQHNjaGVtYShcbiAgICBqb2lJZGVudGlmaWVyTWFwKGpvaVByaW1pdGl2ZSgpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSBtYXAgb2YgYWxsIHZhcmlhYmxlcyBkZWZpbmVkIGluIHRoZSBwcm9qZWN0IGNvbmZpZ3VyYXRpb24uXCIpXG4gICAgICAuZXhhbXBsZSh7IFwidGVhbS1uYW1lXCI6IFwiYmFuYW5hcmFtYWxsYW1hXCIsIFwic29tZS1zZXJ2aWNlLWVuZHBvaW50XCI6IFwiaHR0cHM6Ly9zb21lc2VydmljZS5jb20vYXBpL3YyXCIgfSksXG4gIClcbiAgcHVibGljIHZhcmlhYmxlczogUHJpbWl0aXZlTWFwXG5cbiAgY29uc3RydWN0b3IoXG4gICAgZ2FyZGVuOiBHYXJkZW4sXG4gICAgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIG1vZHVsZUNvbmZpZ3M6IE1vZHVsZUNvbmZpZ1tdLFxuICApIHtcbiAgICBzdXBlcigpXG5cbiAgICBjb25zdCBfdGhpcyA9IHRoaXNcblxuICAgIHRoaXMuZW52aXJvbm1lbnQgPSBuZXcgRW52aXJvbm1lbnRDb250ZXh0KF90aGlzLCBlbnZpcm9ubWVudC5uYW1lKVxuXG4gICAgdGhpcy5tb2R1bGVzID0gbmV3IE1hcChtb2R1bGVDb25maWdzLm1hcCgoY29uZmlnKSA9PlxuICAgICAgPFtzdHJpbmcsICgpID0+IFByb21pc2U8TW9kdWxlQ29udGV4dD5dPltjb25maWcubmFtZSwgYXN5bmMgKCkgPT4ge1xuICAgICAgICBjb25zdCBtb2R1bGUgPSBhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlKGNvbmZpZy5uYW1lKVxuICAgICAgICByZXR1cm4gbmV3IE1vZHVsZUNvbnRleHQoX3RoaXMsIG1vZHVsZSlcbiAgICAgIH1dLFxuICAgICkpXG5cbiAgICBjb25zdCBzZXJ2aWNlTmFtZXMgPSBmbGF0dGVuKG1vZHVsZUNvbmZpZ3MubWFwKG0gPT4gbS5zZXJ2aWNlQ29uZmlncykpLm1hcChzID0+IHMubmFtZSlcblxuICAgIHRoaXMuc2VydmljZXMgPSBuZXcgTWFwKHNlcnZpY2VOYW1lcy5tYXAoKG5hbWUpID0+XG4gICAgICA8W3N0cmluZywgKCkgPT4gUHJvbWlzZTxTZXJ2aWNlQ29udGV4dD5dPltuYW1lLCBhc3luYyAoKSA9PiB7XG4gICAgICAgIGNvbnN0IHNlcnZpY2UgPSBhd2FpdCBnYXJkZW4uZ2V0U2VydmljZShuYW1lKVxuICAgICAgICBjb25zdCBvdXRwdXRzID0ge1xuICAgICAgICAgIC4uLnNlcnZpY2UuY29uZmlnLm91dHB1dHMsXG4gICAgICAgICAgLi4uYXdhaXQgZ2FyZGVuLmFjdGlvbnMuZ2V0U2VydmljZU91dHB1dHMoeyBzZXJ2aWNlIH0pLFxuICAgICAgICB9XG4gICAgICAgIHJldHVybiBuZXcgU2VydmljZUNvbnRleHQoX3RoaXMsIHNlcnZpY2UsIG91dHB1dHMpXG4gICAgICB9XSxcbiAgICApKVxuXG4gICAgdGhpcy5wcm92aWRlcnMgPSBuZXcgTWFwKGVudmlyb25tZW50LnByb3ZpZGVycy5tYXAocCA9PiA8W3N0cmluZywgUHJvdmlkZXJdPltwLm5hbWUsIHBdKSlcblxuICAgIC8vIHRoaXMuY29uZmlnID0gbmV3IFNlY3JldHNDb250ZXh0Tm9kZShjdHgpXG5cbiAgICB0aGlzLnZhcmlhYmxlcyA9IGVudmlyb25tZW50LnZhcmlhYmxlc1xuICB9XG59XG5cbi8vIGNsYXNzIFJlbW90ZUNvbmZpZ0NvbnRleHQgZXh0ZW5kcyBDb25maWdDb250ZXh0IHtcbi8vICAgY29uc3RydWN0b3IocHJpdmF0ZSBjdHg6IFBsdWdpbkNvbnRleHQpIHtcbi8vICAgICBzdXBlcigpXG4vLyAgIH1cblxuLy8gICBhc3luYyByZXNvbHZlKHsga2V5IH06IFJlc29sdmVQYXJhbXMpIHtcbi8vICAgICBjb25zdCB7IHZhbHVlIH0gPSBhd2FpdCB0aGlzLmN0eC5nZXRTZWNyZXQoeyBrZXkgfSlcbi8vICAgICByZXR1cm4gdmFsdWUgPT09IG51bGwgPyB1bmRlZmluZWQgOiB2YWx1ZVxuLy8gICB9XG4vLyB9XG4iXX0= diff --git a/garden-service/build/config/module.d.ts b/garden-service/build/config/module.d.ts new file mode 100644 index 00000000000..fafe81be637 --- /dev/null +++ b/garden-service/build/config/module.d.ts @@ -0,0 +1,39 @@ +import * as Joi from "joi"; +import { ServiceConfig, ServiceSpec } from "./service"; +import { PrimitiveMap } from "./common"; +import { TestConfig, TestSpec } from "./test"; +export interface BuildCopySpec { + source: string; + target: string; +} +export interface BuildDependencyConfig { + name: string; + plugin?: string; + copy: BuildCopySpec[]; +} +export declare const buildDependencySchema: Joi.ObjectSchema; +export interface BuildConfig { + command: string[]; + dependencies: BuildDependencyConfig[]; +} +export interface ModuleSpec { +} +export interface BaseModuleSpec { + allowPublish: boolean; + build: BuildConfig; + description?: string; + name: string; + path: string; + type: string; + variables: PrimitiveMap; + repositoryUrl?: string; +} +export declare const baseModuleSpecSchema: Joi.ObjectSchema; +export interface ModuleConfig extends BaseModuleSpec { + plugin?: string; + serviceConfigs: ServiceConfig[]; + testConfigs: TestConfig[]; + spec: M; +} +export declare const moduleConfigSchema: Joi.ObjectSchema; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/module.js b/garden-service/build/config/module.js new file mode 100644 index 00000000000..51ccf8d6cbe --- /dev/null +++ b/garden-service/build/config/module.js @@ -0,0 +1,76 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const common_1 = require("./common"); +// TODO: allow : delimited string (e.g. some.file:some-dir/) +const copySchema = Joi.object() + .keys({ + // TODO: allow array of strings here + // TODO: disallow paths outside of the module root + source: Joi.string().uri({ relativeOnly: true }).required() + .description("POSIX-style path or filename of the directory or file(s) to copy to the target."), + target: Joi.string().uri({ relativeOnly: true }).default("") + .description("POSIX-style path or filename to copy the directory or file(s) to (defaults to same as source path)."), +}); +exports.buildDependencySchema = Joi.object().keys({ + name: common_1.joiIdentifier().required() + .description("Module name to build ahead of this module"), + plugin: common_1.joiIdentifier() + .meta({ internal: true }) + .description("The name of plugin that provides the build dependency."), + copy: common_1.joiArray(copySchema) + .description("Specify one or more files or directories to copy from the built dependency to this module."), +}); +exports.baseModuleSpecSchema = Joi.object() + .keys({ + type: common_1.joiIdentifier() + .required() + .description("The type of this module.") + .example("container"), + name: common_1.joiIdentifier() + .required() + .description("The name of this module.") + .example("my-sweet-module"), + description: Joi.string(), + repositoryUrl: common_1.joiRepositoryUrl() + .description("A remote repository URL to fetch the module from. Garden will read the garden.yml config" + + " from the local module." + + " Currently only supports git servers."), + variables: common_1.joiVariables() + .description("Variables that this module can reference and expose as environment variables.") + .example({ "my-variable": "some-value" }), + allowPublish: Joi.boolean() + .default(true) + .description("Set to false to disable pushing this module to remote registries."), + build: Joi.object().keys({ + // TODO: move this out of base spec + command: common_1.joiArray(Joi.string()) + .description("The command to run inside the module directory to perform the build.") + .example(["npm", "run", "build"]), + dependencies: common_1.joiArray(exports.buildDependencySchema) + .description("A list of modules that must be built before this module is built.") + .example([{ name: "some-other-module-name" }]), + }) + .default(() => ({ dependencies: [] }), "{}") + .description("Specify how to build the module. Note that plugins may specify additional keys on this object."), +}) + .required() + .unknown(true) + .description("Configure a module whose sources are located in this directory.") + .meta({ extendable: true }); +exports.moduleConfigSchema = exports.baseModuleSpecSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The module spec, as defined by the provider plugin."), +}) + .description("The configuration for a module."); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QztLQUNELFFBQVEsRUFBRTtLQUNWLE9BQU8sQ0FBQyxJQUFJLENBQUM7S0FDYixXQUFXLENBQUMsaUVBQWlFLENBQUM7S0FDOUUsSUFBSSxDQUFDLEVBQUUsVUFBVSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7QUFlaEIsUUFBQSxrQkFBa0IsR0FBRyw0QkFBb0I7S0FDbkQsSUFBSSxDQUFDO0lBQ0osSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDZixJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDMUIsV0FBVyxDQUFDLHFEQUFxRCxDQUFDO0NBQ3RFLENBQUM7S0FDRCxXQUFXLENBQUMsaUNBQWlDLENBQUMsQ0FBQSIsImZpbGUiOiJjb25maWcvbW9kdWxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IFNlcnZpY2VDb25maWcsIFNlcnZpY2VTcGVjIH0gZnJvbSBcIi4vc2VydmljZVwiXG5pbXBvcnQge1xuICBqb2lBcnJheSxcbiAgam9pSWRlbnRpZmllcixcbiAgam9pVmFyaWFibGVzLFxuICBQcmltaXRpdmVNYXAsXG4gIGpvaVJlcG9zaXRvcnlVcmwsXG59IGZyb20gXCIuL2NvbW1vblwiXG5pbXBvcnQgeyBUZXN0Q29uZmlnLCBUZXN0U3BlYyB9IGZyb20gXCIuL3Rlc3RcIlxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkQ29weVNwZWMge1xuICBzb3VyY2U6IHN0cmluZ1xuICB0YXJnZXQ6IHN0cmluZ1xufVxuXG4vLyBUT0RPOiBhbGxvdyA6IGRlbGltaXRlZCBzdHJpbmcgKGUuZy4gc29tZS5maWxlOnNvbWUtZGlyLylcbmNvbnN0IGNvcHlTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIC8vIFRPRE86IGFsbG93IGFycmF5IG9mIHN0cmluZ3MgaGVyZVxuICAgIC8vIFRPRE86IGRpc2FsbG93IHBhdGhzIG91dHNpZGUgb2YgdGhlIG1vZHVsZSByb290XG4gICAgc291cmNlOiBKb2kuc3RyaW5nKCkudXJpKDxhbnk+eyByZWxhdGl2ZU9ubHk6IHRydWUgfSkucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiUE9TSVgtc3R5bGUgcGF0aCBvciBmaWxlbmFtZSBvZiB0aGUgZGlyZWN0b3J5IG9yIGZpbGUocykgdG8gY29weSB0byB0aGUgdGFyZ2V0LlwiKSxcbiAgICB0YXJnZXQ6IEpvaS5zdHJpbmcoKS51cmkoPGFueT57IHJlbGF0aXZlT25seTogdHJ1ZSB9KS5kZWZhdWx0KFwiXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiUE9TSVgtc3R5bGUgcGF0aCBvciBmaWxlbmFtZSB0byBjb3B5IHRoZSBkaXJlY3Rvcnkgb3IgZmlsZShzKSB0byAoZGVmYXVsdHMgdG8gc2FtZSBhcyBzb3VyY2UgcGF0aCkuXCIsXG4gICAgICApLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkRGVwZW5kZW5jeUNvbmZpZyB7XG4gIG5hbWU6IHN0cmluZ1xuICBwbHVnaW4/OiBzdHJpbmdcbiAgY29weTogQnVpbGRDb3B5U3BlY1tdXG59XG5cbmV4cG9ydCBjb25zdCBidWlsZERlcGVuZGVuY3lTY2hlbWEgPSBKb2kub2JqZWN0KCkua2V5cyh7XG4gIG5hbWU6IGpvaUlkZW50aWZpZXIoKS5yZXF1aXJlZCgpXG4gICAgLmRlc2NyaXB0aW9uKFwiTW9kdWxlIG5hbWUgdG8gYnVpbGQgYWhlYWQgb2YgdGhpcyBtb2R1bGVcIiksXG4gIHBsdWdpbjogam9pSWRlbnRpZmllcigpXG4gICAgLm1ldGEoeyBpbnRlcm5hbDogdHJ1ZSB9KVxuICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHBsdWdpbiB0aGF0IHByb3ZpZGVzIHRoZSBidWlsZCBkZXBlbmRlbmN5LlwiKSxcbiAgY29weTogam9pQXJyYXkoY29weVNjaGVtYSlcbiAgICAuZGVzY3JpcHRpb24oXCJTcGVjaWZ5IG9uZSBvciBtb3JlIGZpbGVzIG9yIGRpcmVjdG9yaWVzIHRvIGNvcHkgZnJvbSB0aGUgYnVpbHQgZGVwZW5kZW5jeSB0byB0aGlzIG1vZHVsZS5cIiksXG59KVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkQ29uZmlnIHtcbiAgY29tbWFuZDogc3RyaW5nW10sXG4gIGRlcGVuZGVuY2llczogQnVpbGREZXBlbmRlbmN5Q29uZmlnW10sXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlU3BlYyB7IH1cblxuZXhwb3J0IGludGVyZmFjZSBCYXNlTW9kdWxlU3BlYyB7XG4gIGFsbG93UHVibGlzaDogYm9vbGVhblxuICBidWlsZDogQnVpbGRDb25maWdcbiAgZGVzY3JpcHRpb24/OiBzdHJpbmdcbiAgbmFtZTogc3RyaW5nXG4gIHBhdGg6IHN0cmluZ1xuICB0eXBlOiBzdHJpbmdcbiAgdmFyaWFibGVzOiBQcmltaXRpdmVNYXBcbiAgcmVwb3NpdG9yeVVybD86IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3QgYmFzZU1vZHVsZVNwZWNTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIHR5cGU6IGpvaUlkZW50aWZpZXIoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSB0eXBlIG9mIHRoaXMgbW9kdWxlLlwiKVxuICAgICAgLmV4YW1wbGUoXCJjb250YWluZXJcIiksXG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhpcyBtb2R1bGUuXCIpXG4gICAgICAuZXhhbXBsZShcIm15LXN3ZWV0LW1vZHVsZVwiKSxcbiAgICBkZXNjcmlwdGlvbjogSm9pLnN0cmluZygpLFxuICAgIHJlcG9zaXRvcnlVcmw6IGpvaVJlcG9zaXRvcnlVcmwoKVxuICAgICAgLmRlc2NyaXB0aW9uKFxuICAgICAgICBcIkEgcmVtb3RlIHJlcG9zaXRvcnkgVVJMIHRvIGZldGNoIHRoZSBtb2R1bGUgZnJvbS4gR2FyZGVuIHdpbGwgcmVhZCB0aGUgZ2FyZGVuLnltbCBjb25maWdcIiArXG4gICAgICAgIFwiIGZyb20gdGhlIGxvY2FsIG1vZHVsZS5cIiArXG4gICAgICAgIFwiIEN1cnJlbnRseSBvbmx5IHN1cHBvcnRzIGdpdCBzZXJ2ZXJzLlwiLFxuICAgICAgKSxcbiAgICB2YXJpYWJsZXM6IGpvaVZhcmlhYmxlcygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJWYXJpYWJsZXMgdGhhdCB0aGlzIG1vZHVsZSBjYW4gcmVmZXJlbmNlIGFuZCBleHBvc2UgYXMgZW52aXJvbm1lbnQgdmFyaWFibGVzLlwiKVxuICAgICAgLmV4YW1wbGUoeyBcIm15LXZhcmlhYmxlXCI6IFwic29tZS12YWx1ZVwiIH0pLFxuICAgIGFsbG93UHVibGlzaDogSm9pLmJvb2xlYW4oKVxuICAgICAgLmRlZmF1bHQodHJ1ZSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNldCB0byBmYWxzZSB0byBkaXNhYmxlIHB1c2hpbmcgdGhpcyBtb2R1bGUgdG8gcmVtb3RlIHJlZ2lzdHJpZXMuXCIpLFxuICAgIGJ1aWxkOiBKb2kub2JqZWN0KCkua2V5cyh7XG4gICAgICAvLyBUT0RPOiBtb3ZlIHRoaXMgb3V0IG9mIGJhc2Ugc3BlY1xuICAgICAgY29tbWFuZDogam9pQXJyYXkoSm9pLnN0cmluZygpKVxuICAgICAgICAuZGVzY3JpcHRpb24oXCJUaGUgY29tbWFuZCB0byBydW4gaW5zaWRlIHRoZSBtb2R1bGUgZGlyZWN0b3J5IHRvIHBlcmZvcm0gdGhlIGJ1aWxkLlwiKVxuICAgICAgICAuZXhhbXBsZShbXCJucG1cIiwgXCJydW5cIiwgXCJidWlsZFwiXSksXG4gICAgICBkZXBlbmRlbmNpZXM6IGpvaUFycmF5KGJ1aWxkRGVwZW5kZW5jeVNjaGVtYSlcbiAgICAgICAgLmRlc2NyaXB0aW9uKFwiQSBsaXN0IG9mIG1vZHVsZXMgdGhhdCBtdXN0IGJlIGJ1aWx0IGJlZm9yZSB0aGlzIG1vZHVsZSBpcyBidWlsdC5cIilcbiAgICAgICAgLmV4YW1wbGUoW3sgbmFtZTogXCJzb21lLW90aGVyLW1vZHVsZS1uYW1lXCIgfV0pLFxuICAgIH0pXG4gICAgICAuZGVmYXVsdCgoKSA9PiAoeyBkZXBlbmRlbmNpZXM6IFtdIH0pLCBcInt9XCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJTcGVjaWZ5IGhvdyB0byBidWlsZCB0aGUgbW9kdWxlLiBOb3RlIHRoYXQgcGx1Z2lucyBtYXkgc3BlY2lmeSBhZGRpdGlvbmFsIGtleXMgb24gdGhpcyBvYmplY3QuXCIpLFxuICB9KVxuICAucmVxdWlyZWQoKVxuICAudW5rbm93bih0cnVlKVxuICAuZGVzY3JpcHRpb24oXCJDb25maWd1cmUgYSBtb2R1bGUgd2hvc2Ugc291cmNlcyBhcmUgbG9jYXRlZCBpbiB0aGlzIGRpcmVjdG9yeS5cIilcbiAgLm1ldGEoeyBleHRlbmRhYmxlOiB0cnVlIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlQ29uZmlnXG4gIDxNIGV4dGVuZHMgTW9kdWxlU3BlYyA9IGFueSwgUyBleHRlbmRzIFNlcnZpY2VTcGVjID0gYW55LCBUIGV4dGVuZHMgVGVzdFNwZWMgPSBhbnk+XG4gIGV4dGVuZHMgQmFzZU1vZHVsZVNwZWMge1xuXG4gIHBsdWdpbj86IHN0cmluZyAgIC8vIHVzZWQgdG8gaWRlbnRpZnkgbW9kdWxlcyB0aGF0IGFyZSBidW5kbGVkIGFzIHBhcnQgb2YgYSBwbHVnaW5cblxuICBzZXJ2aWNlQ29uZmlnczogU2VydmljZUNvbmZpZzxTPltdXG4gIHRlc3RDb25maWdzOiBUZXN0Q29uZmlnPFQ+W11cblxuICAvLyBQbHVnaW5zIGNhbiBhZGQgY3VzdG9tIGZpZWxkcyB0aGF0IGFyZSBrZXB0IGhlcmVcbiAgc3BlYzogTVxufVxuXG5leHBvcnQgY29uc3QgbW9kdWxlQ29uZmlnU2NoZW1hID0gYmFzZU1vZHVsZVNwZWNTY2hlbWFcbiAgLmtleXMoe1xuICAgIHNwZWM6IEpvaS5vYmplY3QoKVxuICAgICAgLm1ldGEoeyBleHRlbmRhYmxlOiB0cnVlIH0pXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbW9kdWxlIHNwZWMsIGFzIGRlZmluZWQgYnkgdGhlIHByb3ZpZGVyIHBsdWdpbi5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIlRoZSBjb25maWd1cmF0aW9uIGZvciBhIG1vZHVsZS5cIilcbiJdfQ== diff --git a/garden-service/build/config/project.d.ts b/garden-service/build/config/project.d.ts new file mode 100644 index 00000000000..301a2536c33 --- /dev/null +++ b/garden-service/build/config/project.d.ts @@ -0,0 +1,43 @@ +import * as Joi from "joi"; +import { Primitive } from "./common"; +export interface ProviderConfig { + name: string; + [key: string]: any; +} +export declare const providerConfigBaseSchema: Joi.ObjectSchema; +export interface Provider { + name: string; + config: T; +} +export interface CommonEnvironmentConfig { + providers: ProviderConfig[]; + variables: { + [key: string]: Primitive; + }; +} +export declare const environmentConfigSchema: Joi.ObjectSchema; +export interface Environment extends CommonEnvironmentConfig { + name: string; +} +export declare const environmentSchema: Joi.ObjectSchema; +export interface SourceConfig { + name: string; + repositoryUrl: string; +} +export declare const projectSourceSchema: Joi.ObjectSchema; +export declare const projectSourcesSchema: Joi.ArraySchema; +export interface ProjectConfig { + name: string; + defaultEnvironment: string; + environmentDefaults: CommonEnvironmentConfig; + environments: Environment[]; + sources?: SourceConfig[]; +} +export declare const defaultProviders: { + name: string; +}[]; +export declare const defaultEnvironments: Environment[]; +export declare const projectNameSchema: Joi.StringSchema; +export declare const projectSchema: Joi.ObjectSchema; +export declare const defaultProvider: Provider; +//# sourceMappingURL=project.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/project.js b/garden-service/build/config/project.js new file mode 100644 index 00000000000..c5e410c45a0 --- /dev/null +++ b/garden-service/build/config/project.js @@ -0,0 +1,94 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const js_yaml_1 = require("js-yaml"); +const common_1 = require("./common"); +exports.providerConfigBaseSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier().required() + .description("The name of the provider plugin to configure.") + .example("local-kubernetes"), +}) + .unknown(true) + .meta({ extendable: true }); +exports.environmentConfigSchema = Joi.object() + .keys({ + providers: common_1.joiArray(exports.providerConfigBaseSchema) + .unique("name") + .description("A list of providers that should be used for this environment, and their configuration. " + + "Please refer to individual plugins/providers for details on how to configure them."), + variables: common_1.joiVariables() + .description("A key/value map of variables that modules can reference when using this environment."), +}); +exports.environmentSchema = exports.environmentConfigSchema + .keys({ + name: Joi.string() + .required() + .description("The name of the current environment."), +}); +exports.projectSourceSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("The name of the source to import"), + repositoryUrl: common_1.joiRepositoryUrl() + .required(), +}); +exports.projectSourcesSchema = common_1.joiArray(exports.projectSourceSchema) + .unique("name") + .description("A list of remote sources to import into project"); +exports.defaultProviders = [ + { name: "container" }, +]; +exports.defaultEnvironments = [ + { + name: "local", + providers: [ + { + name: "local-kubernetes", + }, + ], + variables: {}, + }, +]; +const environmentDefaults = { + providers: [], + variables: {}, +}; +exports.projectNameSchema = common_1.joiIdentifier() + .required() + .description("The name of the project.") + .example("my-sweet-project"); +exports.projectSchema = Joi.object() + .keys({ + name: exports.projectNameSchema, + defaultEnvironment: Joi.string() + .default("", "") + .description("The default environment to use when calling commands without the `--env` parameter."), + environmentDefaults: exports.environmentConfigSchema + .default(() => environmentDefaults, js_yaml_1.safeDump(environmentDefaults)) + .example(environmentDefaults) + .description("Default environment settings, that are inherited (but can be overridden) by each configured environment"), + environments: common_1.joiArray(exports.environmentConfigSchema.keys({ name: common_1.joiIdentifier().required() })) + .unique("name") + .default(() => (Object.assign({}, exports.defaultEnvironments)), js_yaml_1.safeDump(exports.defaultEnvironments)) + .description("A list of environments to configure for the project.") + .example(exports.defaultEnvironments), + sources: exports.projectSourcesSchema, +}) + .required() + .description("The configuration for a Garden project. This should be specified in the garden.yml file in your project root."); +// this is used for default handlers in the action handler +exports.defaultProvider = { + name: "_default", + config: {}, +}; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFJLEVBQUUsc0JBQWEsRUFBRSxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUMsQ0FBQztTQUN2RixNQUFNLENBQUMsTUFBTSxDQUFDO1NBQ2QsT0FBTyxDQUFDLEdBQUcsRUFBRSxDQUFDLG1CQUFNLDJCQUFtQixFQUFHLEVBQUUsa0JBQVEsQ0FBQywyQkFBbUIsQ0FBQyxDQUFDO1NBQzFFLFdBQVcsQ0FBQyxzREFBc0QsQ0FBQztTQUNuRSxPQUFPLENBQUMsMkJBQW1CLENBQUM7SUFDL0IsT0FBTyxFQUFFLDRCQUFvQjtDQUM5QixDQUFDO0tBQ0QsUUFBUSxFQUFFO0tBQ1YsV0FBVyxDQUNWLCtHQUErRyxDQUNoSCxDQUFBO0FBRUgsMERBQTBEO0FBQzdDLFFBQUEsZUFBZSxHQUFhO0lBQ3ZDLElBQUksRUFBRSxVQUFVO0lBQ2hCLE1BQU0sRUFBRSxFQUFFO0NBQ1gsQ0FBQSIsImZpbGUiOiJjb25maWcvcHJvamVjdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyBzYWZlRHVtcCB9IGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCB7XG4gIGpvaUFycmF5LFxuICBqb2lJZGVudGlmaWVyLFxuICBqb2lWYXJpYWJsZXMsXG4gIFByaW1pdGl2ZSxcbiAgam9pUmVwb3NpdG9yeVVybCxcbn0gZnJvbSBcIi4vY29tbW9uXCJcblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlckNvbmZpZyB7XG4gIG5hbWU6IHN0cmluZ1xuICBba2V5OiBzdHJpbmddOiBhbnlcbn1cblxuZXhwb3J0IGNvbnN0IHByb3ZpZGVyQ29uZmlnQmFzZVNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBwcm92aWRlciBwbHVnaW4gdG8gY29uZmlndXJlLlwiKVxuICAgICAgLmV4YW1wbGUoXCJsb2NhbC1rdWJlcm5ldGVzXCIpLFxuICB9KVxuICAudW5rbm93bih0cnVlKVxuICAubWV0YSh7IGV4dGVuZGFibGU6IHRydWUgfSlcblxuZXhwb3J0IGludGVyZmFjZSBQcm92aWRlcjxUIGV4dGVuZHMgUHJvdmlkZXJDb25maWcgPSBhbnk+IHtcbiAgbmFtZTogc3RyaW5nXG4gIGNvbmZpZzogVFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbW1vbkVudmlyb25tZW50Q29uZmlnIHtcbiAgcHJvdmlkZXJzOiBQcm92aWRlckNvbmZpZ1tdICAvLyBmdXJ0aGVyIHZhbGlkYXRlZCBieSBlYWNoIHBsdWdpblxuICB2YXJpYWJsZXM6IHsgW2tleTogc3RyaW5nXTogUHJpbWl0aXZlIH1cbn1cblxuZXhwb3J0IGNvbnN0IGVudmlyb25tZW50Q29uZmlnU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBwcm92aWRlcnM6IGpvaUFycmF5KHByb3ZpZGVyQ29uZmlnQmFzZVNjaGVtYSlcbiAgICAgIC51bmlxdWUoXCJuYW1lXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiQSBsaXN0IG9mIHByb3ZpZGVycyB0aGF0IHNob3VsZCBiZSB1c2VkIGZvciB0aGlzIGVudmlyb25tZW50LCBhbmQgdGhlaXIgY29uZmlndXJhdGlvbi4gXCIgK1xuICAgICAgICBcIlBsZWFzZSByZWZlciB0byBpbmRpdmlkdWFsIHBsdWdpbnMvcHJvdmlkZXJzIGZvciBkZXRhaWxzIG9uIGhvdyB0byBjb25maWd1cmUgdGhlbS5cIixcbiAgICAgICksXG4gICAgdmFyaWFibGVzOiBqb2lWYXJpYWJsZXMoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSBrZXkvdmFsdWUgbWFwIG9mIHZhcmlhYmxlcyB0aGF0IG1vZHVsZXMgY2FuIHJlZmVyZW5jZSB3aGVuIHVzaW5nIHRoaXMgZW52aXJvbm1lbnQuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIEVudmlyb25tZW50IGV4dGVuZHMgQ29tbW9uRW52aXJvbm1lbnRDb25maWcge1xuICBuYW1lOiBzdHJpbmdcbn1cblxuZXhwb3J0IGNvbnN0IGVudmlyb25tZW50U2NoZW1hID0gZW52aXJvbm1lbnRDb25maWdTY2hlbWFcbiAgLmtleXMoe1xuICAgIG5hbWU6IEpvaS5zdHJpbmcoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBjdXJyZW50IGVudmlyb25tZW50LlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBTb3VyY2VDb25maWcge1xuICBuYW1lOiBzdHJpbmdcbiAgcmVwb3NpdG9yeVVybDogc3RyaW5nXG59XG5cbmV4cG9ydCBjb25zdCBwcm9qZWN0U291cmNlU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBuYW1lOiBqb2lJZGVudGlmaWVyKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZSBvZiB0aGUgc291cmNlIHRvIGltcG9ydFwiKSxcbiAgICByZXBvc2l0b3J5VXJsOiBqb2lSZXBvc2l0b3J5VXJsKClcbiAgICAgIC5yZXF1aXJlZCgpLFxuICB9KVxuXG5leHBvcnQgY29uc3QgcHJvamVjdFNvdXJjZXNTY2hlbWEgPSBqb2lBcnJheShwcm9qZWN0U291cmNlU2NoZW1hKVxuICAudW5pcXVlKFwibmFtZVwiKVxuICAuZGVzY3JpcHRpb24oXCJBIGxpc3Qgb2YgcmVtb3RlIHNvdXJjZXMgdG8gaW1wb3J0IGludG8gcHJvamVjdFwiKVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2plY3RDb25maWcge1xuICBuYW1lOiBzdHJpbmdcbiAgZGVmYXVsdEVudmlyb25tZW50OiBzdHJpbmdcbiAgZW52aXJvbm1lbnREZWZhdWx0czogQ29tbW9uRW52aXJvbm1lbnRDb25maWdcbiAgZW52aXJvbm1lbnRzOiBFbnZpcm9ubWVudFtdXG4gIHNvdXJjZXM/OiBTb3VyY2VDb25maWdbXVxufVxuXG5leHBvcnQgY29uc3QgZGVmYXVsdFByb3ZpZGVycyA9IFtcbiAgeyBuYW1lOiBcImNvbnRhaW5lclwiIH0sXG5dXG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0RW52aXJvbm1lbnRzOiBFbnZpcm9ubWVudFtdID0gW1xuICB7XG4gICAgbmFtZTogXCJsb2NhbFwiLFxuICAgIHByb3ZpZGVyczogW1xuICAgICAge1xuICAgICAgICBuYW1lOiBcImxvY2FsLWt1YmVybmV0ZXNcIixcbiAgICAgIH0sXG4gICAgXSxcbiAgICB2YXJpYWJsZXM6IHt9LFxuICB9LFxuXVxuXG5jb25zdCBlbnZpcm9ubWVudERlZmF1bHRzID0ge1xuICBwcm92aWRlcnM6IFtdLFxuICB2YXJpYWJsZXM6IHt9LFxufVxuXG5leHBvcnQgY29uc3QgcHJvamVjdE5hbWVTY2hlbWEgPSBqb2lJZGVudGlmaWVyKClcbiAgLnJlcXVpcmVkKClcbiAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhlIHByb2plY3QuXCIpXG4gIC5leGFtcGxlKFwibXktc3dlZXQtcHJvamVjdFwiKVxuXG5leHBvcnQgY29uc3QgcHJvamVjdFNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgbmFtZTogcHJvamVjdE5hbWVTY2hlbWEsXG4gICAgZGVmYXVsdEVudmlyb25tZW50OiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZWZhdWx0KFwiXCIsIFwiPGZpcnN0IHNwZWNpZmllZCBlbnZpcm9ubWVudD5cIilcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBkZWZhdWx0IGVudmlyb25tZW50IHRvIHVzZSB3aGVuIGNhbGxpbmcgY29tbWFuZHMgd2l0aG91dCB0aGUgYC0tZW52YCBwYXJhbWV0ZXIuXCIpLFxuICAgIGVudmlyb25tZW50RGVmYXVsdHM6IGVudmlyb25tZW50Q29uZmlnU2NoZW1hXG4gICAgICAuZGVmYXVsdCgoKSA9PiBlbnZpcm9ubWVudERlZmF1bHRzLCBzYWZlRHVtcChlbnZpcm9ubWVudERlZmF1bHRzKSlcbiAgICAgIC5leGFtcGxlKGVudmlyb25tZW50RGVmYXVsdHMpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiRGVmYXVsdCBlbnZpcm9ubWVudCBzZXR0aW5ncywgdGhhdCBhcmUgaW5oZXJpdGVkIChidXQgY2FuIGJlIG92ZXJyaWRkZW4pIGJ5IGVhY2ggY29uZmlndXJlZCBlbnZpcm9ubWVudFwiLFxuICAgICAgKSxcbiAgICBlbnZpcm9ubWVudHM6IGpvaUFycmF5KGVudmlyb25tZW50Q29uZmlnU2NoZW1hLmtleXMoeyBuYW1lOiBqb2lJZGVudGlmaWVyKCkucmVxdWlyZWQoKSB9KSlcbiAgICAgIC51bmlxdWUoXCJuYW1lXCIpXG4gICAgICAuZGVmYXVsdCgoKSA9PiAoeyAuLi5kZWZhdWx0RW52aXJvbm1lbnRzIH0pLCBzYWZlRHVtcChkZWZhdWx0RW52aXJvbm1lbnRzKSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIkEgbGlzdCBvZiBlbnZpcm9ubWVudHMgdG8gY29uZmlndXJlIGZvciB0aGUgcHJvamVjdC5cIilcbiAgICAgIC5leGFtcGxlKGRlZmF1bHRFbnZpcm9ubWVudHMpLFxuICAgIHNvdXJjZXM6IHByb2plY3RTb3VyY2VzU2NoZW1hLFxuICB9KVxuICAucmVxdWlyZWQoKVxuICAuZGVzY3JpcHRpb24oXG4gICAgXCJUaGUgY29uZmlndXJhdGlvbiBmb3IgYSBHYXJkZW4gcHJvamVjdC4gVGhpcyBzaG91bGQgYmUgc3BlY2lmaWVkIGluIHRoZSBnYXJkZW4ueW1sIGZpbGUgaW4geW91ciBwcm9qZWN0IHJvb3QuXCIsXG4gIClcblxuLy8gdGhpcyBpcyB1c2VkIGZvciBkZWZhdWx0IGhhbmRsZXJzIGluIHRoZSBhY3Rpb24gaGFuZGxlclxuZXhwb3J0IGNvbnN0IGRlZmF1bHRQcm92aWRlcjogUHJvdmlkZXIgPSB7XG4gIG5hbWU6IFwiX2RlZmF1bHRcIixcbiAgY29uZmlnOiB7fSxcbn1cbiJdfQ== diff --git a/garden-service/build/config/service.d.ts b/garden-service/build/config/service.d.ts new file mode 100644 index 00000000000..5d73ee3600e --- /dev/null +++ b/garden-service/build/config/service.d.ts @@ -0,0 +1,16 @@ +import * as Joi from "joi"; +import { PrimitiveMap } from "./common"; +export interface ServiceSpec { +} +export interface BaseServiceSpec extends ServiceSpec { + name: string; + dependencies: string[]; + outputs: PrimitiveMap; +} +export declare const serviceOutputsSchema: Joi.ObjectSchema; +export declare const baseServiceSchema: Joi.ObjectSchema; +export interface ServiceConfig extends BaseServiceSpec { + spec: T; +} +export declare const serviceConfigSchema: Joi.ObjectSchema; +//# sourceMappingURL=service.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/service.js b/garden-service/build/config/service.js new file mode 100644 index 00000000000..8c8a8e3f1ac --- /dev/null +++ b/garden-service/build/config/service.js @@ -0,0 +1,31 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const common_1 = require("./common"); +exports.serviceOutputsSchema = common_1.joiIdentifierMap(common_1.joiPrimitive()); +exports.baseServiceSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier().required(), + dependencies: common_1.joiArray(common_1.joiIdentifier()) + .description("The names of services that this service depends on at runtime."), + outputs: exports.serviceOutputsSchema, +}) + .unknown(true) + .meta({ extendable: true }) + .description("The required attributes of a service. This is generally further defined by plugins."); +exports.serviceConfigSchema = exports.baseServiceSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The service's specification, as defined by its provider plugin."), +}) + .description("The configuration for a module's service."); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbmZpZy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBRUgsMkJBQTBCO0FBQzFCLHFDQUFnRztBQVVuRixRQUFBLG9CQUFvQixHQUFHLHlCQUFnQixDQUFDLHFCQUFZLEVBQUUsQ0FBQyxDQUFBO0FBRXZELFFBQUEsaUJBQWlCLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRTtLQUMxQyxJQUFJLENBQUM7SUFDSixJQUFJLEVBQUUsc0JBQWEsRUFBRSxDQUFDLFFBQVEsRUFBRTtJQUNoQyxZQUFZLEVBQUUsaUJBQVEsQ0FBQyxzQkFBYSxFQUFFLENBQUM7U0FDcEMsV0FBVyxDQUFDLGdFQUFnRSxDQUFDO0lBQ2hGLE9BQU8sRUFBRSw0QkFBb0I7Q0FDOUIsQ0FBQztLQUNELE9BQU8sQ0FBQyxJQUFJLENBQUM7S0FDYixJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7S0FDMUIsV0FBVyxDQUFDLHFGQUFxRixDQUFDLENBQUE7QUFPeEYsUUFBQSxtQkFBbUIsR0FBRyx5QkFBaUI7S0FDakQsSUFBSSxDQUFDO0lBQ0osSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDZixJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDMUIsV0FBVyxDQUFDLGlFQUFpRSxDQUFDO0NBQ2xGLENBQUM7S0FDRCxXQUFXLENBQUMsMkNBQTJDLENBQUMsQ0FBQSIsImZpbGUiOiJjb25maWcvc2VydmljZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyBQcmltaXRpdmVNYXAsIGpvaUlkZW50aWZpZXIsIGpvaUlkZW50aWZpZXJNYXAsIGpvaVByaW1pdGl2ZSwgam9pQXJyYXkgfSBmcm9tIFwiLi9jb21tb25cIlxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VTcGVjIHsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIEJhc2VTZXJ2aWNlU3BlYyBleHRlbmRzIFNlcnZpY2VTcGVjIHtcbiAgbmFtZTogc3RyaW5nXG4gIGRlcGVuZGVuY2llczogc3RyaW5nW11cbiAgb3V0cHV0czogUHJpbWl0aXZlTWFwXG59XG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlT3V0cHV0c1NjaGVtYSA9IGpvaUlkZW50aWZpZXJNYXAoam9pUHJpbWl0aXZlKCkpXG5cbmV4cG9ydCBjb25zdCBiYXNlU2VydmljZVNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpLnJlcXVpcmVkKCksXG4gICAgZGVwZW5kZW5jaWVzOiBqb2lBcnJheShqb2lJZGVudGlmaWVyKCkpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZXMgb2Ygc2VydmljZXMgdGhhdCB0aGlzIHNlcnZpY2UgZGVwZW5kcyBvbiBhdCBydW50aW1lLlwiKSxcbiAgICBvdXRwdXRzOiBzZXJ2aWNlT3V0cHV0c1NjaGVtYSxcbiAgfSlcbiAgLnVua25vd24odHJ1ZSlcbiAgLm1ldGEoeyBleHRlbmRhYmxlOiB0cnVlIH0pXG4gIC5kZXNjcmlwdGlvbihcIlRoZSByZXF1aXJlZCBhdHRyaWJ1dGVzIG9mIGEgc2VydmljZS4gVGhpcyBpcyBnZW5lcmFsbHkgZnVydGhlciBkZWZpbmVkIGJ5IHBsdWdpbnMuXCIpXG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZUNvbmZpZzxUIGV4dGVuZHMgU2VydmljZVNwZWMgPSBTZXJ2aWNlU3BlYz4gZXh0ZW5kcyBCYXNlU2VydmljZVNwZWMge1xuICAvLyBQbHVnaW5zIGNhbiBhZGQgY3VzdG9tIGZpZWxkcyB0aGF0IGFyZSBrZXB0IGhlcmVcbiAgc3BlYzogVFxufVxuXG5leHBvcnQgY29uc3Qgc2VydmljZUNvbmZpZ1NjaGVtYSA9IGJhc2VTZXJ2aWNlU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBzcGVjOiBKb2kub2JqZWN0KClcbiAgICAgIC5tZXRhKHsgZXh0ZW5kYWJsZTogdHJ1ZSB9KVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHNlcnZpY2UncyBzcGVjaWZpY2F0aW9uLCBhcyBkZWZpbmVkIGJ5IGl0cyBwcm92aWRlciBwbHVnaW4uXCIpLFxuICB9KVxuICAuZGVzY3JpcHRpb24oXCJUaGUgY29uZmlndXJhdGlvbiBmb3IgYSBtb2R1bGUncyBzZXJ2aWNlLlwiKVxuIl19 diff --git a/garden-service/build/config/test.d.ts b/garden-service/build/config/test.d.ts new file mode 100644 index 00000000000..28bc91250df --- /dev/null +++ b/garden-service/build/config/test.d.ts @@ -0,0 +1,14 @@ +import * as Joi from "joi"; +export interface TestSpec { +} +export interface BaseTestSpec extends TestSpec { + name: string; + dependencies: string[]; + timeout: number | null; +} +export declare const baseTestSpecSchema: Joi.ObjectSchema; +export interface TestConfig extends BaseTestSpec { + spec: T; +} +export declare const testConfigSchema: Joi.ObjectSchema; +//# sourceMappingURL=test.d.ts.map \ No newline at end of file diff --git a/garden-service/build/config/test.js b/garden-service/build/config/test.js new file mode 100644 index 00000000000..558077bcbbd --- /dev/null +++ b/garden-service/build/config/test.js @@ -0,0 +1,33 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const common_1 = require("./common"); +exports.baseTestSpecSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("The name of the test."), + dependencies: common_1.joiArray(Joi.string()) + .description("The names of services that must be running before the test is run."), + timeout: Joi.number() + .allow(null) + .default(null) + .description("Maximum duration (in seconds) of the test run."), +}) + .description("Required configuration for module tests."); +exports.testConfigSchema = exports.baseTestSpecSchema + .keys({ + spec: Joi.object() + .meta({ extendable: true }) + .description("The configuration for the test, as specified by its module's provider."), +}) + .description("Configuration for a module test."); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbmZpZy90ZXN0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBRUgsMkJBQTBCO0FBQzFCLHFDQUdpQjtBQVVKLFFBQUEsa0JBQWtCLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRTtLQUMzQyxJQUFJLENBQUM7SUFDSixJQUFJLEVBQUUsc0JBQWEsRUFBRTtTQUNsQixRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsdUJBQXVCLENBQUM7SUFDdkMsWUFBWSxFQUFFLGlCQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2pDLFdBQVcsQ0FBQyxvRUFBb0UsQ0FBQztJQUNwRixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNsQixLQUFLLENBQUMsSUFBSSxDQUFDO1NBQ1gsT0FBTyxDQUFDLElBQUksQ0FBQztTQUNiLFdBQVcsQ0FBQyxnREFBZ0QsQ0FBQztDQUNqRSxDQUFDO0tBQ0QsV0FBVyxDQUFDLDBDQUEwQyxDQUFDLENBQUE7QUFPN0MsUUFBQSxnQkFBZ0IsR0FBRywwQkFBa0I7S0FDL0MsSUFBSSxDQUFDO0lBQ0osSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDZixJQUFJLENBQUMsRUFBRSxVQUFVLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDMUIsV0FBVyxDQUFDLHdFQUF3RSxDQUFDO0NBQ3pGLENBQUM7S0FDRCxXQUFXLENBQUMsa0NBQWtDLENBQUMsQ0FBQSIsImZpbGUiOiJjb25maWcvdGVzdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQge1xuICBqb2lBcnJheSxcbiAgam9pSWRlbnRpZmllcixcbn0gZnJvbSBcIi4vY29tbW9uXCJcblxuZXhwb3J0IGludGVyZmFjZSBUZXN0U3BlYyB7IH1cblxuZXhwb3J0IGludGVyZmFjZSBCYXNlVGVzdFNwZWMgZXh0ZW5kcyBUZXN0U3BlYyB7XG4gIG5hbWU6IHN0cmluZ1xuICBkZXBlbmRlbmNpZXM6IHN0cmluZ1tdXG4gIHRpbWVvdXQ6IG51bWJlciB8IG51bGxcbn1cblxuZXhwb3J0IGNvbnN0IGJhc2VUZXN0U3BlY1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhlIHRlc3QuXCIpLFxuICAgIGRlcGVuZGVuY2llczogam9pQXJyYXkoSm9pLnN0cmluZygpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWVzIG9mIHNlcnZpY2VzIHRoYXQgbXVzdCBiZSBydW5uaW5nIGJlZm9yZSB0aGUgdGVzdCBpcyBydW4uXCIpLFxuICAgIHRpbWVvdXQ6IEpvaS5udW1iZXIoKVxuICAgICAgLmFsbG93KG51bGwpXG4gICAgICAuZGVmYXVsdChudWxsKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiTWF4aW11bSBkdXJhdGlvbiAoaW4gc2Vjb25kcykgb2YgdGhlIHRlc3QgcnVuLlwiKSxcbiAgfSlcbiAgLmRlc2NyaXB0aW9uKFwiUmVxdWlyZWQgY29uZmlndXJhdGlvbiBmb3IgbW9kdWxlIHRlc3RzLlwiKVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlc3RDb25maWc8VCBleHRlbmRzIFRlc3RTcGVjID0gVGVzdFNwZWM+IGV4dGVuZHMgQmFzZVRlc3RTcGVjIHtcbiAgLy8gUGx1Z2lucyBjYW4gYWRkIGN1c3RvbSBmaWVsZHMgdGhhdCBhcmUga2VwdCBoZXJlXG4gIHNwZWM6IFRcbn1cblxuZXhwb3J0IGNvbnN0IHRlc3RDb25maWdTY2hlbWEgPSBiYXNlVGVzdFNwZWNTY2hlbWFcbiAgLmtleXMoe1xuICAgIHNwZWM6IEpvaS5vYmplY3QoKVxuICAgICAgLm1ldGEoeyBleHRlbmRhYmxlOiB0cnVlIH0pXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgY29uZmlndXJhdGlvbiBmb3IgdGhlIHRlc3QsIGFzIHNwZWNpZmllZCBieSBpdHMgbW9kdWxlJ3MgcHJvdmlkZXIuXCIpLFxuICB9KVxuICAuZGVzY3JpcHRpb24oXCJDb25maWd1cmF0aW9uIGZvciBhIG1vZHVsZSB0ZXN0LlwiKVxuIl19 diff --git a/garden-service/build/constants.d.ts b/garden-service/build/constants.d.ts new file mode 100644 index 00000000000..8aba905c424 --- /dev/null +++ b/garden-service/build/constants.d.ts @@ -0,0 +1,17 @@ +export declare const MODULE_CONFIG_FILENAME = "garden.yml"; +export declare const LOCAL_CONFIG_FILENAME = "local-config.yml"; +export declare const STATIC_DIR: string; +export declare const GARDEN_DIR_NAME = ".garden"; +export declare const LOGS_DIR: string; +export declare const ERROR_LOG_FILENAME = "error.log"; +export declare const PROJECT_SOURCES_DIR_NAME: string; +export declare const MODULE_SOURCES_DIR_NAME: string; +export declare const GARDEN_BUILD_VERSION_FILENAME = ".garden-build-version"; +export declare const GARDEN_VERSIONFILE_NAME = ".garden-version"; +export declare const DEFAULT_NAMESPACE = "default"; +export declare const DEFAULT_PORT_PROTOCOL = "TCP"; +export declare const GARDEN_ANNOTATION_PREFIX = "garden.io/"; +export declare const GARDEN_ANNOTATION_KEYS_SERVICE: string; +export declare const GARDEN_ANNOTATION_KEYS_VERSION: string; +export declare const DEFAULT_TEST_TIMEOUT: number; +//# sourceMappingURL=constants.d.ts.map \ No newline at end of file diff --git a/garden-service/build/constants.js b/garden-service/build/constants.js new file mode 100644 index 00000000000..f9df15fe68e --- /dev/null +++ b/garden-service/build/constants.js @@ -0,0 +1,28 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +exports.MODULE_CONFIG_FILENAME = "garden.yml"; +exports.LOCAL_CONFIG_FILENAME = "local-config.yml"; +exports.STATIC_DIR = path_1.resolve(__dirname, "..", "static"); +exports.GARDEN_DIR_NAME = ".garden"; +exports.LOGS_DIR = path_1.join(exports.GARDEN_DIR_NAME, "logs"); +exports.ERROR_LOG_FILENAME = "error.log"; +exports.PROJECT_SOURCES_DIR_NAME = path_1.join(exports.GARDEN_DIR_NAME, "sources", "project"); +exports.MODULE_SOURCES_DIR_NAME = path_1.join(exports.GARDEN_DIR_NAME, "sources", "module"); +exports.GARDEN_BUILD_VERSION_FILENAME = ".garden-build-version"; +exports.GARDEN_VERSIONFILE_NAME = ".garden-version"; +exports.DEFAULT_NAMESPACE = "default"; +exports.DEFAULT_PORT_PROTOCOL = "TCP"; +exports.GARDEN_ANNOTATION_PREFIX = "garden.io/"; +exports.GARDEN_ANNOTATION_KEYS_SERVICE = exports.GARDEN_ANNOTATION_PREFIX + "service"; +exports.GARDEN_ANNOTATION_KEYS_VERSION = exports.GARDEN_ANNOTATION_PREFIX + "version"; +exports.DEFAULT_TEST_TIMEOUT = 60 * 1000; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImNvbnN0YW50cy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUVILCtCQUFvQztBQUV2QixRQUFBLHNCQUFzQixHQUFHLFlBQVksQ0FBQTtBQUNyQyxRQUFBLHFCQUFxQixHQUFHLGtCQUFrQixDQUFBO0FBQzFDLFFBQUEsVUFBVSxHQUFHLGNBQU8sQ0FBQyxTQUFTLEVBQUUsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQy9DLFFBQUEsZUFBZSxHQUFHLFNBQVMsQ0FBQTtBQUMzQixRQUFBLFFBQVEsR0FBRyxXQUFJLENBQUMsdUJBQWUsRUFBRSxNQUFNLENBQUMsQ0FBQTtBQUN4QyxRQUFBLGtCQUFrQixHQUFHLFdBQVcsQ0FBQTtBQUNoQyxRQUFBLHdCQUF3QixHQUFHLFdBQUksQ0FBQyx1QkFBZSxFQUFFLFNBQVMsRUFBRSxTQUFTLENBQUMsQ0FBQTtBQUN0RSxRQUFBLHVCQUF1QixHQUFHLFdBQUksQ0FBQyx1QkFBZSxFQUFFLFNBQVMsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUNwRSxRQUFBLDZCQUE2QixHQUFHLHVCQUF1QixDQUFBO0FBQ3ZELFFBQUEsdUJBQXVCLEdBQUcsaUJBQWlCLENBQUE7QUFDM0MsUUFBQSxpQkFBaUIsR0FBRyxTQUFTLENBQUE7QUFDN0IsUUFBQSxxQkFBcUIsR0FBRyxLQUFLLENBQUE7QUFFN0IsUUFBQSx3QkFBd0IsR0FBRyxZQUFZLENBQUE7QUFDdkMsUUFBQSw4QkFBOEIsR0FBRyxnQ0FBd0IsR0FBRyxTQUFTLENBQUE7QUFDckUsUUFBQSw4QkFBOEIsR0FBRyxnQ0FBd0IsR0FBRyxTQUFTLENBQUE7QUFFckUsUUFBQSxvQkFBb0IsR0FBRyxFQUFFLEdBQUcsSUFBSSxDQUFBIiwiZmlsZSI6ImNvbnN0YW50cy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyByZXNvbHZlLCBqb2luIH0gZnJvbSBcInBhdGhcIlxuXG5leHBvcnQgY29uc3QgTU9EVUxFX0NPTkZJR19GSUxFTkFNRSA9IFwiZ2FyZGVuLnltbFwiXG5leHBvcnQgY29uc3QgTE9DQUxfQ09ORklHX0ZJTEVOQU1FID0gXCJsb2NhbC1jb25maWcueW1sXCJcbmV4cG9ydCBjb25zdCBTVEFUSUNfRElSID0gcmVzb2x2ZShfX2Rpcm5hbWUsIFwiLi5cIiwgXCJzdGF0aWNcIilcbmV4cG9ydCBjb25zdCBHQVJERU5fRElSX05BTUUgPSBcIi5nYXJkZW5cIlxuZXhwb3J0IGNvbnN0IExPR1NfRElSID0gam9pbihHQVJERU5fRElSX05BTUUsIFwibG9nc1wiKVxuZXhwb3J0IGNvbnN0IEVSUk9SX0xPR19GSUxFTkFNRSA9IFwiZXJyb3IubG9nXCJcbmV4cG9ydCBjb25zdCBQUk9KRUNUX1NPVVJDRVNfRElSX05BTUUgPSBqb2luKEdBUkRFTl9ESVJfTkFNRSwgXCJzb3VyY2VzXCIsIFwicHJvamVjdFwiKVxuZXhwb3J0IGNvbnN0IE1PRFVMRV9TT1VSQ0VTX0RJUl9OQU1FID0gam9pbihHQVJERU5fRElSX05BTUUsIFwic291cmNlc1wiLCBcIm1vZHVsZVwiKVxuZXhwb3J0IGNvbnN0IEdBUkRFTl9CVUlMRF9WRVJTSU9OX0ZJTEVOQU1FID0gXCIuZ2FyZGVuLWJ1aWxkLXZlcnNpb25cIlxuZXhwb3J0IGNvbnN0IEdBUkRFTl9WRVJTSU9ORklMRV9OQU1FID0gXCIuZ2FyZGVuLXZlcnNpb25cIlxuZXhwb3J0IGNvbnN0IERFRkFVTFRfTkFNRVNQQUNFID0gXCJkZWZhdWx0XCJcbmV4cG9ydCBjb25zdCBERUZBVUxUX1BPUlRfUFJPVE9DT0wgPSBcIlRDUFwiXG5cbmV4cG9ydCBjb25zdCBHQVJERU5fQU5OT1RBVElPTl9QUkVGSVggPSBcImdhcmRlbi5pby9cIlxuZXhwb3J0IGNvbnN0IEdBUkRFTl9BTk5PVEFUSU9OX0tFWVNfU0VSVklDRSA9IEdBUkRFTl9BTk5PVEFUSU9OX1BSRUZJWCArIFwic2VydmljZVwiXG5leHBvcnQgY29uc3QgR0FSREVOX0FOTk9UQVRJT05fS0VZU19WRVJTSU9OID0gR0FSREVOX0FOTk9UQVRJT05fUFJFRklYICsgXCJ2ZXJzaW9uXCJcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfVEVTVF9USU1FT1VUID0gNjAgKiAxMDAwXG4iXX0= diff --git a/garden-service/build/docs/commands.d.ts b/garden-service/build/docs/commands.d.ts new file mode 100644 index 00000000000..e465c5d8946 --- /dev/null +++ b/garden-service/build/docs/commands.d.ts @@ -0,0 +1,2 @@ +export declare function generateCommandReferenceDocs(docsRoot: string): void; +//# sourceMappingURL=commands.d.ts.map \ No newline at end of file diff --git a/garden-service/build/docs/commands.js b/garden-service/build/docs/commands.js new file mode 100644 index 00000000000..ec8ff6bcd2c --- /dev/null +++ b/garden-service/build/docs/commands.js @@ -0,0 +1,37 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = require("fs"); +const handlebars = require("handlebars"); +const path_1 = require("path"); +const cli_1 = require("../cli/cli"); +const commands_1 = require("../commands/commands"); +const lodash_1 = require("lodash"); +const base_1 = require("../commands/base"); +function generateCommandReferenceDocs(docsRoot) { + const referenceDir = path_1.resolve(docsRoot, "reference"); + const outputPath = path_1.resolve(referenceDir, "commands.md"); + const commands = lodash_1.flatten(commands_1.coreCommands.map(cmd => { + if (cmd.subCommands && cmd.subCommands.length) { + return cmd.subCommands.map(subCommandCls => new subCommandCls(cmd).describe()); + } + else { + return [cmd.describe()]; + } + })); + const globalOptions = base_1.describeParameters(cli_1.GLOBAL_OPTIONS); + const templatePath = path_1.resolve(__dirname, "templates", "commands.hbs"); + handlebars.registerPartial("argType", "{{#if choices}}{{#each choices}}`{{.}}` {{/each}}{{else}}{{type}}{{/if}}"); + const template = handlebars.compile(fs_1.readFileSync(templatePath).toString()); + const markdown = template({ commands, globalOptions }); + fs_1.writeFileSync(outputPath, markdown); +} +exports.generateCommandReferenceDocs = generateCommandReferenceDocs; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImRvY3MvY29tbWFuZHMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFFSCwyQkFHVztBQUNYLHlDQUF3QztBQUN4QywrQkFBOEI7QUFDOUIsb0NBQTJDO0FBQzNDLG1EQUFtRDtBQUNuRCxtQ0FBZ0M7QUFDaEMsMkNBQXFEO0FBRXJELFNBQWdCLDRCQUE0QixDQUFDLFFBQWdCO0lBQzNELE1BQU0sWUFBWSxHQUFHLGNBQU8sQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUE7SUFDbkQsTUFBTSxVQUFVLEdBQUcsY0FBTyxDQUFDLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQTtJQUV2RCxNQUFNLFFBQVEsR0FBRyxnQkFBTyxDQUFDLHVCQUFZLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxFQUFFO1FBQzlDLElBQUksR0FBRyxDQUFDLFdBQVcsSUFBSSxHQUFHLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRTtZQUM3QyxPQUFPLEdBQUcsQ0FBQyxXQUFXLENBQUMsR0FBRyxDQUFDLGFBQWEsQ0FBQyxFQUFFLENBQUMsSUFBSSxhQUFhLENBQUMsR0FBRyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtTQUMvRTthQUFNO1lBQ0wsT0FBTyxDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsQ0FBQyxDQUFBO1NBQ3hCO0lBQ0gsQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUVILE1BQU0sYUFBYSxHQUFHLHlCQUFrQixDQUFDLG9CQUFjLENBQUMsQ0FBQTtJQUV4RCxNQUFNLFlBQVksR0FBRyxjQUFPLENBQUMsU0FBUyxFQUFFLFdBQVcsRUFBRSxjQUFjLENBQUMsQ0FBQTtJQUNwRSxVQUFVLENBQUMsZUFBZSxDQUN4QixTQUFTLEVBQ1QsMEVBQTBFLENBQzNFLENBQUE7SUFDRCxNQUFNLFFBQVEsR0FBRyxVQUFVLENBQUMsT0FBTyxDQUFDLGlCQUFZLENBQUMsWUFBWSxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtJQUMxRSxNQUFNLFFBQVEsR0FBRyxRQUFRLENBQUMsRUFBRSxRQUFRLEVBQUUsYUFBYSxFQUFFLENBQUMsQ0FBQTtJQUV0RCxrQkFBYSxDQUFDLFVBQVUsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUNyQyxDQUFDO0FBdkJELG9FQXVCQyIsImZpbGUiOiJkb2NzL2NvbW1hbmRzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIHJlYWRGaWxlU3luYyxcbiAgd3JpdGVGaWxlU3luYyxcbn0gZnJvbSBcImZzXCJcbmltcG9ydCAqIGFzIGhhbmRsZWJhcnMgZnJvbSBcImhhbmRsZWJhcnNcIlxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IEdMT0JBTF9PUFRJT05TIH0gZnJvbSBcIi4uL2NsaS9jbGlcIlxuaW1wb3J0IHsgY29yZUNvbW1hbmRzIH0gZnJvbSBcIi4uL2NvbW1hbmRzL2NvbW1hbmRzXCJcbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7IGRlc2NyaWJlUGFyYW1ldGVycyB9IGZyb20gXCIuLi9jb21tYW5kcy9iYXNlXCJcblxuZXhwb3J0IGZ1bmN0aW9uIGdlbmVyYXRlQ29tbWFuZFJlZmVyZW5jZURvY3MoZG9jc1Jvb3Q6IHN0cmluZykge1xuICBjb25zdCByZWZlcmVuY2VEaXIgPSByZXNvbHZlKGRvY3NSb290LCBcInJlZmVyZW5jZVwiKVxuICBjb25zdCBvdXRwdXRQYXRoID0gcmVzb2x2ZShyZWZlcmVuY2VEaXIsIFwiY29tbWFuZHMubWRcIilcblxuICBjb25zdCBjb21tYW5kcyA9IGZsYXR0ZW4oY29yZUNvbW1hbmRzLm1hcChjbWQgPT4ge1xuICAgIGlmIChjbWQuc3ViQ29tbWFuZHMgJiYgY21kLnN1YkNvbW1hbmRzLmxlbmd0aCkge1xuICAgICAgcmV0dXJuIGNtZC5zdWJDb21tYW5kcy5tYXAoc3ViQ29tbWFuZENscyA9PiBuZXcgc3ViQ29tbWFuZENscyhjbWQpLmRlc2NyaWJlKCkpXG4gICAgfSBlbHNlIHtcbiAgICAgIHJldHVybiBbY21kLmRlc2NyaWJlKCldXG4gICAgfVxuICB9KSlcblxuICBjb25zdCBnbG9iYWxPcHRpb25zID0gZGVzY3JpYmVQYXJhbWV0ZXJzKEdMT0JBTF9PUFRJT05TKVxuXG4gIGNvbnN0IHRlbXBsYXRlUGF0aCA9IHJlc29sdmUoX19kaXJuYW1lLCBcInRlbXBsYXRlc1wiLCBcImNvbW1hbmRzLmhic1wiKVxuICBoYW5kbGViYXJzLnJlZ2lzdGVyUGFydGlhbChcbiAgICBcImFyZ1R5cGVcIixcbiAgICBcInt7I2lmIGNob2ljZXN9fXt7I2VhY2ggY2hvaWNlc319YHt7Ln19YCB7ey9lYWNofX17e2Vsc2V9fXt7dHlwZX19e3svaWZ9fVwiLFxuICApXG4gIGNvbnN0IHRlbXBsYXRlID0gaGFuZGxlYmFycy5jb21waWxlKHJlYWRGaWxlU3luYyh0ZW1wbGF0ZVBhdGgpLnRvU3RyaW5nKCkpXG4gIGNvbnN0IG1hcmtkb3duID0gdGVtcGxhdGUoeyBjb21tYW5kcywgZ2xvYmFsT3B0aW9ucyB9KVxuXG4gIHdyaXRlRmlsZVN5bmMob3V0cHV0UGF0aCwgbWFya2Rvd24pXG59XG4iXX0= diff --git a/garden-service/build/docs/config.d.ts b/garden-service/build/docs/config.d.ts new file mode 100644 index 00000000000..f5b7e34964d --- /dev/null +++ b/garden-service/build/docs/config.d.ts @@ -0,0 +1,9 @@ +import * as Joi from "joi"; +interface RenderOpts { + level?: number; + required?: boolean; +} +export declare function renderSchemaDescription(description: Joi.Description, opts: RenderOpts): string; +export declare function generateConfigReferenceDocs(docsRoot: string): void; +export {}; +//# sourceMappingURL=config.d.ts.map \ No newline at end of file diff --git a/garden-service/build/docs/config.js b/garden-service/build/docs/config.js new file mode 100644 index 00000000000..a3344611ac6 --- /dev/null +++ b/garden-service/build/docs/config.js @@ -0,0 +1,145 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_1 = require("fs"); +const handlebars = require("handlebars"); +const js_yaml_1 = require("js-yaml"); +const linewrap = require("linewrap"); +const Joi = require("joi"); +const path_1 = require("path"); +const lodash_1 = require("lodash"); +const container_1 = require("../plugins/container"); +const generic_1 = require("../plugins/generic"); +const base_1 = require("../config/base"); +const module_1 = require("../config/module"); +const maxWidth = 100; +const builtInModuleTypes = [ + { name: "generic", schema: generic_1.genericModuleSpecSchema }, + { name: "container", schema: container_1.containerModuleSpecSchema }, +]; +function renderCommentDescription(description, width, { required }) { + const output = []; + const meta = []; + if (description.description) { + output.push(description.description); + } + if (description.examples && description.examples.length) { + const example = description.examples[0]; + if (description.type === "object" || description.type === "array") { + meta.push("Example:", ...indent(js_yaml_1.safeDump(example).trim().split("\n"), 1), ""); + } + else { + meta.push("Example: " + JSON.stringify(example), ""); + } + } + const allowOnly = lodash_1.get(description, "flags.allowOnly") === true; + if (required) { + const presenceRequired = lodash_1.get(description, "flags.presence") === "required"; + if (presenceRequired || allowOnly) { + meta.push("Required."); + } + else if (output.length) { + meta.push("Optional."); + } + } + if (allowOnly) { + meta.push("Allowed values: " + description.valids.map(v => JSON.stringify(v)).join(", ")); + } + if (meta.length > 0) { + output.push("", ...meta); + } + if (output.length === 0) { + return output; + } + const wrap = linewrap(width - 2, { whitespace: "line" }); + return wrap(output.join("\n")).split("\n").map(line => "# " + line); +} +function getDefaultValue(description) { + const defaultSpec = lodash_1.get(description, "flags.default"); + if (defaultSpec === undefined) { + return; + } + else if (defaultSpec && defaultSpec.function) { + return defaultSpec.function(); + } + else { + return defaultSpec; + } +} +function indent(lines, level) { + const prefix = lodash_1.padEnd("", level * 2, " "); + return lines.map(line => prefix + line); +} +function indentFromSecondLine(lines, level) { + return [...lines.slice(0, 1), ...indent(lines.slice(1), level)]; +} +function renderSchemaDescription(description, opts) { + const { level = 0 } = opts; + const indentSpaces = level * 2; + const descriptionWidth = maxWidth - indentSpaces - 2; + const output = []; + const defaultValue = getDefaultValue(description); + switch (description.type) { + case "object": + const children = Object.entries(description.children || {}); + if (!children.length) { + if (defaultValue) { + output.push("", ...js_yaml_1.safeDump(defaultValue).trim().split("\n")); + } + else { + output.push("{}"); + } + break; + } + output.push(""); + for (const [key, keyDescription] of children) { + if (lodash_1.get(keyDescription, "meta[0].internal")) { + continue; + } + output.push(...renderCommentDescription(keyDescription, descriptionWidth, opts), `${key}: ${renderSchemaDescription(keyDescription, Object.assign({}, opts, { level: level + 1 }))}`, ""); + } + output.pop(); + break; + case "array": + if (!description.items.length) { + output.push("[]"); + } + const itemDescription = description.items[0]; + output.push("", ...renderCommentDescription(itemDescription, descriptionWidth, opts), "- " + renderSchemaDescription(itemDescription, Object.assign({}, opts, { level: level + 1 })).trim(), ""); + break; + default: + output.push(defaultValue === undefined ? "" : defaultValue + ""); + } + // we don't indent the first line + return indentFromSecondLine(output, level) + .map(line => line.trimRight()) + .join("\n"); +} +exports.renderSchemaDescription = renderSchemaDescription; +function generateConfigReferenceDocs(docsRoot) { + const referenceDir = path_1.resolve(docsRoot, "reference"); + const outputPath = path_1.resolve(referenceDir, "config.md"); + const yaml = renderSchemaDescription(base_1.configSchema.describe(), { required: true }); + const moduleTypes = builtInModuleTypes.map(({ name, schema }) => { + schema = Joi.object().keys({ + module: module_1.baseModuleSpecSchema.concat(schema), + }); + return { + name, + yaml: renderSchemaDescription(schema.describe(), { required: true }), + }; + }); + const templatePath = path_1.resolve(__dirname, "templates", "config.hbs"); + const template = handlebars.compile(fs_1.readFileSync(templatePath).toString()); + const markdown = template({ yaml, moduleTypes }); + fs_1.writeFileSync(outputPath, markdown); +} +exports.generateConfigReferenceDocs = generateConfigReferenceDocs; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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TUFBTSxXQUFXLEdBQUcsa0JBQWtCLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLEVBQUUsRUFBRTtRQUM5RCxNQUFNLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQztZQUN6QixNQUFNLEVBQUUsNkJBQW9CLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztTQUM1QyxDQUFDLENBQUE7UUFDRixPQUFPO1lBQ0wsSUFBSTtZQUNKLElBQUksRUFBRSx1QkFBdUIsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsSUFBSSxFQUFFLENBQUM7U0FDckUsQ0FBQTtJQUNILENBQUMsQ0FBQyxDQUFBO0lBRUYsTUFBTSxZQUFZLEdBQUcsY0FBTyxDQUFDLFNBQVMsRUFBRSxXQUFXLEVBQUUsWUFBWSxDQUFDLENBQUE7SUFDbEUsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxpQkFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDMUUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEVBQUUsSUFBSSxFQUFFLFdBQVcsRUFBRSxDQUFDLENBQUE7SUFFaEQsa0JBQWEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckMsQ0FBQztBQXBCRCxrRUFvQkMiLCJmaWxlIjoiZG9jcy9jb25maWcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHtcbiAgcmVhZEZpbGVTeW5jLFxuICB3cml0ZUZpbGVTeW5jLFxufSBmcm9tIFwiZnNcIlxuaW1wb3J0ICogYXMgaGFuZGxlYmFycyBmcm9tIFwiaGFuZGxlYmFyc1wiXG5pbXBvcnQgeyBzYWZlRHVtcCB9IGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCAqIGFzIGxpbmV3cmFwIGZyb20gXCJsaW5ld3JhcFwiXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyByZXNvbHZlIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHtcbiAgZ2V0LFxuICBwYWRFbmQsXG59IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgY29udGFpbmVyTW9kdWxlU3BlY1NjaGVtYSB9IGZyb20gXCIuLi9wbHVnaW5zL2NvbnRhaW5lclwiXG5pbXBvcnQgeyBnZW5lcmljTW9kdWxlU3BlY1NjaGVtYSB9IGZyb20gXCIuLi9wbHVnaW5zL2dlbmVyaWNcIlxuaW1wb3J0IHsgY29uZmlnU2NoZW1hIH0gZnJvbSBcIi4uL2NvbmZpZy9iYXNlXCJcbmltcG9ydCB7IGJhc2VNb2R1bGVTcGVjU2NoZW1hIH0gZnJvbSBcIi4uL2NvbmZpZy9tb2R1bGVcIlxuXG5jb25zdCBtYXhXaWR0aCA9IDEwMFxuY29uc3QgYnVpbHRJbk1vZHVsZVR5cGVzID0gW1xuICB7IG5hbWU6IFwiZ2VuZXJpY1wiLCBzY2hlbWE6IGdlbmVyaWNNb2R1bGVTcGVjU2NoZW1hIH0sXG4gIHsgbmFtZTogXCJjb250YWluZXJcIiwgc2NoZW1hOiBjb250YWluZXJNb2R1bGVTcGVjU2NoZW1hIH0sXG5dXG5cbmludGVyZmFjZSBSZW5kZXJPcHRzIHtcbiAgbGV2ZWw/OiBudW1iZXJcbiAgcmVxdWlyZWQ/OiBib29sZWFuXG59XG5cbmZ1bmN0aW9uIHJlbmRlckNvbW1lbnREZXNjcmlwdGlvbihkZXNjcmlwdGlvbjogSm9pLkRlc2NyaXB0aW9uLCB3aWR0aDogbnVtYmVyLCB7IHJlcXVpcmVkIH06IFJlbmRlck9wdHMpIHtcbiAgY29uc3Qgb3V0cHV0OiBzdHJpbmdbXSA9IFtdXG4gIGNvbnN0IG1ldGE6IHN0cmluZ1tdID0gW11cblxuICBpZiAoZGVzY3JpcHRpb24uZGVzY3JpcHRpb24pIHtcbiAgICBvdXRwdXQucHVzaChkZXNjcmlwdGlvbi5kZXNjcmlwdGlvbilcbiAgfVxuXG4gIGlmIChkZXNjcmlwdGlvbi5leGFtcGxlcyAmJiBkZXNjcmlwdGlvbi5leGFtcGxlcy5sZW5ndGgpIHtcbiAgICBjb25zdCBleGFtcGxlID0gZGVzY3JpcHRpb24uZXhhbXBsZXNbMF1cblxuICAgIGlmIChkZXNjcmlwdGlvbi50eXBlID09PSBcIm9iamVjdFwiIHx8IGRlc2NyaXB0aW9uLnR5cGUgPT09IFwiYXJyYXlcIikge1xuICAgICAgbWV0YS5wdXNoKFwiRXhhbXBsZTpcIiwgLi4uaW5kZW50KHNhZmVEdW1wKGV4YW1wbGUpLnRyaW0oKS5zcGxpdChcIlxcblwiKSwgMSksIFwiXCIpXG4gICAgfSBlbHNlIHtcbiAgICAgIG1ldGEucHVzaChcIkV4YW1wbGU6IFwiICsgSlNPTi5zdHJpbmdpZnkoZXhhbXBsZSksIFwiXCIpXG4gICAgfVxuICB9XG5cbiAgY29uc3QgYWxsb3dPbmx5ID0gZ2V0KGRlc2NyaXB0aW9uLCBcImZsYWdzLmFsbG93T25seVwiKSA9PT0gdHJ1ZVxuXG4gIGlmIChyZXF1aXJlZCkge1xuICAgIGNvbnN0IHByZXNlbmNlUmVxdWlyZWQgPSBnZXQoZGVzY3JpcHRpb24sIFwiZmxhZ3MucHJlc2VuY2VcIikgPT09IFwicmVxdWlyZWRcIlxuXG4gICAgaWYgKHByZXNlbmNlUmVxdWlyZWQgfHwgYWxsb3dPbmx5KSB7XG4gICAgICBtZXRhLnB1c2goXCJSZXF1aXJlZC5cIilcbiAgICB9IGVsc2UgaWYgKG91dHB1dC5sZW5ndGgpIHtcbiAgICAgIG1ldGEucHVzaChcIk9wdGlvbmFsLlwiKVxuICAgIH1cbiAgfVxuXG4gIGlmIChhbGxvd09ubHkpIHtcbiAgICBtZXRhLnB1c2goXCJBbGxvd2VkIHZhbHVlczogXCIgKyBkZXNjcmlwdGlvbi52YWxpZHMhLm1hcCh2ID0+IEpTT04uc3RyaW5naWZ5KHYpKS5qb2luKFwiLCBcIikpXG4gIH1cblxuICBpZiAobWV0YS5sZW5ndGggPiAwKSB7XG4gICAgb3V0cHV0LnB1c2goXCJcIiwgLi4ubWV0YSlcbiAgfVxuXG4gIGlmIChvdXRwdXQubGVuZ3RoID09PSAwKSB7XG4gICAgcmV0dXJuIG91dHB1dFxuICB9XG5cbiAgY29uc3Qgd3JhcCA9IGxpbmV3cmFwKHdpZHRoIC0gMiwgeyB3aGl0ZXNwYWNlOiBcImxpbmVcIiB9KVxuICByZXR1cm4gd3JhcChvdXRwdXQuam9pbihcIlxcblwiKSkuc3BsaXQoXCJcXG5cIikubWFwKGxpbmUgPT4gXCIjIFwiICsgbGluZSlcbn1cblxuZnVuY3Rpb24gZ2V0RGVmYXVsdFZhbHVlKGRlc2NyaXB0aW9uOiBKb2kuRGVzY3JpcHRpb24pIHtcbiAgY29uc3QgZGVmYXVsdFNwZWMgPSBnZXQoZGVzY3JpcHRpb24sIFwiZmxhZ3MuZGVmYXVsdFwiKVxuXG4gIGlmIChkZWZhdWx0U3BlYyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgcmV0dXJuXG4gIH0gZWxzZSBpZiAoZGVmYXVsdFNwZWMgJiYgZGVmYXVsdFNwZWMuZnVuY3Rpb24pIHtcbiAgICByZXR1cm4gZGVmYXVsdFNwZWMuZnVuY3Rpb24oKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBkZWZhdWx0U3BlY1xuICB9XG59XG5cbmZ1bmN0aW9uIGluZGVudChsaW5lczogc3RyaW5nW10sIGxldmVsOiBudW1iZXIpIHtcbiAgY29uc3QgcHJlZml4ID0gcGFkRW5kKFwiXCIsIGxldmVsICogMiwgXCIgXCIpXG4gIHJldHVybiBsaW5lcy5tYXAobGluZSA9PiBwcmVmaXggKyBsaW5lKVxufVxuXG5mdW5jdGlvbiBpbmRlbnRGcm9tU2Vjb25kTGluZShsaW5lczogc3RyaW5nW10sIGxldmVsOiBudW1iZXIpIHtcbiAgcmV0dXJuIFsuLi5saW5lcy5zbGljZSgwLCAxKSwgLi4uaW5kZW50KGxpbmVzLnNsaWNlKDEpLCBsZXZlbCldXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJTY2hlbWFEZXNjcmlwdGlvbihkZXNjcmlwdGlvbjogSm9pLkRlc2NyaXB0aW9uLCBvcHRzOiBSZW5kZXJPcHRzKSB7XG4gIGNvbnN0IHsgbGV2ZWwgPSAwIH0gPSBvcHRzXG4gIGNvbnN0IGluZGVudFNwYWNlcyA9IGxldmVsICogMlxuICBjb25zdCBkZXNjcmlwdGlvbldpZHRoID0gbWF4V2lkdGggLSBpbmRlbnRTcGFjZXMgLSAyXG5cbiAgY29uc3Qgb3V0cHV0OiBzdHJpbmdbXSA9IFtdXG4gIGNvbnN0IGRlZmF1bHRWYWx1ZSA9IGdldERlZmF1bHRWYWx1ZShkZXNjcmlwdGlvbilcblxuICBzd2l0Y2ggKGRlc2NyaXB0aW9uLnR5cGUpIHtcbiAgICBjYXNlIFwib2JqZWN0XCI6XG4gICAgICBjb25zdCBjaGlsZHJlbiA9IE9iamVjdC5lbnRyaWVzKGRlc2NyaXB0aW9uLmNoaWxkcmVuIHx8IHt9KVxuXG4gICAgICBpZiAoIWNoaWxkcmVuLmxlbmd0aCkge1xuICAgICAgICBpZiAoZGVmYXVsdFZhbHVlKSB7XG4gICAgICAgICAgb3V0cHV0LnB1c2goXCJcIiwgLi4uc2FmZUR1bXAoZGVmYXVsdFZhbHVlKS50cmltKCkuc3BsaXQoXCJcXG5cIikpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgb3V0cHV0LnB1c2goXCJ7fVwiKVxuICAgICAgICB9XG4gICAgICAgIGJyZWFrXG4gICAgICB9XG5cbiAgICAgIG91dHB1dC5wdXNoKFwiXCIpXG5cbiAgICAgIGZvciAoY29uc3QgW2tleSwga2V5RGVzY3JpcHRpb25dIG9mIGNoaWxkcmVuKSB7XG4gICAgICAgIGlmIChnZXQoa2V5RGVzY3JpcHRpb24sIFwibWV0YVswXS5pbnRlcm5hbFwiKSkge1xuICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgIH1cblxuICAgICAgICBvdXRwdXQucHVzaChcbiAgICAgICAgICAuLi5yZW5kZXJDb21tZW50RGVzY3JpcHRpb24oa2V5RGVzY3JpcHRpb24sIGRlc2NyaXB0aW9uV2lkdGgsIG9wdHMpLFxuICAgICAgICAgIGAke2tleX06ICR7cmVuZGVyU2NoZW1hRGVzY3JpcHRpb24oa2V5RGVzY3JpcHRpb24sIHsgLi4ub3B0cywgbGV2ZWw6IGxldmVsICsgMSB9KX1gLFxuICAgICAgICAgIFwiXCIsXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgb3V0cHV0LnBvcCgpXG5cbiAgICAgIGJyZWFrXG5cbiAgICBjYXNlIFwiYXJyYXlcIjpcbiAgICAgIGlmICghZGVzY3JpcHRpb24uaXRlbXMubGVuZ3RoKSB7XG4gICAgICAgIG91dHB1dC5wdXNoKFwiW11cIilcbiAgICAgIH1cblxuICAgICAgY29uc3QgaXRlbURlc2NyaXB0aW9uID0gZGVzY3JpcHRpb24uaXRlbXNbMF1cblxuICAgICAgb3V0cHV0LnB1c2goXG4gICAgICAgIFwiXCIsXG4gICAgICAgIC4uLnJlbmRlckNvbW1lbnREZXNjcmlwdGlvbihpdGVtRGVzY3JpcHRpb24sIGRlc2NyaXB0aW9uV2lkdGgsIG9wdHMpLFxuICAgICAgICBcIi0gXCIgKyByZW5kZXJTY2hlbWFEZXNjcmlwdGlvbihpdGVtRGVzY3JpcHRpb24sIHsgLi4ub3B0cywgbGV2ZWw6IGxldmVsICsgMSB9KS50cmltKCksXG4gICAgICAgIFwiXCIsXG4gICAgICApXG5cbiAgICAgIGJyZWFrXG5cbiAgICBkZWZhdWx0OlxuICAgICAgb3V0cHV0LnB1c2goZGVmYXVsdFZhbHVlID09PSB1bmRlZmluZWQgPyBcIlwiIDogZGVmYXVsdFZhbHVlICsgXCJcIilcbiAgfVxuXG4gIC8vIHdlIGRvbid0IGluZGVudCB0aGUgZmlyc3QgbGluZVxuICByZXR1cm4gaW5kZW50RnJvbVNlY29uZExpbmUob3V0cHV0LCBsZXZlbClcbiAgICAubWFwKGxpbmUgPT4gbGluZS50cmltUmlnaHQoKSlcbiAgICAuam9pbihcIlxcblwiKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVDb25maWdSZWZlcmVuY2VEb2NzKGRvY3NSb290OiBzdHJpbmcpIHtcbiAgY29uc3QgcmVmZXJlbmNlRGlyID0gcmVzb2x2ZShkb2NzUm9vdCwgXCJyZWZlcmVuY2VcIilcbiAgY29uc3Qgb3V0cHV0UGF0aCA9IHJlc29sdmUocmVmZXJlbmNlRGlyLCBcImNvbmZpZy5tZFwiKVxuXG4gIGNvbnN0IHlhbWwgPSByZW5kZXJTY2hlbWFEZXNjcmlwdGlvbihjb25maWdTY2hlbWEuZGVzY3JpYmUoKSwgeyByZXF1aXJlZDogdHJ1ZSB9KVxuICBjb25zdCBtb2R1bGVUeXBlcyA9IGJ1aWx0SW5Nb2R1bGVUeXBlcy5tYXAoKHsgbmFtZSwgc2NoZW1hIH0pID0+IHtcbiAgICBzY2hlbWEgPSBKb2kub2JqZWN0KCkua2V5cyh7XG4gICAgICBtb2R1bGU6IGJhc2VNb2R1bGVTcGVjU2NoZW1hLmNvbmNhdChzY2hlbWEpLFxuICAgIH0pXG4gICAgcmV0dXJuIHtcbiAgICAgIG5hbWUsXG4gICAgICB5YW1sOiByZW5kZXJTY2hlbWFEZXNjcmlwdGlvbihzY2hlbWEuZGVzY3JpYmUoKSwgeyByZXF1aXJlZDogdHJ1ZSB9KSxcbiAgICB9XG4gIH0pXG5cbiAgY29uc3QgdGVtcGxhdGVQYXRoID0gcmVzb2x2ZShfX2Rpcm5hbWUsIFwidGVtcGxhdGVzXCIsIFwiY29uZmlnLmhic1wiKVxuICBjb25zdCB0ZW1wbGF0ZSA9IGhhbmRsZWJhcnMuY29tcGlsZShyZWFkRmlsZVN5bmModGVtcGxhdGVQYXRoKS50b1N0cmluZygpKVxuICBjb25zdCBtYXJrZG93biA9IHRlbXBsYXRlKHsgeWFtbCwgbW9kdWxlVHlwZXMgfSlcblxuICB3cml0ZUZpbGVTeW5jKG91dHB1dFBhdGgsIG1hcmtkb3duKVxufVxuIl19 diff --git a/garden-service/build/docs/generate.d.ts b/garden-service/build/docs/generate.d.ts new file mode 100644 index 00000000000..796b31808d4 --- /dev/null +++ b/garden-service/build/docs/generate.d.ts @@ -0,0 +1,2 @@ +export declare function generateDocs(targetDir: string): void; +//# sourceMappingURL=generate.d.ts.map \ No newline at end of file diff --git a/garden-service/build/docs/generate.js b/garden-service/build/docs/generate.js new file mode 100644 index 00000000000..a8dea9dc8e0 --- /dev/null +++ b/garden-service/build/docs/generate.js @@ -0,0 +1,26 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const commands_1 = require("./commands"); +const config_1 = require("./config"); +const process_1 = require("process"); +const template_strings_1 = require("./template-strings"); +function generateDocs(targetDir) { + const docsRoot = path_1.resolve(process.cwd(), targetDir); + commands_1.generateCommandReferenceDocs(docsRoot); + config_1.generateConfigReferenceDocs(docsRoot); + template_strings_1.generateTemplateStringReferenceDocs(docsRoot); +} +exports.generateDocs = generateDocs; +if (require.main === module) { + generateDocs(process_1.argv[2]); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImRvY3MvZ2VuZXJhdGUudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFFSCwrQkFBOEI7QUFDOUIseUNBQXlEO0FBQ3pELHFDQUFzRDtBQUN0RCxxQ0FBOEI7QUFDOUIseURBQXdFO0FBRXhFLFNBQWdCLFlBQVksQ0FBQyxTQUFpQjtJQUM1QyxNQUFNLFFBQVEsR0FBRyxjQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsRUFBRSxFQUFFLFNBQVMsQ0FBQyxDQUFBO0lBQ2xELHVDQUE0QixDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ3RDLG9DQUEyQixDQUFDLFFBQVEsQ0FBQyxDQUFBO0lBQ3JDLHNEQUFtQyxDQUFDLFFBQVEsQ0FBQyxDQUFBO0FBQy9DLENBQUM7QUFMRCxvQ0FLQztBQUVELElBQUksT0FBTyxDQUFDLElBQUksS0FBSyxNQUFNLEVBQUU7SUFDM0IsWUFBWSxDQUFDLGNBQUksQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO0NBQ3RCIiwiZmlsZSI6ImRvY3MvZ2VuZXJhdGUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IGdlbmVyYXRlQ29tbWFuZFJlZmVyZW5jZURvY3MgfSBmcm9tIFwiLi9jb21tYW5kc1wiXG5pbXBvcnQgeyBnZW5lcmF0ZUNvbmZpZ1JlZmVyZW5jZURvY3MgfSBmcm9tIFwiLi9jb25maWdcIlxuaW1wb3J0IHsgYXJndiB9IGZyb20gXCJwcm9jZXNzXCJcbmltcG9ydCB7IGdlbmVyYXRlVGVtcGxhdGVTdHJpbmdSZWZlcmVuY2VEb2NzIH0gZnJvbSBcIi4vdGVtcGxhdGUtc3RyaW5nc1wiXG5cbmV4cG9ydCBmdW5jdGlvbiBnZW5lcmF0ZURvY3ModGFyZ2V0RGlyOiBzdHJpbmcpIHtcbiAgY29uc3QgZG9jc1Jvb3QgPSByZXNvbHZlKHByb2Nlc3MuY3dkKCksIHRhcmdldERpcilcbiAgZ2VuZXJhdGVDb21tYW5kUmVmZXJlbmNlRG9jcyhkb2NzUm9vdClcbiAgZ2VuZXJhdGVDb25maWdSZWZlcmVuY2VEb2NzKGRvY3NSb290KVxuICBnZW5lcmF0ZVRlbXBsYXRlU3RyaW5nUmVmZXJlbmNlRG9jcyhkb2NzUm9vdClcbn1cblxuaWYgKHJlcXVpcmUubWFpbiA9PT0gbW9kdWxlKSB7XG4gIGdlbmVyYXRlRG9jcyhhcmd2WzJdKVxufVxuIl19 diff --git a/garden-service/build/docs/template-strings.d.ts b/garden-service/build/docs/template-strings.d.ts new file mode 100644 index 00000000000..5d589c54224 --- /dev/null +++ b/garden-service/build/docs/template-strings.d.ts @@ -0,0 +1,2 @@ +export declare function generateTemplateStringReferenceDocs(docsRoot: string): void; +//# sourceMappingURL=template-strings.d.ts.map \ No newline at end of file diff --git a/garden-service/build/docs/template-strings.js b/garden-service/build/docs/template-strings.js new file mode 100644 index 00000000000..26a74f2de28 --- /dev/null +++ b/garden-service/build/docs/template-strings.js @@ -0,0 +1,30 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const config_1 = require("./config"); +const config_context_1 = require("../config/config-context"); +const fs_1 = require("fs"); +const handlebars = require("handlebars"); +function generateTemplateStringReferenceDocs(docsRoot) { + const referenceDir = path_1.resolve(docsRoot, "reference"); + const outputPath = path_1.resolve(referenceDir, "template-strings.md"); + const projectContext = config_1.renderSchemaDescription(config_context_1.ProjectConfigContext.getSchema().describe(), { required: false }); + const moduleContext = config_1.renderSchemaDescription(config_context_1.ModuleConfigContext.getSchema().describe(), { required: false }); + const templatePath = path_1.resolve(__dirname, "templates", "template-strings.hbs"); + const template = handlebars.compile(fs_1.readFileSync(templatePath).toString()); + const markdown = template({ projectContext, moduleContext }); + fs_1.writeFileSync(outputPath, markdown); +} +exports.generateTemplateStringReferenceDocs = generateTemplateStringReferenceDocs; +if (require.main === module) { + generateTemplateStringReferenceDocs(path_1.resolve(__dirname, "..", "..", "..", "docs")); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImRvY3MvdGVtcGxhdGUtc3RyaW5ncy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUVILCtCQUE4QjtBQUM5QixxQ0FBa0Q7QUFDbEQsNkRBQW9GO0FBQ3BGLDJCQUFnRDtBQUNoRCx5Q0FBd0M7QUFFeEMsU0FBZ0IsbUNBQW1DLENBQUMsUUFBZ0I7SUFDbEUsTUFBTSxZQUFZLEdBQUcsY0FBTyxDQUFDLFFBQVEsRUFBRSxXQUFXLENBQUMsQ0FBQTtJQUNuRCxNQUFNLFVBQVUsR0FBRyxjQUFPLENBQUMsWUFBWSxFQUFFLHFCQUFxQixDQUFDLENBQUE7SUFFL0QsTUFBTSxjQUFjLEdBQUcsZ0NBQXVCLENBQUMscUNBQW9CLENBQUMsU0FBUyxFQUFFLENBQUMsUUFBUSxFQUFFLEVBQUUsRUFBRSxRQUFRLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtJQUNoSCxNQUFNLGFBQWEsR0FBRyxnQ0FBdUIsQ0FBQyxvQ0FBbUIsQ0FBQyxTQUFTLEVBQUUsQ0FBQyxRQUFRLEVBQUUsRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO0lBRTlHLE1BQU0sWUFBWSxHQUFHLGNBQU8sQ0FBQyxTQUFTLEVBQUUsV0FBVyxFQUFFLHNCQUFzQixDQUFDLENBQUE7SUFDNUUsTUFBTSxRQUFRLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxpQkFBWSxDQUFDLFlBQVksQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFDLENBQUE7SUFDMUUsTUFBTSxRQUFRLEdBQUcsUUFBUSxDQUFDLEVBQUUsY0FBYyxFQUFFLGFBQWEsRUFBRSxDQUFDLENBQUE7SUFFNUQsa0JBQWEsQ0FBQyxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDckMsQ0FBQztBQVpELGtGQVlDO0FBRUQsSUFBSSxPQUFPLENBQUMsSUFBSSxLQUFLLE1BQU0sRUFBRTtJQUMzQixtQ0FBbUMsQ0FBQyxjQUFPLENBQUMsU0FBUyxFQUFFLElBQUksRUFBRSxJQUFJLEVBQUUsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7Q0FDbEYiLCJmaWxlIjoiZG9jcy90ZW1wbGF0ZS1zdHJpbmdzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IHJlc29sdmUgfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyByZW5kZXJTY2hlbWFEZXNjcmlwdGlvbiB9IGZyb20gXCIuL2NvbmZpZ1wiXG5pbXBvcnQgeyBQcm9qZWN0Q29uZmlnQ29udGV4dCwgTW9kdWxlQ29uZmlnQ29udGV4dCB9IGZyb20gXCIuLi9jb25maWcvY29uZmlnLWNvbnRleHRcIlxuaW1wb3J0IHsgcmVhZEZpbGVTeW5jLCB3cml0ZUZpbGVTeW5jIH0gZnJvbSBcImZzXCJcbmltcG9ydCAqIGFzIGhhbmRsZWJhcnMgZnJvbSBcImhhbmRsZWJhcnNcIlxuXG5leHBvcnQgZnVuY3Rpb24gZ2VuZXJhdGVUZW1wbGF0ZVN0cmluZ1JlZmVyZW5jZURvY3MoZG9jc1Jvb3Q6IHN0cmluZykge1xuICBjb25zdCByZWZlcmVuY2VEaXIgPSByZXNvbHZlKGRvY3NSb290LCBcInJlZmVyZW5jZVwiKVxuICBjb25zdCBvdXRwdXRQYXRoID0gcmVzb2x2ZShyZWZlcmVuY2VEaXIsIFwidGVtcGxhdGUtc3RyaW5ncy5tZFwiKVxuXG4gIGNvbnN0IHByb2plY3RDb250ZXh0ID0gcmVuZGVyU2NoZW1hRGVzY3JpcHRpb24oUHJvamVjdENvbmZpZ0NvbnRleHQuZ2V0U2NoZW1hKCkuZGVzY3JpYmUoKSwgeyByZXF1aXJlZDogZmFsc2UgfSlcbiAgY29uc3QgbW9kdWxlQ29udGV4dCA9IHJlbmRlclNjaGVtYURlc2NyaXB0aW9uKE1vZHVsZUNvbmZpZ0NvbnRleHQuZ2V0U2NoZW1hKCkuZGVzY3JpYmUoKSwgeyByZXF1aXJlZDogZmFsc2UgfSlcblxuICBjb25zdCB0ZW1wbGF0ZVBhdGggPSByZXNvbHZlKF9fZGlybmFtZSwgXCJ0ZW1wbGF0ZXNcIiwgXCJ0ZW1wbGF0ZS1zdHJpbmdzLmhic1wiKVxuICBjb25zdCB0ZW1wbGF0ZSA9IGhhbmRsZWJhcnMuY29tcGlsZShyZWFkRmlsZVN5bmModGVtcGxhdGVQYXRoKS50b1N0cmluZygpKVxuICBjb25zdCBtYXJrZG93biA9IHRlbXBsYXRlKHsgcHJvamVjdENvbnRleHQsIG1vZHVsZUNvbnRleHQgfSlcblxuICB3cml0ZUZpbGVTeW5jKG91dHB1dFBhdGgsIG1hcmtkb3duKVxufVxuXG5pZiAocmVxdWlyZS5tYWluID09PSBtb2R1bGUpIHtcbiAgZ2VuZXJhdGVUZW1wbGF0ZVN0cmluZ1JlZmVyZW5jZURvY3MocmVzb2x2ZShfX2Rpcm5hbWUsIFwiLi5cIiwgXCIuLlwiLCBcIi4uXCIsIFwiZG9jc1wiKSlcbn1cbiJdfQ== diff --git a/garden-service/build/exceptions.d.ts b/garden-service/build/exceptions.d.ts new file mode 100644 index 00000000000..8742be941e6 --- /dev/null +++ b/garden-service/build/exceptions.d.ts @@ -0,0 +1,49 @@ +export interface GardenError { + type: string; + message: string; + detail?: any; + stack?: string; +} +export declare abstract class GardenBaseError extends Error implements GardenError { + abstract type: string; + detail: any; + constructor(message: string, detail: object); +} +export declare function toGardenError(err: Error | GardenError): GardenError; +export declare class AuthenticationError extends GardenBaseError { + type: string; +} +export declare class ConfigurationError extends GardenBaseError { + type: string; +} +export declare class LocalConfigError extends GardenBaseError { + type: string; +} +export declare class ValidationError extends GardenBaseError { + type: string; +} +export declare class PluginError extends GardenBaseError { + type: string; +} +export declare class ParameterError extends GardenBaseError { + type: string; +} +export declare class NotImplementedError extends GardenBaseError { + type: string; +} +export declare class DeploymentError extends GardenBaseError { + type: string; +} +export declare class RuntimeError extends GardenBaseError { + type: string; +} +export declare class InternalError extends GardenBaseError { + type: string; +} +export declare class TimeoutError extends GardenBaseError { + type: string; +} +export declare class NotFoundError extends GardenBaseError { + type: string; +} +//# sourceMappingURL=exceptions.d.ts.map \ No newline at end of file diff --git a/garden-service/build/exceptions.js b/garden-service/build/exceptions.js new file mode 100644 index 00000000000..974a077562e --- /dev/null +++ b/garden-service/build/exceptions.js @@ -0,0 +1,113 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +class GardenBaseError extends Error { + constructor(message, detail) { + super(message); + this.detail = detail; + } +} +exports.GardenBaseError = GardenBaseError; +function toGardenError(err) { + if (err instanceof GardenBaseError) { + return err; + } + else { + const out = new RuntimeError(err.message, {}); + out.stack = err.stack; + return out; + } +} +exports.toGardenError = toGardenError; +class AuthenticationError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "authentication"; + } +} +exports.AuthenticationError = AuthenticationError; +class ConfigurationError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "configuration"; + } +} +exports.ConfigurationError = ConfigurationError; +class LocalConfigError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "local-config"; + } +} +exports.LocalConfigError = LocalConfigError; +class ValidationError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "validation"; + } +} +exports.ValidationError = ValidationError; +class PluginError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "plugin"; + } +} +exports.PluginError = PluginError; +class ParameterError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "parameter"; + } +} +exports.ParameterError = ParameterError; +class NotImplementedError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "not-implemented"; + } +} +exports.NotImplementedError = NotImplementedError; +class DeploymentError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "deployment"; + } +} +exports.DeploymentError = DeploymentError; +class RuntimeError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "runtime"; + } +} +exports.RuntimeError = RuntimeError; +class InternalError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "internal"; + } +} +exports.InternalError = InternalError; +class TimeoutError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "timeout"; + } +} +exports.TimeoutError = TimeoutError; +class NotFoundError extends GardenBaseError { + constructor() { + super(...arguments); + this.type = "not-found"; + } +} +exports.NotFoundError = NotFoundError; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImV4Y2VwdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFTSCxNQUFzQixlQUFnQixTQUFRLEtBQUs7SUFJakQsWUFBWSxPQUFlLEVBQUUsTUFBYztRQUN6QyxLQUFLLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtJQUN0QixDQUFDO0NBQ0Y7QUFSRCwwQ0FRQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxHQUF3QjtJQUNwRCxJQUFJLEdBQUcsWUFBWSxlQUFlLEVBQUU7UUFDbEMsT0FBTyxHQUFHLENBQUE7S0FDWDtTQUFNO1FBQ0wsTUFBTSxHQUFHLEdBQUcsSUFBSSxZQUFZLENBQUMsR0FBRyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsQ0FBQTtRQUM3QyxHQUFHLENBQUMsS0FBSyxHQUFHLEdBQUcsQ0FBQyxLQUFLLENBQUE7UUFDckIsT0FBTyxHQUFHLENBQUE7S0FDWDtBQUNILENBQUM7QUFSRCxzQ0FRQztBQUVELE1BQWEsbUJBQW9CLFNBQVEsZUFBZTtJQUF4RDs7UUFDRSxTQUFJLEdBQUcsZ0JBQWdCLENBQUE7SUFDekIsQ0FBQztDQUFBO0FBRkQsa0RBRUM7QUFFRCxNQUFhLGtCQUFtQixTQUFRLGVBQWU7SUFBdkQ7O1FBQ0UsU0FBSSxHQUFHLGVBQWUsQ0FBQTtJQUN4QixDQUFDO0NBQUE7QUFGRCxnREFFQztBQUVELE1BQWEsZ0JBQWlCLFNBQVEsZUFBZTtJQUFyRDs7UUFDRSxTQUFJLEdBQUcsY0FBYyxDQUFBO0lBQ3ZCLENBQUM7Q0FBQTtBQUZELDRDQUVDO0FBRUQsTUFBYSxlQUFnQixTQUFRLGVBQWU7SUFBcEQ7O1FBQ0UsU0FBSSxHQUFHLFlBQVksQ0FBQTtJQUNyQixDQUFDO0NBQUE7QUFGRCwwQ0FFQztBQUVELE1BQWEsV0FBWSxTQUFRLGVBQWU7SUFBaEQ7O1FBQ0UsU0FBSSxHQUFHLFFBQVEsQ0FBQTtJQUNqQixDQUFDO0NBQUE7QUFGRCxrQ0FFQztBQUVELE1BQWEsY0FBZSxTQUFRLGVBQWU7SUFBbkQ7O1FBQ0UsU0FBSSxHQUFHLFdBQVcsQ0FBQTtJQUNwQixDQUFDO0NBQUE7QUFGRCx3Q0FFQztBQUVELE1BQWEsbUJBQW9CLFNBQVEsZUFBZTtJQUF4RDs7UUFDRSxTQUFJLEdBQUcsaUJBQWlCLENBQUE7SUFDMUIsQ0FBQztDQUFBO0FBRkQsa0RBRUM7QUFFRCxNQUFhLGVBQWdCLFNBQVEsZUFBZTtJQUFwRDs7UUFDRSxTQUFJLEdBQUcsWUFBWSxDQUFBO0lBQ3JCLENBQUM7Q0FBQTtBQUZELDBDQUVDO0FBRUQsTUFBYSxZQUFhLFNBQVEsZUFBZTtJQUFqRDs7UUFDRSxTQUFJLEdBQUcsU0FBUyxDQUFBO0lBQ2xCLENBQUM7Q0FBQTtBQUZELG9DQUVDO0FBRUQsTUFBYSxhQUFjLFNBQVEsZUFBZTtJQUFsRDs7UUFDRSxTQUFJLEdBQUcsVUFBVSxDQUFBO0lBQ25CLENBQUM7Q0FBQTtBQUZELHNDQUVDO0FBRUQsTUFBYSxZQUFhLFNBQVEsZUFBZTtJQUFqRDs7UUFDRSxTQUFJLEdBQUcsU0FBUyxDQUFBO0lBQ2xCLENBQUM7Q0FBQTtBQUZELG9DQUVDO0FBRUQsTUFBYSxhQUFjLFNBQVEsZUFBZTtJQUFsRDs7UUFDRSxTQUFJLEdBQUcsV0FBVyxDQUFBO0lBQ3BCLENBQUM7Q0FBQTtBQUZELHNDQUVDIiwiZmlsZSI6ImV4Y2VwdGlvbnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuZXhwb3J0IGludGVyZmFjZSBHYXJkZW5FcnJvciB7XG4gIHR5cGU6IHN0cmluZ1xuICBtZXNzYWdlOiBzdHJpbmdcbiAgZGV0YWlsPzogYW55XG4gIHN0YWNrPzogc3RyaW5nXG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBHYXJkZW5CYXNlRXJyb3IgZXh0ZW5kcyBFcnJvciBpbXBsZW1lbnRzIEdhcmRlbkVycm9yIHtcbiAgYWJzdHJhY3QgdHlwZTogc3RyaW5nXG4gIGRldGFpbDogYW55XG5cbiAgY29uc3RydWN0b3IobWVzc2FnZTogc3RyaW5nLCBkZXRhaWw6IG9iamVjdCkge1xuICAgIHN1cGVyKG1lc3NhZ2UpXG4gICAgdGhpcy5kZXRhaWwgPSBkZXRhaWxcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gdG9HYXJkZW5FcnJvcihlcnI6IEVycm9yIHwgR2FyZGVuRXJyb3IpOiBHYXJkZW5FcnJvciB7XG4gIGlmIChlcnIgaW5zdGFuY2VvZiBHYXJkZW5CYXNlRXJyb3IpIHtcbiAgICByZXR1cm4gZXJyXG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgb3V0ID0gbmV3IFJ1bnRpbWVFcnJvcihlcnIubWVzc2FnZSwge30pXG4gICAgb3V0LnN0YWNrID0gZXJyLnN0YWNrXG4gICAgcmV0dXJuIG91dFxuICB9XG59XG5cbmV4cG9ydCBjbGFzcyBBdXRoZW50aWNhdGlvbkVycm9yIGV4dGVuZHMgR2FyZGVuQmFzZUVycm9yIHtcbiAgdHlwZSA9IFwiYXV0aGVudGljYXRpb25cIlxufVxuXG5leHBvcnQgY2xhc3MgQ29uZmlndXJhdGlvbkVycm9yIGV4dGVuZHMgR2FyZGVuQmFzZUVycm9yIHtcbiAgdHlwZSA9IFwiY29uZmlndXJhdGlvblwiXG59XG5cbmV4cG9ydCBjbGFzcyBMb2NhbENvbmZpZ0Vycm9yIGV4dGVuZHMgR2FyZGVuQmFzZUVycm9yIHtcbiAgdHlwZSA9IFwibG9jYWwtY29uZmlnXCJcbn1cblxuZXhwb3J0IGNsYXNzIFZhbGlkYXRpb25FcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcInZhbGlkYXRpb25cIlxufVxuXG5leHBvcnQgY2xhc3MgUGx1Z2luRXJyb3IgZXh0ZW5kcyBHYXJkZW5CYXNlRXJyb3Ige1xuICB0eXBlID0gXCJwbHVnaW5cIlxufVxuXG5leHBvcnQgY2xhc3MgUGFyYW1ldGVyRXJyb3IgZXh0ZW5kcyBHYXJkZW5CYXNlRXJyb3Ige1xuICB0eXBlID0gXCJwYXJhbWV0ZXJcIlxufVxuXG5leHBvcnQgY2xhc3MgTm90SW1wbGVtZW50ZWRFcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcIm5vdC1pbXBsZW1lbnRlZFwiXG59XG5cbmV4cG9ydCBjbGFzcyBEZXBsb3ltZW50RXJyb3IgZXh0ZW5kcyBHYXJkZW5CYXNlRXJyb3Ige1xuICB0eXBlID0gXCJkZXBsb3ltZW50XCJcbn1cblxuZXhwb3J0IGNsYXNzIFJ1bnRpbWVFcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcInJ1bnRpbWVcIlxufVxuXG5leHBvcnQgY2xhc3MgSW50ZXJuYWxFcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcImludGVybmFsXCJcbn1cblxuZXhwb3J0IGNsYXNzIFRpbWVvdXRFcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcInRpbWVvdXRcIlxufVxuXG5leHBvcnQgY2xhc3MgTm90Rm91bmRFcnJvciBleHRlbmRzIEdhcmRlbkJhc2VFcnJvciB7XG4gIHR5cGUgPSBcIm5vdC1mb3VuZFwiXG59XG4iXX0= diff --git a/garden-service/build/garden.d.ts b/garden-service/build/garden.d.ts new file mode 100644 index 00000000000..4b3030b39fe --- /dev/null +++ b/garden-service/build/garden.d.ts @@ -0,0 +1,135 @@ +import { TreeCache } from "./cache"; +import { Module } from "./types/module"; +import { Environment, SourceConfig } from "./config/project"; +import { VcsHandler, ModuleVersion } from "./vcs/base"; +import { BuildDir } from "./build-dir"; +import { TaskResults } from "./task-graph"; +import { Logger } from "./logger/logger"; +import { PluginActions } from "./types/plugin/plugin"; +import { Service } from "./types/service"; +import { GardenConfig } from "./config/base"; +import { Task } from "./tasks/base"; +import { LocalConfigStore } from "./config-store"; +import { ExternalSourceType } from "./util/ext-source-util"; +import { BuildDependencyConfig, ModuleConfig } from "./config/module"; +import { ActionHelper } from "./actions"; +import { ModuleAndServiceActions, Plugins } from "./types/plugin/plugin"; +export interface ActionHandlerMap { + [actionName: string]: PluginActions[T]; +} +export interface ModuleActionHandlerMap { + [actionName: string]: ModuleAndServiceActions[T]; +} +export declare type PluginActionMap = { + [A in keyof PluginActions]: { + [pluginName: string]: PluginActions[A]; + }; +}; +export declare type ModuleActionMap = { + [A in keyof ModuleAndServiceActions]: { + [moduleType: string]: { + [pluginName: string]: ModuleAndServiceActions[A]; + }; + }; +}; +export interface ContextOpts { + config?: GardenConfig; + env?: string; + logger?: Logger; + plugins?: Plugins; +} +export declare class Garden { + readonly projectRoot: string; + readonly projectName: string; + readonly environment: Environment; + readonly projectSources: SourceConfig[]; + readonly buildDir: BuildDir; + readonly log: Logger; + readonly actionHandlers: PluginActionMap; + readonly moduleActionHandlers: ModuleActionMap; + private readonly loadedPlugins; + private moduleConfigs; + private modulesScanned; + private readonly registeredPlugins; + private readonly serviceNameIndex; + private readonly taskGraph; + readonly localConfigStore: LocalConfigStore; + readonly vcs: VcsHandler; + readonly cache: TreeCache; + readonly actions: ActionHelper; + constructor(projectRoot: string, projectName: string, environment: Environment, projectSources: SourceConfig[], buildDir: BuildDir, logger?: Logger); + static factory(currentDirectory: string, { env, config, logger, plugins }?: ContextOpts): Promise; + getPluginContext(providerName: string): import("./plugin-context").PluginContext; + clearBuilds(): Promise; + addTask(task: Task): Promise; + processTasks(): Promise; + private registerPlugin; + private loadPlugin; + private getPlugin; + private addActionHandler; + private addModuleActionHandler; + getModules(names?: string[], noScan?: boolean): Promise; + /** + * Returns the module with the specified name. Throws error if it doesn't exist. + */ + getModule(name: string, noScan?: boolean): Promise; + /** + * Given the provided lists of build and service dependencies, return a list of all modules + * required to satisfy those dependencies. + */ + resolveModuleDependencies(buildDependencies: BuildDependencyConfig[], serviceDependencies: string[]): any; + /** + * Given a module, and a list of dependencies, resolve the version for that combination of modules. + * The combined version is a either the latest dirty module version (if any), or the hash of the module version + * and the versions of its dependencies (in sorted order). + */ + resolveVersion(moduleName: string, moduleDependencies: BuildDependencyConfig[], force?: boolean): Promise; + getServices(names?: string[], noScan?: boolean): Promise; + /** + * Returns the service with the specified name. Throws error if it doesn't exist. + */ + getService(name: string, noScan?: boolean): Promise>; + scanModules(force?: boolean): Promise; + private detectCircularDependencies; + addModule(config: ModuleConfig, force?: boolean): Promise; + resolveModule(nameOrLocation: string): Promise; + /** + * Clones the project/module source if needed and returns the path (either from .garden/sources or from a local path) + */ + loadExtSourcePath({ name, repositoryUrl, sourceType }: { + name: string; + repositoryUrl: string; + sourceType: ExternalSourceType; + }): Promise; + /** + * Get a handler for the specified action. + */ + getActionHandlers(actionType: T, pluginName?: string): ActionHandlerMap; + /** + * Get a handler for the specified module action. + */ + getModuleActionHandlers({ actionType, moduleType, pluginName }: { + actionType: T; + moduleType: string; + pluginName?: string; + }): ModuleActionHandlerMap; + private filterActionHandlers; + /** + * Get the last configured handler for the specified action (and optionally module type). + */ + getActionHandler({ actionType, pluginName, defaultHandler }: { + actionType: T; + pluginName?: string; + defaultHandler?: PluginActions[T]; + }): PluginActions[T]; + /** + * Get the last configured handler for the specified action. + */ + getModuleActionHandler({ actionType, moduleType, pluginName, defaultHandler }: { + actionType: T; + moduleType: string; + pluginName?: string; + defaultHandler?: ModuleAndServiceActions[T]; + }): ModuleAndServiceActions[T]; +} +//# sourceMappingURL=garden.d.ts.map \ No newline at end of file diff --git a/garden-service/build/garden.js b/garden-service/build/garden.js new file mode 100644 index 00000000000..de46e159d77 --- /dev/null +++ b/garden-service/build/garden.js @@ -0,0 +1,673 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const path_1 = require("path"); +const lodash_1 = require("lodash"); +const AsyncLock = require("async-lock"); +const cache_1 = require("./cache"); +const plugins_1 = require("./plugins/plugins"); +const module_1 = require("./types/module"); +const plugin_1 = require("./types/plugin/plugin"); +const project_1 = require("./config/project"); +const util_1 = require("./util/util"); +const constants_1 = require("./constants"); +const exceptions_1 = require("./exceptions"); +const git_1 = require("./vcs/git"); +const build_dir_1 = require("./build-dir"); +const task_graph_1 = require("./task-graph"); +const logger_1 = require("./logger/logger"); +const plugin_2 = require("./types/plugin/plugin"); +const common_1 = require("./config/common"); +const template_string_1 = require("./template-string"); +const base_1 = require("./config/base"); +const config_store_1 = require("./config-store"); +const detectCycles_1 = require("./util/detectCycles"); +const ext_source_util_1 = require("./util/ext-source-util"); +const config_context_1 = require("./config/config-context"); +const file_writer_1 = require("./logger/writers/file-writer"); +const log_node_1 = require("./logger/log-node"); +const actions_1 = require("./actions"); +const plugin_context_1 = require("./plugin-context"); +const scanLock = new AsyncLock(); +const fileWriterConfigs = [ + { filename: "development.log" }, + { filename: constants_1.ERROR_LOG_FILENAME, level: log_node_1.LogLevel.error }, + { filename: constants_1.ERROR_LOG_FILENAME, level: log_node_1.LogLevel.error, path: ".", truncatePrevious: true }, +]; +class Garden { + constructor(projectRoot, projectName, environment, projectSources = [], buildDir, logger) { + this.projectRoot = projectRoot; + this.projectName = projectName; + this.environment = environment; + this.projectSources = projectSources; + this.buildDir = buildDir; + this.modulesScanned = false; + this.log = logger || logger_1.getLogger(); + // TODO: Support other VCS options. + this.vcs = new git_1.GitHandler(this.projectRoot); + this.localConfigStore = new config_store_1.LocalConfigStore(this.projectRoot); + this.cache = new cache_1.TreeCache(); + this.moduleConfigs = {}; + this.serviceNameIndex = {}; + this.loadedPlugins = {}; + this.registeredPlugins = {}; + this.actionHandlers = lodash_1.fromPairs(plugin_2.pluginActionNames.map(n => [n, {}])); + this.moduleActionHandlers = lodash_1.fromPairs(plugin_1.moduleActionNames.map(n => [n, {}])); + this.taskGraph = new task_graph_1.TaskGraph(this); + this.actions = new actions_1.ActionHelper(this); + } + static factory(currentDirectory, { env, config, logger, plugins = {} } = {}) { + return __awaiter(this, void 0, void 0, function* () { + let parsedConfig; + if (config) { + parsedConfig = common_1.validate(config, base_1.configSchema, { context: "root configuration" }); + if (!parsedConfig.project) { + throw new exceptions_1.ConfigurationError(`Supplied config does not contain a project configuration`, { + currentDirectory, + config, + }); + } + } + else { + config = yield base_1.findProjectConfig(currentDirectory); + if (!config || !config.project) { + throw new exceptions_1.ConfigurationError(`Not a project directory (or any of the parent directories): ${currentDirectory}`, { currentDirectory }); + } + parsedConfig = yield template_string_1.resolveTemplateStrings(config, new config_context_1.ProjectConfigContext()); + } + const projectRoot = parsedConfig.path; + const { defaultEnvironment, environments, name: projectName, environmentDefaults, sources: projectSources, } = parsedConfig.project; + if (!env) { + env = defaultEnvironment; + } + const parts = env.split("."); + const environmentName = parts[0]; + const namespace = parts.slice(1).join(".") || constants_1.DEFAULT_NAMESPACE; + const environmentConfig = util_1.findByName(environments, environmentName); + if (!environmentConfig) { + throw new exceptions_1.ParameterError(`Project ${projectName} does not specify environment ${environmentName}`, { + projectName, + env, + definedEnvironments: util_1.getNames(environments), + }); + } + if (!environmentConfig.providers || environmentConfig.providers.length === 0) { + throw new exceptions_1.ConfigurationError(`Environment '${environmentName}' does not specify any providers`, { + projectName, + env, + environmentConfig, + }); + } + if (namespace.startsWith("garden-")) { + throw new exceptions_1.ParameterError(`Namespace cannot start with "garden-"`, { + environmentConfig, + namespace, + }); + } + const fixedProviders = plugins_1.fixedPlugins.map(name => ({ name })); + const mergedProviders = lodash_1.merge(fixedProviders, lodash_1.keyBy(environmentDefaults.providers, "name"), lodash_1.keyBy(environmentConfig.providers, "name")); + // Resolve the project configuration based on selected environment + const environment = { + name: environmentConfig.name, + providers: Object.values(mergedProviders), + variables: lodash_1.merge({}, environmentDefaults.variables, environmentConfig.variables), + }; + const buildDir = yield build_dir_1.BuildDir.factory(projectRoot); + // Register log writers + if (logger) { + for (const writerConfig of fileWriterConfigs) { + logger.writers.push(yield file_writer_1.FileWriter.factory(Object.assign({ level: logger.level, root: projectRoot }, writerConfig))); + } + } + const garden = new Garden(projectRoot, projectName, environment, projectSources, buildDir, logger); + // Register plugins + for (const [name, pluginFactory] of Object.entries(Object.assign({}, plugins_1.builtinPlugins, plugins))) { + garden.registerPlugin(name, pluginFactory); + } + // Load configured plugins + // Validate configuration + for (const provider of environment.providers) { + yield garden.loadPlugin(provider.name, provider); + } + return garden; + }); + } + getPluginContext(providerName) { + return plugin_context_1.createPluginContext(this, providerName); + } + clearBuilds() { + return __awaiter(this, void 0, void 0, function* () { + return this.buildDir.clear(); + }); + } + addTask(task) { + return __awaiter(this, void 0, void 0, function* () { + yield this.taskGraph.addTask(task); + }); + } + processTasks() { + return __awaiter(this, void 0, void 0, function* () { + return this.taskGraph.processTasks(); + }); + } + registerPlugin(name, moduleOrFactory) { + let factory; + if (typeof moduleOrFactory === "function") { + factory = moduleOrFactory; + } + else if (lodash_1.isString(moduleOrFactory)) { + let moduleNameOrLocation = moduleOrFactory; + const parsedLocation = path_1.parse(moduleNameOrLocation); + // allow relative references to project root + if (path_1.parse(moduleNameOrLocation).dir !== "") { + console.log(this.projectRoot); + console.log(moduleNameOrLocation); + moduleNameOrLocation = path_1.resolve(this.projectRoot, moduleNameOrLocation); + } + let pluginModule; + try { + pluginModule = require(moduleNameOrLocation); + } + catch (error) { + throw new exceptions_1.ConfigurationError(`Unable to load plugin "${moduleNameOrLocation}" (could not load module: ${error.message})`, { + message: error.message, + moduleNameOrLocation, + }); + } + try { + pluginModule = common_1.validate(pluginModule, plugin_1.pluginModuleSchema, { context: `plugin module "${moduleNameOrLocation}"` }); + if (pluginModule.name) { + name = pluginModule.name; + } + else { + if (parsedLocation.name === "index") { + // use parent directory name + name = parsedLocation.dir.split(path_1.sep).slice(-1)[0]; + } + else { + name = parsedLocation.name; + } + } + common_1.validate(name, common_1.joiIdentifier(), { context: `name of plugin "${moduleNameOrLocation}"` }); + } + catch (err) { + throw new exceptions_1.PluginError(`Unable to load plugin: ${err}`, { + moduleNameOrLocation, + err, + }); + } + factory = pluginModule.gardenPlugin; + } + else { + throw new TypeError(`Expected plugin factory function, module name or module path`); + } + this.registeredPlugins[name] = factory; + } + loadPlugin(pluginName, config) { + return __awaiter(this, void 0, void 0, function* () { + const factory = this.registeredPlugins[pluginName]; + if (!factory) { + throw new exceptions_1.ConfigurationError(`Configured plugin '${pluginName}' has not been registered`, { + name: pluginName, + availablePlugins: Object.keys(this.registeredPlugins), + }); + } + let plugin; + try { + plugin = yield factory({ + projectName: this.projectName, + config, + logEntry: this.log, + }); + } + catch (error) { + throw new exceptions_1.PluginError(`Unexpected error when loading plugin "${pluginName}": ${error}`, { + pluginName, + error, + }); + } + plugin = common_1.validate(plugin, plugin_1.pluginSchema, { context: `plugin "${pluginName}"` }); + this.loadedPlugins[pluginName] = plugin; + // allow plugins to extend their own config (that gets passed to action handlers) + const providerConfig = util_1.findByName(this.environment.providers, pluginName); + if (providerConfig) { + lodash_1.extend(providerConfig, plugin.config, config); + } + else { + this.environment.providers.push(lodash_1.extend({ name: pluginName }, plugin.config, config)); + } + for (const modulePath of plugin.modules || []) { + let moduleConfig = yield this.resolveModule(modulePath); + if (!moduleConfig) { + throw new exceptions_1.PluginError(`Could not load module "${modulePath}" specified in plugin "${pluginName}"`, { + pluginName, + modulePath, + }); + } + moduleConfig.plugin = pluginName; + yield this.addModule(moduleConfig); + } + const actions = plugin.actions || {}; + for (const actionType of plugin_2.pluginActionNames) { + const handler = actions[actionType]; + handler && this.addActionHandler(pluginName, actionType, handler); + } + const moduleActions = plugin.moduleActions || {}; + for (const moduleType of Object.keys(moduleActions)) { + for (const actionType of plugin_1.moduleActionNames) { + const handler = moduleActions[moduleType][actionType]; + handler && this.addModuleActionHandler(pluginName, actionType, moduleType, handler); + } + } + }); + } + getPlugin(pluginName) { + const plugin = this.loadedPlugins[pluginName]; + if (!plugin) { + throw new exceptions_1.PluginError(`Could not find plugin ${pluginName}. Are you missing a provider configuration?`, { + pluginName, + availablePlugins: Object.keys(this.loadedPlugins), + }); + } + return plugin; + } + addActionHandler(pluginName, actionType, handler) { + const plugin = this.getPlugin(pluginName); + const schema = plugin_1.pluginActionDescriptions[actionType].resultSchema; + const wrapped = (...args) => __awaiter(this, void 0, void 0, function* () { + const result = yield handler.apply(plugin, args); + return common_1.validate(result, schema, { context: `${actionType} output from plugin ${pluginName}` }); + }); + wrapped["actionType"] = actionType; + wrapped["pluginName"] = pluginName; + this.actionHandlers[actionType][pluginName] = wrapped; + } + addModuleActionHandler(pluginName, actionType, moduleType, handler) { + const plugin = this.getPlugin(pluginName); + const schema = plugin_1.moduleActionDescriptions[actionType].resultSchema; + const wrapped = (...args) => __awaiter(this, void 0, void 0, function* () { + const result = yield handler.apply(plugin, args); + return common_1.validate(result, schema, { context: `${actionType} output from plugin ${pluginName}` }); + }); + wrapped["actionType"] = actionType; + wrapped["pluginName"] = pluginName; + wrapped["moduleType"] = moduleType; + if (!this.moduleActionHandlers[actionType]) { + this.moduleActionHandlers[actionType] = {}; + } + if (!this.moduleActionHandlers[actionType][moduleType]) { + this.moduleActionHandlers[actionType][moduleType] = {}; + } + this.moduleActionHandlers[actionType][moduleType][pluginName] = wrapped; + } + /* + Returns all modules that are registered in this context. + Scans for modules in the project root if it hasn't already been done. + */ + getModules(names, noScan) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.modulesScanned && !noScan) { + yield this.scanModules(); + } + let configs; + if (!!names) { + configs = []; + const missing = []; + for (const name of names) { + const module = this.moduleConfigs[name]; + if (!module) { + missing.push(name); + } + else { + configs.push(module); + } + } + if (missing.length) { + throw new exceptions_1.ParameterError(`Could not find module(s): ${missing.join(", ")}`, { + missing, + available: Object.keys(this.moduleConfigs), + }); + } + } + else { + configs = Object.values(this.moduleConfigs); + } + return Bluebird.map(configs, config => module_1.moduleFromConfig(this, config)); + }); + } + /** + * Returns the module with the specified name. Throws error if it doesn't exist. + */ + getModule(name, noScan) { + return __awaiter(this, void 0, void 0, function* () { + return (yield this.getModules([name], noScan))[0]; + }); + } + /** + * Given the provided lists of build and service dependencies, return a list of all modules + * required to satisfy those dependencies. + */ + resolveModuleDependencies(buildDependencies, serviceDependencies) { + return __awaiter(this, void 0, void 0, function* () { + const buildDeps = yield Bluebird.map(buildDependencies, (dep) => __awaiter(this, void 0, void 0, function* () { + const moduleKey = module_1.getModuleKey(dep.name, dep.plugin); + const module = yield this.getModule(moduleKey); + return [module].concat(yield this.resolveModuleDependencies(module.build.dependencies, [])); + })); + const runtimeDeps = yield Bluebird.map(serviceDependencies, (serviceName) => __awaiter(this, void 0, void 0, function* () { + const service = yield this.getService(serviceName); + return this.resolveModuleDependencies([{ name: service.module.name, copy: [] }], service.config.dependencies || []); + })); + const deps = lodash_1.flatten(buildDeps).concat(lodash_1.flatten(runtimeDeps)); + return lodash_1.sortBy(lodash_1.uniqBy(deps, "name"), "name"); + }); + } + /** + * Given a module, and a list of dependencies, resolve the version for that combination of modules. + * The combined version is a either the latest dirty module version (if any), or the hash of the module version + * and the versions of its dependencies (in sorted order). + */ + resolveVersion(moduleName, moduleDependencies, force = false) { + return __awaiter(this, void 0, void 0, function* () { + const config = this.moduleConfigs[moduleName]; + const cacheKey = ["moduleVersions", moduleName]; + if (!force) { + const cached = this.cache.get(cacheKey); + if (cached) { + return cached; + } + } + const dependencyKeys = moduleDependencies.map(dep => module_1.getModuleKey(dep.name, dep.plugin)); + const dependencies = Object.values(util_1.pickKeys(this.moduleConfigs, dependencyKeys, "module config")); + const cacheContexts = dependencies.concat([config]).map(c => module_1.getModuleCacheContext(c)); + const version = yield this.vcs.resolveVersion(config, dependencies); + this.cache.set(cacheKey, version, ...cacheContexts); + return version; + }); + } + /* + Returns all services that are registered in this context, or the ones specified. + Scans for modules and services in the project root if it hasn't already been done. + */ + getServices(names, noScan) { + return __awaiter(this, void 0, void 0, function* () { + if (!this.modulesScanned && !noScan) { + yield this.scanModules(); + } + const picked = names ? util_1.pickKeys(this.serviceNameIndex, names, "service") : this.serviceNameIndex; + return Bluebird.map(Object.entries(picked), ([serviceName, moduleName]) => __awaiter(this, void 0, void 0, function* () { + const module = yield this.getModule(moduleName); + const config = util_1.findByName(module.serviceConfigs, serviceName); + return { + name: serviceName, + config, + module, + spec: config.spec, + }; + })); + }); + } + /** + * Returns the service with the specified name. Throws error if it doesn't exist. + */ + getService(name, noScan) { + return __awaiter(this, void 0, void 0, function* () { + return (yield this.getServices([name], noScan))[0]; + }); + } + /* + Scans the project root for modules and adds them to the context. + */ + scanModules(force = false) { + return __awaiter(this, void 0, void 0, function* () { + return scanLock.acquire("scan-modules", () => __awaiter(this, void 0, void 0, function* () { + if (this.modulesScanned && !force) { + return; + } + let extSourcePaths = []; + // Add external sources that are defined at the project level. External sources are either kept in + // the .garden/sources dir (and cloned there if needed), or they're linked to a local path via the link command. + for (const { name, repositoryUrl } of this.projectSources) { + const path = yield this.loadExtSourcePath({ name, repositoryUrl, sourceType: "project" }); + extSourcePaths.push(path); + } + const dirsToScan = [this.projectRoot, ...extSourcePaths]; + const modulePaths = lodash_1.flatten(yield Bluebird.map(dirsToScan, (dir) => __awaiter(this, void 0, void 0, function* () { + var e_1, _a; + const ignorer = yield util_1.getIgnorer(dir); + const scanOpts = { + filter: (path) => { + const relPath = path_1.relative(this.projectRoot, path); + return !ignorer.ignores(relPath); + }, + }; + const paths = []; + try { + for (var _b = __asyncValues(util_1.scanDirectory(dir, scanOpts)), _c; _c = yield _b.next(), !_c.done;) { + const item = _c.value; + if (!item) { + continue; + } + const parsedPath = path_1.parse(item.path); + if (parsedPath.base !== constants_1.MODULE_CONFIG_FILENAME) { + continue; + } + paths.push(parsedPath.dir); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); + } + finally { if (e_1) throw e_1.error; } + } + return paths; + }))).filter(Boolean); + yield Bluebird.map(modulePaths, (path) => __awaiter(this, void 0, void 0, function* () { + const config = yield this.resolveModule(path); + config && (yield this.addModule(config)); + })); + this.modulesScanned = true; + yield this.detectCircularDependencies(); + const moduleConfigContext = new config_context_1.ModuleConfigContext(this, this.environment, Object.values(this.moduleConfigs)); + this.moduleConfigs = yield template_string_1.resolveTemplateStrings(this.moduleConfigs, moduleConfigContext); + })); + }); + } + detectCircularDependencies() { + return __awaiter(this, void 0, void 0, function* () { + const modules = yield this.getModules(); + const services = yield this.getServices(); + return detectCycles_1.detectCircularDependencies(modules, services); + }); + } + /* + Adds the specified module to the context + + @param force - add the module again, even if it's already registered + */ + addModule(config, force = false) { + return __awaiter(this, void 0, void 0, function* () { + const validateHandler = yield this.getModuleActionHandler({ actionType: "validate", moduleType: config.type }); + const ctx = this.getPluginContext(validateHandler["pluginName"]); + config = yield validateHandler({ ctx, moduleConfig: config }); + // FIXME: this is rather clumsy + config.name = module_1.getModuleKey(config.name, config.plugin); + if (!force && this.moduleConfigs[config.name]) { + const pathA = path_1.relative(this.projectRoot, this.moduleConfigs[config.name].path); + const pathB = path_1.relative(this.projectRoot, config.path); + throw new exceptions_1.ConfigurationError(`Module ${config.name} is declared multiple times ('${pathA}' and '${pathB}')`, { pathA, pathB }); + } + this.moduleConfigs[config.name] = config; + // Add to service-module map + for (const serviceConfig of config.serviceConfigs) { + const serviceName = serviceConfig.name; + if (!force && this.serviceNameIndex[serviceName]) { + throw new exceptions_1.ConfigurationError(`Service names must be unique - ${serviceName} is declared multiple times ` + + `(in '${this.serviceNameIndex[serviceName]}' and '${config.name}')`, { + serviceName, + moduleA: this.serviceNameIndex[serviceName], + moduleB: config.name, + }); + } + this.serviceNameIndex[serviceName] = config.name; + } + if (this.modulesScanned) { + // need to re-run this if adding modules after initial scan + yield this.detectCircularDependencies(); + } + }); + } + /* + Maps the provided name or locator to a Module. We first look for a module in the + project with the provided name. If it does not exist, we treat it as a path + (resolved with the project path as a base path) and attempt to load the module + from there. + */ + resolveModule(nameOrLocation) { + return __awaiter(this, void 0, void 0, function* () { + const parsedPath = path_1.parse(nameOrLocation); + if (parsedPath.dir === "") { + // Looks like a name + const existingModule = this.moduleConfigs[nameOrLocation]; + if (!existingModule) { + throw new exceptions_1.ConfigurationError(`Module ${nameOrLocation} could not be found`, { + name: nameOrLocation, + }); + } + return existingModule; + } + // Looks like a path + const path = path_1.resolve(this.projectRoot, nameOrLocation); + const config = yield base_1.loadConfig(this.projectRoot, path); + if (!config || !config.module) { + return null; + } + const moduleConfig = lodash_1.cloneDeep(config.module); + if (moduleConfig.repositoryUrl) { + moduleConfig.path = yield this.loadExtSourcePath({ + name: moduleConfig.name, + repositoryUrl: moduleConfig.repositoryUrl, + sourceType: "module", + }); + } + return moduleConfig; + }); + } + //=========================================================================== + //region Internal helpers + //=========================================================================== + /** + * Clones the project/module source if needed and returns the path (either from .garden/sources or from a local path) + */ + loadExtSourcePath({ name, repositoryUrl, sourceType }) { + return __awaiter(this, void 0, void 0, function* () { + const linkedSources = yield ext_source_util_1.getLinkedSources(this, sourceType); + const linked = util_1.findByName(linkedSources, name); + if (linked) { + return linked.path; + } + const path = yield this.vcs.ensureRemoteSource({ name, sourceType, url: repositoryUrl, logEntry: this.log }); + return path; + }); + } + /** + * Get a handler for the specified action. + */ + getActionHandlers(actionType, pluginName) { + return this.filterActionHandlers(this.actionHandlers[actionType], pluginName); + } + /** + * Get a handler for the specified module action. + */ + getModuleActionHandlers({ actionType, moduleType, pluginName }) { + return this.filterActionHandlers((this.moduleActionHandlers[actionType] || {})[moduleType], pluginName); + } + filterActionHandlers(handlers, pluginName) { + // make sure plugin is loaded + if (!!pluginName) { + this.getPlugin(pluginName); + } + if (handlers === undefined) { + handlers = {}; + } + return !pluginName ? handlers : lodash_1.pickBy(handlers, (handler) => handler["pluginName"] === pluginName); + } + /** + * Get the last configured handler for the specified action (and optionally module type). + */ + getActionHandler({ actionType, pluginName, defaultHandler }) { + const handlers = Object.values(this.getActionHandlers(actionType, pluginName)); + if (handlers.length) { + return handlers[handlers.length - 1]; + } + else if (defaultHandler) { + defaultHandler["pluginName"] = project_1.defaultProvider.name; + return defaultHandler; + } + const errorDetails = { + requestedHandlerType: actionType, + environment: this.environment.name, + pluginName, + }; + if (pluginName) { + throw new exceptions_1.PluginError(`Plugin '${pluginName}' does not have a '${actionType}' handler.`, errorDetails); + } + else { + throw new exceptions_1.ParameterError(`No '${actionType}' handler configured in environment '${this.environment.name}'. ` + + `Are you missing a provider configuration?`, errorDetails); + } + } + /** + * Get the last configured handler for the specified action. + */ + getModuleActionHandler({ actionType, moduleType, pluginName, defaultHandler }) { + const handlers = Object.values(this.getModuleActionHandlers({ actionType, moduleType, pluginName })); + if (handlers.length) { + return handlers[handlers.length - 1]; + } + else if (defaultHandler) { + defaultHandler["pluginName"] = project_1.defaultProvider.name; + return defaultHandler; + } + const errorDetails = { + requestedHandlerType: actionType, + requestedModuleType: moduleType, + environment: this.environment.name, + pluginName, + }; + if (pluginName) { + throw new exceptions_1.PluginError(`Plugin '${pluginName}' does not have a '${actionType}' handler for module type '${moduleType}'.`, errorDetails); + } + else { + throw new exceptions_1.ParameterError(`No '${actionType}' handler configured for module type '${moduleType}' in environment ` + + `'${this.environment.name}'. Are you missing a provider configuration?`, errorDetails); + } + } +} +exports.Garden = Garden; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImdhcmRlbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7Ozs7Ozs7OztBQUVILHFDQUFxQztBQUNyQywrQkFLYTtBQUNiLG1DQVdlO0FBQ2YsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLFlBQVksQ0FBQyxDQUFBO0FBRXZDLG1DQUFtQztBQUNuQywrQ0FHMEI7QUFDMUIsMkNBQStHO0FBQy9HLGtEQU04QjtBQUM5Qiw4Q0FBNkU7QUFDN0Usc0NBTW9CO0FBQ3BCLDJDQUlvQjtBQUNwQiw2Q0FJcUI7QUFFckIsbUNBQXNDO0FBQ3RDLDJDQUFzQztBQUN0Qyw2Q0FHcUI7QUFDckIsNENBR3dCO0FBQ3hCLGtEQU04QjtBQUM5Qiw0Q0FBeUQ7QUFFekQsdURBQTBEO0FBQzFELHdDQUtzQjtBQUV0QixpREFBaUQ7QUFDakQsc0RBQWdFO0FBQ2hFLDREQUcrQjtBQUUvQiw0REFBbUY7QUFDbkYsOERBQXlEO0FBQ3pELGdEQUE0QztBQUM1Qyx1Q0FBd0M7QUFDeEMscURBQXNEO0FBZ0N0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLFNBQVMsRUFBRSxDQUFBO0FBRWhDLE1BQU0saUJBQWlCLEdBQUc7SUFDeEIsRUFBRSxRQUFRLEVBQUUsaUJBQWlCLEVBQUU7SUFDL0IsRUFBRSxRQUFRLEVBQUUsOEJBQWtCLEVBQUUsS0FBSyxFQUFFLG1CQUFRLENBQUMsS0FBSyxFQUFFO0lBQ3ZELEVBQUUsUUFBUSxFQUFFLDhCQUFrQixFQUFFLEtBQUssRUFBRSxtQkFBUSxDQUFDLEtBQUssRUFBRSxJQUFJLEVBQUUsR0FBRyxFQUFFLGdCQUFnQixFQUFFLElBQUksRUFBRTtDQUMzRixDQUFBO0FBRUQsTUFBYSxNQUFNO0lBaUJqQixZQUNrQixXQUFtQixFQUNuQixXQUFtQixFQUNuQixXQUF3QixFQUN4QixpQkFBaUMsRUFBRSxFQUNuQyxRQUFrQixFQUNsQyxNQUFlO1FBTEMsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDbkIsZ0JBQVcsR0FBWCxXQUFXLENBQVE7UUFDbkIsZ0JBQVcsR0FBWCxXQUFXLENBQWE7UUFDeEIsbUJBQWMsR0FBZCxjQUFjLENBQXFCO1FBQ25DLGFBQVEsR0FBUixRQUFRLENBQVU7UUFHbEMsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUE7UUFDM0IsSUFBSSxDQUFDLEdBQUcsR0FBRyxNQUFNLElBQUksa0JBQVMsRUFBRSxDQUFBO1FBQ2hDLG1DQUFtQztRQUNuQyxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksZ0JBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDM0MsSUFBSSxDQUFDLGdCQUFnQixHQUFHLElBQUksK0JBQWdCLENBQUMsSUFBSSxDQUFDLFdBQVcsQ0FBQyxDQUFBO1FBQzlELElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxpQkFBUyxFQUFFLENBQUE7UUFFNUIsSUFBSSxDQUFDLGFBQWEsR0FBRyxFQUFFLENBQUE7UUFDdkIsSUFBSSxDQUFDLGdCQUFnQixHQUFHLEVBQUUsQ0FBQTtRQUMxQixJQUFJLENBQUMsYUFBYSxHQUFHLEVBQUUsQ0FBQTtRQUN2QixJQUFJLENBQUMsaUJBQWlCLEdBQUcsRUFBRSxDQUFBO1FBQzNCLElBQUksQ0FBQyxjQUFjLEdBQW9CLGtCQUFTLENBQUMsMEJBQWlCLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3JGLElBQUksQ0FBQyxvQkFBb0IsR0FBb0Isa0JBQVMsQ0FBQywwQkFBaUIsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFFM0YsSUFBSSxDQUFDLFNBQVMsR0FBRyxJQUFJLHNCQUFTLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDcEMsSUFBSSxDQUFDLE9BQU8sR0FBRyxJQUFJLHNCQUFZLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDdkMsQ0FBQztJQUVELE1BQU0sQ0FBTyxPQUFPLENBQUMsZ0JBQXdCLEVBQUUsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxPQUFPLEdBQUcsRUFBRSxLQUFrQixFQUFFOztZQUNwRyxJQUFJLFlBQTBCLENBQUE7WUFFOUIsSUFBSSxNQUFNLEVBQUU7Z0JBQ1YsWUFBWSxHQUFpQixpQkFBUSxDQUFDLE1BQU0sRUFBRSxtQkFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLG9CQUFvQixFQUFFLENBQUMsQ0FBQTtnQkFFOUYsSUFBSSxDQUFDLFlBQVksQ0FBQyxPQUFPLEVBQUU7b0JBQ3pCLE1BQU0sSUFBSSwrQkFBa0IsQ0FBQywwREFBMEQsRUFBRTt3QkFDdkYsZ0JBQWdCO3dCQUNoQixNQUFNO3FCQUNQLENBQUMsQ0FBQTtpQkFDSDthQUNGO2lCQUFNO2dCQUNMLE1BQU0sR0FBRyxNQUFNLHdCQUFpQixDQUFDLGdCQUFnQixDQUFDLENBQUE7Z0JBRWxELElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFO29CQUM5QixNQUFNLElBQUksK0JBQWtCLENBQzFCLCtEQUErRCxnQkFBZ0IsRUFBRSxFQUNqRixFQUFFLGdCQUFnQixFQUFFLENBQ3JCLENBQUE7aUJBQ0Y7Z0JBRUQsWUFBWSxHQUFHLE1BQU0sd0NBQXNCLENBQUMsTUFBTyxFQUFFLElBQUkscUNBQW9CLEVBQUUsQ0FBQyxDQUFBO2FBQ2pGO1lBRUQsTUFBTSxXQUFXLEdBQUcsWUFBWSxDQUFDLElBQUksQ0FBQTtZQUVyQyxNQUFNLEVBQ0osa0JBQWtCLEVBQ2xCLFlBQVksRUFDWixJQUFJLEVBQUUsV0FBVyxFQUNqQixtQkFBbUIsRUFDbkIsT0FBTyxFQUFFLGNBQWMsR0FDeEIsR0FBRyxZQUFZLENBQUMsT0FBUSxDQUFBO1lBRXpCLElBQUksQ0FBQyxHQUFHLEVBQUU7Z0JBQ1IsR0FBRyxHQUFHLGtCQUFrQixDQUFBO2FBQ3pCO1lBRUQsTUFBTSxLQUFLLEdBQUcsR0FBRyxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQTtZQUM1QixNQUFNLGVBQWUsR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFDaEMsTUFBTSxTQUFTLEdBQUcsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksNkJBQWlCLENBQUE7WUFFL0QsTUFBTSxpQkFBaUIsR0FBRyxpQkFBVSxDQUFDLFlBQVksRUFBRSxlQUFlLENBQUMsQ0FBQTtZQUVuRSxJQUFJLENBQUMsaUJBQWlCLEVBQUU7Z0JBQ3RCLE1BQU0sSUFBSSwyQkFBYyxDQUFDLFdBQVcsV0FBVyxpQ0FBaUMsZUFBZSxFQUFFLEVBQUU7b0JBQ2pHLFdBQVc7b0JBQ1gsR0FBRztvQkFDSCxtQkFBbUIsRUFBRSxlQUFRLENBQUMsWUFBWSxDQUFDO2lCQUM1QyxDQUFDLENBQUE7YUFDSDtZQUVELElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLElBQUksaUJBQWlCLENBQUMsU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7Z0JBQzVFLE1BQU0sSUFBSSwrQkFBa0IsQ0FBQyxnQkFBZ0IsZUFBZSxrQ0FBa0MsRUFBRTtvQkFDOUYsV0FBVztvQkFDWCxHQUFHO29CQUNILGlCQUFpQjtpQkFDbEIsQ0FBQyxDQUFBO2FBQ0g7WUFFRCxJQUFJLFNBQVMsQ0FBQyxVQUFVLENBQUMsU0FBUyxDQUFDLEVBQUU7Z0JBQ25DLE1BQU0sSUFBSSwyQkFBYyxDQUFDLHVDQUF1QyxFQUFFO29CQUNoRSxpQkFBaUI7b0JBQ2pCLFNBQVM7aUJBQ1YsQ0FBQyxDQUFBO2FBQ0g7WUFFRCxNQUFNLGNBQWMsR0FBRyxzQkFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFDLENBQUE7WUFFM0QsTUFBTSxlQUFlLEdBQUcsY0FBSyxDQUMzQixjQUFjLEVBQ2QsY0FBSyxDQUFDLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsRUFDNUMsY0FBSyxDQUFDLGlCQUFpQixDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FDM0MsQ0FBQTtZQUVELGtFQUFrRTtZQUNsRSxNQUFNLFdBQVcsR0FBZ0I7Z0JBQy9CLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxJQUFJO2dCQUM1QixTQUFTLEVBQUUsTUFBTSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUM7Z0JBQ3pDLFNBQVMsRUFBRSxjQUFLLENBQUMsRUFBRSxFQUFFLG1CQUFtQixDQUFDLFNBQVMsRUFBRSxpQkFBaUIsQ0FBQyxTQUFTLENBQUM7YUFDakYsQ0FBQTtZQUVELE1BQU0sUUFBUSxHQUFHLE1BQU0sb0JBQVEsQ0FBQyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUE7WUFFcEQsdUJBQXVCO1lBQ3ZCLElBQUksTUFBTSxFQUFFO2dCQUNWLEtBQUssTUFBTSxZQUFZLElBQUksaUJBQWlCLEVBQUU7b0JBQzVDLE1BQU0sQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUNqQixNQUFNLHdCQUFVLENBQUMsT0FBTyxpQkFDdEIsS0FBSyxFQUFFLE1BQU0sQ0FBQyxLQUFLLEVBQ25CLElBQUksRUFBRSxXQUFXLElBQ2QsWUFBWSxFQUNmLENBQ0gsQ0FBQTtpQkFDRjthQUNGO1lBRUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxNQUFNLENBQ3ZCLFdBQVcsRUFDWCxXQUFXLEVBQ1gsV0FBVyxFQUNYLGNBQWMsRUFDZCxRQUFRLEVBQ1IsTUFBTSxDQUNQLENBQUE7WUFFRCxtQkFBbUI7WUFDbkIsS0FBSyxNQUFNLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxJQUFJLE1BQU0sQ0FBQyxPQUFPLG1CQUFNLHdCQUFjLEVBQUssT0FBTyxFQUFHLEVBQUU7Z0JBQ3JGLE1BQU0sQ0FBQyxjQUFjLENBQUMsSUFBSSxFQUFFLGFBQWEsQ0FBQyxDQUFBO2FBQzNDO1lBRUQsMEJBQTBCO1lBQzFCLHlCQUF5QjtZQUN6QixLQUFLLE1BQU0sUUFBUSxJQUFJLFdBQVcsQ0FBQyxTQUFTLEVBQUU7Z0JBQzVDLE1BQU0sTUFBTSxDQUFDLFVBQVUsQ0FBQyxRQUFRLENBQUMsSUFBSSxFQUFFLFFBQVEsQ0FBQyxDQUFBO2FBQ2pEO1lBRUQsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDO0tBQUE7SUFFRCxnQkFBZ0IsQ0FBQyxZQUFvQjtRQUNuQyxPQUFPLG9DQUFtQixDQUFDLElBQUksRUFBRSxZQUFZLENBQUMsQ0FBQTtJQUNoRCxDQUFDO0lBRUssV0FBVzs7WUFDZixPQUFPLElBQUksQ0FBQyxRQUFRLENBQUMsS0FBSyxFQUFFLENBQUE7UUFDOUIsQ0FBQztLQUFBO0lBRUssT0FBTyxDQUFDLElBQVU7O1lBQ3RCLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLENBQUE7UUFDcEMsQ0FBQztLQUFBO0lBRUssWUFBWTs7WUFDaEIsT0FBTyxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksRUFBRSxDQUFBO1FBQ3RDLENBQUM7S0FBQTtJQUVPLGNBQWMsQ0FBQyxJQUFZLEVBQUUsZUFBb0M7UUFDdkUsSUFBSSxPQUFzQixDQUFBO1FBRTFCLElBQUksT0FBTyxlQUFlLEtBQUssVUFBVSxFQUFFO1lBQ3pDLE9BQU8sR0FBRyxlQUFlLENBQUE7U0FFMUI7YUFBTSxJQUFJLGlCQUFRLENBQUMsZUFBZSxDQUFDLEVBQUU7WUFDcEMsSUFBSSxvQkFBb0IsR0FBRyxlQUFlLENBQUE7WUFDMUMsTUFBTSxjQUFjLEdBQUcsWUFBSyxDQUFDLG9CQUFvQixDQUFDLENBQUE7WUFFbEQsNENBQTRDO1lBQzVDLElBQUksWUFBSyxDQUFDLG9CQUFvQixDQUFDLENBQUMsR0FBRyxLQUFLLEVBQUUsRUFBRTtnQkFDMUMsT0FBTyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7Z0JBQzdCLE9BQU8sQ0FBQyxHQUFHLENBQUMsb0JBQW9CLENBQUMsQ0FBQTtnQkFDakMsb0JBQW9CLEdBQUcsY0FBTyxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsb0JBQW9CLENBQUMsQ0FBQTthQUN2RTtZQUVELElBQUksWUFBWSxDQUFBO1lBRWhCLElBQUk7Z0JBQ0YsWUFBWSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO2FBQzdDO1lBQUMsT0FBTyxLQUFLLEVBQUU7Z0JBQ2QsTUFBTSxJQUFJLCtCQUFrQixDQUMxQiwwQkFBMEIsb0JBQW9CLDZCQUE2QixLQUFLLENBQUMsT0FBTyxHQUFHLEVBQUU7b0JBQzNGLE9BQU8sRUFBRSxLQUFLLENBQUMsT0FBTztvQkFDdEIsb0JBQW9CO2lCQUNyQixDQUFDLENBQUE7YUFDTDtZQUVELElBQUk7Z0JBQ0YsWUFBWSxHQUFHLGlCQUFRLENBQ3JCLFlBQVksRUFDWiwyQkFBa0IsRUFDbEIsRUFBRSxPQUFPLEVBQUUsa0JBQWtCLG9CQUFvQixHQUFHLEVBQUUsQ0FDdkQsQ0FBQTtnQkFFRCxJQUFJLFlBQVksQ0FBQyxJQUFJLEVBQUU7b0JBQ3JCLElBQUksR0FBRyxZQUFZLENBQUMsSUFBSSxDQUFBO2lCQUN6QjtxQkFBTTtvQkFDTCxJQUFJLGNBQWMsQ0FBQyxJQUFJLEtBQUssT0FBTyxFQUFFO3dCQUNuQyw0QkFBNEI7d0JBQzVCLElBQUksR0FBRyxjQUFjLENBQUMsR0FBRyxDQUFDLEtBQUssQ0FBQyxVQUFHLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtxQkFDbEQ7eUJBQU07d0JBQ0wsSUFBSSxHQUFHLGNBQWMsQ0FBQyxJQUFJLENBQUE7cUJBQzNCO2lCQUNGO2dCQUVELGlCQUFRLENBQUMsSUFBSSxFQUFFLHNCQUFhLEVBQUUsRUFBRSxFQUFFLE9BQU8sRUFBRSxtQkFBbUIsb0JBQW9CLEdBQUcsRUFBRSxDQUFDLENBQUE7YUFDekY7WUFBQyxPQUFPLEdBQUcsRUFBRTtnQkFDWixNQUFNLElBQUksd0JBQVcsQ0FBQywwQkFBMEIsR0FBRyxFQUFFLEVBQUU7b0JBQ3JELG9CQUFvQjtvQkFDcEIsR0FBRztpQkFDSixDQUFDLENBQUE7YUFDSDtZQUVELE9BQU8sR0FBRyxZQUFZLENBQUMsWUFBWSxDQUFBO1NBRXBDO2FBQU07WUFDTCxNQUFNLElBQUksU0FBUyxDQUFDLDhEQUE4RCxDQUFDLENBQUE7U0FDcEY7UUFFRCxJQUFJLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLEdBQUcsT0FBTyxDQUFBO0lBQ3hDLENBQUM7SUFFYSxVQUFVLENBQUMsVUFBa0IsRUFBRSxNQUFjOztZQUN6RCxNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUMsVUFBVSxDQUFDLENBQUE7WUFFbEQsSUFBSSxDQUFDLE9BQU8sRUFBRTtnQkFDWixNQUFNLElBQUksK0JBQWtCLENBQUMsc0JBQXNCLFVBQVUsMkJBQTJCLEVBQUU7b0JBQ3hGLElBQUksRUFBRSxVQUFVO29CQUNoQixnQkFBZ0IsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQztpQkFDdEQsQ0FBQyxDQUFBO2FBQ0g7WUFFRCxJQUFJLE1BQU0sQ0FBQTtZQUVWLElBQUk7Z0JBQ0YsTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDO29CQUNyQixXQUFXLEVBQUUsSUFBSSxDQUFDLFdBQVc7b0JBQzdCLE1BQU07b0JBQ04sUUFBUSxFQUFFLElBQUksQ0FBQyxHQUFHO2lCQUNuQixDQUFDLENBQUE7YUFDSDtZQUFDLE9BQU8sS0FBSyxFQUFFO2dCQUNkLE1BQU0sSUFBSSx3QkFBVyxDQUFDLHlDQUF5QyxVQUFVLE1BQU0sS0FBSyxFQUFFLEVBQUU7b0JBQ3RGLFVBQVU7b0JBQ1YsS0FBSztpQkFDTixDQUFDLENBQUE7YUFDSDtZQUVELE1BQU0sR0FBRyxpQkFBUSxDQUFDLE1BQU0sRUFBRSxxQkFBWSxFQUFFLEVBQUUsT0FBTyxFQUFFLFdBQVcsVUFBVSxHQUFHLEVBQUUsQ0FBQyxDQUFBO1lBRTlFLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLEdBQUcsTUFBTSxDQUFBO1lBRXZDLGlGQUFpRjtZQUNqRixNQUFNLGNBQWMsR0FBRyxpQkFBVSxDQUFDLElBQUksQ0FBQyxXQUFXLENBQUMsU0FBUyxFQUFFLFVBQVUsQ0FBQyxDQUFBO1lBQ3pFLElBQUksY0FBYyxFQUFFO2dCQUNsQixlQUFNLENBQUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxNQUFNLEVBQUUsTUFBTSxDQUFDLENBQUE7YUFDOUM7aUJBQU07Z0JBQ0wsSUFBSSxDQUFDLFdBQVcsQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLGVBQU0sQ0FBQyxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUUsRUFBRSxNQUFNLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7YUFDckY7WUFFRCxLQUFLLE1BQU0sVUFBVSxJQUFJLE1BQU0sQ0FBQyxPQUFPLElBQUksRUFBRSxFQUFFO2dCQUM3QyxJQUFJLFlBQVksR0FBRyxNQUFNLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUE7Z0JBQ3ZELElBQUksQ0FBQyxZQUFZLEVBQUU7b0JBQ2pCLE1BQU0sSUFBSSx3QkFBVyxDQUFDLDBCQUEwQixVQUFVLDBCQUEwQixVQUFVLEdBQUcsRUFBRTt3QkFDakcsVUFBVTt3QkFDVixVQUFVO3FCQUNYLENBQUMsQ0FBQTtpQkFDSDtnQkFDRCxZQUFZLENBQUMsTUFBTSxHQUFHLFVBQVUsQ0FBQTtnQkFDaEMsTUFBTSxJQUFJLENBQUMsU0FBUyxDQUFDLFlBQVksQ0FBQyxDQUFBO2FBQ25DO1lBRUQsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUE7WUFFcEMsS0FBSyxNQUFNLFVBQVUsSUFBSSwwQkFBaUIsRUFBRTtnQkFDMUMsTUFBTSxPQUFPLEdBQUcsT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFBO2dCQUNuQyxPQUFPLElBQUksSUFBSSxDQUFDLGdCQUFnQixDQUFDLFVBQVUsRUFBRSxVQUFVLEVBQUUsT0FBTyxDQUFDLENBQUE7YUFDbEU7WUFFRCxNQUFNLGFBQWEsR0FBRyxNQUFNLENBQUMsYUFBYSxJQUFJLEVBQUUsQ0FBQTtZQUVoRCxLQUFLLE1BQU0sVUFBVSxJQUFJLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLEVBQUU7Z0JBQ25ELEtBQUssTUFBTSxVQUFVLElBQUksMEJBQWlCLEVBQUU7b0JBQzFDLE1BQU0sT0FBTyxHQUFHLGFBQWEsQ0FBQyxVQUFVLENBQUMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtvQkFDckQsT0FBTyxJQUFJLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxVQUFVLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxPQUFPLENBQUMsQ0FBQTtpQkFDcEY7YUFDRjtRQUNILENBQUM7S0FBQTtJQUVPLFNBQVMsQ0FBQyxVQUFrQjtRQUNsQyxNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLFVBQVUsQ0FBQyxDQUFBO1FBRTdDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDWCxNQUFNLElBQUksd0JBQVcsQ0FBQyx5QkFBeUIsVUFBVSw2Q0FBNkMsRUFBRTtnQkFDdEcsVUFBVTtnQkFDVixnQkFBZ0IsRUFBRSxNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUM7YUFDbEQsQ0FBQyxDQUFBO1NBQ0g7UUFFRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7SUFFTyxnQkFBZ0IsQ0FDdEIsVUFBa0IsRUFBRSxVQUFhLEVBQUUsT0FBeUI7UUFFNUQsTUFBTSxNQUFNLEdBQUcsSUFBSSxDQUFDLFNBQVMsQ0FBQyxVQUFVLENBQUMsQ0FBQTtRQUN6QyxNQUFNLE1BQU0sR0FBRyxpQ0FBd0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxZQUFZLENBQUE7UUFFaEUsTUFBTSxPQUFPLEdBQUcsQ0FBTyxHQUFHLElBQUksRUFBRSxFQUFFO1lBQ2hDLE1BQU0sTUFBTSxHQUFHLE1BQU0sT0FBTyxDQUFDLEtBQUssQ0FBQyxNQUFNLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDaEQsT0FBTyxpQkFBUSxDQUFDLE1BQU0sRUFBRSxNQUFNLEVBQUUsRUFBRSxPQUFPLEVBQUUsR0FBRyxVQUFVLHVCQUF1QixVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUE7UUFDaEcsQ0FBQyxDQUFBLENBQUE7UUFDRCxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsVUFBVSxDQUFBO1FBQ2xDLE9BQU8sQ0FBQyxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUE7UUFFbEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxVQUFVLENBQUMsQ0FBQyxVQUFVLENBQUMsR0FBRyxPQUFPLENBQUE7SUFDdkQsQ0FBQztJQUVPLHNCQUFzQixDQUM1QixVQUFrQixFQUFFLFVBQWEsRUFBRSxVQUFrQixFQUFFLE9BQXlCO1FBRWhGLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUE7UUFDekMsTUFBTSxNQUFNLEdBQUcsaUNBQXdCLENBQUMsVUFBVSxDQUFDLENBQUMsWUFBWSxDQUFBO1FBRWhFLE1BQU0sT0FBTyxHQUFHLENBQU8sR0FBRyxJQUFJLEVBQUUsRUFBRTtZQUNoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxLQUFLLENBQUMsTUFBTSxFQUFFLElBQUksQ0FBQyxDQUFBO1lBQ2hELE9BQU8saUJBQVEsQ0FBQyxNQUFNLEVBQUUsTUFBTSxFQUFFLEVBQUUsT0FBTyxFQUFFLEdBQUcsVUFBVSx1QkFBdUIsVUFBVSxFQUFFLEVBQUUsQ0FBQyxDQUFBO1FBQ2hHLENBQUMsQ0FBQSxDQUFBO1FBQ0QsT0FBTyxDQUFDLFlBQVksQ0FBQyxHQUFHLFVBQVUsQ0FBQTtRQUNsQyxPQUFPLENBQUMsWUFBWSxDQUFDLEdBQUcsVUFBVSxDQUFBO1FBQ2xDLE9BQU8sQ0FBQyxZQUFZLENBQUMsR0FBRyxVQUFVLENBQUE7UUFFbEMsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUMxQyxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFBO1NBQzNDO1FBRUQsSUFBSSxDQUFDLElBQUksQ0FBQyxvQkFBb0IsQ0FBQyxVQUFVLENBQUMsQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUN0RCxJQUFJLENBQUMsb0JBQW9CLENBQUMsVUFBVSxDQUFDLENBQUMsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFBO1NBQ3ZEO1FBRUQsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxHQUFHLE9BQU8sQ0FBQTtJQUN6RSxDQUFDO0lBRUQ7OztPQUdHO0lBQ0csVUFBVSxDQUFDLEtBQWdCLEVBQUUsTUFBZ0I7O1lBQ2pELElBQUksQ0FBQyxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsTUFBTSxFQUFFO2dCQUNuQyxNQUFNLElBQUksQ0FBQyxXQUFXLEVBQUUsQ0FBQTthQUN6QjtZQUVELElBQUksT0FBdUIsQ0FBQTtZQUUzQixJQUFJLENBQUMsQ0FBQyxLQUFLLEVBQUU7Z0JBQ1gsT0FBTyxHQUFHLEVBQUUsQ0FBQTtnQkFDWixNQUFNLE9BQU8sR0FBYSxFQUFFLENBQUE7Z0JBRTVCLEtBQUssTUFBTSxJQUFJLElBQUksS0FBSyxFQUFFO29CQUN4QixNQUFNLE1BQU0sR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLElBQUksQ0FBQyxDQUFBO29CQUV2QyxJQUFJLENBQUMsTUFBTSxFQUFFO3dCQUNYLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7cUJBQ25CO3lCQUFNO3dCQUNMLE9BQU8sQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7cUJBQ3JCO2lCQUNGO2dCQUVELElBQUksT0FBTyxDQUFDLE1BQU0sRUFBRTtvQkFDbEIsTUFBTSxJQUFJLDJCQUFjLENBQUMsNkJBQTZCLE9BQU8sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEVBQUUsRUFBRTt3QkFDMUUsT0FBTzt3QkFDUCxTQUFTLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDO3FCQUMzQyxDQUFDLENBQUE7aUJBQ0g7YUFDRjtpQkFBTTtnQkFDTCxPQUFPLEdBQUcsTUFBTSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUE7YUFDNUM7WUFFRCxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFLE1BQU0sQ0FBQyxFQUFFLENBQUMseUJBQWdCLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7UUFDeEUsQ0FBQztLQUFBO0lBRUQ7O09BRUc7SUFDRyxTQUFTLENBQUMsSUFBWSxFQUFFLE1BQWdCOztZQUM1QyxPQUFPLENBQUMsTUFBTSxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUMsSUFBSSxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQTtRQUNuRCxDQUFDO0tBQUE7SUFFRDs7O09BR0c7SUFDRyx5QkFBeUIsQ0FBQyxpQkFBMEMsRUFBRSxtQkFBNkI7O1lBQ3ZHLE1BQU0sU0FBUyxHQUFHLE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxpQkFBaUIsRUFBRSxDQUFPLEdBQUcsRUFBRSxFQUFFO2dCQUNwRSxNQUFNLFNBQVMsR0FBRyxxQkFBWSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxDQUFBO2dCQUNwRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsU0FBUyxDQUFDLENBQUE7Z0JBQzlDLE9BQU8sQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsTUFBTSxJQUFJLENBQUMseUJBQXlCLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsRUFBRSxDQUFDLENBQUMsQ0FBQTtZQUM3RixDQUFDLENBQUEsQ0FBQyxDQUFBO1lBRUYsTUFBTSxXQUFXLEdBQUcsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUFDLG1CQUFtQixFQUFFLENBQU8sV0FBVyxFQUFFLEVBQUU7Z0JBQ2hGLE1BQU0sT0FBTyxHQUFHLE1BQU0sSUFBSSxDQUFDLFVBQVUsQ0FBQyxXQUFXLENBQUMsQ0FBQTtnQkFDbEQsT0FBTyxJQUFJLENBQUMseUJBQXlCLENBQ25DLENBQUMsRUFBRSxJQUFJLEVBQUUsT0FBTyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsSUFBSSxFQUFFLEVBQUUsRUFBRSxDQUFDLEVBQ3pDLE9BQU8sQ0FBQyxNQUFNLENBQUMsWUFBWSxJQUFJLEVBQUUsQ0FDbEMsQ0FBQTtZQUNILENBQUMsQ0FBQSxDQUFDLENBQUE7WUFFRixNQUFNLElBQUksR0FBRyxnQkFBTyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxnQkFBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUE7WUFFNUQsT0FBTyxlQUFNLENBQUMsZUFBTSxDQUFDLElBQUksRUFBRSxNQUFNLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQTtRQUM3QyxDQUFDO0tBQUE7SUFFRDs7OztPQUlHO0lBQ0csY0FBYyxDQUFDLFVBQWtCLEVBQUUsa0JBQTJDLEVBQUUsS0FBSyxHQUFHLEtBQUs7O1lBQ2pHLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxhQUFhLENBQUMsVUFBVSxDQUFDLENBQUE7WUFDN0MsTUFBTSxRQUFRLEdBQUcsQ0FBQyxnQkFBZ0IsRUFBRSxVQUFVLENBQUMsQ0FBQTtZQUUvQyxJQUFJLENBQUMsS0FBSyxFQUFFO2dCQUNWLE1BQU0sTUFBTSxHQUFrQixJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtnQkFFdEQsSUFBSSxNQUFNLEVBQUU7b0JBQ1YsT0FBTyxNQUFNLENBQUE7aUJBQ2Q7YUFDRjtZQUVELE1BQU0sY0FBYyxHQUFHLGtCQUFrQixDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsRUFBRSxDQUFDLHFCQUFZLENBQUMsR0FBRyxDQUFDLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQTtZQUN4RixNQUFNLFlBQVksR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLGVBQVEsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLGNBQWMsRUFBRSxlQUFlLENBQUMsQ0FBQyxDQUFBO1lBQ2pHLE1BQU0sYUFBYSxHQUFHLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLDhCQUFxQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7WUFFdEYsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsR0FBRyxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFFbkUsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsUUFBUSxFQUFFLE9BQU8sRUFBRSxHQUFHLGFBQWEsQ0FBQyxDQUFBO1lBQ25ELE9BQU8sT0FBTyxDQUFBO1FBQ2hCLENBQUM7S0FBQTtJQUVEOzs7T0FHRztJQUNHLFdBQVcsQ0FBQyxLQUFnQixFQUFFLE1BQWdCOztZQUNsRCxJQUFJLENBQUMsSUFBSSxDQUFDLGNBQWMsSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDbkMsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7YUFDekI7WUFFRCxNQUFNLE1BQU0sR0FBRyxLQUFLLENBQUMsQ0FBQyxDQUFDLGVBQVEsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsS0FBSyxFQUFFLFNBQVMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLENBQUE7WUFFaEcsT0FBTyxRQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBTyxDQUFDLFdBQVcsRUFBRSxVQUFVLENBQUMsRUFBRSxFQUFFO2dCQUM5RSxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxTQUFTLENBQUMsVUFBVSxDQUFDLENBQUE7Z0JBQy9DLE1BQU0sTUFBTSxHQUFHLGlCQUFVLENBQUMsTUFBTSxDQUFDLGNBQWMsRUFBRSxXQUFXLENBQUUsQ0FBQTtnQkFFOUQsT0FBTztvQkFDTCxJQUFJLEVBQUUsV0FBVztvQkFDakIsTUFBTTtvQkFDTixNQUFNO29CQUNOLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTtpQkFDbEIsQ0FBQTtZQUNILENBQUMsQ0FBQSxDQUFDLENBQUE7UUFDSixDQUFDO0tBQUE7SUFFRDs7T0FFRztJQUNHLFVBQVUsQ0FBQyxJQUFZLEVBQUUsTUFBZ0I7O1lBQzdDLE9BQU8sQ0FBQyxNQUFNLElBQUksQ0FBQyxXQUFXLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBQ3BELENBQUM7S0FBQTtJQUVEOztPQUVHO0lBQ0csV0FBVyxDQUFDLEtBQUssR0FBRyxLQUFLOztZQUM3QixPQUFPLFFBQVEsQ0FBQyxPQUFPLENBQUMsY0FBYyxFQUFFLEdBQVMsRUFBRTtnQkFDakQsSUFBSSxJQUFJLENBQUMsY0FBYyxJQUFJLENBQUMsS0FBSyxFQUFFO29CQUNqQyxPQUFNO2lCQUNQO2dCQUVELElBQUksY0FBYyxHQUFhLEVBQUUsQ0FBQTtnQkFFakMsa0dBQWtHO2dCQUNsRyxnSEFBZ0g7Z0JBQ2hILEtBQUssTUFBTSxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsSUFBSSxJQUFJLENBQUMsY0FBYyxFQUFFO29CQUN6RCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7b0JBQ3pGLGNBQWMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7aUJBQzFCO2dCQUVELE1BQU0sVUFBVSxHQUFHLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxHQUFHLGNBQWMsQ0FBQyxDQUFBO2dCQUV4RCxNQUFNLFdBQVcsR0FBRyxnQkFBTyxDQUFDLE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxVQUFVLEVBQUUsQ0FBTSxHQUFHLEVBQUMsRUFBRTs7b0JBQ3JFLE1BQU0sT0FBTyxHQUFHLE1BQU0saUJBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQTtvQkFDckMsTUFBTSxRQUFRLEdBQUc7d0JBQ2YsTUFBTSxFQUFFLENBQUMsSUFBSSxFQUFFLEVBQUU7NEJBQ2YsTUFBTSxPQUFPLEdBQUcsZUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsSUFBSSxDQUFDLENBQUE7NEJBQ2hELE9BQU8sQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO3dCQUNsQyxDQUFDO3FCQUNGLENBQUE7b0JBQ0QsTUFBTSxLQUFLLEdBQWEsRUFBRSxDQUFBOzt3QkFFMUIsS0FBeUIsSUFBQSxLQUFBLGNBQUEsb0JBQWEsQ0FBQyxHQUFHLEVBQUUsUUFBUSxDQUFDLENBQUEsSUFBQTs0QkFBMUMsTUFBTSxJQUFJLFdBQUEsQ0FBQTs0QkFDbkIsSUFBSSxDQUFDLElBQUksRUFBRTtnQ0FDVCxTQUFROzZCQUNUOzRCQUVELE1BQU0sVUFBVSxHQUFHLFlBQUssQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUE7NEJBRW5DLElBQUksVUFBVSxDQUFDLElBQUksS0FBSyxrQ0FBc0IsRUFBRTtnQ0FDOUMsU0FBUTs2QkFDVDs0QkFFRCxLQUFLLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQTt5QkFDM0I7Ozs7Ozs7OztvQkFFRCxPQUFPLEtBQUssQ0FBQTtnQkFDZCxDQUFDLENBQUEsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFBO2dCQUVuQixNQUFNLFFBQVEsQ0FBQyxHQUFHLENBQUMsV0FBVyxFQUFFLENBQU0sSUFBSSxFQUFDLEVBQUU7b0JBQzNDLE1BQU0sTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsQ0FBQTtvQkFDN0MsTUFBTSxLQUFJLE1BQU0sSUFBSSxDQUFDLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQSxDQUFBO2dCQUN4QyxDQUFDLENBQUEsQ0FBQyxDQUFBO2dCQUVGLElBQUksQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFBO2dCQUUxQixNQUFNLElBQUksQ0FBQywwQkFBMEIsRUFBRSxDQUFBO2dCQUV2QyxNQUFNLG1CQUFtQixHQUFHLElBQUksb0NBQW1CLENBQ2pELElBQUksRUFBRSxJQUFJLENBQUMsV0FBVyxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLGFBQWEsQ0FBQyxDQUMxRCxDQUFBO2dCQUNELElBQUksQ0FBQyxhQUFhLEdBQUcsTUFBTSx3Q0FBc0IsQ0FBQyxJQUFJLENBQUMsYUFBYSxFQUFFLG1CQUFtQixDQUFDLENBQUE7WUFDNUYsQ0FBQyxDQUFBLENBQUMsQ0FBQTtRQUNKLENBQUM7S0FBQTtJQUVhLDBCQUEwQjs7WUFDdEMsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsVUFBVSxFQUFFLENBQUE7WUFDdkMsTUFBTSxRQUFRLEdBQUcsTUFBTSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUE7WUFFekMsT0FBTyx5Q0FBMEIsQ0FBQyxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7UUFDdEQsQ0FBQztLQUFBO0lBRUQ7Ozs7T0FJRztJQUNHLFNBQVMsQ0FBQyxNQUFvQixFQUFFLEtBQUssR0FBRyxLQUFLOztZQUNqRCxNQUFNLGVBQWUsR0FBRyxNQUFNLElBQUksQ0FBQyxzQkFBc0IsQ0FBQyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO1lBQzlHLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxlQUFlLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQTtZQUVoRSxNQUFNLEdBQUcsTUFBTSxlQUFlLENBQUMsRUFBRSxHQUFHLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUE7WUFFN0QsK0JBQStCO1lBQy9CLE1BQU0sQ0FBQyxJQUFJLEdBQUcscUJBQVksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtZQUV0RCxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxFQUFFO2dCQUM3QyxNQUFNLEtBQUssR0FBRyxlQUFRLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQTtnQkFDOUUsTUFBTSxLQUFLLEdBQUcsZUFBUSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO2dCQUVyRCxNQUFNLElBQUksK0JBQWtCLENBQzFCLFVBQVUsTUFBTSxDQUFDLElBQUksaUNBQWlDLEtBQUssVUFBVSxLQUFLLElBQUksRUFDOUUsRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQ2pCLENBQUE7YUFDRjtZQUVELElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLE1BQU0sQ0FBQTtZQUV4Qyw0QkFBNEI7WUFDNUIsS0FBSyxNQUFNLGFBQWEsSUFBSSxNQUFNLENBQUMsY0FBYyxFQUFFO2dCQUNqRCxNQUFNLFdBQVcsR0FBRyxhQUFhLENBQUMsSUFBSSxDQUFBO2dCQUV0QyxJQUFJLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxXQUFXLENBQUMsRUFBRTtvQkFDaEQsTUFBTSxJQUFJLCtCQUFrQixDQUMxQixrQ0FBa0MsV0FBVyw4QkFBOEI7d0JBQzNFLFFBQVEsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxVQUFVLE1BQU0sQ0FBQyxJQUFJLElBQUksRUFDbkU7d0JBQ0UsV0FBVzt3QkFDWCxPQUFPLEVBQUUsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQzt3QkFDM0MsT0FBTyxFQUFFLE1BQU0sQ0FBQyxJQUFJO3FCQUNyQixDQUNGLENBQUE7aUJBQ0Y7Z0JBRUQsSUFBSSxDQUFDLGdCQUFnQixDQUFDLFdBQVcsQ0FBQyxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUE7YUFDakQ7WUFFRCxJQUFJLElBQUksQ0FBQyxjQUFjLEVBQUU7Z0JBQ3ZCLDJEQUEyRDtnQkFDM0QsTUFBTSxJQUFJLENBQUMsMEJBQTBCLEVBQUUsQ0FBQTthQUN4QztRQUNILENBQUM7S0FBQTtJQUVEOzs7OztPQUtHO0lBQ0csYUFBYSxDQUFDLGNBQXNCOztZQUN4QyxNQUFNLFVBQVUsR0FBRyxZQUFLLENBQUMsY0FBYyxDQUFDLENBQUE7WUFFeEMsSUFBSSxVQUFVLENBQUMsR0FBRyxLQUFLLEVBQUUsRUFBRTtnQkFDekIsb0JBQW9CO2dCQUNwQixNQUFNLGNBQWMsR0FBRyxJQUFJLENBQUMsYUFBYSxDQUFDLGNBQWMsQ0FBQyxDQUFBO2dCQUV6RCxJQUFJLENBQUMsY0FBYyxFQUFFO29CQUNuQixNQUFNLElBQUksK0JBQWtCLENBQUMsVUFBVSxjQUFjLHFCQUFxQixFQUFFO3dCQUMxRSxJQUFJLEVBQUUsY0FBYztxQkFDckIsQ0FBQyxDQUFBO2lCQUNIO2dCQUVELE9BQU8sY0FBYyxDQUFBO2FBQ3RCO1lBRUQsb0JBQW9CO1lBQ3BCLE1BQU0sSUFBSSxHQUFHLGNBQU8sQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLGNBQWMsQ0FBQyxDQUFBO1lBQ3RELE1BQU0sTUFBTSxHQUFHLE1BQU0saUJBQVUsQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLElBQUksQ0FBQyxDQUFBO1lBRXZELElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO2dCQUM3QixPQUFPLElBQUksQ0FBQTthQUNaO1lBRUQsTUFBTSxZQUFZLEdBQUcsa0JBQVMsQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7WUFFN0MsSUFBSSxZQUFZLENBQUMsYUFBYSxFQUFFO2dCQUM5QixZQUFZLENBQUMsSUFBSSxHQUFHLE1BQU0sSUFBSSxDQUFDLGlCQUFpQixDQUFDO29CQUMvQyxJQUFJLEVBQUUsWUFBWSxDQUFDLElBQUk7b0JBQ3ZCLGFBQWEsRUFBRSxZQUFZLENBQUMsYUFBYTtvQkFDekMsVUFBVSxFQUFFLFFBQVE7aUJBQ3JCLENBQUMsQ0FBQTthQUNIO1lBRUQsT0FBTyxZQUFZLENBQUE7UUFDckIsQ0FBQztLQUFBO0lBRUQsNkVBQTZFO0lBQzdFLHlCQUF5QjtJQUN6Qiw2RUFBNkU7SUFFN0U7O09BRUc7SUFDVSxpQkFBaUIsQ0FBQyxFQUFFLElBQUksRUFBRSxhQUFhLEVBQUUsVUFBVSxFQUkvRDs7WUFFQyxNQUFNLGFBQWEsR0FBRyxNQUFNLGtDQUFnQixDQUFDLElBQUksRUFBRSxVQUFVLENBQUMsQ0FBQTtZQUU5RCxNQUFNLE1BQU0sR0FBRyxpQkFBVSxDQUFDLGFBQWEsRUFBRSxJQUFJLENBQUMsQ0FBQTtZQUU5QyxJQUFJLE1BQU0sRUFBRTtnQkFDVixPQUFPLE1BQU0sQ0FBQyxJQUFJLENBQUE7YUFDbkI7WUFFRCxNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLEdBQUcsRUFBRSxhQUFhLEVBQUUsUUFBUSxFQUFFLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFBO1lBRTVHLE9BQU8sSUFBSSxDQUFBO1FBQ2IsQ0FBQztLQUFBO0lBRUQ7O09BRUc7SUFDSSxpQkFBaUIsQ0FBZ0MsVUFBYSxFQUFFLFVBQW1CO1FBQ3hGLE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxDQUFDLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDL0UsQ0FBQztJQUVEOztPQUVHO0lBQ0ksdUJBQXVCLENBQzVCLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQ3dCO1FBRTVELE9BQU8sSUFBSSxDQUFDLG9CQUFvQixDQUFDLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLFVBQVUsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFDLFVBQVUsQ0FBQyxFQUFFLFVBQVUsQ0FBQyxDQUFBO0lBQ3pHLENBQUM7SUFFTyxvQkFBb0IsQ0FBQyxRQUFRLEVBQUUsVUFBbUI7UUFDeEQsNkJBQTZCO1FBQzdCLElBQUksQ0FBQyxDQUFDLFVBQVUsRUFBRTtZQUNoQixJQUFJLENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQyxDQUFBO1NBQzNCO1FBRUQsSUFBSSxRQUFRLEtBQUssU0FBUyxFQUFFO1lBQzFCLFFBQVEsR0FBRyxFQUFFLENBQUE7U0FDZDtRQUVELE9BQU8sQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsZUFBTSxDQUFDLFFBQVEsRUFBRSxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxLQUFLLFVBQVUsQ0FBQyxDQUFBO0lBQ3JHLENBQUM7SUFFRDs7T0FFRztJQUNJLGdCQUFnQixDQUNyQixFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUNtQztRQUczRSxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxVQUFVLEVBQUUsVUFBVSxDQUFDLENBQUMsQ0FBQTtRQUU5RSxJQUFJLFFBQVEsQ0FBQyxNQUFNLEVBQUU7WUFDbkIsT0FBTyxRQUFRLENBQUMsUUFBUSxDQUFDLE1BQU0sR0FBRyxDQUFDLENBQUMsQ0FBQTtTQUNyQzthQUFNLElBQUksY0FBYyxFQUFFO1lBQ3pCLGNBQWMsQ0FBQyxZQUFZLENBQUMsR0FBRyx5QkFBZSxDQUFDLElBQUksQ0FBQTtZQUNuRCxPQUFPLGNBQWMsQ0FBQTtTQUN0QjtRQUVELE1BQU0sWUFBWSxHQUFHO1lBQ25CLG9CQUFvQixFQUFFLFVBQVU7WUFDaEMsV0FBVyxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSTtZQUNsQyxVQUFVO1NBQ1gsQ0FBQTtRQUVELElBQUksVUFBVSxFQUFFO1lBQ2QsTUFBTSxJQUFJLHdCQUFXLENBQUMsV0FBVyxVQUFVLHNCQUFzQixVQUFVLFlBQVksRUFBRSxZQUFZLENBQUMsQ0FBQTtTQUN2RzthQUFNO1lBQ0wsTUFBTSxJQUFJLDJCQUFjLENBQ3RCLE9BQU8sVUFBVSx3Q0FBd0MsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLEtBQUs7Z0JBQ25GLDJDQUEyQyxFQUMzQyxZQUFZLENBQ2IsQ0FBQTtTQUNGO0lBQ0gsQ0FBQztJQUVEOztPQUVHO0lBQ0ksc0JBQXNCLENBQzNCLEVBQUUsVUFBVSxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsY0FBYyxFQUNxRDtRQUd6RyxNQUFNLFFBQVEsR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyx1QkFBdUIsQ0FBQyxFQUFFLFVBQVUsRUFBRSxVQUFVLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFBO1FBRXBHLElBQUksUUFBUSxDQUFDLE1BQU0sRUFBRTtZQUNuQixPQUFPLFFBQVEsQ0FBQyxRQUFRLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQyxDQUFBO1NBQ3JDO2FBQU0sSUFBSSxjQUFjLEVBQUU7WUFDekIsY0FBYyxDQUFDLFlBQVksQ0FBQyxHQUFHLHlCQUFlLENBQUMsSUFBSSxDQUFBO1lBQ25ELE9BQU8sY0FBYyxDQUFBO1NBQ3RCO1FBRUQsTUFBTSxZQUFZLEdBQUc7WUFDbkIsb0JBQW9CLEVBQUUsVUFBVTtZQUNoQyxtQkFBbUIsRUFBRSxVQUFVO1lBQy9CLFdBQVcsRUFBRSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUk7WUFDbEMsVUFBVTtTQUNYLENBQUE7UUFFRCxJQUFJLFVBQVUsRUFBRTtZQUNkLE1BQU0sSUFBSSx3QkFBVyxDQUNuQixXQUFXLFVBQVUsc0JBQXNCLFVBQVUsOEJBQThCLFVBQVUsSUFBSSxFQUNqRyxZQUFZLENBQ2IsQ0FBQTtTQUNGO2FBQU07WUFDTCxNQUFNLElBQUksMkJBQWMsQ0FDdEIsT0FBTyxVQUFVLHlDQUF5QyxVQUFVLG1CQUFtQjtnQkFDdkYsSUFBSSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksOENBQThDLEVBQ3ZFLFlBQVksQ0FDYixDQUFBO1NBQ0Y7SUFDSCxDQUFDO0NBR0Y7QUFoeEJELHdCQWd4QkMiLCJmaWxlIjoiZ2FyZGVuLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBCbHVlYmlyZCA9IHJlcXVpcmUoXCJibHVlYmlyZFwiKVxuaW1wb3J0IHtcbiAgcGFyc2UsXG4gIHJlbGF0aXZlLFxuICByZXNvbHZlLFxuICBzZXAsXG59IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7XG4gIGV4dGVuZCxcbiAgZmxhdHRlbixcbiAgaXNTdHJpbmcsXG4gIGZyb21QYWlycyxcbiAgbWVyZ2UsXG4gIGtleUJ5LFxuICBjbG9uZURlZXAsXG4gIHBpY2tCeSxcbiAgc29ydEJ5LFxuICB1bmlxQnksXG59IGZyb20gXCJsb2Rhc2hcIlxuY29uc3QgQXN5bmNMb2NrID0gcmVxdWlyZShcImFzeW5jLWxvY2tcIilcblxuaW1wb3J0IHsgVHJlZUNhY2hlIH0gZnJvbSBcIi4vY2FjaGVcIlxuaW1wb3J0IHtcbiAgYnVpbHRpblBsdWdpbnMsXG4gIGZpeGVkUGx1Z2lucyxcbn0gZnJvbSBcIi4vcGx1Z2lucy9wbHVnaW5zXCJcbmltcG9ydCB7IE1vZHVsZSwgbW9kdWxlRnJvbUNvbmZpZywgZ2V0TW9kdWxlQ2FjaGVDb250ZXh0LCBnZXRNb2R1bGVLZXksIE1vZHVsZUNvbmZpZ01hcCB9IGZyb20gXCIuL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQge1xuICBtb2R1bGVBY3Rpb25EZXNjcmlwdGlvbnMsXG4gIG1vZHVsZUFjdGlvbk5hbWVzLFxuICBwbHVnaW5BY3Rpb25EZXNjcmlwdGlvbnMsXG4gIHBsdWdpbk1vZHVsZVNjaGVtYSxcbiAgcGx1Z2luU2NoZW1hLFxufSBmcm9tIFwiLi90eXBlcy9wbHVnaW4vcGx1Z2luXCJcbmltcG9ydCB7IEVudmlyb25tZW50LCBTb3VyY2VDb25maWcsIGRlZmF1bHRQcm92aWRlciB9IGZyb20gXCIuL2NvbmZpZy9wcm9qZWN0XCJcbmltcG9ydCB7XG4gIGZpbmRCeU5hbWUsXG4gIGdldElnbm9yZXIsXG4gIGdldE5hbWVzLFxuICBzY2FuRGlyZWN0b3J5LFxuICBwaWNrS2V5cyxcbn0gZnJvbSBcIi4vdXRpbC91dGlsXCJcbmltcG9ydCB7XG4gIERFRkFVTFRfTkFNRVNQQUNFLFxuICBNT0RVTEVfQ09ORklHX0ZJTEVOQU1FLFxuICBFUlJPUl9MT0dfRklMRU5BTUUsXG59IGZyb20gXCIuL2NvbnN0YW50c1wiXG5pbXBvcnQge1xuICBDb25maWd1cmF0aW9uRXJyb3IsXG4gIFBhcmFtZXRlckVycm9yLFxuICBQbHVnaW5FcnJvcixcbn0gZnJvbSBcIi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBWY3NIYW5kbGVyLCBNb2R1bGVWZXJzaW9uIH0gZnJvbSBcIi4vdmNzL2Jhc2VcIlxuaW1wb3J0IHsgR2l0SGFuZGxlciB9IGZyb20gXCIuL3Zjcy9naXRcIlxuaW1wb3J0IHsgQnVpbGREaXIgfSBmcm9tIFwiLi9idWlsZC1kaXJcIlxuaW1wb3J0IHtcbiAgVGFza0dyYXBoLFxuICBUYXNrUmVzdWx0cyxcbn0gZnJvbSBcIi4vdGFzay1ncmFwaFwiXG5pbXBvcnQge1xuICBnZXRMb2dnZXIsXG4gIExvZ2dlcixcbn0gZnJvbSBcIi4vbG9nZ2VyL2xvZ2dlclwiXG5pbXBvcnQge1xuICBwbHVnaW5BY3Rpb25OYW1lcyxcbiAgUGx1Z2luQWN0aW9ucyxcbiAgUGx1Z2luRmFjdG9yeSxcbiAgR2FyZGVuUGx1Z2luLFxuICBNb2R1bGVBY3Rpb25zLFxufSBmcm9tIFwiLi90eXBlcy9wbHVnaW4vcGx1Z2luXCJcbmltcG9ydCB7IGpvaUlkZW50aWZpZXIsIHZhbGlkYXRlIH0gZnJvbSBcIi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBTZXJ2aWNlIH0gZnJvbSBcIi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyByZXNvbHZlVGVtcGxhdGVTdHJpbmdzIH0gZnJvbSBcIi4vdGVtcGxhdGUtc3RyaW5nXCJcbmltcG9ydCB7XG4gIGNvbmZpZ1NjaGVtYSxcbiAgR2FyZGVuQ29uZmlnLFxuICBsb2FkQ29uZmlnLFxuICBmaW5kUHJvamVjdENvbmZpZyxcbn0gZnJvbSBcIi4vY29uZmlnL2Jhc2VcIlxuaW1wb3J0IHsgVGFzayB9IGZyb20gXCIuL3Rhc2tzL2Jhc2VcIlxuaW1wb3J0IHsgTG9jYWxDb25maWdTdG9yZSB9IGZyb20gXCIuL2NvbmZpZy1zdG9yZVwiXG5pbXBvcnQgeyBkZXRlY3RDaXJjdWxhckRlcGVuZGVuY2llcyB9IGZyb20gXCIuL3V0aWwvZGV0ZWN0Q3ljbGVzXCJcbmltcG9ydCB7XG4gIGdldExpbmtlZFNvdXJjZXMsXG4gIEV4dGVybmFsU291cmNlVHlwZSxcbn0gZnJvbSBcIi4vdXRpbC9leHQtc291cmNlLXV0aWxcIlxuaW1wb3J0IHsgQnVpbGREZXBlbmRlbmN5Q29uZmlnLCBNb2R1bGVDb25maWcgfSBmcm9tIFwiLi9jb25maWcvbW9kdWxlXCJcbmltcG9ydCB7IFByb2plY3RDb25maWdDb250ZXh0LCBNb2R1bGVDb25maWdDb250ZXh0IH0gZnJvbSBcIi4vY29uZmlnL2NvbmZpZy1jb250ZXh0XCJcbmltcG9ydCB7IEZpbGVXcml0ZXIgfSBmcm9tIFwiLi9sb2dnZXIvd3JpdGVycy9maWxlLXdyaXRlclwiXG5pbXBvcnQgeyBMb2dMZXZlbCB9IGZyb20gXCIuL2xvZ2dlci9sb2ctbm9kZVwiXG5pbXBvcnQgeyBBY3Rpb25IZWxwZXIgfSBmcm9tIFwiLi9hY3Rpb25zXCJcbmltcG9ydCB7IGNyZWF0ZVBsdWdpbkNvbnRleHQgfSBmcm9tIFwiLi9wbHVnaW4tY29udGV4dFwiXG5pbXBvcnQgeyBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9ucywgUGx1Z2lucywgUmVnaXN0ZXJQbHVnaW5QYXJhbSB9IGZyb20gXCIuL3R5cGVzL3BsdWdpbi9wbHVnaW5cIlxuXG5leHBvcnQgaW50ZXJmYWNlIEFjdGlvbkhhbmRsZXJNYXA8VCBleHRlbmRzIGtleW9mIFBsdWdpbkFjdGlvbnM+IHtcbiAgW2FjdGlvbk5hbWU6IHN0cmluZ106IFBsdWdpbkFjdGlvbnNbVF1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBNb2R1bGVBY3Rpb25IYW5kbGVyTWFwPFQgZXh0ZW5kcyBrZXlvZiBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9ucz4ge1xuICBbYWN0aW9uTmFtZTogc3RyaW5nXTogTW9kdWxlQW5kU2VydmljZUFjdGlvbnNbVF1cbn1cblxuZXhwb3J0IHR5cGUgUGx1Z2luQWN0aW9uTWFwID0ge1xuICBbQSBpbiBrZXlvZiBQbHVnaW5BY3Rpb25zXToge1xuICAgIFtwbHVnaW5OYW1lOiBzdHJpbmddOiBQbHVnaW5BY3Rpb25zW0FdLFxuICB9XG59XG5cbmV4cG9ydCB0eXBlIE1vZHVsZUFjdGlvbk1hcCA9IHtcbiAgW0EgaW4ga2V5b2YgTW9kdWxlQW5kU2VydmljZUFjdGlvbnNdOiB7XG4gICAgW21vZHVsZVR5cGU6IHN0cmluZ106IHtcbiAgICAgIFtwbHVnaW5OYW1lOiBzdHJpbmddOiBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9uc1tBXSxcbiAgICB9LFxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGV4dE9wdHMge1xuICBjb25maWc/OiBHYXJkZW5Db25maWcsXG4gIGVudj86IHN0cmluZyxcbiAgbG9nZ2VyPzogTG9nZ2VyLFxuICBwbHVnaW5zPzogUGx1Z2lucyxcbn1cblxuY29uc3Qgc2NhbkxvY2sgPSBuZXcgQXN5bmNMb2NrKClcblxuY29uc3QgZmlsZVdyaXRlckNvbmZpZ3MgPSBbXG4gIHsgZmlsZW5hbWU6IFwiZGV2ZWxvcG1lbnQubG9nXCIgfSxcbiAgeyBmaWxlbmFtZTogRVJST1JfTE9HX0ZJTEVOQU1FLCBsZXZlbDogTG9nTGV2ZWwuZXJyb3IgfSxcbiAgeyBmaWxlbmFtZTogRVJST1JfTE9HX0ZJTEVOQU1FLCBsZXZlbDogTG9nTGV2ZWwuZXJyb3IsIHBhdGg6IFwiLlwiLCB0cnVuY2F0ZVByZXZpb3VzOiB0cnVlIH0sXG5dXG5cbmV4cG9ydCBjbGFzcyBHYXJkZW4ge1xuICBwdWJsaWMgcmVhZG9ubHkgbG9nOiBMb2dnZXJcbiAgcHVibGljIHJlYWRvbmx5IGFjdGlvbkhhbmRsZXJzOiBQbHVnaW5BY3Rpb25NYXBcbiAgcHVibGljIHJlYWRvbmx5IG1vZHVsZUFjdGlvbkhhbmRsZXJzOiBNb2R1bGVBY3Rpb25NYXBcblxuICBwcml2YXRlIHJlYWRvbmx5IGxvYWRlZFBsdWdpbnM6IHsgW2tleTogc3RyaW5nXTogR2FyZGVuUGx1Z2luIH1cbiAgcHJpdmF0ZSBtb2R1bGVDb25maWdzOiBNb2R1bGVDb25maWdNYXBcbiAgcHJpdmF0ZSBtb2R1bGVzU2Nhbm5lZDogYm9vbGVhblxuICBwcml2YXRlIHJlYWRvbmx5IHJlZ2lzdGVyZWRQbHVnaW5zOiB7IFtrZXk6IHN0cmluZ106IFBsdWdpbkZhY3RvcnkgfVxuICBwcml2YXRlIHJlYWRvbmx5IHNlcnZpY2VOYW1lSW5kZXg6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH1cbiAgcHJpdmF0ZSByZWFkb25seSB0YXNrR3JhcGg6IFRhc2tHcmFwaFxuXG4gIHB1YmxpYyByZWFkb25seSBsb2NhbENvbmZpZ1N0b3JlOiBMb2NhbENvbmZpZ1N0b3JlXG4gIHB1YmxpYyByZWFkb25seSB2Y3M6IFZjc0hhbmRsZXJcbiAgcHVibGljIHJlYWRvbmx5IGNhY2hlOiBUcmVlQ2FjaGVcbiAgcHVibGljIHJlYWRvbmx5IGFjdGlvbnM6IEFjdGlvbkhlbHBlclxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBwcm9qZWN0Um9vdDogc3RyaW5nLFxuICAgIHB1YmxpYyByZWFkb25seSBwcm9qZWN0TmFtZTogc3RyaW5nLFxuICAgIHB1YmxpYyByZWFkb25seSBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQsXG4gICAgcHVibGljIHJlYWRvbmx5IHByb2plY3RTb3VyY2VzOiBTb3VyY2VDb25maWdbXSA9IFtdLFxuICAgIHB1YmxpYyByZWFkb25seSBidWlsZERpcjogQnVpbGREaXIsXG4gICAgbG9nZ2VyPzogTG9nZ2VyLFxuICApIHtcbiAgICB0aGlzLm1vZHVsZXNTY2FubmVkID0gZmFsc2VcbiAgICB0aGlzLmxvZyA9IGxvZ2dlciB8fCBnZXRMb2dnZXIoKVxuICAgIC8vIFRPRE86IFN1cHBvcnQgb3RoZXIgVkNTIG9wdGlvbnMuXG4gICAgdGhpcy52Y3MgPSBuZXcgR2l0SGFuZGxlcih0aGlzLnByb2plY3RSb290KVxuICAgIHRoaXMubG9jYWxDb25maWdTdG9yZSA9IG5ldyBMb2NhbENvbmZpZ1N0b3JlKHRoaXMucHJvamVjdFJvb3QpXG4gICAgdGhpcy5jYWNoZSA9IG5ldyBUcmVlQ2FjaGUoKVxuXG4gICAgdGhpcy5tb2R1bGVDb25maWdzID0ge31cbiAgICB0aGlzLnNlcnZpY2VOYW1lSW5kZXggPSB7fVxuICAgIHRoaXMubG9hZGVkUGx1Z2lucyA9IHt9XG4gICAgdGhpcy5yZWdpc3RlcmVkUGx1Z2lucyA9IHt9XG4gICAgdGhpcy5hY3Rpb25IYW5kbGVycyA9IDxQbHVnaW5BY3Rpb25NYXA+ZnJvbVBhaXJzKHBsdWdpbkFjdGlvbk5hbWVzLm1hcChuID0+IFtuLCB7fV0pKVxuICAgIHRoaXMubW9kdWxlQWN0aW9uSGFuZGxlcnMgPSA8TW9kdWxlQWN0aW9uTWFwPmZyb21QYWlycyhtb2R1bGVBY3Rpb25OYW1lcy5tYXAobiA9PiBbbiwge31dKSlcblxuICAgIHRoaXMudGFza0dyYXBoID0gbmV3IFRhc2tHcmFwaCh0aGlzKVxuICAgIHRoaXMuYWN0aW9ucyA9IG5ldyBBY3Rpb25IZWxwZXIodGhpcylcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBmYWN0b3J5KGN1cnJlbnREaXJlY3Rvcnk6IHN0cmluZywgeyBlbnYsIGNvbmZpZywgbG9nZ2VyLCBwbHVnaW5zID0ge30gfTogQ29udGV4dE9wdHMgPSB7fSkge1xuICAgIGxldCBwYXJzZWRDb25maWc6IEdhcmRlbkNvbmZpZ1xuXG4gICAgaWYgKGNvbmZpZykge1xuICAgICAgcGFyc2VkQ29uZmlnID0gPEdhcmRlbkNvbmZpZz52YWxpZGF0ZShjb25maWcsIGNvbmZpZ1NjaGVtYSwgeyBjb250ZXh0OiBcInJvb3QgY29uZmlndXJhdGlvblwiIH0pXG5cbiAgICAgIGlmICghcGFyc2VkQ29uZmlnLnByb2plY3QpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihgU3VwcGxpZWQgY29uZmlnIGRvZXMgbm90IGNvbnRhaW4gYSBwcm9qZWN0IGNvbmZpZ3VyYXRpb25gLCB7XG4gICAgICAgICAgY3VycmVudERpcmVjdG9yeSxcbiAgICAgICAgICBjb25maWcsXG4gICAgICAgIH0pXG4gICAgICB9XG4gICAgfSBlbHNlIHtcbiAgICAgIGNvbmZpZyA9IGF3YWl0IGZpbmRQcm9qZWN0Q29uZmlnKGN1cnJlbnREaXJlY3RvcnkpXG5cbiAgICAgIGlmICghY29uZmlnIHx8ICFjb25maWcucHJvamVjdCkge1xuICAgICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgICAgIGBOb3QgYSBwcm9qZWN0IGRpcmVjdG9yeSAob3IgYW55IG9mIHRoZSBwYXJlbnQgZGlyZWN0b3JpZXMpOiAke2N1cnJlbnREaXJlY3Rvcnl9YCxcbiAgICAgICAgICB7IGN1cnJlbnREaXJlY3RvcnkgfSxcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICBwYXJzZWRDb25maWcgPSBhd2FpdCByZXNvbHZlVGVtcGxhdGVTdHJpbmdzKGNvbmZpZyEsIG5ldyBQcm9qZWN0Q29uZmlnQ29udGV4dCgpKVxuICAgIH1cblxuICAgIGNvbnN0IHByb2plY3RSb290ID0gcGFyc2VkQ29uZmlnLnBhdGhcblxuICAgIGNvbnN0IHtcbiAgICAgIGRlZmF1bHRFbnZpcm9ubWVudCxcbiAgICAgIGVudmlyb25tZW50cyxcbiAgICAgIG5hbWU6IHByb2plY3ROYW1lLFxuICAgICAgZW52aXJvbm1lbnREZWZhdWx0cyxcbiAgICAgIHNvdXJjZXM6IHByb2plY3RTb3VyY2VzLFxuICAgIH0gPSBwYXJzZWRDb25maWcucHJvamVjdCFcblxuICAgIGlmICghZW52KSB7XG4gICAgICBlbnYgPSBkZWZhdWx0RW52aXJvbm1lbnRcbiAgICB9XG5cbiAgICBjb25zdCBwYXJ0cyA9IGVudi5zcGxpdChcIi5cIilcbiAgICBjb25zdCBlbnZpcm9ubWVudE5hbWUgPSBwYXJ0c1swXVxuICAgIGNvbnN0IG5hbWVzcGFjZSA9IHBhcnRzLnNsaWNlKDEpLmpvaW4oXCIuXCIpIHx8IERFRkFVTFRfTkFNRVNQQUNFXG5cbiAgICBjb25zdCBlbnZpcm9ubWVudENvbmZpZyA9IGZpbmRCeU5hbWUoZW52aXJvbm1lbnRzLCBlbnZpcm9ubWVudE5hbWUpXG5cbiAgICBpZiAoIWVudmlyb25tZW50Q29uZmlnKSB7XG4gICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IoYFByb2plY3QgJHtwcm9qZWN0TmFtZX0gZG9lcyBub3Qgc3BlY2lmeSBlbnZpcm9ubWVudCAke2Vudmlyb25tZW50TmFtZX1gLCB7XG4gICAgICAgIHByb2plY3ROYW1lLFxuICAgICAgICBlbnYsXG4gICAgICAgIGRlZmluZWRFbnZpcm9ubWVudHM6IGdldE5hbWVzKGVudmlyb25tZW50cyksXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmICghZW52aXJvbm1lbnRDb25maWcucHJvdmlkZXJzIHx8IGVudmlyb25tZW50Q29uZmlnLnByb3ZpZGVycy5sZW5ndGggPT09IDApIHtcbiAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoYEVudmlyb25tZW50ICcke2Vudmlyb25tZW50TmFtZX0nIGRvZXMgbm90IHNwZWNpZnkgYW55IHByb3ZpZGVyc2AsIHtcbiAgICAgICAgcHJvamVjdE5hbWUsXG4gICAgICAgIGVudixcbiAgICAgICAgZW52aXJvbm1lbnRDb25maWcsXG4gICAgICB9KVxuICAgIH1cblxuICAgIGlmIChuYW1lc3BhY2Uuc3RhcnRzV2l0aChcImdhcmRlbi1cIikpIHtcbiAgICAgIHRocm93IG5ldyBQYXJhbWV0ZXJFcnJvcihgTmFtZXNwYWNlIGNhbm5vdCBzdGFydCB3aXRoIFwiZ2FyZGVuLVwiYCwge1xuICAgICAgICBlbnZpcm9ubWVudENvbmZpZyxcbiAgICAgICAgbmFtZXNwYWNlLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBjb25zdCBmaXhlZFByb3ZpZGVycyA9IGZpeGVkUGx1Z2lucy5tYXAobmFtZSA9PiAoeyBuYW1lIH0pKVxuXG4gICAgY29uc3QgbWVyZ2VkUHJvdmlkZXJzID0gbWVyZ2UoXG4gICAgICBmaXhlZFByb3ZpZGVycyxcbiAgICAgIGtleUJ5KGVudmlyb25tZW50RGVmYXVsdHMucHJvdmlkZXJzLCBcIm5hbWVcIiksXG4gICAgICBrZXlCeShlbnZpcm9ubWVudENvbmZpZy5wcm92aWRlcnMsIFwibmFtZVwiKSxcbiAgICApXG5cbiAgICAvLyBSZXNvbHZlIHRoZSBwcm9qZWN0IGNvbmZpZ3VyYXRpb24gYmFzZWQgb24gc2VsZWN0ZWQgZW52aXJvbm1lbnRcbiAgICBjb25zdCBlbnZpcm9ubWVudDogRW52aXJvbm1lbnQgPSB7XG4gICAgICBuYW1lOiBlbnZpcm9ubWVudENvbmZpZy5uYW1lLFxuICAgICAgcHJvdmlkZXJzOiBPYmplY3QudmFsdWVzKG1lcmdlZFByb3ZpZGVycyksXG4gICAgICB2YXJpYWJsZXM6IG1lcmdlKHt9LCBlbnZpcm9ubWVudERlZmF1bHRzLnZhcmlhYmxlcywgZW52aXJvbm1lbnRDb25maWcudmFyaWFibGVzKSxcbiAgICB9XG5cbiAgICBjb25zdCBidWlsZERpciA9IGF3YWl0IEJ1aWxkRGlyLmZhY3RvcnkocHJvamVjdFJvb3QpXG5cbiAgICAvLyBSZWdpc3RlciBsb2cgd3JpdGVyc1xuICAgIGlmIChsb2dnZXIpIHtcbiAgICAgIGZvciAoY29uc3Qgd3JpdGVyQ29uZmlnIG9mIGZpbGVXcml0ZXJDb25maWdzKSB7XG4gICAgICAgIGxvZ2dlci53cml0ZXJzLnB1c2goXG4gICAgICAgICAgYXdhaXQgRmlsZVdyaXRlci5mYWN0b3J5KHtcbiAgICAgICAgICAgIGxldmVsOiBsb2dnZXIubGV2ZWwsXG4gICAgICAgICAgICByb290OiBwcm9qZWN0Um9vdCxcbiAgICAgICAgICAgIC4uLndyaXRlckNvbmZpZyxcbiAgICAgICAgICB9KSxcbiAgICAgICAgKVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbnN0IGdhcmRlbiA9IG5ldyBHYXJkZW4oXG4gICAgICBwcm9qZWN0Um9vdCxcbiAgICAgIHByb2plY3ROYW1lLFxuICAgICAgZW52aXJvbm1lbnQsXG4gICAgICBwcm9qZWN0U291cmNlcyxcbiAgICAgIGJ1aWxkRGlyLFxuICAgICAgbG9nZ2VyLFxuICAgIClcblxuICAgIC8vIFJlZ2lzdGVyIHBsdWdpbnNcbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBwbHVnaW5GYWN0b3J5XSBvZiBPYmplY3QuZW50cmllcyh7IC4uLmJ1aWx0aW5QbHVnaW5zLCAuLi5wbHVnaW5zIH0pKSB7XG4gICAgICBnYXJkZW4ucmVnaXN0ZXJQbHVnaW4obmFtZSwgcGx1Z2luRmFjdG9yeSlcbiAgICB9XG5cbiAgICAvLyBMb2FkIGNvbmZpZ3VyZWQgcGx1Z2luc1xuICAgIC8vIFZhbGlkYXRlIGNvbmZpZ3VyYXRpb25cbiAgICBmb3IgKGNvbnN0IHByb3ZpZGVyIG9mIGVudmlyb25tZW50LnByb3ZpZGVycykge1xuICAgICAgYXdhaXQgZ2FyZGVuLmxvYWRQbHVnaW4ocHJvdmlkZXIubmFtZSwgcHJvdmlkZXIpXG4gICAgfVxuXG4gICAgcmV0dXJuIGdhcmRlblxuICB9XG5cbiAgZ2V0UGx1Z2luQ29udGV4dChwcm92aWRlck5hbWU6IHN0cmluZykge1xuICAgIHJldHVybiBjcmVhdGVQbHVnaW5Db250ZXh0KHRoaXMsIHByb3ZpZGVyTmFtZSlcbiAgfVxuXG4gIGFzeW5jIGNsZWFyQnVpbGRzKCkge1xuICAgIHJldHVybiB0aGlzLmJ1aWxkRGlyLmNsZWFyKClcbiAgfVxuXG4gIGFzeW5jIGFkZFRhc2sodGFzazogVGFzaykge1xuICAgIGF3YWl0IHRoaXMudGFza0dyYXBoLmFkZFRhc2sodGFzaylcbiAgfVxuXG4gIGFzeW5jIHByb2Nlc3NUYXNrcygpOiBQcm9taXNlPFRhc2tSZXN1bHRzPiB7XG4gICAgcmV0dXJuIHRoaXMudGFza0dyYXBoLnByb2Nlc3NUYXNrcygpXG4gIH1cblxuICBwcml2YXRlIHJlZ2lzdGVyUGx1Z2luKG5hbWU6IHN0cmluZywgbW9kdWxlT3JGYWN0b3J5OiBSZWdpc3RlclBsdWdpblBhcmFtKSB7XG4gICAgbGV0IGZhY3Rvcnk6IFBsdWdpbkZhY3RvcnlcblxuICAgIGlmICh0eXBlb2YgbW9kdWxlT3JGYWN0b3J5ID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgIGZhY3RvcnkgPSBtb2R1bGVPckZhY3RvcnlcblxuICAgIH0gZWxzZSBpZiAoaXNTdHJpbmcobW9kdWxlT3JGYWN0b3J5KSkge1xuICAgICAgbGV0IG1vZHVsZU5hbWVPckxvY2F0aW9uID0gbW9kdWxlT3JGYWN0b3J5XG4gICAgICBjb25zdCBwYXJzZWRMb2NhdGlvbiA9IHBhcnNlKG1vZHVsZU5hbWVPckxvY2F0aW9uKVxuXG4gICAgICAvLyBhbGxvdyByZWxhdGl2ZSByZWZlcmVuY2VzIHRvIHByb2plY3Qgcm9vdFxuICAgICAgaWYgKHBhcnNlKG1vZHVsZU5hbWVPckxvY2F0aW9uKS5kaXIgIT09IFwiXCIpIHtcbiAgICAgICAgY29uc29sZS5sb2codGhpcy5wcm9qZWN0Um9vdClcbiAgICAgICAgY29uc29sZS5sb2cobW9kdWxlTmFtZU9yTG9jYXRpb24pXG4gICAgICAgIG1vZHVsZU5hbWVPckxvY2F0aW9uID0gcmVzb2x2ZSh0aGlzLnByb2plY3RSb290LCBtb2R1bGVOYW1lT3JMb2NhdGlvbilcbiAgICAgIH1cblxuICAgICAgbGV0IHBsdWdpbk1vZHVsZVxuXG4gICAgICB0cnkge1xuICAgICAgICBwbHVnaW5Nb2R1bGUgPSByZXF1aXJlKG1vZHVsZU5hbWVPckxvY2F0aW9uKVxuICAgICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgICBgVW5hYmxlIHRvIGxvYWQgcGx1Z2luIFwiJHttb2R1bGVOYW1lT3JMb2NhdGlvbn1cIiAoY291bGQgbm90IGxvYWQgbW9kdWxlOiAke2Vycm9yLm1lc3NhZ2V9KWAsIHtcbiAgICAgICAgICAgIG1lc3NhZ2U6IGVycm9yLm1lc3NhZ2UsXG4gICAgICAgICAgICBtb2R1bGVOYW1lT3JMb2NhdGlvbixcbiAgICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICB0cnkge1xuICAgICAgICBwbHVnaW5Nb2R1bGUgPSB2YWxpZGF0ZShcbiAgICAgICAgICBwbHVnaW5Nb2R1bGUsXG4gICAgICAgICAgcGx1Z2luTW9kdWxlU2NoZW1hLFxuICAgICAgICAgIHsgY29udGV4dDogYHBsdWdpbiBtb2R1bGUgXCIke21vZHVsZU5hbWVPckxvY2F0aW9ufVwiYCB9LFxuICAgICAgICApXG5cbiAgICAgICAgaWYgKHBsdWdpbk1vZHVsZS5uYW1lKSB7XG4gICAgICAgICAgbmFtZSA9IHBsdWdpbk1vZHVsZS5uYW1lXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgaWYgKHBhcnNlZExvY2F0aW9uLm5hbWUgPT09IFwiaW5kZXhcIikge1xuICAgICAgICAgICAgLy8gdXNlIHBhcmVudCBkaXJlY3RvcnkgbmFtZVxuICAgICAgICAgICAgbmFtZSA9IHBhcnNlZExvY2F0aW9uLmRpci5zcGxpdChzZXApLnNsaWNlKC0xKVswXVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICBuYW1lID0gcGFyc2VkTG9jYXRpb24ubmFtZVxuICAgICAgICAgIH1cbiAgICAgICAgfVxuXG4gICAgICAgIHZhbGlkYXRlKG5hbWUsIGpvaUlkZW50aWZpZXIoKSwgeyBjb250ZXh0OiBgbmFtZSBvZiBwbHVnaW4gXCIke21vZHVsZU5hbWVPckxvY2F0aW9ufVwiYCB9KVxuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIHRocm93IG5ldyBQbHVnaW5FcnJvcihgVW5hYmxlIHRvIGxvYWQgcGx1Z2luOiAke2Vycn1gLCB7XG4gICAgICAgICAgbW9kdWxlTmFtZU9yTG9jYXRpb24sXG4gICAgICAgICAgZXJyLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICBmYWN0b3J5ID0gcGx1Z2luTW9kdWxlLmdhcmRlblBsdWdpblxuXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBUeXBlRXJyb3IoYEV4cGVjdGVkIHBsdWdpbiBmYWN0b3J5IGZ1bmN0aW9uLCBtb2R1bGUgbmFtZSBvciBtb2R1bGUgcGF0aGApXG4gICAgfVxuXG4gICAgdGhpcy5yZWdpc3RlcmVkUGx1Z2luc1tuYW1lXSA9IGZhY3RvcnlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbG9hZFBsdWdpbihwbHVnaW5OYW1lOiBzdHJpbmcsIGNvbmZpZzogb2JqZWN0KSB7XG4gICAgY29uc3QgZmFjdG9yeSA9IHRoaXMucmVnaXN0ZXJlZFBsdWdpbnNbcGx1Z2luTmFtZV1cblxuICAgIGlmICghZmFjdG9yeSkge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihgQ29uZmlndXJlZCBwbHVnaW4gJyR7cGx1Z2luTmFtZX0nIGhhcyBub3QgYmVlbiByZWdpc3RlcmVkYCwge1xuICAgICAgICBuYW1lOiBwbHVnaW5OYW1lLFxuICAgICAgICBhdmFpbGFibGVQbHVnaW5zOiBPYmplY3Qua2V5cyh0aGlzLnJlZ2lzdGVyZWRQbHVnaW5zKSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgbGV0IHBsdWdpblxuXG4gICAgdHJ5IHtcbiAgICAgIHBsdWdpbiA9IGF3YWl0IGZhY3Rvcnkoe1xuICAgICAgICBwcm9qZWN0TmFtZTogdGhpcy5wcm9qZWN0TmFtZSxcbiAgICAgICAgY29uZmlnLFxuICAgICAgICBsb2dFbnRyeTogdGhpcy5sb2csXG4gICAgICB9KVxuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYFVuZXhwZWN0ZWQgZXJyb3Igd2hlbiBsb2FkaW5nIHBsdWdpbiBcIiR7cGx1Z2luTmFtZX1cIjogJHtlcnJvcn1gLCB7XG4gICAgICAgIHBsdWdpbk5hbWUsXG4gICAgICAgIGVycm9yLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICBwbHVnaW4gPSB2YWxpZGF0ZShwbHVnaW4sIHBsdWdpblNjaGVtYSwgeyBjb250ZXh0OiBgcGx1Z2luIFwiJHtwbHVnaW5OYW1lfVwiYCB9KVxuXG4gICAgdGhpcy5sb2FkZWRQbHVnaW5zW3BsdWdpbk5hbWVdID0gcGx1Z2luXG5cbiAgICAvLyBhbGxvdyBwbHVnaW5zIHRvIGV4dGVuZCB0aGVpciBvd24gY29uZmlnICh0aGF0IGdldHMgcGFzc2VkIHRvIGFjdGlvbiBoYW5kbGVycylcbiAgICBjb25zdCBwcm92aWRlckNvbmZpZyA9IGZpbmRCeU5hbWUodGhpcy5lbnZpcm9ubWVudC5wcm92aWRlcnMsIHBsdWdpbk5hbWUpXG4gICAgaWYgKHByb3ZpZGVyQ29uZmlnKSB7XG4gICAgICBleHRlbmQocHJvdmlkZXJDb25maWcsIHBsdWdpbi5jb25maWcsIGNvbmZpZylcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5lbnZpcm9ubWVudC5wcm92aWRlcnMucHVzaChleHRlbmQoeyBuYW1lOiBwbHVnaW5OYW1lIH0sIHBsdWdpbi5jb25maWcsIGNvbmZpZykpXG4gICAgfVxuXG4gICAgZm9yIChjb25zdCBtb2R1bGVQYXRoIG9mIHBsdWdpbi5tb2R1bGVzIHx8IFtdKSB7XG4gICAgICBsZXQgbW9kdWxlQ29uZmlnID0gYXdhaXQgdGhpcy5yZXNvbHZlTW9kdWxlKG1vZHVsZVBhdGgpXG4gICAgICBpZiAoIW1vZHVsZUNvbmZpZykge1xuICAgICAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYENvdWxkIG5vdCBsb2FkIG1vZHVsZSBcIiR7bW9kdWxlUGF0aH1cIiBzcGVjaWZpZWQgaW4gcGx1Z2luIFwiJHtwbHVnaW5OYW1lfVwiYCwge1xuICAgICAgICAgIHBsdWdpbk5hbWUsXG4gICAgICAgICAgbW9kdWxlUGF0aCxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICAgIG1vZHVsZUNvbmZpZy5wbHVnaW4gPSBwbHVnaW5OYW1lXG4gICAgICBhd2FpdCB0aGlzLmFkZE1vZHVsZShtb2R1bGVDb25maWcpXG4gICAgfVxuXG4gICAgY29uc3QgYWN0aW9ucyA9IHBsdWdpbi5hY3Rpb25zIHx8IHt9XG5cbiAgICBmb3IgKGNvbnN0IGFjdGlvblR5cGUgb2YgcGx1Z2luQWN0aW9uTmFtZXMpIHtcbiAgICAgIGNvbnN0IGhhbmRsZXIgPSBhY3Rpb25zW2FjdGlvblR5cGVdXG4gICAgICBoYW5kbGVyICYmIHRoaXMuYWRkQWN0aW9uSGFuZGxlcihwbHVnaW5OYW1lLCBhY3Rpb25UeXBlLCBoYW5kbGVyKVxuICAgIH1cblxuICAgIGNvbnN0IG1vZHVsZUFjdGlvbnMgPSBwbHVnaW4ubW9kdWxlQWN0aW9ucyB8fCB7fVxuXG4gICAgZm9yIChjb25zdCBtb2R1bGVUeXBlIG9mIE9iamVjdC5rZXlzKG1vZHVsZUFjdGlvbnMpKSB7XG4gICAgICBmb3IgKGNvbnN0IGFjdGlvblR5cGUgb2YgbW9kdWxlQWN0aW9uTmFtZXMpIHtcbiAgICAgICAgY29uc3QgaGFuZGxlciA9IG1vZHVsZUFjdGlvbnNbbW9kdWxlVHlwZV1bYWN0aW9uVHlwZV1cbiAgICAgICAgaGFuZGxlciAmJiB0aGlzLmFkZE1vZHVsZUFjdGlvbkhhbmRsZXIocGx1Z2luTmFtZSwgYWN0aW9uVHlwZSwgbW9kdWxlVHlwZSwgaGFuZGxlcilcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGdldFBsdWdpbihwbHVnaW5OYW1lOiBzdHJpbmcpIHtcbiAgICBjb25zdCBwbHVnaW4gPSB0aGlzLmxvYWRlZFBsdWdpbnNbcGx1Z2luTmFtZV1cblxuICAgIGlmICghcGx1Z2luKSB7XG4gICAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYENvdWxkIG5vdCBmaW5kIHBsdWdpbiAke3BsdWdpbk5hbWV9LiBBcmUgeW91IG1pc3NpbmcgYSBwcm92aWRlciBjb25maWd1cmF0aW9uP2AsIHtcbiAgICAgICAgcGx1Z2luTmFtZSxcbiAgICAgICAgYXZhaWxhYmxlUGx1Z2luczogT2JqZWN0LmtleXModGhpcy5sb2FkZWRQbHVnaW5zKSxcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIHBsdWdpblxuICB9XG5cbiAgcHJpdmF0ZSBhZGRBY3Rpb25IYW5kbGVyPFQgZXh0ZW5kcyBrZXlvZiBQbHVnaW5BY3Rpb25zPihcbiAgICBwbHVnaW5OYW1lOiBzdHJpbmcsIGFjdGlvblR5cGU6IFQsIGhhbmRsZXI6IFBsdWdpbkFjdGlvbnNbVF0sXG4gICkge1xuICAgIGNvbnN0IHBsdWdpbiA9IHRoaXMuZ2V0UGx1Z2luKHBsdWdpbk5hbWUpXG4gICAgY29uc3Qgc2NoZW1hID0gcGx1Z2luQWN0aW9uRGVzY3JpcHRpb25zW2FjdGlvblR5cGVdLnJlc3VsdFNjaGVtYVxuXG4gICAgY29uc3Qgd3JhcHBlZCA9IGFzeW5jICguLi5hcmdzKSA9PiB7XG4gICAgICBjb25zdCByZXN1bHQgPSBhd2FpdCBoYW5kbGVyLmFwcGx5KHBsdWdpbiwgYXJncylcbiAgICAgIHJldHVybiB2YWxpZGF0ZShyZXN1bHQsIHNjaGVtYSwgeyBjb250ZXh0OiBgJHthY3Rpb25UeXBlfSBvdXRwdXQgZnJvbSBwbHVnaW4gJHtwbHVnaW5OYW1lfWAgfSlcbiAgICB9XG4gICAgd3JhcHBlZFtcImFjdGlvblR5cGVcIl0gPSBhY3Rpb25UeXBlXG4gICAgd3JhcHBlZFtcInBsdWdpbk5hbWVcIl0gPSBwbHVnaW5OYW1lXG5cbiAgICB0aGlzLmFjdGlvbkhhbmRsZXJzW2FjdGlvblR5cGVdW3BsdWdpbk5hbWVdID0gd3JhcHBlZFxuICB9XG5cbiAgcHJpdmF0ZSBhZGRNb2R1bGVBY3Rpb25IYW5kbGVyPFQgZXh0ZW5kcyBrZXlvZiBNb2R1bGVBY3Rpb25zPihcbiAgICBwbHVnaW5OYW1lOiBzdHJpbmcsIGFjdGlvblR5cGU6IFQsIG1vZHVsZVR5cGU6IHN0cmluZywgaGFuZGxlcjogTW9kdWxlQWN0aW9uc1tUXSxcbiAgKSB7XG4gICAgY29uc3QgcGx1Z2luID0gdGhpcy5nZXRQbHVnaW4ocGx1Z2luTmFtZSlcbiAgICBjb25zdCBzY2hlbWEgPSBtb2R1bGVBY3Rpb25EZXNjcmlwdGlvbnNbYWN0aW9uVHlwZV0ucmVzdWx0U2NoZW1hXG5cbiAgICBjb25zdCB3cmFwcGVkID0gYXN5bmMgKC4uLmFyZ3MpID0+IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGhhbmRsZXIuYXBwbHkocGx1Z2luLCBhcmdzKVxuICAgICAgcmV0dXJuIHZhbGlkYXRlKHJlc3VsdCwgc2NoZW1hLCB7IGNvbnRleHQ6IGAke2FjdGlvblR5cGV9IG91dHB1dCBmcm9tIHBsdWdpbiAke3BsdWdpbk5hbWV9YCB9KVxuICAgIH1cbiAgICB3cmFwcGVkW1wiYWN0aW9uVHlwZVwiXSA9IGFjdGlvblR5cGVcbiAgICB3cmFwcGVkW1wicGx1Z2luTmFtZVwiXSA9IHBsdWdpbk5hbWVcbiAgICB3cmFwcGVkW1wibW9kdWxlVHlwZVwiXSA9IG1vZHVsZVR5cGVcblxuICAgIGlmICghdGhpcy5tb2R1bGVBY3Rpb25IYW5kbGVyc1thY3Rpb25UeXBlXSkge1xuICAgICAgdGhpcy5tb2R1bGVBY3Rpb25IYW5kbGVyc1thY3Rpb25UeXBlXSA9IHt9XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLm1vZHVsZUFjdGlvbkhhbmRsZXJzW2FjdGlvblR5cGVdW21vZHVsZVR5cGVdKSB7XG4gICAgICB0aGlzLm1vZHVsZUFjdGlvbkhhbmRsZXJzW2FjdGlvblR5cGVdW21vZHVsZVR5cGVdID0ge31cbiAgICB9XG5cbiAgICB0aGlzLm1vZHVsZUFjdGlvbkhhbmRsZXJzW2FjdGlvblR5cGVdW21vZHVsZVR5cGVdW3BsdWdpbk5hbWVdID0gd3JhcHBlZFxuICB9XG5cbiAgLypcbiAgICBSZXR1cm5zIGFsbCBtb2R1bGVzIHRoYXQgYXJlIHJlZ2lzdGVyZWQgaW4gdGhpcyBjb250ZXh0LlxuICAgIFNjYW5zIGZvciBtb2R1bGVzIGluIHRoZSBwcm9qZWN0IHJvb3QgaWYgaXQgaGFzbid0IGFscmVhZHkgYmVlbiBkb25lLlxuICAgKi9cbiAgYXN5bmMgZ2V0TW9kdWxlcyhuYW1lcz86IHN0cmluZ1tdLCBub1NjYW4/OiBib29sZWFuKTogUHJvbWlzZTxNb2R1bGVbXT4ge1xuICAgIGlmICghdGhpcy5tb2R1bGVzU2Nhbm5lZCAmJiAhbm9TY2FuKSB7XG4gICAgICBhd2FpdCB0aGlzLnNjYW5Nb2R1bGVzKClcbiAgICB9XG5cbiAgICBsZXQgY29uZmlnczogTW9kdWxlQ29uZmlnW11cblxuICAgIGlmICghIW5hbWVzKSB7XG4gICAgICBjb25maWdzID0gW11cbiAgICAgIGNvbnN0IG1pc3Npbmc6IHN0cmluZ1tdID0gW11cblxuICAgICAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgICAgIGNvbnN0IG1vZHVsZSA9IHRoaXMubW9kdWxlQ29uZmlnc1tuYW1lXVxuXG4gICAgICAgIGlmICghbW9kdWxlKSB7XG4gICAgICAgICAgbWlzc2luZy5wdXNoKG5hbWUpXG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgY29uZmlncy5wdXNoKG1vZHVsZSlcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICBpZiAobWlzc2luZy5sZW5ndGgpIHtcbiAgICAgICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBDb3VsZCBub3QgZmluZCBtb2R1bGUocyk6ICR7bWlzc2luZy5qb2luKFwiLCBcIil9YCwge1xuICAgICAgICAgIG1pc3NpbmcsXG4gICAgICAgICAgYXZhaWxhYmxlOiBPYmplY3Qua2V5cyh0aGlzLm1vZHVsZUNvbmZpZ3MpLFxuICAgICAgICB9KVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICBjb25maWdzID0gT2JqZWN0LnZhbHVlcyh0aGlzLm1vZHVsZUNvbmZpZ3MpXG4gICAgfVxuXG4gICAgcmV0dXJuIEJsdWViaXJkLm1hcChjb25maWdzLCBjb25maWcgPT4gbW9kdWxlRnJvbUNvbmZpZyh0aGlzLCBjb25maWcpKVxuICB9XG5cbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIG1vZHVsZSB3aXRoIHRoZSBzcGVjaWZpZWQgbmFtZS4gVGhyb3dzIGVycm9yIGlmIGl0IGRvZXNuJ3QgZXhpc3QuXG4gICAqL1xuICBhc3luYyBnZXRNb2R1bGUobmFtZTogc3RyaW5nLCBub1NjYW4/OiBib29sZWFuKTogUHJvbWlzZTxNb2R1bGU+IHtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuZ2V0TW9kdWxlcyhbbmFtZV0sIG5vU2NhbikpWzBdXG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gdGhlIHByb3ZpZGVkIGxpc3RzIG9mIGJ1aWxkIGFuZCBzZXJ2aWNlIGRlcGVuZGVuY2llcywgcmV0dXJuIGEgbGlzdCBvZiBhbGwgbW9kdWxlc1xuICAgKiByZXF1aXJlZCB0byBzYXRpc2Z5IHRob3NlIGRlcGVuZGVuY2llcy5cbiAgICovXG4gIGFzeW5jIHJlc29sdmVNb2R1bGVEZXBlbmRlbmNpZXMoYnVpbGREZXBlbmRlbmNpZXM6IEJ1aWxkRGVwZW5kZW5jeUNvbmZpZ1tdLCBzZXJ2aWNlRGVwZW5kZW5jaWVzOiBzdHJpbmdbXSkge1xuICAgIGNvbnN0IGJ1aWxkRGVwcyA9IGF3YWl0IEJsdWViaXJkLm1hcChidWlsZERlcGVuZGVuY2llcywgYXN5bmMgKGRlcCkgPT4ge1xuICAgICAgY29uc3QgbW9kdWxlS2V5ID0gZ2V0TW9kdWxlS2V5KGRlcC5uYW1lLCBkZXAucGx1Z2luKVxuICAgICAgY29uc3QgbW9kdWxlID0gYXdhaXQgdGhpcy5nZXRNb2R1bGUobW9kdWxlS2V5KVxuICAgICAgcmV0dXJuIFttb2R1bGVdLmNvbmNhdChhd2FpdCB0aGlzLnJlc29sdmVNb2R1bGVEZXBlbmRlbmNpZXMobW9kdWxlLmJ1aWxkLmRlcGVuZGVuY2llcywgW10pKVxuICAgIH0pXG5cbiAgICBjb25zdCBydW50aW1lRGVwcyA9IGF3YWl0IEJsdWViaXJkLm1hcChzZXJ2aWNlRGVwZW5kZW5jaWVzLCBhc3luYyAoc2VydmljZU5hbWUpID0+IHtcbiAgICAgIGNvbnN0IHNlcnZpY2UgPSBhd2FpdCB0aGlzLmdldFNlcnZpY2Uoc2VydmljZU5hbWUpXG4gICAgICByZXR1cm4gdGhpcy5yZXNvbHZlTW9kdWxlRGVwZW5kZW5jaWVzKFxuICAgICAgICBbeyBuYW1lOiBzZXJ2aWNlLm1vZHVsZS5uYW1lLCBjb3B5OiBbXSB9XSxcbiAgICAgICAgc2VydmljZS5jb25maWcuZGVwZW5kZW5jaWVzIHx8IFtdLFxuICAgICAgKVxuICAgIH0pXG5cbiAgICBjb25zdCBkZXBzID0gZmxhdHRlbihidWlsZERlcHMpLmNvbmNhdChmbGF0dGVuKHJ1bnRpbWVEZXBzKSlcblxuICAgIHJldHVybiBzb3J0QnkodW5pcUJ5KGRlcHMsIFwibmFtZVwiKSwgXCJuYW1lXCIpXG4gIH1cblxuICAvKipcbiAgICogR2l2ZW4gYSBtb2R1bGUsIGFuZCBhIGxpc3Qgb2YgZGVwZW5kZW5jaWVzLCByZXNvbHZlIHRoZSB2ZXJzaW9uIGZvciB0aGF0IGNvbWJpbmF0aW9uIG9mIG1vZHVsZXMuXG4gICAqIFRoZSBjb21iaW5lZCB2ZXJzaW9uIGlzIGEgZWl0aGVyIHRoZSBsYXRlc3QgZGlydHkgbW9kdWxlIHZlcnNpb24gKGlmIGFueSksIG9yIHRoZSBoYXNoIG9mIHRoZSBtb2R1bGUgdmVyc2lvblxuICAgKiBhbmQgdGhlIHZlcnNpb25zIG9mIGl0cyBkZXBlbmRlbmNpZXMgKGluIHNvcnRlZCBvcmRlcikuXG4gICAqL1xuICBhc3luYyByZXNvbHZlVmVyc2lvbihtb2R1bGVOYW1lOiBzdHJpbmcsIG1vZHVsZURlcGVuZGVuY2llczogQnVpbGREZXBlbmRlbmN5Q29uZmlnW10sIGZvcmNlID0gZmFsc2UpIHtcbiAgICBjb25zdCBjb25maWcgPSB0aGlzLm1vZHVsZUNvbmZpZ3NbbW9kdWxlTmFtZV1cbiAgICBjb25zdCBjYWNoZUtleSA9IFtcIm1vZHVsZVZlcnNpb25zXCIsIG1vZHVsZU5hbWVdXG5cbiAgICBpZiAoIWZvcmNlKSB7XG4gICAgICBjb25zdCBjYWNoZWQgPSA8TW9kdWxlVmVyc2lvbj50aGlzLmNhY2hlLmdldChjYWNoZUtleSlcblxuICAgICAgaWYgKGNhY2hlZCkge1xuICAgICAgICByZXR1cm4gY2FjaGVkXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgZGVwZW5kZW5jeUtleXMgPSBtb2R1bGVEZXBlbmRlbmNpZXMubWFwKGRlcCA9PiBnZXRNb2R1bGVLZXkoZGVwLm5hbWUsIGRlcC5wbHVnaW4pKVxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IE9iamVjdC52YWx1ZXMocGlja0tleXModGhpcy5tb2R1bGVDb25maWdzLCBkZXBlbmRlbmN5S2V5cywgXCJtb2R1bGUgY29uZmlnXCIpKVxuICAgIGNvbnN0IGNhY2hlQ29udGV4dHMgPSBkZXBlbmRlbmNpZXMuY29uY2F0KFtjb25maWddKS5tYXAoYyA9PiBnZXRNb2R1bGVDYWNoZUNvbnRleHQoYykpXG5cbiAgICBjb25zdCB2ZXJzaW9uID0gYXdhaXQgdGhpcy52Y3MucmVzb2x2ZVZlcnNpb24oY29uZmlnLCBkZXBlbmRlbmNpZXMpXG5cbiAgICB0aGlzLmNhY2hlLnNldChjYWNoZUtleSwgdmVyc2lvbiwgLi4uY2FjaGVDb250ZXh0cylcbiAgICByZXR1cm4gdmVyc2lvblxuICB9XG5cbiAgLypcbiAgICBSZXR1cm5zIGFsbCBzZXJ2aWNlcyB0aGF0IGFyZSByZWdpc3RlcmVkIGluIHRoaXMgY29udGV4dCwgb3IgdGhlIG9uZXMgc3BlY2lmaWVkLlxuICAgIFNjYW5zIGZvciBtb2R1bGVzIGFuZCBzZXJ2aWNlcyBpbiB0aGUgcHJvamVjdCByb290IGlmIGl0IGhhc24ndCBhbHJlYWR5IGJlZW4gZG9uZS5cbiAgICovXG4gIGFzeW5jIGdldFNlcnZpY2VzKG5hbWVzPzogc3RyaW5nW10sIG5vU2Nhbj86IGJvb2xlYW4pOiBQcm9taXNlPFNlcnZpY2VbXT4ge1xuICAgIGlmICghdGhpcy5tb2R1bGVzU2Nhbm5lZCAmJiAhbm9TY2FuKSB7XG4gICAgICBhd2FpdCB0aGlzLnNjYW5Nb2R1bGVzKClcbiAgICB9XG5cbiAgICBjb25zdCBwaWNrZWQgPSBuYW1lcyA/IHBpY2tLZXlzKHRoaXMuc2VydmljZU5hbWVJbmRleCwgbmFtZXMsIFwic2VydmljZVwiKSA6IHRoaXMuc2VydmljZU5hbWVJbmRleFxuXG4gICAgcmV0dXJuIEJsdWViaXJkLm1hcChPYmplY3QuZW50cmllcyhwaWNrZWQpLCBhc3luYyAoW3NlcnZpY2VOYW1lLCBtb2R1bGVOYW1lXSkgPT4ge1xuICAgICAgY29uc3QgbW9kdWxlID0gYXdhaXQgdGhpcy5nZXRNb2R1bGUobW9kdWxlTmFtZSlcbiAgICAgIGNvbnN0IGNvbmZpZyA9IGZpbmRCeU5hbWUobW9kdWxlLnNlcnZpY2VDb25maWdzLCBzZXJ2aWNlTmFtZSkhXG5cbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWU6IHNlcnZpY2VOYW1lLFxuICAgICAgICBjb25maWcsXG4gICAgICAgIG1vZHVsZSxcbiAgICAgICAgc3BlYzogY29uZmlnLnNwZWMsXG4gICAgICB9XG4gICAgfSlcbiAgfVxuXG4gIC8qKlxuICAgKiBSZXR1cm5zIHRoZSBzZXJ2aWNlIHdpdGggdGhlIHNwZWNpZmllZCBuYW1lLiBUaHJvd3MgZXJyb3IgaWYgaXQgZG9lc24ndCBleGlzdC5cbiAgICovXG4gIGFzeW5jIGdldFNlcnZpY2UobmFtZTogc3RyaW5nLCBub1NjYW4/OiBib29sZWFuKTogUHJvbWlzZTxTZXJ2aWNlPE1vZHVsZT4+IHtcbiAgICByZXR1cm4gKGF3YWl0IHRoaXMuZ2V0U2VydmljZXMoW25hbWVdLCBub1NjYW4pKVswXVxuICB9XG5cbiAgLypcbiAgICBTY2FucyB0aGUgcHJvamVjdCByb290IGZvciBtb2R1bGVzIGFuZCBhZGRzIHRoZW0gdG8gdGhlIGNvbnRleHQuXG4gICAqL1xuICBhc3luYyBzY2FuTW9kdWxlcyhmb3JjZSA9IGZhbHNlKSB7XG4gICAgcmV0dXJuIHNjYW5Mb2NrLmFjcXVpcmUoXCJzY2FuLW1vZHVsZXNcIiwgYXN5bmMgKCkgPT4ge1xuICAgICAgaWYgKHRoaXMubW9kdWxlc1NjYW5uZWQgJiYgIWZvcmNlKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuXG4gICAgICBsZXQgZXh0U291cmNlUGF0aHM6IHN0cmluZ1tdID0gW11cblxuICAgICAgLy8gQWRkIGV4dGVybmFsIHNvdXJjZXMgdGhhdCBhcmUgZGVmaW5lZCBhdCB0aGUgcHJvamVjdCBsZXZlbC4gRXh0ZXJuYWwgc291cmNlcyBhcmUgZWl0aGVyIGtlcHQgaW5cbiAgICAgIC8vIHRoZSAuZ2FyZGVuL3NvdXJjZXMgZGlyIChhbmQgY2xvbmVkIHRoZXJlIGlmIG5lZWRlZCksIG9yIHRoZXkncmUgbGlua2VkIHRvIGEgbG9jYWwgcGF0aCB2aWEgdGhlIGxpbmsgY29tbWFuZC5cbiAgICAgIGZvciAoY29uc3QgeyBuYW1lLCByZXBvc2l0b3J5VXJsIH0gb2YgdGhpcy5wcm9qZWN0U291cmNlcykge1xuICAgICAgICBjb25zdCBwYXRoID0gYXdhaXQgdGhpcy5sb2FkRXh0U291cmNlUGF0aCh7IG5hbWUsIHJlcG9zaXRvcnlVcmwsIHNvdXJjZVR5cGU6IFwicHJvamVjdFwiIH0pXG4gICAgICAgIGV4dFNvdXJjZVBhdGhzLnB1c2gocGF0aClcbiAgICAgIH1cblxuICAgICAgY29uc3QgZGlyc1RvU2NhbiA9IFt0aGlzLnByb2plY3RSb290LCAuLi5leHRTb3VyY2VQYXRoc11cblxuICAgICAgY29uc3QgbW9kdWxlUGF0aHMgPSBmbGF0dGVuKGF3YWl0IEJsdWViaXJkLm1hcChkaXJzVG9TY2FuLCBhc3luYyBkaXIgPT4ge1xuICAgICAgICBjb25zdCBpZ25vcmVyID0gYXdhaXQgZ2V0SWdub3JlcihkaXIpXG4gICAgICAgIGNvbnN0IHNjYW5PcHRzID0ge1xuICAgICAgICAgIGZpbHRlcjogKHBhdGgpID0+IHtcbiAgICAgICAgICAgIGNvbnN0IHJlbFBhdGggPSByZWxhdGl2ZSh0aGlzLnByb2plY3RSb290LCBwYXRoKVxuICAgICAgICAgICAgcmV0dXJuICFpZ25vcmVyLmlnbm9yZXMocmVsUGF0aClcbiAgICAgICAgICB9LFxuICAgICAgICB9XG4gICAgICAgIGNvbnN0IHBhdGhzOiBzdHJpbmdbXSA9IFtdXG5cbiAgICAgICAgZm9yIGF3YWl0IChjb25zdCBpdGVtIG9mIHNjYW5EaXJlY3RvcnkoZGlyLCBzY2FuT3B0cykpIHtcbiAgICAgICAgICBpZiAoIWl0ZW0pIHtcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgY29uc3QgcGFyc2VkUGF0aCA9IHBhcnNlKGl0ZW0ucGF0aClcblxuICAgICAgICAgIGlmIChwYXJzZWRQYXRoLmJhc2UgIT09IE1PRFVMRV9DT05GSUdfRklMRU5BTUUpIHtcbiAgICAgICAgICAgIGNvbnRpbnVlXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgcGF0aHMucHVzaChwYXJzZWRQYXRoLmRpcilcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBwYXRoc1xuICAgICAgfSkpLmZpbHRlcihCb29sZWFuKVxuXG4gICAgICBhd2FpdCBCbHVlYmlyZC5tYXAobW9kdWxlUGF0aHMsIGFzeW5jIHBhdGggPT4ge1xuICAgICAgICBjb25zdCBjb25maWcgPSBhd2FpdCB0aGlzLnJlc29sdmVNb2R1bGUocGF0aClcbiAgICAgICAgY29uZmlnICYmIGF3YWl0IHRoaXMuYWRkTW9kdWxlKGNvbmZpZylcbiAgICAgIH0pXG5cbiAgICAgIHRoaXMubW9kdWxlc1NjYW5uZWQgPSB0cnVlXG5cbiAgICAgIGF3YWl0IHRoaXMuZGV0ZWN0Q2lyY3VsYXJEZXBlbmRlbmNpZXMoKVxuXG4gICAgICBjb25zdCBtb2R1bGVDb25maWdDb250ZXh0ID0gbmV3IE1vZHVsZUNvbmZpZ0NvbnRleHQoXG4gICAgICAgIHRoaXMsIHRoaXMuZW52aXJvbm1lbnQsIE9iamVjdC52YWx1ZXModGhpcy5tb2R1bGVDb25maWdzKSxcbiAgICAgIClcbiAgICAgIHRoaXMubW9kdWxlQ29uZmlncyA9IGF3YWl0IHJlc29sdmVUZW1wbGF0ZVN0cmluZ3ModGhpcy5tb2R1bGVDb25maWdzLCBtb2R1bGVDb25maWdDb250ZXh0KVxuICAgIH0pXG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGRldGVjdENpcmN1bGFyRGVwZW5kZW5jaWVzKCkge1xuICAgIGNvbnN0IG1vZHVsZXMgPSBhd2FpdCB0aGlzLmdldE1vZHVsZXMoKVxuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgdGhpcy5nZXRTZXJ2aWNlcygpXG5cbiAgICByZXR1cm4gZGV0ZWN0Q2lyY3VsYXJEZXBlbmRlbmNpZXMobW9kdWxlcywgc2VydmljZXMpXG4gIH1cblxuICAvKlxuICAgIEFkZHMgdGhlIHNwZWNpZmllZCBtb2R1bGUgdG8gdGhlIGNvbnRleHRcblxuICAgIEBwYXJhbSBmb3JjZSAtIGFkZCB0aGUgbW9kdWxlIGFnYWluLCBldmVuIGlmIGl0J3MgYWxyZWFkeSByZWdpc3RlcmVkXG4gICAqL1xuICBhc3luYyBhZGRNb2R1bGUoY29uZmlnOiBNb2R1bGVDb25maWcsIGZvcmNlID0gZmFsc2UpIHtcbiAgICBjb25zdCB2YWxpZGF0ZUhhbmRsZXIgPSBhd2FpdCB0aGlzLmdldE1vZHVsZUFjdGlvbkhhbmRsZXIoeyBhY3Rpb25UeXBlOiBcInZhbGlkYXRlXCIsIG1vZHVsZVR5cGU6IGNvbmZpZy50eXBlIH0pXG4gICAgY29uc3QgY3R4ID0gdGhpcy5nZXRQbHVnaW5Db250ZXh0KHZhbGlkYXRlSGFuZGxlcltcInBsdWdpbk5hbWVcIl0pXG5cbiAgICBjb25maWcgPSBhd2FpdCB2YWxpZGF0ZUhhbmRsZXIoeyBjdHgsIG1vZHVsZUNvbmZpZzogY29uZmlnIH0pXG5cbiAgICAvLyBGSVhNRTogdGhpcyBpcyByYXRoZXIgY2x1bXN5XG4gICAgY29uZmlnLm5hbWUgPSBnZXRNb2R1bGVLZXkoY29uZmlnLm5hbWUsIGNvbmZpZy5wbHVnaW4pXG5cbiAgICBpZiAoIWZvcmNlICYmIHRoaXMubW9kdWxlQ29uZmlnc1tjb25maWcubmFtZV0pIHtcbiAgICAgIGNvbnN0IHBhdGhBID0gcmVsYXRpdmUodGhpcy5wcm9qZWN0Um9vdCwgdGhpcy5tb2R1bGVDb25maWdzW2NvbmZpZy5uYW1lXS5wYXRoKVxuICAgICAgY29uc3QgcGF0aEIgPSByZWxhdGl2ZSh0aGlzLnByb2plY3RSb290LCBjb25maWcucGF0aClcblxuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgYE1vZHVsZSAke2NvbmZpZy5uYW1lfSBpcyBkZWNsYXJlZCBtdWx0aXBsZSB0aW1lcyAoJyR7cGF0aEF9JyBhbmQgJyR7cGF0aEJ9JylgLFxuICAgICAgICB7IHBhdGhBLCBwYXRoQiB9LFxuICAgICAgKVxuICAgIH1cblxuICAgIHRoaXMubW9kdWxlQ29uZmlnc1tjb25maWcubmFtZV0gPSBjb25maWdcblxuICAgIC8vIEFkZCB0byBzZXJ2aWNlLW1vZHVsZSBtYXBcbiAgICBmb3IgKGNvbnN0IHNlcnZpY2VDb25maWcgb2YgY29uZmlnLnNlcnZpY2VDb25maWdzKSB7XG4gICAgICBjb25zdCBzZXJ2aWNlTmFtZSA9IHNlcnZpY2VDb25maWcubmFtZVxuXG4gICAgICBpZiAoIWZvcmNlICYmIHRoaXMuc2VydmljZU5hbWVJbmRleFtzZXJ2aWNlTmFtZV0pIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgICBgU2VydmljZSBuYW1lcyBtdXN0IGJlIHVuaXF1ZSAtICR7c2VydmljZU5hbWV9IGlzIGRlY2xhcmVkIG11bHRpcGxlIHRpbWVzIGAgK1xuICAgICAgICAgIGAoaW4gJyR7dGhpcy5zZXJ2aWNlTmFtZUluZGV4W3NlcnZpY2VOYW1lXX0nIGFuZCAnJHtjb25maWcubmFtZX0nKWAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgc2VydmljZU5hbWUsXG4gICAgICAgICAgICBtb2R1bGVBOiB0aGlzLnNlcnZpY2VOYW1lSW5kZXhbc2VydmljZU5hbWVdLFxuICAgICAgICAgICAgbW9kdWxlQjogY29uZmlnLm5hbWUsXG4gICAgICAgICAgfSxcbiAgICAgICAgKVxuICAgICAgfVxuXG4gICAgICB0aGlzLnNlcnZpY2VOYW1lSW5kZXhbc2VydmljZU5hbWVdID0gY29uZmlnLm5hbWVcbiAgICB9XG5cbiAgICBpZiAodGhpcy5tb2R1bGVzU2Nhbm5lZCkge1xuICAgICAgLy8gbmVlZCB0byByZS1ydW4gdGhpcyBpZiBhZGRpbmcgbW9kdWxlcyBhZnRlciBpbml0aWFsIHNjYW5cbiAgICAgIGF3YWl0IHRoaXMuZGV0ZWN0Q2lyY3VsYXJEZXBlbmRlbmNpZXMoKVxuICAgIH1cbiAgfVxuXG4gIC8qXG4gICAgTWFwcyB0aGUgcHJvdmlkZWQgbmFtZSBvciBsb2NhdG9yIHRvIGEgTW9kdWxlLiBXZSBmaXJzdCBsb29rIGZvciBhIG1vZHVsZSBpbiB0aGVcbiAgICBwcm9qZWN0IHdpdGggdGhlIHByb3ZpZGVkIG5hbWUuIElmIGl0IGRvZXMgbm90IGV4aXN0LCB3ZSB0cmVhdCBpdCBhcyBhIHBhdGhcbiAgICAocmVzb2x2ZWQgd2l0aCB0aGUgcHJvamVjdCBwYXRoIGFzIGEgYmFzZSBwYXRoKSBhbmQgYXR0ZW1wdCB0byBsb2FkIHRoZSBtb2R1bGVcbiAgICBmcm9tIHRoZXJlLlxuICAgKi9cbiAgYXN5bmMgcmVzb2x2ZU1vZHVsZShuYW1lT3JMb2NhdGlvbjogc3RyaW5nKTogUHJvbWlzZTxNb2R1bGVDb25maWcgfCBudWxsPiB7XG4gICAgY29uc3QgcGFyc2VkUGF0aCA9IHBhcnNlKG5hbWVPckxvY2F0aW9uKVxuXG4gICAgaWYgKHBhcnNlZFBhdGguZGlyID09PSBcIlwiKSB7XG4gICAgICAvLyBMb29rcyBsaWtlIGEgbmFtZVxuICAgICAgY29uc3QgZXhpc3RpbmdNb2R1bGUgPSB0aGlzLm1vZHVsZUNvbmZpZ3NbbmFtZU9yTG9jYXRpb25dXG5cbiAgICAgIGlmICghZXhpc3RpbmdNb2R1bGUpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihgTW9kdWxlICR7bmFtZU9yTG9jYXRpb259IGNvdWxkIG5vdCBiZSBmb3VuZGAsIHtcbiAgICAgICAgICBuYW1lOiBuYW1lT3JMb2NhdGlvbixcbiAgICAgICAgfSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGV4aXN0aW5nTW9kdWxlXG4gICAgfVxuXG4gICAgLy8gTG9va3MgbGlrZSBhIHBhdGhcbiAgICBjb25zdCBwYXRoID0gcmVzb2x2ZSh0aGlzLnByb2plY3RSb290LCBuYW1lT3JMb2NhdGlvbilcbiAgICBjb25zdCBjb25maWcgPSBhd2FpdCBsb2FkQ29uZmlnKHRoaXMucHJvamVjdFJvb3QsIHBhdGgpXG5cbiAgICBpZiAoIWNvbmZpZyB8fCAhY29uZmlnLm1vZHVsZSkge1xuICAgICAgcmV0dXJuIG51bGxcbiAgICB9XG5cbiAgICBjb25zdCBtb2R1bGVDb25maWcgPSBjbG9uZURlZXAoY29uZmlnLm1vZHVsZSlcblxuICAgIGlmIChtb2R1bGVDb25maWcucmVwb3NpdG9yeVVybCkge1xuICAgICAgbW9kdWxlQ29uZmlnLnBhdGggPSBhd2FpdCB0aGlzLmxvYWRFeHRTb3VyY2VQYXRoKHtcbiAgICAgICAgbmFtZTogbW9kdWxlQ29uZmlnLm5hbWUsXG4gICAgICAgIHJlcG9zaXRvcnlVcmw6IG1vZHVsZUNvbmZpZy5yZXBvc2l0b3J5VXJsLFxuICAgICAgICBzb3VyY2VUeXBlOiBcIm1vZHVsZVwiLFxuICAgICAgfSlcbiAgICB9XG5cbiAgICByZXR1cm4gbW9kdWxlQ29uZmlnXG4gIH1cblxuICAvLz09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PVxuICAvL3JlZ2lvbiBJbnRlcm5hbCBoZWxwZXJzXG4gIC8vPT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09PT09XG5cbiAgLyoqXG4gICAqIENsb25lcyB0aGUgcHJvamVjdC9tb2R1bGUgc291cmNlIGlmIG5lZWRlZCBhbmQgcmV0dXJucyB0aGUgcGF0aCAoZWl0aGVyIGZyb20gLmdhcmRlbi9zb3VyY2VzIG9yIGZyb20gYSBsb2NhbCBwYXRoKVxuICAgKi9cbiAgcHVibGljIGFzeW5jIGxvYWRFeHRTb3VyY2VQYXRoKHsgbmFtZSwgcmVwb3NpdG9yeVVybCwgc291cmNlVHlwZSB9OiB7XG4gICAgbmFtZTogc3RyaW5nLFxuICAgIHJlcG9zaXRvcnlVcmw6IHN0cmluZyxcbiAgICBzb3VyY2VUeXBlOiBFeHRlcm5hbFNvdXJjZVR5cGUsXG4gIH0pOiBQcm9taXNlPHN0cmluZz4ge1xuXG4gICAgY29uc3QgbGlua2VkU291cmNlcyA9IGF3YWl0IGdldExpbmtlZFNvdXJjZXModGhpcywgc291cmNlVHlwZSlcblxuICAgIGNvbnN0IGxpbmtlZCA9IGZpbmRCeU5hbWUobGlua2VkU291cmNlcywgbmFtZSlcblxuICAgIGlmIChsaW5rZWQpIHtcbiAgICAgIHJldHVybiBsaW5rZWQucGF0aFxuICAgIH1cblxuICAgIGNvbnN0IHBhdGggPSBhd2FpdCB0aGlzLnZjcy5lbnN1cmVSZW1vdGVTb3VyY2UoeyBuYW1lLCBzb3VyY2VUeXBlLCB1cmw6IHJlcG9zaXRvcnlVcmwsIGxvZ0VudHJ5OiB0aGlzLmxvZyB9KVxuXG4gICAgcmV0dXJuIHBhdGhcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgYSBoYW5kbGVyIGZvciB0aGUgc3BlY2lmaWVkIGFjdGlvbi5cbiAgICovXG4gIHB1YmxpYyBnZXRBY3Rpb25IYW5kbGVyczxUIGV4dGVuZHMga2V5b2YgUGx1Z2luQWN0aW9ucz4oYWN0aW9uVHlwZTogVCwgcGx1Z2luTmFtZT86IHN0cmluZyk6IEFjdGlvbkhhbmRsZXJNYXA8VD4ge1xuICAgIHJldHVybiB0aGlzLmZpbHRlckFjdGlvbkhhbmRsZXJzKHRoaXMuYWN0aW9uSGFuZGxlcnNbYWN0aW9uVHlwZV0sIHBsdWdpbk5hbWUpXG4gIH1cblxuICAvKipcbiAgICogR2V0IGEgaGFuZGxlciBmb3IgdGhlIHNwZWNpZmllZCBtb2R1bGUgYWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGdldE1vZHVsZUFjdGlvbkhhbmRsZXJzPFQgZXh0ZW5kcyBrZXlvZiBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9ucz4oXG4gICAgeyBhY3Rpb25UeXBlLCBtb2R1bGVUeXBlLCBwbHVnaW5OYW1lIH06XG4gICAgICB7IGFjdGlvblR5cGU6IFQsIG1vZHVsZVR5cGU6IHN0cmluZywgcGx1Z2luTmFtZT86IHN0cmluZyB9LFxuICApOiBNb2R1bGVBY3Rpb25IYW5kbGVyTWFwPFQ+IHtcbiAgICByZXR1cm4gdGhpcy5maWx0ZXJBY3Rpb25IYW5kbGVycygodGhpcy5tb2R1bGVBY3Rpb25IYW5kbGVyc1thY3Rpb25UeXBlXSB8fCB7fSlbbW9kdWxlVHlwZV0sIHBsdWdpbk5hbWUpXG4gIH1cblxuICBwcml2YXRlIGZpbHRlckFjdGlvbkhhbmRsZXJzKGhhbmRsZXJzLCBwbHVnaW5OYW1lPzogc3RyaW5nKSB7XG4gICAgLy8gbWFrZSBzdXJlIHBsdWdpbiBpcyBsb2FkZWRcbiAgICBpZiAoISFwbHVnaW5OYW1lKSB7XG4gICAgICB0aGlzLmdldFBsdWdpbihwbHVnaW5OYW1lKVxuICAgIH1cblxuICAgIGlmIChoYW5kbGVycyA9PT0gdW5kZWZpbmVkKSB7XG4gICAgICBoYW5kbGVycyA9IHt9XG4gICAgfVxuXG4gICAgcmV0dXJuICFwbHVnaW5OYW1lID8gaGFuZGxlcnMgOiBwaWNrQnkoaGFuZGxlcnMsIChoYW5kbGVyKSA9PiBoYW5kbGVyW1wicGx1Z2luTmFtZVwiXSA9PT0gcGx1Z2luTmFtZSlcbiAgfVxuXG4gIC8qKlxuICAgKiBHZXQgdGhlIGxhc3QgY29uZmlndXJlZCBoYW5kbGVyIGZvciB0aGUgc3BlY2lmaWVkIGFjdGlvbiAoYW5kIG9wdGlvbmFsbHkgbW9kdWxlIHR5cGUpLlxuICAgKi9cbiAgcHVibGljIGdldEFjdGlvbkhhbmRsZXI8VCBleHRlbmRzIGtleW9mIFBsdWdpbkFjdGlvbnM+KFxuICAgIHsgYWN0aW9uVHlwZSwgcGx1Z2luTmFtZSwgZGVmYXVsdEhhbmRsZXIgfTpcbiAgICAgIHsgYWN0aW9uVHlwZTogVCwgcGx1Z2luTmFtZT86IHN0cmluZywgZGVmYXVsdEhhbmRsZXI/OiBQbHVnaW5BY3Rpb25zW1RdIH0sXG4gICk6IFBsdWdpbkFjdGlvbnNbVF0ge1xuXG4gICAgY29uc3QgaGFuZGxlcnMgPSBPYmplY3QudmFsdWVzKHRoaXMuZ2V0QWN0aW9uSGFuZGxlcnMoYWN0aW9uVHlwZSwgcGx1Z2luTmFtZSkpXG5cbiAgICBpZiAoaGFuZGxlcnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gaGFuZGxlcnNbaGFuZGxlcnMubGVuZ3RoIC0gMV1cbiAgICB9IGVsc2UgaWYgKGRlZmF1bHRIYW5kbGVyKSB7XG4gICAgICBkZWZhdWx0SGFuZGxlcltcInBsdWdpbk5hbWVcIl0gPSBkZWZhdWx0UHJvdmlkZXIubmFtZVxuICAgICAgcmV0dXJuIGRlZmF1bHRIYW5kbGVyXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JEZXRhaWxzID0ge1xuICAgICAgcmVxdWVzdGVkSGFuZGxlclR5cGU6IGFjdGlvblR5cGUsXG4gICAgICBlbnZpcm9ubWVudDogdGhpcy5lbnZpcm9ubWVudC5uYW1lLFxuICAgICAgcGx1Z2luTmFtZSxcbiAgICB9XG5cbiAgICBpZiAocGx1Z2luTmFtZSkge1xuICAgICAgdGhyb3cgbmV3IFBsdWdpbkVycm9yKGBQbHVnaW4gJyR7cGx1Z2luTmFtZX0nIGRvZXMgbm90IGhhdmUgYSAnJHthY3Rpb25UeXBlfScgaGFuZGxlci5gLCBlcnJvckRldGFpbHMpXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IG5ldyBQYXJhbWV0ZXJFcnJvcihcbiAgICAgICAgYE5vICcke2FjdGlvblR5cGV9JyBoYW5kbGVyIGNvbmZpZ3VyZWQgaW4gZW52aXJvbm1lbnQgJyR7dGhpcy5lbnZpcm9ubWVudC5uYW1lfScuIGAgK1xuICAgICAgICBgQXJlIHlvdSBtaXNzaW5nIGEgcHJvdmlkZXIgY29uZmlndXJhdGlvbj9gLFxuICAgICAgICBlcnJvckRldGFpbHMsXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEdldCB0aGUgbGFzdCBjb25maWd1cmVkIGhhbmRsZXIgZm9yIHRoZSBzcGVjaWZpZWQgYWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGdldE1vZHVsZUFjdGlvbkhhbmRsZXI8VCBleHRlbmRzIGtleW9mIE1vZHVsZUFuZFNlcnZpY2VBY3Rpb25zPihcbiAgICB7IGFjdGlvblR5cGUsIG1vZHVsZVR5cGUsIHBsdWdpbk5hbWUsIGRlZmF1bHRIYW5kbGVyIH06XG4gICAgICB7IGFjdGlvblR5cGU6IFQsIG1vZHVsZVR5cGU6IHN0cmluZywgcGx1Z2luTmFtZT86IHN0cmluZywgZGVmYXVsdEhhbmRsZXI/OiBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9uc1tUXSB9LFxuICApOiBNb2R1bGVBbmRTZXJ2aWNlQWN0aW9uc1tUXSB7XG5cbiAgICBjb25zdCBoYW5kbGVycyA9IE9iamVjdC52YWx1ZXModGhpcy5nZXRNb2R1bGVBY3Rpb25IYW5kbGVycyh7IGFjdGlvblR5cGUsIG1vZHVsZVR5cGUsIHBsdWdpbk5hbWUgfSkpXG5cbiAgICBpZiAoaGFuZGxlcnMubGVuZ3RoKSB7XG4gICAgICByZXR1cm4gaGFuZGxlcnNbaGFuZGxlcnMubGVuZ3RoIC0gMV1cbiAgICB9IGVsc2UgaWYgKGRlZmF1bHRIYW5kbGVyKSB7XG4gICAgICBkZWZhdWx0SGFuZGxlcltcInBsdWdpbk5hbWVcIl0gPSBkZWZhdWx0UHJvdmlkZXIubmFtZVxuICAgICAgcmV0dXJuIGRlZmF1bHRIYW5kbGVyXG4gICAgfVxuXG4gICAgY29uc3QgZXJyb3JEZXRhaWxzID0ge1xuICAgICAgcmVxdWVzdGVkSGFuZGxlclR5cGU6IGFjdGlvblR5cGUsXG4gICAgICByZXF1ZXN0ZWRNb2R1bGVUeXBlOiBtb2R1bGVUeXBlLFxuICAgICAgZW52aXJvbm1lbnQ6IHRoaXMuZW52aXJvbm1lbnQubmFtZSxcbiAgICAgIHBsdWdpbk5hbWUsXG4gICAgfVxuXG4gICAgaWYgKHBsdWdpbk5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBQbHVnaW5FcnJvcihcbiAgICAgICAgYFBsdWdpbiAnJHtwbHVnaW5OYW1lfScgZG9lcyBub3QgaGF2ZSBhICcke2FjdGlvblR5cGV9JyBoYW5kbGVyIGZvciBtb2R1bGUgdHlwZSAnJHttb2R1bGVUeXBlfScuYCxcbiAgICAgICAgZXJyb3JEZXRhaWxzLFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IoXG4gICAgICAgIGBObyAnJHthY3Rpb25UeXBlfScgaGFuZGxlciBjb25maWd1cmVkIGZvciBtb2R1bGUgdHlwZSAnJHttb2R1bGVUeXBlfScgaW4gZW52aXJvbm1lbnQgYCArXG4gICAgICAgIGAnJHt0aGlzLmVudmlyb25tZW50Lm5hbWV9Jy4gQXJlIHlvdSBtaXNzaW5nIGEgcHJvdmlkZXIgY29uZmlndXJhdGlvbj9gLFxuICAgICAgICBlcnJvckRldGFpbHMsXG4gICAgICApXG4gICAgfVxuICB9XG5cbiAgLy9lbmRyZWdpb25cbn1cbiJdfQ== diff --git a/garden-service/build/index.d.ts b/garden-service/build/index.d.ts new file mode 100644 index 00000000000..ad95451ac4d --- /dev/null +++ b/garden-service/build/index.d.ts @@ -0,0 +1,2 @@ +declare const cli: any; +//# sourceMappingURL=index.d.ts.map \ No newline at end of file diff --git a/garden-service/build/index.js b/garden-service/build/index.js new file mode 100644 index 00000000000..20db0a94200 --- /dev/null +++ b/garden-service/build/index.js @@ -0,0 +1,11 @@ +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +const cli = require("./cli/cli"); +cli.run(); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImluZGV4LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7R0FNRztBQUVILE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxXQUFXLENBQUMsQ0FBQTtBQUVoQyxHQUFHLENBQUMsR0FBRyxFQUFFLENBQUEiLCJmaWxlIjoiaW5kZXguanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuY29uc3QgY2xpID0gcmVxdWlyZShcIi4vY2xpL2NsaVwiKVxuXG5jbGkucnVuKClcbiJdfQ== diff --git a/garden-service/build/logger/log-entry.d.ts b/garden-service/build/logger/log-entry.d.ts new file mode 100644 index 00000000000..8cf3cb274fa --- /dev/null +++ b/garden-service/build/logger/log-entry.d.ts @@ -0,0 +1,47 @@ +import * as logSymbols from "log-symbols"; +import * as nodeEmoji from "node-emoji"; +import { LogNode, LogLevel } from "./log-node"; +import { GardenError } from "../exceptions"; +import { Omit } from "../util/util"; +export declare type EmojiName = keyof typeof nodeEmoji.emoji; +export declare type LogSymbol = keyof typeof logSymbols | "empty"; +export declare type EntryStatus = "active" | "done" | "error" | "success" | "warn"; +export interface UpdateOpts { + msg?: string | string[]; + section?: string; + emoji?: EmojiName; + symbol?: LogSymbol; + append?: boolean; + fromStdStream?: boolean; + showDuration?: boolean; + error?: GardenError; + status?: EntryStatus; + indentationLevel?: number; +} +export interface CreateOpts extends UpdateOpts { + id?: string; +} +export declare type CreateParam = string | CreateOpts; +export interface LogEntryConstructor { + level: LogLevel; + opts: CreateOpts; + parent: LogNode; +} +export declare function resolveParam(param?: string | T): T; +export declare class LogEntry extends LogNode { + opts: UpdateOpts; + constructor({ level, opts, parent }: LogEntryConstructor); + private setOwnState; + private deepSetState; + createNode(level: LogLevel, parent: LogNode, param?: CreateParam): LogEntry; + setState(param?: string | UpdateOpts): LogEntry; + setDone(param?: string | Omit): LogEntry; + setSuccess(param?: string | Omit): LogEntry; + setError(param?: string | Omit): LogEntry; + setWarn(param?: string | Omit): LogEntry; + fromStdStream(): boolean; + stop(): this; + inspect(): void; + filterBySection(section: string): LogEntry[]; +} +//# sourceMappingURL=log-entry.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/log-entry.js b/garden-service/build/logger/log-entry.js new file mode 100644 index 00000000000..663019cd26a --- /dev/null +++ b/garden-service/build/logger/log-entry.js @@ -0,0 +1,125 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __rest = (this && this.__rest) || function (s, e) { + var t = {}; + for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p) && e.indexOf(p) < 0) + t[p] = s[p]; + if (s != null && typeof Object.getOwnPropertySymbols === "function") + for (var i = 0, p = Object.getOwnPropertySymbols(s); i < p.length; i++) if (e.indexOf(p[i]) < 0) + t[p[i]] = s[p[i]]; + return t; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const log_node_1 = require("./log-node"); +const util_1 = require("./util"); +// TODO Fix any cast +function resolveParam(param) { + return typeof param === "string" ? { msg: param } : param || {}; +} +exports.resolveParam = resolveParam; +class LogEntry extends log_node_1.LogNode { + constructor({ level, opts, parent }) { + const { id } = opts, otherOpts = __rest(opts, ["id"]); + super(level, parent, id); + this.opts = otherOpts; + if (this.level === log_node_1.LogLevel.error) { + this.opts.status = "error"; + } + } + setOwnState(nextOpts) { + let msg; + const { append, msg: nextMsg } = nextOpts; + const prevMsg = this.opts.msg; + if (prevMsg !== undefined && nextMsg && append) { + msg = lodash_1.flatten([...[prevMsg], ...[nextMsg]]); + } + else if (nextMsg) { + msg = nextMsg; + } + else { + msg = prevMsg; + } + // Hack to preserve section alignment if symbols or spinners disappear + const hadSymbolOrSpinner = this.opts.symbol || this.opts.status === "active"; + const hasSymbolOrSpinner = nextOpts.symbol || nextOpts.status === "active"; + if (this.opts.section && hadSymbolOrSpinner && !hasSymbolOrSpinner) { + nextOpts.symbol = "empty"; + } + this.opts = Object.assign({}, this.opts, nextOpts, { msg }); + } + // Update node and child nodes + deepSetState(opts) { + const wasActive = this.opts.status === "active"; + this.setOwnState(opts); + // Stop active child nodes if parent is no longer active + if (wasActive && this.opts.status !== "active") { + util_1.getChildEntries(this).forEach(entry => { + if (entry.opts.status === "active") { + entry.setOwnState({ status: "done" }); + } + }); + } + } + createNode(level, parent, param) { + // Empty entries inherit their parent's indentation level + let { indentationLevel } = this.opts; + if (param) { + indentationLevel = (indentationLevel || 0) + 1; + } + const opts = Object.assign({ indentationLevel }, resolveParam(param)); + return new LogEntry({ level, opts, parent }); + } + // Preserves status + setState(param) { + this.deepSetState(Object.assign({}, resolveParam(param), { status: this.opts.status })); + this.root.onGraphChange(this); + return this; + } + setDone(param) { + this.deepSetState(Object.assign({}, resolveParam(param), { status: "done" })); + this.root.onGraphChange(this); + return this; + } + setSuccess(param) { + this.deepSetState(Object.assign({}, resolveParam(param), { symbol: "success", status: "success" })); + this.root.onGraphChange(this); + return this; + } + setError(param) { + this.deepSetState(Object.assign({}, resolveParam(param), { symbol: "error", status: "error" })); + this.root.onGraphChange(this); + return this; + } + setWarn(param) { + this.deepSetState(Object.assign({}, resolveParam(param), { symbol: "warning", status: "warn" })); + this.root.onGraphChange(this); + return this; + } + fromStdStream() { + return !!this.opts.fromStdStream; + } + stop() { + // Stop gracefully if still in active state + if (this.opts.status === "active") { + this.setOwnState({ symbol: "empty", status: "done" }); + this.root.onGraphChange(this); + } + return this; + } + inspect() { + console.log(JSON.stringify(Object.assign({}, this.opts, { level: this.level, children: this.children }))); + } + filterBySection(section) { + return util_1.getChildEntries(this).filter(entry => entry.opts.section === section); + } +} +exports.LogEntry = LogEntry; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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LENBQUE7SUFDTCxDQUFDO0lBRUQsZUFBZSxDQUFDLE9BQWU7UUFDN0IsT0FBTyxzQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsT0FBTyxLQUFLLE9BQU8sQ0FBQyxDQUFBO0lBQzlFLENBQUM7Q0FFRjtBQXZIRCw0QkF1SEMiLCJmaWxlIjoibG9nZ2VyL2xvZy1lbnRyeS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBsb2dTeW1ib2xzIGZyb20gXCJsb2ctc3ltYm9sc1wiXG5pbXBvcnQgKiBhcyBub2RlRW1vamkgZnJvbSBcIm5vZGUtZW1vamlcIlxuaW1wb3J0IHsgZmxhdHRlbiB9IGZyb20gXCJsb2Rhc2hcIlxuXG5pbXBvcnQgeyBMb2dOb2RlLCBMb2dMZXZlbCB9IGZyb20gXCIuL2xvZy1ub2RlXCJcbmltcG9ydCB7IGdldENoaWxkRW50cmllcyB9IGZyb20gXCIuL3V0aWxcIlxuaW1wb3J0IHsgR2FyZGVuRXJyb3IgfSBmcm9tIFwiLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBPbWl0IH0gZnJvbSBcIi4uL3V0aWwvdXRpbFwiXG5cbmV4cG9ydCB0eXBlIEVtb2ppTmFtZSA9IGtleW9mIHR5cGVvZiBub2RlRW1vamkuZW1vamlcbmV4cG9ydCB0eXBlIExvZ1N5bWJvbCA9IGtleW9mIHR5cGVvZiBsb2dTeW1ib2xzIHwgXCJlbXB0eVwiXG5leHBvcnQgdHlwZSBFbnRyeVN0YXR1cyA9IFwiYWN0aXZlXCIgfCBcImRvbmVcIiB8IFwiZXJyb3JcIiB8IFwic3VjY2Vzc1wiIHwgXCJ3YXJuXCJcblxuZXhwb3J0IGludGVyZmFjZSBVcGRhdGVPcHRzIHtcbiAgbXNnPzogc3RyaW5nIHwgc3RyaW5nW11cbiAgc2VjdGlvbj86IHN0cmluZ1xuICBlbW9qaT86IEVtb2ppTmFtZVxuICBzeW1ib2w/OiBMb2dTeW1ib2xcbiAgYXBwZW5kPzogYm9vbGVhblxuICBmcm9tU3RkU3RyZWFtPzogYm9vbGVhblxuICBzaG93RHVyYXRpb24/OiBib29sZWFuXG4gIGVycm9yPzogR2FyZGVuRXJyb3JcbiAgc3RhdHVzPzogRW50cnlTdGF0dXNcbiAgaW5kZW50YXRpb25MZXZlbD86IG51bWJlclxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENyZWF0ZU9wdHMgZXh0ZW5kcyBVcGRhdGVPcHRzIHtcbiAgaWQ/OiBzdHJpbmdcbn1cblxuZXhwb3J0IHR5cGUgQ3JlYXRlUGFyYW0gPSBzdHJpbmcgfCBDcmVhdGVPcHRzXG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nRW50cnlDb25zdHJ1Y3RvciB7XG4gIGxldmVsOiBMb2dMZXZlbFxuICBvcHRzOiBDcmVhdGVPcHRzXG4gIHBhcmVudDogTG9nTm9kZVxufVxuXG4vLyBUT0RPIEZpeCBhbnkgY2FzdFxuZXhwb3J0IGZ1bmN0aW9uIHJlc29sdmVQYXJhbTxUIGV4dGVuZHMgVXBkYXRlT3B0cz4ocGFyYW0/OiBzdHJpbmcgfCBUKTogVCB7XG4gIHJldHVybiB0eXBlb2YgcGFyYW0gPT09IFwic3RyaW5nXCIgPyA8YW55PnsgbXNnOiBwYXJhbSB9IDogcGFyYW0gfHwge31cbn1cblxuZXhwb3J0IGNsYXNzIExvZ0VudHJ5IGV4dGVuZHMgTG9nTm9kZSB7XG4gIHB1YmxpYyBvcHRzOiBVcGRhdGVPcHRzXG5cbiAgY29uc3RydWN0b3IoeyBsZXZlbCwgb3B0cywgcGFyZW50IH06IExvZ0VudHJ5Q29uc3RydWN0b3IpIHtcbiAgICBjb25zdCB7IGlkLCAuLi5vdGhlck9wdHMgfSA9IG9wdHNcbiAgICBzdXBlcihsZXZlbCwgcGFyZW50LCBpZClcbiAgICB0aGlzLm9wdHMgPSBvdGhlck9wdHNcbiAgICBpZiAodGhpcy5sZXZlbCA9PT0gTG9nTGV2ZWwuZXJyb3IpIHtcbiAgICAgIHRoaXMub3B0cy5zdGF0dXMgPSBcImVycm9yXCJcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIHNldE93blN0YXRlKG5leHRPcHRzOiBVcGRhdGVPcHRzKTogdm9pZCB7XG4gICAgbGV0IG1zZzogc3RyaW5nIHwgc3RyaW5nW10gfCB1bmRlZmluZWRcbiAgICBjb25zdCB7IGFwcGVuZCwgbXNnOiBuZXh0TXNnIH0gPSBuZXh0T3B0c1xuICAgIGNvbnN0IHByZXZNc2cgPSB0aGlzLm9wdHMubXNnXG4gICAgaWYgKHByZXZNc2cgIT09IHVuZGVmaW5lZCAmJiBuZXh0TXNnICYmIGFwcGVuZCkge1xuICAgICAgbXNnID0gZmxhdHRlbihbLi4uW3ByZXZNc2ddLCAuLi5bbmV4dE1zZ11dKVxuICAgIH0gZWxzZSBpZiAobmV4dE1zZykge1xuICAgICAgbXNnID0gbmV4dE1zZ1xuICAgIH0gZWxzZSB7XG4gICAgICBtc2cgPSBwcmV2TXNnXG4gICAgfVxuXG4gICAgLy8gSGFjayB0byBwcmVzZXJ2ZSBzZWN0aW9uIGFsaWdubWVudCBpZiBzeW1ib2xzIG9yIHNwaW5uZXJzIGRpc2FwcGVhclxuICAgIGNvbnN0IGhhZFN5bWJvbE9yU3Bpbm5lciA9IHRoaXMub3B0cy5zeW1ib2wgfHwgdGhpcy5vcHRzLnN0YXR1cyA9PT0gXCJhY3RpdmVcIlxuICAgIGNvbnN0IGhhc1N5bWJvbE9yU3Bpbm5lciA9IG5leHRPcHRzLnN5bWJvbCB8fCBuZXh0T3B0cy5zdGF0dXMgPT09IFwiYWN0aXZlXCJcbiAgICBpZiAodGhpcy5vcHRzLnNlY3Rpb24gJiYgaGFkU3ltYm9sT3JTcGlubmVyICYmICFoYXNTeW1ib2xPclNwaW5uZXIpIHtcbiAgICAgIG5leHRPcHRzLnN5bWJvbCA9IFwiZW1wdHlcIlxuICAgIH1cblxuICAgIHRoaXMub3B0cyA9IHsgLi4udGhpcy5vcHRzLCAuLi5uZXh0T3B0cywgbXNnIH1cbiAgfVxuXG4gIC8vICBVcGRhdGUgbm9kZSBhbmQgY2hpbGQgbm9kZXNcbiAgcHJpdmF0ZSBkZWVwU2V0U3RhdGUob3B0czogVXBkYXRlT3B0cyk6IHZvaWQge1xuICAgIGNvbnN0IHdhc0FjdGl2ZSA9IHRoaXMub3B0cy5zdGF0dXMgPT09IFwiYWN0aXZlXCJcblxuICAgIHRoaXMuc2V0T3duU3RhdGUob3B0cylcblxuICAgIC8vIFN0b3AgYWN0aXZlIGNoaWxkIG5vZGVzIGlmIHBhcmVudCBpcyBubyBsb25nZXIgYWN0aXZlXG4gICAgaWYgKHdhc0FjdGl2ZSAmJiB0aGlzLm9wdHMuc3RhdHVzICE9PSBcImFjdGl2ZVwiKSB7XG4gICAgICBnZXRDaGlsZEVudHJpZXModGhpcykuZm9yRWFjaChlbnRyeSA9PiB7XG4gICAgICAgIGlmIChlbnRyeS5vcHRzLnN0YXR1cyA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgICAgIGVudHJ5LnNldE93blN0YXRlKHsgc3RhdHVzOiBcImRvbmVcIiB9KVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH1cbiAgfVxuXG4gIGNyZWF0ZU5vZGUobGV2ZWw6IExvZ0xldmVsLCBwYXJlbnQ6IExvZ05vZGUsIHBhcmFtPzogQ3JlYXRlUGFyYW0pIHtcbiAgICAvLyBFbXB0eSBlbnRyaWVzIGluaGVyaXQgdGhlaXIgcGFyZW50J3MgaW5kZW50YXRpb24gbGV2ZWxcbiAgICBsZXQgeyBpbmRlbnRhdGlvbkxldmVsIH0gPSB0aGlzLm9wdHNcbiAgICBpZiAocGFyYW0pIHtcbiAgICAgIGluZGVudGF0aW9uTGV2ZWwgPSAoaW5kZW50YXRpb25MZXZlbCB8fCAwKSArIDFcbiAgICB9XG4gICAgY29uc3Qgb3B0cyA9IHtcbiAgICAgIGluZGVudGF0aW9uTGV2ZWwsXG4gICAgICAuLi5yZXNvbHZlUGFyYW0ocGFyYW0pLFxuICAgIH1cbiAgICByZXR1cm4gbmV3IExvZ0VudHJ5KHsgbGV2ZWwsIG9wdHMsIHBhcmVudCB9KVxuICB9XG5cbiAgLy8gUHJlc2VydmVzIHN0YXR1c1xuICBzZXRTdGF0ZShwYXJhbT86IHN0cmluZyB8IFVwZGF0ZU9wdHMpOiBMb2dFbnRyeSB7XG4gICAgdGhpcy5kZWVwU2V0U3RhdGUoeyAuLi5yZXNvbHZlUGFyYW0ocGFyYW0pLCBzdGF0dXM6IHRoaXMub3B0cy5zdGF0dXMgfSlcbiAgICB0aGlzLnJvb3Qub25HcmFwaENoYW5nZSh0aGlzKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBzZXREb25lKHBhcmFtPzogc3RyaW5nIHwgT21pdDxVcGRhdGVPcHRzLCBcInN0YXR1c1wiPik6IExvZ0VudHJ5IHtcbiAgICB0aGlzLmRlZXBTZXRTdGF0ZSh7IC4uLnJlc29sdmVQYXJhbShwYXJhbSksIHN0YXR1czogXCJkb25lXCIgfSlcbiAgICB0aGlzLnJvb3Qub25HcmFwaENoYW5nZSh0aGlzKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBzZXRTdWNjZXNzKHBhcmFtPzogc3RyaW5nIHwgT21pdDxVcGRhdGVPcHRzLCBcInN0YXR1c1wiICYgXCJzeW1ib2xcIj4pOiBMb2dFbnRyeSB7XG4gICAgdGhpcy5kZWVwU2V0U3RhdGUoeyAuLi5yZXNvbHZlUGFyYW0ocGFyYW0pLCBzeW1ib2w6IFwic3VjY2Vzc1wiLCBzdGF0dXM6IFwic3VjY2Vzc1wiIH0pXG4gICAgdGhpcy5yb290Lm9uR3JhcGhDaGFuZ2UodGhpcylcbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgc2V0RXJyb3IocGFyYW0/OiBzdHJpbmcgfCBPbWl0PFVwZGF0ZU9wdHMsIFwic3RhdHVzXCIgJiBcInN5bWJvbFwiPik6IExvZ0VudHJ5IHtcbiAgICB0aGlzLmRlZXBTZXRTdGF0ZSh7IC4uLnJlc29sdmVQYXJhbShwYXJhbSksIHN5bWJvbDogXCJlcnJvclwiLCBzdGF0dXM6IFwiZXJyb3JcIiB9KVxuICAgIHRoaXMucm9vdC5vbkdyYXBoQ2hhbmdlKHRoaXMpXG4gICAgcmV0dXJuIHRoaXNcbiAgfVxuXG4gIHNldFdhcm4ocGFyYW0/OiBzdHJpbmcgfCBPbWl0PFVwZGF0ZU9wdHMsIFwic3RhdHVzXCIgJiBcInN5bWJvbFwiPik6IExvZ0VudHJ5IHtcbiAgICB0aGlzLmRlZXBTZXRTdGF0ZSh7IC4uLnJlc29sdmVQYXJhbShwYXJhbSksIHN5bWJvbDogXCJ3YXJuaW5nXCIsIHN0YXR1czogXCJ3YXJuXCIgfSlcbiAgICB0aGlzLnJvb3Qub25HcmFwaENoYW5nZSh0aGlzKVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBmcm9tU3RkU3RyZWFtKCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiAhIXRoaXMub3B0cy5mcm9tU3RkU3RyZWFtXG4gIH1cblxuICBzdG9wKCkge1xuICAgIC8vIFN0b3AgZ3JhY2VmdWxseSBpZiBzdGlsbCBpbiBhY3RpdmUgc3RhdGVcbiAgICBpZiAodGhpcy5vcHRzLnN0YXR1cyA9PT0gXCJhY3RpdmVcIikge1xuICAgICAgdGhpcy5zZXRPd25TdGF0ZSh7IHN5bWJvbDogXCJlbXB0eVwiLCBzdGF0dXM6IFwiZG9uZVwiIH0pXG4gICAgICB0aGlzLnJvb3Qub25HcmFwaENoYW5nZSh0aGlzKVxuICAgIH1cbiAgICByZXR1cm4gdGhpc1xuICB9XG5cbiAgaW5zcGVjdCgpIHtcbiAgICBjb25zb2xlLmxvZyhKU09OLnN0cmluZ2lmeSh7XG4gICAgICAuLi50aGlzLm9wdHMsXG4gICAgICBsZXZlbDogdGhpcy5sZXZlbCxcbiAgICAgIGNoaWxkcmVuOiB0aGlzLmNoaWxkcmVuLFxuICAgIH0pKVxuICB9XG5cbiAgZmlsdGVyQnlTZWN0aW9uKHNlY3Rpb246IHN0cmluZyk6IExvZ0VudHJ5W10ge1xuICAgIHJldHVybiBnZXRDaGlsZEVudHJpZXModGhpcykuZmlsdGVyKGVudHJ5ID0+IGVudHJ5Lm9wdHMuc2VjdGlvbiA9PT0gc2VjdGlvbilcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/logger/log-node.d.ts b/garden-service/build/logger/log-node.d.ts new file mode 100644 index 00000000000..23d62f55c21 --- /dev/null +++ b/garden-service/build/logger/log-node.d.ts @@ -0,0 +1,36 @@ +import { LogEntry, CreateParam } from "./log-entry"; +export declare enum LogLevel { + error = 0, + warn = 1, + info = 2, + verbose = 3, + debug = 4, + silly = 5 +} +export declare abstract class LogNode { + readonly level: LogLevel; + readonly parent?: LogNode | undefined; + readonly id?: string | undefined; + readonly timestamp: number; + readonly key: string; + readonly children: T[]; + readonly root: RootLogNode; + constructor(level: LogLevel, parent?: LogNode | undefined, id?: string | undefined); + abstract createNode(level: LogLevel, parent: LogNode, param?: U): T; + protected appendNode(level: LogLevel, param?: U): T; + silly(param?: U): T; + debug(param?: U): T; + verbose(param?: U): T; + info(param?: U): T; + warn(param?: U): T; + error(param?: U): T; + /** + * Returns the duration in seconds, defaults to 2 decimal precision + */ + getDuration(precision?: number): number; +} +export declare abstract class RootLogNode extends LogNode { + abstract onGraphChange(node: T): void; + findById(id: string): T | void; +} +//# sourceMappingURL=log-node.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/log-node.js b/garden-service/build/logger/log-node.js new file mode 100644 index 00000000000..9340b29da3d --- /dev/null +++ b/garden-service/build/logger/log-node.js @@ -0,0 +1,77 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const uniqid = require("uniqid"); +const lodash_1 = require("lodash"); +const util_1 = require("./util"); +var LogLevel; +(function (LogLevel) { + LogLevel[LogLevel["error"] = 0] = "error"; + LogLevel[LogLevel["warn"] = 1] = "warn"; + LogLevel[LogLevel["info"] = 2] = "info"; + LogLevel[LogLevel["verbose"] = 3] = "verbose"; + LogLevel[LogLevel["debug"] = 4] = "debug"; + LogLevel[LogLevel["silly"] = 5] = "silly"; +})(LogLevel = exports.LogLevel || (exports.LogLevel = {})); +class LogNode { + constructor(level, parent, id) { + this.level = level; + this.parent = parent; + this.id = id; + if (this instanceof RootLogNode) { + this.root = this; + } + else { + // Non-root nodes have a parent + this.root = parent.root; + } + this.key = uniqid(); + this.timestamp = Date.now(); + this.children = []; + } + appendNode(level, param) { + const node = this.createNode(level, this, param); + this.children.push(node); + this.root.onGraphChange(node); + return node; + } + silly(param) { + return this.appendNode(LogLevel.silly, param); + } + debug(param) { + return this.appendNode(LogLevel.debug, param); + } + verbose(param) { + return this.appendNode(LogLevel.verbose, param); + } + info(param) { + return this.appendNode(LogLevel.info, param); + } + warn(param) { + return this.appendNode(LogLevel.warn, param); + } + error(param) { + return this.appendNode(LogLevel.error, param); + } + /** + * Returns the duration in seconds, defaults to 2 decimal precision + */ + getDuration(precision = 2) { + return lodash_1.round((Date.now() - this.timestamp) / 1000, precision); + } +} +exports.LogNode = LogNode; +class RootLogNode extends LogNode { + findById(id) { + return util_1.findLogNode(this, node => node.id === id); + } +} +exports.RootLogNode = RootLogNode; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO0lBQ2xELENBQUM7Q0FFRjtBQVBELGtDQU9DIiwiZmlsZSI6ImxvZ2dlci9sb2ctbm9kZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyB1bmlxaWQgZnJvbSBcInVuaXFpZFwiXG5pbXBvcnQgeyByb3VuZCB9IGZyb20gXCJsb2Rhc2hcIlxuXG5pbXBvcnQgeyBmaW5kTG9nTm9kZSB9IGZyb20gXCIuL3V0aWxcIlxuaW1wb3J0IHsgTG9nRW50cnksIENyZWF0ZVBhcmFtIH0gZnJvbSBcIi4vbG9nLWVudHJ5XCJcblxuZXhwb3J0IGVudW0gTG9nTGV2ZWwge1xuICBlcnJvciA9IDAsXG4gIHdhcm4gPSAxLFxuICBpbmZvID0gMixcbiAgdmVyYm9zZSA9IDMsXG4gIGRlYnVnID0gNCxcbiAgc2lsbHkgPSA1LFxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgTG9nTm9kZTxUID0gTG9nRW50cnksIFUgPSBDcmVhdGVQYXJhbT4ge1xuICBwdWJsaWMgcmVhZG9ubHkgdGltZXN0YW1wOiBudW1iZXJcbiAgcHVibGljIHJlYWRvbmx5IGtleTogc3RyaW5nXG4gIHB1YmxpYyByZWFkb25seSBjaGlsZHJlbjogVFtdXG4gIHB1YmxpYyByZWFkb25seSByb290OiBSb290TG9nTm9kZTxUPlxuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWFkb25seSBsZXZlbDogTG9nTGV2ZWwsXG4gICAgcHVibGljIHJlYWRvbmx5IHBhcmVudD86IExvZ05vZGU8VD4sXG4gICAgcHVibGljIHJlYWRvbmx5IGlkPzogc3RyaW5nLFxuICApIHtcbiAgICBpZiAodGhpcyBpbnN0YW5jZW9mIFJvb3RMb2dOb2RlKSB7XG4gICAgICB0aGlzLnJvb3QgPSB0aGlzXG4gICAgfSBlbHNlIHtcbiAgICAgIC8vIE5vbi1yb290IG5vZGVzIGhhdmUgYSBwYXJlbnRcbiAgICAgIHRoaXMucm9vdCA9IHBhcmVudCEucm9vdFxuICAgIH1cbiAgICB0aGlzLmtleSA9IHVuaXFpZCgpXG4gICAgdGhpcy50aW1lc3RhbXAgPSBEYXRlLm5vdygpXG4gICAgdGhpcy5jaGlsZHJlbiA9IFtdXG4gIH1cblxuICBhYnN0cmFjdCBjcmVhdGVOb2RlKGxldmVsOiBMb2dMZXZlbCwgcGFyZW50OiBMb2dOb2RlPFQsIFU+LCBwYXJhbT86IFUpOiBUXG5cbiAgcHJvdGVjdGVkIGFwcGVuZE5vZGUobGV2ZWw6IExvZ0xldmVsLCBwYXJhbT86IFUpOiBUIHtcbiAgICBjb25zdCBub2RlID0gdGhpcy5jcmVhdGVOb2RlKGxldmVsLCB0aGlzLCBwYXJhbSlcbiAgICB0aGlzLmNoaWxkcmVuLnB1c2gobm9kZSlcbiAgICB0aGlzLnJvb3Qub25HcmFwaENoYW5nZShub2RlKVxuICAgIHJldHVybiBub2RlXG4gIH1cblxuICBzaWxseShwYXJhbT86IFUpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5hcHBlbmROb2RlKExvZ0xldmVsLnNpbGx5LCBwYXJhbSlcbiAgfVxuXG4gIGRlYnVnKHBhcmFtPzogVSk6IFQge1xuICAgIHJldHVybiB0aGlzLmFwcGVuZE5vZGUoTG9nTGV2ZWwuZGVidWcsIHBhcmFtKVxuICB9XG5cbiAgdmVyYm9zZShwYXJhbT86IFUpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5hcHBlbmROb2RlKExvZ0xldmVsLnZlcmJvc2UsIHBhcmFtKVxuICB9XG5cbiAgaW5mbyhwYXJhbT86IFUpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5hcHBlbmROb2RlKExvZ0xldmVsLmluZm8sIHBhcmFtKVxuICB9XG5cbiAgd2FybihwYXJhbT86IFUpOiBUIHtcbiAgICByZXR1cm4gdGhpcy5hcHBlbmROb2RlKExvZ0xldmVsLndhcm4sIHBhcmFtKVxuICB9XG5cbiAgZXJyb3IocGFyYW0/OiBVKTogVCB7XG4gICAgcmV0dXJuIHRoaXMuYXBwZW5kTm9kZShMb2dMZXZlbC5lcnJvciwgcGFyYW0pXG4gIH1cblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgZHVyYXRpb24gaW4gc2Vjb25kcywgZGVmYXVsdHMgdG8gMiBkZWNpbWFsIHByZWNpc2lvblxuICAgKi9cbiAgZ2V0RHVyYXRpb24ocHJlY2lzaW9uOiBudW1iZXIgPSAyKTogbnVtYmVyIHtcbiAgICByZXR1cm4gcm91bmQoKERhdGUubm93KCkgLSB0aGlzLnRpbWVzdGFtcCkgLyAxMDAwLCBwcmVjaXNpb24pXG4gIH1cblxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgUm9vdExvZ05vZGU8VCA9IExvZ0VudHJ5PiBleHRlbmRzIExvZ05vZGU8VD4ge1xuICBhYnN0cmFjdCBvbkdyYXBoQ2hhbmdlKG5vZGU6IFQpOiB2b2lkXG5cbiAgZmluZEJ5SWQoaWQ6IHN0cmluZyk6IFQgfCB2b2lkIHtcbiAgICByZXR1cm4gZmluZExvZ05vZGUodGhpcywgbm9kZSA9PiBub2RlLmlkID09PSBpZClcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/logger/logger.d.ts b/garden-service/build/logger/logger.d.ts new file mode 100644 index 00000000000..2028ab72b27 --- /dev/null +++ b/garden-service/build/logger/logger.d.ts @@ -0,0 +1,37 @@ +import { RootLogNode, LogNode } from "./log-node"; +import { LogEntry, CreateOpts } from "./log-entry"; +import { Writer } from "./writers/base"; +import { LogLevel } from "./log-node"; +export declare enum LoggerType { + quiet = "quiet", + basic = "basic", + fancy = "fancy" +} +export declare function getCommonConfig(loggerType: LoggerType): LoggerConfig; +export interface LoggerConfig { + level: LogLevel; + writers?: Writer[]; +} +export declare class Logger extends RootLogNode { + writers: Writer[]; + private static instance; + static getInstance(): Logger; + static initialize(config: LoggerConfig): any; + private constructor(); + createNode(level: LogLevel, _parent: LogNode, opts: CreateOpts): any; + onGraphChange(entry: LogEntry): void; + getLogEntries(): LogEntry[]; + filterBySection(section: string): LogEntry[]; + header({ command, emoji, level }: { + command: string; + emoji?: string; + level?: LogLevel; + }): LogEntry; + finish({ showDuration, level }?: { + showDuration?: boolean; + level?: LogLevel; + }): LogEntry; + stop(): void; +} +export declare function getLogger(): Logger; +//# sourceMappingURL=logger.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/logger.js b/garden-service/build/logger/logger.js new file mode 100644 index 00000000000..1aa87a0c24f --- /dev/null +++ b/garden-service/build/logger/logger.js @@ -0,0 +1,118 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const nodeEmoji = require("node-emoji"); +const chalk_1 = require("chalk"); +const log_node_1 = require("./log-node"); +const log_entry_1 = require("./log-entry"); +const util_1 = require("./util"); +const exceptions_1 = require("../exceptions"); +const log_node_2 = require("./log-node"); +const fancy_terminal_writer_1 = require("./writers/fancy-terminal-writer"); +const basic_terminal_writer_1 = require("./writers/basic-terminal-writer"); +const renderers_1 = require("./renderers"); +var LoggerType; +(function (LoggerType) { + LoggerType["quiet"] = "quiet"; + LoggerType["basic"] = "basic"; + LoggerType["fancy"] = "fancy"; +})(LoggerType = exports.LoggerType || (exports.LoggerType = {})); +function getCommonConfig(loggerType) { + const configs = { + [LoggerType.fancy]: { + level: log_node_2.LogLevel.info, + writers: [new fancy_terminal_writer_1.FancyTerminalWriter()], + }, + [LoggerType.basic]: { + level: log_node_2.LogLevel.info, + writers: [new basic_terminal_writer_1.BasicTerminalWriter()], + }, + [LoggerType.quiet]: { + level: log_node_2.LogLevel.info, + }, + }; + return configs[loggerType]; +} +exports.getCommonConfig = getCommonConfig; +class Logger extends log_node_1.RootLogNode { + static getInstance() { + if (!Logger.instance) { + throw new exceptions_1.InternalError("Logger not initialized", {}); + } + return Logger.instance; + } + static initialize(config) { + if (Logger.instance) { + throw new exceptions_1.InternalError("Logger already initialized", {}); + } + let instance; + // If GARDEN_LOGGER_TYPE env variable is set it takes precedence over the config param + if (process.env.GARDEN_LOGGER_TYPE) { + const loggerType = LoggerType[process.env.GARDEN_LOGGER_TYPE]; + if (!loggerType) { + throw new exceptions_1.ParameterError(`Invalid logger type specified: ${process.env.GARDEN_LOGGER_TYPE}`, { + loggerType: process.env.GARDEN_LOGGER_TYPE, + availableTypes: Object.keys(LoggerType), + }); + } + instance = new Logger(getCommonConfig(loggerType)); + instance.debug(`Setting logger type to ${loggerType} (from GARDEN_LOGGER_TYPE)`); + } + else { + instance = new Logger(config); + } + Logger.instance = instance; + return instance; + } + constructor(config) { + super(config.level); + this.writers = config.writers || []; + } + createNode(level, _parent, opts) { + return new log_entry_1.LogEntry({ level, parent: this, opts: log_entry_1.resolveParam(opts) }); + } + onGraphChange(entry) { + this.writers.forEach(writer => writer.onGraphChange(entry, this)); + } + getLogEntries() { + return util_1.getChildEntries(this).filter(entry => !entry.fromStdStream()); + } + filterBySection(section) { + return util_1.getChildEntries(this).filter(entry => entry.opts.section === section); + } + header({ command, emoji, level = log_node_2.LogLevel.info }) { + const msg = renderers_1.combine([ + [chalk_1.default.bold.magenta(command)], + [emoji ? " " + nodeEmoji.get(emoji) : ""], + ["\n"], + ]); + const lvlStr = log_node_2.LogLevel[level]; + return this[lvlStr](msg); + } + finish({ showDuration = true, level = log_node_2.LogLevel.info } = {}) { + const msg = renderers_1.combine([ + [`\n${nodeEmoji.get("sparkles")} Finished`], + [showDuration ? ` in ${chalk_1.default.bold(this.getDuration() + "s")}` : "!"], + ["\n"], + ]); + const lvlStr = log_node_2.LogLevel[level]; + return this[lvlStr](msg); + } + stop() { + this.getLogEntries().forEach(e => e.stop()); + this.writers.forEach(writer => writer.stop()); + } +} +exports.Logger = Logger; +function getLogger() { + return Logger.getInstance(); +} +exports.getLogger = getLogger; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxvZ2dlci9sb2dnZXIudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFFSCx3Q0FBdUM7QUFDdkMsaUNBQXlCO0FBRXpCLHlDQUFpRDtBQUNqRCwyQ0FBZ0U7QUFDaEUsaUNBQXdDO0FBRXhDLDhDQUE2RDtBQUM3RCx5Q0FBcUM7QUFDckMsMkVBQXFFO0FBQ3JFLDJFQUFxRTtBQUNyRSwyQ0FBcUM7QUFFckMsSUFBWSxVQUlYO0FBSkQsV0FBWSxVQUFVO0lBQ3BCLDZCQUFlLENBQUE7SUFDZiw2QkFBZSxDQUFBO0lBQ2YsNkJBQWUsQ0FBQTtBQUNqQixDQUFDLEVBSlcsVUFBVSxHQUFWLGtCQUFVLEtBQVYsa0JBQVUsUUFJckI7QUFFRCxTQUFnQixlQUFlLENBQUMsVUFBc0I7SUFDcEQsTUFBTSxPQUFPLEdBQTBDO1FBQ3JELENBQUMsVUFBVSxDQUFDLEtBQUssQ0FBQyxFQUFFO1lBQ2xCLEtBQUssRUFBRSxtQkFBUSxDQUFDLElBQUk7WUFDcEIsT0FBTyxFQUFFLENBQUMsSUFBSSwyQ0FBbUIsRUFBRSxDQUFDO1NBQ3JDO1FBQ0QsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUU7WUFDbEIsS0FBSyxFQUFFLG1CQUFRLENBQUMsSUFBSTtZQUNwQixPQUFPLEVBQUUsQ0FBQyxJQUFJLDJDQUFtQixFQUFFLENBQUM7U0FDckM7UUFDRCxDQUFDLFVBQVUsQ0FBQyxLQUFLLENBQUMsRUFBRTtZQUNsQixLQUFLLEVBQUUsbUJBQVEsQ0FBQyxJQUFJO1NBQ3JCO0tBQ0YsQ0FBQTtJQUNELE9BQU8sT0FBTyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0FBQzVCLENBQUM7QUFmRCwwQ0FlQztBQU9ELE1BQWEsTUFBTyxTQUFRLHNCQUFxQjtJQUsvQyxNQUFNLENBQUMsV0FBVztRQUNoQixJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsRUFBRTtZQUNwQixNQUFNLElBQUksMEJBQWEsQ0FBQyx3QkFBd0IsRUFBRSxFQUFFLENBQUMsQ0FBQTtTQUN0RDtRQUNELE9BQU8sTUFBTSxDQUFDLFFBQVEsQ0FBQTtJQUN4QixDQUFDO0lBRUQsTUFBTSxDQUFDLFVBQVUsQ0FBQyxNQUFvQjtRQUNwQyxJQUFJLE1BQU0sQ0FBQyxRQUFRLEVBQUU7WUFDbkIsTUFBTSxJQUFJLDBCQUFhLENBQUMsNEJBQTRCLEVBQUUsRUFBRSxDQUFDLENBQUE7U0FDMUQ7UUFFRCxJQUFJLFFBQVEsQ0FBQTtRQUVaLHNGQUFzRjtRQUN0RixJQUFJLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLEVBQUU7WUFDbEMsTUFBTSxVQUFVLEdBQUcsVUFBVSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsa0JBQWtCLENBQUMsQ0FBQTtZQUU3RCxJQUFJLENBQUMsVUFBVSxFQUFFO2dCQUNmLE1BQU0sSUFBSSwyQkFBYyxDQUFDLGtDQUFrQyxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQixFQUFFLEVBQUU7b0JBQzNGLFVBQVUsRUFBRSxPQUFPLENBQUMsR0FBRyxDQUFDLGtCQUFrQjtvQkFDMUMsY0FBYyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDO2lCQUN4QyxDQUFDLENBQUE7YUFDSDtZQUVELFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxlQUFlLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQTtZQUNsRCxRQUFRLENBQUMsS0FBSyxDQUFDLDBCQUEwQixVQUFVLDRCQUE0QixDQUFDLENBQUE7U0FDakY7YUFBTTtZQUNMLFFBQVEsR0FBRyxJQUFJLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQTtTQUM5QjtRQUVELE1BQU0sQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFBO1FBQzFCLE9BQU8sUUFBUSxDQUFBO0lBQ2pCLENBQUM7SUFFRCxZQUFvQixNQUFvQjtRQUN0QyxLQUFLLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQ25CLElBQUksQ0FBQyxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sSUFBSSxFQUFFLENBQUE7SUFDckMsQ0FBQztJQUVELFVBQVUsQ0FBQyxLQUFlLEVBQUUsT0FBZ0IsRUFBRSxJQUFnQjtRQUM1RCxPQUFPLElBQUksb0JBQVEsQ0FBQyxFQUFFLEtBQUssRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSx3QkFBWSxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQTtJQUN4RSxDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQWU7UUFDM0IsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsYUFBYSxDQUFDLEtBQUssRUFBRSxJQUFJLENBQUMsQ0FBQyxDQUFBO0lBQ25FLENBQUM7SUFFRCxhQUFhO1FBQ1gsT0FBTyxzQkFBZSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxDQUFDLGFBQWEsRUFBRSxDQUFDLENBQUE7SUFDdEUsQ0FBQztJQUVELGVBQWUsQ0FBQyxPQUFlO1FBQzdCLE9BQU8sc0JBQWUsQ0FBQyxJQUFJLENBQUMsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sS0FBSyxPQUFPLENBQUMsQ0FBQTtJQUM5RSxDQUFDO0lBRUQsTUFBTSxDQUNKLEVBQUUsT0FBTyxFQUFFLEtBQUssRUFBRSxLQUFLLEdBQUcsbUJBQVEsQ0FBQyxJQUFJLEVBQXlEO1FBRWhHLE1BQU0sR0FBRyxHQUFHLG1CQUFPLENBQUM7WUFDbEIsQ0FBQyxlQUFLLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM3QixDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsR0FBRyxHQUFHLFNBQVMsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQztZQUN6QyxDQUFDLElBQUksQ0FBQztTQUNQLENBQUMsQ0FBQTtRQUNGLE1BQU0sTUFBTSxHQUFHLG1CQUFRLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDOUIsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDMUIsQ0FBQztJQUVELE1BQU0sQ0FDSixFQUFFLFlBQVksR0FBRyxJQUFJLEVBQUUsS0FBSyxHQUFHLG1CQUFRLENBQUMsSUFBSSxLQUFtRCxFQUFFO1FBRWpHLE1BQU0sR0FBRyxHQUFHLG1CQUFPLENBQUM7WUFDbEIsQ0FBQyxLQUFLLFNBQVMsQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFDLFlBQVksQ0FBQztZQUM1QyxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUMsT0FBTyxlQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxXQUFXLEVBQUUsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxHQUFHLENBQUM7WUFDcEUsQ0FBQyxJQUFJLENBQUM7U0FDUCxDQUFDLENBQUE7UUFDRixNQUFNLE1BQU0sR0FBRyxtQkFBUSxDQUFDLEtBQUssQ0FBQyxDQUFBO1FBQzlCLE9BQU8sSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsQ0FBQyxDQUFBO0lBQzFCLENBQUM7SUFFRCxJQUFJO1FBQ0YsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLEVBQUUsQ0FBQyxDQUFBO1FBQzNDLElBQUksQ0FBQyxPQUFPLENBQUMsT0FBTyxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUE7SUFDL0MsQ0FBQztDQUVGO0FBMUZELHdCQTBGQztBQUVELFNBQWdCLFNBQVM7SUFDdkIsT0FBTyxNQUFNLENBQUMsV0FBVyxFQUFFLENBQUE7QUFDN0IsQ0FBQztBQUZELDhCQUVDIiwiZmlsZSI6ImxvZ2dlci9sb2dnZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgbm9kZUVtb2ppIGZyb20gXCJub2RlLWVtb2ppXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuXG5pbXBvcnQgeyBSb290TG9nTm9kZSwgTG9nTm9kZSB9IGZyb20gXCIuL2xvZy1ub2RlXCJcbmltcG9ydCB7IExvZ0VudHJ5LCBDcmVhdGVPcHRzLCByZXNvbHZlUGFyYW0gfSBmcm9tIFwiLi9sb2ctZW50cnlcIlxuaW1wb3J0IHsgZ2V0Q2hpbGRFbnRyaWVzIH0gZnJvbSBcIi4vdXRpbFwiXG5pbXBvcnQgeyBXcml0ZXIgfSBmcm9tIFwiLi93cml0ZXJzL2Jhc2VcIlxuaW1wb3J0IHsgSW50ZXJuYWxFcnJvciwgUGFyYW1ldGVyRXJyb3IgfSBmcm9tIFwiLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBMb2dMZXZlbCB9IGZyb20gXCIuL2xvZy1ub2RlXCJcbmltcG9ydCB7IEZhbmN5VGVybWluYWxXcml0ZXIgfSBmcm9tIFwiLi93cml0ZXJzL2ZhbmN5LXRlcm1pbmFsLXdyaXRlclwiXG5pbXBvcnQgeyBCYXNpY1Rlcm1pbmFsV3JpdGVyIH0gZnJvbSBcIi4vd3JpdGVycy9iYXNpYy10ZXJtaW5hbC13cml0ZXJcIlxuaW1wb3J0IHsgY29tYmluZSB9IGZyb20gXCIuL3JlbmRlcmVyc1wiXG5cbmV4cG9ydCBlbnVtIExvZ2dlclR5cGUge1xuICBxdWlldCA9IFwicXVpZXRcIixcbiAgYmFzaWMgPSBcImJhc2ljXCIsXG4gIGZhbmN5ID0gXCJmYW5jeVwiLFxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0Q29tbW9uQ29uZmlnKGxvZ2dlclR5cGU6IExvZ2dlclR5cGUpOiBMb2dnZXJDb25maWcge1xuICBjb25zdCBjb25maWdzOiB7IFtrZXkgaW4gTG9nZ2VyVHlwZV06IExvZ2dlckNvbmZpZyB9ID0ge1xuICAgIFtMb2dnZXJUeXBlLmZhbmN5XToge1xuICAgICAgbGV2ZWw6IExvZ0xldmVsLmluZm8sXG4gICAgICB3cml0ZXJzOiBbbmV3IEZhbmN5VGVybWluYWxXcml0ZXIoKV0sXG4gICAgfSxcbiAgICBbTG9nZ2VyVHlwZS5iYXNpY106IHtcbiAgICAgIGxldmVsOiBMb2dMZXZlbC5pbmZvLFxuICAgICAgd3JpdGVyczogW25ldyBCYXNpY1Rlcm1pbmFsV3JpdGVyKCldLFxuICAgIH0sXG4gICAgW0xvZ2dlclR5cGUucXVpZXRdOiB7XG4gICAgICBsZXZlbDogTG9nTGV2ZWwuaW5mbyxcbiAgICB9LFxuICB9XG4gIHJldHVybiBjb25maWdzW2xvZ2dlclR5cGVdXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9nZ2VyQ29uZmlnIHtcbiAgbGV2ZWw6IExvZ0xldmVsXG4gIHdyaXRlcnM/OiBXcml0ZXJbXVxufVxuXG5leHBvcnQgY2xhc3MgTG9nZ2VyIGV4dGVuZHMgUm9vdExvZ05vZGU8TG9nRW50cnk+IHtcbiAgcHVibGljIHdyaXRlcnM6IFdyaXRlcltdXG5cbiAgcHJpdmF0ZSBzdGF0aWMgaW5zdGFuY2U6IExvZ2dlclxuXG4gIHN0YXRpYyBnZXRJbnN0YW5jZSgpIHtcbiAgICBpZiAoIUxvZ2dlci5pbnN0YW5jZSkge1xuICAgICAgdGhyb3cgbmV3IEludGVybmFsRXJyb3IoXCJMb2dnZXIgbm90IGluaXRpYWxpemVkXCIsIHt9KVxuICAgIH1cbiAgICByZXR1cm4gTG9nZ2VyLmluc3RhbmNlXG4gIH1cblxuICBzdGF0aWMgaW5pdGlhbGl6ZShjb25maWc6IExvZ2dlckNvbmZpZykge1xuICAgIGlmIChMb2dnZXIuaW5zdGFuY2UpIHtcbiAgICAgIHRocm93IG5ldyBJbnRlcm5hbEVycm9yKFwiTG9nZ2VyIGFscmVhZHkgaW5pdGlhbGl6ZWRcIiwge30pXG4gICAgfVxuXG4gICAgbGV0IGluc3RhbmNlXG5cbiAgICAvLyBJZiBHQVJERU5fTE9HR0VSX1RZUEUgZW52IHZhcmlhYmxlIGlzIHNldCBpdCB0YWtlcyBwcmVjZWRlbmNlIG92ZXIgdGhlIGNvbmZpZyBwYXJhbVxuICAgIGlmIChwcm9jZXNzLmVudi5HQVJERU5fTE9HR0VSX1RZUEUpIHtcbiAgICAgIGNvbnN0IGxvZ2dlclR5cGUgPSBMb2dnZXJUeXBlW3Byb2Nlc3MuZW52LkdBUkRFTl9MT0dHRVJfVFlQRV1cblxuICAgICAgaWYgKCFsb2dnZXJUeXBlKSB7XG4gICAgICAgIHRocm93IG5ldyBQYXJhbWV0ZXJFcnJvcihgSW52YWxpZCBsb2dnZXIgdHlwZSBzcGVjaWZpZWQ6ICR7cHJvY2Vzcy5lbnYuR0FSREVOX0xPR0dFUl9UWVBFfWAsIHtcbiAgICAgICAgICBsb2dnZXJUeXBlOiBwcm9jZXNzLmVudi5HQVJERU5fTE9HR0VSX1RZUEUsXG4gICAgICAgICAgYXZhaWxhYmxlVHlwZXM6IE9iamVjdC5rZXlzKExvZ2dlclR5cGUpLFxuICAgICAgICB9KVxuICAgICAgfVxuXG4gICAgICBpbnN0YW5jZSA9IG5ldyBMb2dnZXIoZ2V0Q29tbW9uQ29uZmlnKGxvZ2dlclR5cGUpKVxuICAgICAgaW5zdGFuY2UuZGVidWcoYFNldHRpbmcgbG9nZ2VyIHR5cGUgdG8gJHtsb2dnZXJUeXBlfSAoZnJvbSBHQVJERU5fTE9HR0VSX1RZUEUpYClcbiAgICB9IGVsc2Uge1xuICAgICAgaW5zdGFuY2UgPSBuZXcgTG9nZ2VyKGNvbmZpZylcbiAgICB9XG5cbiAgICBMb2dnZXIuaW5zdGFuY2UgPSBpbnN0YW5jZVxuICAgIHJldHVybiBpbnN0YW5jZVxuICB9XG5cbiAgcHJpdmF0ZSBjb25zdHJ1Y3Rvcihjb25maWc6IExvZ2dlckNvbmZpZykge1xuICAgIHN1cGVyKGNvbmZpZy5sZXZlbClcbiAgICB0aGlzLndyaXRlcnMgPSBjb25maWcud3JpdGVycyB8fCBbXVxuICB9XG5cbiAgY3JlYXRlTm9kZShsZXZlbDogTG9nTGV2ZWwsIF9wYXJlbnQ6IExvZ05vZGUsIG9wdHM6IENyZWF0ZU9wdHMpIHtcbiAgICByZXR1cm4gbmV3IExvZ0VudHJ5KHsgbGV2ZWwsIHBhcmVudDogdGhpcywgb3B0czogcmVzb2x2ZVBhcmFtKG9wdHMpIH0pXG4gIH1cblxuICBvbkdyYXBoQ2hhbmdlKGVudHJ5OiBMb2dFbnRyeSkge1xuICAgIHRoaXMud3JpdGVycy5mb3JFYWNoKHdyaXRlciA9PiB3cml0ZXIub25HcmFwaENoYW5nZShlbnRyeSwgdGhpcykpXG4gIH1cblxuICBnZXRMb2dFbnRyaWVzKCk6IExvZ0VudHJ5W10ge1xuICAgIHJldHVybiBnZXRDaGlsZEVudHJpZXModGhpcykuZmlsdGVyKGVudHJ5ID0+ICFlbnRyeS5mcm9tU3RkU3RyZWFtKCkpXG4gIH1cblxuICBmaWx0ZXJCeVNlY3Rpb24oc2VjdGlvbjogc3RyaW5nKTogTG9nRW50cnlbXSB7XG4gICAgcmV0dXJuIGdldENoaWxkRW50cmllcyh0aGlzKS5maWx0ZXIoZW50cnkgPT4gZW50cnkub3B0cy5zZWN0aW9uID09PSBzZWN0aW9uKVxuICB9XG5cbiAgaGVhZGVyKFxuICAgIHsgY29tbWFuZCwgZW1vamksIGxldmVsID0gTG9nTGV2ZWwuaW5mbyB9OiB7IGNvbW1hbmQ6IHN0cmluZywgZW1vamk/OiBzdHJpbmcsIGxldmVsPzogTG9nTGV2ZWwgfSxcbiAgKTogTG9nRW50cnkge1xuICAgIGNvbnN0IG1zZyA9IGNvbWJpbmUoW1xuICAgICAgW2NoYWxrLmJvbGQubWFnZW50YShjb21tYW5kKV0sXG4gICAgICBbZW1vamkgPyBcIiBcIiArIG5vZGVFbW9qaS5nZXQoZW1vamkpIDogXCJcIl0sXG4gICAgICBbXCJcXG5cIl0sXG4gICAgXSlcbiAgICBjb25zdCBsdmxTdHIgPSBMb2dMZXZlbFtsZXZlbF1cbiAgICByZXR1cm4gdGhpc1tsdmxTdHJdKG1zZylcbiAgfVxuXG4gIGZpbmlzaChcbiAgICB7IHNob3dEdXJhdGlvbiA9IHRydWUsIGxldmVsID0gTG9nTGV2ZWwuaW5mbyB9OiB7IHNob3dEdXJhdGlvbj86IGJvb2xlYW4sIGxldmVsPzogTG9nTGV2ZWwgfSA9IHt9LFxuICApOiBMb2dFbnRyeSB7XG4gICAgY29uc3QgbXNnID0gY29tYmluZShbXG4gICAgICBbYFxcbiR7bm9kZUVtb2ppLmdldChcInNwYXJrbGVzXCIpfSAgRmluaXNoZWRgXSxcbiAgICAgIFtzaG93RHVyYXRpb24gPyBgIGluICR7Y2hhbGsuYm9sZCh0aGlzLmdldER1cmF0aW9uKCkgKyBcInNcIil9YCA6IFwiIVwiXSxcbiAgICAgIFtcIlxcblwiXSxcbiAgICBdKVxuICAgIGNvbnN0IGx2bFN0ciA9IExvZ0xldmVsW2xldmVsXVxuICAgIHJldHVybiB0aGlzW2x2bFN0cl0obXNnKVxuICB9XG5cbiAgc3RvcCgpOiB2b2lkIHtcbiAgICB0aGlzLmdldExvZ0VudHJpZXMoKS5mb3JFYWNoKGUgPT4gZS5zdG9wKCkpXG4gICAgdGhpcy53cml0ZXJzLmZvckVhY2god3JpdGVyID0+IHdyaXRlci5zdG9wKCkpXG4gIH1cblxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TG9nZ2VyKCkge1xuICByZXR1cm4gTG9nZ2VyLmdldEluc3RhbmNlKClcbn1cbiJdfQ== diff --git a/garden-service/build/logger/renderers.d.ts b/garden-service/build/logger/renderers.d.ts new file mode 100644 index 00000000000..cbed51fabec --- /dev/null +++ b/garden-service/build/logger/renderers.d.ts @@ -0,0 +1,19 @@ +import { LogEntry } from "./log-entry"; +export declare type ToRender = string | ((...args: any[]) => string); +export declare type Renderer = [ToRender, any[]] | ToRender[]; +export declare type Renderers = Renderer[]; +export declare const msgStyle: (s: string) => string; +export declare const errorStyle: import("chalk").Chalk & { + supportsColor: import("chalk").ColorSupport; +}; +export declare function combine(renderers: Renderers): string; +/*** RENDERERS ***/ +export declare function leftPad(entry: LogEntry): string; +export declare function renderEmoji(entry: LogEntry): string; +export declare function renderError(entry: LogEntry): string | string[]; +export declare function renderSymbol(entry: LogEntry): string; +export declare function renderMsg(entry: LogEntry): string; +export declare function renderSection(entry: LogEntry): string; +export declare function renderDuration(entry: LogEntry): string; +export declare function formatForTerminal(entry: LogEntry): string; +//# sourceMappingURL=renderers.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/renderers.js b/garden-service/build/logger/renderers.js new file mode 100644 index 00000000000..cb1ab102cfc --- /dev/null +++ b/garden-service/build/logger/renderers.js @@ -0,0 +1,125 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const logSymbols = require("log-symbols"); +const nodeEmoji = require("node-emoji"); +const yaml = require("js-yaml"); +const chalk_1 = require("chalk"); +const lodash_1 = require("lodash"); +const cliTruncate = require("cli-truncate"); +const stringWidth = require("string-width"); +const hasAnsi = require("has-ansi"); +/*** STYLE HELPERS ***/ +const SECTION_PREFIX_WIDTH = 25; +const cliPadEnd = (s, width) => { + const diff = width - stringWidth(s); + return diff <= 0 ? s : s + lodash_1.repeat(" ", diff); +}; +const truncateSection = (s) => cliTruncate(s, SECTION_PREFIX_WIDTH); +const sectionStyle = (s) => chalk_1.default.cyan.italic(cliPadEnd(truncateSection(s), SECTION_PREFIX_WIDTH)); +exports.msgStyle = (s) => hasAnsi(s) ? s : chalk_1.default.gray(s); +exports.errorStyle = chalk_1.default.red; +/*** RENDER HELPERS ***/ +function insertVal(out, idx, toRender, renderArgs) { + out[idx] = typeof toRender === "string" ? toRender : toRender(...renderArgs); + return out; +} +// Creates a chain of renderers that each receives the updated output array along with the provided parameters +function applyRenderers(renderers) { + const curried = renderers.map(([toRender, renderArgs], idx) => { + const args = [idx, toRender, renderArgs]; + // FIXME Currying like this throws "Expected 0-4 arguments, but got 0 or more" + return lodash_1.curryRight(insertVal)(...args); + }); + return lodash_1.flow(curried); +} +function combine(renderers) { + const initOutput = []; + return applyRenderers(renderers)(initOutput).join(""); +} +exports.combine = combine; +/*** RENDERERS ***/ +function leftPad(entry) { + return lodash_1.padStart("", (entry.opts.indentationLevel || 0) * 3); +} +exports.leftPad = leftPad; +function renderEmoji(entry) { + const { emoji } = entry.opts; + if (emoji && nodeEmoji.hasEmoji(emoji)) { + return `${nodeEmoji.get(emoji)} `; + } + return ""; +} +exports.renderEmoji = renderEmoji; +function renderError(entry) { + const { msg, error } = entry.opts; + if (error) { + const { detail, message, stack } = error; + let out = stack || message; + if (!lodash_1.isEmpty(detail)) { + const kebabCasedDetail = lodash_1.reduce(detail, (acc, val, key) => { + acc[lodash_1.kebabCase(key)] = val; + return acc; + }, {}); + const yamlDetail = yaml.safeDump(kebabCasedDetail, { noRefs: true, skipInvalid: true }); + out += `\nError Details:\n${yamlDetail}`; + } + return out; + } + return msg || ""; +} +exports.renderError = renderError; +function renderSymbol(entry) { + const { symbol } = entry.opts; + if (symbol === "empty") { + return " "; + } + return symbol ? `${logSymbols[symbol]} ` : ""; +} +exports.renderSymbol = renderSymbol; +function renderMsg(entry) { + const { fromStdStream, msg, status } = entry.opts; + if (fromStdStream) { + return lodash_1.isArray(msg) ? msg.join(" ") : msg || ""; + } + const styleFn = status === "error" ? exports.errorStyle : exports.msgStyle; + if (lodash_1.isArray(msg)) { + // We apply the style function to each item (as opposed to the entire string) in case some + // part of the message already has a style + return msg.map(str => styleFn(str)).join(styleFn(" → ")); + } + return msg ? styleFn(msg) : ""; +} +exports.renderMsg = renderMsg; +function renderSection(entry) { + const { section } = entry.opts; + return section ? `${sectionStyle(section)} → ` : ""; +} +exports.renderSection = renderSection; +function renderDuration(entry) { + const { showDuration = false } = entry.opts; + return showDuration + ? exports.msgStyle(` (finished in ${entry.getDuration()}s)`) + : ""; +} +exports.renderDuration = renderDuration; +function formatForTerminal(entry) { + return combine([ + [leftPad, [entry]], + [renderSymbol, [entry]], + [renderSection, [entry]], + [renderEmoji, [entry]], + [renderMsg, [entry]], + [renderDuration, [entry]], + ["\n"], + ]); +} +exports.formatForTerminal = formatForTerminal; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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LENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUE7QUFDckQsQ0FBQztBQUhELHNDQUdDO0FBRUQsU0FBZ0IsY0FBYyxDQUFDLEtBQWU7SUFDNUMsTUFBTSxFQUFFLFlBQVksR0FBRyxLQUFLLEVBQUUsR0FBRyxLQUFLLENBQUMsSUFBSSxDQUFBO0lBQzNDLE9BQU8sWUFBWTtRQUNqQixDQUFDLENBQUMsZ0JBQVEsQ0FBQyxpQkFBaUIsS0FBSyxDQUFDLFdBQVcsRUFBRSxJQUFJLENBQUM7UUFDcEQsQ0FBQyxDQUFDLEVBQUUsQ0FBQTtBQUNSLENBQUM7QUFMRCx3Q0FLQztBQUVELFNBQWdCLGlCQUFpQixDQUFDLEtBQWU7SUFDL0MsT0FBTyxPQUFPLENBQUM7UUFDYixDQUFDLE9BQU8sRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ2xCLENBQUMsWUFBWSxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDdkIsQ0FBQyxhQUFhLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN4QixDQUFDLFdBQVcsRUFBRSxDQUFDLEtBQUssQ0FBQyxDQUFDO1FBQ3RCLENBQUMsU0FBUyxFQUFFLENBQUMsS0FBSyxDQUFDLENBQUM7UUFDcEIsQ0FBQyxjQUFjLEVBQUUsQ0FBQyxLQUFLLENBQUMsQ0FBQztRQUN6QixDQUFDLElBQUksQ0FBQztLQUNQLENBQUMsQ0FBQTtBQUNKLENBQUM7QUFWRCw4Q0FVQyIsImZpbGUiOiJsb2dnZXIvcmVuZGVyZXJzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIGxvZ1N5bWJvbHMgZnJvbSBcImxvZy1zeW1ib2xzXCJcbmltcG9ydCAqIGFzIG5vZGVFbW9qaSBmcm9tIFwibm9kZS1lbW9qaVwiXG5pbXBvcnQgKiBhcyB5YW1sIGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHtcbiAgY3VycnlSaWdodCxcbiAgZmxvdyxcbiAgaXNBcnJheSxcbiAgaXNFbXB0eSxcbiAgcGFkU3RhcnQsXG4gIHJlZHVjZSxcbiAga2ViYWJDYXNlLFxuICByZXBlYXQsXG59IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IGNsaVRydW5jYXRlID0gcmVxdWlyZShcImNsaS10cnVuY2F0ZVwiKVxuaW1wb3J0IHN0cmluZ1dpZHRoID0gcmVxdWlyZShcInN0cmluZy13aWR0aFwiKVxuaW1wb3J0IGhhc0Fuc2kgPSByZXF1aXJlKFwiaGFzLWFuc2lcIilcblxuaW1wb3J0IHsgTG9nRW50cnkgfSBmcm9tIFwiLi9sb2ctZW50cnlcIlxuXG5leHBvcnQgdHlwZSBUb1JlbmRlciA9IHN0cmluZyB8ICgoLi4uYXJnczogYW55W10pID0+IHN0cmluZylcbmV4cG9ydCB0eXBlIFJlbmRlcmVyID0gW1RvUmVuZGVyLCBhbnlbXV0gfCBUb1JlbmRlcltdXG5leHBvcnQgdHlwZSBSZW5kZXJlcnMgPSBSZW5kZXJlcltdXG5cbi8qKiogU1RZTEUgSEVMUEVSUyAqKiovXG5cbmNvbnN0IFNFQ1RJT05fUFJFRklYX1dJRFRIID0gMjVcbmNvbnN0IGNsaVBhZEVuZCA9IChzOiBzdHJpbmcsIHdpZHRoOiBudW1iZXIpOiBzdHJpbmcgPT4ge1xuICBjb25zdCBkaWZmID0gd2lkdGggLSBzdHJpbmdXaWR0aChzKVxuICByZXR1cm4gZGlmZiA8PSAwID8gcyA6IHMgKyByZXBlYXQoXCIgXCIsIGRpZmYpXG59XG5jb25zdCB0cnVuY2F0ZVNlY3Rpb24gPSAoczogc3RyaW5nKSA9PiBjbGlUcnVuY2F0ZShzLCBTRUNUSU9OX1BSRUZJWF9XSURUSClcbmNvbnN0IHNlY3Rpb25TdHlsZSA9IChzOiBzdHJpbmcpID0+IGNoYWxrLmN5YW4uaXRhbGljKGNsaVBhZEVuZCh0cnVuY2F0ZVNlY3Rpb24ocyksIFNFQ1RJT05fUFJFRklYX1dJRFRIKSlcbmV4cG9ydCBjb25zdCBtc2dTdHlsZSA9IChzOiBzdHJpbmcpID0+IGhhc0Fuc2kocykgPyBzIDogY2hhbGsuZ3JheShzKVxuZXhwb3J0IGNvbnN0IGVycm9yU3R5bGUgPSBjaGFsay5yZWRcblxuLyoqKiBSRU5ERVIgSEVMUEVSUyAqKiovXG5mdW5jdGlvbiBpbnNlcnRWYWwob3V0OiBzdHJpbmdbXSwgaWR4OiBudW1iZXIsIHRvUmVuZGVyOiBGdW5jdGlvbiB8IHN0cmluZywgcmVuZGVyQXJnczogYW55W10pOiBzdHJpbmdbXSB7XG4gIG91dFtpZHhdID0gdHlwZW9mIHRvUmVuZGVyID09PSBcInN0cmluZ1wiID8gdG9SZW5kZXIgOiB0b1JlbmRlciguLi5yZW5kZXJBcmdzKVxuICByZXR1cm4gb3V0XG59XG5cbi8vIENyZWF0ZXMgYSBjaGFpbiBvZiByZW5kZXJlcnMgdGhhdCBlYWNoIHJlY2VpdmVzIHRoZSB1cGRhdGVkIG91dHB1dCBhcnJheSBhbG9uZyB3aXRoIHRoZSBwcm92aWRlZCBwYXJhbWV0ZXJzXG5mdW5jdGlvbiBhcHBseVJlbmRlcmVycyhyZW5kZXJlcnM6IFJlbmRlcmVycyk6IEZ1bmN0aW9uIHtcbiAgY29uc3QgY3VycmllZCA9IHJlbmRlcmVycy5tYXAoKFt0b1JlbmRlciwgcmVuZGVyQXJnc106IFJlbmRlcmVyLCBpZHg6IG51bWJlcikgPT4ge1xuICAgIGNvbnN0IGFyZ3MgPSBbaWR4LCB0b1JlbmRlciwgcmVuZGVyQXJnc11cbiAgICAvLyBGSVhNRSBDdXJyeWluZyBsaWtlIHRoaXMgdGhyb3dzIFwiRXhwZWN0ZWQgMC00IGFyZ3VtZW50cywgYnV0IGdvdCAwIG9yIG1vcmVcIlxuICAgIHJldHVybiAoPGFueT5jdXJyeVJpZ2h0KShpbnNlcnRWYWwpKC4uLmFyZ3MpXG4gIH0pXG4gIHJldHVybiBmbG93KGN1cnJpZWQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBjb21iaW5lKHJlbmRlcmVyczogUmVuZGVyZXJzKTogc3RyaW5nIHtcbiAgY29uc3QgaW5pdE91dHB1dCA9IFtdXG4gIHJldHVybiBhcHBseVJlbmRlcmVycyhyZW5kZXJlcnMpKGluaXRPdXRwdXQpLmpvaW4oXCJcIilcbn1cblxuLyoqKiBSRU5ERVJFUlMgKioqL1xuZXhwb3J0IGZ1bmN0aW9uIGxlZnRQYWQoZW50cnk6IExvZ0VudHJ5KTogc3RyaW5nIHtcbiAgcmV0dXJuIHBhZFN0YXJ0KFwiXCIsIChlbnRyeS5vcHRzLmluZGVudGF0aW9uTGV2ZWwgfHwgMCkgKiAzKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyRW1vamkoZW50cnk6IExvZ0VudHJ5KTogc3RyaW5nIHtcbiAgY29uc3QgeyBlbW9qaSB9ID0gZW50cnkub3B0c1xuICBpZiAoZW1vamkgJiYgbm9kZUVtb2ppLmhhc0Vtb2ppKGVtb2ppKSkge1xuICAgIHJldHVybiBgJHtub2RlRW1vamkuZ2V0KGVtb2ppKX0gIGBcbiAgfVxuICByZXR1cm4gXCJcIlxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVuZGVyRXJyb3IoZW50cnk6IExvZ0VudHJ5KSB7XG4gIGNvbnN0IHsgbXNnLCBlcnJvciB9ID0gZW50cnkub3B0c1xuICBpZiAoZXJyb3IpIHtcbiAgICBjb25zdCB7IGRldGFpbCwgbWVzc2FnZSwgc3RhY2sgfSA9IGVycm9yXG4gICAgbGV0IG91dCA9IHN0YWNrIHx8IG1lc3NhZ2VcbiAgICBpZiAoIWlzRW1wdHkoZGV0YWlsKSkge1xuICAgICAgY29uc3Qga2ViYWJDYXNlZERldGFpbCA9IHJlZHVjZShkZXRhaWwsIChhY2MsIHZhbCwga2V5KSA9PiB7XG4gICAgICAgIGFjY1trZWJhYkNhc2Uoa2V5KV0gPSB2YWxcbiAgICAgICAgcmV0dXJuIGFjY1xuICAgICAgfSwge30pXG4gICAgICBjb25zdCB5YW1sRGV0YWlsID0geWFtbC5zYWZlRHVtcChrZWJhYkNhc2VkRGV0YWlsLCB7IG5vUmVmczogdHJ1ZSwgc2tpcEludmFsaWQ6IHRydWUgfSlcbiAgICAgIG91dCArPSBgXFxuRXJyb3IgRGV0YWlsczpcXG4ke3lhbWxEZXRhaWx9YFxuICAgIH1cbiAgICByZXR1cm4gb3V0XG4gIH1cbiAgcmV0dXJuIG1zZyB8fCBcIlwiXG59XG5cbmV4cG9ydCBmdW5jdGlvbiByZW5kZXJTeW1ib2woZW50cnk6IExvZ0VudHJ5KTogc3RyaW5nIHtcbiAgY29uc3QgeyBzeW1ib2wgfSA9IGVudHJ5Lm9wdHNcbiAgaWYgKHN5bWJvbCA9PT0gXCJlbXB0eVwiKSB7XG4gICAgcmV0dXJuIFwiIFwiXG4gIH1cbiAgcmV0dXJuIHN5bWJvbCA/IGAke2xvZ1N5bWJvbHNbc3ltYm9sXX0gYCA6IFwiXCJcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlck1zZyhlbnRyeTogTG9nRW50cnkpOiBzdHJpbmcge1xuICBjb25zdCB7IGZyb21TdGRTdHJlYW0sIG1zZywgc3RhdHVzIH0gPSBlbnRyeS5vcHRzXG5cbiAgaWYgKGZyb21TdGRTdHJlYW0pIHtcbiAgICByZXR1cm4gaXNBcnJheShtc2cpID8gbXNnLmpvaW4oXCIgXCIpIDogbXNnIHx8IFwiXCJcbiAgfVxuXG4gIGNvbnN0IHN0eWxlRm4gPSBzdGF0dXMgPT09IFwiZXJyb3JcIiA/IGVycm9yU3R5bGUgOiBtc2dTdHlsZVxuICBpZiAoaXNBcnJheShtc2cpKSB7XG4gICAgLy8gV2UgYXBwbHkgdGhlIHN0eWxlIGZ1bmN0aW9uIHRvIGVhY2ggaXRlbSAoYXMgb3Bwb3NlZCB0byB0aGUgZW50aXJlIHN0cmluZykgaW4gY2FzZSBzb21lXG4gICAgLy8gcGFydCBvZiB0aGUgbWVzc2FnZSBhbHJlYWR5IGhhcyBhIHN0eWxlXG4gICAgcmV0dXJuIG1zZy5tYXAoc3RyID0+IHN0eWxlRm4oc3RyKSkuam9pbihzdHlsZUZuKFwiIOKGkiBcIikpXG4gIH1cbiAgcmV0dXJuIG1zZyA/IHN0eWxlRm4obXNnKSA6IFwiXCJcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlclNlY3Rpb24oZW50cnk6IExvZ0VudHJ5KTogc3RyaW5nIHtcbiAgY29uc3QgeyBzZWN0aW9uIH0gPSBlbnRyeS5vcHRzXG4gIHJldHVybiBzZWN0aW9uID8gYCR7c2VjdGlvblN0eWxlKHNlY3Rpb24pfSDihpIgYCA6IFwiXCJcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIHJlbmRlckR1cmF0aW9uKGVudHJ5OiBMb2dFbnRyeSk6IHN0cmluZyB7XG4gIGNvbnN0IHsgc2hvd0R1cmF0aW9uID0gZmFsc2UgfSA9IGVudHJ5Lm9wdHNcbiAgcmV0dXJuIHNob3dEdXJhdGlvblxuICAgID8gbXNnU3R5bGUoYCAoZmluaXNoZWQgaW4gJHtlbnRyeS5nZXREdXJhdGlvbigpfXMpYClcbiAgICA6IFwiXCJcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZvcm1hdEZvclRlcm1pbmFsKGVudHJ5OiBMb2dFbnRyeSk6IHN0cmluZyB7XG4gIHJldHVybiBjb21iaW5lKFtcbiAgICBbbGVmdFBhZCwgW2VudHJ5XV0sXG4gICAgW3JlbmRlclN5bWJvbCwgW2VudHJ5XV0sXG4gICAgW3JlbmRlclNlY3Rpb24sIFtlbnRyeV1dLFxuICAgIFtyZW5kZXJFbW9qaSwgW2VudHJ5XV0sXG4gICAgW3JlbmRlck1zZywgW2VudHJ5XV0sXG4gICAgW3JlbmRlckR1cmF0aW9uLCBbZW50cnldXSxcbiAgICBbXCJcXG5cIl0sXG4gIF0pXG59XG4iXX0= diff --git a/garden-service/build/logger/util.d.ts b/garden-service/build/logger/util.d.ts new file mode 100644 index 00000000000..6747a9c741c --- /dev/null +++ b/garden-service/build/logger/util.d.ts @@ -0,0 +1,25 @@ +/// +import { LogNode, LogLevel } from "./log-node"; +import { LogEntry, CreateOpts } from "./log-entry"; +export interface Node { + children: any[]; +} +export declare type LogOptsResolvers = { + [K in keyof CreateOpts]?: Function; +}; +export declare type ProcessNode = (node: T) => boolean; +export declare function getChildNodes(node: T | U): U[]; +export declare function getChildEntries(node: LogNode): LogEntry[]; +export declare function findLogNode(node: LogNode, predicate: ProcessNode>): T | void; +/** + * Intercepts the write method of a WriteableStream and calls the provided callback on the + * string to write (or optionally applies the string to the write method) + * Returns a function which sets the write back to default. + * + * Used e.g. by FancyLogger so that writes from other sources can be intercepted + * and pushed to the log stack. + */ +export declare function interceptStream(stream: NodeJS.WriteStream, callback: Function): () => void; +export declare function getTerminalWidth(stream?: NodeJS.WriteStream): number; +export declare function validate(level: LogLevel, entry: LogEntry): boolean; +//# sourceMappingURL=util.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/util.js b/garden-service/build/logger/util.js new file mode 100644 index 00000000000..f70737ce859 --- /dev/null +++ b/garden-service/build/logger/util.js @@ -0,0 +1,87 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +function traverseChildren(node, cb) { + const children = node.children; + for (let idx = 0; idx < children.length; idx++) { + const proceed = cb(children[idx]); + if (!proceed) { + return; + } + traverseChildren(children[idx], cb); + } +} +// Parent (T|U) can have different type then child (U) +function getChildNodes(node) { + let childNodes = []; + traverseChildren(node, child => { + childNodes.push(child); + return true; + }); + return childNodes; +} +exports.getChildNodes = getChildNodes; +function getChildEntries(node) { + return getChildNodes(node); +} +exports.getChildEntries = getChildEntries; +function findLogNode(node, predicate) { + let found; + traverseChildren(node, entry => { + if (predicate(entry)) { + found = entry; + return false; + } + return true; + }); + return found; +} +exports.findLogNode = findLogNode; +/** + * Intercepts the write method of a WriteableStream and calls the provided callback on the + * string to write (or optionally applies the string to the write method) + * Returns a function which sets the write back to default. + * + * Used e.g. by FancyLogger so that writes from other sources can be intercepted + * and pushed to the log stack. + */ +function interceptStream(stream, callback) { + const prevWrite = stream.write; + stream.write = (write => (string, encoding, cb, extraParam) => { + if (extraParam && extraParam.noIntercept) { + const args = [string, encoding, cb]; + return write.apply(stream, args); + } + callback(string); + return true; + })(stream.write); + const restore = () => { + stream.write = prevWrite; + }; + return restore; +} +exports.interceptStream = interceptStream; +function getTerminalWidth(stream = process.stdout) { + const columns = (stream || {}).columns; + if (!columns) { + return 80; + } + // Windows appears to wrap a character early + if (process.platform === "win32") { + return columns - 1; + } + return columns; +} +exports.getTerminalWidth = getTerminalWidth; +function validate(level, entry) { + return level >= entry.level && entry.opts.msg !== undefined; +} +exports.validate = validate; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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TyxFQUFFO1FBQ2hDLE9BQU8sT0FBTyxHQUFHLENBQUMsQ0FBQTtLQUNuQjtJQUVELE9BQU8sT0FBTyxDQUFBO0FBQ2hCLENBQUM7QUFiRCw0Q0FhQztBQUVELFNBQWdCLFFBQVEsQ0FBQyxLQUFlLEVBQUUsS0FBZTtJQUN2RCxPQUFPLEtBQUssSUFBSSxLQUFLLENBQUMsS0FBSyxJQUFJLEtBQUssQ0FBQyxJQUFJLENBQUMsR0FBRyxLQUFLLFNBQVMsQ0FBQTtBQUM3RCxDQUFDO0FBRkQsNEJBRUMiLCJmaWxlIjoibG9nZ2VyL3V0aWwuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgTG9nTm9kZSwgTG9nTGV2ZWwgfSBmcm9tIFwiLi9sb2ctbm9kZVwiXG5pbXBvcnQgeyBMb2dFbnRyeSwgQ3JlYXRlT3B0cyB9IGZyb20gXCIuL2xvZy1lbnRyeVwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgTm9kZSB7XG4gIGNoaWxkcmVuOiBhbnlbXVxufVxuXG5leHBvcnQgdHlwZSBMb2dPcHRzUmVzb2x2ZXJzID0geyBbSyBpbiBrZXlvZiBDcmVhdGVPcHRzXT86IEZ1bmN0aW9uIH1cblxuZXhwb3J0IHR5cGUgUHJvY2Vzc05vZGU8VCBleHRlbmRzIE5vZGUgPSBOb2RlPiA9IChub2RlOiBUKSA9PiBib29sZWFuXG5cbmZ1bmN0aW9uIHRyYXZlcnNlQ2hpbGRyZW48VCBleHRlbmRzIE5vZGUsIFUgZXh0ZW5kcyBOb2RlPihub2RlOiBUIHwgVSwgY2I6IFByb2Nlc3NOb2RlPFU+KSB7XG4gIGNvbnN0IGNoaWxkcmVuID0gbm9kZS5jaGlsZHJlblxuICBmb3IgKGxldCBpZHggPSAwOyBpZHggPCBjaGlsZHJlbi5sZW5ndGg7IGlkeCsrKSB7XG4gICAgY29uc3QgcHJvY2VlZCA9IGNiKGNoaWxkcmVuW2lkeF0pXG4gICAgaWYgKCFwcm9jZWVkKSB7XG4gICAgICByZXR1cm5cbiAgICB9XG4gICAgdHJhdmVyc2VDaGlsZHJlbihjaGlsZHJlbltpZHhdLCBjYilcbiAgfVxufVxuXG4vLyBQYXJlbnQgKFR8VSkgY2FuIGhhdmUgZGlmZmVyZW50IHR5cGUgdGhlbiBjaGlsZCAoVSlcbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGlsZE5vZGVzPFQgZXh0ZW5kcyBOb2RlLCBVIGV4dGVuZHMgTm9kZT4obm9kZTogVCB8IFUpOiBVW10ge1xuICBsZXQgY2hpbGROb2RlczogVVtdID0gW11cbiAgdHJhdmVyc2VDaGlsZHJlbjxULCBVPihub2RlLCBjaGlsZCA9PiB7XG4gICAgY2hpbGROb2Rlcy5wdXNoKGNoaWxkKVxuICAgIHJldHVybiB0cnVlXG4gIH0pXG4gIHJldHVybiBjaGlsZE5vZGVzXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRDaGlsZEVudHJpZXMobm9kZTogTG9nTm9kZSk6IExvZ0VudHJ5W10ge1xuICByZXR1cm4gZ2V0Q2hpbGROb2RlczxMb2dOb2RlLCBMb2dFbnRyeT4obm9kZSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGZpbmRMb2dOb2RlPFQ+KG5vZGU6IExvZ05vZGU8VD4sIHByZWRpY2F0ZTogUHJvY2Vzc05vZGU8TG9nTm9kZTxUPj4pOiBUIHwgdm9pZCB7XG4gIGxldCBmb3VuZFxuICB0cmF2ZXJzZUNoaWxkcmVuPExvZ05vZGU8VD4sIExvZ05vZGU8VD4+KG5vZGUsIGVudHJ5ID0+IHtcbiAgICBpZiAocHJlZGljYXRlKGVudHJ5KSkge1xuICAgICAgZm91bmQgPSBlbnRyeVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICAgIHJldHVybiB0cnVlXG4gIH0pXG4gIHJldHVybiBmb3VuZFxufVxuXG5pbnRlcmZhY2UgU3RyZWFtV3JpdGVFeHRyYVBhcmFtIHtcbiAgbm9JbnRlcmNlcHQ/OiBib29sZWFuXG59XG5cbi8qKlxuICogSW50ZXJjZXB0cyB0aGUgd3JpdGUgbWV0aG9kIG9mIGEgV3JpdGVhYmxlU3RyZWFtIGFuZCBjYWxscyB0aGUgcHJvdmlkZWQgY2FsbGJhY2sgb24gdGhlXG4gKiBzdHJpbmcgdG8gd3JpdGUgKG9yIG9wdGlvbmFsbHkgYXBwbGllcyB0aGUgc3RyaW5nIHRvIHRoZSB3cml0ZSBtZXRob2QpXG4gKiBSZXR1cm5zIGEgZnVuY3Rpb24gd2hpY2ggc2V0cyB0aGUgd3JpdGUgYmFjayB0byBkZWZhdWx0LlxuICpcbiAqIFVzZWQgZS5nLiBieSBGYW5jeUxvZ2dlciBzbyB0aGF0IHdyaXRlcyBmcm9tIG90aGVyIHNvdXJjZXMgY2FuIGJlIGludGVyY2VwdGVkXG4gKiBhbmQgcHVzaGVkIHRvIHRoZSBsb2cgc3RhY2suXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpbnRlcmNlcHRTdHJlYW0oc3RyZWFtOiBOb2RlSlMuV3JpdGVTdHJlYW0sIGNhbGxiYWNrOiBGdW5jdGlvbikge1xuICBjb25zdCBwcmV2V3JpdGUgPSBzdHJlYW0ud3JpdGVcblxuICBzdHJlYW0ud3JpdGUgPSAod3JpdGUgPT5cbiAgICAoXG4gICAgICBzdHJpbmc6IHN0cmluZyxcbiAgICAgIGVuY29kaW5nPzogc3RyaW5nLFxuICAgICAgY2I/OiBGdW5jdGlvbixcbiAgICAgIGV4dHJhUGFyYW0/OiBTdHJlYW1Xcml0ZUV4dHJhUGFyYW0sXG4gICAgKTogYm9vbGVhbiA9PiB7XG4gICAgICBpZiAoZXh0cmFQYXJhbSAmJiBleHRyYVBhcmFtLm5vSW50ZXJjZXB0KSB7XG4gICAgICAgIGNvbnN0IGFyZ3MgPSBbc3RyaW5nLCBlbmNvZGluZywgY2JdXG4gICAgICAgIHJldHVybiB3cml0ZS5hcHBseShzdHJlYW0sIGFyZ3MpXG4gICAgICB9XG4gICAgICBjYWxsYmFjayhzdHJpbmcpXG4gICAgICByZXR1cm4gdHJ1ZVxuICAgIH0pKHN0cmVhbS53cml0ZSkgYXMgYW55XG5cbiAgY29uc3QgcmVzdG9yZSA9ICgpID0+IHtcbiAgICBzdHJlYW0ud3JpdGUgPSBwcmV2V3JpdGVcbiAgfVxuXG4gIHJldHVybiByZXN0b3JlXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnZXRUZXJtaW5hbFdpZHRoKHN0cmVhbTogTm9kZUpTLldyaXRlU3RyZWFtID0gcHJvY2Vzcy5zdGRvdXQpIHtcbiAgY29uc3QgY29sdW1ucyA9IChzdHJlYW0gfHwge30pLmNvbHVtbnNcblxuICBpZiAoIWNvbHVtbnMpIHtcbiAgICByZXR1cm4gODBcbiAgfVxuXG4gIC8vIFdpbmRvd3MgYXBwZWFycyB0byB3cmFwIGEgY2hhcmFjdGVyIGVhcmx5XG4gIGlmIChwcm9jZXNzLnBsYXRmb3JtID09PSBcIndpbjMyXCIpIHtcbiAgICByZXR1cm4gY29sdW1ucyAtIDFcbiAgfVxuXG4gIHJldHVybiBjb2x1bW5zXG59XG5cbmV4cG9ydCBmdW5jdGlvbiB2YWxpZGF0ZShsZXZlbDogTG9nTGV2ZWwsIGVudHJ5OiBMb2dFbnRyeSk6IGJvb2xlYW4ge1xuICByZXR1cm4gbGV2ZWwgPj0gZW50cnkubGV2ZWwgJiYgZW50cnkub3B0cy5tc2cgIT09IHVuZGVmaW5lZFxufVxuIl19 diff --git a/garden-service/build/logger/writers/base.d.ts b/garden-service/build/logger/writers/base.d.ts new file mode 100644 index 00000000000..5e11a42f72e --- /dev/null +++ b/garden-service/build/logger/writers/base.d.ts @@ -0,0 +1,14 @@ +import { LogLevel } from "../log-node"; +import { LogEntry } from "../log-entry"; +import { Logger } from "../logger"; +export interface WriterConfig { + level?: LogLevel; +} +export declare abstract class Writer { + level: LogLevel | undefined; + constructor({ level }?: WriterConfig); + abstract render(...args: any[]): string | string[] | null; + abstract onGraphChange(entry: LogEntry, logger: Logger): void; + abstract stop(): void; +} +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/writers/base.js b/garden-service/build/logger/writers/base.js new file mode 100644 index 00000000000..6a6de548bed --- /dev/null +++ b/garden-service/build/logger/writers/base.js @@ -0,0 +1,17 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +class Writer { + constructor({ level } = {}) { + this.level = level; + } +} +exports.Writer = Writer; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxvZ2dlci93cml0ZXJzL2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFVSCxNQUFzQixNQUFNO0lBRzFCLFlBQVksRUFBRSxLQUFLLEtBQW1CLEVBQUU7UUFDdEMsSUFBSSxDQUFDLEtBQUssR0FBRyxLQUFLLENBQUE7SUFDcEIsQ0FBQztDQUtGO0FBVkQsd0JBVUMiLCJmaWxlIjoibG9nZ2VyL3dyaXRlcnMvYmFzZS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBMb2dMZXZlbCB9IGZyb20gXCIuLi9sb2ctbm9kZVwiXG5pbXBvcnQgeyBMb2dFbnRyeSB9IGZyb20gXCIuLi9sb2ctZW50cnlcIlxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIi4uL2xvZ2dlclwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgV3JpdGVyQ29uZmlnIHtcbiAgbGV2ZWw/OiBMb2dMZXZlbFxufVxuXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgV3JpdGVyIHtcbiAgcHVibGljIGxldmVsOiBMb2dMZXZlbCB8IHVuZGVmaW5lZFxuXG4gIGNvbnN0cnVjdG9yKHsgbGV2ZWwgfTogV3JpdGVyQ29uZmlnID0ge30pIHtcbiAgICB0aGlzLmxldmVsID0gbGV2ZWxcbiAgfVxuXG4gIGFic3RyYWN0IHJlbmRlciguLi5hcmdzKTogc3RyaW5nIHwgc3RyaW5nW10gfCBudWxsXG4gIGFic3RyYWN0IG9uR3JhcGhDaGFuZ2UoZW50cnk6IExvZ0VudHJ5LCBsb2dnZXI6IExvZ2dlcik6IHZvaWRcbiAgYWJzdHJhY3Qgc3RvcCgpOiB2b2lkXG59XG4iXX0= diff --git a/garden-service/build/logger/writers/basic-terminal-writer.d.ts b/garden-service/build/logger/writers/basic-terminal-writer.d.ts new file mode 100644 index 00000000000..8d33a43faea --- /dev/null +++ b/garden-service/build/logger/writers/basic-terminal-writer.d.ts @@ -0,0 +1,11 @@ +import { LogLevel } from "../log-node"; +import { LogEntry } from "../log-entry"; +import { Logger } from "../logger"; +import { Writer } from "./base"; +export declare class BasicTerminalWriter extends Writer { + level: LogLevel; + render(entry: LogEntry, logger: Logger): string | null; + onGraphChange(entry: LogEntry, logger: Logger): void; + stop(): void; +} +//# sourceMappingURL=basic-terminal-writer.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/writers/basic-terminal-writer.js b/garden-service/build/logger/writers/basic-terminal-writer.js new file mode 100644 index 00000000000..e86c58fc4fc --- /dev/null +++ b/garden-service/build/logger/writers/basic-terminal-writer.js @@ -0,0 +1,31 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const renderers_1 = require("../renderers"); +const util_1 = require("../util"); +const base_1 = require("./base"); +class BasicTerminalWriter extends base_1.Writer { + render(entry, logger) { + const level = this.level || logger.level; + if (util_1.validate(level, entry)) { + return renderers_1.formatForTerminal(entry); + } + return null; + } + onGraphChange(entry, logger) { + const out = this.render(entry, logger); + if (out) { + process.stdout.write(out); + } + } + stop() { } +} +exports.BasicTerminalWriter = BasicTerminalWriter; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxvZ2dlci93cml0ZXJzL2Jhc2ljLXRlcm1pbmFsLXdyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUdILDRDQUFnRDtBQUdoRCxrQ0FBa0M7QUFDbEMsaUNBQStCO0FBRS9CLE1BQWEsbUJBQW9CLFNBQVEsYUFBTTtJQUc3QyxNQUFNLENBQUMsS0FBZSxFQUFFLE1BQWM7UUFDcEMsTUFBTSxLQUFLLEdBQUcsSUFBSSxDQUFDLEtBQUssSUFBSSxNQUFNLENBQUMsS0FBSyxDQUFBO1FBQ3hDLElBQUksZUFBUSxDQUFDLEtBQUssRUFBRSxLQUFLLENBQUMsRUFBRTtZQUMxQixPQUFPLDZCQUFpQixDQUFDLEtBQUssQ0FBQyxDQUFBO1NBQ2hDO1FBQ0QsT0FBTyxJQUFJLENBQUE7SUFDYixDQUFDO0lBRUQsYUFBYSxDQUFDLEtBQWUsRUFBRSxNQUFjO1FBQzNDLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxFQUFFLE1BQU0sQ0FBQyxDQUFBO1FBQ3RDLElBQUksR0FBRyxFQUFFO1lBQ1AsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUE7U0FDMUI7SUFDSCxDQUFDO0lBRUQsSUFBSSxLQUFLLENBQUM7Q0FDWDtBQW5CRCxrREFtQkMiLCJmaWxlIjoibG9nZ2VyL3dyaXRlcnMvYmFzaWMtdGVybWluYWwtd3JpdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IExvZ0xldmVsIH0gZnJvbSBcIi4uL2xvZy1ub2RlXCJcbmltcG9ydCB7IGZvcm1hdEZvclRlcm1pbmFsIH0gZnJvbSBcIi4uL3JlbmRlcmVyc1wiXG5pbXBvcnQgeyBMb2dFbnRyeSB9IGZyb20gXCIuLi9sb2ctZW50cnlcIlxuaW1wb3J0IHsgTG9nZ2VyIH0gZnJvbSBcIi4uL2xvZ2dlclwiXG5pbXBvcnQgeyB2YWxpZGF0ZSB9IGZyb20gXCIuLi91dGlsXCJcbmltcG9ydCB7IFdyaXRlciB9IGZyb20gXCIuL2Jhc2VcIlxuXG5leHBvcnQgY2xhc3MgQmFzaWNUZXJtaW5hbFdyaXRlciBleHRlbmRzIFdyaXRlciB7XG4gIHB1YmxpYyBsZXZlbDogTG9nTGV2ZWxcblxuICByZW5kZXIoZW50cnk6IExvZ0VudHJ5LCBsb2dnZXI6IExvZ2dlcik6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGxldmVsID0gdGhpcy5sZXZlbCB8fCBsb2dnZXIubGV2ZWxcbiAgICBpZiAodmFsaWRhdGUobGV2ZWwsIGVudHJ5KSkge1xuICAgICAgcmV0dXJuIGZvcm1hdEZvclRlcm1pbmFsKGVudHJ5KVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgb25HcmFwaENoYW5nZShlbnRyeTogTG9nRW50cnksIGxvZ2dlcjogTG9nZ2VyKSB7XG4gICAgY29uc3Qgb3V0ID0gdGhpcy5yZW5kZXIoZW50cnksIGxvZ2dlcilcbiAgICBpZiAob3V0KSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShvdXQpXG4gICAgfVxuICB9XG5cbiAgc3RvcCgpIHsgfVxufVxuIl19 diff --git a/garden-service/build/logger/writers/fancy-terminal-writer.d.ts b/garden-service/build/logger/writers/fancy-terminal-writer.d.ts new file mode 100644 index 00000000000..06d18d8730d --- /dev/null +++ b/garden-service/build/logger/writers/fancy-terminal-writer.d.ts @@ -0,0 +1,40 @@ +/// +import { LogEntry } from "../log-entry"; +import { Logger } from "../logger"; +import { LogLevel } from "../log-node"; +import { Writer, WriterConfig } from "./base"; +export declare type Coords = [number, number]; +export interface TerminalEntry { + key: string; + text: string; + lineNumber: number; + spinnerCoords?: Coords; +} +export interface TerminalEntryWithSpinner extends TerminalEntry { + spinnerCoords: Coords; +} +export interface CustomStream extends NodeJS.WriteStream { + cleanUp: Function; +} +export declare class FancyTerminalWriter extends Writer { + private spinners; + private intervalID; + private stream; + private prevOutput; + private lastInterceptAt; + private updatePending; + level: LogLevel; + constructor(config?: WriterConfig); + private initStream; + private spin; + private startLoop; + private stopLoop; + private tickSpinner; + private write; + private handleGraphChange; + toTerminalEntries(logger: Logger): TerminalEntry[]; + render(terminalEntries: TerminalEntry[]): string[]; + onGraphChange(logEntry: LogEntry, logger: Logger): void; + stop(): void; +} +//# sourceMappingURL=fancy-terminal-writer.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/writers/fancy-terminal-writer.js b/garden-service/build/logger/writers/fancy-terminal-writer.js new file mode 100644 index 00000000000..739bc6759d1 --- /dev/null +++ b/garden-service/build/logger/writers/fancy-terminal-writer.js @@ -0,0 +1,175 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const ansiEscapes = require("ansi-escapes"); +const cliCursor = require("cli-cursor"); +const elegantSpinner = require("elegant-spinner"); +const wrapAnsi = require("wrap-ansi"); +const chalk_1 = require("chalk"); +const renderers_1 = require("../renderers"); +const util_1 = require("../util"); +const base_1 = require("./base"); +const INTERVAL_MS = 60; +const THROTTLE_MS = 600; +const spinnerStyle = chalk_1.default.cyan; +class FancyTerminalWriter extends base_1.Writer { + constructor(config = {}) { + super(config); + this.intervalID = null; + this.spinners = {}; // Each entry has it's own spinner + this.prevOutput = []; + this.lastInterceptAt = null; + this.updatePending = false; + } + initStream(logger) { + // Create custom stream that calls write method with the 'noIntercept' option. + const stream = Object.assign({}, process.stdout, { write: (str, enc, cb) => process.stdout.write(str, enc, cb, { noIntercept: true }) }); + const onIntercept = msg => logger.info({ msg, fromStdStream: true }); + const restoreStreamFns = [ + util_1.interceptStream(process.stdout, onIntercept), + util_1.interceptStream(process.stderr, onIntercept), + ]; + stream.cleanUp = () => { + cliCursor.show(this.stream); + restoreStreamFns.forEach(restoreStream => restoreStream()); + }; + return stream; + } + spin(entries, totalLines) { + entries.forEach(e => { + let out = ""; + const [x, y] = e.spinnerCoords; + const termX = x === 0 ? x : x + 1; + const termY = -(totalLines - y - 1); + out += ansiEscapes.cursorSavePosition; + out += ansiEscapes.cursorTo(0); // Ensure cursor is to the left + out += ansiEscapes.cursorMove(termX, termY); + out += spinnerStyle(this.tickSpinner(e.key)); + out += ansiEscapes.cursorRestorePosition; + this.stream.write(out); + }); + } + startLoop(entries, totalLines) { + this.stopLoop(); + this.intervalID = setInterval(() => this.spin(entries, totalLines), INTERVAL_MS); + } + stopLoop() { + if (this.intervalID) { + clearInterval(this.intervalID); + this.intervalID = null; + } + } + tickSpinner(key) { + if (!this.spinners[key]) { + this.spinners[key] = elegantSpinner(); + } + return this.spinners[key](); + } + write(output, nextEntry) { + cliCursor.hide(this.stream); + const lineNumber = output.length >= this.prevOutput.length ? nextEntry.lineNumber : 0; + const nLinesToErase = this.prevOutput.length - lineNumber; + this.stream.write(ansiEscapes.eraseLines(nLinesToErase) + output.slice(lineNumber).join("\n")); + } + handleGraphChange(logEntry, logger, didWrite = false) { + this.updatePending = false; + // Suspend processing and write immediately if a lot of data is being intercepted, e.g. when user is typing in input + if (logEntry.fromStdStream() && !didWrite) { + const now = Date.now(); + const throttleProcessing = this.lastInterceptAt && (now - this.lastInterceptAt) < THROTTLE_MS; + this.lastInterceptAt = now; + if (throttleProcessing) { + this.stopLoop(); + this.stream.write(renderers_1.renderMsg(logEntry)); + this.updatePending = true; + // Resume processing if idle and original update is still pending + setTimeout(() => { + if (this.updatePending) { + this.handleGraphChange(logEntry, logger, true); + } + }, THROTTLE_MS); + return; + } + } + const terminalEntries = this.toTerminalEntries(logger); + const nextEntry = terminalEntries.find(e => e.key === logEntry.key); + // Nothing to do, e.g. because entry level is higher than writer level + if (!nextEntry) { + return; + } + const output = this.render(terminalEntries); + if (!didWrite) { + this.write(output, nextEntry); + } + const entriesWithspinner = terminalEntries.filter(e => e.spinnerCoords); + if (entriesWithspinner.length > 0) { + this.startLoop(entriesWithspinner, output.length); + } + else { + this.stopLoop(); + } + this.prevOutput = output; + } + toTerminalEntries(logger) { + const level = this.level || logger.level; + let currentLineNumber = 0; + return util_1.getChildEntries(logger) + .filter(entry => util_1.validate(level, entry)) + .reduce((acc, entry) => { + let spinnerFrame = ""; + let spinnerX; + let spinnerCoords; + if (entry.opts.status === "active") { + spinnerX = renderers_1.leftPad(entry).length; + spinnerFrame = this.tickSpinner(entry.key); + spinnerCoords = [spinnerX, currentLineNumber]; + } + else { + delete this.spinners[entry.key]; + } + const text = [entry] + .map(e => (e.fromStdStream() + ? renderers_1.renderMsg(e) + : renderers_1.formatForTerminal(e))) + .map(str => (spinnerFrame + ? `${str.slice(0, spinnerX)}${spinnerStyle(spinnerFrame)} ${str.slice(spinnerX)}` + : str)) + .map(str => wrapAnsi(str, util_1.getTerminalWidth(this.stream), { + trim: false, + hard: true, + wordWrap: false, + })) + .pop(); + acc.push({ + key: entry.key, + lineNumber: currentLineNumber, + spinnerCoords, + text, + }); + currentLineNumber += text.split("\n").length - 1; + return acc; + }, []); + } + render(terminalEntries) { + return terminalEntries.map(e => e.text).join("").split("\n"); + } + onGraphChange(logEntry, logger) { + if (!this.stream) { + this.stream = this.initStream(logger); + } + this.handleGraphChange(logEntry, logger, false); + } + stop() { + this.stopLoop(); + this.stream && this.stream.cleanUp(); + } +} +exports.FancyTerminalWriter = FancyTerminalWriter; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxvZ2dlci93cml0ZXJzL2ZhbmN5LXRlcm1pbmFsLXdyaXRlci50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOztBQUVILDRDQUEyQztBQUMzQyx3Q0FBdUM7QUFDdkMsa0RBQWlEO0FBQ2pELHNDQUFxQztBQUNyQyxpQ0FBeUI7QUFFekIsNENBSXFCO0FBSXJCLGtDQUtnQjtBQUNoQixpQ0FBNkM7QUFFN0MsTUFBTSxXQUFXLEdBQUcsRUFBRSxDQUFBO0FBQ3RCLE1BQU0sV0FBVyxHQUFHLEdBQUcsQ0FBQTtBQUV2QixNQUFNLFlBQVksR0FBRyxlQUFLLENBQUMsSUFBSSxDQUFBO0FBbUIvQixNQUFhLG1CQUFvQixTQUFRLGFBQU07SUFVN0MsWUFBWSxTQUF1QixFQUFFO1FBQ25DLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUNiLElBQUksQ0FBQyxVQUFVLEdBQUcsSUFBSSxDQUFBO1FBQ3RCLElBQUksQ0FBQyxRQUFRLEdBQUcsRUFBRSxDQUFBLENBQUMsa0NBQWtDO1FBQ3JELElBQUksQ0FBQyxVQUFVLEdBQUcsRUFBRSxDQUFBO1FBQ3BCLElBQUksQ0FBQyxlQUFlLEdBQUcsSUFBSSxDQUFBO1FBQzNCLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFBO0lBQzVCLENBQUM7SUFFTyxVQUFVLENBQUMsTUFBYztRQUMvQiw4RUFBOEU7UUFDOUUsTUFBTSxNQUFNLEdBQUcsa0JBQ1YsT0FBTyxDQUFDLE1BQU0sSUFDakIsS0FBSyxFQUFFLENBQUMsR0FBRyxFQUFFLEdBQUcsRUFBRSxFQUFFLEVBQUUsRUFBRSxDQUFPLE9BQU8sQ0FBQyxNQUFNLENBQUMsS0FBTSxDQUFDLEdBQUcsRUFBRSxHQUFHLEVBQUUsRUFBRSxFQUFFLEVBQUUsV0FBVyxFQUFFLElBQUksRUFBRSxDQUFDLEdBQzFGLENBQUE7UUFFRCxNQUFNLFdBQVcsR0FBRyxHQUFHLENBQUMsRUFBRSxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFBRSxH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QUVULEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ1AsR0FBRyxFQUFFLEtBQUssQ0FBQyxHQUFHO2dCQUNkLFVBQVUsRUFBRSxpQkFBaUI7Z0JBQzdCLGFBQWE7Z0JBQ2IsSUFBSTthQUNMLENBQUMsQ0FBQTtZQUVGLGlCQUFpQixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUMsTUFBTSxHQUFHLENBQUMsQ0FBQTtZQUVoRCxPQUFPLEdBQUcsQ0FBQTtRQUNaLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQTtJQUNWLENBQUM7SUFFTSxNQUFNLENBQUMsZUFBZ0M7UUFDNUMsT0FBTyxlQUFlLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDOUQsQ0FBQztJQUVNLGFBQWEsQ0FBQyxRQUFrQixFQUFFLE1BQWM7UUFDckQsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDaEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUMsVUFBVSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1NBQ3RDO1FBRUQsSUFBSSxDQUFDLGlCQUFpQixDQUFDLFFBQVEsRUFBRSxNQUFNLEVBQUUsS0FBSyxDQUFDLENBQUE7SUFDakQsQ0FBQztJQUVNLElBQUk7UUFDVCxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUE7UUFDZixJQUFJLENBQUMsTUFBTSxJQUFJLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxFQUFFLENBQUE7SUFDdEMsQ0FBQztDQUVGO0FBM01ELGtEQTJNQyIsImZpbGUiOiJsb2dnZXIvd3JpdGVycy9mYW5jeS10ZXJtaW5hbC13cml0ZXIuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgYW5zaUVzY2FwZXMgZnJvbSBcImFuc2ktZXNjYXBlc1wiXG5pbXBvcnQgKiBhcyBjbGlDdXJzb3IgZnJvbSBcImNsaS1jdXJzb3JcIlxuaW1wb3J0ICogYXMgZWxlZ2FudFNwaW5uZXIgZnJvbSBcImVsZWdhbnQtc3Bpbm5lclwiXG5pbXBvcnQgKiBhcyB3cmFwQW5zaSBmcm9tIFwid3JhcC1hbnNpXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuXG5pbXBvcnQge1xuICBmb3JtYXRGb3JUZXJtaW5hbCxcbiAgbGVmdFBhZCxcbiAgcmVuZGVyTXNnLFxufSBmcm9tIFwiLi4vcmVuZGVyZXJzXCJcbmltcG9ydCB7IExvZ0VudHJ5IH0gZnJvbSBcIi4uL2xvZy1lbnRyeVwiXG5pbXBvcnQgeyBMb2dnZXIgfSBmcm9tIFwiLi4vbG9nZ2VyXCJcbmltcG9ydCB7IExvZ0xldmVsIH0gZnJvbSBcIi4uL2xvZy1ub2RlXCJcbmltcG9ydCB7XG4gIGdldENoaWxkRW50cmllcyxcbiAgZ2V0VGVybWluYWxXaWR0aCxcbiAgaW50ZXJjZXB0U3RyZWFtLFxuICB2YWxpZGF0ZSxcbn0gZnJvbSBcIi4uL3V0aWxcIlxuaW1wb3J0IHsgV3JpdGVyLCBXcml0ZXJDb25maWcgfSBmcm9tIFwiLi9iYXNlXCJcblxuY29uc3QgSU5URVJWQUxfTVMgPSA2MFxuY29uc3QgVEhST1RUTEVfTVMgPSA2MDBcblxuY29uc3Qgc3Bpbm5lclN0eWxlID0gY2hhbGsuY3lhblxuXG5leHBvcnQgdHlwZSBDb29yZHMgPSBbbnVtYmVyLCBudW1iZXJdXG5cbmV4cG9ydCBpbnRlcmZhY2UgVGVybWluYWxFbnRyeSB7XG4gIGtleTogc3RyaW5nXG4gIHRleHQ6IHN0cmluZ1xuICBsaW5lTnVtYmVyOiBudW1iZXJcbiAgc3Bpbm5lckNvb3Jkcz86IENvb3Jkc1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlcm1pbmFsRW50cnlXaXRoU3Bpbm5lciBleHRlbmRzIFRlcm1pbmFsRW50cnkge1xuICBzcGlubmVyQ29vcmRzOiBDb29yZHNcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDdXN0b21TdHJlYW0gZXh0ZW5kcyBOb2RlSlMuV3JpdGVTdHJlYW0ge1xuICBjbGVhblVwOiBGdW5jdGlvblxufVxuXG5leHBvcnQgY2xhc3MgRmFuY3lUZXJtaW5hbFdyaXRlciBleHRlbmRzIFdyaXRlciB7XG4gIHByaXZhdGUgc3Bpbm5lcnM6IHsgW2tleTogc3RyaW5nXTogRnVuY3Rpb24gfVxuICBwcml2YXRlIGludGVydmFsSUQ6IE5vZGVKUy5UaW1lciB8IG51bGxcbiAgcHJpdmF0ZSBzdHJlYW06IEN1c3RvbVN0cmVhbVxuICBwcml2YXRlIHByZXZPdXRwdXQ6IHN0cmluZ1tdXG4gIHByaXZhdGUgbGFzdEludGVyY2VwdEF0OiBudW1iZXIgfCBudWxsXG4gIHByaXZhdGUgdXBkYXRlUGVuZGluZzogYm9vbGVhblxuXG4gIHB1YmxpYyBsZXZlbDogTG9nTGV2ZWxcblxuICBjb25zdHJ1Y3Rvcihjb25maWc6IFdyaXRlckNvbmZpZyA9IHt9KSB7XG4gICAgc3VwZXIoY29uZmlnKVxuICAgIHRoaXMuaW50ZXJ2YWxJRCA9IG51bGxcbiAgICB0aGlzLnNwaW5uZXJzID0ge30gLy8gRWFjaCBlbnRyeSBoYXMgaXQncyBvd24gc3Bpbm5lclxuICAgIHRoaXMucHJldk91dHB1dCA9IFtdXG4gICAgdGhpcy5sYXN0SW50ZXJjZXB0QXQgPSBudWxsXG4gICAgdGhpcy51cGRhdGVQZW5kaW5nID0gZmFsc2VcbiAgfVxuXG4gIHByaXZhdGUgaW5pdFN0cmVhbShsb2dnZXI6IExvZ2dlcik6IEN1c3RvbVN0cmVhbSB7XG4gICAgLy8gQ3JlYXRlIGN1c3RvbSBzdHJlYW0gdGhhdCBjYWxscyB3cml0ZSBtZXRob2Qgd2l0aCB0aGUgJ25vSW50ZXJjZXB0JyBvcHRpb24uXG4gICAgY29uc3Qgc3RyZWFtID0gPEN1c3RvbVN0cmVhbT57XG4gICAgICAuLi5wcm9jZXNzLnN0ZG91dCxcbiAgICAgIHdyaXRlOiAoc3RyLCBlbmMsIGNiKSA9PiAoPGFueT5wcm9jZXNzLnN0ZG91dC53cml0ZSkoc3RyLCBlbmMsIGNiLCB7IG5vSW50ZXJjZXB0OiB0cnVlIH0pLFxuICAgIH1cblxuICAgIGNvbnN0IG9uSW50ZXJjZXB0ID0gbXNnID0+IGxvZ2dlci5pbmZvKHsgbXNnLCBmcm9tU3RkU3RyZWFtOiB0cnVlIH0pXG5cbiAgICBjb25zdCByZXN0b3JlU3RyZWFtRm5zID0gW1xuICAgICAgaW50ZXJjZXB0U3RyZWFtKHByb2Nlc3Muc3Rkb3V0LCBvbkludGVyY2VwdCksXG4gICAgICBpbnRlcmNlcHRTdHJlYW0ocHJvY2Vzcy5zdGRlcnIsIG9uSW50ZXJjZXB0KSxcbiAgICBdXG5cbiAgICBzdHJlYW0uY2xlYW5VcCA9ICgpID0+IHtcbiAgICAgIGNsaUN1cnNvci5zaG93KHRoaXMuc3RyZWFtKVxuICAgICAgcmVzdG9yZVN0cmVhbUZucy5mb3JFYWNoKHJlc3RvcmVTdHJlYW0gPT4gcmVzdG9yZVN0cmVhbSgpKVxuICAgIH1cblxuICAgIHJldHVybiBzdHJlYW1cbiAgfVxuXG4gIHByaXZhdGUgc3BpbihlbnRyaWVzOiBUZXJtaW5hbEVudHJ5V2l0aFNwaW5uZXJbXSwgdG90YWxMaW5lczogbnVtYmVyKTogdm9pZCB7XG4gICAgZW50cmllcy5mb3JFYWNoKGUgPT4ge1xuICAgICAgbGV0IG91dCA9IFwiXCJcbiAgICAgIGNvbnN0IFt4LCB5XSA9IGUuc3Bpbm5lckNvb3Jkc1xuICAgICAgY29uc3QgdGVybVggPSB4ID09PSAwID8geCA6IHggKyAxXG4gICAgICBjb25zdCB0ZXJtWSA9IC0odG90YWxMaW5lcyAtIHkgLSAxKVxuICAgICAgb3V0ICs9IGFuc2lFc2NhcGVzLmN1cnNvclNhdmVQb3NpdGlvblxuICAgICAgb3V0ICs9IGFuc2lFc2NhcGVzLmN1cnNvclRvKDApIC8vIEVuc3VyZSBjdXJzb3IgaXMgdG8gdGhlIGxlZnRcbiAgICAgIG91dCArPSBhbnNpRXNjYXBlcy5jdXJzb3JNb3ZlKHRlcm1YLCB0ZXJtWSlcbiAgICAgIG91dCArPSBzcGlubmVyU3R5bGUodGhpcy50aWNrU3Bpbm5lcihlLmtleSkpXG4gICAgICBvdXQgKz0gYW5zaUVzY2FwZXMuY3Vyc29yUmVzdG9yZVBvc2l0aW9uXG4gICAgICB0aGlzLnN0cmVhbS53cml0ZShvdXQpXG4gICAgfSlcbiAgfVxuXG4gIHByaXZhdGUgc3RhcnRMb29wKGVudHJpZXM6IFRlcm1pbmFsRW50cnlXaXRoU3Bpbm5lcltdLCB0b3RhbExpbmVzOiBudW1iZXIpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3BMb29wKClcbiAgICB0aGlzLmludGVydmFsSUQgPSBzZXRJbnRlcnZhbChcbiAgICAgICgpID0+IHRoaXMuc3BpbihlbnRyaWVzLCB0b3RhbExpbmVzKSxcbiAgICAgIElOVEVSVkFMX01TLFxuICAgIClcbiAgfVxuXG4gIHByaXZhdGUgc3RvcExvb3AoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW50ZXJ2YWxJRCkge1xuICAgICAgY2xlYXJJbnRlcnZhbCh0aGlzLmludGVydmFsSUQpXG4gICAgICB0aGlzLmludGVydmFsSUQgPSBudWxsXG4gICAgfVxuICB9XG5cbiAgcHJpdmF0ZSB0aWNrU3Bpbm5lcihrZXk6IHN0cmluZyk6IHN0cmluZyB7XG4gICAgaWYgKCF0aGlzLnNwaW5uZXJzW2tleV0pIHtcbiAgICAgIHRoaXMuc3Bpbm5lcnNba2V5XSA9IGVsZWdhbnRTcGlubmVyKClcbiAgICB9XG4gICAgcmV0dXJuIHRoaXMuc3Bpbm5lcnNba2V5XSgpXG4gIH1cblxuICBwcml2YXRlIHdyaXRlKG91dHB1dDogc3RyaW5nW10sIG5leHRFbnRyeTogVGVybWluYWxFbnRyeSkge1xuICAgIGNsaUN1cnNvci5oaWRlKHRoaXMuc3RyZWFtKVxuXG4gICAgY29uc3QgbGluZU51bWJlciA9IG91dHB1dC5sZW5ndGggPj0gdGhpcy5wcmV2T3V0cHV0Lmxlbmd0aCA/IG5leHRFbnRyeS5saW5lTnVtYmVyIDogMFxuICAgIGNvbnN0IG5MaW5lc1RvRXJhc2UgPSB0aGlzLnByZXZPdXRwdXQubGVuZ3RoIC0gbGluZU51bWJlclxuICAgIHRoaXMuc3RyZWFtLndyaXRlKFxuICAgICAgYW5zaUVzY2FwZXMuZXJhc2VMaW5lcyhuTGluZXNUb0VyYXNlKSArIG91dHB1dC5zbGljZShsaW5lTnVtYmVyKS5qb2luKFwiXFxuXCIpLFxuICAgIClcbiAgfVxuXG4gIHByaXZhdGUgaGFuZGxlR3JhcGhDaGFuZ2UobG9nRW50cnk6IExvZ0VudHJ5LCBsb2dnZXI6IExvZ2dlciwgZGlkV3JpdGU6IGJvb2xlYW4gPSBmYWxzZSkge1xuICAgIHRoaXMudXBkYXRlUGVuZGluZyA9IGZhbHNlXG5cbiAgICAvLyBTdXNwZW5kIHByb2Nlc3NpbmcgYW5kIHdyaXRlIGltbWVkaWF0ZWx5IGlmIGEgbG90IG9mIGRhdGEgaXMgYmVpbmcgaW50ZXJjZXB0ZWQsIGUuZy4gd2hlbiB1c2VyIGlzIHR5cGluZyBpbiBpbnB1dFxuICAgIGlmIChsb2dFbnRyeS5mcm9tU3RkU3RyZWFtKCkgJiYgIWRpZFdyaXRlKSB7XG4gICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpXG4gICAgICBjb25zdCB0aHJvdHRsZVByb2Nlc3NpbmcgPSB0aGlzLmxhc3RJbnRlcmNlcHRBdCAmJiAobm93IC0gdGhpcy5sYXN0SW50ZXJjZXB0QXQpIDwgVEhST1RUTEVfTVNcbiAgICAgIHRoaXMubGFzdEludGVyY2VwdEF0ID0gbm93XG5cbiAgICAgIGlmICh0aHJvdHRsZVByb2Nlc3NpbmcpIHtcbiAgICAgICAgdGhpcy5zdG9wTG9vcCgpXG4gICAgICAgIHRoaXMuc3RyZWFtLndyaXRlKHJlbmRlck1zZyhsb2dFbnRyeSkpXG4gICAgICAgIHRoaXMudXBkYXRlUGVuZGluZyA9IHRydWVcblxuICAgICAgICAvLyBSZXN1bWUgcHJvY2Vzc2luZyBpZiBpZGxlIGFuZCBvcmlnaW5hbCB1cGRhdGUgaXMgc3RpbGwgcGVuZGluZ1xuICAgICAgICBzZXRUaW1lb3V0KCgpID0+IHtcbiAgICAgICAgICBpZiAodGhpcy51cGRhdGVQZW5kaW5nKSB7XG4gICAgICAgICAgICB0aGlzLmhhbmRsZUdyYXBoQ2hhbmdlKGxvZ0VudHJ5LCBsb2dnZXIsIHRydWUpXG4gICAgICAgICAgfVxuICAgICAgICB9LCBUSFJPVFRMRV9NUylcbiAgICAgICAgcmV0dXJuXG4gICAgICB9XG4gICAgfVxuXG4gICAgY29uc3QgdGVybWluYWxFbnRyaWVzID0gdGhpcy50b1Rlcm1pbmFsRW50cmllcyhsb2dnZXIpXG4gICAgY29uc3QgbmV4dEVudHJ5ID0gdGVybWluYWxFbnRyaWVzLmZpbmQoZSA9PiBlLmtleSA9PT0gbG9nRW50cnkua2V5KVxuXG4gICAgLy8gTm90aGluZyB0byBkbywgZS5nLiBiZWNhdXNlIGVudHJ5IGxldmVsIGlzIGhpZ2hlciB0aGFuIHdyaXRlciBsZXZlbFxuICAgIGlmICghbmV4dEVudHJ5KSB7XG4gICAgICByZXR1cm5cbiAgICB9XG5cbiAgICBjb25zdCBvdXRwdXQgPSB0aGlzLnJlbmRlcih0ZXJtaW5hbEVudHJpZXMpXG4gICAgaWYgKCFkaWRXcml0ZSkge1xuICAgICAgdGhpcy53cml0ZShvdXRwdXQsIG5leHRFbnRyeSlcbiAgICB9XG5cbiAgICBjb25zdCBlbnRyaWVzV2l0aHNwaW5uZXIgPSA8VGVybWluYWxFbnRyeVdpdGhTcGlubmVyW10+dGVybWluYWxFbnRyaWVzLmZpbHRlcihlID0+IGUuc3Bpbm5lckNvb3JkcylcblxuICAgIGlmIChlbnRyaWVzV2l0aHNwaW5uZXIubGVuZ3RoID4gMCkge1xuICAgICAgdGhpcy5zdGFydExvb3AoZW50cmllc1dpdGhzcGlubmVyLCBvdXRwdXQubGVuZ3RoKVxuICAgIH0gZWxzZSB7XG4gICAgICB0aGlzLnN0b3BMb29wKClcbiAgICB9XG5cbiAgICB0aGlzLnByZXZPdXRwdXQgPSBvdXRwdXRcbiAgfVxuXG4gIHB1YmxpYyB0b1Rlcm1pbmFsRW50cmllcyhsb2dnZXI6IExvZ2dlcik6IFRlcm1pbmFsRW50cnlbXSB7XG4gICAgY29uc3QgbGV2ZWwgPSB0aGlzLmxldmVsIHx8IGxvZ2dlci5sZXZlbFxuICAgIGxldCBjdXJyZW50TGluZU51bWJlciA9IDBcblxuICAgIHJldHVybiBnZXRDaGlsZEVudHJpZXMobG9nZ2VyKVxuICAgICAgLmZpbHRlcihlbnRyeSA9PiB2YWxpZGF0ZShsZXZlbCwgZW50cnkpKVxuICAgICAgLnJlZHVjZSgoYWNjOiBUZXJtaW5hbEVudHJ5W10sIGVudHJ5OiBMb2dFbnRyeSk6IFRlcm1pbmFsRW50cnlbXSA9PiB7XG4gICAgICAgIGxldCBzcGlubmVyRnJhbWUgPSBcIlwiXG4gICAgICAgIGxldCBzcGlubmVyWFxuICAgICAgICBsZXQgc3Bpbm5lckNvb3JkczogQ29vcmRzIHwgdW5kZWZpbmVkXG5cbiAgICAgICAgaWYgKGVudHJ5Lm9wdHMuc3RhdHVzID09PSBcImFjdGl2ZVwiKSB7XG4gICAgICAgICAgc3Bpbm5lclggPSBsZWZ0UGFkKGVudHJ5KS5sZW5ndGhcbiAgICAgICAgICBzcGlubmVyRnJhbWUgPSB0aGlzLnRpY2tTcGlubmVyKGVudHJ5LmtleSlcbiAgICAgICAgICBzcGlubmVyQ29vcmRzID0gW3NwaW5uZXJYLCBjdXJyZW50TGluZU51bWJlcl1cbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBkZWxldGUgdGhpcy5zcGlubmVyc1tlbnRyeS5rZXldXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCB0ZXh0ID0gW2VudHJ5XVxuICAgICAgICAgIC5tYXAoZSA9PiAoXG4gICAgICAgICAgICBlLmZyb21TdGRTdHJlYW0oKVxuICAgICAgICAgICAgICA/IHJlbmRlck1zZyhlKVxuICAgICAgICAgICAgICA6IGZvcm1hdEZvclRlcm1pbmFsKGUpXG4gICAgICAgICAgKSlcbiAgICAgICAgICAubWFwKHN0ciA9PiAoXG4gICAgICAgICAgICBzcGlubmVyRnJhbWVcbiAgICAgICAgICAgICAgPyBgJHtzdHIuc2xpY2UoMCwgc3Bpbm5lclgpfSR7c3Bpbm5lclN0eWxlKHNwaW5uZXJGcmFtZSl9ICR7c3RyLnNsaWNlKHNwaW5uZXJYKX1gXG4gICAgICAgICAgICAgIDogc3RyXG4gICAgICAgICAgKSlcbiAgICAgICAgICAubWFwKHN0ciA9PiB3cmFwQW5zaShzdHIsIGdldFRlcm1pbmFsV2lkdGgodGhpcy5zdHJlYW0pLCB7XG4gICAgICAgICAgICB0cmltOiBmYWxzZSxcbiAgICAgICAgICAgIGhhcmQ6IHRydWUsXG4gICAgICAgICAgICB3b3JkV3JhcDogZmFsc2UsXG4gICAgICAgICAgfSkpXG4gICAgICAgICAgLnBvcCgpIVxuXG4gICAgICAgIGFjYy5wdXNoKHtcbiAgICAgICAgICBrZXk6IGVudHJ5LmtleSxcbiAgICAgICAgICBsaW5lTnVtYmVyOiBjdXJyZW50TGluZU51bWJlcixcbiAgICAgICAgICBzcGlubmVyQ29vcmRzLFxuICAgICAgICAgIHRleHQsXG4gICAgICAgIH0pXG5cbiAgICAgICAgY3VycmVudExpbmVOdW1iZXIgKz0gdGV4dC5zcGxpdChcIlxcblwiKS5sZW5ndGggLSAxXG5cbiAgICAgICAgcmV0dXJuIGFjY1xuICAgICAgfSwgW10pXG4gIH1cblxuICBwdWJsaWMgcmVuZGVyKHRlcm1pbmFsRW50cmllczogVGVybWluYWxFbnRyeVtdKTogc3RyaW5nW10ge1xuICAgIHJldHVybiB0ZXJtaW5hbEVudHJpZXMubWFwKGUgPT4gZS50ZXh0KS5qb2luKFwiXCIpLnNwbGl0KFwiXFxuXCIpXG4gIH1cblxuICBwdWJsaWMgb25HcmFwaENoYW5nZShsb2dFbnRyeTogTG9nRW50cnksIGxvZ2dlcjogTG9nZ2VyKTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLnN0cmVhbSkge1xuICAgICAgdGhpcy5zdHJlYW0gPSB0aGlzLmluaXRTdHJlYW0obG9nZ2VyKVxuICAgIH1cblxuICAgIHRoaXMuaGFuZGxlR3JhcGhDaGFuZ2UobG9nRW50cnksIGxvZ2dlciwgZmFsc2UpXG4gIH1cblxuICBwdWJsaWMgc3RvcCgpOiB2b2lkIHtcbiAgICB0aGlzLnN0b3BMb29wKClcbiAgICB0aGlzLnN0cmVhbSAmJiB0aGlzLnN0cmVhbS5jbGVhblVwKClcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/logger/writers/file-writer.d.ts b/garden-service/build/logger/writers/file-writer.d.ts new file mode 100644 index 00000000000..3daeccf3c68 --- /dev/null +++ b/garden-service/build/logger/writers/file-writer.d.ts @@ -0,0 +1,25 @@ +import * as winston from "winston"; +import { LogLevel } from "../log-node"; +import { LogEntry } from "../log-entry"; +import { Writer } from "./base"; +export interface FileWriterConfig { + level: LogLevel; + root: string; + filename: string; + path?: string; + fileTransportOptions?: {}; + truncatePrevious?: boolean; +} +export declare class FileWriter extends Writer { + private fileLogger; + private filePath; + private fileTransportOptions; + level: LogLevel; + constructor(filePath: string, config: FileWriterConfig); + static factory(config: FileWriterConfig): Promise; + initFileLogger(): winston.Logger; + render(entry: LogEntry): string | null; + onGraphChange(entry: LogEntry): void; + stop(): void; +} +//# sourceMappingURL=file-writer.d.ts.map \ No newline at end of file diff --git a/garden-service/build/logger/writers/file-writer.js b/garden-service/build/logger/writers/file-writer.js new file mode 100644 index 00000000000..719ca17a5a6 --- /dev/null +++ b/garden-service/build/logger/writers/file-writer.js @@ -0,0 +1,87 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const winston = require("winston"); +const path_1 = require("path"); +const stripAnsi = require("strip-ansi"); +const fs_extra_1 = require("fs-extra"); +const log_node_1 = require("../log-node"); +const base_1 = require("./base"); +const util_1 = require("../util"); +const renderers_1 = require("../renderers"); +const constants_1 = require("../../constants"); +const { combine: winstonCombine, timestamp, printf } = winston.format; +const DEFAULT_FILE_TRANSPORT_OPTIONS = { + format: winstonCombine(timestamp(), printf(info => `\n[${info.timestamp}] ${info.message}`)), + maxsize: 10000000, + maxFiles: 1, +}; +const levelToStr = (lvl) => log_node_1.LogLevel[lvl]; +class FileWriter extends base_1.Writer { + constructor(filePath, config) { + const { fileTransportOptions = DEFAULT_FILE_TRANSPORT_OPTIONS, level, } = config; + super({ level }); + this.fileTransportOptions = fileTransportOptions; + this.filePath = filePath; + this.fileLogger = null; + } + static factory(config) { + return __awaiter(this, void 0, void 0, function* () { + const { filename, root, truncatePrevious, path = constants_1.LOGS_DIR, } = config; + const fullPath = path_1.join(root, path); + yield fs_extra_1.ensureDir(fullPath); + const filePath = path_1.join(fullPath, filename); + if (truncatePrevious) { + try { + yield fs_extra_1.truncate(filePath); + } + catch (_) { + } + } + return new FileWriter(filePath, config); + }); + } + // Only init if needed to prevent unnecessary file writes + initFileLogger() { + return winston.createLogger({ + level: levelToStr(this.level), + transports: [ + new winston.transports.File(Object.assign({}, this.fileTransportOptions, { filename: this.filePath })), + ], + }); + } + render(entry) { + if (util_1.validate(this.level, entry)) { + const renderFn = entry.level === log_node_1.LogLevel.error ? renderers_1.renderError : renderers_1.renderMsg; + return stripAnsi(renderFn(entry)); + } + return null; + } + onGraphChange(entry) { + const out = this.render(entry); + if (out) { + if (!this.fileLogger) { + this.fileLogger = this.initFileLogger(); + } + this.fileLogger.log(levelToStr(entry.level), out); + } + } + stop() { } +} +exports.FileWriter = FileWriter; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbImxvZ2dlci93cml0ZXJzL2ZpbGUtd3JpdGVyLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxtQ0FBa0M7QUFDbEMsK0JBQTJCO0FBQzNCLHdDQUF1QztBQUN2Qyx1Q0FBOEM7QUFFOUMsMENBQXNDO0FBRXRDLGlDQUErQjtBQUMvQixrQ0FBa0M7QUFDbEMsNENBR3FCO0FBQ3JCLCtDQUEwQztBQWExQyxNQUFNLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxTQUFTLEVBQUUsTUFBTSxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQTtBQUVyRSxNQUFNLDhCQUE4QixHQUF5QjtJQUMzRCxNQUFNLEVBQUUsY0FBYyxDQUNwQixTQUFTLEVBQUUsRUFDWCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxNQUFNLElBQUksQ0FBQyxTQUFTLEtBQUssSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQ3hEO0lBQ0QsT0FBTyxFQUFFLFFBQVE7SUFDakIsUUFBUSxFQUFFLENBQUM7Q0FDWixDQUFBO0FBRUQsTUFBTSxVQUFVLEdBQUcsQ0FBQyxHQUFhLEVBQVUsRUFBRSxDQUFDLG1CQUFRLENBQUMsR0FBRyxDQUFDLENBQUE7QUFFM0QsTUFBYSxVQUFXLFNBQVEsYUFBTTtJQU9wQyxZQUFZLFFBQWdCLEVBQUUsTUFBd0I7UUFDcEQsTUFBTSxFQUNKLG9CQUFvQixHQUFHLDhCQUE4QixFQUNyRCxLQUFLLEdBQ04sR0FBRyxNQUFNLENBQUE7UUFFVixLQUFLLENBQUMsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBO1FBRWhCLElBQUksQ0FBQyxvQkFBb0IsR0FBRyxvQkFBb0IsQ0FBQTtRQUNoRCxJQUFJLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTtRQUN4QixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQTtJQUN4QixDQUFDO0lBRUQsTUFBTSxDQUFPLE9BQU8sQ0FBQyxNQUF3Qjs7WUFDM0MsTUFBTSxFQUNKLFFBQVEsRUFDUixJQUFJLEVBQ0osZ0JBQWdCLEVBQ2hCLElBQUksR0FBRyxvQkFBUSxHQUNoQixHQUFHLE1BQU0sQ0FBQTtZQUNWLE1BQU0sUUFBUSxHQUFHLFdBQUksQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFDakMsTUFBTSxvQkFBUyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBQ3pCLE1BQU0sUUFBUSxHQUFHLFdBQUksQ0FBQyxRQUFRLEVBQUUsUUFBUSxDQUFDLENBQUE7WUFDekMsSUFBSSxnQkFBZ0IsRUFBRTtnQkFDcEIsSUFBSTtvQkFDRixNQUFNLG1CQUFRLENBQUMsUUFBUSxDQUFDLENBQUE7aUJBQ3pCO2dCQUFDLE9BQU8sQ0FBQyxFQUFFO2lCQUNYO2FBQ0Y7WUFDRCxPQUFPLElBQUksVUFBVSxDQUFDLFFBQVEsRUFBRSxNQUFNLENBQUMsQ0FBQTtRQUN6QyxDQUFDO0tBQUE7SUFFRCx5REFBeUQ7SUFDekQsY0FBYztRQUNaLE9BQU8sT0FBTyxDQUFDLFlBQVksQ0FBQztZQUMxQixLQUFLLEVBQUUsVUFBVSxDQUFDLElBQUksQ0FBQyxLQUFLLENBQUM7WUFDN0IsVUFBVSxFQUFFO2dCQUNWLElBQUksT0FBTyxDQUFDLFVBQVUsQ0FBQyxJQUFJLG1CQUN0QixJQUFJLENBQUMsb0JBQW9CLElBQzVCLFFBQVEsRUFBRSxJQUFJLENBQUMsUUFBUSxJQUN2QjthQUNIO1NBQ0YsQ0FBQyxDQUFBO0lBQ0osQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFlO1FBQ3BCLElBQUksZUFBUSxDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUUsS0FBSyxDQUFDLEVBQUU7WUFDL0IsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssS0FBSyxtQkFBUSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsdUJBQVcsQ0FBQyxDQUFDLENBQUMscUJBQVMsQ0FBQTtZQUN6RSxPQUFPLFNBQVMsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQTtTQUNsQztRQUNELE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVELGFBQWEsQ0FBQyxLQUFlO1FBQzNCLE1BQU0sR0FBRyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUE7UUFDOUIsSUFBSSxHQUFHLEVBQUU7WUFDUCxJQUFJLENBQUMsSUFBSSxDQUFDLFVBQVUsRUFBRTtnQkFFcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUE7YUFDeEM7WUFDRCxJQUFJLENBQUMsVUFBVSxDQUFDLEdBQUcsQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1NBQ2xEO0lBQ0gsQ0FBQztJQUVELElBQUksS0FBSyxDQUFDO0NBQ1g7QUF4RUQsZ0NBd0VDIiwiZmlsZSI6ImxvZ2dlci93cml0ZXJzL2ZpbGUtd3JpdGVyLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIHdpbnN0b24gZnJvbSBcIndpbnN0b25cIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCAqIGFzIHN0cmlwQW5zaSBmcm9tIFwic3RyaXAtYW5zaVwiXG5pbXBvcnQgeyBlbnN1cmVEaXIsIHRydW5jYXRlIH0gZnJvbSBcImZzLWV4dHJhXCJcblxuaW1wb3J0IHsgTG9nTGV2ZWwgfSBmcm9tIFwiLi4vbG9nLW5vZGVcIlxuaW1wb3J0IHsgTG9nRW50cnkgfSBmcm9tIFwiLi4vbG9nLWVudHJ5XCJcbmltcG9ydCB7IFdyaXRlciB9IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHsgdmFsaWRhdGUgfSBmcm9tIFwiLi4vdXRpbFwiXG5pbXBvcnQge1xuICByZW5kZXJFcnJvcixcbiAgcmVuZGVyTXNnLFxufSBmcm9tIFwiLi4vcmVuZGVyZXJzXCJcbmltcG9ydCB7IExPR1NfRElSIH0gZnJvbSBcIi4uLy4uL2NvbnN0YW50c1wiXG5cbmV4cG9ydCBpbnRlcmZhY2UgRmlsZVdyaXRlckNvbmZpZyB7XG4gIGxldmVsOiBMb2dMZXZlbFxuICByb290OiBzdHJpbmdcbiAgZmlsZW5hbWU6IHN0cmluZ1xuICBwYXRoPzogc3RyaW5nXG4gIGZpbGVUcmFuc3BvcnRPcHRpb25zPzoge31cbiAgdHJ1bmNhdGVQcmV2aW91cz86IGJvb2xlYW5cbn1cblxudHlwZSBGaWxlVHJhbnNwb3J0T3B0aW9ucyA9IHdpbnN0b24udHJhbnNwb3J0cy5GaWxlVHJhbnNwb3J0T3B0aW9uc1xuXG5jb25zdCB7IGNvbWJpbmU6IHdpbnN0b25Db21iaW5lLCB0aW1lc3RhbXAsIHByaW50ZiB9ID0gd2luc3Rvbi5mb3JtYXRcblxuY29uc3QgREVGQVVMVF9GSUxFX1RSQU5TUE9SVF9PUFRJT05TOiBGaWxlVHJhbnNwb3J0T3B0aW9ucyA9IHtcbiAgZm9ybWF0OiB3aW5zdG9uQ29tYmluZShcbiAgICB0aW1lc3RhbXAoKSxcbiAgICBwcmludGYoaW5mbyA9PiBgXFxuWyR7aW5mby50aW1lc3RhbXB9XSAke2luZm8ubWVzc2FnZX1gKSxcbiAgKSxcbiAgbWF4c2l6ZTogMTAwMDAwMDAsIC8vIDEwIE1CXG4gIG1heEZpbGVzOiAxLFxufVxuXG5jb25zdCBsZXZlbFRvU3RyID0gKGx2bDogTG9nTGV2ZWwpOiBzdHJpbmcgPT4gTG9nTGV2ZWxbbHZsXVxuXG5leHBvcnQgY2xhc3MgRmlsZVdyaXRlciBleHRlbmRzIFdyaXRlciB7XG4gIHByaXZhdGUgZmlsZUxvZ2dlcjogd2luc3Rvbi5Mb2dnZXIgfCBudWxsXG4gIHByaXZhdGUgZmlsZVBhdGg6IHN0cmluZ1xuICBwcml2YXRlIGZpbGVUcmFuc3BvcnRPcHRpb25zOiBGaWxlVHJhbnNwb3J0T3B0aW9uc1xuXG4gIHB1YmxpYyBsZXZlbDogTG9nTGV2ZWxcblxuICBjb25zdHJ1Y3RvcihmaWxlUGF0aDogc3RyaW5nLCBjb25maWc6IEZpbGVXcml0ZXJDb25maWcpIHtcbiAgICBjb25zdCB7XG4gICAgICBmaWxlVHJhbnNwb3J0T3B0aW9ucyA9IERFRkFVTFRfRklMRV9UUkFOU1BPUlRfT1BUSU9OUyxcbiAgICAgIGxldmVsLFxuICAgIH0gPSBjb25maWdcblxuICAgIHN1cGVyKHsgbGV2ZWwgfSlcblxuICAgIHRoaXMuZmlsZVRyYW5zcG9ydE9wdGlvbnMgPSBmaWxlVHJhbnNwb3J0T3B0aW9uc1xuICAgIHRoaXMuZmlsZVBhdGggPSBmaWxlUGF0aFxuICAgIHRoaXMuZmlsZUxvZ2dlciA9IG51bGxcbiAgfVxuXG4gIHN0YXRpYyBhc3luYyBmYWN0b3J5KGNvbmZpZzogRmlsZVdyaXRlckNvbmZpZykge1xuICAgIGNvbnN0IHtcbiAgICAgIGZpbGVuYW1lLFxuICAgICAgcm9vdCxcbiAgICAgIHRydW5jYXRlUHJldmlvdXMsXG4gICAgICBwYXRoID0gTE9HU19ESVIsXG4gICAgfSA9IGNvbmZpZ1xuICAgIGNvbnN0IGZ1bGxQYXRoID0gam9pbihyb290LCBwYXRoKVxuICAgIGF3YWl0IGVuc3VyZURpcihmdWxsUGF0aClcbiAgICBjb25zdCBmaWxlUGF0aCA9IGpvaW4oZnVsbFBhdGgsIGZpbGVuYW1lKVxuICAgIGlmICh0cnVuY2F0ZVByZXZpb3VzKSB7XG4gICAgICB0cnkge1xuICAgICAgICBhd2FpdCB0cnVuY2F0ZShmaWxlUGF0aClcbiAgICAgIH0gY2F0Y2ggKF8pIHtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuIG5ldyBGaWxlV3JpdGVyKGZpbGVQYXRoLCBjb25maWcpXG4gIH1cblxuICAvLyBPbmx5IGluaXQgaWYgbmVlZGVkIHRvIHByZXZlbnQgdW5uZWNlc3NhcnkgZmlsZSB3cml0ZXNcbiAgaW5pdEZpbGVMb2dnZXIoKSB7XG4gICAgcmV0dXJuIHdpbnN0b24uY3JlYXRlTG9nZ2VyKHtcbiAgICAgIGxldmVsOiBsZXZlbFRvU3RyKHRoaXMubGV2ZWwpLFxuICAgICAgdHJhbnNwb3J0czogW1xuICAgICAgICBuZXcgd2luc3Rvbi50cmFuc3BvcnRzLkZpbGUoe1xuICAgICAgICAgIC4uLnRoaXMuZmlsZVRyYW5zcG9ydE9wdGlvbnMsXG4gICAgICAgICAgZmlsZW5hbWU6IHRoaXMuZmlsZVBhdGgsXG4gICAgICAgIH0pLFxuICAgICAgXSxcbiAgICB9KVxuICB9XG5cbiAgcmVuZGVyKGVudHJ5OiBMb2dFbnRyeSk6IHN0cmluZyB8IG51bGwge1xuICAgIGlmICh2YWxpZGF0ZSh0aGlzLmxldmVsLCBlbnRyeSkpIHtcbiAgICAgIGNvbnN0IHJlbmRlckZuID0gZW50cnkubGV2ZWwgPT09IExvZ0xldmVsLmVycm9yID8gcmVuZGVyRXJyb3IgOiByZW5kZXJNc2dcbiAgICAgIHJldHVybiBzdHJpcEFuc2kocmVuZGVyRm4oZW50cnkpKVxuICAgIH1cbiAgICByZXR1cm4gbnVsbFxuICB9XG5cbiAgb25HcmFwaENoYW5nZShlbnRyeTogTG9nRW50cnkpIHtcbiAgICBjb25zdCBvdXQgPSB0aGlzLnJlbmRlcihlbnRyeSlcbiAgICBpZiAob3V0KSB7XG4gICAgICBpZiAoIXRoaXMuZmlsZUxvZ2dlcikge1xuXG4gICAgICAgIHRoaXMuZmlsZUxvZ2dlciA9IHRoaXMuaW5pdEZpbGVMb2dnZXIoKVxuICAgICAgfVxuICAgICAgdGhpcy5maWxlTG9nZ2VyLmxvZyhsZXZlbFRvU3RyKGVudHJ5LmxldmVsKSwgb3V0KVxuICAgIH1cbiAgfVxuXG4gIHN0b3AoKSB7IH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugin-context.d.ts b/garden-service/build/plugin-context.d.ts new file mode 100644 index 00000000000..045e303dc1a --- /dev/null +++ b/garden-service/build/plugin-context.d.ts @@ -0,0 +1,14 @@ +import { Garden } from "./garden"; +import * as Joi from "joi"; +import { Provider } from "./config/project"; +declare type WrappedFromGarden = Pick; +export interface PluginContext extends WrappedFromGarden { + provider: Provider; + providers: { + [name: string]: Provider; + }; +} +export declare const pluginContextSchema: Joi.ObjectSchema; +export declare function createPluginContext(garden: Garden, providerName: string): PluginContext; +export {}; +//# sourceMappingURL=plugin-context.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugin-context.js b/garden-service/build/plugin-context.js new file mode 100644 index 00000000000..200cbb51d18 --- /dev/null +++ b/garden-service/build/plugin-context.js @@ -0,0 +1,64 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const Joi = require("joi"); +const project_1 = require("./config/project"); +const common_1 = require("./config/common"); +const exceptions_1 = require("./exceptions"); +const project_2 = require("./config/project"); +const providerSchema = Joi.object() + .options({ presence: "required" }) + .keys({ + name: common_1.joiIdentifier() + .description("The name of the provider (plugin)."), + config: project_1.providerConfigBaseSchema, +}); +// NOTE: this is used more for documentation than validation, outside of internal testing +// TODO: validate the output from createPluginContext against this schema (in tests) +exports.pluginContextSchema = Joi.object() + .options({ presence: "required" }) + .keys({ + projectName: project_1.projectNameSchema, + projectRoot: Joi.string() + .uri({ relativeOnly: true }) + .description("The absolute path of the project root."), + projectSources: project_1.projectSourcesSchema, + localConfigStore: Joi.object() + .description("Helper class for managing local configuration for plugins."), + environment: project_1.environmentSchema, + provider: providerSchema + .description("The provider being used for this context."), + providers: common_1.joiIdentifierMap(providerSchema) + .description("Map of all configured providers for the current environment and project."), +}); +function createPluginContext(garden, providerName) { + const projectConfig = lodash_1.cloneDeep(garden.environment); + const providerConfigs = lodash_1.keyBy(projectConfig.providers, "name"); + const providers = lodash_1.mapValues(providerConfigs, (config, name) => ({ name, config })); + let provider = providers[providerName]; + if (providerName === "_default") { + provider = project_2.defaultProvider; + } + if (!provider) { + throw new exceptions_1.PluginError(`Could not find provider '${providerName}'`, { providerName, providers }); + } + return { + projectName: garden.projectName, + projectRoot: garden.projectRoot, + projectSources: lodash_1.cloneDeep(garden.projectSources), + environment: projectConfig, + localConfigStore: garden.localConfigStore, + provider, + providers, + }; +} +exports.createPluginContext = createPluginContext; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbi1jb250ZXh0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBR0gsbUNBQW9EO0FBQ3BELDJCQUEwQjtBQUMxQiw4Q0FNeUI7QUFDekIsNENBQWlFO0FBQ2pFLDZDQUEwQztBQUMxQyw4Q0FBa0Q7QUFXbEQsTUFBTSxjQUFjLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRTtLQUNoQyxPQUFPLENBQUMsRUFBRSxRQUFRLEVBQUUsVUFBVSxFQUFFLENBQUM7S0FDakMsSUFBSSxDQUFDO0lBQ0osSUFBSSxFQUFFLHNCQUFhLEVBQUU7U0FDbEIsV0FBVyxDQUFDLG9DQUFvQyxDQUFDO0lBQ3BELE1BQU0sRUFBRSxrQ0FBd0I7Q0FDakMsQ0FBQyxDQUFBO0FBT0oseUZBQXlGO0FBQ3pGLG9GQUFvRjtBQUN2RSxRQUFBLG1CQUFtQixHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUU7S0FDNUMsT0FBTyxDQUFDLEVBQUUsUUFBUSxFQUFFLFVBQVUsRUFBRSxDQUFDO0tBQ2pDLElBQUksQ0FBQztJQUNKLFdBQVcsRUFBRSwyQkFBaUI7SUFDOUIsV0FBVyxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDdEIsR0FBRyxDQUFNLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDO1NBQ2hDLFdBQVcsQ0FBQyx3Q0FBd0MsQ0FBQztJQUN4RCxjQUFjLEVBQUUsOEJBQW9CO0lBQ3BDLGdCQUFnQixFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDM0IsV0FBVyxDQUFDLDREQUE0RCxDQUFDO0lBQzVFLFdBQVcsRUFBRSwyQkFBaUI7SUFDOUIsUUFBUSxFQUFFLGNBQWM7U0FDckIsV0FBVyxDQUFDLDJDQUEyQyxDQUFDO0lBQzNELFNBQVMsRUFBRSx5QkFBZ0IsQ0FBQyxjQUFjLENBQUM7U0FDeEMsV0FBVyxDQUFDLDBFQUEwRSxDQUFDO0NBQzNGLENBQUMsQ0FBQTtBQUVKLFNBQWdCLG1CQUFtQixDQUFDLE1BQWMsRUFBRSxZQUFvQjtJQUN0RSxNQUFNLGFBQWEsR0FBRyxrQkFBUyxDQUFDLE1BQU0sQ0FBQyxXQUFXLENBQUMsQ0FBQTtJQUNuRCxNQUFNLGVBQWUsR0FBRyxjQUFLLENBQUMsYUFBYSxDQUFDLFNBQVMsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUM5RCxNQUFNLFNBQVMsR0FBRyxrQkFBUyxDQUFDLGVBQWUsRUFBRSxDQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUUsRUFBRSxDQUFDLENBQUMsRUFBRSxJQUFJLEVBQUUsTUFBTSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2xGLElBQUksUUFBUSxHQUFHLFNBQVMsQ0FBQyxZQUFZLENBQUMsQ0FBQTtJQUV0QyxJQUFJLFlBQVksS0FBSyxVQUFVLEVBQUU7UUFDL0IsUUFBUSxHQUFHLHlCQUFlLENBQUE7S0FDM0I7SUFFRCxJQUFJLENBQUMsUUFBUSxFQUFFO1FBQ2IsTUFBTSxJQUFJLHdCQUFXLENBQUMsNEJBQTRCLFlBQVksR0FBRyxFQUFFLEVBQUUsWUFBWSxFQUFFLFNBQVMsRUFBRSxDQUFDLENBQUE7S0FDaEc7SUFFRCxPQUFPO1FBQ0wsV0FBVyxFQUFFLE1BQU0sQ0FBQyxXQUFXO1FBQy9CLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztRQUMvQixjQUFjLEVBQUUsa0JBQVMsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDO1FBQ2hELFdBQVcsRUFBRSxhQUFhO1FBQzFCLGdCQUFnQixFQUFFLE1BQU0sQ0FBQyxnQkFBZ0I7UUFDekMsUUFBUTtRQUNSLFNBQVM7S0FDVixDQUFBO0FBQ0gsQ0FBQztBQXZCRCxrREF1QkMiLCJmaWxlIjoicGx1Z2luLWNvbnRleHQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4vZ2FyZGVuXCJcbmltcG9ydCB7IG1hcFZhbHVlcywga2V5QnksIGNsb25lRGVlcCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHtcbiAgUHJvdmlkZXIsXG4gIHByb2plY3ROYW1lU2NoZW1hLFxuICBwcm9qZWN0U291cmNlc1NjaGVtYSxcbiAgZW52aXJvbm1lbnRTY2hlbWEsXG4gIHByb3ZpZGVyQ29uZmlnQmFzZVNjaGVtYSxcbn0gZnJvbSBcIi4vY29uZmlnL3Byb2plY3RcIlxuaW1wb3J0IHsgam9pSWRlbnRpZmllciwgam9pSWRlbnRpZmllck1hcCB9IGZyb20gXCIuL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgUGx1Z2luRXJyb3IgfSBmcm9tIFwiLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IGRlZmF1bHRQcm92aWRlciB9IGZyb20gXCIuL2NvbmZpZy9wcm9qZWN0XCJcblxudHlwZSBXcmFwcGVkRnJvbUdhcmRlbiA9IFBpY2s8R2FyZGVuLFxuICBcInByb2plY3ROYW1lXCIgfFxuICBcInByb2plY3RSb290XCIgfFxuICBcInByb2plY3RTb3VyY2VzXCIgfFxuICAvLyBUT0RPOiByZW1vdmUgdGhpcyBmcm9tIHRoZSBpbnRlcmZhY2VcbiAgXCJsb2NhbENvbmZpZ1N0b3JlXCIgfFxuICBcImVudmlyb25tZW50XCJcbiAgPlxuXG5jb25zdCBwcm92aWRlclNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAub3B0aW9ucyh7IHByZXNlbmNlOiBcInJlcXVpcmVkXCIgfSlcbiAgLmtleXMoe1xuICAgIG5hbWU6IGpvaUlkZW50aWZpZXIoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhlIHByb3ZpZGVyIChwbHVnaW4pLlwiKSxcbiAgICBjb25maWc6IHByb3ZpZGVyQ29uZmlnQmFzZVNjaGVtYSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5Db250ZXh0IGV4dGVuZHMgV3JhcHBlZEZyb21HYXJkZW4ge1xuICBwcm92aWRlcjogUHJvdmlkZXJcbiAgcHJvdmlkZXJzOiB7IFtuYW1lOiBzdHJpbmddOiBQcm92aWRlciB9XG59XG5cbi8vIE5PVEU6IHRoaXMgaXMgdXNlZCBtb3JlIGZvciBkb2N1bWVudGF0aW9uIHRoYW4gdmFsaWRhdGlvbiwgb3V0c2lkZSBvZiBpbnRlcm5hbCB0ZXN0aW5nXG4vLyBUT0RPOiB2YWxpZGF0ZSB0aGUgb3V0cHV0IGZyb20gY3JlYXRlUGx1Z2luQ29udGV4dCBhZ2FpbnN0IHRoaXMgc2NoZW1hIChpbiB0ZXN0cylcbmV4cG9ydCBjb25zdCBwbHVnaW5Db250ZXh0U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5vcHRpb25zKHsgcHJlc2VuY2U6IFwicmVxdWlyZWRcIiB9KVxuICAua2V5cyh7XG4gICAgcHJvamVjdE5hbWU6IHByb2plY3ROYW1lU2NoZW1hLFxuICAgIHByb2plY3RSb290OiBKb2kuc3RyaW5nKClcbiAgICAgIC51cmkoPGFueT57IHJlbGF0aXZlT25seTogdHJ1ZSB9KVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGFic29sdXRlIHBhdGggb2YgdGhlIHByb2plY3Qgcm9vdC5cIiksXG4gICAgcHJvamVjdFNvdXJjZXM6IHByb2plY3RTb3VyY2VzU2NoZW1hLFxuICAgIGxvY2FsQ29uZmlnU3RvcmU6IEpvaS5vYmplY3QoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiSGVscGVyIGNsYXNzIGZvciBtYW5hZ2luZyBsb2NhbCBjb25maWd1cmF0aW9uIGZvciBwbHVnaW5zLlwiKSxcbiAgICBlbnZpcm9ubWVudDogZW52aXJvbm1lbnRTY2hlbWEsXG4gICAgcHJvdmlkZXI6IHByb3ZpZGVyU2NoZW1hXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcHJvdmlkZXIgYmVpbmcgdXNlZCBmb3IgdGhpcyBjb250ZXh0LlwiKSxcbiAgICBwcm92aWRlcnM6IGpvaUlkZW50aWZpZXJNYXAocHJvdmlkZXJTY2hlbWEpXG4gICAgICAuZGVzY3JpcHRpb24oXCJNYXAgb2YgYWxsIGNvbmZpZ3VyZWQgcHJvdmlkZXJzIGZvciB0aGUgY3VycmVudCBlbnZpcm9ubWVudCBhbmQgcHJvamVjdC5cIiksXG4gIH0pXG5cbmV4cG9ydCBmdW5jdGlvbiBjcmVhdGVQbHVnaW5Db250ZXh0KGdhcmRlbjogR2FyZGVuLCBwcm92aWRlck5hbWU6IHN0cmluZyk6IFBsdWdpbkNvbnRleHQge1xuICBjb25zdCBwcm9qZWN0Q29uZmlnID0gY2xvbmVEZWVwKGdhcmRlbi5lbnZpcm9ubWVudClcbiAgY29uc3QgcHJvdmlkZXJDb25maWdzID0ga2V5QnkocHJvamVjdENvbmZpZy5wcm92aWRlcnMsIFwibmFtZVwiKVxuICBjb25zdCBwcm92aWRlcnMgPSBtYXBWYWx1ZXMocHJvdmlkZXJDb25maWdzLCAoY29uZmlnLCBuYW1lKSA9PiAoeyBuYW1lLCBjb25maWcgfSkpXG4gIGxldCBwcm92aWRlciA9IHByb3ZpZGVyc1twcm92aWRlck5hbWVdXG5cbiAgaWYgKHByb3ZpZGVyTmFtZSA9PT0gXCJfZGVmYXVsdFwiKSB7XG4gICAgcHJvdmlkZXIgPSBkZWZhdWx0UHJvdmlkZXJcbiAgfVxuXG4gIGlmICghcHJvdmlkZXIpIHtcbiAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYENvdWxkIG5vdCBmaW5kIHByb3ZpZGVyICcke3Byb3ZpZGVyTmFtZX0nYCwgeyBwcm92aWRlck5hbWUsIHByb3ZpZGVycyB9KVxuICB9XG5cbiAgcmV0dXJuIHtcbiAgICBwcm9qZWN0TmFtZTogZ2FyZGVuLnByb2plY3ROYW1lLFxuICAgIHByb2plY3RSb290OiBnYXJkZW4ucHJvamVjdFJvb3QsXG4gICAgcHJvamVjdFNvdXJjZXM6IGNsb25lRGVlcChnYXJkZW4ucHJvamVjdFNvdXJjZXMpLFxuICAgIGVudmlyb25tZW50OiBwcm9qZWN0Q29uZmlnLFxuICAgIGxvY2FsQ29uZmlnU3RvcmU6IGdhcmRlbi5sb2NhbENvbmZpZ1N0b3JlLFxuICAgIHByb3ZpZGVyLFxuICAgIHByb3ZpZGVycyxcbiAgfVxufVxuIl19 diff --git a/garden-service/build/plugins/container.d.ts b/garden-service/build/plugins/container.d.ts new file mode 100644 index 00000000000..0d074288d91 --- /dev/null +++ b/garden-service/build/plugins/container.d.ts @@ -0,0 +1,101 @@ +import * as Joi from "joi"; +import { Module } from "../types/module"; +import { PrimitiveMap } from "../config/common"; +import { GardenPlugin } from "../types/plugin/plugin"; +import { ValidateModuleParams } from "../types/plugin/params"; +import { Service } from "../types/service"; +import { GenericTestSpec } from "./generic"; +import { ModuleSpec, ModuleConfig } from "../config/module"; +import { BaseServiceSpec, ServiceConfig } from "../config/service"; +export interface ContainerIngressSpec { + hostname?: string; + path: string; + port: string; +} +export declare type ServicePortProtocol = "TCP" | "UDP"; +export interface ServicePortSpec { + name: string; + protocol: ServicePortProtocol; + containerPort: number; + hostPort?: number; + nodePort?: number; +} +export interface ServiceVolumeSpec { + name: string; + containerPath: string; + hostPath?: string; +} +export interface ServiceHealthCheckSpec { + httpGet?: { + path: string; + port: string; + scheme?: "HTTP" | "HTTPS"; + }; + command?: string[]; + tcpPort?: string; +} +export interface ContainerServiceSpec extends BaseServiceSpec { + command: string[]; + daemon: boolean; + ingresses: ContainerIngressSpec[]; + env: PrimitiveMap; + healthCheck?: ServiceHealthCheckSpec; + ports: ServicePortSpec[]; + volumes: ServiceVolumeSpec[]; +} +export declare type ContainerServiceConfig = ServiceConfig; +export interface ContainerRegistryConfig { + hostname: string; + port?: number; + namespace: string; +} +export declare const containerRegistryConfigSchema: Joi.ObjectSchema; +export interface ContainerService extends Service { +} +export interface ContainerTestSpec extends GenericTestSpec { +} +export declare const containerTestSchema: Joi.ObjectSchema; +export interface ContainerModuleSpec extends ModuleSpec { + buildArgs: PrimitiveMap; + image?: string; + services: ContainerServiceSpec[]; + tests: ContainerTestSpec[]; +} +export declare type ContainerModuleConfig = ModuleConfig; +export declare const defaultNamespace = "_"; +export declare const defaultTag = "latest"; +export declare const containerModuleSpecSchema: Joi.ObjectSchema; +export interface ContainerModule extends Module { +} +interface ParsedImageId { + host?: string; + namespace?: string; + repository: string; + tag: string; +} +export declare const helpers: { + /** + * Returns the image ID used locally, when building and deploying to local environments + * (when we don't need to push to remote registries). + */ + getLocalImageId(module: ContainerModule): Promise; + /** + * Returns the image ID to be used for publishing to container registries + * (not to be confused with the ID used when pushing to private deployment registries). + */ + getPublicImageId(module: ContainerModule): Promise; + /** + * Returns the image ID to be used when pushing to deployment registries. + */ + getDeploymentImageId(module: ContainerModule, registryConfig?: ContainerRegistryConfig | undefined): Promise; + parseImageId(imageId: string): ParsedImageId; + unparseImageId(parsed: ParsedImageId): string; + pullImage(module: ContainerModule): Promise; + imageExistsLocally(module: ContainerModule): Promise; + dockerCli(module: ContainerModule, args: any): Promise; + hasDockerfile(module: ContainerModule): Promise; +}; +export declare function validateContainerModule({ moduleConfig }: ValidateModuleParams): Promise>; +export declare const gardenPlugin: () => GardenPlugin; +export {}; +//# sourceMappingURL=container.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/container.js b/garden-service/build/plugins/container.js new file mode 100644 index 00000000000..b30da7d5623 --- /dev/null +++ b/garden-service/build/plugins/container.js @@ -0,0 +1,398 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const childProcess = require("child-process-promise"); +const common_1 = require("../config/common"); +const fs_extra_1 = require("fs-extra"); +const path_1 = require("path"); +const dedent = require("dedent"); +const exceptions_1 = require("../exceptions"); +const service_1 = require("../types/service"); +const constants_1 = require("../constants"); +const util_1 = require("../util/util"); +const lodash_1 = require("lodash"); +const generic_1 = require("./generic"); +const service_2 = require("../config/service"); +const ingressSchema = Joi.object() + .keys({ + hostname: service_1.ingressHostnameSchema, + path: Joi.string().uri({ relativeOnly: true }) + .default("/") + .description("The path which should be routed to the service."), + port: Joi.string() + .required() + .description("The name of the container port where the specified paths should be routed."), +}); +const healthCheckSchema = Joi.object() + .keys({ + httpGet: Joi.object() + .keys({ + path: Joi.string() + .uri({ relativeOnly: true }) + .required() + .description("The path of the service's health check endpoint."), + port: Joi.string() + .required() + .description("The name of the port where the service's health check endpoint should be available."), + scheme: Joi.string().allow("HTTP", "HTTPS").default("HTTP"), + }) + .description("Set this to check the service's health by making an HTTP request"), + command: Joi.array().items(Joi.string()) + .description("Set this to check the service's health by running a command in its container."), + tcpPort: Joi.string() + .description("Set this to check the service's health by checking if this TCP port is accepting connections."), +}).xor("httpGet", "command", "tcpPort"); +const portSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("The name of the port (used when referencing the port elsewhere in the service configuration."), + protocol: Joi.string() + .allow("TCP", "UDP") + .default(constants_1.DEFAULT_PORT_PROTOCOL) + .description("The protocol of the service container port."), + containerPort: Joi.number() + .required() + .description("The port number on the service container."), + hostPort: Joi.number() + .meta({ deprecated: true }), + nodePort: Joi.number() + .description("Set this to expose the service on the specified port on the host node " + + "(may not be supported by all providers)."), +}) + .required(); +const volumeSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("The name of the allocated volume."), + containerPath: Joi.string() + .required() + .description("The path where the volume should be mounted in the container."), + hostPath: Joi.string() + .meta({ deprecated: true }), +}); +const serviceSchema = service_2.baseServiceSchema + .keys({ + command: Joi.array().items(Joi.string()) + .description("The arguments to run the container with when starting the service."), + daemon: Joi.boolean() + .default(false) + .description("Whether to run the service as a daemon (to ensure only one runs per node)."), + ingresses: common_1.joiArray(ingressSchema) + .description("List of ingress endpoints that the service exposes.") + .example([{ + path: "/api", + port: "http", + }]), + env: common_1.joiEnvVars(), + healthCheck: healthCheckSchema + .description("Specify how the service's health should be checked after deploying."), + ports: common_1.joiArray(portSchema) + .unique("name") + .description("List of ports that the service container exposes."), + volumes: common_1.joiArray(volumeSchema) + .unique("name") + .description("List of volumes that should be mounted when deploying the container."), +}); +exports.containerRegistryConfigSchema = Joi.object() + .keys({ + hostname: Joi.string() + .hostname() + .required() + .description("The hostname (and optionally port, if not the default port) of the registry.") + .example("gcr.io"), + port: Joi.number() + .integer() + .description("The port where the registry listens on, if not the default."), + namespace: Joi.string() + .default("_") + .description("The namespace in the registry where images should be pushed.") + .example("my-project"), +}) + .required() + .description(dedent ` + The registry where built containers should be pushed to, and then pulled to the cluster when deploying + services. + `); +exports.containerTestSchema = generic_1.genericTestSchema; +exports.defaultNamespace = "_"; +exports.defaultTag = "latest"; +exports.containerModuleSpecSchema = Joi.object() + .keys({ + buildArgs: Joi.object() + .pattern(/.+/, common_1.joiPrimitive()) + .default(() => ({}), "{}") + .description("Specify build arguments when building the container image."), + // TODO: validate the image name format + image: Joi.string() + .description("Specify the image name for the container. Should be a valid docker image identifier. If specified and " + + "the module does not contain a Dockerfile, this image will be used to deploy the container services. " + + "If specified and the module does contain a Dockerfile, this identifier is used when pushing the built image."), + services: common_1.joiArray(serviceSchema) + .unique("name") + .description("List of services to deploy from this container module."), + tests: common_1.joiArray(exports.containerTestSchema) + .description("A list of tests to run in the module."), +}) + .description("Configuration for a container module."); +exports.helpers = { + /** + * Returns the image ID used locally, when building and deploying to local environments + * (when we don't need to push to remote registries). + */ + getLocalImageId(module) { + return __awaiter(this, void 0, void 0, function* () { + if (yield exports.helpers.hasDockerfile(module)) { + const { versionString } = module.version; + return `${module.name}:${versionString}`; + } + else { + return module.spec.image; + } + }); + }, + /** + * Returns the image ID to be used for publishing to container registries + * (not to be confused with the ID used when pushing to private deployment registries). + */ + getPublicImageId(module) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: allow setting a default user/org prefix in the project/plugin config + const image = module.spec.image; + if (image) { + let [imageName, version] = util_1.splitFirst(image, ":"); + if (version) { + // we use the version in the image name, if specified + // (allows specifying version on source images, and also setting specific version name when publishing images) + return image; + } + else { + const { versionString } = module.version; + return `${imageName}:${versionString}`; + } + } + else { + return exports.helpers.getLocalImageId(module); + } + }); + }, + /** + * Returns the image ID to be used when pushing to deployment registries. + */ + getDeploymentImageId(module, registryConfig) { + return __awaiter(this, void 0, void 0, function* () { + const localId = yield exports.helpers.getLocalImageId(module); + if (!registryConfig) { + return localId; + } + const parsedId = exports.helpers.parseImageId(localId); + const host = registryConfig.port ? `${registryConfig.hostname}:${registryConfig.port}` : registryConfig.hostname; + return exports.helpers.unparseImageId({ + host, + namespace: registryConfig.namespace, + repository: parsedId.repository, + tag: parsedId.tag, + }); + }); + }, + parseImageId(imageId) { + const parts = imageId.split("/"); + let [repository, tag] = parts[0].split(":"); + if (!tag) { + tag = exports.defaultTag; + } + if (parts.length === 1) { + return { + namespace: exports.defaultNamespace, + repository, + tag, + }; + } + else if (parts.length === 2) { + return { + namespace: parts[0], + repository, + tag, + }; + } + else if (parts.length === 3) { + return { + host: parts[0], + namespace: parts[1], + repository, + tag, + }; + } + else { + throw new exceptions_1.ConfigurationError(`Invalid container image tag: ${imageId}`, { imageId }); + } + }, + unparseImageId(parsed) { + const name = `${parsed.repository}:${parsed.tag}`; + if (parsed.host) { + return `${parsed.host}/${parsed.namespace}/${name}`; + } + else if (parsed.namespace) { + return `${parsed.namespace}/${name}`; + } + else { + return name; + } + }, + pullImage(module) { + return __awaiter(this, void 0, void 0, function* () { + const identifier = yield exports.helpers.getPublicImageId(module); + yield exports.helpers.dockerCli(module, `pull ${identifier}`); + }); + }, + imageExistsLocally(module) { + return __awaiter(this, void 0, void 0, function* () { + const identifier = yield exports.helpers.getLocalImageId(module); + const exists = (yield exports.helpers.dockerCli(module, `images ${identifier} -q`)).stdout.trim().length > 0; + return exists ? identifier : null; + }); + }, + dockerCli(module, args) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: use dockerode instead of CLI + return childProcess.exec("docker " + args, { cwd: module.buildPath, maxBuffer: 1024 * 1024 }); + }); + }, + hasDockerfile(module) { + return __awaiter(this, void 0, void 0, function* () { + const buildPath = module.buildPath; + return fs_extra_1.pathExists(path_1.join(buildPath, "Dockerfile")); + }); + }, +}; +function validateContainerModule({ moduleConfig }) { + return __awaiter(this, void 0, void 0, function* () { + moduleConfig.spec = common_1.validate(moduleConfig.spec, exports.containerModuleSpecSchema, { context: `module ${moduleConfig.name}` }); + // validate services + moduleConfig.serviceConfigs = moduleConfig.spec.services.map(spec => { + // make sure ports are correctly configured + const name = spec.name; + const definedPorts = spec.ports; + const portsByName = lodash_1.keyBy(spec.ports, "name"); + for (const ingress of spec.ingresses) { + const ingressPort = ingress.port; + if (!portsByName[ingressPort]) { + throw new exceptions_1.ConfigurationError(`Service ${name} does not define port ${ingressPort} defined in ingress`, { definedPorts, ingressPort }); + } + } + if (spec.healthCheck && spec.healthCheck.httpGet) { + const healthCheckHttpPort = spec.healthCheck.httpGet.port; + if (!portsByName[healthCheckHttpPort]) { + throw new exceptions_1.ConfigurationError(`Service ${name} does not define port ${healthCheckHttpPort} defined in httpGet health check`, { definedPorts, healthCheckHttpPort }); + } + } + if (spec.healthCheck && spec.healthCheck.tcpPort) { + const healthCheckTcpPort = spec.healthCheck.tcpPort; + if (!portsByName[healthCheckTcpPort]) { + throw new exceptions_1.ConfigurationError(`Service ${name} does not define port ${healthCheckTcpPort} defined in tcpPort health check`, { definedPorts, healthCheckTcpPort }); + } + } + return { + name, + dependencies: spec.dependencies, + outputs: spec.outputs, + spec, + }; + }); + moduleConfig.testConfigs = moduleConfig.spec.tests.map(t => ({ + name: t.name, + dependencies: t.dependencies, + spec: t, + timeout: t.timeout, + })); + // make sure we can build the thing + if (!moduleConfig.spec.image && !(yield fs_extra_1.pathExists(path_1.join(moduleConfig.path, "Dockerfile")))) { + throw new exceptions_1.ConfigurationError(`Module ${moduleConfig.name} neither specifies image nor provides Dockerfile`, {}); + } + return moduleConfig; + }); +} +exports.validateContainerModule = validateContainerModule; +// TODO: rename this plugin to docker +exports.gardenPlugin = () => ({ + moduleActions: { + container: { + validate: validateContainerModule, + getBuildStatus({ module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const identifier = yield exports.helpers.imageExistsLocally(module); + if (identifier) { + logEntry && logEntry.debug({ + section: module.name, + msg: `Image ${identifier} already exists`, + symbol: "info", + }); + } + return { ready: !!identifier }; + }); + }, + build({ module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const buildPath = module.buildPath; + const image = module.spec.image; + if (!!image && !(yield exports.helpers.hasDockerfile(module))) { + if (yield exports.helpers.imageExistsLocally(module)) { + return { fresh: false }; + } + logEntry && logEntry.setState(`Pulling image ${image}...`); + yield exports.helpers.pullImage(module); + return { fetched: true }; + } + const identifier = yield exports.helpers.getLocalImageId(module); + // build doesn't exist, so we create it + logEntry && logEntry.setState(`Building ${identifier}...`); + const buildArgs = Object.entries(module.spec.buildArgs).map(([key, value]) => { + // TODO: may need to escape this + return `--build-arg ${key}=${value}`; + }).join(" "); + // TODO: log error if it occurs + // TODO: stream output to log if at debug log level + yield exports.helpers.dockerCli(module, `build ${buildArgs} -t ${identifier} ${buildPath}`); + return { fresh: true, details: { identifier } }; + }); + }, + publishModule({ module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + if (!(yield exports.helpers.hasDockerfile(module))) { + logEntry && logEntry.setState({ msg: `Nothing to publish` }); + return { published: false }; + } + const localId = yield exports.helpers.getLocalImageId(module); + const remoteId = yield exports.helpers.getPublicImageId(module); + logEntry && logEntry.setState({ msg: `Publishing image ${remoteId}...` }); + if (localId !== remoteId) { + yield exports.helpers.dockerCli(module, `tag ${localId} ${remoteId}`); + } + // TODO: log error if it occurs + // TODO: stream output to log if at debug log level + // TODO: check if module already exists remotely? + yield exports.helpers.dockerCli(module, `push ${remoteId}`); + return { published: true, message: `Published ${remoteId}` }; + }); + }, + }, + }, +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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K0I7b0JBQy9CLG1EQUFtRDtvQkFDbkQsaURBQWlEO29CQUNqRCxNQUFNLGVBQU8sQ0FBQyxTQUFTLENBQUMsTUFBTSxFQUFFLFFBQVEsUUFBUSxFQUFFLENBQUMsQ0FBQTtvQkFFbkQsT0FBTyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsT0FBTyxFQUFFLGFBQWEsUUFBUSxFQUFFLEVBQUUsQ0FBQTtnQkFDOUQsQ0FBQzthQUFBO1NBQ0Y7S0FDRjtDQUNGLENBQUMsQ0FBQSIsImZpbGUiOiJwbHVnaW5zL2NvbnRhaW5lci5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgKiBhcyBjaGlsZFByb2Nlc3MgZnJvbSBcImNoaWxkLXByb2Nlc3MtcHJvbWlzZVwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7XG4gIGpvaUVudlZhcnMsXG4gIGpvaUlkZW50aWZpZXIsXG4gIGpvaUFycmF5LFxuICB2YWxpZGF0ZSxcbiAgUHJpbWl0aXZlTWFwLFxuICBqb2lQcmltaXRpdmUsXG59IGZyb20gXCIuLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IHBhdGhFeGlzdHMgfSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgeyBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQge1xuICBHYXJkZW5QbHVnaW4sXG59IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vcGx1Z2luXCJcbmltcG9ydCB7XG4gIEJ1aWxkTW9kdWxlUGFyYW1zLFxuICBHZXRCdWlsZFN0YXR1c1BhcmFtcyxcbiAgVmFsaWRhdGVNb2R1bGVQYXJhbXMsXG4gIFB1Ymxpc2hNb2R1bGVQYXJhbXMsXG59IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IFNlcnZpY2UsIGluZ3Jlc3NIb3N0bmFtZVNjaGVtYSB9IGZyb20gXCIuLi90eXBlcy9zZXJ2aWNlXCJcbmltcG9ydCB7IERFRkFVTFRfUE9SVF9QUk9UT0NPTCB9IGZyb20gXCIuLi9jb25zdGFudHNcIlxuaW1wb3J0IHsgc3BsaXRGaXJzdCB9IGZyb20gXCIuLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsga2V5QnkgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7IGdlbmVyaWNUZXN0U2NoZW1hLCBHZW5lcmljVGVzdFNwZWMgfSBmcm9tIFwiLi9nZW5lcmljXCJcbmltcG9ydCB7IE1vZHVsZVNwZWMsIE1vZHVsZUNvbmZpZyB9IGZyb20gXCIuLi9jb25maWcvbW9kdWxlXCJcbmltcG9ydCB7IEJhc2VTZXJ2aWNlU3BlYywgU2VydmljZUNvbmZpZywgYmFzZVNlcnZpY2VTY2hlbWEgfSBmcm9tIFwiLi4vY29uZmlnL3NlcnZpY2VcIlxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhaW5lckluZ3Jlc3NTcGVjIHtcbiAgaG9zdG5hbWU/OiBzdHJpbmdcbiAgcGF0aDogc3RyaW5nXG4gIHBvcnQ6IHN0cmluZ1xufVxuXG5leHBvcnQgdHlwZSBTZXJ2aWNlUG9ydFByb3RvY29sID0gXCJUQ1BcIiB8IFwiVURQXCJcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlUG9ydFNwZWMge1xuICBuYW1lOiBzdHJpbmdcbiAgcHJvdG9jb2w6IFNlcnZpY2VQb3J0UHJvdG9jb2xcbiAgY29udGFpbmVyUG9ydDogbnVtYmVyXG4gIGhvc3RQb3J0PzogbnVtYmVyXG4gIG5vZGVQb3J0PzogbnVtYmVyXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZVZvbHVtZVNwZWMge1xuICBuYW1lOiBzdHJpbmdcbiAgY29udGFpbmVyUGF0aDogc3RyaW5nXG4gIGhvc3RQYXRoPzogc3RyaW5nXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZUhlYWx0aENoZWNrU3BlYyB7XG4gIGh0dHBHZXQ/OiB7XG4gICAgcGF0aDogc3RyaW5nLFxuICAgIHBvcnQ6IHN0cmluZyxcbiAgICBzY2hlbWU/OiBcIkhUVFBcIiB8IFwiSFRUUFNcIixcbiAgfSxcbiAgY29tbWFuZD86IHN0cmluZ1tdLFxuICB0Y3BQb3J0Pzogc3RyaW5nLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhaW5lclNlcnZpY2VTcGVjIGV4dGVuZHMgQmFzZVNlcnZpY2VTcGVjIHtcbiAgY29tbWFuZDogc3RyaW5nW10sXG4gIGRhZW1vbjogYm9vbGVhblxuICBpbmdyZXNzZXM6IENvbnRhaW5lckluZ3Jlc3NTcGVjW10sXG4gIGVudjogUHJpbWl0aXZlTWFwLFxuICBoZWFsdGhDaGVjaz86IFNlcnZpY2VIZWFsdGhDaGVja1NwZWMsXG4gIHBvcnRzOiBTZXJ2aWNlUG9ydFNwZWNbXSxcbiAgdm9sdW1lczogU2VydmljZVZvbHVtZVNwZWNbXSxcbn1cblxuZXhwb3J0IHR5cGUgQ29udGFpbmVyU2VydmljZUNvbmZpZyA9IFNlcnZpY2VDb25maWc8Q29udGFpbmVyU2VydmljZVNwZWM+XG5cbmNvbnN0IGluZ3Jlc3NTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIGhvc3RuYW1lOiBpbmdyZXNzSG9zdG5hbWVTY2hlbWEsXG4gICAgcGF0aDogSm9pLnN0cmluZygpLnVyaSg8YW55PnsgcmVsYXRpdmVPbmx5OiB0cnVlIH0pXG4gICAgICAuZGVmYXVsdChcIi9cIilcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBwYXRoIHdoaWNoIHNob3VsZCBiZSByb3V0ZWQgdG8gdGhlIHNlcnZpY2UuXCIpLFxuICAgIHBvcnQ6IEpvaS5zdHJpbmcoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBjb250YWluZXIgcG9ydCB3aGVyZSB0aGUgc3BlY2lmaWVkIHBhdGhzIHNob3VsZCBiZSByb3V0ZWQuXCIpLFxuICB9KVxuXG5jb25zdCBoZWFsdGhDaGVja1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgaHR0cEdldDogSm9pLm9iamVjdCgpXG4gICAgICAua2V5cyh7XG4gICAgICAgIHBhdGg6IEpvaS5zdHJpbmcoKVxuICAgICAgICAgIC51cmkoPGFueT57IHJlbGF0aXZlT25seTogdHJ1ZSB9KVxuICAgICAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHBhdGggb2YgdGhlIHNlcnZpY2UncyBoZWFsdGggY2hlY2sgZW5kcG9pbnQuXCIpLFxuICAgICAgICBwb3J0OiBKb2kuc3RyaW5nKClcbiAgICAgICAgICAucmVxdWlyZWQoKVxuICAgICAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBwb3J0IHdoZXJlIHRoZSBzZXJ2aWNlJ3MgaGVhbHRoIGNoZWNrIGVuZHBvaW50IHNob3VsZCBiZSBhdmFpbGFibGUuXCIpLFxuICAgICAgICBzY2hlbWU6IEpvaS5zdHJpbmcoKS5hbGxvdyhcIkhUVFBcIiwgXCJIVFRQU1wiKS5kZWZhdWx0KFwiSFRUUFwiKSxcbiAgICAgIH0pXG4gICAgICAuZGVzY3JpcHRpb24oXCJTZXQgdGhpcyB0byBjaGVjayB0aGUgc2VydmljZSdzIGhlYWx0aCBieSBtYWtpbmcgYW4gSFRUUCByZXF1ZXN0XCIpLFxuICAgIGNvbW1hbmQ6IEpvaS5hcnJheSgpLml0ZW1zKEpvaS5zdHJpbmcoKSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNldCB0aGlzIHRvIGNoZWNrIHRoZSBzZXJ2aWNlJ3MgaGVhbHRoIGJ5IHJ1bm5pbmcgYSBjb21tYW5kIGluIGl0cyBjb250YWluZXIuXCIpLFxuICAgIHRjcFBvcnQ6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiU2V0IHRoaXMgdG8gY2hlY2sgdGhlIHNlcnZpY2UncyBoZWFsdGggYnkgY2hlY2tpbmcgaWYgdGhpcyBUQ1AgcG9ydCBpcyBhY2NlcHRpbmcgY29ubmVjdGlvbnMuXCIpLFxuICB9KS54b3IoXCJodHRwR2V0XCIsIFwiY29tbWFuZFwiLCBcInRjcFBvcnRcIilcblxuY29uc3QgcG9ydFNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhlIHBvcnQgKHVzZWQgd2hlbiByZWZlcmVuY2luZyB0aGUgcG9ydCBlbHNld2hlcmUgaW4gdGhlIHNlcnZpY2UgY29uZmlndXJhdGlvbi5cIiksXG4gICAgcHJvdG9jb2w6IEpvaS5zdHJpbmcoKVxuICAgICAgLmFsbG93KFwiVENQXCIsIFwiVURQXCIpXG4gICAgICAuZGVmYXVsdChERUZBVUxUX1BPUlRfUFJPVE9DT0wpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcHJvdG9jb2wgb2YgdGhlIHNlcnZpY2UgY29udGFpbmVyIHBvcnQuXCIpLFxuICAgIGNvbnRhaW5lclBvcnQ6IEpvaS5udW1iZXIoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBwb3J0IG51bWJlciBvbiB0aGUgc2VydmljZSBjb250YWluZXIuXCIpLFxuICAgIGhvc3RQb3J0OiBKb2kubnVtYmVyKClcbiAgICAgIC5tZXRhKHsgZGVwcmVjYXRlZDogdHJ1ZSB9KSxcbiAgICBub2RlUG9ydDogSm9pLm51bWJlcigpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiU2V0IHRoaXMgdG8gZXhwb3NlIHRoZSBzZXJ2aWNlIG9uIHRoZSBzcGVjaWZpZWQgcG9ydCBvbiB0aGUgaG9zdCBub2RlIFwiICtcbiAgICAgICAgXCIobWF5IG5vdCBiZSBzdXBwb3J0ZWQgYnkgYWxsIHByb3ZpZGVycykuXCIsXG4gICAgICApLFxuICB9KVxuICAucmVxdWlyZWQoKVxuXG5jb25zdCB2b2x1bWVTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIG5hbWU6IGpvaUlkZW50aWZpZXIoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBhbGxvY2F0ZWQgdm9sdW1lLlwiKSxcbiAgICBjb250YWluZXJQYXRoOiBKb2kuc3RyaW5nKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcGF0aCB3aGVyZSB0aGUgdm9sdW1lIHNob3VsZCBiZSBtb3VudGVkIGluIHRoZSBjb250YWluZXIuXCIpLFxuICAgIGhvc3RQYXRoOiBKb2kuc3RyaW5nKClcbiAgICAgIC5tZXRhKHsgZGVwcmVjYXRlZDogdHJ1ZSB9KSxcbiAgfSlcblxuY29uc3Qgc2VydmljZVNjaGVtYSA9IGJhc2VTZXJ2aWNlU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBjb21tYW5kOiBKb2kuYXJyYXkoKS5pdGVtcyhKb2kuc3RyaW5nKCkpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgYXJndW1lbnRzIHRvIHJ1biB0aGUgY29udGFpbmVyIHdpdGggd2hlbiBzdGFydGluZyB0aGUgc2VydmljZS5cIiksXG4gICAgZGFlbW9uOiBKb2kuYm9vbGVhbigpXG4gICAgICAuZGVmYXVsdChmYWxzZSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIldoZXRoZXIgdG8gcnVuIHRoZSBzZXJ2aWNlIGFzIGEgZGFlbW9uICh0byBlbnN1cmUgb25seSBvbmUgcnVucyBwZXIgbm9kZSkuXCIpLFxuICAgIGluZ3Jlc3Nlczogam9pQXJyYXkoaW5ncmVzc1NjaGVtYSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIkxpc3Qgb2YgaW5ncmVzcyBlbmRwb2ludHMgdGhhdCB0aGUgc2VydmljZSBleHBvc2VzLlwiKVxuICAgICAgLmV4YW1wbGUoW3tcbiAgICAgICAgcGF0aDogXCIvYXBpXCIsXG4gICAgICAgIHBvcnQ6IFwiaHR0cFwiLFxuICAgICAgfV0pLFxuICAgIGVudjogam9pRW52VmFycygpLFxuICAgIGhlYWx0aENoZWNrOiBoZWFsdGhDaGVja1NjaGVtYVxuICAgICAgLmRlc2NyaXB0aW9uKFwiU3BlY2lmeSBob3cgdGhlIHNlcnZpY2UncyBoZWFsdGggc2hvdWxkIGJlIGNoZWNrZWQgYWZ0ZXIgZGVwbG95aW5nLlwiKSxcbiAgICBwb3J0czogam9pQXJyYXkocG9ydFNjaGVtYSlcbiAgICAgIC51bmlxdWUoXCJuYW1lXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJMaXN0IG9mIHBvcnRzIHRoYXQgdGhlIHNlcnZpY2UgY29udGFpbmVyIGV4cG9zZXMuXCIpLFxuICAgIHZvbHVtZXM6IGpvaUFycmF5KHZvbHVtZVNjaGVtYSlcbiAgICAgIC51bmlxdWUoXCJuYW1lXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJMaXN0IG9mIHZvbHVtZXMgdGhhdCBzaG91bGQgYmUgbW91bnRlZCB3aGVuIGRlcGxveWluZyB0aGUgY29udGFpbmVyLlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBDb250YWluZXJSZWdpc3RyeUNvbmZpZyB7XG4gIGhvc3RuYW1lOiBzdHJpbmcsXG4gIHBvcnQ/OiBudW1iZXIsXG4gIG5hbWVzcGFjZTogc3RyaW5nLFxufVxuXG5leHBvcnQgY29uc3QgY29udGFpbmVyUmVnaXN0cnlDb25maWdTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIGhvc3RuYW1lOiBKb2kuc3RyaW5nKClcbiAgICAgIC5ob3N0bmFtZSgpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGhvc3RuYW1lIChhbmQgb3B0aW9uYWxseSBwb3J0LCBpZiBub3QgdGhlIGRlZmF1bHQgcG9ydCkgb2YgdGhlIHJlZ2lzdHJ5LlwiKVxuICAgICAgLmV4YW1wbGUoXCJnY3IuaW9cIiksXG4gICAgcG9ydDogSm9pLm51bWJlcigpXG4gICAgICAuaW50ZWdlcigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcG9ydCB3aGVyZSB0aGUgcmVnaXN0cnkgbGlzdGVucyBvbiwgaWYgbm90IHRoZSBkZWZhdWx0LlwiKSxcbiAgICBuYW1lc3BhY2U6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlZmF1bHQoXCJfXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZXNwYWNlIGluIHRoZSByZWdpc3RyeSB3aGVyZSBpbWFnZXMgc2hvdWxkIGJlIHB1c2hlZC5cIilcbiAgICAgIC5leGFtcGxlKFwibXktcHJvamVjdFwiKSxcbiAgfSlcbiAgLnJlcXVpcmVkKClcbiAgLmRlc2NyaXB0aW9uKGRlZGVudGBcbiAgICBUaGUgcmVnaXN0cnkgd2hlcmUgYnVpbHQgY29udGFpbmVycyBzaG91bGQgYmUgcHVzaGVkIHRvLCBhbmQgdGhlbiBwdWxsZWQgdG8gdGhlIGNsdXN0ZXIgd2hlbiBkZXBsb3lpbmdcbiAgICBzZXJ2aWNlcy5cbiAgYClcblxuZXhwb3J0IGludGVyZmFjZSBDb250YWluZXJTZXJ2aWNlIGV4dGVuZHMgU2VydmljZTxDb250YWluZXJNb2R1bGU+IHsgfVxuXG5leHBvcnQgaW50ZXJmYWNlIENvbnRhaW5lclRlc3RTcGVjIGV4dGVuZHMgR2VuZXJpY1Rlc3RTcGVjIHsgfVxuXG5leHBvcnQgY29uc3QgY29udGFpbmVyVGVzdFNjaGVtYSA9IGdlbmVyaWNUZXN0U2NoZW1hXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ29udGFpbmVyTW9kdWxlU3BlYyBleHRlbmRzIE1vZHVsZVNwZWMge1xuICBidWlsZEFyZ3M6IFByaW1pdGl2ZU1hcCxcbiAgaW1hZ2U/OiBzdHJpbmcsXG4gIHNlcnZpY2VzOiBDb250YWluZXJTZXJ2aWNlU3BlY1tdLFxuICB0ZXN0czogQ29udGFpbmVyVGVzdFNwZWNbXSxcbn1cblxuZXhwb3J0IHR5cGUgQ29udGFpbmVyTW9kdWxlQ29uZmlnID0gTW9kdWxlQ29uZmlnPENvbnRhaW5lck1vZHVsZVNwZWM+XG5cbmV4cG9ydCBjb25zdCBkZWZhdWx0TmFtZXNwYWNlID0gXCJfXCJcbmV4cG9ydCBjb25zdCBkZWZhdWx0VGFnID0gXCJsYXRlc3RcIlxuXG5leHBvcnQgY29uc3QgY29udGFpbmVyTW9kdWxlU3BlY1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgYnVpbGRBcmdzOiBKb2kub2JqZWN0KClcbiAgICAgIC5wYXR0ZXJuKC8uKy8sIGpvaVByaW1pdGl2ZSgpKVxuICAgICAgLmRlZmF1bHQoKCkgPT4gKHt9KSwgXCJ7fVwiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiU3BlY2lmeSBidWlsZCBhcmd1bWVudHMgd2hlbiBidWlsZGluZyB0aGUgY29udGFpbmVyIGltYWdlLlwiKSxcbiAgICAvLyBUT0RPOiB2YWxpZGF0ZSB0aGUgaW1hZ2UgbmFtZSBmb3JtYXRcbiAgICBpbWFnZTogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiU3BlY2lmeSB0aGUgaW1hZ2UgbmFtZSBmb3IgdGhlIGNvbnRhaW5lci4gU2hvdWxkIGJlIGEgdmFsaWQgZG9ja2VyIGltYWdlIGlkZW50aWZpZXIuIElmIHNwZWNpZmllZCBhbmQgXCIgK1xuICAgICAgICBcInRoZSBtb2R1bGUgZG9lcyBub3QgY29udGFpbiBhIERvY2tlcmZpbGUsIHRoaXMgaW1hZ2Ugd2lsbCBiZSB1c2VkIHRvIGRlcGxveSB0aGUgY29udGFpbmVyIHNlcnZpY2VzLiBcIiArXG4gICAgICAgIFwiSWYgc3BlY2lmaWVkIGFuZCB0aGUgbW9kdWxlIGRvZXMgY29udGFpbiBhIERvY2tlcmZpbGUsIHRoaXMgaWRlbnRpZmllciBpcyB1c2VkIHdoZW4gcHVzaGluZyB0aGUgYnVpbHQgaW1hZ2UuXCIsXG4gICAgICApLFxuICAgIHNlcnZpY2VzOiBqb2lBcnJheShzZXJ2aWNlU2NoZW1hKVxuICAgICAgLnVuaXF1ZShcIm5hbWVcIilcbiAgICAgIC5kZXNjcmlwdGlvbihcIkxpc3Qgb2Ygc2VydmljZXMgdG8gZGVwbG95IGZyb20gdGhpcyBjb250YWluZXIgbW9kdWxlLlwiKSxcbiAgICB0ZXN0czogam9pQXJyYXkoY29udGFpbmVyVGVzdFNjaGVtYSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIkEgbGlzdCBvZiB0ZXN0cyB0byBydW4gaW4gdGhlIG1vZHVsZS5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIkNvbmZpZ3VyYXRpb24gZm9yIGEgY29udGFpbmVyIG1vZHVsZS5cIilcblxuZXhwb3J0IGludGVyZmFjZSBDb250YWluZXJNb2R1bGU8XG4gIE0gZXh0ZW5kcyBDb250YWluZXJNb2R1bGVTcGVjID0gQ29udGFpbmVyTW9kdWxlU3BlYyxcbiAgUyBleHRlbmRzIENvbnRhaW5lclNlcnZpY2VTcGVjID0gQ29udGFpbmVyU2VydmljZVNwZWMsXG4gIFQgZXh0ZW5kcyBDb250YWluZXJUZXN0U3BlYyA9IENvbnRhaW5lclRlc3RTcGVjLFxuICA+IGV4dGVuZHMgTW9kdWxlPE0sIFMsIFQ+IHsgfVxuXG5pbnRlcmZhY2UgUGFyc2VkSW1hZ2VJZCB7XG4gIGhvc3Q/OiBzdHJpbmdcbiAgbmFtZXNwYWNlPzogc3RyaW5nXG4gIHJlcG9zaXRvcnk6IHN0cmluZ1xuICB0YWc6IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3QgaGVscGVycyA9IHtcbiAgLyoqXG4gICAqIFJldHVybnMgdGhlIGltYWdlIElEIHVzZWQgbG9jYWxseSwgd2hlbiBidWlsZGluZyBhbmQgZGVwbG95aW5nIHRvIGxvY2FsIGVudmlyb25tZW50c1xuICAgKiAod2hlbiB3ZSBkb24ndCBuZWVkIHRvIHB1c2ggdG8gcmVtb3RlIHJlZ2lzdHJpZXMpLlxuICAgKi9cbiAgYXN5bmMgZ2V0TG9jYWxJbWFnZUlkKG1vZHVsZTogQ29udGFpbmVyTW9kdWxlKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBpZiAoYXdhaXQgaGVscGVycy5oYXNEb2NrZXJmaWxlKG1vZHVsZSkpIHtcbiAgICAgIGNvbnN0IHsgdmVyc2lvblN0cmluZyB9ID0gbW9kdWxlLnZlcnNpb25cbiAgICAgIHJldHVybiBgJHttb2R1bGUubmFtZX06JHt2ZXJzaW9uU3RyaW5nfWBcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG1vZHVsZS5zcGVjLmltYWdlIVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW1hZ2UgSUQgdG8gYmUgdXNlZCBmb3IgcHVibGlzaGluZyB0byBjb250YWluZXIgcmVnaXN0cmllc1xuICAgKiAobm90IHRvIGJlIGNvbmZ1c2VkIHdpdGggdGhlIElEIHVzZWQgd2hlbiBwdXNoaW5nIHRvIHByaXZhdGUgZGVwbG95bWVudCByZWdpc3RyaWVzKS5cbiAgICovXG4gIGFzeW5jIGdldFB1YmxpY0ltYWdlSWQobW9kdWxlOiBDb250YWluZXJNb2R1bGUpIHtcbiAgICAvLyBUT0RPOiBhbGxvdyBzZXR0aW5nIGEgZGVmYXVsdCB1c2VyL29yZyBwcmVmaXggaW4gdGhlIHByb2plY3QvcGx1Z2luIGNvbmZpZ1xuICAgIGNvbnN0IGltYWdlID0gbW9kdWxlLnNwZWMuaW1hZ2VcblxuICAgIGlmIChpbWFnZSkge1xuICAgICAgbGV0IFtpbWFnZU5hbWUsIHZlcnNpb25dID0gc3BsaXRGaXJzdChpbWFnZSwgXCI6XCIpXG5cbiAgICAgIGlmICh2ZXJzaW9uKSB7XG4gICAgICAgIC8vIHdlIHVzZSB0aGUgdmVyc2lvbiBpbiB0aGUgaW1hZ2UgbmFtZSwgaWYgc3BlY2lmaWVkXG4gICAgICAgIC8vIChhbGxvd3Mgc3BlY2lmeWluZyB2ZXJzaW9uIG9uIHNvdXJjZSBpbWFnZXMsIGFuZCBhbHNvIHNldHRpbmcgc3BlY2lmaWMgdmVyc2lvbiBuYW1lIHdoZW4gcHVibGlzaGluZyBpbWFnZXMpXG4gICAgICAgIHJldHVybiBpbWFnZVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgY29uc3QgeyB2ZXJzaW9uU3RyaW5nIH0gPSBtb2R1bGUudmVyc2lvblxuICAgICAgICByZXR1cm4gYCR7aW1hZ2VOYW1lfToke3ZlcnNpb25TdHJpbmd9YFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICByZXR1cm4gaGVscGVycy5nZXRMb2NhbEltYWdlSWQobW9kdWxlKVxuICAgIH1cbiAgfSxcblxuICAvKipcbiAgICogUmV0dXJucyB0aGUgaW1hZ2UgSUQgdG8gYmUgdXNlZCB3aGVuIHB1c2hpbmcgdG8gZGVwbG95bWVudCByZWdpc3RyaWVzLlxuICAgKi9cbiAgYXN5bmMgZ2V0RGVwbG95bWVudEltYWdlSWQobW9kdWxlOiBDb250YWluZXJNb2R1bGUsIHJlZ2lzdHJ5Q29uZmlnPzogQ29udGFpbmVyUmVnaXN0cnlDb25maWcpIHtcbiAgICBjb25zdCBsb2NhbElkID0gYXdhaXQgaGVscGVycy5nZXRMb2NhbEltYWdlSWQobW9kdWxlKVxuXG4gICAgaWYgKCFyZWdpc3RyeUNvbmZpZykge1xuICAgICAgcmV0dXJuIGxvY2FsSWRcbiAgICB9XG5cbiAgICBjb25zdCBwYXJzZWRJZCA9IGhlbHBlcnMucGFyc2VJbWFnZUlkKGxvY2FsSWQpXG5cbiAgICBjb25zdCBob3N0ID0gcmVnaXN0cnlDb25maWcucG9ydCA/IGAke3JlZ2lzdHJ5Q29uZmlnLmhvc3RuYW1lfToke3JlZ2lzdHJ5Q29uZmlnLnBvcnR9YCA6IHJlZ2lzdHJ5Q29uZmlnLmhvc3RuYW1lXG5cbiAgICByZXR1cm4gaGVscGVycy51bnBhcnNlSW1hZ2VJZCh7XG4gICAgICBob3N0LFxuICAgICAgbmFtZXNwYWNlOiByZWdpc3RyeUNvbmZpZy5uYW1lc3BhY2UsXG4gICAgICByZXBvc2l0b3J5OiBwYXJzZWRJZC5yZXBvc2l0b3J5LFxuICAgICAgdGFnOiBwYXJzZWRJZC50YWcsXG4gICAgfSlcbiAgfSxcblxuICBwYXJzZUltYWdlSWQoaW1hZ2VJZDogc3RyaW5nKTogUGFyc2VkSW1hZ2VJZCB7XG4gICAgY29uc3QgcGFydHMgPSBpbWFnZUlkLnNwbGl0KFwiL1wiKVxuICAgIGxldCBbcmVwb3NpdG9yeSwgdGFnXSA9IHBhcnRzWzBdLnNwbGl0KFwiOlwiKVxuICAgIGlmICghdGFnKSB7XG4gICAgICB0YWcgPSBkZWZhdWx0VGFnXG4gICAgfVxuXG4gICAgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMSkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgbmFtZXNwYWNlOiBkZWZhdWx0TmFtZXNwYWNlLFxuICAgICAgICByZXBvc2l0b3J5LFxuICAgICAgICB0YWcsXG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChwYXJ0cy5sZW5ndGggPT09IDIpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIG5hbWVzcGFjZTogcGFydHNbMF0sXG4gICAgICAgIHJlcG9zaXRvcnksXG4gICAgICAgIHRhZyxcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHBhcnRzLmxlbmd0aCA9PT0gMykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgaG9zdDogcGFydHNbMF0sXG4gICAgICAgIG5hbWVzcGFjZTogcGFydHNbMV0sXG4gICAgICAgIHJlcG9zaXRvcnksXG4gICAgICAgIHRhZyxcbiAgICAgIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihgSW52YWxpZCBjb250YWluZXIgaW1hZ2UgdGFnOiAke2ltYWdlSWR9YCwgeyBpbWFnZUlkIH0pXG4gICAgfVxuICB9LFxuXG4gIHVucGFyc2VJbWFnZUlkKHBhcnNlZDogUGFyc2VkSW1hZ2VJZCkge1xuICAgIGNvbnN0IG5hbWUgPSBgJHtwYXJzZWQucmVwb3NpdG9yeX06JHtwYXJzZWQudGFnfWBcblxuICAgIGlmIChwYXJzZWQuaG9zdCkge1xuICAgICAgcmV0dXJuIGAke3BhcnNlZC5ob3N0fS8ke3BhcnNlZC5uYW1lc3BhY2V9LyR7bmFtZX1gXG4gICAgfSBlbHNlIGlmIChwYXJzZWQubmFtZXNwYWNlKSB7XG4gICAgICByZXR1cm4gYCR7cGFyc2VkLm5hbWVzcGFjZX0vJHtuYW1lfWBcbiAgICB9IGVsc2Uge1xuICAgICAgcmV0dXJuIG5hbWVcbiAgICB9XG4gIH0sXG5cbiAgYXN5bmMgcHVsbEltYWdlKG1vZHVsZTogQ29udGFpbmVyTW9kdWxlKSB7XG4gICAgY29uc3QgaWRlbnRpZmllciA9IGF3YWl0IGhlbHBlcnMuZ2V0UHVibGljSW1hZ2VJZChtb2R1bGUpXG4gICAgYXdhaXQgaGVscGVycy5kb2NrZXJDbGkobW9kdWxlLCBgcHVsbCAke2lkZW50aWZpZXJ9YClcbiAgfSxcblxuICBhc3luYyBpbWFnZUV4aXN0c0xvY2FsbHkobW9kdWxlOiBDb250YWluZXJNb2R1bGUpIHtcbiAgICBjb25zdCBpZGVudGlmaWVyID0gYXdhaXQgaGVscGVycy5nZXRMb2NhbEltYWdlSWQobW9kdWxlKVxuICAgIGNvbnN0IGV4aXN0cyA9IChhd2FpdCBoZWxwZXJzLmRvY2tlckNsaShtb2R1bGUsIGBpbWFnZXMgJHtpZGVudGlmaWVyfSAtcWApKS5zdGRvdXQudHJpbSgpLmxlbmd0aCA+IDBcbiAgICByZXR1cm4gZXhpc3RzID8gaWRlbnRpZmllciA6IG51bGxcbiAgfSxcblxuICBhc3luYyBkb2NrZXJDbGkobW9kdWxlOiBDb250YWluZXJNb2R1bGUsIGFyZ3MpIHtcbiAgICAvLyBUT0RPOiB1c2UgZG9ja2Vyb2RlIGluc3RlYWQgb2YgQ0xJXG4gICAgcmV0dXJuIGNoaWxkUHJvY2Vzcy5leGVjKFwiZG9ja2VyIFwiICsgYXJncywgeyBjd2Q6IG1vZHVsZS5idWlsZFBhdGgsIG1heEJ1ZmZlcjogMTAyNCAqIDEwMjQgfSlcbiAgfSxcblxuICBhc3luYyBoYXNEb2NrZXJmaWxlKG1vZHVsZTogQ29udGFpbmVyTW9kdWxlKSB7XG4gICAgY29uc3QgYnVpbGRQYXRoID0gbW9kdWxlLmJ1aWxkUGF0aFxuICAgIHJldHVybiBwYXRoRXhpc3RzKGpvaW4oYnVpbGRQYXRoLCBcIkRvY2tlcmZpbGVcIikpXG4gIH0sXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiB2YWxpZGF0ZUNvbnRhaW5lck1vZHVsZSh7IG1vZHVsZUNvbmZpZyB9OiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxDb250YWluZXJNb2R1bGU+KSB7XG4gIG1vZHVsZUNvbmZpZy5zcGVjID0gdmFsaWRhdGUobW9kdWxlQ29uZmlnLnNwZWMsIGNvbnRhaW5lck1vZHVsZVNwZWNTY2hlbWEsIHsgY29udGV4dDogYG1vZHVsZSAke21vZHVsZUNvbmZpZy5uYW1lfWAgfSlcblxuICAvLyB2YWxpZGF0ZSBzZXJ2aWNlc1xuICBtb2R1bGVDb25maWcuc2VydmljZUNvbmZpZ3MgPSBtb2R1bGVDb25maWcuc3BlYy5zZXJ2aWNlcy5tYXAoc3BlYyA9PiB7XG4gICAgLy8gbWFrZSBzdXJlIHBvcnRzIGFyZSBjb3JyZWN0bHkgY29uZmlndXJlZFxuICAgIGNvbnN0IG5hbWUgPSBzcGVjLm5hbWVcbiAgICBjb25zdCBkZWZpbmVkUG9ydHMgPSBzcGVjLnBvcnRzXG4gICAgY29uc3QgcG9ydHNCeU5hbWUgPSBrZXlCeShzcGVjLnBvcnRzLCBcIm5hbWVcIilcblxuICAgIGZvciAoY29uc3QgaW5ncmVzcyBvZiBzcGVjLmluZ3Jlc3Nlcykge1xuICAgICAgY29uc3QgaW5ncmVzc1BvcnQgPSBpbmdyZXNzLnBvcnRcblxuICAgICAgaWYgKCFwb3J0c0J5TmFtZVtpbmdyZXNzUG9ydF0pIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgICBgU2VydmljZSAke25hbWV9IGRvZXMgbm90IGRlZmluZSBwb3J0ICR7aW5ncmVzc1BvcnR9IGRlZmluZWQgaW4gaW5ncmVzc2AsXG4gICAgICAgICAgeyBkZWZpbmVkUG9ydHMsIGluZ3Jlc3NQb3J0IH0sXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3BlYy5oZWFsdGhDaGVjayAmJiBzcGVjLmhlYWx0aENoZWNrLmh0dHBHZXQpIHtcbiAgICAgIGNvbnN0IGhlYWx0aENoZWNrSHR0cFBvcnQgPSBzcGVjLmhlYWx0aENoZWNrLmh0dHBHZXQucG9ydFxuXG4gICAgICBpZiAoIXBvcnRzQnlOYW1lW2hlYWx0aENoZWNrSHR0cFBvcnRdKSB7XG4gICAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICAgICAgYFNlcnZpY2UgJHtuYW1lfSBkb2VzIG5vdCBkZWZpbmUgcG9ydCAke2hlYWx0aENoZWNrSHR0cFBvcnR9IGRlZmluZWQgaW4gaHR0cEdldCBoZWFsdGggY2hlY2tgLFxuICAgICAgICAgIHsgZGVmaW5lZFBvcnRzLCBoZWFsdGhDaGVja0h0dHBQb3J0IH0sXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG5cbiAgICBpZiAoc3BlYy5oZWFsdGhDaGVjayAmJiBzcGVjLmhlYWx0aENoZWNrLnRjcFBvcnQpIHtcbiAgICAgIGNvbnN0IGhlYWx0aENoZWNrVGNwUG9ydCA9IHNwZWMuaGVhbHRoQ2hlY2sudGNwUG9ydFxuXG4gICAgICBpZiAoIXBvcnRzQnlOYW1lW2hlYWx0aENoZWNrVGNwUG9ydF0pIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgICBgU2VydmljZSAke25hbWV9IGRvZXMgbm90IGRlZmluZSBwb3J0ICR7aGVhbHRoQ2hlY2tUY3BQb3J0fSBkZWZpbmVkIGluIHRjcFBvcnQgaGVhbHRoIGNoZWNrYCxcbiAgICAgICAgICB7IGRlZmluZWRQb3J0cywgaGVhbHRoQ2hlY2tUY3BQb3J0IH0sXG4gICAgICAgIClcbiAgICAgIH1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgbmFtZSxcbiAgICAgIGRlcGVuZGVuY2llczogc3BlYy5kZXBlbmRlbmNpZXMsXG4gICAgICBvdXRwdXRzOiBzcGVjLm91dHB1dHMsXG4gICAgICBzcGVjLFxuICAgIH1cbiAgfSlcblxuICBtb2R1bGVDb25maWcudGVzdENvbmZpZ3MgPSBtb2R1bGVDb25maWcuc3BlYy50ZXN0cy5tYXAodCA9PiAoe1xuICAgIG5hbWU6IHQubmFtZSxcbiAgICBkZXBlbmRlbmNpZXM6IHQuZGVwZW5kZW5jaWVzLFxuICAgIHNwZWM6IHQsXG4gICAgdGltZW91dDogdC50aW1lb3V0LFxuICB9KSlcblxuICAvLyBtYWtlIHN1cmUgd2UgY2FuIGJ1aWxkIHRoZSB0aGluZ1xuICBpZiAoIW1vZHVsZUNvbmZpZy5zcGVjLmltYWdlICYmICEoYXdhaXQgcGF0aEV4aXN0cyhqb2luKG1vZHVsZUNvbmZpZy5wYXRoLCBcIkRvY2tlcmZpbGVcIikpKSkge1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICBgTW9kdWxlICR7bW9kdWxlQ29uZmlnLm5hbWV9IG5laXRoZXIgc3BlY2lmaWVzIGltYWdlIG5vciBwcm92aWRlcyBEb2NrZXJmaWxlYCxcbiAgICAgIHt9LFxuICAgIClcbiAgfVxuXG4gIHJldHVybiBtb2R1bGVDb25maWdcbn1cblxuLy8gVE9ETzogcmVuYW1lIHRoaXMgcGx1Z2luIHRvIGRvY2tlclxuZXhwb3J0IGNvbnN0IGdhcmRlblBsdWdpbiA9ICgpOiBHYXJkZW5QbHVnaW4gPT4gKHtcbiAgbW9kdWxlQWN0aW9uczoge1xuICAgIGNvbnRhaW5lcjoge1xuICAgICAgdmFsaWRhdGU6IHZhbGlkYXRlQ29udGFpbmVyTW9kdWxlLFxuXG4gICAgICBhc3luYyBnZXRCdWlsZFN0YXR1cyh7IG1vZHVsZSwgbG9nRW50cnkgfTogR2V0QnVpbGRTdGF0dXNQYXJhbXM8Q29udGFpbmVyTW9kdWxlPikge1xuICAgICAgICBjb25zdCBpZGVudGlmaWVyID0gYXdhaXQgaGVscGVycy5pbWFnZUV4aXN0c0xvY2FsbHkobW9kdWxlKVxuXG4gICAgICAgIGlmIChpZGVudGlmaWVyKSB7XG4gICAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkuZGVidWcoe1xuICAgICAgICAgICAgc2VjdGlvbjogbW9kdWxlLm5hbWUsXG4gICAgICAgICAgICBtc2c6IGBJbWFnZSAke2lkZW50aWZpZXJ9IGFscmVhZHkgZXhpc3RzYCxcbiAgICAgICAgICAgIHN5bWJvbDogXCJpbmZvXCIsXG4gICAgICAgICAgfSlcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiB7IHJlYWR5OiAhIWlkZW50aWZpZXIgfVxuICAgICAgfSxcblxuICAgICAgYXN5bmMgYnVpbGQoeyBtb2R1bGUsIGxvZ0VudHJ5IH06IEJ1aWxkTW9kdWxlUGFyYW1zPENvbnRhaW5lck1vZHVsZT4pIHtcbiAgICAgICAgY29uc3QgYnVpbGRQYXRoID0gbW9kdWxlLmJ1aWxkUGF0aFxuICAgICAgICBjb25zdCBpbWFnZSA9IG1vZHVsZS5zcGVjLmltYWdlXG5cbiAgICAgICAgaWYgKCEhaW1hZ2UgJiYgIShhd2FpdCBoZWxwZXJzLmhhc0RvY2tlcmZpbGUobW9kdWxlKSkpIHtcbiAgICAgICAgICBpZiAoYXdhaXQgaGVscGVycy5pbWFnZUV4aXN0c0xvY2FsbHkobW9kdWxlKSkge1xuICAgICAgICAgICAgcmV0dXJuIHsgZnJlc2g6IGZhbHNlIH1cbiAgICAgICAgICB9XG4gICAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkuc2V0U3RhdGUoYFB1bGxpbmcgaW1hZ2UgJHtpbWFnZX0uLi5gKVxuICAgICAgICAgIGF3YWl0IGhlbHBlcnMucHVsbEltYWdlKG1vZHVsZSlcbiAgICAgICAgICByZXR1cm4geyBmZXRjaGVkOiB0cnVlIH1cbiAgICAgICAgfVxuXG4gICAgICAgIGNvbnN0IGlkZW50aWZpZXIgPSBhd2FpdCBoZWxwZXJzLmdldExvY2FsSW1hZ2VJZChtb2R1bGUpXG5cbiAgICAgICAgLy8gYnVpbGQgZG9lc24ndCBleGlzdCwgc28gd2UgY3JlYXRlIGl0XG4gICAgICAgIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LnNldFN0YXRlKGBCdWlsZGluZyAke2lkZW50aWZpZXJ9Li4uYClcblxuICAgICAgICBjb25zdCBidWlsZEFyZ3MgPSBPYmplY3QuZW50cmllcyhtb2R1bGUuc3BlYy5idWlsZEFyZ3MpLm1hcCgoW2tleSwgdmFsdWVdKSA9PiB7XG4gICAgICAgICAgLy8gVE9ETzogbWF5IG5lZWQgdG8gZXNjYXBlIHRoaXNcbiAgICAgICAgICByZXR1cm4gYC0tYnVpbGQtYXJnICR7a2V5fT0ke3ZhbHVlfWBcbiAgICAgICAgfSkuam9pbihcIiBcIilcblxuICAgICAgICAvLyBUT0RPOiBsb2cgZXJyb3IgaWYgaXQgb2NjdXJzXG4gICAgICAgIC8vIFRPRE86IHN0cmVhbSBvdXRwdXQgdG8gbG9nIGlmIGF0IGRlYnVnIGxvZyBsZXZlbFxuICAgICAgICBhd2FpdCBoZWxwZXJzLmRvY2tlckNsaShtb2R1bGUsIGBidWlsZCAke2J1aWxkQXJnc30gLXQgJHtpZGVudGlmaWVyfSAke2J1aWxkUGF0aH1gKVxuXG4gICAgICAgIHJldHVybiB7IGZyZXNoOiB0cnVlLCBkZXRhaWxzOiB7IGlkZW50aWZpZXIgfSB9XG4gICAgICB9LFxuXG4gICAgICBhc3luYyBwdWJsaXNoTW9kdWxlKHsgbW9kdWxlLCBsb2dFbnRyeSB9OiBQdWJsaXNoTW9kdWxlUGFyYW1zPENvbnRhaW5lck1vZHVsZT4pIHtcbiAgICAgICAgaWYgKCEoYXdhaXQgaGVscGVycy5oYXNEb2NrZXJmaWxlKG1vZHVsZSkpKSB7XG4gICAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkuc2V0U3RhdGUoeyBtc2c6IGBOb3RoaW5nIHRvIHB1Ymxpc2hgIH0pXG4gICAgICAgICAgcmV0dXJuIHsgcHVibGlzaGVkOiBmYWxzZSB9XG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBsb2NhbElkID0gYXdhaXQgaGVscGVycy5nZXRMb2NhbEltYWdlSWQobW9kdWxlKVxuICAgICAgICBjb25zdCByZW1vdGVJZCA9IGF3YWl0IGhlbHBlcnMuZ2V0UHVibGljSW1hZ2VJZChtb2R1bGUpXG5cbiAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkuc2V0U3RhdGUoeyBtc2c6IGBQdWJsaXNoaW5nIGltYWdlICR7cmVtb3RlSWR9Li4uYCB9KVxuXG4gICAgICAgIGlmIChsb2NhbElkICE9PSByZW1vdGVJZCkge1xuICAgICAgICAgIGF3YWl0IGhlbHBlcnMuZG9ja2VyQ2xpKG1vZHVsZSwgYHRhZyAke2xvY2FsSWR9ICR7cmVtb3RlSWR9YClcbiAgICAgICAgfVxuXG4gICAgICAgIC8vIFRPRE86IGxvZyBlcnJvciBpZiBpdCBvY2N1cnNcbiAgICAgICAgLy8gVE9ETzogc3RyZWFtIG91dHB1dCB0byBsb2cgaWYgYXQgZGVidWcgbG9nIGxldmVsXG4gICAgICAgIC8vIFRPRE86IGNoZWNrIGlmIG1vZHVsZSBhbHJlYWR5IGV4aXN0cyByZW1vdGVseT9cbiAgICAgICAgYXdhaXQgaGVscGVycy5kb2NrZXJDbGkobW9kdWxlLCBgcHVzaCAke3JlbW90ZUlkfWApXG5cbiAgICAgICAgcmV0dXJuIHsgcHVibGlzaGVkOiB0cnVlLCBtZXNzYWdlOiBgUHVibGlzaGVkICR7cmVtb3RlSWR9YCB9XG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59KVxuIl19 diff --git a/garden-service/build/plugins/generic.d.ts b/garden-service/build/plugins/generic.d.ts new file mode 100644 index 00000000000..f989167e9da --- /dev/null +++ b/garden-service/build/plugins/generic.d.ts @@ -0,0 +1,32 @@ +import * as Joi from "joi"; +import { GardenPlugin } from "../types/plugin/plugin"; +import { Module } from "../types/module"; +import { BuildResult, BuildStatus, ValidateModuleResult, TestResult } from "../types/plugin/outputs"; +import { BuildModuleParams, GetBuildStatusParams, ValidateModuleParams, TestModuleParams } from "../types/plugin/params"; +import { BaseServiceSpec } from "../config/service"; +import { BaseTestSpec } from "../config/test"; +import { ModuleSpec } from "../config/module"; +export declare const name = "generic"; +export interface GenericTestSpec extends BaseTestSpec { + command: string[]; + env: { + [key: string]: string; + }; +} +export declare const genericTestSchema: Joi.ObjectSchema; +export interface GenericModuleSpec extends ModuleSpec { + env: { + [key: string]: string; + }; + tests: GenericTestSpec[]; +} +export declare const genericModuleSpecSchema: Joi.ObjectSchema; +export interface GenericModule extends Module { +} +export declare function parseGenericModule({ moduleConfig }: ValidateModuleParams): Promise; +export declare function getGenericModuleBuildStatus({ module }: GetBuildStatusParams): Promise; +export declare function buildGenericModule({ module }: BuildModuleParams): Promise; +export declare function testGenericModule({ module, testConfig }: TestModuleParams): Promise; +export declare const genericPlugin: GardenPlugin; +export declare const gardenPlugin: () => GardenPlugin; +//# sourceMappingURL=generic.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/generic.js b/garden-service/build/plugins/generic.js new file mode 100644 index 00000000000..4361f4f2f2f --- /dev/null +++ b/garden-service/build/plugins/generic.js @@ -0,0 +1,126 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const common_1 = require("../config/common"); +const test_1 = require("../config/test"); +const base_1 = require("../vcs/base"); +const constants_1 = require("../constants"); +const execa = require("execa"); +exports.name = "generic"; +exports.genericTestSchema = test_1.baseTestSpecSchema + .keys({ + command: Joi.array().items(Joi.string()) + .description("The command to run in the module build context in order to test it."), + env: common_1.joiEnvVars(), +}) + .description("The test specification of a generic module."); +exports.genericModuleSpecSchema = Joi.object() + .keys({ + env: common_1.joiEnvVars(), + tests: common_1.joiArray(exports.genericTestSchema) + .description("A list of tests to run in the module."), +}) + .unknown(false) + .description("The module specification for a generic module."); +function parseGenericModule({ moduleConfig }) { + return __awaiter(this, void 0, void 0, function* () { + moduleConfig.spec = common_1.validate(moduleConfig.spec, exports.genericModuleSpecSchema, { context: `module ${moduleConfig.name}` }); + moduleConfig.testConfigs = moduleConfig.spec.tests.map(t => ({ + name: t.name, + dependencies: t.dependencies, + spec: t, + timeout: t.timeout, + })); + return moduleConfig; + }); +} +exports.parseGenericModule = parseGenericModule; +function getGenericModuleBuildStatus({ module }) { + return __awaiter(this, void 0, void 0, function* () { + const buildVersionFilePath = path_1.join(module.buildPath, constants_1.GARDEN_BUILD_VERSION_FILENAME); + let builtVersion = null; + try { + builtVersion = yield base_1.readModuleVersionFile(buildVersionFilePath); + } + catch (_) { + // just ignore this error, can be caused by an outdated format + } + if (builtVersion && builtVersion.versionString === module.version.versionString) { + return { ready: true }; + } + return { ready: false }; + }); +} +exports.getGenericModuleBuildStatus = getGenericModuleBuildStatus; +function buildGenericModule({ module }) { + return __awaiter(this, void 0, void 0, function* () { + const config = module; + const output = {}; + const buildPath = module.buildPath; + if (config.build.command.length) { + const res = yield execa.shell(config.build.command.join(" "), { + cwd: buildPath, + env: Object.assign({}, process.env, lodash_1.mapValues(module.spec.env, v => v.toString())), + }); + output.fresh = true; + output.buildLog = res.stdout + res.stderr; + } + // keep track of which version has been built + const buildVersionFilePath = path_1.join(buildPath, constants_1.GARDEN_BUILD_VERSION_FILENAME); + yield base_1.writeModuleVersionFile(buildVersionFilePath, module.version); + return output; + }); +} +exports.buildGenericModule = buildGenericModule; +function testGenericModule({ module, testConfig }) { + return __awaiter(this, void 0, void 0, function* () { + const startedAt = new Date(); + const command = testConfig.spec.command; + const result = yield execa.shell(command.join(" "), { + cwd: module.path, + env: Object.assign({}, process.env, lodash_1.mapValues(module.spec.env, v => v + ""), lodash_1.mapValues(testConfig.spec.env, v => v + "")), + reject: false, + }); + return { + moduleName: module.name, + command, + testName: testConfig.name, + version: module.version, + success: result.code === 0, + startedAt, + completedAt: new Date(), + output: result.stdout + result.stderr, + }; + }); +} +exports.testGenericModule = testGenericModule; +exports.genericPlugin = { + moduleActions: { + generic: { + validate: parseGenericModule, + getBuildStatus: getGenericModuleBuildStatus, + build: buildGenericModule, + testModule: testGenericModule, + }, + }, +}; +exports.gardenPlugin = () => exports.genericPlugin; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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RyxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUMvQztZQUNELE1BQU0sRUFBRSxLQUFLO1NBQ2QsQ0FDRixDQUFBO1FBRUQsT0FBTztZQUNMLFVBQVUsRUFBRSxNQUFNLENBQUMsSUFBSTtZQUN2QixPQUFPO1lBQ1AsUUFBUSxFQUFFLFVBQVUsQ0FBQyxJQUFJO1lBQ3pCLE9BQU8sRUFBRSxNQUFNLENBQUMsT0FBTztZQUN2QixPQUFPLEVBQUUsTUFBTSxDQUFDLElBQUksS0FBSyxDQUFDO1lBQzFCLFNBQVM7WUFDVCxXQUFXLEVBQUUsSUFBSSxJQUFJLEVBQUU7WUFDdkIsTUFBTSxFQUFFLE1BQU0sQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFDLE1BQU07U0FDdEMsQ0FBQTtJQUNILENBQUM7Q0FBQTtBQTVCRCw4Q0E0QkM7QUFFWSxRQUFBLGFBQWEsR0FBaUI7SUFDekMsYUFBYSxFQUFFO1FBQ2IsT0FBTyxFQUFFO1lBQ1AsUUFBUSxFQUFFLGtCQUFrQjtZQUM1QixjQUFjLEVBQUUsMkJBQTJCO1lBQzNDLEtBQUssRUFBRSxrQkFBa0I7WUFDekIsVUFBVSxFQUFFLGlCQUFpQjtTQUM5QjtLQUNGO0NBQ0YsQ0FBQTtBQUVZLFFBQUEsWUFBWSxHQUFHLEdBQUcsRUFBRSxDQUFDLHFCQUFhLENBQUEiLCJmaWxlIjoicGx1Z2lucy9nZW5lcmljLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IG1hcFZhbHVlcyB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7XG4gIGpvaUFycmF5LFxuICBqb2lFbnZWYXJzLFxuICB2YWxpZGF0ZSxcbn0gZnJvbSBcIi4uL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHtcbiAgR2FyZGVuUGx1Z2luLFxufSBmcm9tIFwiLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7XG4gIEJ1aWxkUmVzdWx0LFxuICBCdWlsZFN0YXR1cyxcbiAgVmFsaWRhdGVNb2R1bGVSZXN1bHQsXG4gIFRlc3RSZXN1bHQsXG59IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQge1xuICBCdWlsZE1vZHVsZVBhcmFtcyxcbiAgR2V0QnVpbGRTdGF0dXNQYXJhbXMsXG4gIFZhbGlkYXRlTW9kdWxlUGFyYW1zLFxuICBUZXN0TW9kdWxlUGFyYW1zLFxufSBmcm9tIFwiLi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQgeyBCYXNlU2VydmljZVNwZWMgfSBmcm9tIFwiLi4vY29uZmlnL3NlcnZpY2VcIlxuaW1wb3J0IHsgQmFzZVRlc3RTcGVjLCBiYXNlVGVzdFNwZWNTY2hlbWEgfSBmcm9tIFwiLi4vY29uZmlnL3Rlc3RcIlxuaW1wb3J0IHsgcmVhZE1vZHVsZVZlcnNpb25GaWxlLCB3cml0ZU1vZHVsZVZlcnNpb25GaWxlLCBNb2R1bGVWZXJzaW9uIH0gZnJvbSBcIi4uL3Zjcy9iYXNlXCJcbmltcG9ydCB7IEdBUkRFTl9CVUlMRF9WRVJTSU9OX0ZJTEVOQU1FIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiXG5pbXBvcnQgeyBNb2R1bGVTcGVjLCBNb2R1bGVDb25maWcgfSBmcm9tIFwiLi4vY29uZmlnL21vZHVsZVwiXG5pbXBvcnQgZXhlY2EgPSByZXF1aXJlKFwiZXhlY2FcIilcblxuZXhwb3J0IGNvbnN0IG5hbWUgPSBcImdlbmVyaWNcIlxuXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyaWNUZXN0U3BlYyBleHRlbmRzIEJhc2VUZXN0U3BlYyB7XG4gIGNvbW1hbmQ6IHN0cmluZ1tdLFxuICBlbnY6IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIH0sXG59XG5cbmV4cG9ydCBjb25zdCBnZW5lcmljVGVzdFNjaGVtYSA9IGJhc2VUZXN0U3BlY1NjaGVtYVxuICAua2V5cyh7XG4gICAgY29tbWFuZDogSm9pLmFycmF5KCkuaXRlbXMoSm9pLnN0cmluZygpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGNvbW1hbmQgdG8gcnVuIGluIHRoZSBtb2R1bGUgYnVpbGQgY29udGV4dCBpbiBvcmRlciB0byB0ZXN0IGl0LlwiKSxcbiAgICBlbnY6IGpvaUVudlZhcnMoKSxcbiAgfSlcbiAgLmRlc2NyaXB0aW9uKFwiVGhlIHRlc3Qgc3BlY2lmaWNhdGlvbiBvZiBhIGdlbmVyaWMgbW9kdWxlLlwiKVxuXG5leHBvcnQgaW50ZXJmYWNlIEdlbmVyaWNNb2R1bGVTcGVjIGV4dGVuZHMgTW9kdWxlU3BlYyB7XG4gIGVudjogeyBba2V5OiBzdHJpbmddOiBzdHJpbmcgfSxcbiAgdGVzdHM6IEdlbmVyaWNUZXN0U3BlY1tdLFxufVxuXG5leHBvcnQgY29uc3QgZ2VuZXJpY01vZHVsZVNwZWNTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIGVudjogam9pRW52VmFycygpLFxuICAgIHRlc3RzOiBqb2lBcnJheShnZW5lcmljVGVzdFNjaGVtYSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIkEgbGlzdCBvZiB0ZXN0cyB0byBydW4gaW4gdGhlIG1vZHVsZS5cIiksXG4gIH0pXG4gIC51bmtub3duKGZhbHNlKVxuICAuZGVzY3JpcHRpb24oXCJUaGUgbW9kdWxlIHNwZWNpZmljYXRpb24gZm9yIGEgZ2VuZXJpYyBtb2R1bGUuXCIpXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2VuZXJpY01vZHVsZSBleHRlbmRzIE1vZHVsZTxHZW5lcmljTW9kdWxlU3BlYywgQmFzZVNlcnZpY2VTcGVjLCBHZW5lcmljVGVzdFNwZWM+IHsgfVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcGFyc2VHZW5lcmljTW9kdWxlKFxuICB7IG1vZHVsZUNvbmZpZyB9OiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxHZW5lcmljTW9kdWxlPixcbik6IFByb21pc2U8VmFsaWRhdGVNb2R1bGVSZXN1bHQ+IHtcbiAgbW9kdWxlQ29uZmlnLnNwZWMgPSB2YWxpZGF0ZShtb2R1bGVDb25maWcuc3BlYywgZ2VuZXJpY01vZHVsZVNwZWNTY2hlbWEsIHsgY29udGV4dDogYG1vZHVsZSAke21vZHVsZUNvbmZpZy5uYW1lfWAgfSlcblxuICBtb2R1bGVDb25maWcudGVzdENvbmZpZ3MgPSBtb2R1bGVDb25maWcuc3BlYy50ZXN0cy5tYXAodCA9PiAoe1xuICAgIG5hbWU6IHQubmFtZSxcbiAgICBkZXBlbmRlbmNpZXM6IHQuZGVwZW5kZW5jaWVzLFxuICAgIHNwZWM6IHQsXG4gICAgdGltZW91dDogdC50aW1lb3V0LFxuICB9KSlcblxuICByZXR1cm4gbW9kdWxlQ29uZmlnXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRHZW5lcmljTW9kdWxlQnVpbGRTdGF0dXMoeyBtb2R1bGUgfTogR2V0QnVpbGRTdGF0dXNQYXJhbXMpOiBQcm9taXNlPEJ1aWxkU3RhdHVzPiB7XG4gIGNvbnN0IGJ1aWxkVmVyc2lvbkZpbGVQYXRoID0gam9pbihtb2R1bGUuYnVpbGRQYXRoLCBHQVJERU5fQlVJTERfVkVSU0lPTl9GSUxFTkFNRSlcbiAgbGV0IGJ1aWx0VmVyc2lvbjogTW9kdWxlVmVyc2lvbiB8IG51bGwgPSBudWxsXG5cbiAgdHJ5IHtcbiAgICBidWlsdFZlcnNpb24gPSBhd2FpdCByZWFkTW9kdWxlVmVyc2lvbkZpbGUoYnVpbGRWZXJzaW9uRmlsZVBhdGgpXG4gIH0gY2F0Y2ggKF8pIHtcbiAgICAvLyBqdXN0IGlnbm9yZSB0aGlzIGVycm9yLCBjYW4gYmUgY2F1c2VkIGJ5IGFuIG91dGRhdGVkIGZvcm1hdFxuICB9XG5cbiAgaWYgKGJ1aWx0VmVyc2lvbiAmJiBidWlsdFZlcnNpb24udmVyc2lvblN0cmluZyA9PT0gbW9kdWxlLnZlcnNpb24udmVyc2lvblN0cmluZykge1xuICAgIHJldHVybiB7IHJlYWR5OiB0cnVlIH1cbiAgfVxuXG4gIHJldHVybiB7IHJlYWR5OiBmYWxzZSB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBidWlsZEdlbmVyaWNNb2R1bGUoeyBtb2R1bGUgfTogQnVpbGRNb2R1bGVQYXJhbXM8R2VuZXJpY01vZHVsZT4pOiBQcm9taXNlPEJ1aWxkUmVzdWx0PiB7XG4gIGNvbnN0IGNvbmZpZzogTW9kdWxlQ29uZmlnID0gbW9kdWxlXG4gIGNvbnN0IG91dHB1dDogQnVpbGRSZXN1bHQgPSB7fVxuICBjb25zdCBidWlsZFBhdGggPSBtb2R1bGUuYnVpbGRQYXRoXG5cbiAgaWYgKGNvbmZpZy5idWlsZC5jb21tYW5kLmxlbmd0aCkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGV4ZWNhLnNoZWxsKFxuICAgICAgY29uZmlnLmJ1aWxkLmNvbW1hbmQuam9pbihcIiBcIiksXG4gICAgICB7XG4gICAgICAgIGN3ZDogYnVpbGRQYXRoLFxuICAgICAgICBlbnY6IHsgLi4ucHJvY2Vzcy5lbnYsIC4uLm1hcFZhbHVlcyhtb2R1bGUuc3BlYy5lbnYsIHYgPT4gdi50b1N0cmluZygpKSB9LFxuICAgICAgfSxcbiAgICApXG5cbiAgICBvdXRwdXQuZnJlc2ggPSB0cnVlXG4gICAgb3V0cHV0LmJ1aWxkTG9nID0gcmVzLnN0ZG91dCArIHJlcy5zdGRlcnJcbiAgfVxuXG4gIC8vIGtlZXAgdHJhY2sgb2Ygd2hpY2ggdmVyc2lvbiBoYXMgYmVlbiBidWlsdFxuICBjb25zdCBidWlsZFZlcnNpb25GaWxlUGF0aCA9IGpvaW4oYnVpbGRQYXRoLCBHQVJERU5fQlVJTERfVkVSU0lPTl9GSUxFTkFNRSlcbiAgYXdhaXQgd3JpdGVNb2R1bGVWZXJzaW9uRmlsZShidWlsZFZlcnNpb25GaWxlUGF0aCwgbW9kdWxlLnZlcnNpb24pXG5cbiAgcmV0dXJuIG91dHB1dFxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdGVzdEdlbmVyaWNNb2R1bGUoeyBtb2R1bGUsIHRlc3RDb25maWcgfTogVGVzdE1vZHVsZVBhcmFtczxHZW5lcmljTW9kdWxlPik6IFByb21pc2U8VGVzdFJlc3VsdD4ge1xuICBjb25zdCBzdGFydGVkQXQgPSBuZXcgRGF0ZSgpXG4gIGNvbnN0IGNvbW1hbmQgPSB0ZXN0Q29uZmlnLnNwZWMuY29tbWFuZFxuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGV4ZWNhLnNoZWxsKFxuICAgIGNvbW1hbmQuam9pbihcIiBcIiksXG4gICAge1xuICAgICAgY3dkOiBtb2R1bGUucGF0aCxcbiAgICAgIGVudjoge1xuICAgICAgICAuLi5wcm9jZXNzLmVudixcbiAgICAgICAgLy8gbmVlZCB0byBjYXN0IHRoZSB2YWx1ZXMgdG8gc3RyaW5nc1xuICAgICAgICAuLi5tYXBWYWx1ZXMobW9kdWxlLnNwZWMuZW52LCB2ID0+IHYgKyBcIlwiKSxcbiAgICAgICAgLi4ubWFwVmFsdWVzKHRlc3RDb25maWcuc3BlYy5lbnYsIHYgPT4gdiArIFwiXCIpLFxuICAgICAgfSxcbiAgICAgIHJlamVjdDogZmFsc2UsXG4gICAgfSxcbiAgKVxuXG4gIHJldHVybiB7XG4gICAgbW9kdWxlTmFtZTogbW9kdWxlLm5hbWUsXG4gICAgY29tbWFuZCxcbiAgICB0ZXN0TmFtZTogdGVzdENvbmZpZy5uYW1lLFxuICAgIHZlcnNpb246IG1vZHVsZS52ZXJzaW9uLFxuICAgIHN1Y2Nlc3M6IHJlc3VsdC5jb2RlID09PSAwLFxuICAgIHN0YXJ0ZWRBdCxcbiAgICBjb21wbGV0ZWRBdDogbmV3IERhdGUoKSxcbiAgICBvdXRwdXQ6IHJlc3VsdC5zdGRvdXQgKyByZXN1bHQuc3RkZXJyLFxuICB9XG59XG5cbmV4cG9ydCBjb25zdCBnZW5lcmljUGx1Z2luOiBHYXJkZW5QbHVnaW4gPSB7XG4gIG1vZHVsZUFjdGlvbnM6IHtcbiAgICBnZW5lcmljOiB7XG4gICAgICB2YWxpZGF0ZTogcGFyc2VHZW5lcmljTW9kdWxlLFxuICAgICAgZ2V0QnVpbGRTdGF0dXM6IGdldEdlbmVyaWNNb2R1bGVCdWlsZFN0YXR1cyxcbiAgICAgIGJ1aWxkOiBidWlsZEdlbmVyaWNNb2R1bGUsXG4gICAgICB0ZXN0TW9kdWxlOiB0ZXN0R2VuZXJpY01vZHVsZSxcbiAgICB9LFxuICB9LFxufVxuXG5leHBvcnQgY29uc3QgZ2FyZGVuUGx1Z2luID0gKCkgPT4gZ2VuZXJpY1BsdWdpblxuIl19 diff --git a/garden-service/build/plugins/google/common.d.ts b/garden-service/build/plugins/google/common.d.ts new file mode 100644 index 00000000000..8ece96d5f44 --- /dev/null +++ b/garden-service/build/plugins/google/common.d.ts @@ -0,0 +1,27 @@ +import { Module } from "../../types/module"; +import { PrepareEnvironmentParams } from "../../types/plugin/params"; +import { Service } from "../../types/service"; +import { GenericTestSpec } from "../generic"; +import { GCloud } from "./gcloud"; +import { ModuleSpec } from "../../config/module"; +import { BaseServiceSpec } from "../../config/service"; +import { Provider } from "../../config/project"; +export declare const GOOGLE_CLOUD_DEFAULT_REGION = "us-central1"; +export interface GoogleCloudServiceSpec extends BaseServiceSpec { + project?: string; +} +export interface GoogleCloudModule extends Module { +} +export declare function getEnvironmentStatus(): Promise<{ + ready: boolean; + detail: { + sdkInstalled: boolean; + sdkInitialized: boolean; + betaComponentsInstalled: boolean; + sdkInfo: {}; + }; +}>; +export declare function prepareEnvironment({ status, logEntry }: PrepareEnvironmentParams): Promise<{}>; +export declare function gcloud(project?: string, account?: string): GCloud; +export declare function getProject(service: Service, provider: Provider): any; +//# sourceMappingURL=common.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/google/common.js b/garden-service/build/plugins/google/common.js new file mode 100644 index 00000000000..b55d26412bf --- /dev/null +++ b/garden-service/build/plugins/google/common.js @@ -0,0 +1,86 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const exceptions_1 = require("../../exceptions"); +const gcloud_1 = require("./gcloud"); +exports.GOOGLE_CLOUD_DEFAULT_REGION = "us-central1"; +function getEnvironmentStatus() { + return __awaiter(this, void 0, void 0, function* () { + let sdkInfo; + const output = { + ready: true, + detail: { + sdkInstalled: true, + sdkInitialized: true, + betaComponentsInstalled: true, + sdkInfo: {}, + }, + }; + try { + sdkInfo = output.detail.sdkInfo = yield gcloud().json(["info"]); + } + catch (err) { + output.ready = false; + output.detail.sdkInstalled = false; + } + if (!sdkInfo.config.account) { + output.ready = false; + output.detail.sdkInitialized = false; + } + if (!sdkInfo.installation.components.beta) { + output.ready = false; + output.detail.betaComponentsInstalled = false; + } + return output; + }); +} +exports.getEnvironmentStatus = getEnvironmentStatus; +function prepareEnvironment({ status, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + if (!status.detail.sdkInstalled) { + throw new exceptions_1.ConfigurationError("Google Cloud SDK is not installed. " + + "Please visit https://cloud.google.com/sdk/downloads for installation instructions.", {}); + } + if (!status.detail.betaComponentsInstalled) { + logEntry && logEntry.info({ + section: "google-cloud-functions", + msg: `Installing gcloud SDK beta components...`, + }); + yield gcloud().call(["components update"]); + yield gcloud().call(["components install beta"]); + } + if (!status.detail.sdkInitialized) { + logEntry && logEntry.info({ + section: "google-cloud-functions", + msg: `Initializing SDK...`, + }); + yield gcloud().tty(["init"], { silent: false }); + } + return {}; + }); +} +exports.prepareEnvironment = prepareEnvironment; +function gcloud(project, account) { + return new gcloud_1.GCloud({ project, account }); +} +exports.gcloud = gcloud; +function getProject(service, provider) { + return service.spec.project || provider.config["default-project"] || null; +} +exports.getProject = getProject; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvZ29vZ2xlL2NvbW1vbi50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBS0gsaURBQXFEO0FBRXJELHFDQUFpQztBQUtwQixRQUFBLDJCQUEyQixHQUFHLGFBQWEsQ0FBQTtBQVl4RCxTQUFzQixvQkFBb0I7O1FBQ3hDLElBQUksT0FBTyxDQUFBO1FBRVgsTUFBTSxNQUFNLEdBQUc7WUFDYixLQUFLLEVBQUUsSUFBSTtZQUNYLE1BQU0sRUFBRTtnQkFDTixZQUFZLEVBQUUsSUFBSTtnQkFDbEIsY0FBYyxFQUFFLElBQUk7Z0JBQ3BCLHVCQUF1QixFQUFFLElBQUk7Z0JBQzdCLE9BQU8sRUFBRSxFQUFFO2FBQ1o7U0FDRixDQUFBO1FBRUQsSUFBSTtZQUNGLE9BQU8sR0FBRyxNQUFNLENBQUMsTUFBTSxDQUFDLE9BQU8sR0FBRyxNQUFNLE1BQU0sRUFBRSxDQUFDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUE7U0FDaEU7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1lBQ3BCLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQTtTQUNuQztRQUVELElBQUksQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRTtZQUMzQixNQUFNLENBQUMsS0FBSyxHQUFHLEtBQUssQ0FBQTtZQUNwQixNQUFNLENBQUMsTUFBTSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUE7U0FDckM7UUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLFlBQVksQ0FBQyxVQUFVLENBQUMsSUFBSSxFQUFFO1lBQ3pDLE1BQU0sQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFBO1lBQ3BCLE1BQU0sQ0FBQyxNQUFNLENBQUMsdUJBQXVCLEdBQUcsS0FBSyxDQUFBO1NBQzlDO1FBRUQsT0FBTyxNQUFNLENBQUE7SUFDZixDQUFDO0NBQUE7QUEvQkQsb0RBK0JDO0FBRUQsU0FBc0Isa0JBQWtCLENBQUMsRUFBRSxNQUFNLEVBQUUsUUFBUSxFQUE0Qjs7UUFDckYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFO1lBQy9CLE1BQU0sSUFBSSwrQkFBa0IsQ0FDMUIscUNBQXFDO2dCQUNyQyxvRkFBb0YsRUFDcEYsRUFBRSxDQUNILENBQUE7U0FDRjtRQUVELElBQUksQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLHVCQUF1QixFQUFFO1lBQzFDLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDO2dCQUN4QixPQUFPLEVBQUUsd0JBQXdCO2dCQUNqQyxHQUFHLEVBQUUsMENBQTBDO2FBQ2hELENBQUMsQ0FBQTtZQUNGLE1BQU0sTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMsbUJBQW1CLENBQUMsQ0FBQyxDQUFBO1lBQzFDLE1BQU0sTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDLENBQUMseUJBQXlCLENBQUMsQ0FBQyxDQUFBO1NBQ2pEO1FBRUQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsY0FBYyxFQUFFO1lBQ2pDLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDO2dCQUN4QixPQUFPLEVBQUUsd0JBQXdCO2dCQUNqQyxHQUFHLEVBQUUscUJBQXFCO2FBQzNCLENBQUMsQ0FBQTtZQUNGLE1BQU0sTUFBTSxFQUFFLENBQUMsR0FBRyxDQUFDLENBQUMsTUFBTSxDQUFDLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQTtTQUNoRDtRQUVELE9BQU8sRUFBRSxDQUFBO0lBQ1gsQ0FBQztDQUFBO0FBM0JELGdEQTJCQztBQUVELFNBQWdCLE1BQU0sQ0FBQyxPQUFnQixFQUFFLE9BQWdCO0lBQ3ZELE9BQU8sSUFBSSxlQUFNLENBQUMsRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUFFLENBQUMsQ0FBQTtBQUN6QyxDQUFDO0FBRkQsd0JBRUM7QUFFRCxTQUFnQixVQUFVLENBQThCLE9BQW1CLEVBQUUsUUFBa0I7SUFDN0YsT0FBTyxPQUFPLENBQUMsSUFBSSxDQUFDLE9BQU8sSUFBSSxRQUFRLENBQUMsTUFBTSxDQUFDLGlCQUFpQixDQUFDLElBQUksSUFBSSxDQUFBO0FBQzNFLENBQUM7QUFGRCxnQ0FFQyIsImZpbGUiOiJwbHVnaW5zL2dvb2dsZS9jb21tb24uanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uLy4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBQcmVwYXJlRW52aXJvbm1lbnRQYXJhbXMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQgeyBTZXJ2aWNlIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgR2VuZXJpY1Rlc3RTcGVjIH0gZnJvbSBcIi4uL2dlbmVyaWNcIlxuaW1wb3J0IHsgR0Nsb3VkIH0gZnJvbSBcIi4vZ2Nsb3VkXCJcbmltcG9ydCB7IE1vZHVsZVNwZWMgfSBmcm9tIFwiLi4vLi4vY29uZmlnL21vZHVsZVwiXG5pbXBvcnQgeyBCYXNlU2VydmljZVNwZWMgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3NlcnZpY2VcIlxuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3Byb2plY3RcIlxuXG5leHBvcnQgY29uc3QgR09PR0xFX0NMT1VEX0RFRkFVTFRfUkVHSU9OID0gXCJ1cy1jZW50cmFsMVwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgR29vZ2xlQ2xvdWRTZXJ2aWNlU3BlYyBleHRlbmRzIEJhc2VTZXJ2aWNlU3BlYyB7XG4gIHByb2plY3Q/OiBzdHJpbmcsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgR29vZ2xlQ2xvdWRNb2R1bGU8XG4gIE0gZXh0ZW5kcyBNb2R1bGVTcGVjID0gTW9kdWxlU3BlYyxcbiAgUyBleHRlbmRzIEdvb2dsZUNsb3VkU2VydmljZVNwZWMgPSBHb29nbGVDbG91ZFNlcnZpY2VTcGVjLFxuICBUIGV4dGVuZHMgR2VuZXJpY1Rlc3RTcGVjID0gR2VuZXJpY1Rlc3RTcGVjLFxuICA+IGV4dGVuZHMgTW9kdWxlPE0sIFMsIFQ+IHsgfVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0RW52aXJvbm1lbnRTdGF0dXMoKSB7XG4gIGxldCBzZGtJbmZvXG5cbiAgY29uc3Qgb3V0cHV0ID0ge1xuICAgIHJlYWR5OiB0cnVlLFxuICAgIGRldGFpbDoge1xuICAgICAgc2RrSW5zdGFsbGVkOiB0cnVlLFxuICAgICAgc2RrSW5pdGlhbGl6ZWQ6IHRydWUsXG4gICAgICBiZXRhQ29tcG9uZW50c0luc3RhbGxlZDogdHJ1ZSxcbiAgICAgIHNka0luZm86IHt9LFxuICAgIH0sXG4gIH1cblxuICB0cnkge1xuICAgIHNka0luZm8gPSBvdXRwdXQuZGV0YWlsLnNka0luZm8gPSBhd2FpdCBnY2xvdWQoKS5qc29uKFtcImluZm9cIl0pXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIG91dHB1dC5yZWFkeSA9IGZhbHNlXG4gICAgb3V0cHV0LmRldGFpbC5zZGtJbnN0YWxsZWQgPSBmYWxzZVxuICB9XG5cbiAgaWYgKCFzZGtJbmZvLmNvbmZpZy5hY2NvdW50KSB7XG4gICAgb3V0cHV0LnJlYWR5ID0gZmFsc2VcbiAgICBvdXRwdXQuZGV0YWlsLnNka0luaXRpYWxpemVkID0gZmFsc2VcbiAgfVxuXG4gIGlmICghc2RrSW5mby5pbnN0YWxsYXRpb24uY29tcG9uZW50cy5iZXRhKSB7XG4gICAgb3V0cHV0LnJlYWR5ID0gZmFsc2VcbiAgICBvdXRwdXQuZGV0YWlsLmJldGFDb21wb25lbnRzSW5zdGFsbGVkID0gZmFsc2VcbiAgfVxuXG4gIHJldHVybiBvdXRwdXRcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVFbnZpcm9ubWVudCh7IHN0YXR1cywgbG9nRW50cnkgfTogUHJlcGFyZUVudmlyb25tZW50UGFyYW1zKSB7XG4gIGlmICghc3RhdHVzLmRldGFpbC5zZGtJbnN0YWxsZWQpIHtcbiAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgXCJHb29nbGUgQ2xvdWQgU0RLIGlzIG5vdCBpbnN0YWxsZWQuIFwiICtcbiAgICAgIFwiUGxlYXNlIHZpc2l0IGh0dHBzOi8vY2xvdWQuZ29vZ2xlLmNvbS9zZGsvZG93bmxvYWRzIGZvciBpbnN0YWxsYXRpb24gaW5zdHJ1Y3Rpb25zLlwiLFxuICAgICAge30sXG4gICAgKVxuICB9XG5cbiAgaWYgKCFzdGF0dXMuZGV0YWlsLmJldGFDb21wb25lbnRzSW5zdGFsbGVkKSB7XG4gICAgbG9nRW50cnkgJiYgbG9nRW50cnkuaW5mbyh7XG4gICAgICBzZWN0aW9uOiBcImdvb2dsZS1jbG91ZC1mdW5jdGlvbnNcIixcbiAgICAgIG1zZzogYEluc3RhbGxpbmcgZ2Nsb3VkIFNESyBiZXRhIGNvbXBvbmVudHMuLi5gLFxuICAgIH0pXG4gICAgYXdhaXQgZ2Nsb3VkKCkuY2FsbChbXCJjb21wb25lbnRzIHVwZGF0ZVwiXSlcbiAgICBhd2FpdCBnY2xvdWQoKS5jYWxsKFtcImNvbXBvbmVudHMgaW5zdGFsbCBiZXRhXCJdKVxuICB9XG5cbiAgaWYgKCFzdGF0dXMuZGV0YWlsLnNka0luaXRpYWxpemVkKSB7XG4gICAgbG9nRW50cnkgJiYgbG9nRW50cnkuaW5mbyh7XG4gICAgICBzZWN0aW9uOiBcImdvb2dsZS1jbG91ZC1mdW5jdGlvbnNcIixcbiAgICAgIG1zZzogYEluaXRpYWxpemluZyBTREsuLi5gLFxuICAgIH0pXG4gICAgYXdhaXQgZ2Nsb3VkKCkudHR5KFtcImluaXRcIl0sIHsgc2lsZW50OiBmYWxzZSB9KVxuICB9XG5cbiAgcmV0dXJuIHt9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBnY2xvdWQocHJvamVjdD86IHN0cmluZywgYWNjb3VudD86IHN0cmluZykge1xuICByZXR1cm4gbmV3IEdDbG91ZCh7IHByb2plY3QsIGFjY291bnQgfSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldFByb2plY3Q8VCBleHRlbmRzIEdvb2dsZUNsb3VkTW9kdWxlPihzZXJ2aWNlOiBTZXJ2aWNlPFQ+LCBwcm92aWRlcjogUHJvdmlkZXIpIHtcbiAgcmV0dXJuIHNlcnZpY2Uuc3BlYy5wcm9qZWN0IHx8IHByb3ZpZGVyLmNvbmZpZ1tcImRlZmF1bHQtcHJvamVjdFwiXSB8fCBudWxsXG59XG4iXX0= diff --git a/garden-service/build/plugins/google/gcloud.d.ts b/garden-service/build/plugins/google/gcloud.d.ts new file mode 100644 index 00000000000..052a9f980aa --- /dev/null +++ b/garden-service/build/plugins/google/gcloud.d.ts @@ -0,0 +1,30 @@ +/// +export interface GCloudParams { + data?: Buffer; + ignoreError?: boolean; + silent?: boolean; + timeout?: number; + cwd?: string; +} +export interface GCloudOutput { + code: number; + output: string; + stdout?: string; + stderr?: string; +} +export declare class GCloud { + account?: string; + project?: string; + constructor({ account, project }: { + account?: string; + project?: string; + }); + call(args: string[], { data, ignoreError, silent, timeout, cwd }?: GCloudParams): Promise; + json(args: string[], opts?: GCloudParams): Promise; + tty(args: string[], { silent, cwd }?: { + silent?: boolean; + cwd?: string; + }): Promise; + private prepareArgs; +} +//# sourceMappingURL=gcloud.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/google/gcloud.js b/garden-service/build/plugins/google/gcloud.js new file mode 100644 index 00000000000..d2de17c1b1f --- /dev/null +++ b/garden-service/build/plugins/google/gcloud.js @@ -0,0 +1,107 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const child_process_1 = require("child_process"); +const lodash_1 = require("lodash"); +const util_1 = require("../../util/util"); +const DEFAULT_TIMEOUT = 600; +// TODO: re-use code across this and Kubectl +class GCloud { + constructor({ account, project }) { + this.account = account; + this.project = project; + } + call(args, { data, ignoreError = false, silent = true, timeout = DEFAULT_TIMEOUT, cwd } = {}) { + return __awaiter(this, void 0, void 0, function* () { + const out = { + code: 0, + output: "", + stdout: "", + stderr: "", + }; + const proc = child_process_1.spawn("gcloud", this.prepareArgs(args), { cwd }); + proc.stdout.on("data", (s) => { + if (!silent) { + process.stdout.write(s); + } + out.output += s; + out.stdout += s; + }); + proc.stderr.on("data", (s) => { + if (!silent) { + process.stderr.write(s); + } + out.output += s; + out.stderr += s; + }); + if (data) { + proc.stdin.end(data); + } + return new Promise((resolve, reject) => { + let _timeout; + const _reject = (msg) => { + const err = new Error(msg); + lodash_1.extend(err, out); + reject(err); + }; + if (timeout > 0) { + _timeout = setTimeout(() => { + proc.kill("SIGKILL"); + _reject(`gcloud timed out after ${timeout} seconds.`); + }, timeout * 1000); + } + proc.on("close", (code) => { + _timeout && clearTimeout(_timeout); + out.code = code; + if (code === 0 || ignoreError) { + resolve(out); + } + else { + _reject("Process exited with code " + code); + } + }); + }); + }); + } + json(args, opts = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (!args.includes("--format=json")) { + args.push("--format=json"); + } + const result = yield this.call(args, opts); + return JSON.parse(result.output); + }); + } + tty(args, { silent = true, cwd } = {}) { + return __awaiter(this, void 0, void 0, function* () { + return util_1.spawnPty("gcloud", this.prepareArgs(args), { silent, cwd, tty: true }); + }); + } + prepareArgs(args) { + const ops = []; + if (this.account) { + ops.push(`--account=${this.account}`); + } + if (this.project) { + ops.push(`--project=${this.project}`); + } + return ops.concat(args); + } +} +exports.GCloud = GCloud; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvZ29vZ2xlL2djbG91ZC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsaURBQXFDO0FBQ3JDLG1DQUErQjtBQUMvQiwwQ0FBMEM7QUFpQjFDLE1BQU0sZUFBZSxHQUFHLEdBQUcsQ0FBQTtBQUUzQiw0Q0FBNEM7QUFDNUMsTUFBYSxNQUFNO0lBSWpCLFlBQVksRUFBRSxPQUFPLEVBQUUsT0FBTyxFQUEwQztRQUN0RSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtRQUN0QixJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQTtJQUN4QixDQUFDO0lBRUssSUFBSSxDQUNSLElBQWMsRUFDZCxFQUFFLElBQUksRUFBRSxXQUFXLEdBQUcsS0FBSyxFQUFFLE1BQU0sR0FBRyxJQUFJLEVBQUUsT0FBTyxHQUFHLGVBQWUsRUFBRSxHQUFHLEtBQW1CLEVBQUU7O1lBRy9GLE1BQU0sR0FBRyxHQUFpQjtnQkFDeEIsSUFBSSxFQUFFLENBQUM7Z0JBQ1AsTUFBTSxFQUFFLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLEVBQUU7Z0JBQ1YsTUFBTSxFQUFFLEVBQUU7YUFDWCxDQUFBO1lBRUQsTUFBTSxJQUFJLEdBQUcscUJBQUssQ0FBQyxRQUFRLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUE7WUFFN0QsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksQ0FBQyxNQUFNLEVBQUU7b0JBQ1gsT0FBTyxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUE7aUJBQ3hCO2dCQUNELEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFBO2dCQUNmLEdBQUcsQ0FBQyxNQUFPLElBQUksQ0FBQyxDQUFBO1lBQ2xCLENBQUMsQ0FBQyxDQUFBO1lB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QUksQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1NBQ3RDO1FBRUQsT0FBTyxHQUFHLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO0lBQ3pCLENBQUM7Q0FDRjtBQW5HRCx3QkFtR0MiLCJmaWxlIjoicGx1Z2lucy9nb29nbGUvZ2Nsb3VkLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IHNwYXduIH0gZnJvbSBcImNoaWxkX3Byb2Nlc3NcIlxuaW1wb3J0IHsgZXh0ZW5kIH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyBzcGF3blB0eSB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuXG5leHBvcnQgaW50ZXJmYWNlIEdDbG91ZFBhcmFtcyB7XG4gIGRhdGE/OiBCdWZmZXIsXG4gIGlnbm9yZUVycm9yPzogYm9vbGVhbixcbiAgc2lsZW50PzogYm9vbGVhbixcbiAgdGltZW91dD86IG51bWJlcixcbiAgY3dkPzogc3RyaW5nLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEdDbG91ZE91dHB1dCB7XG4gIGNvZGU6IG51bWJlcixcbiAgb3V0cHV0OiBzdHJpbmcsXG4gIHN0ZG91dD86IHN0cmluZyxcbiAgc3RkZXJyPzogc3RyaW5nLFxufVxuXG5jb25zdCBERUZBVUxUX1RJTUVPVVQgPSA2MDBcblxuLy8gVE9ETzogcmUtdXNlIGNvZGUgYWNyb3NzIHRoaXMgYW5kIEt1YmVjdGxcbmV4cG9ydCBjbGFzcyBHQ2xvdWQge1xuICBwdWJsaWMgYWNjb3VudD86IHN0cmluZ1xuICBwdWJsaWMgcHJvamVjdD86IHN0cmluZ1xuXG4gIGNvbnN0cnVjdG9yKHsgYWNjb3VudCwgcHJvamVjdCB9OiB7IGFjY291bnQ/OiBzdHJpbmcsIHByb2plY3Q/OiBzdHJpbmcgfSkge1xuICAgIHRoaXMuYWNjb3VudCA9IGFjY291bnRcbiAgICB0aGlzLnByb2plY3QgPSBwcm9qZWN0XG4gIH1cblxuICBhc3luYyBjYWxsKFxuICAgIGFyZ3M6IHN0cmluZ1tdLFxuICAgIHsgZGF0YSwgaWdub3JlRXJyb3IgPSBmYWxzZSwgc2lsZW50ID0gdHJ1ZSwgdGltZW91dCA9IERFRkFVTFRfVElNRU9VVCwgY3dkIH06IEdDbG91ZFBhcmFtcyA9IHt9LFxuICApOiBQcm9taXNlPEdDbG91ZE91dHB1dD4ge1xuXG4gICAgY29uc3Qgb3V0OiBHQ2xvdWRPdXRwdXQgPSB7XG4gICAgICBjb2RlOiAwLFxuICAgICAgb3V0cHV0OiBcIlwiLFxuICAgICAgc3Rkb3V0OiBcIlwiLFxuICAgICAgc3RkZXJyOiBcIlwiLFxuICAgIH1cblxuICAgIGNvbnN0IHByb2MgPSBzcGF3bihcImdjbG91ZFwiLCB0aGlzLnByZXBhcmVBcmdzKGFyZ3MpLCB7IGN3ZCB9KVxuXG4gICAgcHJvYy5zdGRvdXQub24oXCJkYXRhXCIsIChzKSA9PiB7XG4gICAgICBpZiAoIXNpbGVudCkge1xuICAgICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShzKVxuICAgICAgfVxuICAgICAgb3V0Lm91dHB1dCArPSBzXG4gICAgICBvdXQuc3Rkb3V0ISArPSBzXG4gICAgfSlcblxuICAgIHByb2Muc3RkZXJyLm9uKFwiZGF0YVwiLCAocykgPT4ge1xuICAgICAgaWYgKCFzaWxlbnQpIHtcbiAgICAgICAgcHJvY2Vzcy5zdGRlcnIud3JpdGUocylcbiAgICAgIH1cbiAgICAgIG91dC5vdXRwdXQgKz0gc1xuICAgICAgb3V0LnN0ZGVyciEgKz0gc1xuICAgIH0pXG5cbiAgICBpZiAoZGF0YSkge1xuICAgICAgcHJvYy5zdGRpbi5lbmQoZGF0YSlcbiAgICB9XG5cbiAgICByZXR1cm4gbmV3IFByb21pc2U8R0Nsb3VkT3V0cHV0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgX3RpbWVvdXRcblxuICAgICAgY29uc3QgX3JlamVjdCA9IChtc2c6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBlcnIgPSBuZXcgRXJyb3IobXNnKVxuICAgICAgICBleHRlbmQoZXJyLCA8YW55Pm91dClcbiAgICAgICAgcmVqZWN0KGVycilcbiAgICAgIH1cblxuICAgICAgaWYgKHRpbWVvdXQgPiAwKSB7XG4gICAgICAgIF90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgcHJvYy5raWxsKFwiU0lHS0lMTFwiKVxuICAgICAgICAgIF9yZWplY3QoYGdjbG91ZCB0aW1lZCBvdXQgYWZ0ZXIgJHt0aW1lb3V0fSBzZWNvbmRzLmApXG4gICAgICAgIH0sIHRpbWVvdXQgKiAxMDAwKVxuICAgICAgfVxuXG4gICAgICBwcm9jLm9uKFwiY2xvc2VcIiwgKGNvZGUpID0+IHtcbiAgICAgICAgX3RpbWVvdXQgJiYgY2xlYXJUaW1lb3V0KF90aW1lb3V0KVxuICAgICAgICBvdXQuY29kZSA9IGNvZGVcblxuICAgICAgICBpZiAoY29kZSA9PT0gMCB8fCBpZ25vcmVFcnJvcikge1xuICAgICAgICAgIHJlc29sdmUob3V0KVxuICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgIF9yZWplY3QoXCJQcm9jZXNzIGV4aXRlZCB3aXRoIGNvZGUgXCIgKyBjb2RlKVxuICAgICAgICB9XG4gICAgICB9KVxuICAgIH0pXG4gIH1cblxuICBhc3luYyBqc29uKGFyZ3M6IHN0cmluZ1tdLCBvcHRzOiBHQ2xvdWRQYXJhbXMgPSB7fSk6IFByb21pc2U8YW55PiB7XG4gICAgaWYgKCFhcmdzLmluY2x1ZGVzKFwiLS1mb3JtYXQ9anNvblwiKSkge1xuICAgICAgYXJncy5wdXNoKFwiLS1mb3JtYXQ9anNvblwiKVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FsbChhcmdzLCBvcHRzKVxuXG4gICAgcmV0dXJuIEpTT04ucGFyc2UocmVzdWx0Lm91dHB1dClcbiAgfVxuXG4gIGFzeW5jIHR0eShhcmdzOiBzdHJpbmdbXSwgeyBzaWxlbnQgPSB0cnVlLCBjd2QgfTogeyBzaWxlbnQ/OiBib29sZWFuLCBjd2Q/OiBzdHJpbmcgfSA9IHt9KTogUHJvbWlzZTxHQ2xvdWRPdXRwdXQ+IHtcbiAgICByZXR1cm4gc3Bhd25QdHkoXCJnY2xvdWRcIiwgdGhpcy5wcmVwYXJlQXJncyhhcmdzKSwgeyBzaWxlbnQsIGN3ZCwgdHR5OiB0cnVlIH0pXG4gIH1cblxuICBwcml2YXRlIHByZXBhcmVBcmdzKGFyZ3M6IHN0cmluZ1tdKSB7XG4gICAgY29uc3Qgb3BzOiBzdHJpbmdbXSA9IFtdXG5cbiAgICBpZiAodGhpcy5hY2NvdW50KSB7XG4gICAgICBvcHMucHVzaChgLS1hY2NvdW50PSR7dGhpcy5hY2NvdW50fWApXG4gICAgfVxuXG4gICAgaWYgKHRoaXMucHJvamVjdCkge1xuICAgICAgb3BzLnB1c2goYC0tcHJvamVjdD0ke3RoaXMucHJvamVjdH1gKVxuICAgIH1cblxuICAgIHJldHVybiBvcHMuY29uY2F0KGFyZ3MpXG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugins/google/google-app-engine.d.ts b/garden-service/build/plugins/google/google-app-engine.d.ts new file mode 100644 index 00000000000..3896dc9fdfb --- /dev/null +++ b/garden-service/build/plugins/google/google-app-engine.d.ts @@ -0,0 +1,9 @@ +import { ContainerModule, ContainerModuleSpec, ContainerServiceSpec } from "../container"; +import { GardenPlugin } from "../../types/plugin/plugin"; +export interface GoogleAppEngineServiceSpec extends ContainerServiceSpec { + project?: string; +} +export interface GoogleAppEngineModule extends ContainerModule { +} +export declare const gardenPlugin: () => GardenPlugin; +//# sourceMappingURL=google-app-engine.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/google/google-app-engine.js b/garden-service/build/plugins/google/google-app-engine.js new file mode 100644 index 00000000000..86d9f720da7 --- /dev/null +++ b/garden-service/build/plugins/google/google-app-engine.js @@ -0,0 +1,90 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const common_1 = require("./common"); +const common_2 = require("./common"); +const util_1 = require("../../util/util"); +exports.gardenPlugin = () => ({ + actions: { + getEnvironmentStatus: common_2.getEnvironmentStatus, + prepareEnvironment: common_2.prepareEnvironment, + }, + moduleActions: { + container: { + getServiceStatus() { + return __awaiter(this, void 0, void 0, function* () { + // TODO + // const project = this.getProject(service, env) + // + // const appStatus = await this.gcloud(project).json(["app", "describe"]) + // const services = await this.gcloud(project).json(["app", "services", "list"]) + // const instances: any[] = await this.gcloud(project).json(["app", "instances", "list"]) + return {}; + }); + }, + deployService({ ctx, service, runtimeContext, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + logEntry && logEntry.info({ + section: service.name, + msg: `Deploying app...`, + }); + const config = service.spec; + // prepare app.yaml + const appYaml = { + runtime: "custom", + env: "flex", + env_variables: Object.assign({}, runtimeContext.envVars, service.spec.env), + }; + if (config.healthCheck) { + if (config.healthCheck.tcpPort || config.healthCheck.command) { + logEntry && logEntry.warn({ + section: service.name, + msg: "GAE only supports httpGet health checks", + }); + } + if (config.healthCheck.httpGet) { + appYaml.liveness_check = { path: config.healthCheck.httpGet.path }; + appYaml.readiness_check = { path: config.healthCheck.httpGet.path }; + } + } + // write app.yaml to build context + const appYamlPath = path_1.join(service.module.path, "app.yaml"); + yield util_1.dumpYaml(appYamlPath, appYaml); + // deploy to GAE + const project = common_1.getProject(service, ctx.provider); + yield common_1.gcloud(project).call([ + "app", "deploy", "--quiet", + ], { cwd: service.module.path }); + logEntry && logEntry.info({ section: service.name, msg: `App deployed` }); + return {}; + }); + }, + getServiceOutputs({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: we may want to pull this from the service status instead, along with other outputs + const project = common_1.getProject(service, ctx.provider); + return { + ingress: `https://${common_2.GOOGLE_CLOUD_DEFAULT_REGION}-${project}.cloudfunctions.net/${service.name}`, + }; + }); + }, + }, + }, +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvZ29vZ2xlL2dvb2dsZS1hcHAtZW5naW5lLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFPSCwrQkFBMkI7QUFDM0IscUNBR2lCO0FBQ2pCLHFDQUlpQjtBQU1qQiwwQ0FBMEM7QUFXN0IsUUFBQSxZQUFZLEdBQUcsR0FBaUIsRUFBRSxDQUFDLENBQUM7SUFDL0MsT0FBTyxFQUFFO1FBQ1Asb0JBQW9CLEVBQXBCLDZCQUFvQjtRQUNwQixrQkFBa0IsRUFBbEIsMkJBQWtCO0tBQ25CO0lBQ0QsYUFBYSxFQUFFO1FBQ2IsU0FBUyxFQUFFO1lBQ0gsZ0JBQWdCOztvQkFDcEIsT0FBTztvQkFDUCxnREFBZ0Q7b0JBQ2hELEVBQUU7b0JBQ0YseUVBQXlFO29CQUN6RSxnRkFBZ0Y7b0JBQ2hGLHlGQUF5RjtvQkFFekYsT0FBTyxFQUFFLENBQUE7Z0JBQ1gsQ0FBQzthQUFBO1lBRUssYUFBYSxDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQUUsUUFBUSxFQUE4Qzs7b0JBQ3hHLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDO3dCQUN4QixPQUFPLEVBQUUsT0FBTyxDQUFDLElBQUk7d0JBQ3JCLEdBQUcsRUFBRSxrQkFBa0I7cUJBQ3hCLENBQUMsQ0FBQTtvQkFFRixNQUFNLE1BQU0sR0FBRyxPQUFPLENBQUMsSUFBSSxDQUFBO29CQUUzQixtQkFBbUI7b0JBQ25CLE1BQU0sT0FBTyxHQUFRO3dCQUNuQixPQUFPLEVBQUUsUUFBUTt3QkFDakIsR0FBRyxFQUFFLE1BQU07d0JBQ1gsYUFBYSxvQkFBTyxjQUFjLENBQUMsT0FBTyxFQUFLLE9BQU8sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFFO3FCQUNsRSxDQUFBO29CQUVELElBQUksTUFBTSxDQUFDLFdBQVcsRUFBRTt3QkFDdEIsSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sSUFBSSxNQUFNLENBQUMsV0FBVyxDQUFDLE9BQU8sRUFBRTs0QkFDNUQsUUFBUSxJQUFJLFFBQVEsQ0FBQyxJQUFJLENBQUM7Z0NBQ3hCLE9BQU8sRUFBRSxPQUFPLENBQUMsSUFBSTtnQ0FDckIsR0FBRyxFQUFFLHlDQUF5Qzs2QkFDL0MsQ0FBQyxDQUFBO3lCQUNIO3dCQUNELElBQUksTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLEVBQUU7NEJBQzlCLE9BQU8sQ0FBQyxjQUFjLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUE7NEJBQ2xFLE9BQU8sQ0FBQyxlQUFlLEdBQUcsRUFBRSxJQUFJLEVBQUUsTUFBTSxDQUFDLFdBQVcsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLENBQUE7eUJBQ3BFO3FCQUNGO29CQUVELGtDQUFrQztvQkFDbEMsTUFBTSxXQUFXLEdBQUcsV0FBSSxDQUFDLE9BQU8sQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLFVBQVUsQ0FBQyxDQUFBO29CQUN6RCxNQUFNLGVBQVEsQ0FBQyxXQUFXLEVBQUUsT0FBTyxDQUFDLENBQUE7b0JBRXBDLGdCQUFnQjtvQkFDaEIsTUFBTSxPQUFPLEdBQUcsbUJBQVUsQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO29CQUVqRCxNQUFNLGVBQU0sQ0FBQyxPQUFPLENBQUMsQ0FBQyxJQUFJLENBQUM7d0JBQ3pCLEtBQUssRUFBRSxRQUFRLEVBQUUsU0FBUztxQkFDM0IsRUFBRSxFQUFFLEdBQUcsRUFBRSxPQUFPLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFDLENBQUE7b0JBRWhDLFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLGNBQWMsRUFBRSxDQUFDLENBQUE7b0JBRXpFLE9BQU8sRUFBRSxDQUFBO2dCQUNYLENBQUM7YUFBQTtZQUVLLGlCQUFpQixDQUFDLEVBQUUsR0FBRyxFQUFFLE9BQU8sRUFBa0Q7O29CQUN0RiwyRkFBMkY7b0JBQzNGLE1BQU0sT0FBTyxHQUFHLG1CQUFVLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtvQkFFakQsT0FBTzt3QkFDTCxPQUFPLEVBQUUsV0FBVyxvQ0FBMkIsSUFBSSxPQUFPLHVCQUF1QixPQUFPLENBQUMsSUFBSSxFQUFFO3FCQUNoRyxDQUFBO2dCQUNILENBQUM7YUFBQTtTQUNGO0tBQ0Y7Q0FDRixDQUFDLENBQUEiLCJmaWxlIjoicGx1Z2lucy9nb29nbGUvZ29vZ2xlLWFwcC1lbmdpbmUuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHtcbiAgRGVwbG95U2VydmljZVBhcmFtcyxcbiAgR2V0U2VydmljZU91dHB1dHNQYXJhbXMsXG59IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IFNlcnZpY2VTdGF0dXMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHtcbiAgZ2Nsb3VkLFxuICBnZXRQcm9qZWN0LFxufSBmcm9tIFwiLi9jb21tb25cIlxuaW1wb3J0IHtcbiAgZ2V0RW52aXJvbm1lbnRTdGF0dXMsXG4gIEdPT0dMRV9DTE9VRF9ERUZBVUxUX1JFR0lPTixcbiAgcHJlcGFyZUVudmlyb25tZW50LFxufSBmcm9tIFwiLi9jb21tb25cIlxuaW1wb3J0IHtcbiAgQ29udGFpbmVyTW9kdWxlLFxuICBDb250YWluZXJNb2R1bGVTcGVjLFxuICBDb250YWluZXJTZXJ2aWNlU3BlYyxcbn0gZnJvbSBcIi4uL2NvbnRhaW5lclwiXG5pbXBvcnQgeyBkdW1wWWFtbCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHtcbiAgR2FyZGVuUGx1Z2luLFxufSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgR29vZ2xlQXBwRW5naW5lU2VydmljZVNwZWMgZXh0ZW5kcyBDb250YWluZXJTZXJ2aWNlU3BlYyB7XG4gIHByb2plY3Q/OiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBHb29nbGVBcHBFbmdpbmVNb2R1bGUgZXh0ZW5kcyBDb250YWluZXJNb2R1bGU8Q29udGFpbmVyTW9kdWxlU3BlYywgR29vZ2xlQXBwRW5naW5lU2VydmljZVNwZWM+IHsgfVxuXG5leHBvcnQgY29uc3QgZ2FyZGVuUGx1Z2luID0gKCk6IEdhcmRlblBsdWdpbiA9PiAoe1xuICBhY3Rpb25zOiB7XG4gICAgZ2V0RW52aXJvbm1lbnRTdGF0dXMsXG4gICAgcHJlcGFyZUVudmlyb25tZW50LFxuICB9LFxuICBtb2R1bGVBY3Rpb25zOiB7XG4gICAgY29udGFpbmVyOiB7XG4gICAgICBhc3luYyBnZXRTZXJ2aWNlU3RhdHVzKCk6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICAgICAgICAvLyBUT0RPXG4gICAgICAgIC8vIGNvbnN0IHByb2plY3QgPSB0aGlzLmdldFByb2plY3Qoc2VydmljZSwgZW52KVxuICAgICAgICAvL1xuICAgICAgICAvLyBjb25zdCBhcHBTdGF0dXMgPSBhd2FpdCB0aGlzLmdjbG91ZChwcm9qZWN0KS5qc29uKFtcImFwcFwiLCBcImRlc2NyaWJlXCJdKVxuICAgICAgICAvLyBjb25zdCBzZXJ2aWNlcyA9IGF3YWl0IHRoaXMuZ2Nsb3VkKHByb2plY3QpLmpzb24oW1wiYXBwXCIsIFwic2VydmljZXNcIiwgXCJsaXN0XCJdKVxuICAgICAgICAvLyBjb25zdCBpbnN0YW5jZXM6IGFueVtdID0gYXdhaXQgdGhpcy5nY2xvdWQocHJvamVjdCkuanNvbihbXCJhcHBcIiwgXCJpbnN0YW5jZXNcIiwgXCJsaXN0XCJdKVxuXG4gICAgICAgIHJldHVybiB7fVxuICAgICAgfSxcblxuICAgICAgYXN5bmMgZGVwbG95U2VydmljZSh7IGN0eCwgc2VydmljZSwgcnVudGltZUNvbnRleHQsIGxvZ0VudHJ5IH06IERlcGxveVNlcnZpY2VQYXJhbXM8R29vZ2xlQXBwRW5naW5lTW9kdWxlPikge1xuICAgICAgICBsb2dFbnRyeSAmJiBsb2dFbnRyeS5pbmZvKHtcbiAgICAgICAgICBzZWN0aW9uOiBzZXJ2aWNlLm5hbWUsXG4gICAgICAgICAgbXNnOiBgRGVwbG95aW5nIGFwcC4uLmAsXG4gICAgICAgIH0pXG5cbiAgICAgICAgY29uc3QgY29uZmlnID0gc2VydmljZS5zcGVjXG5cbiAgICAgICAgLy8gcHJlcGFyZSBhcHAueWFtbFxuICAgICAgICBjb25zdCBhcHBZYW1sOiBhbnkgPSB7XG4gICAgICAgICAgcnVudGltZTogXCJjdXN0b21cIixcbiAgICAgICAgICBlbnY6IFwiZmxleFwiLFxuICAgICAgICAgIGVudl92YXJpYWJsZXM6IHsgLi4ucnVudGltZUNvbnRleHQuZW52VmFycywgLi4uc2VydmljZS5zcGVjLmVudiB9LFxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGNvbmZpZy5oZWFsdGhDaGVjaykge1xuICAgICAgICAgIGlmIChjb25maWcuaGVhbHRoQ2hlY2sudGNwUG9ydCB8fCBjb25maWcuaGVhbHRoQ2hlY2suY29tbWFuZCkge1xuICAgICAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkud2Fybih7XG4gICAgICAgICAgICAgIHNlY3Rpb246IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICAgICAgbXNnOiBcIkdBRSBvbmx5IHN1cHBvcnRzIGh0dHBHZXQgaGVhbHRoIGNoZWNrc1wiLFxuICAgICAgICAgICAgfSlcbiAgICAgICAgICB9XG4gICAgICAgICAgaWYgKGNvbmZpZy5oZWFsdGhDaGVjay5odHRwR2V0KSB7XG4gICAgICAgICAgICBhcHBZYW1sLmxpdmVuZXNzX2NoZWNrID0geyBwYXRoOiBjb25maWcuaGVhbHRoQ2hlY2suaHR0cEdldC5wYXRoIH1cbiAgICAgICAgICAgIGFwcFlhbWwucmVhZGluZXNzX2NoZWNrID0geyBwYXRoOiBjb25maWcuaGVhbHRoQ2hlY2suaHR0cEdldC5wYXRoIH1cbiAgICAgICAgICB9XG4gICAgICAgIH1cblxuICAgICAgICAvLyB3cml0ZSBhcHAueWFtbCB0byBidWlsZCBjb250ZXh0XG4gICAgICAgIGNvbnN0IGFwcFlhbWxQYXRoID0gam9pbihzZXJ2aWNlLm1vZHVsZS5wYXRoLCBcImFwcC55YW1sXCIpXG4gICAgICAgIGF3YWl0IGR1bXBZYW1sKGFwcFlhbWxQYXRoLCBhcHBZYW1sKVxuXG4gICAgICAgIC8vIGRlcGxveSB0byBHQUVcbiAgICAgICAgY29uc3QgcHJvamVjdCA9IGdldFByb2plY3Qoc2VydmljZSwgY3R4LnByb3ZpZGVyKVxuXG4gICAgICAgIGF3YWl0IGdjbG91ZChwcm9qZWN0KS5jYWxsKFtcbiAgICAgICAgICBcImFwcFwiLCBcImRlcGxveVwiLCBcIi0tcXVpZXRcIixcbiAgICAgICAgXSwgeyBjd2Q6IHNlcnZpY2UubW9kdWxlLnBhdGggfSlcblxuICAgICAgICBsb2dFbnRyeSAmJiBsb2dFbnRyeS5pbmZvKHsgc2VjdGlvbjogc2VydmljZS5uYW1lLCBtc2c6IGBBcHAgZGVwbG95ZWRgIH0pXG5cbiAgICAgICAgcmV0dXJuIHt9XG4gICAgICB9LFxuXG4gICAgICBhc3luYyBnZXRTZXJ2aWNlT3V0cHV0cyh7IGN0eCwgc2VydmljZSB9OiBHZXRTZXJ2aWNlT3V0cHV0c1BhcmFtczxHb29nbGVBcHBFbmdpbmVNb2R1bGU+KSB7XG4gICAgICAgIC8vIFRPRE86IHdlIG1heSB3YW50IHRvIHB1bGwgdGhpcyBmcm9tIHRoZSBzZXJ2aWNlIHN0YXR1cyBpbnN0ZWFkLCBhbG9uZyB3aXRoIG90aGVyIG91dHB1dHNcbiAgICAgICAgY29uc3QgcHJvamVjdCA9IGdldFByb2plY3Qoc2VydmljZSwgY3R4LnByb3ZpZGVyKVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgaW5ncmVzczogYGh0dHBzOi8vJHtHT09HTEVfQ0xPVURfREVGQVVMVF9SRUdJT059LSR7cHJvamVjdH0uY2xvdWRmdW5jdGlvbnMubmV0LyR7c2VydmljZS5uYW1lfWAsXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn0pXG4iXX0= diff --git a/garden-service/build/plugins/google/google-cloud-functions.d.ts b/garden-service/build/plugins/google/google-cloud-functions.d.ts new file mode 100644 index 00000000000..079b968f16a --- /dev/null +++ b/garden-service/build/plugins/google/google-cloud-functions.d.ts @@ -0,0 +1,26 @@ +import { Module } from "../../types/module"; +import { ValidateModuleResult } from "../../types/plugin/outputs"; +import { GetServiceStatusParams, ValidateModuleParams } from "../../types/plugin/params"; +import { ServiceStatus } from "../../types/service"; +import * as Joi from "joi"; +import { GenericTestSpec } from "../generic"; +import { GoogleCloudServiceSpec } from "./common"; +import { GardenPlugin } from "../../types/plugin/plugin"; +import { ModuleSpec } from "../../config/module"; +export interface GcfServiceSpec extends GoogleCloudServiceSpec { + entrypoint?: string; + function: string; + hostname?: string; + path: string; +} +export declare const gcfServicesSchema: Joi.ArraySchema; +export interface GcfModuleSpec extends ModuleSpec { + functions: GcfServiceSpec[]; + tests: GenericTestSpec[]; +} +export interface GcfModule extends Module { +} +export declare function parseGcfModule({ moduleConfig }: ValidateModuleParams): Promise>; +export declare const gardenPlugin: () => GardenPlugin; +export declare function getServiceStatus({ ctx, service }: GetServiceStatusParams): Promise; +//# sourceMappingURL=google-cloud-functions.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/google/google-cloud-functions.js b/garden-service/build/plugins/google/google-cloud-functions.js new file mode 100644 index 00000000000..2a3f792092a --- /dev/null +++ b/garden-service/build/plugins/google/google-cloud-functions.js @@ -0,0 +1,128 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const common_1 = require("../../config/common"); +const service_1 = require("../../types/service"); +const path_1 = require("path"); +const Joi = require("joi"); +const constants_1 = require("../../constants"); +const generic_1 = require("../generic"); +const common_2 = require("./common"); +const service_2 = require("../../config/service"); +const gcfServiceSchema = service_2.baseServiceSchema + .keys({ + entrypoint: Joi.string() + .description("The entrypoint for the function (exported name in the function's module)"), + hostname: service_1.ingressHostnameSchema, + path: Joi.string() + .default(".") + .description("The path of the module that contains the function."), + project: Joi.string() + .description("The Google Cloud project name of the function."), +}) + .description("Configuration for a Google Cloud Function."); +exports.gcfServicesSchema = common_1.joiArray(gcfServiceSchema) + .min(1) + .unique("name") + .description("List of configurations for one or more Google Cloud Functions."); +const gcfModuleSpecSchema = Joi.object() + .keys({ + functions: exports.gcfServicesSchema, + tests: common_1.joiArray(generic_1.genericTestSchema), +}); +function parseGcfModule({ moduleConfig }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: check that each function exists at the specified path + moduleConfig.spec = common_1.validate(moduleConfig.spec, gcfModuleSpecSchema, { context: `module ${moduleConfig.name}` }); + moduleConfig.serviceConfigs = moduleConfig.spec.functions.map(f => ({ + name: f.name, + dependencies: f.dependencies, + outputs: f.outputs, + spec: f, + })); + moduleConfig.testConfigs = moduleConfig.spec.tests.map(t => ({ + name: t.name, + dependencies: t.dependencies, + timeout: t.timeout, + spec: t, + })); + return moduleConfig; + }); +} +exports.parseGcfModule = parseGcfModule; +exports.gardenPlugin = () => ({ + actions: { + getEnvironmentStatus: common_2.getEnvironmentStatus, + prepareEnvironment: common_2.prepareEnvironment, + }, + moduleActions: { + "google-cloud-function": { + validate: parseGcfModule, + deployService({ ctx, module, service, runtimeContext, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: provide env vars somehow to function + const project = common_2.getProject(service, ctx.provider); + const functionPath = path_1.resolve(service.module.path, service.spec.path); + const entrypoint = service.spec.entrypoint || service.name; + yield common_2.gcloud(project).call([ + "beta", "functions", + "deploy", service.name, + `--source=${functionPath}`, + `--entry-point=${entrypoint}`, + // TODO: support other trigger types + "--trigger-http", + ]); + return getServiceStatus({ ctx, module, service, runtimeContext, logEntry }); + }); + }, + getServiceOutputs({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: we may want to pull this from the service status instead, along with other outputs + const project = common_2.getProject(service, ctx.provider); + return { + ingress: `https://${common_2.GOOGLE_CLOUD_DEFAULT_REGION}-${project}.cloudfunctions.net/${service.name}`, + }; + }); + }, + }, + }, +}); +function getServiceStatus({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + const project = common_2.getProject(service, ctx.provider); + const functions = yield common_2.gcloud(project).json(["beta", "functions", "list"]); + const providerId = `projects/${project}/locations/${common_2.GOOGLE_CLOUD_DEFAULT_REGION}/functions/${service.name}`; + const status = functions.filter(f => f.name === providerId)[0]; + if (!status) { + // not deployed yet + return {}; + } + // TODO: map states properly + const state = status.status === "ACTIVE" ? "ready" : "unhealthy"; + return { + providerId, + providerVersion: status.versionId, + version: status.labels[constants_1.GARDEN_ANNOTATION_KEYS_VERSION], + state, + updatedAt: status.updateTime, + detail: status, + }; + }); +} +exports.getServiceStatus = getServiceStatus; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvZ29vZ2xlL2dvb2dsZS1jbG91ZC1mdW5jdGlvbnMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGdEQUc0QjtBQVM1QixpREFBd0Y7QUFDeEYsK0JBRWE7QUFDYiwyQkFBMEI7QUFDMUIsK0NBQWdFO0FBQ2hFLHdDQUErRDtBQUMvRCxxQ0FPaUI7QUFHakIsa0RBQXdEO0FBU3hELE1BQU0sZ0JBQWdCLEdBQUcsMkJBQWlCO0tBQ3ZDLElBQUksQ0FBQztJQUNKLFVBQVUsRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFO1NBQ3JCLFdBQVcsQ0FBQywwRUFBMEUsQ0FBQztJQUMxRixRQUFRLEVBQUUsK0JBQXFCO0lBQy9CLElBQUksRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFO1NBQ2YsT0FBTyxDQUFDLEdBQUcsQ0FBQztTQUNaLFdBQVcsQ0FBQyxvREFBb0QsQ0FBQztJQUNwRSxPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNsQixXQUFXLENBQUMsZ0RBQWdELENBQUM7Q0FDakUsQ0FBQztLQUNELFdBQVcsQ0FBQyw0Q0FBNEMsQ0FBQyxDQUFBO0FBRS9DLFFBQUEsaUJBQWlCLEdBQUcsaUJBQVEsQ0FBQyxnQkFBZ0IsQ0FBQztLQUN4RCxHQUFHLENBQUMsQ0FBQyxDQUFDO0tBQ04sTUFBTSxDQUFDLE1BQU0sQ0FBQztLQUNkLFdBQVcsQ0FBQyxnRUFBZ0UsQ0FBQyxDQUFBO0FBT2hGLE1BQU0sbUJBQW1CLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRTtLQUNyQyxJQUFJLENBQUM7SUFDSixTQUFTLEVBQUUseUJBQWlCO0lBQzVCLEtBQUssRUFBRSxpQkFBUSxDQUFDLDJCQUFpQixDQUFDO0NBQ25DLENBQUMsQ0FBQTtBQUlKLFNBQXNCLGNBQWMsQ0FDbEMsRUFBRSxZQUFZLEVBQW1DOztRQUVqRCw4REFBOEQ7UUFDOUQsWUFBWSxDQUFDLElBQUksR0FBRyxpQkFBUSxDQUMxQixZ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LENBQUMsQ0FBQyxNQUFNLEVBQUUsV0FBVyxFQUFFLE1BQU0sQ0FBQyxDQUFDLENBQUE7UUFDbEYsTUFBTSxVQUFVLEdBQUcsWUFBWSxPQUFPLGNBQWMsb0NBQTJCLGNBQWMsT0FBTyxDQUFDLElBQUksRUFBRSxDQUFBO1FBRTNHLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxLQUFLLFVBQVUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFBO1FBRTlELElBQUksQ0FBQyxNQUFNLEVBQUU7WUFDWCxtQkFBbUI7WUFDbkIsT0FBTyxFQUFFLENBQUE7U0FDVjtRQUVELDRCQUE0QjtRQUM1QixNQUFNLEtBQUssR0FBaUIsTUFBTSxDQUFDLE1BQU0sS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUMsV0FBVyxDQUFBO1FBRTlFLE9BQU87WUFDTCxVQUFVO1lBQ1YsZUFBZSxFQUFFLE1BQU0sQ0FBQyxTQUFTO1lBQ2pDLE9BQU8sRUFBRSxNQUFNLENBQUMsTUFBTSxDQUFDLDBDQUE4QixDQUFDO1lBQ3RELEtBQUs7WUFDTCxTQUFTLEVBQUUsTUFBTSxDQUFDLFVBQVU7WUFDNUIsTUFBTSxFQUFFLE1BQU07U0FDZixDQUFBO0lBQ0gsQ0FBQztDQUFBO0FBekJELDRDQXlCQyIsImZpbGUiOiJwbHVnaW5zL2dvb2dsZS9nb29nbGUtY2xvdWQtZnVuY3Rpb25zLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIGpvaUFycmF5LFxuICB2YWxpZGF0ZSxcbn0gZnJvbSBcIi4uLy4uL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uLy4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBWYWxpZGF0ZU1vZHVsZVJlc3VsdCB9IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQge1xuICBEZXBsb3lTZXJ2aWNlUGFyYW1zLFxuICBHZXRTZXJ2aWNlT3V0cHV0c1BhcmFtcyxcbiAgR2V0U2VydmljZVN0YXR1c1BhcmFtcyxcbiAgVmFsaWRhdGVNb2R1bGVQYXJhbXMsXG59IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IFNlcnZpY2VTdGF0ZSwgU2VydmljZVN0YXR1cywgaW5ncmVzc0hvc3RuYW1lU2NoZW1hIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHtcbiAgcmVzb2x2ZSxcbn0gZnJvbSBcInBhdGhcIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHsgR0FSREVOX0FOTk9UQVRJT05fS0VZU19WRVJTSU9OIH0gZnJvbSBcIi4uLy4uL2NvbnN0YW50c1wiXG5pbXBvcnQgeyBHZW5lcmljVGVzdFNwZWMsIGdlbmVyaWNUZXN0U2NoZW1hIH0gZnJvbSBcIi4uL2dlbmVyaWNcIlxuaW1wb3J0IHtcbiAgcHJlcGFyZUVudmlyb25tZW50LFxuICBnY2xvdWQsXG4gIGdldEVudmlyb25tZW50U3RhdHVzLFxuICBnZXRQcm9qZWN0LFxuICBHT09HTEVfQ0xPVURfREVGQVVMVF9SRUdJT04sXG4gIEdvb2dsZUNsb3VkU2VydmljZVNwZWMsXG59IGZyb20gXCIuL2NvbW1vblwiXG5pbXBvcnQgeyBHYXJkZW5QbHVnaW4gfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQgeyBNb2R1bGVTcGVjIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9tb2R1bGVcIlxuaW1wb3J0IHsgYmFzZVNlcnZpY2VTY2hlbWEgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3NlcnZpY2VcIlxuXG5leHBvcnQgaW50ZXJmYWNlIEdjZlNlcnZpY2VTcGVjIGV4dGVuZHMgR29vZ2xlQ2xvdWRTZXJ2aWNlU3BlYyB7XG4gIGVudHJ5cG9pbnQ/OiBzdHJpbmcsXG4gIGZ1bmN0aW9uOiBzdHJpbmcsXG4gIGhvc3RuYW1lPzogc3RyaW5nXG4gIHBhdGg6IHN0cmluZyxcbn1cblxuY29uc3QgZ2NmU2VydmljZVNjaGVtYSA9IGJhc2VTZXJ2aWNlU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBlbnRyeXBvaW50OiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBlbnRyeXBvaW50IGZvciB0aGUgZnVuY3Rpb24gKGV4cG9ydGVkIG5hbWUgaW4gdGhlIGZ1bmN0aW9uJ3MgbW9kdWxlKVwiKSxcbiAgICBob3N0bmFtZTogaW5ncmVzc0hvc3RuYW1lU2NoZW1hLFxuICAgIHBhdGg6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlZmF1bHQoXCIuXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcGF0aCBvZiB0aGUgbW9kdWxlIHRoYXQgY29udGFpbnMgdGhlIGZ1bmN0aW9uLlwiKSxcbiAgICBwcm9qZWN0OiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBHb29nbGUgQ2xvdWQgcHJvamVjdCBuYW1lIG9mIHRoZSBmdW5jdGlvbi5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIkNvbmZpZ3VyYXRpb24gZm9yIGEgR29vZ2xlIENsb3VkIEZ1bmN0aW9uLlwiKVxuXG5leHBvcnQgY29uc3QgZ2NmU2VydmljZXNTY2hlbWEgPSBqb2lBcnJheShnY2ZTZXJ2aWNlU2NoZW1hKVxuICAubWluKDEpXG4gIC51bmlxdWUoXCJuYW1lXCIpXG4gIC5kZXNjcmlwdGlvbihcIkxpc3Qgb2YgY29uZmlndXJhdGlvbnMgZm9yIG9uZSBvciBtb3JlIEdvb2dsZSBDbG91ZCBGdW5jdGlvbnMuXCIpXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2NmTW9kdWxlU3BlYyBleHRlbmRzIE1vZHVsZVNwZWMge1xuICBmdW5jdGlvbnM6IEdjZlNlcnZpY2VTcGVjW10sXG4gIHRlc3RzOiBHZW5lcmljVGVzdFNwZWNbXSxcbn1cblxuY29uc3QgZ2NmTW9kdWxlU3BlY1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgZnVuY3Rpb25zOiBnY2ZTZXJ2aWNlc1NjaGVtYSxcbiAgICB0ZXN0czogam9pQXJyYXkoZ2VuZXJpY1Rlc3RTY2hlbWEpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIEdjZk1vZHVsZSBleHRlbmRzIE1vZHVsZTxHY2ZNb2R1bGVTcGVjLCBHY2ZTZXJ2aWNlU3BlYywgR2VuZXJpY1Rlc3RTcGVjPiB7IH1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHBhcnNlR2NmTW9kdWxlKFxuICB7IG1vZHVsZUNvbmZpZyB9OiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxHY2ZNb2R1bGU+LFxuKTogUHJvbWlzZTxWYWxpZGF0ZU1vZHVsZVJlc3VsdDxHY2ZNb2R1bGU+PiB7XG4gIC8vIFRPRE86IGNoZWNrIHRoYXQgZWFjaCBmdW5jdGlvbiBleGlzdHMgYXQgdGhlIHNwZWNpZmllZCBwYXRoXG4gIG1vZHVsZUNvbmZpZy5zcGVjID0gdmFsaWRhdGUoXG4gICAgbW9kdWxlQ29uZmlnLnNwZWMsIGdjZk1vZHVsZVNwZWNTY2hlbWEsIHsgY29udGV4dDogYG1vZHVsZSAke21vZHVsZUNvbmZpZy5uYW1lfWAgfSxcbiAgKVxuXG4gIG1vZHVsZUNvbmZpZy5zZXJ2aWNlQ29uZmlncyA9IG1vZHVsZUNvbmZpZy5zcGVjLmZ1bmN0aW9ucy5tYXAoZiA9PiAoe1xuICAgIG5hbWU6IGYubmFtZSxcbiAgICBkZXBlbmRlbmNpZXM6IGYuZGVwZW5kZW5jaWVzLFxuICAgIG91dHB1dHM6IGYub3V0cHV0cyxcbiAgICBzcGVjOiBmLFxuICB9KSlcblxuICBtb2R1bGVDb25maWcudGVzdENvbmZpZ3MgPSBtb2R1bGVDb25maWcuc3BlYy50ZXN0cy5tYXAodCA9PiAoe1xuICAgIG5hbWU6IHQubmFtZSxcbiAgICBkZXBlbmRlbmNpZXM6IHQuZGVwZW5kZW5jaWVzLFxuICAgIHRpbWVvdXQ6IHQudGltZW91dCxcbiAgICBzcGVjOiB0LFxuICB9KSlcblxuICByZXR1cm4gbW9kdWxlQ29uZmlnXG59XG5cbmV4cG9ydCBjb25zdCBnYXJkZW5QbHVnaW4gPSAoKTogR2FyZGVuUGx1Z2luID0+ICh7XG4gIGFjdGlvbnM6IHtcbiAgICBnZXRFbnZpcm9ubWVudFN0YXR1cyxcbiAgICBwcmVwYXJlRW52aXJvbm1lbnQsXG4gIH0sXG4gIG1vZHVsZUFjdGlvbnM6IHtcbiAgICBcImdvb2dsZS1jbG91ZC1mdW5jdGlvblwiOiB7XG4gICAgICB2YWxpZGF0ZTogcGFyc2VHY2ZNb2R1bGUsXG5cbiAgICAgIGFzeW5jIGRlcGxveVNlcnZpY2UoXG4gICAgICAgIHsgY3R4LCBtb2R1bGUsIHNlcnZpY2UsIHJ1bnRpbWVDb250ZXh0LCBsb2dFbnRyeSB9OiBEZXBsb3lTZXJ2aWNlUGFyYW1zPEdjZk1vZHVsZT4sXG4gICAgICApIHtcbiAgICAgICAgLy8gVE9ETzogcHJvdmlkZSBlbnYgdmFycyBzb21laG93IHRvIGZ1bmN0aW9uXG4gICAgICAgIGNvbnN0IHByb2plY3QgPSBnZXRQcm9qZWN0KHNlcnZpY2UsIGN0eC5wcm92aWRlcilcbiAgICAgICAgY29uc3QgZnVuY3Rpb25QYXRoID0gcmVzb2x2ZShzZXJ2aWNlLm1vZHVsZS5wYXRoLCBzZXJ2aWNlLnNwZWMucGF0aClcbiAgICAgICAgY29uc3QgZW50cnlwb2ludCA9IHNlcnZpY2Uuc3BlYy5lbnRyeXBvaW50IHx8IHNlcnZpY2UubmFtZVxuXG4gICAgICAgIGF3YWl0IGdjbG91ZChwcm9qZWN0KS5jYWxsKFtcbiAgICAgICAgICBcImJldGFcIiwgXCJmdW5jdGlvbnNcIixcbiAgICAgICAgICBcImRlcGxveVwiLCBzZXJ2aWNlLm5hbWUsXG4gICAgICAgICAgYC0tc291cmNlPSR7ZnVuY3Rpb25QYXRofWAsXG4gICAgICAgICAgYC0tZW50cnktcG9pbnQ9JHtlbnRyeXBvaW50fWAsXG4gICAgICAgICAgLy8gVE9ETzogc3VwcG9ydCBvdGhlciB0cmlnZ2VyIHR5cGVzXG4gICAgICAgICAgXCItLXRyaWdnZXItaHR0cFwiLFxuICAgICAgICBdKVxuXG4gICAgICAgIHJldHVybiBnZXRTZXJ2aWNlU3RhdHVzKHsgY3R4LCBtb2R1bGUsIHNlcnZpY2UsIHJ1bnRpbWVDb250ZXh0LCBsb2dFbnRyeSB9KVxuICAgICAgfSxcblxuICAgICAgYXN5bmMgZ2V0U2VydmljZU91dHB1dHMoeyBjdHgsIHNlcnZpY2UgfTogR2V0U2VydmljZU91dHB1dHNQYXJhbXM8R2NmTW9kdWxlPikge1xuICAgICAgICAvLyBUT0RPOiB3ZSBtYXkgd2FudCB0byBwdWxsIHRoaXMgZnJvbSB0aGUgc2VydmljZSBzdGF0dXMgaW5zdGVhZCwgYWxvbmcgd2l0aCBvdGhlciBvdXRwdXRzXG4gICAgICAgIGNvbnN0IHByb2plY3QgPSBnZXRQcm9qZWN0KHNlcnZpY2UsIGN0eC5wcm92aWRlcilcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGluZ3Jlc3M6IGBodHRwczovLyR7R09PR0xFX0NMT1VEX0RFRkFVTFRfUkVHSU9OfS0ke3Byb2plY3R9LmNsb3VkZnVuY3Rpb25zLm5ldC8ke3NlcnZpY2UubmFtZX1gLFxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0sXG4gIH0sXG59KVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0U2VydmljZVN0YXR1cyhcbiAgeyBjdHgsIHNlcnZpY2UgfTogR2V0U2VydmljZVN0YXR1c1BhcmFtczxHY2ZNb2R1bGU+LFxuKTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPiB7XG4gIGNvbnN0IHByb2plY3QgPSBnZXRQcm9qZWN0KHNlcnZpY2UsIGN0eC5wcm92aWRlcilcbiAgY29uc3QgZnVuY3Rpb25zOiBhbnlbXSA9IGF3YWl0IGdjbG91ZChwcm9qZWN0KS5qc29uKFtcImJldGFcIiwgXCJmdW5jdGlvbnNcIiwgXCJsaXN0XCJdKVxuICBjb25zdCBwcm92aWRlcklkID0gYHByb2plY3RzLyR7cHJvamVjdH0vbG9jYXRpb25zLyR7R09PR0xFX0NMT1VEX0RFRkFVTFRfUkVHSU9OfS9mdW5jdGlvbnMvJHtzZXJ2aWNlLm5hbWV9YFxuXG4gIGNvbnN0IHN0YXR1cyA9IGZ1bmN0aW9ucy5maWx0ZXIoZiA9PiBmLm5hbWUgPT09IHByb3ZpZGVySWQpWzBdXG5cbiAgaWYgKCFzdGF0dXMpIHtcbiAgICAvLyBub3QgZGVwbG95ZWQgeWV0XG4gICAgcmV0dXJuIHt9XG4gIH1cblxuICAvLyBUT0RPOiBtYXAgc3RhdGVzIHByb3Blcmx5XG4gIGNvbnN0IHN0YXRlOiBTZXJ2aWNlU3RhdGUgPSBzdGF0dXMuc3RhdHVzID09PSBcIkFDVElWRVwiID8gXCJyZWFkeVwiIDogXCJ1bmhlYWx0aHlcIlxuXG4gIHJldHVybiB7XG4gICAgcHJvdmlkZXJJZCxcbiAgICBwcm92aWRlclZlcnNpb246IHN0YXR1cy52ZXJzaW9uSWQsXG4gICAgdmVyc2lvbjogc3RhdHVzLmxhYmVsc1tHQVJERU5fQU5OT1RBVElPTl9LRVlTX1ZFUlNJT05dLFxuICAgIHN0YXRlLFxuICAgIHVwZGF0ZWRBdDogc3RhdHVzLnVwZGF0ZVRpbWUsXG4gICAgZGV0YWlsOiBzdGF0dXMsXG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/actions.d.ts b/garden-service/build/plugins/kubernetes/actions.d.ts new file mode 100644 index 00000000000..6becfa24025 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/actions.d.ts @@ -0,0 +1,20 @@ +import { GetServiceLogsResult, RunResult, TestResult } from "../../types/plugin/outputs"; +import { ExecInServiceParams, GetServiceLogsParams, GetServiceOutputsParams, GetTestResultParams, RunModuleParams, TestModuleParams, DeleteServiceParams, RunServiceParams } from "../../types/plugin/params"; +import { ContainerModule } from "../container"; +import { ServiceStatus } from "../../types/service"; +import { ValidateModuleParams } from "../../types/plugin/params"; +export declare function validate(params: ValidateModuleParams): Promise; +export declare function deleteService(params: DeleteServiceParams): Promise; +export declare function getServiceOutputs({ service }: GetServiceOutputsParams): Promise<{ + host: string; +}>; +export declare function execInService(params: ExecInServiceParams): Promise<{ + code: number; + output: string; +}>; +export declare function runModule({ ctx, module, command, interactive, runtimeContext, silent, timeout }: RunModuleParams): Promise; +export declare function runService({ ctx, service, interactive, runtimeContext, silent, timeout, logEntry }: RunServiceParams): Promise; +export declare function testModule({ ctx, interactive, module, runtimeContext, silent, testConfig, logEntry }: TestModuleParams): Promise; +export declare function getTestResult({ ctx, module, testName, version }: GetTestResultParams): Promise; +export declare function getServiceLogs({ ctx, service, stream, tail }: GetServiceLogsParams): Promise; +//# sourceMappingURL=actions.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/actions.js b/garden-service/build/plugins/kubernetes/actions.js new file mode 100644 index 00000000000..fd142572d5c --- /dev/null +++ b/garden-service/build/plugins/kubernetes/actions.js @@ -0,0 +1,268 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const split = require("split"); +const moment = require("moment"); +const exceptions_1 = require("../../exceptions"); +const container_1 = require("../container"); +const util_1 = require("../../util/util"); +const api_1 = require("./api"); +const namespace_1 = require("./namespace"); +const kubectl_1 = require("./kubectl"); +const constants_1 = require("../../constants"); +const deployment_1 = require("./deployment"); +function validate(params) { + return __awaiter(this, void 0, void 0, function* () { + const config = yield container_1.validateContainerModule(params); + // validate ingress specs + const provider = params.ctx.provider; + for (const serviceConfig of config.serviceConfigs) { + for (const ingressSpec of serviceConfig.spec.ingresses) { + const hostname = ingressSpec.hostname || provider.config.defaultHostname; + if (!hostname) { + throw new exceptions_1.ConfigurationError(`No hostname configured for one of the ingresses on service ${serviceConfig.name}. ` + + `Please configure a default hostname or specify a hostname for the ingress.`, { + serviceName: serviceConfig.name, + ingressSpec, + }); + } + // make sure the hostname is set + ingressSpec.hostname = hostname; + } + } + }); +} +exports.validate = validate; +function deleteService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, logEntry, service } = params; + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const provider = ctx.provider; + yield deployment_1.deleteContainerService({ provider, namespace, serviceName: service.name, logEntry }); + return deployment_1.getContainerServiceStatus(params); + }); +} +exports.deleteService = deleteService; +function getServiceOutputs({ service }) { + return __awaiter(this, void 0, void 0, function* () { + return { + host: service.name, + }; + }); +} +exports.getServiceOutputs = getServiceOutputs; +function execInService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, service, command } = params; + const api = new api_1.KubeApi(ctx.provider); + const status = yield deployment_1.getContainerServiceStatus(params); + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + // TODO: this check should probably live outside of the plugin + if (!status.state || status.state !== "ready") { + throw new exceptions_1.DeploymentError(`Service ${service.name} is not running`, { + name: service.name, + state: status.state, + }); + } + // get a running pod + // NOTE: the awkward function signature called out here: https://github.com/kubernetes-client/javascript/issues/53 + const podsRes = yield api.core.listNamespacedPod(namespace, undefined, undefined, undefined, undefined, `service=${service.name}`); + const pod = podsRes.body.items[0]; + if (!pod) { + // This should not happen because of the prior status check, but checking to be sure + throw new exceptions_1.DeploymentError(`Could not find running pod for ${service.name}`, { + serviceName: service.name, + }); + } + // exec in the pod via kubectl + const kubecmd = ["exec", "-it", pod.metadata.name, "--", ...command]; + const res = yield kubectl_1.kubectl(api.context, namespace).tty(kubecmd, { + ignoreError: true, + silent: false, + timeout: 999999, + tty: true, + }); + return { code: res.code, output: res.output }; + }); +} +exports.execInService = execInService; +function runModule({ ctx, module, command, interactive, runtimeContext, silent, timeout }) { + return __awaiter(this, void 0, void 0, function* () { + const context = ctx.provider.config.context; + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const envArgs = Object.entries(runtimeContext.envVars).map(([k, v]) => `--env=${k}=${v}`); + const commandStr = command.join(" "); + const image = yield container_1.helpers.getLocalImageId(module); + const version = module.version; + const opts = [ + `--image=${image}`, + "--restart=Never", + "--command", + "--tty", + "--rm", + "-i", + "--quiet", + ]; + const kubecmd = [ + "run", `run-${module.name}-${Math.round(new Date().getTime())}`, + ...opts, + ...envArgs, + "--", + "/bin/sh", + "-c", + commandStr, + ]; + const startedAt = new Date(); + const res = yield kubectl_1.kubectl(context, namespace).tty(kubecmd, { + ignoreError: true, + silent: !interactive || silent, + timeout, + tty: interactive, + }); + return { + moduleName: module.name, + command, + version, + success: res.code === 0, + startedAt, + completedAt: new Date(), + output: res.output, + }; + }); +} +exports.runModule = runModule; +function runService({ ctx, service, interactive, runtimeContext, silent, timeout, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + return runModule({ + ctx, + module: service.module, + command: service.spec.command || [], + interactive, + runtimeContext, + silent, + timeout, + logEntry, + }); + }); +} +exports.runService = runService; +function testModule({ ctx, interactive, module, runtimeContext, silent, testConfig, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const testName = testConfig.name; + const command = testConfig.spec.command; + runtimeContext.envVars = Object.assign({}, runtimeContext.envVars, testConfig.spec.env); + const timeout = testConfig.timeout || constants_1.DEFAULT_TEST_TIMEOUT; + const result = yield runModule({ + ctx, + module, + command, + interactive, + runtimeContext, + silent, + timeout, + logEntry, + }); + const api = new api_1.KubeApi(ctx.provider); + // store test result + const testResult = Object.assign({}, result, { testName }); + const ns = yield namespace_1.getMetadataNamespace(ctx, ctx.provider); + const resultKey = getTestResultKey(module, testName, result.version); + const body = { + apiVersion: "v1", + kind: "ConfigMap", + metadata: { + name: resultKey, + annotations: { + "garden.io/generated": "true", + }, + }, + data: util_1.serializeValues(testResult), + }; + try { + yield api.core.createNamespacedConfigMap(ns, body); + } + catch (err) { + if (err.code === 409) { + yield api.core.patchNamespacedConfigMap(resultKey, ns, body); + } + else { + throw err; + } + } + return testResult; + }); +} +exports.testModule = testModule; +function getTestResult({ ctx, module, testName, version }) { + return __awaiter(this, void 0, void 0, function* () { + const api = new api_1.KubeApi(ctx.provider); + const ns = yield namespace_1.getMetadataNamespace(ctx, ctx.provider); + const resultKey = getTestResultKey(module, testName, version); + try { + const res = yield api.core.readNamespacedConfigMap(resultKey, ns); + return util_1.deserializeValues(res.body.data); + } + catch (err) { + if (err.code === 404) { + return null; + } + else { + throw err; + } + } + }); +} +exports.getTestResult = getTestResult; +function getServiceLogs({ ctx, service, stream, tail }) { + return __awaiter(this, void 0, void 0, function* () { + const context = ctx.provider.config.context; + const resourceType = service.spec.daemon ? "daemonset" : "deployment"; + const kubectlArgs = ["logs", `${resourceType}/${service.name}`, "--timestamps=true"]; + if (tail) { + kubectlArgs.push("--follow"); + } + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const proc = kubectl_1.kubectl(context, namespace).spawn(kubectlArgs); + let timestamp; + proc.stdout + .pipe(split()) + .on("data", (s) => { + if (!s) { + return; + } + const [timestampStr, msg] = util_1.splitFirst(s, " "); + try { + timestamp = moment(timestampStr).toDate(); + } + catch (_a) { } + void stream.write({ serviceName: service.name, timestamp, msg }); + }); + proc.stderr.pipe(process.stderr); + return new Promise((resolve, reject) => { + proc.on("error", reject); + proc.on("exit", () => { + resolve({}); + }); + }); + }); +} +exports.getServiceLogs = getServiceLogs; +function getTestResultKey(module, testName, version) { + return `test-result--${module.name}--${testName}--${version.versionString}`; +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9hY3Rpb25zLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCwrQkFBOEI7QUFDOUIsaUNBQWlDO0FBRWpDLGlEQUFzRTtBQWF0RSw0Q0FBZ0Y7QUFDaEYsMENBQWdGO0FBQ2hGLCtCQUErQjtBQUMvQiwyQ0FBbUU7QUFDbkUsdUNBQW1DO0FBQ25DLCtDQUFzRDtBQUV0RCw2Q0FBZ0Y7QUFJaEYsU0FBc0IsUUFBUSxDQUFDLE1BQTZDOztRQUMxRSxNQUFNLE1BQU0sR0FBRyxNQUFNLG1DQUF1QixDQUFDLE1BQU0sQ0FBQyxDQUFBO1FBRXBELHlCQUF5QjtRQUN6QixNQUFNLFFBQVEsR0FBdUIsTUFBTSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUE7UUFFeEQsS0FBSyxNQUFNLGFBQWEsSUFBSSxNQUFNLENBQUMsY0FBYyxFQUFFO1lBQ2pELEtBQUssTUFBTSxXQUFXLElBQUksYUFBYSxDQUFDLElBQUksQ0FBQyxTQUFTLEVBQUU7Z0JBQ3RELE1BQU0sUUFBUSxHQUFHLFdBQVcsQ0FBQyxRQUFRLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxlQUFlLENBQUE7Z0JBRXhFLElBQUksQ0FBQyxRQUFRLEVBQUU7b0JBQ2IsTUFBTSxJQUFJLCtCQUFrQixDQUMxQiw4REFBOEQsYUFBYSxDQUFDLElBQUksSUFBSTt3QkFDcEYsNEVBQTRFLEVBQzVFO3dCQUNFLFdBQVcsRUFBRSxhQUFhLENBQUMsSUFBSTt3QkFDL0IsV0FBVztxQkFDWixDQUNGLENBQUE7aUJBQ0Y7Z0JBRUQsZ0NBQWdDO2dCQUNoQyxXQUFXLENBQUMsUUFBUSxHQUFHLFFBQVEsQ0FBQTthQUNoQztTQUNGO0lBQ0gsQ0FBQztDQUFBO0FBekJELDRCQXlCQztBQUVELFNBQXNCLGFBQWEsQ0FBQyxNQUEyQjs7UUFDN0QsTUFBTSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsT0FBTyxFQUFFLEdBQUcsTUFBTSxDQUFB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LEVBQUU7Z0JBQ25CLE9BQU8sQ0FBQyxFQUFFLENBQUMsQ0FBQTtZQUNiLENBQUMsQ0FBQyxDQUFBO1FBQ0osQ0FBQyxDQUFDLENBQUE7SUFDSixDQUFDO0NBQUE7QUF0Q0Qsd0NBc0NDO0FBRUQsU0FBUyxnQkFBZ0IsQ0FBQyxNQUF1QixFQUFFLFFBQWdCLEVBQUUsT0FBc0I7SUFDekYsT0FBTyxnQkFBZ0IsTUFBTSxDQUFDLElBQUksS0FBSyxRQUFRLEtBQUssT0FBTyxDQUFDLGFBQWEsRUFBRSxDQUFBO0FBQzdFLENBQUMiLCJmaWxlIjoicGx1Z2lucy9rdWJlcm5ldGVzL2FjdGlvbnMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgc3BsaXQgZnJvbSBcInNwbGl0XCJcbmltcG9ydCBtb21lbnQgPSByZXF1aXJlKFwibW9tZW50XCIpXG5cbmltcG9ydCB7IERlcGxveW1lbnRFcnJvciwgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgR2V0U2VydmljZUxvZ3NSZXN1bHQsIFJ1blJlc3VsdCwgVGVzdFJlc3VsdCB9IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQge1xuICBFeGVjSW5TZXJ2aWNlUGFyYW1zLFxuICBHZXRTZXJ2aWNlTG9nc1BhcmFtcyxcbiAgR2V0U2VydmljZU91dHB1dHNQYXJhbXMsXG4gIEdldFRlc3RSZXN1bHRQYXJhbXMsXG4gIFJ1bk1vZHVsZVBhcmFtcyxcbiAgVGVzdE1vZHVsZVBhcmFtcyxcbiAgRGVsZXRlU2VydmljZVBhcmFtcyxcbiAgUnVuU2VydmljZVBhcmFtcyxcbn0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9wYXJhbXNcIlxuaW1wb3J0IHsgTW9kdWxlVmVyc2lvbiB9IGZyb20gXCIuLi8uLi92Y3MvYmFzZVwiXG5pbXBvcnQgeyBDb250YWluZXJNb2R1bGUsIGhlbHBlcnMsIHZhbGlkYXRlQ29udGFpbmVyTW9kdWxlIH0gZnJvbSBcIi4uL2NvbnRhaW5lclwiXG5pbXBvcnQgeyBkZXNlcmlhbGl6ZVZhbHVlcywgc2VyaWFsaXplVmFsdWVzLCBzcGxpdEZpcnN0IH0gZnJvbSBcIi4uLy4uL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBLdWJlQXBpIH0gZnJvbSBcIi4vYXBpXCJcbmltcG9ydCB7IGdldEFwcE5hbWVzcGFjZSwgZ2V0TWV0YWRhdGFOYW1lc3BhY2UgfSBmcm9tIFwiLi9uYW1lc3BhY2VcIlxuaW1wb3J0IHsga3ViZWN0bCB9IGZyb20gXCIuL2t1YmVjdGxcIlxuaW1wb3J0IHsgREVGQVVMVF9URVNUX1RJTUVPVVQgfSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IEt1YmVybmV0ZXNQcm92aWRlciB9IGZyb20gXCIuL2t1YmVybmV0ZXNcIlxuaW1wb3J0IHsgZGVsZXRlQ29udGFpbmVyU2VydmljZSwgZ2V0Q29udGFpbmVyU2VydmljZVN0YXR1cyB9IGZyb20gXCIuL2RlcGxveW1lbnRcIlxuaW1wb3J0IHsgU2VydmljZVN0YXR1cyB9IGZyb20gXCIuLi8uLi90eXBlcy9zZXJ2aWNlXCJcbmltcG9ydCB7IFZhbGlkYXRlTW9kdWxlUGFyYW1zIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9wYXJhbXNcIlxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gdmFsaWRhdGUocGFyYW1zOiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxDb250YWluZXJNb2R1bGU+KSB7XG4gIGNvbnN0IGNvbmZpZyA9IGF3YWl0IHZhbGlkYXRlQ29udGFpbmVyTW9kdWxlKHBhcmFtcylcblxuICAvLyB2YWxpZGF0ZSBpbmdyZXNzIHNwZWNzXG4gIGNvbnN0IHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIgPSBwYXJhbXMuY3R4LnByb3ZpZGVyXG5cbiAgZm9yIChjb25zdCBzZXJ2aWNlQ29uZmlnIG9mIGNvbmZpZy5zZXJ2aWNlQ29uZmlncykge1xuICAgIGZvciAoY29uc3QgaW5ncmVzc1NwZWMgb2Ygc2VydmljZUNvbmZpZy5zcGVjLmluZ3Jlc3Nlcykge1xuICAgICAgY29uc3QgaG9zdG5hbWUgPSBpbmdyZXNzU3BlYy5ob3N0bmFtZSB8fCBwcm92aWRlci5jb25maWcuZGVmYXVsdEhvc3RuYW1lXG5cbiAgICAgIGlmICghaG9zdG5hbWUpIHtcbiAgICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgICBgTm8gaG9zdG5hbWUgY29uZmlndXJlZCBmb3Igb25lIG9mIHRoZSBpbmdyZXNzZXMgb24gc2VydmljZSAke3NlcnZpY2VDb25maWcubmFtZX0uIGAgK1xuICAgICAgICAgIGBQbGVhc2UgY29uZmlndXJlIGEgZGVmYXVsdCBob3N0bmFtZSBvciBzcGVjaWZ5IGEgaG9zdG5hbWUgZm9yIHRoZSBpbmdyZXNzLmAsXG4gICAgICAgICAge1xuICAgICAgICAgICAgc2VydmljZU5hbWU6IHNlcnZpY2VDb25maWcubmFtZSxcbiAgICAgICAgICAgIGluZ3Jlc3NTcGVjLFxuICAgICAgICAgIH0sXG4gICAgICAgIClcbiAgICAgIH1cblxuICAgICAgLy8gbWFrZSBzdXJlIHRoZSBob3N0bmFtZSBpcyBzZXRcbiAgICAgIGluZ3Jlc3NTcGVjLmhvc3RuYW1lID0gaG9zdG5hbWVcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZVNlcnZpY2UocGFyYW1zOiBEZWxldGVTZXJ2aWNlUGFyYW1zKTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPiB7XG4gIGNvbnN0IHsgY3R4LCBsb2dFbnRyeSwgc2VydmljZSB9ID0gcGFyYW1zXG4gIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcbiAgY29uc3QgcHJvdmlkZXIgPSBjdHgucHJvdmlkZXJcblxuICBhd2FpdCBkZWxldGVDb250YWluZXJTZXJ2aWNlKFxuICAgIHsgcHJvdmlkZXIsIG5hbWVzcGFjZSwgc2VydmljZU5hbWU6IHNlcnZpY2UubmFtZSwgbG9nRW50cnkgfSlcblxuICByZXR1cm4gZ2V0Q29udGFpbmVyU2VydmljZVN0YXR1cyhwYXJhbXMpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRTZXJ2aWNlT3V0cHV0cyh7IHNlcnZpY2UgfTogR2V0U2VydmljZU91dHB1dHNQYXJhbXM8Q29udGFpbmVyTW9kdWxlPikge1xuICByZXR1cm4ge1xuICAgIGhvc3Q6IHNlcnZpY2UubmFtZSxcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZXhlY0luU2VydmljZShwYXJhbXM6IEV4ZWNJblNlcnZpY2VQYXJhbXM8Q29udGFpbmVyTW9kdWxlPikge1xuICBjb25zdCB7IGN0eCwgc2VydmljZSwgY29tbWFuZCB9ID0gcGFyYW1zXG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKGN0eC5wcm92aWRlcilcbiAgY29uc3Qgc3RhdHVzID0gYXdhaXQgZ2V0Q29udGFpbmVyU2VydmljZVN0YXR1cyhwYXJhbXMpXG4gIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcblxuICAvLyBUT0RPOiB0aGlzIGNoZWNrIHNob3VsZCBwcm9iYWJseSBsaXZlIG91dHNpZGUgb2YgdGhlIHBsdWdpblxuICBpZiAoIXN0YXR1cy5zdGF0ZSB8fCBzdGF0dXMuc3RhdGUgIT09IFwicmVhZHlcIikge1xuICAgIHRocm93IG5ldyBEZXBsb3ltZW50RXJyb3IoYFNlcnZpY2UgJHtzZXJ2aWNlLm5hbWV9IGlzIG5vdCBydW5uaW5nYCwge1xuICAgICAgbmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgc3RhdGU6IHN0YXR1cy5zdGF0ZSxcbiAgICB9KVxuICB9XG5cbiAgLy8gZ2V0IGEgcnVubmluZyBwb2RcbiAgLy8gTk9URTogdGhlIGF3a3dhcmQgZnVuY3Rpb24gc2lnbmF0dXJlIGNhbGxlZCBvdXQgaGVyZTogaHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMtY2xpZW50L2phdmFzY3JpcHQvaXNzdWVzLzUzXG4gIGNvbnN0IHBvZHNSZXMgPSBhd2FpdCBhcGkuY29yZS5saXN0TmFtZXNwYWNlZFBvZChcbiAgICBuYW1lc3BhY2UsXG4gICAgdW5kZWZpbmVkLFxuICAgIHVuZGVmaW5lZCxcbiAgICB1bmRlZmluZWQsXG4gICAgdW5kZWZpbmVkLFxuICAgIGBzZXJ2aWNlPSR7c2VydmljZS5uYW1lfWAsXG4gIClcbiAgY29uc3QgcG9kID0gcG9kc1Jlcy5ib2R5Lml0ZW1zWzBdXG5cbiAgaWYgKCFwb2QpIHtcbiAgICAvLyBUaGlzIHNob3VsZCBub3QgaGFwcGVuIGJlY2F1c2Ugb2YgdGhlIHByaW9yIHN0YXR1cyBjaGVjaywgYnV0IGNoZWNraW5nIHRvIGJlIHN1cmVcbiAgICB0aHJvdyBuZXcgRGVwbG95bWVudEVycm9yKGBDb3VsZCBub3QgZmluZCBydW5uaW5nIHBvZCBmb3IgJHtzZXJ2aWNlLm5hbWV9YCwge1xuICAgICAgc2VydmljZU5hbWU6IHNlcnZpY2UubmFtZSxcbiAgICB9KVxuICB9XG5cbiAgLy8gZXhlYyBpbiB0aGUgcG9kIHZpYSBrdWJlY3RsXG4gIGNvbnN0IGt1YmVjbWQgPSBbXCJleGVjXCIsIFwiLWl0XCIsIHBvZC5tZXRhZGF0YS5uYW1lLCBcIi0tXCIsIC4uLmNvbW1hbmRdXG4gIGNvbnN0IHJlcyA9IGF3YWl0IGt1YmVjdGwoYXBpLmNvbnRleHQsIG5hbWVzcGFjZSkudHR5KGt1YmVjbWQsIHtcbiAgICBpZ25vcmVFcnJvcjogdHJ1ZSxcbiAgICBzaWxlbnQ6IGZhbHNlLFxuICAgIHRpbWVvdXQ6IDk5OTk5OSxcbiAgICB0dHk6IHRydWUsXG4gIH0pXG5cbiAgcmV0dXJuIHsgY29kZTogcmVzLmNvZGUsIG91dHB1dDogcmVzLm91dHB1dCB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBydW5Nb2R1bGUoXG4gIHsgY3R4LCBtb2R1bGUsIGNvbW1hbmQsIGludGVyYWN0aXZlLCBydW50aW1lQ29udGV4dCwgc2lsZW50LCB0aW1lb3V0IH06IFJ1bk1vZHVsZVBhcmFtczxDb250YWluZXJNb2R1bGU+LFxuKTogUHJvbWlzZTxSdW5SZXN1bHQ+IHtcbiAgY29uc3QgY29udGV4dCA9IGN0eC5wcm92aWRlci5jb25maWcuY29udGV4dFxuICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBjdHgucHJvdmlkZXIpXG5cbiAgY29uc3QgZW52QXJncyA9IE9iamVjdC5lbnRyaWVzKHJ1bnRpbWVDb250ZXh0LmVudlZhcnMpLm1hcCgoW2ssIHZdKSA9PiBgLS1lbnY9JHtrfT0ke3Z9YClcblxuICBjb25zdCBjb21tYW5kU3RyID0gY29tbWFuZC5qb2luKFwiIFwiKVxuICBjb25zdCBpbWFnZSA9IGF3YWl0IGhlbHBlcnMuZ2V0TG9jYWxJbWFnZUlkKG1vZHVsZSlcbiAgY29uc3QgdmVyc2lvbiA9IG1vZHVsZS52ZXJzaW9uXG5cbiAgY29uc3Qgb3B0cyA9IFtcbiAgICBgLS1pbWFnZT0ke2ltYWdlfWAsXG4gICAgXCItLXJlc3RhcnQ9TmV2ZXJcIixcbiAgICBcIi0tY29tbWFuZFwiLFxuICAgIFwiLS10dHlcIixcbiAgICBcIi0tcm1cIixcbiAgICBcIi1pXCIsXG4gICAgXCItLXF1aWV0XCIsXG4gIF1cblxuICBjb25zdCBrdWJlY21kID0gW1xuICAgIFwicnVuXCIsIGBydW4tJHttb2R1bGUubmFtZX0tJHtNYXRoLnJvdW5kKG5ldyBEYXRlKCkuZ2V0VGltZSgpKX1gLFxuICAgIC4uLm9wdHMsXG4gICAgLi4uZW52QXJncyxcbiAgICBcIi0tXCIsXG4gICAgXCIvYmluL3NoXCIsXG4gICAgXCItY1wiLFxuICAgIGNvbW1hbmRTdHIsXG4gIF1cblxuICBjb25zdCBzdGFydGVkQXQgPSBuZXcgRGF0ZSgpXG5cbiAgY29uc3QgcmVzID0gYXdhaXQga3ViZWN0bChjb250ZXh0LCBuYW1lc3BhY2UpLnR0eShrdWJlY21kLCB7XG4gICAgaWdub3JlRXJyb3I6IHRydWUsXG4gICAgc2lsZW50OiAhaW50ZXJhY3RpdmUgfHwgc2lsZW50LCAvLyBzaG91bGRuJ3QgYmUgc2lsZW50IGluIGludGVyYWN0aXZlIG1vZGVcbiAgICB0aW1lb3V0LFxuICAgIHR0eTogaW50ZXJhY3RpdmUsXG4gIH0pXG5cbiAgcmV0dXJuIHtcbiAgICBtb2R1bGVOYW1lOiBtb2R1bGUubmFtZSxcbiAgICBjb21tYW5kLFxuICAgIHZlcnNpb24sXG4gICAgc3VjY2VzczogcmVzLmNvZGUgPT09IDAsXG4gICAgc3RhcnRlZEF0LFxuICAgIGNvbXBsZXRlZEF0OiBuZXcgRGF0ZSgpLFxuICAgIG91dHB1dDogcmVzLm91dHB1dCxcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcnVuU2VydmljZShcbiAgeyBjdHgsIHNlcnZpY2UsIGludGVyYWN0aXZlLCBydW50aW1lQ29udGV4dCwgc2lsZW50LCB0aW1lb3V0LCBsb2dFbnRyeSB9OlxuICAgIFJ1blNlcnZpY2VQYXJhbXM8Q29udGFpbmVyTW9kdWxlPixcbikge1xuICByZXR1cm4gcnVuTW9kdWxlKHtcbiAgICBjdHgsXG4gICAgbW9kdWxlOiBzZXJ2aWNlLm1vZHVsZSxcbiAgICBjb21tYW5kOiBzZXJ2aWNlLnNwZWMuY29tbWFuZCB8fCBbXSxcbiAgICBpbnRlcmFjdGl2ZSxcbiAgICBydW50aW1lQ29udGV4dCxcbiAgICBzaWxlbnQsXG4gICAgdGltZW91dCxcbiAgICBsb2dFbnRyeSxcbiAgfSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHRlc3RNb2R1bGUoXG4gIHsgY3R4LCBpbnRlcmFjdGl2ZSwgbW9kdWxlLCBydW50aW1lQ29udGV4dCwgc2lsZW50LCB0ZXN0Q29uZmlnLCBsb2dFbnRyeSB9OlxuICAgIFRlc3RNb2R1bGVQYXJhbXM8Q29udGFpbmVyTW9kdWxlPixcbik6IFByb21pc2U8VGVzdFJlc3VsdD4ge1xuICBjb25zdCB0ZXN0TmFtZSA9IHRlc3RDb25maWcubmFtZVxuICBjb25zdCBjb21tYW5kID0gdGVzdENvbmZpZy5zcGVjLmNvbW1hbmRcbiAgcnVudGltZUNvbnRleHQuZW52VmFycyA9IHsgLi4ucnVudGltZUNvbnRleHQuZW52VmFycywgLi4udGVzdENvbmZpZy5zcGVjLmVudiB9XG4gIGNvbnN0IHRpbWVvdXQgPSB0ZXN0Q29uZmlnLnRpbWVvdXQgfHwgREVGQVVMVF9URVNUX1RJTUVPVVRcblxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBydW5Nb2R1bGUoe1xuICAgIGN0eCxcbiAgICBtb2R1bGUsXG4gICAgY29tbWFuZCxcbiAgICBpbnRlcmFjdGl2ZSxcbiAgICBydW50aW1lQ29udGV4dCxcbiAgICBzaWxlbnQsXG4gICAgdGltZW91dCxcbiAgICBsb2dFbnRyeSxcbiAgfSlcblxuICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShjdHgucHJvdmlkZXIpXG5cbiAgLy8gc3RvcmUgdGVzdCByZXN1bHRcbiAgY29uc3QgdGVzdFJlc3VsdDogVGVzdFJlc3VsdCA9IHtcbiAgICAuLi5yZXN1bHQsXG4gICAgdGVzdE5hbWUsXG4gIH1cblxuICBjb25zdCBucyA9IGF3YWl0IGdldE1ldGFkYXRhTmFtZXNwYWNlKGN0eCwgY3R4LnByb3ZpZGVyKVxuICBjb25zdCByZXN1bHRLZXkgPSBnZXRUZXN0UmVzdWx0S2V5KG1vZHVsZSwgdGVzdE5hbWUsIHJlc3VsdC52ZXJzaW9uKVxuICBjb25zdCBib2R5ID0ge1xuICAgIGFwaVZlcnNpb246IFwidjFcIixcbiAgICBraW5kOiBcIkNvbmZpZ01hcFwiLFxuICAgIG1ldGFkYXRhOiB7XG4gICAgICBuYW1lOiByZXN1bHRLZXksXG4gICAgICBhbm5vdGF0aW9uczoge1xuICAgICAgICBcImdhcmRlbi5pby9nZW5lcmF0ZWRcIjogXCJ0cnVlXCIsXG4gICAgICB9LFxuICAgIH0sXG4gICAgZGF0YTogc2VyaWFsaXplVmFsdWVzKHRlc3RSZXN1bHQpLFxuICB9XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBhcGkuY29yZS5jcmVhdGVOYW1lc3BhY2VkQ29uZmlnTWFwKG5zLCA8YW55PmJvZHkpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuY29kZSA9PT0gNDA5KSB7XG4gICAgICBhd2FpdCBhcGkuY29yZS5wYXRjaE5hbWVzcGFjZWRDb25maWdNYXAocmVzdWx0S2V5LCBucywgYm9keSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRlc3RSZXN1bHRcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFRlc3RSZXN1bHQoXG4gIHsgY3R4LCBtb2R1bGUsIHRlc3ROYW1lLCB2ZXJzaW9uIH06IEdldFRlc3RSZXN1bHRQYXJhbXM8Q29udGFpbmVyTW9kdWxlPixcbikge1xuICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShjdHgucHJvdmlkZXIpXG4gIGNvbnN0IG5zID0gYXdhaXQgZ2V0TWV0YWRhdGFOYW1lc3BhY2UoY3R4LCBjdHgucHJvdmlkZXIpXG4gIGNvbnN0IHJlc3VsdEtleSA9IGdldFRlc3RSZXN1bHRLZXkobW9kdWxlLCB0ZXN0TmFtZSwgdmVyc2lvbilcblxuICB0cnkge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFwaS5jb3JlLnJlYWROYW1lc3BhY2VkQ29uZmlnTWFwKHJlc3VsdEtleSwgbnMpXG4gICAgcmV0dXJuIDxUZXN0UmVzdWx0PmRlc2VyaWFsaXplVmFsdWVzKHJlcy5ib2R5LmRhdGEpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuY29kZSA9PT0gNDA0KSB7XG4gICAgICByZXR1cm4gbnVsbFxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFNlcnZpY2VMb2dzKFxuICB7IGN0eCwgc2VydmljZSwgc3RyZWFtLCB0YWlsIH06IEdldFNlcnZpY2VMb2dzUGFyYW1zPENvbnRhaW5lck1vZHVsZT4sXG4pIHtcbiAgY29uc3QgY29udGV4dCA9IGN0eC5wcm92aWRlci5jb25maWcuY29udGV4dFxuICBjb25zdCByZXNvdXJjZVR5cGUgPSBzZXJ2aWNlLnNwZWMuZGFlbW9uID8gXCJkYWVtb25zZXRcIiA6IFwiZGVwbG95bWVudFwiXG5cbiAgY29uc3Qga3ViZWN0bEFyZ3MgPSBbXCJsb2dzXCIsIGAke3Jlc291cmNlVHlwZX0vJHtzZXJ2aWNlLm5hbWV9YCwgXCItLXRpbWVzdGFtcHM9dHJ1ZVwiXVxuXG4gIGlmICh0YWlsKSB7XG4gICAga3ViZWN0bEFyZ3MucHVzaChcIi0tZm9sbG93XCIpXG4gIH1cblxuICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBjdHgucHJvdmlkZXIpXG4gIGNvbnN0IHByb2MgPSBrdWJlY3RsKGNvbnRleHQsIG5hbWVzcGFjZSkuc3Bhd24oa3ViZWN0bEFyZ3MpXG4gIGxldCB0aW1lc3RhbXA6IERhdGVcblxuICBwcm9jLnN0ZG91dFxuICAgIC5waXBlKHNwbGl0KCkpXG4gICAgLm9uKFwiZGF0YVwiLCAocykgPT4ge1xuICAgICAgaWYgKCFzKSB7XG4gICAgICAgIHJldHVyblxuICAgICAgfVxuICAgICAgY29uc3QgW3RpbWVzdGFtcFN0ciwgbXNnXSA9IHNwbGl0Rmlyc3QocywgXCIgXCIpXG4gICAgICB0cnkge1xuICAgICAgICB0aW1lc3RhbXAgPSBtb21lbnQodGltZXN0YW1wU3RyKS50b0RhdGUoKVxuICAgICAgfSBjYXRjaCB7IH1cbiAgICAgIHZvaWQgc3RyZWFtLndyaXRlKHsgc2VydmljZU5hbWU6IHNlcnZpY2UubmFtZSwgdGltZXN0YW1wLCBtc2cgfSlcbiAgICB9KVxuXG4gIHByb2Muc3RkZXJyLnBpcGUocHJvY2Vzcy5zdGRlcnIpXG5cbiAgcmV0dXJuIG5ldyBQcm9taXNlPEdldFNlcnZpY2VMb2dzUmVzdWx0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgcHJvYy5vbihcImVycm9yXCIsIHJlamVjdClcblxuICAgIHByb2Mub24oXCJleGl0XCIsICgpID0+IHtcbiAgICAgIHJlc29sdmUoe30pXG4gICAgfSlcbiAgfSlcbn1cblxuZnVuY3Rpb24gZ2V0VGVzdFJlc3VsdEtleShtb2R1bGU6IENvbnRhaW5lck1vZHVsZSwgdGVzdE5hbWU6IHN0cmluZywgdmVyc2lvbjogTW9kdWxlVmVyc2lvbikge1xuICByZXR1cm4gYHRlc3QtcmVzdWx0LS0ke21vZHVsZS5uYW1lfS0tJHt0ZXN0TmFtZX0tLSR7dmVyc2lvbi52ZXJzaW9uU3RyaW5nfWBcbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/api.d.ts b/garden-service/build/plugins/kubernetes/api.d.ts new file mode 100644 index 00000000000..8a4de89952d --- /dev/null +++ b/garden-service/build/plugins/kubernetes/api.d.ts @@ -0,0 +1,100 @@ +/// +import { Core_v1Api, Extensions_v1beta1Api, RbacAuthorization_v1Api, Apps_v1Api, Apiextensions_v1beta1Api, V1Secret, Policy_v1beta1Api } from "@kubernetes/client-node"; +import { GardenBaseError } from "../../exceptions"; +import { KubernetesObject } from "./helm"; +import { KubernetesProvider } from "./kubernetes"; +declare const crudMap: { + Secret: { + type: typeof V1Secret; + group: string; + read: string; + create: string; + patch: string; + delete: string; + }; +}; +declare type CrudMapType = typeof crudMap; +export declare class KubernetesError extends GardenBaseError { + type: string; + code?: number; + response?: any; +} +export declare class KubeApi { + provider: KubernetesProvider; + context: string; + apiExtensions: Apiextensions_v1beta1Api; + apps: Apps_v1Api; + core: Core_v1Api; + extensions: Extensions_v1beta1Api; + policy: Policy_v1beta1Api; + rbac: RbacAuthorization_v1Api; + constructor(provider: KubernetesProvider); + readBySpec(namespace: string, spec: KubernetesObject): Promise<{ + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1beta1CustomResourceDefinition; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1StatefulSet; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1ConfigMap; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1Endpoints; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1LimitRange; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1PersistentVolumeClaim; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1Pod; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1PodTemplate; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1ReplicationController; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1ResourceQuota; + } | { + response: import("http").ClientResponse; + body: V1Secret; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1Service; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1ServiceAccount; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1beta1DaemonSet; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").ExtensionsV1beta1Deployment; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1beta1Ingress; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1beta1ReplicaSet; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1beta1PodDisruptionBudget; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1ClusterRoleBinding; + } | { + response: import("http").ClientResponse; + body: import("@kubernetes/client-node/dist/api").V1Role; + }>; + upsert(kind: K, namespace: string, obj: KubernetesObject): Promise; + /** + * Wrapping the API objects to deal with bugs. + */ + private proxyApi; +} +export {}; +//# sourceMappingURL=api.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/api.js b/garden-service/build/plugins/kubernetes/api.js new file mode 100644 index 00000000000..de40a4cc40d --- /dev/null +++ b/garden-service/build/plugins/kubernetes/api.js @@ -0,0 +1,212 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const client_node_1 = require("@kubernetes/client-node"); +const path_1 = require("path"); +const fs_1 = require("fs"); +const js_yaml_1 = require("js-yaml"); +const lodash_1 = require("lodash"); +const exceptions_1 = require("../../exceptions"); +const os_1 = require("os"); +let kubeConfigStr; +let kubeConfig; +const configs = {}; +const apiTypes = { + apiExtensions: client_node_1.Apiextensions_v1beta1Api, + apps: client_node_1.Apps_v1Api, + core: client_node_1.Core_v1Api, + extensions: client_node_1.Extensions_v1beta1Api, + policy: client_node_1.Policy_v1beta1Api, + rbac: client_node_1.RbacAuthorization_v1Api, +}; +const crudMap = { + Secret: { + type: client_node_1.V1Secret, + group: "core", + read: "readNamespacedSecret", + create: "createNamespacedSecret", + patch: "patchNamespacedSecret", + delete: "deleteNamespacedSecret", + }, +}; +class KubernetesError extends exceptions_1.GardenBaseError { + constructor() { + super(...arguments); + this.type = "kubernetes"; + } +} +exports.KubernetesError = KubernetesError; +class KubeApi { + constructor(provider) { + this.provider = provider; + this.context = provider.config.context; + const config = getSecret(this.context); + for (const [name, cls] of Object.entries(apiTypes)) { + const api = new cls(config.getCurrentCluster().server); + this[name] = this.proxyApi(api, config); + } + } + readBySpec(namespace, spec) { + return __awaiter(this, void 0, void 0, function* () { + // this is just awful, sorry. any better ideas? - JE + const name = spec.metadata.name; + switch (spec.kind) { + case "ConfigMap": + return this.core.readNamespacedConfigMap(name, namespace); + case "Endpoints": + return this.core.readNamespacedEndpoints(name, namespace); + case "LimitRange": + return this.core.readNamespacedLimitRange(name, namespace); + case "PersistentVolumeClaim": + return this.core.readNamespacedPersistentVolumeClaim(name, namespace); + case "Pod": + return this.core.readNamespacedPod(name, namespace); + case "PodTemplate": + return this.core.readNamespacedPodTemplate(name, namespace); + case "ReplicationController": + return this.core.readNamespacedReplicationController(name, namespace); + case "ResourceQuota": + return this.core.readNamespacedResourceQuota(name, namespace); + case "Secret": + return this.core.readNamespacedSecret(name, namespace); + case "Service": + return this.core.readNamespacedService(name, namespace); + case "ServiceAccount": + return this.core.readNamespacedServiceAccount(name, namespace); + case "DaemonSet": + return this.extensions.readNamespacedDaemonSet(name, namespace); + case "Deployment": + return this.extensions.readNamespacedDeployment(name, namespace); + case "Ingress": + return this.extensions.readNamespacedIngress(name, namespace); + case "ReplicaSet": + return this.extensions.readNamespacedReplicaSet(name, namespace); + case "StatefulSet": + return this.apps.readNamespacedStatefulSet(name, namespace); + case "ClusterRole": + return this.rbac.readClusterRole(name); + case "ClusterRoleBinding": + return this.rbac.readClusterRoleBinding(name); + case "Role": + return this.rbac.readNamespacedRole(name, namespace); + case "RoleBinding": + return this.rbac.readNamespacedRoleBinding(name, namespace); + case "CustomResourceDefinition": + return this.apiExtensions.readCustomResourceDefinition(name); + case "PodDisruptionBudget": + return this.policy.readNamespacedPodDisruptionBudget(name, namespace); + default: + throw new exceptions_1.ConfigurationError(`Unsupported Kubernetes spec kind: ${spec.kind}`, { + spec, + }); + } + }); + } + upsert(kind, namespace, obj) { + return __awaiter(this, void 0, void 0, function* () { + const api = this[crudMap[kind].group]; + try { + const res = yield api[crudMap[kind].read](obj.metadata.name, namespace); + return res.body; + } + catch (err) { + if (err.code === 404) { + try { + yield api[crudMap[kind].create](namespace, obj); + } + catch (err) { + if (err.code === 409) { + yield api[crudMap[kind].patch](name, namespace, obj); + } + else { + throw err; + } + } + } + else { + throw err; + } + } + return obj; + }); + } + /** + * Wrapping the API objects to deal with bugs. + */ + proxyApi(api, config) { + api.setDefaultAuthentication(config); + return new Proxy(api, { + get: (target, name, receiver) => { + if (!(name in Object.getPrototypeOf(target))) { // assume methods live on the prototype + return Reflect.get(target, name, receiver); + } + return function (...args) { + const defaultHeaders = target["defaultHeaders"]; + if (name.startsWith("patch")) { + // patch the patch bug... (https://github.com/kubernetes-client/javascript/issues/19) + target["defaultHeaders"] = Object.assign({}, defaultHeaders, { "content-type": "application/strategic-merge-patch+json" }); + } + const output = target[name](...args); + target["defaultHeaders"] = defaultHeaders; + if (typeof output.then === "function") { + // the API errors are not properly formed Error objects + return output.catch(wrapError); + } + else { + return output; + } + }; + }, + }); + } +} +exports.KubeApi = KubeApi; +function getSecret(context) { + if (!kubeConfigStr) { + const kubeConfigPath = process.env.KUBECONFIG || path_1.join(os_1.homedir(), ".kube", "config"); + kubeConfigStr = fs_1.readFileSync(kubeConfigPath).toString(); + kubeConfig = js_yaml_1.safeLoad(kubeConfigStr); + } + if (!configs[context]) { + const kc = new client_node_1.KubeConfig(); + kc.loadFromString(kubeConfigStr); + kc.setCurrentContext(context); + // FIXME: need to patch a bug in the library here (https://github.com/kubernetes-client/javascript/pull/54) + for (const [a, b] of lodash_1.zip(kubeConfig["clusters"] || [], kc.clusters)) { + if (a && a["cluster"]["insecure-skip-tls-verify"] === true) { + b.skipTLSVerify = true; + } + } + configs[context] = kc; + } + return configs[context]; +} +function wrapError(err) { + if (!err.message) { + const wrapped = new KubernetesError(`Got error from Kubernetes API - ${err.body.message}`, { + body: err.body, + request: lodash_1.omitBy(err.response.request, (v, k) => lodash_1.isObject(v) || k[0] === "_"), + }); + wrapped.code = err.response.statusCode; + throw wrapped; + } + else { + throw err; + } +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9hcGkudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILHlEQVNnQztBQUNoQywrQkFBMkI7QUFDM0IsMkJBQWlDO0FBQ2pDLHFDQUFrQztBQUNsQyxtQ0FBOEM7QUFDOUMsaURBQXNFO0FBRXRFLDJCQUE0QjtBQUc1QixJQUFJLGFBQXFCLENBQUE7QUFDekIsSUFBSSxVQUFlLENBQUE7QUFFbkIsTUFBTSxPQUFPLEdBQXNDLEVBQUUsQ0FBQTtBQVlyRCxNQUFNLFFBQVEsR0FBOEM7SUFDMUQsYUFBYSxFQUFFLHNDQUF3QjtJQUN2QyxJQUFJLEVBQUUsd0JBQVU7SUFDaEIsSUFBSSxFQUFFLHdCQUFVO0lBQ2hCLFVBQVUsRUFBRSxtQ0FBcUI7SUFDakMsTUFBTSxFQUFFLCtCQUFpQjtJQUN6QixJQUFJLEVBQUUscUNBQXVCO0NBQzlCLENBQUE7QUFFRCxNQUFNLE9BQU8sR0FBRztJQUNkLE1BQU0sRUFBRTtRQUNOLElBQUksRUFBRSxzQkFBUTtRQUNkLEtBQUssRUFBRSxNQUFNO1FBQ2IsSUFBSSxFQUFFLHNCQUFzQjtRQUM1QixNQUFNLEVBQUUsd0JBQXdCO1FBQ2hDLEtBQUssRUFBRSx1QkFBdUI7UUFDOUIsTUFBTSxFQUFFLHdCQUF3QjtLQUNqQztDQUNGLENBQUE7QUFJRCxNQUFhLGVBQWdCLFNBQVEsNEJBQWU7SUFBcEQ7O1FBQ0UsU0FBSSxHQUFHLFlBQVksQ0FBQTtJQUlyQixDQUFDO0NBQUE7QUFMRCwwQ0FLQztBQUVELE1BQWEsT0FBTztJQVVsQixZQUFtQixRQUE0QjtRQUE1QixhQUFRLEdBQVIsUUFBUSxDQUFvQjtRQUM3QyxJQUFJLENBQUMsT0FBTyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFBO1FBQ3RDLE1BQU0sTUFBTSxHQUFHLFNBQVMsQ0FBQyxJQUFJLENBQUMsT0FBTyxDQUFDLENBQUE7UUFFdEMsS0FBSyxNQUFNLENBQUMsSUFB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SUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLDBCQUEwQixDQUFDLEtBQUssSUFBSSxFQUFFO2dCQUNwRCxDQUFFLENBQUMsYUFBYSxHQUFHLElBQUksQ0FBQTthQUM5QjtTQUNGO1FBRUQsT0FBTyxDQUFDLE9BQU8sQ0FBQyxHQUFHLEVBQUUsQ0FBQTtLQUN0QjtJQUVELE9BQU8sT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO0FBQ3pCLENBQUM7QUFFRCxTQUFTLFNBQVMsQ0FBQyxHQUFHO0lBQ3BCLElBQUksQ0FBQyxHQUFHLENBQUMsT0FBTyxFQUFFO1FBQ2hCLE1BQU0sT0FBTyxHQUFHLElBQUksZUFBZSxDQUFDLG1DQUFtQyxHQUFHLENBQUMsSUFBSSxDQUFDLE9BQU8sRUFBRSxFQUFFO1lBQ3pGLElBQUksRUFBRSxHQUFHLENBQUMsSUFBSTtZQUNkLE9BQU8sRUFBRSxlQUFNLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxpQkFBUSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsQ0FBQyxDQUFDLENBQUMsS0FBSyxHQUFHLENBQUM7U0FDN0UsQ0FBQyxDQUFBO1FBQ0YsT0FBTyxDQUFDLElBQUksR0FBRyxHQUFHLENBQUMsUUFBUSxDQUFDLFVBQVUsQ0FBQTtRQUN0QyxNQUFNLE9BQU8sQ0FBQTtLQUNkO1NBQU07UUFDTCxNQUFNLEdBQUcsQ0FBQTtLQUNWO0FBQ0gsQ0FBQyIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvYXBpLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7XG4gIEt1YmVDb25maWcsXG4gIENvcmVfdjFBcGksXG4gIEV4dGVuc2lvbnNfdjFiZXRhMUFwaSxcbiAgUmJhY0F1dGhvcml6YXRpb25fdjFBcGksXG4gIEFwcHNfdjFBcGksXG4gIEFwaWV4dGVuc2lvbnNfdjFiZXRhMUFwaSxcbiAgVjFTZWNyZXQsXG4gIFBvbGljeV92MWJldGExQXBpLFxufSBmcm9tIFwiQGt1YmVybmV0ZXMvY2xpZW50LW5vZGVcIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IHJlYWRGaWxlU3luYyB9IGZyb20gXCJmc1wiXG5pbXBvcnQgeyBzYWZlTG9hZCB9IGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCB7IHppcCwgb21pdEJ5LCBpc09iamVjdCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgR2FyZGVuQmFzZUVycm9yLCBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBLdWJlcm5ldGVzT2JqZWN0IH0gZnJvbSBcIi4vaGVsbVwiXG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSBcIm9zXCJcbmltcG9ydCB7IEt1YmVybmV0ZXNQcm92aWRlciB9IGZyb20gXCIuL2t1YmVybmV0ZXNcIlxuXG5sZXQga3ViZUNvbmZpZ1N0cjogc3RyaW5nXG5sZXQga3ViZUNvbmZpZzogYW55XG5cbmNvbnN0IGNvbmZpZ3M6IHsgW2NvbnRleHQ6IHN0cmluZ106IEt1YmVDb25maWcgfSA9IHt9XG5cbi8vIE5PVEU6IGJlIHdhcm5lZCwgdGhlIEFQSSBvZiB0aGUgY2xpZW50IGxpYnJhcnkgaXMgdmVyeSBsaWtlbHkgdG8gY2hhbmdlXG5cbnR5cGUgSzhzQXBpID0gQ29yZV92MUFwaVxuICB8IEV4dGVuc2lvbnNfdjFiZXRhMUFwaVxuICB8IFJiYWNBdXRob3JpemF0aW9uX3YxQXBpXG4gIHwgQXBwc192MUFwaVxuICB8IEFwaWV4dGVuc2lvbnNfdjFiZXRhMUFwaVxuICB8IFBvbGljeV92MWJldGExQXBpXG50eXBlIEs4c0FwaUNvbnN0cnVjdG9yPFQgZXh0ZW5kcyBLOHNBcGk+ID0gbmV3IChiYXNlUGF0aD86IHN0cmluZykgPT4gVFxuXG5jb25zdCBhcGlUeXBlczogeyBba2V5OiBzdHJpbmddOiBLOHNBcGlDb25zdHJ1Y3Rvcjxhbnk+IH0gPSB7XG4gIGFwaUV4dGVuc2lvbnM6IEFwaWV4dGVuc2lvbnNfdjFiZXRhMUFwaSxcbiAgYXBwczogQXBwc192MUFwaSxcbiAgY29yZTogQ29yZV92MUFwaSxcbiAgZXh0ZW5zaW9uczogRXh0ZW5zaW9uc192MWJldGExQXBpLFxuICBwb2xpY3k6IFBvbGljeV92MWJldGExQXBpLFxuICByYmFjOiBSYmFjQXV0aG9yaXphdGlvbl92MUFwaSxcbn1cblxuY29uc3QgY3J1ZE1hcCA9IHtcbiAgU2VjcmV0OiB7XG4gICAgdHlwZTogVjFTZWNyZXQsXG4gICAgZ3JvdXA6IFwiY29yZVwiLFxuICAgIHJlYWQ6IFwicmVhZE5hbWVzcGFjZWRTZWNyZXRcIixcbiAgICBjcmVhdGU6IFwiY3JlYXRlTmFtZXNwYWNlZFNlY3JldFwiLFxuICAgIHBhdGNoOiBcInBhdGNoTmFtZXNwYWNlZFNlY3JldFwiLFxuICAgIGRlbGV0ZTogXCJkZWxldGVOYW1lc3BhY2VkU2VjcmV0XCIsXG4gIH0sXG59XG5cbnR5cGUgQ3J1ZE1hcFR5cGUgPSB0eXBlb2YgY3J1ZE1hcFxuXG5leHBvcnQgY2xhc3MgS3ViZXJuZXRlc0Vycm9yIGV4dGVuZHMgR2FyZGVuQmFzZUVycm9yIHtcbiAgdHlwZSA9IFwia3ViZXJuZXRlc1wiXG5cbiAgY29kZT86IG51bWJlclxuICByZXNwb25zZT86IGFueVxufVxuXG5leHBvcnQgY2xhc3MgS3ViZUFwaSB7XG4gIHB1YmxpYyBjb250ZXh0OiBzdHJpbmdcblxuICBwdWJsaWMgYXBpRXh0ZW5zaW9uczogQXBpZXh0ZW5zaW9uc192MWJldGExQXBpXG4gIHB1YmxpYyBhcHBzOiBBcHBzX3YxQXBpXG4gIHB1YmxpYyBjb3JlOiBDb3JlX3YxQXBpXG4gIHB1YmxpYyBleHRlbnNpb25zOiBFeHRlbnNpb25zX3YxYmV0YTFBcGlcbiAgcHVibGljIHBvbGljeTogUG9saWN5X3YxYmV0YTFBcGlcbiAgcHVibGljIHJiYWM6IFJiYWNBdXRob3JpemF0aW9uX3YxQXBpXG5cbiAgY29uc3RydWN0b3IocHVibGljIHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIpIHtcbiAgICB0aGlzLmNvbnRleHQgPSBwcm92aWRlci5jb25maWcuY29udGV4dFxuICAgIGNvbnN0IGNvbmZpZyA9IGdldFNlY3JldCh0aGlzLmNvbnRleHQpXG5cbiAgICBmb3IgKGNvbnN0IFtuYW1lLCBjbHNdIG9mIE9iamVjdC5lbnRyaWVzKGFwaVR5cGVzKSkge1xuICAgICAgY29uc3QgYXBpID0gbmV3IGNscyhjb25maWcuZ2V0Q3VycmVudENsdXN0ZXIoKS5zZXJ2ZXIpXG4gICAgICB0aGlzW25hbWVdID0gdGhpcy5wcm94eUFwaShhcGksIGNvbmZpZylcbiAgICB9XG4gIH1cblxuICBhc3luYyByZWFkQnlTcGVjKG5hbWVzcGFjZTogc3RyaW5nLCBzcGVjOiBLdWJlcm5ldGVzT2JqZWN0KSB7XG4gICAgLy8gdGhpcyBpcyBqdXN0IGF3ZnVsLCBzb3JyeS4gYW55IGJldHRlciBpZGVhcz8gLSBKRVxuICAgIGNvbnN0IG5hbWUgPSBzcGVjLm1ldGFkYXRhLm5hbWVcblxuICAgIHN3aXRjaCAoc3BlYy5raW5kKSB7XG4gICAgICBjYXNlIFwiQ29uZmlnTWFwXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRDb25maWdNYXAobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIkVuZHBvaW50c1wiOlxuICAgICAgICByZXR1cm4gdGhpcy5jb3JlLnJlYWROYW1lc3BhY2VkRW5kcG9pbnRzKG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJMaW1pdFJhbmdlXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRMaW1pdFJhbmdlKG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJQZXJzaXN0ZW50Vm9sdW1lQ2xhaW1cIjpcbiAgICAgICAgcmV0dXJuIHRoaXMuY29yZS5yZWFkTmFtZXNwYWNlZFBlcnNpc3RlbnRWb2x1bWVDbGFpbShuYW1lLCBuYW1lc3BhY2UpXG4gICAgICBjYXNlIFwiUG9kXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRQb2QobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIlBvZFRlbXBsYXRlXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRQb2RUZW1wbGF0ZShuYW1lLCBuYW1lc3BhY2UpXG4gICAgICBjYXNlIFwiUmVwbGljYXRpb25Db250cm9sbGVyXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRSZXBsaWNhdGlvbkNvbnRyb2xsZXIobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIlJlc291cmNlUXVvdGFcIjpcbiAgICAgICAgcmV0dXJuIHRoaXMuY29yZS5yZWFkTmFtZXNwYWNlZFJlc291cmNlUXVvdGEobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIlNlY3JldFwiOlxuICAgICAgICByZXR1cm4gdGhpcy5jb3JlLnJlYWROYW1lc3BhY2VkU2VjcmV0KG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJTZXJ2aWNlXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmNvcmUucmVhZE5hbWVzcGFjZWRTZXJ2aWNlKG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJTZXJ2aWNlQWNjb3VudFwiOlxuICAgICAgICByZXR1cm4gdGhpcy5jb3JlLnJlYWROYW1lc3BhY2VkU2VydmljZUFjY291bnQobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIkRhZW1vblNldFwiOlxuICAgICAgICByZXR1cm4gdGhpcy5leHRlbnNpb25zLnJlYWROYW1lc3BhY2VkRGFlbW9uU2V0KG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJEZXBsb3ltZW50XCI6XG4gICAgICAgIHJldHVybiB0aGlzLmV4dGVuc2lvbnMucmVhZE5hbWVzcGFjZWREZXBsb3ltZW50KG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJJbmdyZXNzXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmV4dGVuc2lvbnMucmVhZE5hbWVzcGFjZWRJbmdyZXNzKG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJSZXBsaWNhU2V0XCI6XG4gICAgICAgIHJldHVybiB0aGlzLmV4dGVuc2lvbnMucmVhZE5hbWVzcGFjZWRSZXBsaWNhU2V0KG5hbWUsIG5hbWVzcGFjZSlcbiAgICAgIGNhc2UgXCJTdGF0ZWZ1bFNldFwiOlxuICAgICAgICByZXR1cm4gdGhpcy5hcHBzLnJlYWROYW1lc3BhY2VkU3RhdGVmdWxTZXQobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIkNsdXN0ZXJSb2xlXCI6XG4gICAgICAgIHJldHVybiB0aGlzLnJiYWMucmVhZENsdXN0ZXJSb2xlKG5hbWUpXG4gICAgICBjYXNlIFwiQ2x1c3RlclJvbGVCaW5kaW5nXCI6XG4gICAgICAgIHJldHVybiB0aGlzLnJiYWMucmVhZENsdXN0ZXJSb2xlQmluZGluZyhuYW1lKVxuICAgICAgY2FzZSBcIlJvbGVcIjpcbiAgICAgICAgcmV0dXJuIHRoaXMucmJhYy5yZWFkTmFtZXNwYWNlZFJvbGUobmFtZSwgbmFtZXNwYWNlKVxuICAgICAgY2FzZSBcIlJvbGVCaW5kaW5nXCI6XG4gICAgICAgIHJldHVybiB0aGlzLnJiYWMucmVhZE5hbWVzcGFjZWRSb2xlQmluZGluZyhuYW1lLCBuYW1lc3BhY2UpXG4gICAgICBjYXNlIFwiQ3VzdG9tUmVzb3VyY2VEZWZpbml0aW9uXCI6XG4gICAgICAgIHJldHVybiB0aGlzLmFwaUV4dGVuc2lvbnMucmVhZEN1c3RvbVJlc291cmNlRGVmaW5pdGlvbihuYW1lKVxuICAgICAgY2FzZSBcIlBvZERpc3J1cHRpb25CdWRnZXRcIjpcbiAgICAgICAgcmV0dXJuIHRoaXMucG9saWN5LnJlYWROYW1lc3BhY2VkUG9kRGlzcnVwdGlvbkJ1ZGdldChuYW1lLCBuYW1lc3BhY2UpXG4gICAgICBkZWZhdWx0OlxuICAgICAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKGBVbnN1cHBvcnRlZCBLdWJlcm5ldGVzIHNwZWMga2luZDogJHtzcGVjLmtpbmR9YCwge1xuICAgICAgICAgIHNwZWMsXG4gICAgICAgIH0pXG4gICAgfVxuICB9XG5cbiAgYXN5bmMgdXBzZXJ0PEsgZXh0ZW5kcyBrZXlvZiBDcnVkTWFwVHlwZT4oXG4gICAga2luZDogSywgbmFtZXNwYWNlOiBzdHJpbmcsIG9iajogS3ViZXJuZXRlc09iamVjdCxcbiAgKTogUHJvbWlzZTxLdWJlcm5ldGVzT2JqZWN0PiB7XG4gICAgY29uc3QgYXBpID0gdGhpc1tjcnVkTWFwW2tpbmRdLmdyb3VwXVxuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFwaVtjcnVkTWFwW2tpbmRdLnJlYWRdKG9iai5tZXRhZGF0YS5uYW1lLCBuYW1lc3BhY2UpXG4gICAgICByZXR1cm4gcmVzLmJvZHlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIuY29kZSA9PT0gNDA0KSB7XG4gICAgICAgIHRyeSB7XG4gICAgICAgICAgYXdhaXQgYXBpW2NydWRNYXBba2luZF0uY3JlYXRlXShuYW1lc3BhY2UsIDxhbnk+b2JqKVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICBpZiAoZXJyLmNvZGUgPT09IDQwOSkge1xuICAgICAgICAgICAgYXdhaXQgYXBpW2NydWRNYXBba2luZF0ucGF0Y2hdKG5hbWUsIG5hbWVzcGFjZSwgb2JqKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICB0aHJvdyBlcnJcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVyclxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiBvYmpcbiAgfVxuXG4gIC8qKlxuICAgKiBXcmFwcGluZyB0aGUgQVBJIG9iamVjdHMgdG8gZGVhbCB3aXRoIGJ1Z3MuXG4gICAqL1xuICBwcml2YXRlIHByb3h5QXBpPFQgZXh0ZW5kcyBLOHNBcGk+KGFwaTogVCwgY29uZmlnKTogVCB7XG4gICAgYXBpLnNldERlZmF1bHRBdXRoZW50aWNhdGlvbihjb25maWcpXG5cbiAgICByZXR1cm4gbmV3IFByb3h5KGFwaSwge1xuICAgICAgZ2V0OiAodGFyZ2V0OiBULCBuYW1lOiBzdHJpbmcsIHJlY2VpdmVyKSA9PiB7XG4gICAgICAgIGlmICghKG5hbWUgaW4gT2JqZWN0LmdldFByb3RvdHlwZU9mKHRhcmdldCkpKSB7IC8vIGFzc3VtZSBtZXRob2RzIGxpdmUgb24gdGhlIHByb3RvdHlwZVxuICAgICAgICAgIHJldHVybiBSZWZsZWN0LmdldCh0YXJnZXQsIG5hbWUsIHJlY2VpdmVyKVxuICAgICAgICB9XG5cbiAgICAgICAgcmV0dXJuIGZ1bmN0aW9uKC4uLmFyZ3MpIHtcbiAgICAgICAgICBjb25zdCBkZWZhdWx0SGVhZGVycyA9IHRhcmdldFtcImRlZmF1bHRIZWFkZXJzXCJdXG5cbiAgICAgICAgICBpZiAobmFtZS5zdGFydHNXaXRoKFwicGF0Y2hcIikpIHtcbiAgICAgICAgICAgIC8vIHBhdGNoIHRoZSBwYXRjaCBidWcuLi4gKGh0dHBzOi8vZ2l0aHViLmNvbS9rdWJlcm5ldGVzLWNsaWVudC9qYXZhc2NyaXB0L2lzc3Vlcy8xOSlcbiAgICAgICAgICAgIHRhcmdldFtcImRlZmF1bHRIZWFkZXJzXCJdID0geyAuLi5kZWZhdWx0SGVhZGVycywgXCJjb250ZW50LXR5cGVcIjogXCJhcHBsaWNhdGlvbi9zdHJhdGVnaWMtbWVyZ2UtcGF0Y2granNvblwiIH1cbiAgICAgICAgICB9XG5cbiAgICAgICAgICBjb25zdCBvdXRwdXQgPSB0YXJnZXRbbmFtZV0oLi4uYXJncylcbiAgICAgICAgICB0YXJnZXRbXCJkZWZhdWx0SGVhZGVyc1wiXSA9IGRlZmF1bHRIZWFkZXJzXG5cbiAgICAgICAgICBpZiAodHlwZW9mIG91dHB1dC50aGVuID09PSBcImZ1bmN0aW9uXCIpIHtcbiAgICAgICAgICAgIC8vIHRoZSBBUEkgZXJyb3JzIGFyZSBub3QgcHJvcGVybHkgZm9ybWVkIEVycm9yIG9iamVjdHNcbiAgICAgICAgICAgIHJldHVybiBvdXRwdXQuY2F0Y2god3JhcEVycm9yKVxuICAgICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgICByZXR1cm4gb3V0cHV0XG4gICAgICAgICAgfVxuICAgICAgICB9XG4gICAgICB9LFxuICAgIH0pXG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0U2VjcmV0KGNvbnRleHQ6IHN0cmluZyk6IEt1YmVDb25maWcge1xuICBpZiAoIWt1YmVDb25maWdTdHIpIHtcbiAgICBjb25zdCBrdWJlQ29uZmlnUGF0aCA9IHByb2Nlc3MuZW52LktVQkVDT05GSUcgfHwgam9pbihob21lZGlyKCksIFwiLmt1YmVcIiwgXCJjb25maWdcIilcbiAgICBrdWJlQ29uZmlnU3RyID0gcmVhZEZpbGVTeW5jKGt1YmVDb25maWdQYXRoKS50b1N0cmluZygpXG4gICAga3ViZUNvbmZpZyA9IHNhZmVMb2FkKGt1YmVDb25maWdTdHIpXG4gIH1cblxuICBpZiAoIWNvbmZpZ3NbY29udGV4dF0pIHtcbiAgICBjb25zdCBrYyA9IG5ldyBLdWJlQ29uZmlnKClcblxuICAgIGtjLmxvYWRGcm9tU3RyaW5nKGt1YmVDb25maWdTdHIpXG4gICAga2Muc2V0Q3VycmVudENvbnRleHQoY29udGV4dClcblxuICAgIC8vIEZJWE1FOiBuZWVkIHRvIHBhdGNoIGEgYnVnIGluIHRoZSBsaWJyYXJ5IGhlcmUgKGh0dHBzOi8vZ2l0aHViLmNvbS9rdWJlcm5ldGVzLWNsaWVudC9qYXZhc2NyaXB0L3B1bGwvNTQpXG4gICAgZm9yIChjb25zdCBbYSwgYl0gb2YgemlwKGt1YmVDb25maWdbXCJjbHVzdGVyc1wiXSB8fCBbXSwga2MuY2x1c3RlcnMpKSB7XG4gICAgICBpZiAoYSAmJiBhW1wiY2x1c3RlclwiXVtcImluc2VjdXJlLXNraXAtdGxzLXZlcmlmeVwiXSA9PT0gdHJ1ZSkge1xuICAgICAgICAoPGFueT5iKS5za2lwVExTVmVyaWZ5ID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cblxuICAgIGNvbmZpZ3NbY29udGV4dF0gPSBrY1xuICB9XG5cbiAgcmV0dXJuIGNvbmZpZ3NbY29udGV4dF1cbn1cblxuZnVuY3Rpb24gd3JhcEVycm9yKGVycikge1xuICBpZiAoIWVyci5tZXNzYWdlKSB7XG4gICAgY29uc3Qgd3JhcHBlZCA9IG5ldyBLdWJlcm5ldGVzRXJyb3IoYEdvdCBlcnJvciBmcm9tIEt1YmVybmV0ZXMgQVBJIC0gJHtlcnIuYm9keS5tZXNzYWdlfWAsIHtcbiAgICAgIGJvZHk6IGVyci5ib2R5LFxuICAgICAgcmVxdWVzdDogb21pdEJ5KGVyci5yZXNwb25zZS5yZXF1ZXN0LCAodiwgaykgPT4gaXNPYmplY3QodikgfHwga1swXSA9PT0gXCJfXCIpLFxuICAgIH0pXG4gICAgd3JhcHBlZC5jb2RlID0gZXJyLnJlc3BvbnNlLnN0YXR1c0NvZGVcbiAgICB0aHJvdyB3cmFwcGVkXG4gIH0gZWxzZSB7XG4gICAgdGhyb3cgZXJyXG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/deployment.d.ts b/garden-service/build/plugins/kubernetes/deployment.d.ts new file mode 100644 index 00000000000..94d4fbcd67a --- /dev/null +++ b/garden-service/build/plugins/kubernetes/deployment.d.ts @@ -0,0 +1,34 @@ +import { DeployServiceParams, GetServiceStatusParams, PushModuleParams } from "../../types/plugin/params"; +import { ContainerModule, ContainerService } from "../container"; +import { RuntimeContext, ServiceStatus } from "../../types/service"; +import { KubernetesObject } from "./helm"; +import { PluginContext } from "../../plugin-context"; +import { KubernetesProvider } from "./kubernetes"; +export declare const DEFAULT_CPU_REQUEST = "10m"; +export declare const DEFAULT_CPU_LIMIT = "500m"; +export declare const DEFAULT_MEMORY_REQUEST = "128Mi"; +export declare const DEFAULT_MEMORY_LIMIT = "512Mi"; +export declare function getContainerServiceStatus({ ctx, module, service, runtimeContext }: GetServiceStatusParams): Promise; +export declare function deployContainerService(params: DeployServiceParams): Promise; +export declare function createContainerObjects(ctx: PluginContext, service: ContainerService, runtimeContext: RuntimeContext): Promise; +export declare function createDeployment(provider: KubernetesProvider, service: ContainerService, runtimeContext: RuntimeContext, namespace: string): Promise; +export declare function deleteContainerService({ namespace, provider, serviceName, logEntry }: { + namespace: any; + provider: any; + serviceName: any; + logEntry: any; +}): Promise; +export declare function deleteContainerDeployment({ namespace, provider, serviceName, logEntry }: { + namespace: any; + provider: any; + serviceName: any; + logEntry: any; +}): Promise; +export declare function pushModule({ ctx, module, logEntry }: PushModuleParams): Promise<{ + pushed: boolean; + message?: undefined; +} | { + pushed: boolean; + message: string; +}>; +//# sourceMappingURL=deployment.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/deployment.js b/garden-service/build/plugins/kubernetes/deployment.js new file mode 100644 index 00000000000..76dc8727fb5 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/deployment.js @@ -0,0 +1,341 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const container_1 = require("../container"); +const lodash_1 = require("lodash"); +const ingress_1 = require("./ingress"); +const service_1 = require("./service"); +const status_1 = require("./status"); +const kubectl_1 = require("./kubectl"); +const namespace_1 = require("./namespace"); +const constants_1 = require("../../constants"); +const api_1 = require("./api"); +exports.DEFAULT_CPU_REQUEST = "10m"; +exports.DEFAULT_CPU_LIMIT = "500m"; +exports.DEFAULT_MEMORY_REQUEST = "128Mi"; +exports.DEFAULT_MEMORY_LIMIT = "512Mi"; +function getContainerServiceStatus({ ctx, module, service, runtimeContext }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: hash and compare all the configuration files (otherwise internal changes don't get deployed) + const version = module.version; + const objects = yield createContainerObjects(ctx, service, runtimeContext); + const matched = yield status_1.compareDeployedObjects(ctx, objects); + const api = new api_1.KubeApi(ctx.provider); + const ingresses = yield ingress_1.getIngresses(service, api); + return { + ingresses, + state: matched ? "ready" : "outdated", + version: matched ? version.versionString : undefined, + }; + }); +} +exports.getContainerServiceStatus = getContainerServiceStatus; +function deployContainerService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, service, runtimeContext, force, logEntry } = params; + const provider = ctx.provider; + const namespace = yield namespace_1.getAppNamespace(ctx, provider); + const objects = yield createContainerObjects(ctx, service, runtimeContext); + // TODO: use Helm instead of kubectl apply + const pruneSelector = "service=" + service.name; + yield kubectl_1.applyMany(provider.config.context, objects, { force, namespace, pruneSelector }); + yield status_1.waitForObjects({ ctx, provider, service, objects, logEntry }); + return getContainerServiceStatus(params); + }); +} +exports.deployContainerService = deployContainerService; +function createContainerObjects(ctx, service, runtimeContext) { + return __awaiter(this, void 0, void 0, function* () { + const version = service.module.version; + const provider = ctx.provider; + const namespace = yield namespace_1.getAppNamespace(ctx, provider); + const deployment = yield createDeployment(provider, service, runtimeContext, namespace); + const kubeservices = yield service_1.createServices(service, namespace); + const api = new api_1.KubeApi(provider); + const ingresses = yield ingress_1.createIngresses(api, namespace, service); + const objects = [deployment, ...kubeservices, ...ingresses]; + return objects.map(obj => { + lodash_1.set(obj, ["metadata", "annotations", "garden.io/generated"], "true"); + lodash_1.set(obj, ["metadata", "annotations", constants_1.GARDEN_ANNOTATION_KEYS_VERSION], version.versionString); + lodash_1.set(obj, ["metadata", "labels", "module"], service.module.name); + lodash_1.set(obj, ["metadata", "labels", "service"], service.name); + return obj; + }); + }); +} +exports.createContainerObjects = createContainerObjects; +function createDeployment(provider, service, runtimeContext, namespace) { + return __awaiter(this, void 0, void 0, function* () { + const spec = service.spec; + // TODO: support specifying replica count + const configuredReplicas = 1; // service.spec.count[env.name] || 1 + const labels = { + module: service.module.name, + service: service.name, + }; + // TODO: moar type-safety + const deployment = { + kind: "Deployment", + apiVersion: "extensions/v1beta1", + metadata: { + name: service.name, + annotations: { + // we can use this to avoid overriding the replica count if it has been manually scaled + "garden.io/configured.replicas": configuredReplicas.toString(), + }, + namespace, + labels, + }, + spec: { + selector: { + matchLabels: { + service: service.name, + }, + }, + template: { + metadata: { + labels, + }, + spec: { + // TODO: set this for non-system pods + // automountServiceAccountToken: false, // this prevents the pod from accessing the kubernetes API + containers: [], + // TODO: make restartPolicy configurable + restartPolicy: "Always", + terminationGracePeriodSeconds: 10, + dnsPolicy: "ClusterFirst", + }, + }, + }, + }; + const envVars = Object.assign({}, runtimeContext.envVars, service.spec.env); + const env = lodash_1.toPairs(envVars).map(([name, value]) => ({ name, value: value + "" })); + // expose some metadata to the container + env.push({ + name: "POD_NAME", + valueFrom: { fieldRef: { fieldPath: "metadata.name" } }, + }); + env.push({ + name: "POD_NAMESPACE", + valueFrom: { fieldRef: { fieldPath: "metadata.namespace" } }, + }); + env.push({ + name: "POD_IP", + valueFrom: { fieldRef: { fieldPath: "status.podIP" } }, + }); + const registryConfig = provider.name === "local-kubernetes" ? undefined : provider.config.deploymentRegistry; + const image = yield container_1.helpers.getDeploymentImageId(service.module, registryConfig); + const container = { + name: service.name, + image, + env, + ports: [], + // TODO: make these configurable + resources: { + requests: { + cpu: exports.DEFAULT_CPU_REQUEST, + memory: exports.DEFAULT_MEMORY_REQUEST, + }, + limits: { + cpu: exports.DEFAULT_CPU_LIMIT, + memory: exports.DEFAULT_MEMORY_LIMIT, + }, + }, + imagePullPolicy: "IfNotPresent", + }; + if (service.spec.command && service.spec.command.length > 0) { + container.args = service.spec.command; + } + // if (config.entrypoint) { + // container.command = [config.entrypoint] + // } + if (spec.healthCheck) { + container.readinessProbe = { + initialDelaySeconds: 10, + periodSeconds: 5, + timeoutSeconds: 3, + successThreshold: 2, + failureThreshold: 5, + }; + container.livenessProbe = { + initialDelaySeconds: 15, + periodSeconds: 5, + timeoutSeconds: 3, + successThreshold: 1, + failureThreshold: 3, + }; + const portsByName = lodash_1.keyBy(spec.ports, "name"); + if (spec.healthCheck.httpGet) { + const httpGet = lodash_1.extend({}, spec.healthCheck.httpGet); + httpGet.port = portsByName[httpGet.port].containerPort; + container.readinessProbe.httpGet = httpGet; + container.livenessProbe.httpGet = httpGet; + } + else if (spec.healthCheck.command) { + container.readinessProbe.exec = { command: spec.healthCheck.command.map(s => s.toString()) }; + container.livenessProbe.exec = container.readinessProbe.exec; + } + else if (spec.healthCheck.tcpPort) { + container.readinessProbe.tcpSocket = { + port: portsByName[spec.healthCheck.tcpPort].containerPort, + }; + container.livenessProbe.tcpSocket = container.readinessProbe.tcpSocket; + } + else { + throw new Error("Must specify type of health check when configuring health check."); + } + } + // if (service.privileged) { + // container.securityContext = { + // privileged: true, + // } + // } + if (spec.volumes && spec.volumes.length) { + const volumes = []; + const volumeMounts = []; + for (const volume of spec.volumes) { + const volumeName = volume.name; + const volumeType = !!volume.hostPath ? "hostPath" : "emptyDir"; + if (!volumeName) { + throw new Error("Must specify volume name"); + } + if (volumeType === "emptyDir") { + volumes.push({ + name: volumeName, + emptyDir: {}, + }); + volumeMounts.push({ + name: volumeName, + mountPath: volume.containerPath, + }); + } + else if (volumeType === "hostPath") { + volumes.push({ + name: volumeName, + hostPath: { + path: volume.hostPath, + }, + }); + volumeMounts.push({ + name: volumeName, + mountPath: volume.containerPath || volume.hostPath, + }); + } + else { + throw new Error("Unsupported volume type: " + volumeType); + } + } + deployment.spec.template.spec.volumes = volumes; + container.volumeMounts = volumeMounts; + } + const ports = spec.ports; + for (const port of ports) { + container.ports.push({ + protocol: port.protocol, + containerPort: port.containerPort, + }); + } + if (spec.daemon) { + // this runs a pod on every node + deployment.kind = "DaemonSet"; + deployment.spec.updateStrategy = { + type: "RollingUpdate", + }; + for (const port of ports.filter(p => p.hostPort)) { + // For daemons we can expose host ports directly on the Pod, as opposed to only via the Service resource. + // This allows us to choose any port. + // TODO: validate that conflicting ports are not defined. + container.ports.push({ + protocol: port.protocol, + containerPort: port.containerPort, + hostPort: port.hostPort, + }); + } + } + else { + deployment.spec.replicas = configuredReplicas; + deployment.spec.strategy = { + type: "RollingUpdate", + rollingUpdate: { + maxUnavailable: "34%", + maxSurge: "34%", + }, + }; + deployment.spec.revisionHistoryLimit = 3; + } + if (provider.config.imagePullSecrets.length > 0) { + // add any configured imagePullSecrets + deployment.spec.template.spec.imagePullSecrets = provider.config.imagePullSecrets.map(s => ({ name: s.name })); + } + deployment.spec.template.spec.containers = [container]; + return deployment; + }); +} +exports.createDeployment = createDeployment; +function deleteContainerService({ namespace, provider, serviceName, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const context = provider.config.context; + yield deleteContainerDeployment({ namespace, provider, serviceName, logEntry }); + yield kubectl_1.deleteObjectsByLabel({ + context, + namespace, + labelKey: "service", + labelValue: serviceName, + objectTypes: ["deployment", "service", "ingress"], + includeUninitialized: false, + }); + }); +} +exports.deleteContainerService = deleteContainerService; +function deleteContainerDeployment({ namespace, provider, serviceName, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + let found = true; + const api = new api_1.KubeApi(provider); + try { + yield api.extensions.deleteNamespacedDeployment(serviceName, namespace, {}); + } + catch (err) { + if (err.code === 404) { + found = false; + } + else { + throw err; + } + } + if (logEntry) { + found ? logEntry.setSuccess("Service deleted") : logEntry.setWarn("Service not deployed"); + } + }); +} +exports.deleteContainerDeployment = deleteContainerDeployment; +function pushModule({ ctx, module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + if (!(yield container_1.helpers.hasDockerfile(module))) { + logEntry && logEntry.setState({ msg: `Nothing to push` }); + return { pushed: false }; + } + const localId = yield container_1.helpers.getLocalImageId(module); + const remoteId = yield container_1.helpers.getDeploymentImageId(module, ctx.provider.config.deploymentRegistry); + logEntry && logEntry.setState({ msg: `Pushing image ${remoteId}...` }); + yield container_1.helpers.dockerCli(module, `tag ${localId} ${remoteId}`); + yield container_1.helpers.dockerCli(module, `push ${remoteId}`); + return { pushed: true, message: `Pushed ${localId}` }; + }); +} +exports.pushModule = pushModule; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9kZXBsb3ltZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFHSCw0Q0FBeUU7QUFDekUsbUNBQW9EO0FBRXBELHVDQUF5RDtBQUN6RCx1Q0FBMEM7QUFDMUMscUNBQWlFO0FBQ2pFLHVDQUEyRDtBQUMzRCwyQ0FBNkM7QUFHN0MsK0NBQWdFO0FBQ2hFLCtCQUErQjtBQUdsQixRQUFBLG1CQUFtQixHQUFHLEtBQUssQ0FBQTtBQUMzQixRQUFBLGlCQUFpQixHQUFHLE1BQU0sQ0FBQTtBQUMxQixRQUFBLHNCQUFzQixHQUFHLE9BQU8sQ0FBQTtBQUNoQyxRQUFBLG9CQUFvQixHQUFHLE9BQU8sQ0FBQTtBQVEzQyxTQUFzQix5QkFBeUIsQ0FDN0MsRUFBRSxHQUFHLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxjQUFjLEVBQTJDOztRQUVqRixxR0FBcUc7UUFDckcsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLE9BQU8sQ0FBQTtRQUM5QixNQUFNLE9BQU8sR0FBRyxNQUFNLHNCQUFzQixDQUFDLEdBQUcsRUFBRSxPQUFPLEVBQUUsY0FBYyxDQUFDLENBQUE7UUFDMUUsTUFBTSxPQUFPLEdBQUcsTUFBTSwrQkFBc0IsQ0FBQyxHQUFHLEVBQUUsT0FBTyxDQUFDLENBQUE7UUFDMUQsTUFBTSxHQUFHLEdBQUcsSUFBSSxhQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3JDLE1BQU0sU0FBUyxHQUFHLE1BQU0sc0JBQVksQ0FBQyxPQUFPLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFFbEQsT0FBTztZQUNMLFNBQVM7WUFDVCxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUMsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLFVBQVU7WUFDckMsT0FBTyxFQUFFLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUztTQUNyRCxD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RUFBRSxPQUFPLEVBQUUsVUFBVSxPQUFPLEVBQUUsRUFBRSxDQUFBO0lBQ3ZELENBQUM7Q0FBQTtBQWZELGdDQWVDIiwiZmlsZSI6InBsdWdpbnMva3ViZXJuZXRlcy9kZXBsb3ltZW50LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IERlcGxveVNlcnZpY2VQYXJhbXMsIEdldFNlcnZpY2VTdGF0dXNQYXJhbXMsIFB1c2hNb2R1bGVQYXJhbXMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQgeyBoZWxwZXJzLCBDb250YWluZXJNb2R1bGUsIENvbnRhaW5lclNlcnZpY2UgfSBmcm9tIFwiLi4vY29udGFpbmVyXCJcbmltcG9ydCB7IHRvUGFpcnMsIGV4dGVuZCwga2V5QnksIHNldCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgUnVudGltZUNvbnRleHQsIFNlcnZpY2VTdGF0dXMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBjcmVhdGVJbmdyZXNzZXMsIGdldEluZ3Jlc3NlcyB9IGZyb20gXCIuL2luZ3Jlc3NcIlxuaW1wb3J0IHsgY3JlYXRlU2VydmljZXMgfSBmcm9tIFwiLi9zZXJ2aWNlXCJcbmltcG9ydCB7IHdhaXRGb3JPYmplY3RzLCBjb21wYXJlRGVwbG95ZWRPYmplY3RzIH0gZnJvbSBcIi4vc3RhdHVzXCJcbmltcG9ydCB7IGFwcGx5TWFueSwgZGVsZXRlT2JqZWN0c0J5TGFiZWwgfSBmcm9tIFwiLi9rdWJlY3RsXCJcbmltcG9ydCB7IGdldEFwcE5hbWVzcGFjZSB9IGZyb20gXCIuL25hbWVzcGFjZVwiXG5pbXBvcnQgeyBLdWJlcm5ldGVzT2JqZWN0IH0gZnJvbSBcIi4vaGVsbVwiXG5pbXBvcnQgeyBQbHVnaW5Db250ZXh0IH0gZnJvbSBcIi4uLy4uL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7IEdBUkRFTl9BTk5PVEFUSU9OX0tFWVNfVkVSU0lPTiB9IGZyb20gXCIuLi8uLi9jb25zdGFudHNcIlxuaW1wb3J0IHsgS3ViZUFwaSB9IGZyb20gXCIuL2FwaVwiXG5pbXBvcnQgeyBLdWJlcm5ldGVzUHJvdmlkZXIgfSBmcm9tIFwiLi9rdWJlcm5ldGVzXCJcblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQ1BVX1JFUVVFU1QgPSBcIjEwbVwiXG5leHBvcnQgY29uc3QgREVGQVVMVF9DUFVfTElNSVQgPSBcIjUwMG1cIlxuZXhwb3J0IGNvbnN0IERFRkFVTFRfTUVNT1JZX1JFUVVFU1QgPSBcIjEyOE1pXCJcbmV4cG9ydCBjb25zdCBERUZBVUxUX01FTU9SWV9MSU1JVCA9IFwiNTEyTWlcIlxuXG5pbnRlcmZhY2UgS3ViZUVudlZhciB7XG4gIG5hbWU6IHN0cmluZ1xuICB2YWx1ZT86IHN0cmluZ1xuICB2YWx1ZUZyb20/OiB7IGZpZWxkUmVmOiB7IGZpZWxkUGF0aDogc3RyaW5nIH0gfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0Q29udGFpbmVyU2VydmljZVN0YXR1cyhcbiAgeyBjdHgsIG1vZHVsZSwgc2VydmljZSwgcnVudGltZUNvbnRleHQgfTogR2V0U2VydmljZVN0YXR1c1BhcmFtczxDb250YWluZXJNb2R1bGU+LFxuKTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPiB7XG4gIC8vIFRPRE86IGhhc2ggYW5kIGNvbXBhcmUgYWxsIHRoZSBjb25maWd1cmF0aW9uIGZpbGVzIChvdGhlcndpc2UgaW50ZXJuYWwgY2hhbmdlcyBkb24ndCBnZXQgZGVwbG95ZWQpXG4gIGNvbnN0IHZlcnNpb24gPSBtb2R1bGUudmVyc2lvblxuICBjb25zdCBvYmplY3RzID0gYXdhaXQgY3JlYXRlQ29udGFpbmVyT2JqZWN0cyhjdHgsIHNlcnZpY2UsIHJ1bnRpbWVDb250ZXh0KVxuICBjb25zdCBtYXRjaGVkID0gYXdhaXQgY29tcGFyZURlcGxveWVkT2JqZWN0cyhjdHgsIG9iamVjdHMpXG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKGN0eC5wcm92aWRlcilcbiAgY29uc3QgaW5ncmVzc2VzID0gYXdhaXQgZ2V0SW5ncmVzc2VzKHNlcnZpY2UsIGFwaSlcblxuICByZXR1cm4ge1xuICAgIGluZ3Jlc3NlcyxcbiAgICBzdGF0ZTogbWF0Y2hlZCA/IFwicmVhZHlcIiA6IFwib3V0ZGF0ZWRcIixcbiAgICB2ZXJzaW9uOiBtYXRjaGVkID8gdmVyc2lvbi52ZXJzaW9uU3RyaW5nIDogdW5kZWZpbmVkLFxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZXBsb3lDb250YWluZXJTZXJ2aWNlKHBhcmFtczogRGVwbG95U2VydmljZVBhcmFtczxDb250YWluZXJNb2R1bGU+KTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPiB7XG4gIGNvbnN0IHsgY3R4LCBzZXJ2aWNlLCBydW50aW1lQ29udGV4dCwgZm9yY2UsIGxvZ0VudHJ5IH0gPSBwYXJhbXNcblxuICBjb25zdCBwcm92aWRlciA9IGN0eC5wcm92aWRlclxuICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBwcm92aWRlcilcbiAgY29uc3Qgb2JqZWN0cyA9IGF3YWl0IGNyZWF0ZUNvbnRhaW5lck9iamVjdHMoY3R4LCBzZXJ2aWNlLCBydW50aW1lQ29udGV4dClcblxuICAvLyBUT0RPOiB1c2UgSGVsbSBpbnN0ZWFkIG9mIGt1YmVjdGwgYXBwbHlcbiAgY29uc3QgcHJ1bmVTZWxlY3RvciA9IFwic2VydmljZT1cIiArIHNlcnZpY2UubmFtZVxuICBhd2FpdCBhcHBseU1hbnkocHJvdmlkZXIuY29uZmlnLmNvbnRleHQsIG9iamVjdHMsIHsgZm9yY2UsIG5hbWVzcGFjZSwgcHJ1bmVTZWxlY3RvciB9KVxuICBhd2FpdCB3YWl0Rm9yT2JqZWN0cyh7IGN0eCwgcHJvdmlkZXIsIHNlcnZpY2UsIG9iamVjdHMsIGxvZ0VudHJ5IH0pXG5cbiAgcmV0dXJuIGdldENvbnRhaW5lclNlcnZpY2VTdGF0dXMocGFyYW1zKVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlQ29udGFpbmVyT2JqZWN0cyhcbiAgY3R4OiBQbHVnaW5Db250ZXh0LCBzZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlLCBydW50aW1lQ29udGV4dDogUnVudGltZUNvbnRleHQsXG4pIHtcbiAgY29uc3QgdmVyc2lvbiA9IHNlcnZpY2UubW9kdWxlLnZlcnNpb25cbiAgY29uc3QgcHJvdmlkZXIgPSBjdHgucHJvdmlkZXJcbiAgY29uc3QgbmFtZXNwYWNlID0gYXdhaXQgZ2V0QXBwTmFtZXNwYWNlKGN0eCwgcHJvdmlkZXIpXG4gIGNvbnN0IGRlcGxveW1lbnQgPSBhd2FpdCBjcmVhdGVEZXBsb3ltZW50KHByb3ZpZGVyLCBzZXJ2aWNlLCBydW50aW1lQ29udGV4dCwgbmFtZXNwYWNlKVxuICBjb25zdCBrdWJlc2VydmljZXMgPSBhd2FpdCBjcmVhdGVTZXJ2aWNlcyhzZXJ2aWNlLCBuYW1lc3BhY2UpXG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKHByb3ZpZGVyKVxuICBjb25zdCBpbmdyZXNzZXMgPSBhd2FpdCBjcmVhdGVJbmdyZXNzZXMoYXBpLCBuYW1lc3BhY2UsIHNlcnZpY2UpXG5cbiAgY29uc3Qgb2JqZWN0cyA9IFtkZXBsb3ltZW50LCAuLi5rdWJlc2VydmljZXMsIC4uLmluZ3Jlc3Nlc11cblxuICByZXR1cm4gb2JqZWN0cy5tYXAob2JqID0+IHtcbiAgICBzZXQob2JqLCBbXCJtZXRhZGF0YVwiLCBcImFubm90YXRpb25zXCIsIFwiZ2FyZGVuLmlvL2dlbmVyYXRlZFwiXSwgXCJ0cnVlXCIpXG4gICAgc2V0KG9iaiwgW1wibWV0YWRhdGFcIiwgXCJhbm5vdGF0aW9uc1wiLCBHQVJERU5fQU5OT1RBVElPTl9LRVlTX1ZFUlNJT05dLCB2ZXJzaW9uLnZlcnNpb25TdHJpbmcpXG4gICAgc2V0KG9iaiwgW1wibWV0YWRhdGFcIiwgXCJsYWJlbHNcIiwgXCJtb2R1bGVcIl0sIHNlcnZpY2UubW9kdWxlLm5hbWUpXG4gICAgc2V0KG9iaiwgW1wibWV0YWRhdGFcIiwgXCJsYWJlbHNcIiwgXCJzZXJ2aWNlXCJdLCBzZXJ2aWNlLm5hbWUpXG4gICAgcmV0dXJuIG9ialxuICB9KVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY3JlYXRlRGVwbG95bWVudChcbiAgcHJvdmlkZXI6IEt1YmVybmV0ZXNQcm92aWRlciwgc2VydmljZTogQ29udGFpbmVyU2VydmljZSwgcnVudGltZUNvbnRleHQ6IFJ1bnRpbWVDb250ZXh0LCBuYW1lc3BhY2U6IHN0cmluZyxcbik6IFByb21pc2U8S3ViZXJuZXRlc09iamVjdD4ge1xuICBjb25zdCBzcGVjID0gc2VydmljZS5zcGVjXG4gIC8vIFRPRE86IHN1cHBvcnQgc3BlY2lmeWluZyByZXBsaWNhIGNvdW50XG4gIGNvbnN0IGNvbmZpZ3VyZWRSZXBsaWNhcyA9IDEgLy8gc2VydmljZS5zcGVjLmNvdW50W2Vudi5uYW1lXSB8fCAxXG5cbiAgY29uc3QgbGFiZWxzID0ge1xuICAgIG1vZHVsZTogc2VydmljZS5tb2R1bGUubmFtZSxcbiAgICBzZXJ2aWNlOiBzZXJ2aWNlLm5hbWUsXG4gIH1cblxuICAvLyBUT0RPOiBtb2FyIHR5cGUtc2FmZXR5XG4gIGNvbnN0IGRlcGxveW1lbnQ6IGFueSA9IHtcbiAgICBraW5kOiBcIkRlcGxveW1lbnRcIixcbiAgICBhcGlWZXJzaW9uOiBcImV4dGVuc2lvbnMvdjFiZXRhMVwiLFxuICAgIG1ldGFkYXRhOiB7XG4gICAgICBuYW1lOiBzZXJ2aWNlLm5hbWUsXG4gICAgICBhbm5vdGF0aW9uczoge1xuICAgICAgICAvLyB3ZSBjYW4gdXNlIHRoaXMgdG8gYXZvaWQgb3ZlcnJpZGluZyB0aGUgcmVwbGljYSBjb3VudCBpZiBpdCBoYXMgYmVlbiBtYW51YWxseSBzY2FsZWRcbiAgICAgICAgXCJnYXJkZW4uaW8vY29uZmlndXJlZC5yZXBsaWNhc1wiOiBjb25maWd1cmVkUmVwbGljYXMudG9TdHJpbmcoKSxcbiAgICAgIH0sXG4gICAgICBuYW1lc3BhY2UsXG4gICAgICBsYWJlbHMsXG4gICAgfSxcbiAgICBzcGVjOiB7XG4gICAgICBzZWxlY3Rvcjoge1xuICAgICAgICBtYXRjaExhYmVsczoge1xuICAgICAgICAgIHNlcnZpY2U6IHNlcnZpY2UubmFtZSxcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB0ZW1wbGF0ZToge1xuICAgICAgICBtZXRhZGF0YToge1xuICAgICAgICAgIGxhYmVscyxcbiAgICAgICAgfSxcbiAgICAgICAgc3BlYzoge1xuICAgICAgICAgIC8vIFRPRE86IHNldCB0aGlzIGZvciBub24tc3lzdGVtIHBvZHNcbiAgICAgICAgICAvLyBhdXRvbW91bnRTZXJ2aWNlQWNjb3VudFRva2VuOiBmYWxzZSwgIC8vIHRoaXMgcHJldmVudHMgdGhlIHBvZCBmcm9tIGFjY2Vzc2luZyB0aGUga3ViZXJuZXRlcyBBUElcbiAgICAgICAgICBjb250YWluZXJzOiBbXSxcbiAgICAgICAgICAvLyBUT0RPOiBtYWtlIHJlc3RhcnRQb2xpY3kgY29uZmlndXJhYmxlXG4gICAgICAgICAgcmVzdGFydFBvbGljeTogXCJBbHdheXNcIixcbiAgICAgICAgICB0ZXJtaW5hdGlvbkdyYWNlUGVyaW9kU2Vjb25kczogMTAsXG4gICAgICAgICAgZG5zUG9saWN5OiBcIkNsdXN0ZXJGaXJzdFwiLFxuICAgICAgICB9LFxuICAgICAgfSxcbiAgICB9LFxuICB9XG5cbiAgY29uc3QgZW52VmFycyA9IHsgLi4ucnVudGltZUNvbnRleHQuZW52VmFycywgLi4uc2VydmljZS5zcGVjLmVudiB9XG5cbiAgY29uc3QgZW52OiBLdWJlRW52VmFyW10gPSB0b1BhaXJzKGVudlZhcnMpLm1hcCgoW25hbWUsIHZhbHVlXSkgPT4gKHsgbmFtZSwgdmFsdWU6IHZhbHVlICsgXCJcIiB9KSlcblxuICAvLyBleHBvc2Ugc29tZSBtZXRhZGF0YSB0byB0aGUgY29udGFpbmVyXG4gIGVudi5wdXNoKHtcbiAgICBuYW1lOiBcIlBPRF9OQU1FXCIsXG4gICAgdmFsdWVGcm9tOiB7IGZpZWxkUmVmOiB7IGZpZWxkUGF0aDogXCJtZXRhZGF0YS5uYW1lXCIgfSB9LFxuICB9KVxuXG4gIGVudi5wdXNoKHtcbiAgICBuYW1lOiBcIlBPRF9OQU1FU1BBQ0VcIixcbiAgICB2YWx1ZUZyb206IHsgZmllbGRSZWY6IHsgZmllbGRQYXRoOiBcIm1ldGFkYXRhLm5hbWVzcGFjZVwiIH0gfSxcbiAgfSlcblxuICBlbnYucHVzaCh7XG4gICAgbmFtZTogXCJQT0RfSVBcIixcbiAgICB2YWx1ZUZyb206IHsgZmllbGRSZWY6IHsgZmllbGRQYXRoOiBcInN0YXR1cy5wb2RJUFwiIH0gfSxcbiAgfSlcblxuICBjb25zdCByZWdpc3RyeUNvbmZpZyA9IHByb3ZpZGVyLm5hbWUgPT09IFwibG9jYWwta3ViZXJuZXRlc1wiID8gdW5kZWZpbmVkIDogcHJvdmlkZXIuY29uZmlnLmRlcGxveW1lbnRSZWdpc3RyeVxuICBjb25zdCBpbWFnZSA9IGF3YWl0IGhlbHBlcnMuZ2V0RGVwbG95bWVudEltYWdlSWQoc2VydmljZS5tb2R1bGUsIHJlZ2lzdHJ5Q29uZmlnKVxuXG4gIGNvbnN0IGNvbnRhaW5lcjogYW55ID0ge1xuICAgIG5hbWU6IHNlcnZpY2UubmFtZSxcbiAgICBpbWFnZSxcbiAgICBlbnYsXG4gICAgcG9ydHM6IFtdLFxuICAgIC8vIFRPRE86IG1ha2UgdGhlc2UgY29uZmlndXJhYmxlXG4gICAgcmVzb3VyY2VzOiB7XG4gICAgICByZXF1ZXN0czoge1xuICAgICAgICBjcHU6IERFRkFVTFRfQ1BVX1JFUVVFU1QsXG4gICAgICAgIG1lbW9yeTogREVGQVVMVF9NRU1PUllfUkVRVUVTVCxcbiAgICAgIH0sXG4gICAgICBsaW1pdHM6IHtcbiAgICAgICAgY3B1OiBERUZBVUxUX0NQVV9MSU1JVCxcbiAgICAgICAgbWVtb3J5OiBERUZBVUxUX01FTU9SWV9MSU1JVCxcbiAgICAgIH0sXG4gICAgfSxcbiAgICBpbWFnZVB1bGxQb2xpY3k6IFwiSWZOb3RQcmVzZW50XCIsXG4gIH1cblxuICBpZiAoc2VydmljZS5zcGVjLmNvbW1hbmQgJiYgc2VydmljZS5zcGVjLmNvbW1hbmQubGVuZ3RoID4gMCkge1xuICAgIGNvbnRhaW5lci5hcmdzID0gc2VydmljZS5zcGVjLmNvbW1hbmRcbiAgfVxuXG4gIC8vIGlmIChjb25maWcuZW50cnlwb2ludCkge1xuICAvLyAgIGNvbnRhaW5lci5jb21tYW5kID0gW2NvbmZpZy5lbnRyeXBvaW50XVxuICAvLyB9XG5cbiAgaWYgKHNwZWMuaGVhbHRoQ2hlY2spIHtcbiAgICBjb250YWluZXIucmVhZGluZXNzUHJvYmUgPSB7XG4gICAgICBpbml0aWFsRGVsYXlTZWNvbmRzOiAxMCxcbiAgICAgIHBlcmlvZFNlY29uZHM6IDUsXG4gICAgICB0aW1lb3V0U2Vjb25kczogMyxcbiAgICAgIHN1Y2Nlc3NUaHJlc2hvbGQ6IDIsXG4gICAgICBmYWlsdXJlVGhyZXNob2xkOiA1LFxuICAgIH1cblxuICAgIGNvbnRhaW5lci5saXZlbmVzc1Byb2JlID0ge1xuICAgICAgaW5pdGlhbERlbGF5U2Vjb25kczogMTUsXG4gICAgICBwZXJpb2RTZWNvbmRzOiA1LFxuICAgICAgdGltZW91dFNlY29uZHM6IDMsXG4gICAgICBzdWNjZXNzVGhyZXNob2xkOiAxLFxuICAgICAgZmFpbHVyZVRocmVzaG9sZDogMyxcbiAgICB9XG5cbiAgICBjb25zdCBwb3J0c0J5TmFtZSA9IGtleUJ5KHNwZWMucG9ydHMsIFwibmFtZVwiKVxuXG4gICAgaWYgKHNwZWMuaGVhbHRoQ2hlY2suaHR0cEdldCkge1xuICAgICAgY29uc3QgaHR0cEdldDogYW55ID0gZXh0ZW5kKHt9LCBzcGVjLmhlYWx0aENoZWNrLmh0dHBHZXQpXG4gICAgICBodHRwR2V0LnBvcnQgPSBwb3J0c0J5TmFtZVtodHRwR2V0LnBvcnRdLmNvbnRhaW5lclBvcnRcblxuICAgICAgY29udGFpbmVyLnJlYWRpbmVzc1Byb2JlLmh0dHBHZXQgPSBodHRwR2V0XG4gICAgICBjb250YWluZXIubGl2ZW5lc3NQcm9iZS5odHRwR2V0ID0gaHR0cEdldFxuICAgIH0gZWxzZSBpZiAoc3BlYy5oZWFsdGhDaGVjay5jb21tYW5kKSB7XG4gICAgICBjb250YWluZXIucmVhZGluZXNzUHJvYmUuZXhlYyA9IHsgY29tbWFuZDogc3BlYy5oZWFsdGhDaGVjay5jb21tYW5kLm1hcChzID0+IHMudG9TdHJpbmcoKSkgfVxuICAgICAgY29udGFpbmVyLmxpdmVuZXNzUHJvYmUuZXhlYyA9IGNvbnRhaW5lci5yZWFkaW5lc3NQcm9iZS5leGVjXG4gICAgfSBlbHNlIGlmIChzcGVjLmhlYWx0aENoZWNrLnRjcFBvcnQpIHtcbiAgICAgIGNvbnRhaW5lci5yZWFkaW5lc3NQcm9iZS50Y3BTb2NrZXQgPSB7XG4gICAgICAgIHBvcnQ6IHBvcnRzQnlOYW1lW3NwZWMuaGVhbHRoQ2hlY2sudGNwUG9ydF0uY29udGFpbmVyUG9ydCxcbiAgICAgIH1cbiAgICAgIGNvbnRhaW5lci5saXZlbmVzc1Byb2JlLnRjcFNvY2tldCA9IGNvbnRhaW5lci5yZWFkaW5lc3NQcm9iZS50Y3BTb2NrZXRcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgbmV3IEVycm9yKFwiTXVzdCBzcGVjaWZ5IHR5cGUgb2YgaGVhbHRoIGNoZWNrIHdoZW4gY29uZmlndXJpbmcgaGVhbHRoIGNoZWNrLlwiKVxuICAgIH1cbiAgfVxuXG4gIC8vIGlmIChzZXJ2aWNlLnByaXZpbGVnZWQpIHtcbiAgLy8gICBjb250YWluZXIuc2VjdXJpdHlDb250ZXh0ID0ge1xuICAvLyAgICAgcHJpdmlsZWdlZDogdHJ1ZSxcbiAgLy8gICB9XG4gIC8vIH1cblxuICBpZiAoc3BlYy52b2x1bWVzICYmIHNwZWMudm9sdW1lcy5sZW5ndGgpIHtcbiAgICBjb25zdCB2b2x1bWVzOiBhbnlbXSA9IFtdXG4gICAgY29uc3Qgdm9sdW1lTW91bnRzOiBhbnlbXSA9IFtdXG5cbiAgICBmb3IgKGNvbnN0IHZvbHVtZSBvZiBzcGVjLnZvbHVtZXMpIHtcbiAgICAgIGNvbnN0IHZvbHVtZU5hbWUgPSB2b2x1bWUubmFtZVxuICAgICAgY29uc3Qgdm9sdW1lVHlwZSA9ICEhdm9sdW1lLmhvc3RQYXRoID8gXCJob3N0UGF0aFwiIDogXCJlbXB0eURpclwiXG5cbiAgICAgIGlmICghdm9sdW1lTmFtZSkge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJNdXN0IHNwZWNpZnkgdm9sdW1lIG5hbWVcIilcbiAgICAgIH1cblxuICAgICAgaWYgKHZvbHVtZVR5cGUgPT09IFwiZW1wdHlEaXJcIikge1xuICAgICAgICB2b2x1bWVzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IHZvbHVtZU5hbWUsXG4gICAgICAgICAgZW1wdHlEaXI6IHt9LFxuICAgICAgICB9KVxuICAgICAgICB2b2x1bWVNb3VudHMucHVzaCh7XG4gICAgICAgICAgbmFtZTogdm9sdW1lTmFtZSxcbiAgICAgICAgICBtb3VudFBhdGg6IHZvbHVtZS5jb250YWluZXJQYXRoLFxuICAgICAgICB9KVxuICAgICAgfSBlbHNlIGlmICh2b2x1bWVUeXBlID09PSBcImhvc3RQYXRoXCIpIHtcbiAgICAgICAgdm9sdW1lcy5wdXNoKHtcbiAgICAgICAgICBuYW1lOiB2b2x1bWVOYW1lLFxuICAgICAgICAgIGhvc3RQYXRoOiB7XG4gICAgICAgICAgICBwYXRoOiB2b2x1bWUuaG9zdFBhdGgsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSlcbiAgICAgICAgdm9sdW1lTW91bnRzLnB1c2goe1xuICAgICAgICAgIG5hbWU6IHZvbHVtZU5hbWUsXG4gICAgICAgICAgbW91bnRQYXRoOiB2b2x1bWUuY29udGFpbmVyUGF0aCB8fCB2b2x1bWUuaG9zdFBhdGgsXG4gICAgICAgIH0pXG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aHJvdyBuZXcgRXJyb3IoXCJVbnN1cHBvcnRlZCB2b2x1bWUgdHlwZTogXCIgKyB2b2x1bWVUeXBlKVxuICAgICAgfVxuICAgIH1cblxuICAgIGRlcGxveW1lbnQuc3BlYy50ZW1wbGF0ZS5zcGVjLnZvbHVtZXMgPSB2b2x1bWVzXG4gICAgY29udGFpbmVyLnZvbHVtZU1vdW50cyA9IHZvbHVtZU1vdW50c1xuICB9XG5cbiAgY29uc3QgcG9ydHMgPSBzcGVjLnBvcnRzXG5cbiAgZm9yIChjb25zdCBwb3J0IG9mIHBvcnRzKSB7XG4gICAgY29udGFpbmVyLnBvcnRzLnB1c2goe1xuICAgICAgcHJvdG9jb2w6IHBvcnQucHJvdG9jb2wsXG4gICAgICBjb250YWluZXJQb3J0OiBwb3J0LmNvbnRhaW5lclBvcnQsXG4gICAgfSlcbiAgfVxuXG4gIGlmIChzcGVjLmRhZW1vbikge1xuICAgIC8vIHRoaXMgcnVucyBhIHBvZCBvbiBldmVyeSBub2RlXG4gICAgZGVwbG95bWVudC5raW5kID0gXCJEYWVtb25TZXRcIlxuICAgIGRlcGxveW1lbnQuc3BlYy51cGRhdGVTdHJhdGVneSA9IHtcbiAgICAgIHR5cGU6IFwiUm9sbGluZ1VwZGF0ZVwiLFxuICAgIH1cblxuICAgIGZvciAoY29uc3QgcG9ydCBvZiBwb3J0cy5maWx0ZXIocCA9PiBwLmhvc3RQb3J0KSkge1xuICAgICAgLy8gRm9yIGRhZW1vbnMgd2UgY2FuIGV4cG9zZSBob3N0IHBvcnRzIGRpcmVjdGx5IG9uIHRoZSBQb2QsIGFzIG9wcG9zZWQgdG8gb25seSB2aWEgdGhlIFNlcnZpY2UgcmVzb3VyY2UuXG4gICAgICAvLyBUaGlzIGFsbG93cyB1cyB0byBjaG9vc2UgYW55IHBvcnQuXG4gICAgICAvLyBUT0RPOiB2YWxpZGF0ZSB0aGF0IGNvbmZsaWN0aW5nIHBvcnRzIGFyZSBub3QgZGVmaW5lZC5cbiAgICAgIGNvbnRhaW5lci5wb3J0cy5wdXNoKHtcbiAgICAgICAgcHJvdG9jb2w6IHBvcnQucHJvdG9jb2wsXG4gICAgICAgIGNvbnRhaW5lclBvcnQ6IHBvcnQuY29udGFpbmVyUG9ydCxcbiAgICAgICAgaG9zdFBvcnQ6IHBvcnQuaG9zdFBvcnQsXG4gICAgICB9KVxuICAgIH1cblxuICB9IGVsc2Uge1xuICAgIGRlcGxveW1lbnQuc3BlYy5yZXBsaWNhcyA9IGNvbmZpZ3VyZWRSZXBsaWNhc1xuICAgIGRlcGxveW1lbnQuc3BlYy5zdHJhdGVneSA9IHtcbiAgICAgIHR5cGU6IFwiUm9sbGluZ1VwZGF0ZVwiLFxuICAgICAgcm9sbGluZ1VwZGF0ZToge1xuICAgICAgICBtYXhVbmF2YWlsYWJsZTogXCIzNCVcIixcbiAgICAgICAgbWF4U3VyZ2U6IFwiMzQlXCIsXG4gICAgICB9LFxuICAgIH1cbiAgICBkZXBsb3ltZW50LnNwZWMucmV2aXNpb25IaXN0b3J5TGltaXQgPSAzXG4gIH1cblxuICBpZiAocHJvdmlkZXIuY29uZmlnLmltYWdlUHVsbFNlY3JldHMubGVuZ3RoID4gMCkge1xuICAgIC8vIGFkZCBhbnkgY29uZmlndXJlZCBpbWFnZVB1bGxTZWNyZXRzXG4gICAgZGVwbG95bWVudC5zcGVjLnRlbXBsYXRlLnNwZWMuaW1hZ2VQdWxsU2VjcmV0cyA9IHByb3ZpZGVyLmNvbmZpZy5pbWFnZVB1bGxTZWNyZXRzLm1hcChzID0+ICh7IG5hbWU6IHMubmFtZSB9KSlcbiAgfVxuXG4gIGRlcGxveW1lbnQuc3BlYy50ZW1wbGF0ZS5zcGVjLmNvbnRhaW5lcnMgPSBbY29udGFpbmVyXVxuXG4gIHJldHVybiBkZXBsb3ltZW50XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVDb250YWluZXJTZXJ2aWNlKFxuICB7IG5hbWVzcGFjZSwgcHJvdmlkZXIsIHNlcnZpY2VOYW1lLCBsb2dFbnRyeSB9LFxuKSB7XG5cbiAgY29uc3QgY29udGV4dCA9IHByb3ZpZGVyLmNvbmZpZy5jb250ZXh0XG4gIGF3YWl0IGRlbGV0ZUNvbnRhaW5lckRlcGxveW1lbnQoeyBuYW1lc3BhY2UsIHByb3ZpZGVyLCBzZXJ2aWNlTmFtZSwgbG9nRW50cnkgfSlcbiAgYXdhaXQgZGVsZXRlT2JqZWN0c0J5TGFiZWwoe1xuICAgIGNvbnRleHQsXG4gICAgbmFtZXNwYWNlLFxuICAgIGxhYmVsS2V5OiBcInNlcnZpY2VcIixcbiAgICBsYWJlbFZhbHVlOiBzZXJ2aWNlTmFtZSxcbiAgICBvYmplY3RUeXBlczogW1wiZGVwbG95bWVudFwiLCBcInNlcnZpY2VcIiwgXCJpbmdyZXNzXCJdLFxuICAgIGluY2x1ZGVVbmluaXRpYWxpemVkOiBmYWxzZSxcbiAgfSlcblxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGVsZXRlQ29udGFpbmVyRGVwbG95bWVudChcbiAgeyBuYW1lc3BhY2UsIHByb3ZpZGVyLCBzZXJ2aWNlTmFtZSwgbG9nRW50cnkgfSxcbikge1xuXG4gIGxldCBmb3VuZCA9IHRydWVcbiAgY29uc3QgYXBpID0gbmV3IEt1YmVBcGkocHJvdmlkZXIpXG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBhcGkuZXh0ZW5zaW9ucy5kZWxldGVOYW1lc3BhY2VkRGVwbG95bWVudChzZXJ2aWNlTmFtZSwgbmFtZXNwYWNlLCA8YW55Pnt9KVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoZXJyLmNvZGUgPT09IDQwNCkge1xuICAgICAgZm91bmQgPSBmYWxzZVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cblxuICBpZiAobG9nRW50cnkpIHtcbiAgICBmb3VuZCA/IGxvZ0VudHJ5LnNldFN1Y2Nlc3MoXCJTZXJ2aWNlIGRlbGV0ZWRcIikgOiBsb2dFbnRyeS5zZXRXYXJuKFwiU2VydmljZSBub3QgZGVwbG95ZWRcIilcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHVzaE1vZHVsZSh7IGN0eCwgbW9kdWxlLCBsb2dFbnRyeSB9OiBQdXNoTW9kdWxlUGFyYW1zPENvbnRhaW5lck1vZHVsZT4pIHtcbiAgaWYgKCEoYXdhaXQgaGVscGVycy5oYXNEb2NrZXJmaWxlKG1vZHVsZSkpKSB7XG4gICAgbG9nRW50cnkgJiYgbG9nRW50cnkuc2V0U3RhdGUoeyBtc2c6IGBOb3RoaW5nIHRvIHB1c2hgIH0pXG4gICAgcmV0dXJuIHsgcHVzaGVkOiBmYWxzZSB9XG4gIH1cblxuICBjb25zdCBsb2NhbElkID0gYXdhaXQgaGVscGVycy5nZXRMb2NhbEltYWdlSWQobW9kdWxlKVxuICBjb25zdCByZW1vdGVJZCA9IGF3YWl0IGhlbHBlcnMuZ2V0RGVwbG95bWVudEltYWdlSWQobW9kdWxlLCBjdHgucHJvdmlkZXIuY29uZmlnLmRlcGxveW1lbnRSZWdpc3RyeSlcblxuICBsb2dFbnRyeSAmJiBsb2dFbnRyeS5zZXRTdGF0ZSh7IG1zZzogYFB1c2hpbmcgaW1hZ2UgJHtyZW1vdGVJZH0uLi5gIH0pXG5cbiAgYXdhaXQgaGVscGVycy5kb2NrZXJDbGkobW9kdWxlLCBgdGFnICR7bG9jYWxJZH0gJHtyZW1vdGVJZH1gKVxuICBhd2FpdCBoZWxwZXJzLmRvY2tlckNsaShtb2R1bGUsIGBwdXNoICR7cmVtb3RlSWR9YClcblxuICByZXR1cm4geyBwdXNoZWQ6IHRydWUsIG1lc3NhZ2U6IGBQdXNoZWQgJHtsb2NhbElkfWAgfVxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/helm.d.ts b/garden-service/build/plugins/kubernetes/helm.d.ts new file mode 100644 index 00000000000..48f9776585e --- /dev/null +++ b/garden-service/build/plugins/kubernetes/helm.d.ts @@ -0,0 +1,31 @@ +import { Primitive } from "../../config/common"; +import { Module } from "../../types/module"; +import { ModuleAndServiceActions } from "../../types/plugin/plugin"; +import { KubernetesProvider } from "./kubernetes"; +import { ServiceSpec } from "../../config/service"; +export interface KubernetesObject { + apiVersion: string; + kind: string; + metadata: { + annotations?: object; + name: string; + namespace?: string; + labels?: object; + }; + spec?: any; +} +export interface HelmServiceSpec extends ServiceSpec { + chart: string; + repo?: string; + dependencies: string[]; + version?: string; + parameters: { + [key: string]: Primitive; + }; +} +export declare type HelmModuleSpec = HelmServiceSpec; +export interface HelmModule extends Module { +} +export declare const helmHandlers: Partial>; +export declare function helm(provider: KubernetesProvider, ...args: string[]): Promise; +//# sourceMappingURL=helm.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/helm.js b/garden-service/build/plugins/kubernetes/helm.js new file mode 100644 index 00000000000..a2655cab199 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/helm.js @@ -0,0 +1,224 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const execa = require("execa"); +const Joi = require("joi"); +const js_yaml_1 = require("js-yaml"); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const common_1 = require("../../config/common"); +const util_1 = require("../../util/util"); +const namespace_1 = require("./namespace"); +const constants_1 = require("../../constants"); +const base_1 = require("../../vcs/base"); +const status_1 = require("./status"); +const generic_1 = require("../generic"); +const api_1 = require("./api"); +const parameterValueSchema = Joi.alternatives(common_1.joiPrimitive(), Joi.array().items(Joi.lazy(() => parameterValueSchema)), Joi.object().pattern(/.+/, Joi.lazy(() => parameterValueSchema))); +const helmModuleSpecSchema = Joi.object().keys({ + // TODO: support placing a helm chart in the module directory + chart: Joi.string() + .required() + .description("A valid Helm chart name or URI."), + repo: Joi.string() + .description("The repository URL to fetch the chart from."), + dependencies: common_1.joiArray(common_1.joiIdentifier()) + .description("List of names of services that should be deployed before this chart."), + version: Joi.string() + .description("The chart version to deploy."), + parameters: Joi.object() + .pattern(/.+/, parameterValueSchema) + .default(() => ({}), "{}") + .description("Map of parameters to pass to Helm when rendering the templates. May include arrays and nested objects."), +}); +const helmStatusCodeMap = { + // see https://github.com/kubernetes/helm/blob/master/_proto/hapi/release/status.proto + 0: "unknown", + 1: "ready", + 2: "missing", + 3: "stopped", + 4: "unhealthy", + 5: "stopped", + 6: "deploying", + 7: "deploying", + 8: "deploying", +}; +exports.helmHandlers = { + validate({ moduleConfig }) { + return __awaiter(this, void 0, void 0, function* () { + moduleConfig.spec = common_1.validate(moduleConfig.spec, helmModuleSpecSchema, { context: `helm module ${moduleConfig.name}` }); + const { chart, version, parameters, dependencies } = moduleConfig.spec; + moduleConfig.serviceConfigs = [{ + name: moduleConfig.name, + dependencies, + outputs: {}, + spec: { chart, version, parameters, dependencies }, + }]; + // TODO: make sure at least either a chart is specified, or module contains a helm chart + return moduleConfig; + }); + }, + getBuildStatus: generic_1.getGenericModuleBuildStatus, + build, + getServiceStatus, + deployService({ ctx, module, service, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const provider = ctx.provider; + const chartPath = yield getChartPath(module); + const valuesPath = getValuesPath(chartPath); + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const releaseName = getReleaseName(namespace, service); + const releaseStatus = yield getReleaseStatus(ctx.provider, releaseName); + if (releaseStatus.state === "missing") { + yield helm(provider, "install", chartPath, "--name", releaseName, "--namespace", namespace, "--values", valuesPath, "--wait"); + } + else { + yield helm(provider, "upgrade", releaseName, chartPath, "--namespace", namespace, "--values", valuesPath, "--wait"); + } + const objects = yield getChartObjects(ctx, service); + yield status_1.waitForObjects({ ctx, provider, service, objects, logEntry }); + return {}; + }); + }, + deleteService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, logEntry, service } = params; + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const releaseName = getReleaseName(namespace, service); + yield helm(ctx.provider, "delete", "--purge", releaseName); + logEntry && logEntry.setSuccess("Service deleted"); + return yield getServiceStatus(params); + }); + }, +}; +function build({ ctx, module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const buildPath = module.buildPath; + const config = module; + // fetch the chart + const fetchArgs = [ + "fetch", config.spec.chart, + "--destination", buildPath, + "--untar", + ]; + if (config.spec.version) { + fetchArgs.push("--version", config.spec.version); + } + if (config.spec.repo) { + fetchArgs.push("--repo", config.spec.repo); + } + logEntry && logEntry.setState("Fetching chart..."); + yield helm(ctx.provider, ...fetchArgs); + const chartPath = yield getChartPath(module); + // create the values.yml file (merge the configured parameters into the default values) + logEntry && logEntry.setState("Preparing chart..."); + const values = js_yaml_1.safeLoad(yield helm(ctx.provider, "inspect", "values", chartPath)) || {}; + Object.entries(flattenValues(config.spec.parameters)) + .map(([k, v]) => lodash_1.set(values, k, v)); + const valuesPath = getValuesPath(chartPath); + yield util_1.dumpYaml(valuesPath, values); + // keep track of which version has been built + const buildVersionFilePath = path_1.join(buildPath, constants_1.GARDEN_BUILD_VERSION_FILENAME); + const version = module.version; + yield base_1.writeTreeVersionFile(buildVersionFilePath, { + latestCommit: version.versionString, + dirtyTimestamp: version.dirtyTimestamp, + }); + return { fresh: true }; + }); +} +function helm(provider, ...args) { + return execa.stdout("helm", [ + "--kube-context", provider.config.context, + ...args, + ]); +} +exports.helm = helm; +function getChartPath(module) { + return __awaiter(this, void 0, void 0, function* () { + const splitName = module.spec.chart.split("/"); + const chartDir = splitName[splitName.length - 1]; + return path_1.join(module.buildPath, chartDir); + }); +} +function getValuesPath(chartPath) { + return path_1.join(chartPath, "garden-values.yml"); +} +function getChartObjects(ctx, service) { + return __awaiter(this, void 0, void 0, function* () { + const chartPath = yield getChartPath(service.module); + const valuesPath = getValuesPath(chartPath); + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const releaseName = getReleaseName(namespace, service); + const objects = js_yaml_1.safeLoadAll(yield helm(ctx.provider, "template", "--name", releaseName, "--namespace", namespace, "--values", valuesPath, chartPath)); + return objects.filter(obj => obj !== null).map((obj) => { + if (!obj.metadata.annotations) { + obj.metadata.annotations = {}; + } + return obj; + }); + }); +} +function getServiceStatus({ ctx, service, module, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + // need to build to be able to check the status + const buildStatus = yield generic_1.getGenericModuleBuildStatus({ ctx, module, logEntry }); + if (!buildStatus.ready) { + yield build({ ctx, module, logEntry }); + } + // first check if the installed objects on the cluster match the current code + const objects = yield getChartObjects(ctx, service); + const matched = yield status_1.compareDeployedObjects(ctx, objects); + if (!matched) { + return { state: "outdated" }; + } + // then check if the rollout is complete + const version = module.version; + const api = new api_1.KubeApi(ctx.provider); + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const { ready } = yield status_1.checkObjectStatus(api, namespace, objects); + // TODO: set state to "unhealthy" if any status is "unhealthy" + const state = ready ? "ready" : "deploying"; + return { state, version: version.versionString }; + }); +} +function getReleaseName(namespace, service) { + return `${namespace}--${service.name}`; +} +function getReleaseStatus(provider, releaseName) { + return __awaiter(this, void 0, void 0, function* () { + try { + const res = JSON.parse(yield helm(provider, "status", releaseName, "--output", "json")); + const statusCode = res.info.status.code; + return { + state: helmStatusCodeMap[statusCode], + detail: res, + }; + } + catch (_) { + // release doesn't exist + return { state: "missing" }; + } + }); +} +// adapted from https://gist.github.com/penguinboy/762197 +function flattenValues(object, prefix = "") { + return Object.keys(object).reduce((prev, element) => object[element] && typeof object[element] === "object" && !Array.isArray(object[element]) + ? Object.assign({}, prev, flattenValues(object[element], `${prefix}${element}.`)) : Object.assign({}, prev, { [`${prefix}${element}`]: object[element] }), {}); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9oZWxtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCwrQkFBK0I7QUFDL0IsMkJBQTBCO0FBQzFCLHFDQUdnQjtBQUNoQixtQ0FBNEI7QUFDNUIsK0JBQTJCO0FBRTNCLGdEQU00QjtBQWU1QiwwQ0FBMEM7QUFFMUMsMkNBQTZDO0FBQzdDLCtDQUErRDtBQUMvRCx5Q0FBcUQ7QUFFckQscUNBQW9GO0FBQ3BGLHdDQUF3RDtBQUV4RCwrQkFBK0I7QUEwQi9CLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDLFlBQVksQ0FDM0MscUJBQVksRUFBRSxFQUNkLEdBQUcsQ0FBQyxLQUFLLEVBQUUsQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxHQUFHLEVBQUUsQ0FBQyxvQkFBb0IsQ0FBQyxDQUFDLEVBQ3ZELEdBQUcsQ0FBQyxNQUFNLEVBQUUsQ0FBQyxPQUFPLENBQUMsSUFBSSxFQUFFLEdBQUcsQ0FBQyxJQUFJLENBQUMsR0FBRyxFQUFFLENBQUMsb0JBQW9CLENBQUMsQ0FBQyxDQUNqRSxDQUFBO0FBRUQsTUFBTSxvQkFBb0IsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsSUFBSSxDQUFDO0lBQzdDLDZEQUE2RDtJQUM3RCxLQUFLLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNoQixRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsaUNBQWlDLENBQUM7SUFDakQsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDZixXQUFXLENBQUMsNkNBQTZDLENBQUM7SUFDN0QsWUFBWSxFQUFFLGlCQUFRLENBQUMsc0JBQWEsRUFBRSxDQUFDO1NBQ3BDLFdBQVcsQ0FBQyxzRUFBc0UsQ0FBQztJQUN0RixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNsQixXQUFXLENBQUMsOEJBQThCLENBQUM7SUFDOUMsVUFBVSxFQUFFLEdBQUcs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SSxDQUFDLE1BQU0sQ0FBQyxDQUFDLE1BQU0sQ0FDL0IsQ0FBQyxJQUFJLEVBQUUsT0FBTyxFQUFFLEVBQUUsQ0FDaEIsTUFBTSxDQUFDLE9BQU8sQ0FBQyxJQUFJLE9BQU8sTUFBTSxDQUFDLE9BQU8sQ0FBQyxLQUFLLFFBQVEsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLENBQUMsTUFBTSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBQ3ZGLENBQUMsbUJBQU0sSUFBSSxFQUFLLGFBQWEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxNQUFNLEdBQUcsT0FBTyxHQUFHLENBQUMsRUFDdEUsQ0FBQyxtQkFBTSxJQUFJLEVBQUssRUFBRSxDQUFDLEdBQUcsTUFBTSxHQUFHLE9BQU8sRUFBRSxDQUFDLEVBQUUsTUFBTSxDQUFDLE9BQU8sQ0FBQyxFQUFFLENBQUUsRUFDbEUsRUFBRSxDQUNILENBQUE7QUFDSCxDQUFDIiwiZmlsZSI6InBsdWdpbnMva3ViZXJuZXRlcy9oZWxtLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBleGVjYSA9IHJlcXVpcmUoXCJleGVjYVwiKVxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHtcbiAgc2FmZUxvYWQsXG4gIHNhZmVMb2FkQWxsLFxufSBmcm9tIFwianMteWFtbFwiXG5pbXBvcnQgeyBzZXQgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBQbHVnaW5Db250ZXh0IH0gZnJvbSBcIi4uLy4uL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7XG4gIGpvaUFycmF5LFxuICBqb2lJZGVudGlmaWVyLFxuICBqb2lQcmltaXRpdmUsXG4gIFByaW1pdGl2ZSxcbiAgdmFsaWRhdGUsXG59IGZyb20gXCIuLi8uLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IE1vZHVsZSB9IGZyb20gXCIuLi8uLi90eXBlcy9tb2R1bGVcIlxuaW1wb3J0IHsgTW9kdWxlQW5kU2VydmljZUFjdGlvbnMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQge1xuICBCdWlsZE1vZHVsZVBhcmFtcyxcbiAgRGVwbG95U2VydmljZVBhcmFtcyxcbiAgR2V0U2VydmljZVN0YXR1c1BhcmFtcyxcbiAgVmFsaWRhdGVNb2R1bGVQYXJhbXMsXG4gIERlbGV0ZVNlcnZpY2VQYXJhbXMsXG59IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7XG4gIEJ1aWxkUmVzdWx0LFxuICBWYWxpZGF0ZU1vZHVsZVJlc3VsdCxcbn0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9vdXRwdXRzXCJcbmltcG9ydCB7IFNlcnZpY2UsIFNlcnZpY2VTdGF0dXMgfSBmcm9tIFwiLi4vLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBkdW1wWWFtbCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgS3ViZXJuZXRlc1Byb3ZpZGVyIH0gZnJvbSBcIi4va3ViZXJuZXRlc1wiXG5pbXBvcnQgeyBnZXRBcHBOYW1lc3BhY2UgfSBmcm9tIFwiLi9uYW1lc3BhY2VcIlxuaW1wb3J0IHsgR0FSREVOX0JVSUxEX1ZFUlNJT05fRklMRU5BTUUgfSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IHdyaXRlVHJlZVZlcnNpb25GaWxlIH0gZnJvbSBcIi4uLy4uL3Zjcy9iYXNlXCJcbmltcG9ydCB7IFNlcnZpY2VTdGF0ZSB9IGZyb20gXCIuLi8uLi90eXBlcy9zZXJ2aWNlXCJcbmltcG9ydCB7IGNvbXBhcmVEZXBsb3llZE9iamVjdHMsIHdhaXRGb3JPYmplY3RzLCBjaGVja09iamVjdFN0YXR1cyB9IGZyb20gXCIuL3N0YXR1c1wiXG5pbXBvcnQgeyBnZXRHZW5lcmljTW9kdWxlQnVpbGRTdGF0dXMgfSBmcm9tIFwiLi4vZ2VuZXJpY1wiXG5pbXBvcnQgeyBTZXJ2aWNlU3BlYyB9IGZyb20gXCIuLi8uLi9jb25maWcvc2VydmljZVwiXG5pbXBvcnQgeyBLdWJlQXBpIH0gZnJvbSBcIi4vYXBpXCJcblxuZXhwb3J0IGludGVyZmFjZSBLdWJlcm5ldGVzT2JqZWN0IHtcbiAgYXBpVmVyc2lvbjogc3RyaW5nXG4gIGtpbmQ6IHN0cmluZ1xuICBtZXRhZGF0YToge1xuICAgIGFubm90YXRpb25zPzogb2JqZWN0LFxuICAgIG5hbWU6IHN0cmluZyxcbiAgICBuYW1lc3BhY2U/OiBzdHJpbmcsXG4gICAgbGFiZWxzPzogb2JqZWN0LFxuICB9XG4gIHNwZWM/OiBhbnlcbn1cblxuZXhwb3J0IGludGVyZmFjZSBIZWxtU2VydmljZVNwZWMgZXh0ZW5kcyBTZXJ2aWNlU3BlYyB7XG4gIGNoYXJ0OiBzdHJpbmdcbiAgcmVwbz86IHN0cmluZ1xuICBkZXBlbmRlbmNpZXM6IHN0cmluZ1tdXG4gIHZlcnNpb24/OiBzdHJpbmdcbiAgcGFyYW1ldGVyczogeyBba2V5OiBzdHJpbmddOiBQcmltaXRpdmUgfVxufVxuXG5leHBvcnQgdHlwZSBIZWxtTW9kdWxlU3BlYyA9IEhlbG1TZXJ2aWNlU3BlY1xuXG5leHBvcnQgaW50ZXJmYWNlIEhlbG1Nb2R1bGUgZXh0ZW5kcyBNb2R1bGU8SGVsbU1vZHVsZVNwZWMsIEhlbG1TZXJ2aWNlU3BlYz4geyB9XG5cbmNvbnN0IHBhcmFtZXRlclZhbHVlU2NoZW1hID0gSm9pLmFsdGVybmF0aXZlcyhcbiAgam9pUHJpbWl0aXZlKCksXG4gIEpvaS5hcnJheSgpLml0ZW1zKEpvaS5sYXp5KCgpID0+IHBhcmFtZXRlclZhbHVlU2NoZW1hKSksXG4gIEpvaS5vYmplY3QoKS5wYXR0ZXJuKC8uKy8sIEpvaS5sYXp5KCgpID0+IHBhcmFtZXRlclZhbHVlU2NoZW1hKSksXG4pXG5cbmNvbnN0IGhlbG1Nb2R1bGVTcGVjU2NoZW1hID0gSm9pLm9iamVjdCgpLmtleXMoe1xuICAvLyBUT0RPOiBzdXBwb3J0IHBsYWNpbmcgYSBoZWxtIGNoYXJ0IGluIHRoZSBtb2R1bGUgZGlyZWN0b3J5XG4gIGNoYXJ0OiBKb2kuc3RyaW5nKClcbiAgICAucmVxdWlyZWQoKVxuICAgIC5kZXNjcmlwdGlvbihcIkEgdmFsaWQgSGVsbSBjaGFydCBuYW1lIG9yIFVSSS5cIiksXG4gIHJlcG86IEpvaS5zdHJpbmcoKVxuICAgIC5kZXNjcmlwdGlvbihcIlRoZSByZXBvc2l0b3J5IFVSTCB0byBmZXRjaCB0aGUgY2hhcnQgZnJvbS5cIiksXG4gIGRlcGVuZGVuY2llczogam9pQXJyYXkoam9pSWRlbnRpZmllcigpKVxuICAgIC5kZXNjcmlwdGlvbihcIkxpc3Qgb2YgbmFtZXMgb2Ygc2VydmljZXMgdGhhdCBzaG91bGQgYmUgZGVwbG95ZWQgYmVmb3JlIHRoaXMgY2hhcnQuXCIpLFxuICB2ZXJzaW9uOiBKb2kuc3RyaW5nKClcbiAgICAuZGVzY3JpcHRpb24oXCJUaGUgY2hhcnQgdmVyc2lvbiB0byBkZXBsb3kuXCIpLFxuICBwYXJhbWV0ZXJzOiBKb2kub2JqZWN0KClcbiAgICAucGF0dGVybigvLisvLCBwYXJhbWV0ZXJWYWx1ZVNjaGVtYSlcbiAgICAuZGVmYXVsdCgoKSA9PiAoe30pLCBcInt9XCIpXG4gICAgLmRlc2NyaXB0aW9uKFxuICAgICAgXCJNYXAgb2YgcGFyYW1ldGVycyB0byBwYXNzIHRvIEhlbG0gd2hlbiByZW5kZXJpbmcgdGhlIHRlbXBsYXRlcy4gTWF5IGluY2x1ZGUgYXJyYXlzIGFuZCBuZXN0ZWQgb2JqZWN0cy5cIixcbiAgICApLFxufSlcblxuY29uc3QgaGVsbVN0YXR1c0NvZGVNYXA6IHsgW2NvZGU6IG51bWJlcl06IFNlcnZpY2VTdGF0ZSB9ID0ge1xuICAvLyBzZWUgaHR0cHM6Ly9naXRodWIuY29tL2t1YmVybmV0ZXMvaGVsbS9ibG9iL21hc3Rlci9fcHJvdG8vaGFwaS9yZWxlYXNlL3N0YXR1cy5wcm90b1xuICAwOiBcInVua25vd25cIiwgICAvLyBVTktOT1dOXG4gIDE6IFwicmVhZHlcIiwgICAgIC8vIERFUExPWUVEXG4gIDI6IFwibWlzc2luZ1wiLCAgIC8vIERFTEVURURcbiAgMzogXCJzdG9wcGVkXCIsICAgLy8gU1VQRVJTRURFRFxuICA0OiBcInVuaGVhbHRoeVwiLCAvLyBGQUlMRURcbiAgNTogXCJzdG9wcGVkXCIsICAgLy8gREVMRVRJTkdcbiAgNjogXCJkZXBsb3lpbmdcIiwgLy8gUEVORElOR19JTlNUQUxMXG4gIDc6IFwiZGVwbG95aW5nXCIsIC8vIFBFTkRJTkdfVVBHUkFERVxuICA4OiBcImRlcGxveWluZ1wiLCAvLyBQRU5ESU5HX1JPTExCQUNLXG59XG5cbmV4cG9ydCBjb25zdCBoZWxtSGFuZGxlcnM6IFBhcnRpYWw8TW9kdWxlQW5kU2VydmljZUFjdGlvbnM8SGVsbU1vZHVsZT4+ID0ge1xuICBhc3luYyB2YWxpZGF0ZSh7IG1vZHVsZUNvbmZpZyB9OiBWYWxpZGF0ZU1vZHVsZVBhcmFtcyk6IFByb21pc2U8VmFsaWRhdGVNb2R1bGVSZXN1bHQ+IHtcbiAgICBtb2R1bGVDb25maWcuc3BlYyA9IHZhbGlkYXRlKFxuICAgICAgbW9kdWxlQ29uZmlnLnNwZWMsXG4gICAgICBoZWxtTW9kdWxlU3BlY1NjaGVtYSxcbiAgICAgIHsgY29udGV4dDogYGhlbG0gbW9kdWxlICR7bW9kdWxlQ29uZmlnLm5hbWV9YCB9LFxuICAgIClcblxuICAgIGNvbnN0IHsgY2hhcnQsIHZlcnNpb24sIHBhcmFtZXRlcnMsIGRlcGVuZGVuY2llcyB9ID0gbW9kdWxlQ29uZmlnLnNwZWNcblxuICAgIG1vZHVsZUNvbmZpZy5zZXJ2aWNlQ29uZmlncyA9IFt7XG4gICAgICBuYW1lOiBtb2R1bGVDb25maWcubmFtZSxcbiAgICAgIGRlcGVuZGVuY2llcyxcbiAgICAgIG91dHB1dHM6IHt9LFxuICAgICAgc3BlYzogeyBjaGFydCwgdmVyc2lvbiwgcGFyYW1ldGVycywgZGVwZW5kZW5jaWVzIH0sXG4gICAgfV1cblxuICAgIC8vIFRPRE86IG1ha2Ugc3VyZSBhdCBsZWFzdCBlaXRoZXIgYSBjaGFydCBpcyBzcGVjaWZpZWQsIG9yIG1vZHVsZSBjb250YWlucyBhIGhlbG0gY2hhcnRcbiAgICByZXR1cm4gbW9kdWxlQ29uZmlnXG4gIH0sXG5cbiAgZ2V0QnVpbGRTdGF0dXM6IGdldEdlbmVyaWNNb2R1bGVCdWlsZFN0YXR1cyxcbiAgYnVpbGQsXG4gIGdldFNlcnZpY2VTdGF0dXMsXG5cbiAgYXN5bmMgZGVwbG95U2VydmljZShcbiAgICB7IGN0eCwgbW9kdWxlLCBzZXJ2aWNlLCBsb2dFbnRyeSB9OiBEZXBsb3lTZXJ2aWNlUGFyYW1zPEhlbG1Nb2R1bGU+LFxuICApOiBQcm9taXNlPFNlcnZpY2VTdGF0dXM+IHtcbiAgICBjb25zdCBwcm92aWRlciA9IGN0eC5wcm92aWRlclxuICAgIGNvbnN0IGNoYXJ0UGF0aCA9IGF3YWl0IGdldENoYXJ0UGF0aChtb2R1bGUpXG4gICAgY29uc3QgdmFsdWVzUGF0aCA9IGdldFZhbHVlc1BhdGgoY2hhcnRQYXRoKVxuICAgIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcbiAgICBjb25zdCByZWxlYXNlTmFtZSA9IGdldFJlbGVhc2VOYW1lKG5hbWVzcGFjZSwgc2VydmljZSlcblxuICAgIGNvbnN0IHJlbGVhc2VTdGF0dXMgPSBhd2FpdCBnZXRSZWxlYXNlU3RhdHVzKGN0eC5wcm92aWRlciwgcmVsZWFzZU5hbWUpXG5cbiAgICBpZiAocmVsZWFzZVN0YXR1cy5zdGF0ZSA9PT0gXCJtaXNzaW5nXCIpIHtcbiAgICAgIGF3YWl0IGhlbG0ocHJvdmlkZXIsXG4gICAgICAgIFwiaW5zdGFsbFwiLCBjaGFydFBhdGgsXG4gICAgICAgIFwiLS1uYW1lXCIsIHJlbGVhc2VOYW1lLFxuICAgICAgICBcIi0tbmFtZXNwYWNlXCIsIG5hbWVzcGFjZSxcbiAgICAgICAgXCItLXZhbHVlc1wiLCB2YWx1ZXNQYXRoLFxuICAgICAgICBcIi0td2FpdFwiLFxuICAgICAgKVxuICAgIH0gZWxzZSB7XG4gICAgICBhd2FpdCBoZWxtKHByb3ZpZGVyLFxuICAgICAgICBcInVwZ3JhZGVcIiwgcmVsZWFzZU5hbWUsIGNoYXJ0UGF0aCxcbiAgICAgICAgXCItLW5hbWVzcGFjZVwiLCBuYW1lc3BhY2UsXG4gICAgICAgIFwiLS12YWx1ZXNcIiwgdmFsdWVzUGF0aCxcbiAgICAgICAgXCItLXdhaXRcIixcbiAgICAgIClcbiAgICB9XG5cbiAgICBjb25zdCBvYmplY3RzID0gYXdhaXQgZ2V0Q2hhcnRPYmplY3RzKGN0eCwgc2VydmljZSlcbiAgICBhd2FpdCB3YWl0Rm9yT2JqZWN0cyh7IGN0eCwgcHJvdmlkZXIsIHNlcnZpY2UsIG9iamVjdHMsIGxvZ0VudHJ5IH0pXG5cbiAgICByZXR1cm4ge31cbiAgfSxcblxuICBhc3luYyBkZWxldGVTZXJ2aWNlKHBhcmFtczogRGVsZXRlU2VydmljZVBhcmFtcyk6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICAgIGNvbnN0IHsgY3R4LCBsb2dFbnRyeSwgc2VydmljZSB9ID0gcGFyYW1zXG4gICAgY29uc3QgbmFtZXNwYWNlID0gYXdhaXQgZ2V0QXBwTmFtZXNwYWNlKGN0eCwgY3R4LnByb3ZpZGVyKVxuICAgIGNvbnN0IHJlbGVhc2VOYW1lID0gZ2V0UmVsZWFzZU5hbWUobmFtZXNwYWNlLCBzZXJ2aWNlKVxuICAgIGF3YWl0IGhlbG0oY3R4LnByb3ZpZGVyLCBcImRlbGV0ZVwiLCBcIi0tcHVyZ2VcIiwgcmVsZWFzZU5hbWUpXG4gICAgbG9nRW50cnkgJiYgbG9nRW50cnkuc2V0U3VjY2VzcyhcIlNlcnZpY2UgZGVsZXRlZFwiKVxuXG4gICAgcmV0dXJuIGF3YWl0IGdldFNlcnZpY2VTdGF0dXMocGFyYW1zKVxuICB9LFxufVxuXG5hc3luYyBmdW5jdGlvbiBidWlsZCh7IGN0eCwgbW9kdWxlLCBsb2dFbnRyeSB9OiBCdWlsZE1vZHVsZVBhcmFtczxIZWxtTW9kdWxlPik6IFByb21pc2U8QnVpbGRSZXN1bHQ+IHtcbiAgY29uc3QgYnVpbGRQYXRoID0gbW9kdWxlLmJ1aWxkUGF0aFxuICBjb25zdCBjb25maWcgPSBtb2R1bGVcblxuICAvLyBmZXRjaCB0aGUgY2hhcnRcbiAgY29uc3QgZmV0Y2hBcmdzID0gW1xuICAgIFwiZmV0Y2hcIiwgY29uZmlnLnNwZWMuY2hhcnQsXG4gICAgXCItLWRlc3RpbmF0aW9uXCIsIGJ1aWxkUGF0aCxcbiAgICBcIi0tdW50YXJcIixcbiAgXVxuICBpZiAoY29uZmlnLnNwZWMudmVyc2lvbikge1xuICAgIGZldGNoQXJncy5wdXNoKFwiLS12ZXJzaW9uXCIsIGNvbmZpZy5zcGVjLnZlcnNpb24pXG4gIH1cbiAgaWYgKGNvbmZpZy5zcGVjLnJlcG8pIHtcbiAgICBmZXRjaEFyZ3MucHVzaChcIi0tcmVwb1wiLCBjb25maWcuc3BlYy5yZXBvKVxuICB9XG4gIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LnNldFN0YXRlKFwiRmV0Y2hpbmcgY2hhcnQuLi5cIilcbiAgYXdhaXQgaGVsbShjdHgucHJvdmlkZXIsIC4uLmZldGNoQXJncylcblxuICBjb25zdCBjaGFydFBhdGggPSBhd2FpdCBnZXRDaGFydFBhdGgobW9kdWxlKVxuXG4gIC8vIGNyZWF0ZSB0aGUgdmFsdWVzLnltbCBmaWxlIChtZXJnZSB0aGUgY29uZmlndXJlZCBwYXJhbWV0ZXJzIGludG8gdGhlIGRlZmF1bHQgdmFsdWVzKVxuICBsb2dFbnRyeSAmJiBsb2dFbnRyeS5zZXRTdGF0ZShcIlByZXBhcmluZyBjaGFydC4uLlwiKVxuICBjb25zdCB2YWx1ZXMgPSBzYWZlTG9hZChhd2FpdCBoZWxtKGN0eC5wcm92aWRlciwgXCJpbnNwZWN0XCIsIFwidmFsdWVzXCIsIGNoYXJ0UGF0aCkpIHx8IHt9XG5cbiAgT2JqZWN0LmVudHJpZXMoZmxhdHRlblZhbHVlcyhjb25maWcuc3BlYy5wYXJhbWV0ZXJzKSlcbiAgICAubWFwKChbaywgdl0pID0+IHNldCh2YWx1ZXMsIGssIHYpKVxuXG4gIGNvbnN0IHZhbHVlc1BhdGggPSBnZXRWYWx1ZXNQYXRoKGNoYXJ0UGF0aClcbiAgYXdhaXQgZHVtcFlhbWwodmFsdWVzUGF0aCwgdmFsdWVzKVxuXG4gIC8vIGtlZXAgdHJhY2sgb2Ygd2hpY2ggdmVyc2lvbiBoYXMgYmVlbiBidWlsdFxuICBjb25zdCBidWlsZFZlcnNpb25GaWxlUGF0aCA9IGpvaW4oYnVpbGRQYXRoLCBHQVJERU5fQlVJTERfVkVSU0lPTl9GSUxFTkFNRSlcbiAgY29uc3QgdmVyc2lvbiA9IG1vZHVsZS52ZXJzaW9uXG4gIGF3YWl0IHdyaXRlVHJlZVZlcnNpb25GaWxlKGJ1aWxkVmVyc2lvbkZpbGVQYXRoLCB7XG4gICAgbGF0ZXN0Q29tbWl0OiB2ZXJzaW9uLnZlcnNpb25TdHJpbmcsXG4gICAgZGlydHlUaW1lc3RhbXA6IHZlcnNpb24uZGlydHlUaW1lc3RhbXAsXG4gIH0pXG5cbiAgcmV0dXJuIHsgZnJlc2g6IHRydWUgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gaGVsbShwcm92aWRlcjogS3ViZXJuZXRlc1Byb3ZpZGVyLCAuLi5hcmdzOiBzdHJpbmdbXSkge1xuICByZXR1cm4gZXhlY2Euc3Rkb3V0KFwiaGVsbVwiLCBbXG4gICAgXCItLWt1YmUtY29udGV4dFwiLCBwcm92aWRlci5jb25maWcuY29udGV4dCxcbiAgICAuLi5hcmdzLFxuICBdKVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRDaGFydFBhdGgobW9kdWxlOiBIZWxtTW9kdWxlKSB7XG4gIGNvbnN0IHNwbGl0TmFtZSA9IG1vZHVsZS5zcGVjLmNoYXJ0LnNwbGl0KFwiL1wiKVxuICBjb25zdCBjaGFydERpciA9IHNwbGl0TmFtZVtzcGxpdE5hbWUubGVuZ3RoIC0gMV1cbiAgcmV0dXJuIGpvaW4obW9kdWxlLmJ1aWxkUGF0aCwgY2hhcnREaXIpXG59XG5cbmZ1bmN0aW9uIGdldFZhbHVlc1BhdGgoY2hhcnRQYXRoOiBzdHJpbmcpIHtcbiAgcmV0dXJuIGpvaW4oY2hhcnRQYXRoLCBcImdhcmRlbi12YWx1ZXMueW1sXCIpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENoYXJ0T2JqZWN0cyhjdHg6IFBsdWdpbkNvbnRleHQsIHNlcnZpY2U6IFNlcnZpY2UpIHtcbiAgY29uc3QgY2hhcnRQYXRoID0gYXdhaXQgZ2V0Q2hhcnRQYXRoKHNlcnZpY2UubW9kdWxlKVxuICBjb25zdCB2YWx1ZXNQYXRoID0gZ2V0VmFsdWVzUGF0aChjaGFydFBhdGgpXG4gIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcbiAgY29uc3QgcmVsZWFzZU5hbWUgPSBnZXRSZWxlYXNlTmFtZShuYW1lc3BhY2UsIHNlcnZpY2UpXG5cbiAgY29uc3Qgb2JqZWN0cyA9IDxLdWJlcm5ldGVzT2JqZWN0W10+c2FmZUxvYWRBbGwoYXdhaXQgaGVsbShjdHgucHJvdmlkZXIsXG4gICAgXCJ0ZW1wbGF0ZVwiLFxuICAgIFwiLS1uYW1lXCIsIHJlbGVhc2VOYW1lLFxuICAgIFwiLS1uYW1lc3BhY2VcIiwgbmFtZXNwYWNlLFxuICAgIFwiLS12YWx1ZXNcIiwgdmFsdWVzUGF0aCxcbiAgICBjaGFydFBhdGgsXG4gICkpXG5cbiAgcmV0dXJuIG9iamVjdHMuZmlsdGVyKG9iaiA9PiBvYmogIT09IG51bGwpLm1hcCgob2JqKSA9PiB7XG4gICAgaWYgKCFvYmoubWV0YWRhdGEuYW5ub3RhdGlvbnMpIHtcbiAgICAgIG9iai5tZXRhZGF0YS5hbm5vdGF0aW9ucyA9IHt9XG4gICAgfVxuICAgIHJldHVybiBvYmpcbiAgfSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0U2VydmljZVN0YXR1cyhcbiAgeyBjdHgsIHNlcnZpY2UsIG1vZHVsZSwgbG9nRW50cnkgfTogR2V0U2VydmljZVN0YXR1c1BhcmFtczxIZWxtTW9kdWxlPixcbik6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICAvLyBuZWVkIHRvIGJ1aWxkIHRvIGJlIGFibGUgdG8gY2hlY2sgdGhlIHN0YXR1c1xuICBjb25zdCBidWlsZFN0YXR1cyA9IGF3YWl0IGdldEdlbmVyaWNNb2R1bGVCdWlsZFN0YXR1cyh7IGN0eCwgbW9kdWxlLCBsb2dFbnRyeSB9KVxuICBpZiAoIWJ1aWxkU3RhdHVzLnJlYWR5KSB7XG4gICAgYXdhaXQgYnVpbGQoeyBjdHgsIG1vZHVsZSwgbG9nRW50cnkgfSlcbiAgfVxuXG4gIC8vIGZpcnN0IGNoZWNrIGlmIHRoZSBpbnN0YWxsZWQgb2JqZWN0cyBvbiB0aGUgY2x1c3RlciBtYXRjaCB0aGUgY3VycmVudCBjb2RlXG4gIGNvbnN0IG9iamVjdHMgPSBhd2FpdCBnZXRDaGFydE9iamVjdHMoY3R4LCBzZXJ2aWNlKVxuICBjb25zdCBtYXRjaGVkID0gYXdhaXQgY29tcGFyZURlcGxveWVkT2JqZWN0cyhjdHgsIG9iamVjdHMpXG5cbiAgaWYgKCFtYXRjaGVkKSB7XG4gICAgcmV0dXJuIHsgc3RhdGU6IFwib3V0ZGF0ZWRcIiB9XG4gIH1cblxuICAvLyB0aGVuIGNoZWNrIGlmIHRoZSByb2xsb3V0IGlzIGNvbXBsZXRlXG4gIGNvbnN0IHZlcnNpb24gPSBtb2R1bGUudmVyc2lvblxuICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShjdHgucHJvdmlkZXIpXG4gIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcbiAgY29uc3QgeyByZWFkeSB9ID0gYXdhaXQgY2hlY2tPYmplY3RTdGF0dXMoYXBpLCBuYW1lc3BhY2UsIG9iamVjdHMpXG5cbiAgLy8gVE9ETzogc2V0IHN0YXRlIHRvIFwidW5oZWFsdGh5XCIgaWYgYW55IHN0YXR1cyBpcyBcInVuaGVhbHRoeVwiXG4gIGNvbnN0IHN0YXRlID0gcmVhZHkgPyBcInJlYWR5XCIgOiBcImRlcGxveWluZ1wiXG5cbiAgcmV0dXJuIHsgc3RhdGUsIHZlcnNpb246IHZlcnNpb24udmVyc2lvblN0cmluZyB9XG59XG5cbmZ1bmN0aW9uIGdldFJlbGVhc2VOYW1lKG5hbWVzcGFjZTogc3RyaW5nLCBzZXJ2aWNlOiBTZXJ2aWNlKSB7XG4gIHJldHVybiBgJHtuYW1lc3BhY2V9LS0ke3NlcnZpY2UubmFtZX1gXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFJlbGVhc2VTdGF0dXMocHJvdmlkZXI6IEt1YmVybmV0ZXNQcm92aWRlciwgcmVsZWFzZU5hbWU6IHN0cmluZyk6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICB0cnkge1xuICAgIGNvbnN0IHJlcyA9IEpTT04ucGFyc2UoYXdhaXQgaGVsbShwcm92aWRlciwgXCJzdGF0dXNcIiwgcmVsZWFzZU5hbWUsIFwiLS1vdXRwdXRcIiwgXCJqc29uXCIpKVxuICAgIGNvbnN0IHN0YXR1c0NvZGUgPSByZXMuaW5mby5zdGF0dXMuY29kZVxuICAgIHJldHVybiB7XG4gICAgICBzdGF0ZTogaGVsbVN0YXR1c0NvZGVNYXBbc3RhdHVzQ29kZV0sXG4gICAgICBkZXRhaWw6IHJlcyxcbiAgICB9XG4gIH0gY2F0Y2ggKF8pIHtcbiAgICAvLyByZWxlYXNlIGRvZXNuJ3QgZXhpc3RcbiAgICByZXR1cm4geyBzdGF0ZTogXCJtaXNzaW5nXCIgfVxuICB9XG59XG5cbi8vIGFkYXB0ZWQgZnJvbSBodHRwczovL2dpc3QuZ2l0aHViLmNvbS9wZW5ndWluYm95Lzc2MjE5N1xuZnVuY3Rpb24gZmxhdHRlblZhbHVlcyhvYmplY3QsIHByZWZpeCA9IFwiXCIpIHtcbiAgcmV0dXJuIE9iamVjdC5rZXlzKG9iamVjdCkucmVkdWNlKFxuICAgIChwcmV2LCBlbGVtZW50KSA9PlxuICAgICAgb2JqZWN0W2VsZW1lbnRdICYmIHR5cGVvZiBvYmplY3RbZWxlbWVudF0gPT09IFwib2JqZWN0XCIgJiYgIUFycmF5LmlzQXJyYXkob2JqZWN0W2VsZW1lbnRdKVxuICAgICAgICA/IHsgLi4ucHJldiwgLi4uZmxhdHRlblZhbHVlcyhvYmplY3RbZWxlbWVudF0sIGAke3ByZWZpeH0ke2VsZW1lbnR9LmApIH1cbiAgICAgICAgOiB7IC4uLnByZXYsIC4uLnsgW2Ake3ByZWZpeH0ke2VsZW1lbnR9YF06IG9iamVjdFtlbGVtZW50XSB9IH0sXG4gICAge30sXG4gIClcbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/ingress.d.ts b/garden-service/build/plugins/kubernetes/ingress.d.ts new file mode 100644 index 00000000000..d7eff86651e --- /dev/null +++ b/garden-service/build/plugins/kubernetes/ingress.d.ts @@ -0,0 +1,18 @@ +import { ContainerService } from "../container"; +import { ServiceIngress } from "../../types/service"; +import { KubeApi } from "./api"; +export declare function createIngresses(api: KubeApi, namespace: string, service: ContainerService): Promise<{ + apiVersion: string; + kind: string; + metadata: { + name: string; + annotations: { + "kubernetes.io/ingress.class": string; + "ingress.kubernetes.io/force-ssl-redirect": string; + }; + namespace: string; + }; + spec: any; +}[]>; +export declare function getIngresses(service: ContainerService, api: KubeApi): Promise; +//# sourceMappingURL=ingress.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/ingress.js b/garden-service/build/plugins/kubernetes/ingress.js new file mode 100644 index 00000000000..ca87f7970a6 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/ingress.js @@ -0,0 +1,180 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const util_1 = require("../../util/util"); +const Bluebird = require("bluebird"); +const exceptions_1 = require("../../exceptions"); +const certpem_1 = require("certpem"); +const secrets_1 = require("./secrets"); +const certificateHostnames = {}; +function createIngresses(api, namespace, service) { + return __awaiter(this, void 0, void 0, function* () { + if (service.spec.ingresses.length === 0) { + return []; + } + const allIngresses = yield getIngressesWithCert(service, api); + // first group ingress endpoints by certificate, so we can properly configure TLS + const groupedByCert = lodash_1.groupBy(allIngresses, e => e.certificate ? e.certificate.name : undefined); + return Bluebird.map(Object.values(groupedByCert), (certIngresses) => __awaiter(this, void 0, void 0, function* () { + // second, group ingress endpoints by hostname + const groupedByHostname = lodash_1.groupBy(certIngresses, e => e.hostname); + const rules = Object.entries(groupedByHostname).map(([host, hostnameIngresses]) => ({ + host, + http: { + paths: hostnameIngresses.map(ingress => ({ + path: ingress.path, + backend: { + serviceName: service.name, + servicePort: util_1.findByName(service.spec.ports, ingress.spec.port).containerPort, + }, + })), + }, + })); + const cert = certIngresses[0].certificate; + const annotations = { + "kubernetes.io/ingress.class": api.provider.config.ingressClass, + "ingress.kubernetes.io/force-ssl-redirect": !!cert + "", + }; + const spec = { rules }; + if (!!cert) { + // make sure the TLS secrets exist in this namespace + yield secrets_1.ensureSecret(api, cert.secretRef, namespace); + spec.tls = [{ + secretName: cert.secretRef.name, + }]; + } + return { + apiVersion: "extensions/v1beta1", + kind: "Ingress", + metadata: { + name: service.name, + annotations, + namespace, + }, + spec, + }; + })); + }); +} +exports.createIngresses = createIngresses; +function getIngress(service, api, spec) { + return __awaiter(this, void 0, void 0, function* () { + const hostname = spec.hostname || api.provider.config.defaultHostname; + if (!hostname) { + // this should be caught when parsing the module + throw new exceptions_1.PluginError(`Missing hostname in ingress spec`, { serviceSpec: service.spec, ingressSpec: spec }); + } + const certificate = yield pickCertificate(service, api, hostname); + // TODO: support other protocols + const protocol = !!certificate ? "https" : "http"; + const port = !!certificate ? api.provider.config.ingressHttpsPort : api.provider.config.ingressHttpPort; + return Object.assign({}, spec, { certificate, + hostname, path: spec.path, port, + protocol, + spec }); + }); +} +function getIngressesWithCert(service, api) { + return __awaiter(this, void 0, void 0, function* () { + return Bluebird.map(service.spec.ingresses, spec => getIngress(service, api, spec)); + }); +} +function getIngresses(service, api) { + return __awaiter(this, void 0, void 0, function* () { + return (yield getIngressesWithCert(service, api)) + .map(e => lodash_1.omit(e, ["certificate", "spec"])); + }); +} +exports.getIngresses = getIngresses; +function getCertificateHostnames(api, cert) { + return __awaiter(this, void 0, void 0, function* () { + if (cert.hostnames) { + // use explicitly specified hostnames, if given + return cert.hostnames; + } + else if (certificateHostnames[cert.name]) { + // return cached hostnames if available + return certificateHostnames[cert.name]; + } + else { + // pull secret via secret ref from k8s + let res; + try { + res = yield api.core.readNamespacedSecret(cert.secretRef.name, cert.secretRef.namespace); + } + catch (err) { + if (err.code === 404) { + throw new exceptions_1.ConfigurationError(`Cannot find Secret ${cert.secretRef.name} configured for TLS certificate ${cert.name}`, cert); + } + else { + throw err; + } + } + const secret = res.body; + if (!secret.data["tls.crt"] || !secret.data["tls.key"]) { + throw new exceptions_1.ConfigurationError(`Secret '${cert.secretRef.name}' is not a valid TLS secret (missing tls.crt and/or tls.key).`, cert); + } + const crtData = Buffer.from(secret.data["tls.crt"], "base64").toString(); + try { + // Note: Can't use the certpem.info() method here because of multiple bugs. + // And yes, this API is insane. Crypto people are bonkers. Seriously. - JE + const certInfo = certpem_1.certpem.debug(crtData); + const hostnames = []; + const commonNameField = lodash_1.find(certInfo.subject.types_and_values, ["type", "2.5.4.3"]); + if (commonNameField) { + hostnames.push(commonNameField.value.value_block.value); + } + for (const ext of certInfo.extensions || []) { + if (ext.parsedValue && ext.parsedValue.altNames) { + for (const alt of ext.parsedValue.altNames) { + hostnames.push(alt.Name); + } + } + } + certificateHostnames[cert.name] = hostnames; + return hostnames; + } + catch (error) { + throw new exceptions_1.ConfigurationError(`Unable to parse Secret '${cert.secretRef.name}' as a valid TLS certificate`, Object.assign({}, cert, { error })); + } + } + }); +} +function pickCertificate(service, api, hostname) { + return __awaiter(this, void 0, void 0, function* () { + for (const cert of api.provider.config.tlsCertificates) { + const certHostnames = yield getCertificateHostnames(api, cert); + for (const certHostname of certHostnames) { + if (certHostname === hostname + || certHostname.startsWith("*") && hostname.endsWith(certHostname.slice(1))) { + return cert; + } + } + } + if (api.provider.config.forceSsl) { + throw new exceptions_1.ConfigurationError(`Could not find certificate for hostname '${hostname}' ` + + `configured on service '${service.name}' and forceSsl flag is set.`, { + serviceName: service.name, + hostname, + }); + } + return undefined; + }); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9pbmdyZXNzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxtQ0FBNEM7QUFDNUMsMENBQTRDO0FBSTVDLHFDQUFvQztBQUVwQyxpREFBa0U7QUFDbEUscUNBQWlDO0FBQ2pDLHVDQUF3QztBQU94QyxNQUFNLG9CQUFvQixHQUFpQyxFQUFFLENBQUE7QUFFN0QsU0FBc0IsZUFBZSxDQUFDLEdBQVksRUFBRSxTQUFpQixFQUFFLE9BQXlCOztRQUM5RixJQUFJLE9BQU8sQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLE1BQU0sS0FBSyxDQUFDLEVBQUU7WUFDdkMsT0FBTyxFQUFFLENBQUE7U0FDVjtRQUVELE1BQU0sWUFBWSxHQUFHLE1BQU0sb0JBQW9CLENBQUMsT0FBTyxFQUFFLEdBQUcsQ0FBQyxDQUFBO1FBRTdELGlGQUFpRjtRQUNqRixNQUFNLGFBQWEsR0FBRyxnQkFBTyxDQUFDLFlBQVksRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxTQUFTLENBQUMsQ0FBQTtRQUVoRyxPQUFPLFFBQVEsQ0FBQyxHQUFHLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFPLGFBQWEsRUFBRSxFQUFFO1lBQ3hFLDhDQUE4QztZQUM5QyxNQUFNLGlCQUFpQixHQUFHLGdCQUFPLENBQUMsYUFBYSxFQUFFLENBQUMsQ0FBQyxFQUFFLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1lBRWpFLE1BQU0sS0FBSyxHQUFHLE1BQU0sQ0FBQyxPQUFPLENBQUMsaUJBQWlCLENBQUMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLElBQUksRUFBRSxpQkFBaUIsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxDQUFDO2dCQUNsRixJQUFJO2dCQUNK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QUksQ0FBQyxHQUFHLFNBQVMsQ0FBQTtnQkFFM0MsT0FBTyxTQUFTLENBQUE7YUFDakI7WUFBQyxPQUFPLEtBQUssRUFBRTtnQkFDZCxNQUFNLElBQUksK0JBQWtCLENBQzFCLDJCQUEyQixJQUFJLENBQUMsU0FBUyxDQUFDLElBQUksOEJBQThCLG9CQUN2RSxJQUFJLElBQUUsS0FBSyxJQUNqQixDQUFBO2FBQ0Y7U0FDRjtJQUNILENBQUM7Q0FBQTtBQUVELFNBQWUsZUFBZSxDQUM1QixPQUF5QixFQUFFLEdBQVksRUFBRSxRQUFnQjs7UUFFekQsS0FBSyxNQUFNLElBQUksSUFBSSxHQUFHLENBQUMsUUFBUSxDQUFDLE1BQU0sQ0FBQyxlQUFlLEVBQUU7WUFDdEQsTUFBTSxhQUFhLEdBQUcsTUFBTSx1QkFBdUIsQ0FBQyxHQUFHLEVBQUUsSUFBSSxDQUFDLENBQUE7WUFFOUQsS0FBSyxNQUFNLFlBQVksSUFBSSxhQUFhLEVBQUU7Z0JBQ3hDLElBQ0UsWUFBWSxLQUFLLFFBQVE7dUJBQ3RCLFlBQVksQ0FBQyxVQUFVLENBQUMsR0FBRyxDQUFDLElBQUksUUFBUSxDQUFDLFFBQVEsQ0FBQyxZQUFZLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQzNFO29CQUNBLE9BQU8sSUFBSSxDQUFBO2lCQUNaO2FBQ0Y7U0FDRjtRQUVELElBQUksR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsUUFBUSxFQUFFO1lBQ2hDLE1BQU0sSUFBSSwrQkFBa0IsQ0FDMUIsNENBQTRDLFFBQVEsSUFBSTtnQkFDeEQsMEJBQTBCLE9BQU8sQ0FBQyxJQUFJLDZCQUE2QixFQUNuRTtnQkFDRSxXQUFXLEVBQUUsT0FBTyxDQUFDLElBQUk7Z0JBQ3pCLFFBQVE7YUFDVCxDQUNGLENBQUE7U0FDRjtRQUVELE9BQU8sU0FBUyxDQUFBO0lBQ2xCLENBQUM7Q0FBQSIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvaW5ncmVzcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBncm91cEJ5LCBvbWl0LCBmaW5kIH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyBmaW5kQnlOYW1lIH0gZnJvbSBcIi4uLy4uL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBDb250YWluZXJTZXJ2aWNlLCBDb250YWluZXJJbmdyZXNzU3BlYyB9IGZyb20gXCIuLi9jb250YWluZXJcIlxuaW1wb3J0IHsgSW5ncmVzc1Rsc0NlcnRpZmljYXRlIH0gZnJvbSBcIi4va3ViZXJuZXRlc1wiXG5pbXBvcnQgeyBTZXJ2aWNlSW5ncmVzcywgU2VydmljZVByb3RvY29sIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCB7IEt1YmVBcGkgfSBmcm9tIFwiLi9hcGlcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yLCBQbHVnaW5FcnJvciB9IGZyb20gXCIuLi8uLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IGNlcnRwZW0gfSBmcm9tIFwiY2VydHBlbVwiXG5pbXBvcnQgeyBlbnN1cmVTZWNyZXQgfSBmcm9tIFwiLi9zZWNyZXRzXCJcblxuaW50ZXJmYWNlIFNlcnZpY2VJbmdyZXNzV2l0aENlcnQgZXh0ZW5kcyBTZXJ2aWNlSW5ncmVzcyB7XG4gIHNwZWM6IENvbnRhaW5lckluZ3Jlc3NTcGVjXG4gIGNlcnRpZmljYXRlPzogSW5ncmVzc1Rsc0NlcnRpZmljYXRlXG59XG5cbmNvbnN0IGNlcnRpZmljYXRlSG9zdG5hbWVzOiB7IFtuYW1lOiBzdHJpbmddOiBzdHJpbmdbXSB9ID0ge31cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZUluZ3Jlc3NlcyhhcGk6IEt1YmVBcGksIG5hbWVzcGFjZTogc3RyaW5nLCBzZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlKSB7XG4gIGlmIChzZXJ2aWNlLnNwZWMuaW5ncmVzc2VzLmxlbmd0aCA9PT0gMCkge1xuICAgIHJldHVybiBbXVxuICB9XG5cbiAgY29uc3QgYWxsSW5ncmVzc2VzID0gYXdhaXQgZ2V0SW5ncmVzc2VzV2l0aENlcnQoc2VydmljZSwgYXBpKVxuXG4gIC8vIGZpcnN0IGdyb3VwIGluZ3Jlc3MgZW5kcG9pbnRzIGJ5IGNlcnRpZmljYXRlLCBzbyB3ZSBjYW4gcHJvcGVybHkgY29uZmlndXJlIFRMU1xuICBjb25zdCBncm91cGVkQnlDZXJ0ID0gZ3JvdXBCeShhbGxJbmdyZXNzZXMsIGUgPT4gZS5jZXJ0aWZpY2F0ZSA/IGUuY2VydGlmaWNhdGUubmFtZSA6IHVuZGVmaW5lZClcblxuICByZXR1cm4gQmx1ZWJpcmQubWFwKE9iamVjdC52YWx1ZXMoZ3JvdXBlZEJ5Q2VydCksIGFzeW5jIChjZXJ0SW5ncmVzc2VzKSA9PiB7XG4gICAgLy8gc2Vjb25kLCBncm91cCBpbmdyZXNzIGVuZHBvaW50cyBieSBob3N0bmFtZVxuICAgIGNvbnN0IGdyb3VwZWRCeUhvc3RuYW1lID0gZ3JvdXBCeShjZXJ0SW5ncmVzc2VzLCBlID0+IGUuaG9zdG5hbWUpXG5cbiAgICBjb25zdCBydWxlcyA9IE9iamVjdC5lbnRyaWVzKGdyb3VwZWRCeUhvc3RuYW1lKS5tYXAoKFtob3N0LCBob3N0bmFtZUluZ3Jlc3Nlc10pID0+ICh7XG4gICAgICBob3N0LFxuICAgICAgaHR0cDoge1xuICAgICAgICBwYXRoczogaG9zdG5hbWVJbmdyZXNzZXMubWFwKGluZ3Jlc3MgPT4gKHtcbiAgICAgICAgICBwYXRoOiBpbmdyZXNzLnBhdGgsXG4gICAgICAgICAgYmFja2VuZDoge1xuICAgICAgICAgICAgc2VydmljZU5hbWU6IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICAgIHNlcnZpY2VQb3J0OiBmaW5kQnlOYW1lKHNlcnZpY2Uuc3BlYy5wb3J0cywgaW5ncmVzcy5zcGVjLnBvcnQpIS5jb250YWluZXJQb3J0LFxuICAgICAgICAgIH0sXG4gICAgICAgIH0pKSxcbiAgICAgIH0sXG4gICAgfSkpXG5cbiAgICBjb25zdCBjZXJ0ID0gY2VydEluZ3Jlc3Nlc1swXS5jZXJ0aWZpY2F0ZVxuXG4gICAgY29uc3QgYW5ub3RhdGlvbnMgPSB7XG4gICAgICBcImt1YmVybmV0ZXMuaW8vaW5ncmVzcy5jbGFzc1wiOiBhcGkucHJvdmlkZXIuY29uZmlnLmluZ3Jlc3NDbGFzcyxcbiAgICAgIFwiaW5ncmVzcy5rdWJlcm5ldGVzLmlvL2ZvcmNlLXNzbC1yZWRpcmVjdFwiOiAhIWNlcnQgKyBcIlwiLFxuICAgIH1cblxuICAgIGNvbnN0IHNwZWM6IGFueSA9IHsgcnVsZXMgfVxuXG4gICAgaWYgKCEhY2VydCkge1xuICAgICAgLy8gbWFrZSBzdXJlIHRoZSBUTFMgc2VjcmV0cyBleGlzdCBpbiB0aGlzIG5hbWVzcGFjZVxuICAgICAgYXdhaXQgZW5zdXJlU2VjcmV0KGFwaSwgY2VydC5zZWNyZXRSZWYsIG5hbWVzcGFjZSlcblxuICAgICAgc3BlYy50bHMgPSBbe1xuICAgICAgICBzZWNyZXROYW1lOiBjZXJ0LnNlY3JldFJlZi5uYW1lLFxuICAgICAgfV1cbiAgICB9XG5cbiAgICByZXR1cm4ge1xuICAgICAgYXBpVmVyc2lvbjogXCJleHRlbnNpb25zL3YxYmV0YTFcIixcbiAgICAgIGtpbmQ6IFwiSW5ncmVzc1wiLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgICBhbm5vdGF0aW9ucyxcbiAgICAgICAgbmFtZXNwYWNlLFxuICAgICAgfSxcbiAgICAgIHNwZWMsXG4gICAgfVxuICB9KVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRJbmdyZXNzKFxuICBzZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlLCBhcGk6IEt1YmVBcGksIHNwZWM6IENvbnRhaW5lckluZ3Jlc3NTcGVjLFxuKTogUHJvbWlzZTxTZXJ2aWNlSW5ncmVzc1dpdGhDZXJ0PiB7XG4gIGNvbnN0IGhvc3RuYW1lID0gc3BlYy5ob3N0bmFtZSB8fCBhcGkucHJvdmlkZXIuY29uZmlnLmRlZmF1bHRIb3N0bmFtZVxuXG4gIGlmICghaG9zdG5hbWUpIHtcbiAgICAvLyB0aGlzIHNob3VsZCBiZSBjYXVnaHQgd2hlbiBwYXJzaW5nIHRoZSBtb2R1bGVcbiAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYE1pc3NpbmcgaG9zdG5hbWUgaW4gaW5ncmVzcyBzcGVjYCwgeyBzZXJ2aWNlU3BlYzogc2VydmljZS5zcGVjLCBpbmdyZXNzU3BlYzogc3BlYyB9KVxuICB9XG5cbiAgY29uc3QgY2VydGlmaWNhdGUgPSBhd2FpdCBwaWNrQ2VydGlmaWNhdGUoc2VydmljZSwgYXBpLCBob3N0bmFtZSlcbiAgLy8gVE9ETzogc3VwcG9ydCBvdGhlciBwcm90b2NvbHNcbiAgY29uc3QgcHJvdG9jb2w6IFNlcnZpY2VQcm90b2NvbCA9ICEhY2VydGlmaWNhdGUgPyBcImh0dHBzXCIgOiBcImh0dHBcIlxuICBjb25zdCBwb3J0ID0gISFjZXJ0aWZpY2F0ZSA/IGFwaS5wcm92aWRlci5jb25maWcuaW5ncmVzc0h0dHBzUG9ydCA6IGFwaS5wcm92aWRlci5jb25maWcuaW5ncmVzc0h0dHBQb3J0XG5cbiAgcmV0dXJuIHtcbiAgICAuLi5zcGVjLFxuICAgIGNlcnRpZmljYXRlLFxuICAgIGhvc3RuYW1lLFxuICAgIHBhdGg6IHNwZWMucGF0aCxcbiAgICBwb3J0LFxuICAgIHByb3RvY29sLFxuICAgIHNwZWMsXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SW5ncmVzc2VzV2l0aENlcnQoc2VydmljZTogQ29udGFpbmVyU2VydmljZSwgYXBpOiBLdWJlQXBpKTogUHJvbWlzZTxTZXJ2aWNlSW5ncmVzc1dpdGhDZXJ0W10+IHtcbiAgcmV0dXJuIEJsdWViaXJkLm1hcChzZXJ2aWNlLnNwZWMuaW5ncmVzc2VzLCBzcGVjID0+IGdldEluZ3Jlc3Moc2VydmljZSwgYXBpLCBzcGVjKSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEluZ3Jlc3NlcyhzZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlLCBhcGk6IEt1YmVBcGkpOiBQcm9taXNlPFNlcnZpY2VJbmdyZXNzW10+IHtcbiAgcmV0dXJuIChhd2FpdCBnZXRJbmdyZXNzZXNXaXRoQ2VydChzZXJ2aWNlLCBhcGkpKVxuICAgIC5tYXAoZSA9PiBvbWl0KGUsIFtcImNlcnRpZmljYXRlXCIsIFwic3BlY1wiXSkpXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldENlcnRpZmljYXRlSG9zdG5hbWVzKGFwaTogS3ViZUFwaSwgY2VydDogSW5ncmVzc1Rsc0NlcnRpZmljYXRlKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBpZiAoY2VydC5ob3N0bmFtZXMpIHtcbiAgICAvLyB1c2UgZXhwbGljaXRseSBzcGVjaWZpZWQgaG9zdG5hbWVzLCBpZiBnaXZlblxuICAgIHJldHVybiBjZXJ0Lmhvc3RuYW1lc1xuICB9IGVsc2UgaWYgKGNlcnRpZmljYXRlSG9zdG5hbWVzW2NlcnQubmFtZV0pIHtcbiAgICAvLyByZXR1cm4gY2FjaGVkIGhvc3RuYW1lcyBpZiBhdmFpbGFibGVcbiAgICByZXR1cm4gY2VydGlmaWNhdGVIb3N0bmFtZXNbY2VydC5uYW1lXVxuICB9IGVsc2Uge1xuICAgIC8vIHB1bGwgc2VjcmV0IHZpYSBzZWNyZXQgcmVmIGZyb20gazhzXG4gICAgbGV0IHJlc1xuXG4gICAgdHJ5IHtcbiAgICAgIHJlcyA9IGF3YWl0IGFwaS5jb3JlLnJlYWROYW1lc3BhY2VkU2VjcmV0KGNlcnQuc2VjcmV0UmVmLm5hbWUsIGNlcnQuc2VjcmV0UmVmLm5hbWVzcGFjZSlcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIGlmIChlcnIuY29kZSA9PT0gNDA0KSB7XG4gICAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICAgICAgYENhbm5vdCBmaW5kIFNlY3JldCAke2NlcnQuc2VjcmV0UmVmLm5hbWV9IGNvbmZpZ3VyZWQgZm9yIFRMUyBjZXJ0aWZpY2F0ZSAke2NlcnQubmFtZX1gLFxuICAgICAgICAgIGNlcnQsXG4gICAgICAgIClcbiAgICAgIH0gZWxzZSB7XG4gICAgICAgIHRocm93IGVyclxuICAgICAgfVxuICAgIH1cbiAgICBjb25zdCBzZWNyZXQgPSByZXMuYm9keVxuXG4gICAgaWYgKCFzZWNyZXQuZGF0YVtcInRscy5jcnRcIl0gfHwgIXNlY3JldC5kYXRhW1widGxzLmtleVwiXSkge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgYFNlY3JldCAnJHtjZXJ0LnNlY3JldFJlZi5uYW1lfScgaXMgbm90IGEgdmFsaWQgVExTIHNlY3JldCAobWlzc2luZyB0bHMuY3J0IGFuZC9vciB0bHMua2V5KS5gLFxuICAgICAgICBjZXJ0LFxuICAgICAgKVxuICAgIH1cblxuICAgIGNvbnN0IGNydERhdGEgPSBCdWZmZXIuZnJvbShzZWNyZXQuZGF0YVtcInRscy5jcnRcIl0sIFwiYmFzZTY0XCIpLnRvU3RyaW5nKClcblxuICAgIHRyeSB7XG4gICAgICAvLyBOb3RlOiBDYW4ndCB1c2UgdGhlIGNlcnRwZW0uaW5mbygpIG1ldGhvZCBoZXJlIGJlY2F1c2Ugb2YgbXVsdGlwbGUgYnVncy5cbiAgICAgIC8vIEFuZCB5ZXMsIHRoaXMgQVBJIGlzIGluc2FuZS4gQ3J5cHRvIHBlb3BsZSBhcmUgYm9ua2Vycy4gU2VyaW91c2x5LiAtIEpFXG4gICAgICBjb25zdCBjZXJ0SW5mbyA9IGNlcnRwZW0uZGVidWcoY3J0RGF0YSlcblxuICAgICAgY29uc3QgaG9zdG5hbWVzOiBzdHJpbmdbXSA9IFtdXG5cbiAgICAgIGNvbnN0IGNvbW1vbk5hbWVGaWVsZCA9IGZpbmQoY2VydEluZm8uc3ViamVjdC50eXBlc19hbmRfdmFsdWVzLCBbXCJ0eXBlXCIsIFwiMi41LjQuM1wiXSlcbiAgICAgIGlmIChjb21tb25OYW1lRmllbGQpIHtcbiAgICAgICAgaG9zdG5hbWVzLnB1c2goY29tbW9uTmFtZUZpZWxkLnZhbHVlLnZhbHVlX2Jsb2NrLnZhbHVlKVxuICAgICAgfVxuXG4gICAgICBmb3IgKGNvbnN0IGV4dCBvZiBjZXJ0SW5mby5leHRlbnNpb25zIHx8IFtdKSB7XG4gICAgICAgIGlmIChleHQucGFyc2VkVmFsdWUgJiYgZXh0LnBhcnNlZFZhbHVlLmFsdE5hbWVzKSB7XG4gICAgICAgICAgZm9yIChjb25zdCBhbHQgb2YgZXh0LnBhcnNlZFZhbHVlLmFsdE5hbWVzKSB7XG4gICAgICAgICAgICBob3N0bmFtZXMucHVzaChhbHQuTmFtZSlcbiAgICAgICAgICB9XG4gICAgICAgIH1cbiAgICAgIH1cblxuICAgICAgY2VydGlmaWNhdGVIb3N0bmFtZXNbY2VydC5uYW1lXSA9IGhvc3RuYW1lc1xuXG4gICAgICByZXR1cm4gaG9zdG5hbWVzXG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICAgIGBVbmFibGUgdG8gcGFyc2UgU2VjcmV0ICcke2NlcnQuc2VjcmV0UmVmLm5hbWV9JyBhcyBhIHZhbGlkIFRMUyBjZXJ0aWZpY2F0ZWAsXG4gICAgICAgIHsgLi4uY2VydCwgZXJyb3IgfSxcbiAgICAgIClcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcGlja0NlcnRpZmljYXRlKFxuICBzZXJ2aWNlOiBDb250YWluZXJTZXJ2aWNlLCBhcGk6IEt1YmVBcGksIGhvc3RuYW1lOiBzdHJpbmcsXG4pOiBQcm9taXNlPEluZ3Jlc3NUbHNDZXJ0aWZpY2F0ZSB8IHVuZGVmaW5lZD4ge1xuICBmb3IgKGNvbnN0IGNlcnQgb2YgYXBpLnByb3ZpZGVyLmNvbmZpZy50bHNDZXJ0aWZpY2F0ZXMpIHtcbiAgICBjb25zdCBjZXJ0SG9zdG5hbWVzID0gYXdhaXQgZ2V0Q2VydGlmaWNhdGVIb3N0bmFtZXMoYXBpLCBjZXJ0KVxuXG4gICAgZm9yIChjb25zdCBjZXJ0SG9zdG5hbWUgb2YgY2VydEhvc3RuYW1lcykge1xuICAgICAgaWYgKFxuICAgICAgICBjZXJ0SG9zdG5hbWUgPT09IGhvc3RuYW1lXG4gICAgICAgIHx8IGNlcnRIb3N0bmFtZS5zdGFydHNXaXRoKFwiKlwiKSAmJiBob3N0bmFtZS5lbmRzV2l0aChjZXJ0SG9zdG5hbWUuc2xpY2UoMSkpXG4gICAgICApIHtcbiAgICAgICAgcmV0dXJuIGNlcnRcbiAgICAgIH1cbiAgICB9XG4gIH1cblxuICBpZiAoYXBpLnByb3ZpZGVyLmNvbmZpZy5mb3JjZVNzbCkge1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICBgQ291bGQgbm90IGZpbmQgY2VydGlmaWNhdGUgZm9yIGhvc3RuYW1lICcke2hvc3RuYW1lfScgYCArXG4gICAgICBgY29uZmlndXJlZCBvbiBzZXJ2aWNlICcke3NlcnZpY2UubmFtZX0nIGFuZCBmb3JjZVNzbCBmbGFnIGlzIHNldC5gLFxuICAgICAge1xuICAgICAgICBzZXJ2aWNlTmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgICBob3N0bmFtZSxcbiAgICAgIH0sXG4gICAgKVxuICB9XG5cbiAgcmV0dXJuIHVuZGVmaW5lZFxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/init.d.ts b/garden-service/build/plugins/kubernetes/init.d.ts new file mode 100644 index 00000000000..213de36fba1 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/init.d.ts @@ -0,0 +1,13 @@ +import { PrepareEnvironmentParams, CleanupEnvironmentParams, GetEnvironmentStatusParams } from "../../types/plugin/params"; +export declare function getRemoteEnvironmentStatus({ ctx }: GetEnvironmentStatusParams): Promise<{ + ready: boolean; + needUserInput: boolean; +}>; +export declare function getLocalEnvironmentStatus({ ctx }: GetEnvironmentStatusParams): Promise<{ + ready: boolean; + needUserInput: boolean; +}>; +export declare function prepareRemoteEnvironment({ ctx, logEntry }: PrepareEnvironmentParams): Promise<{}>; +export declare function prepareLocalEnvironment({ ctx, force, logEntry }: PrepareEnvironmentParams): Promise<{}>; +export declare function cleanupEnvironment({ ctx, logEntry }: CleanupEnvironmentParams): Promise<{}>; +//# sourceMappingURL=init.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/init.js b/garden-service/build/plugins/kubernetes/init.js new file mode 100644 index 00000000000..3c3ee1c348a --- /dev/null +++ b/garden-service/build/plugins/kubernetes/init.js @@ -0,0 +1,275 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const inquirer = require("inquirer"); +const Joi = require("joi"); +const lodash_1 = require("lodash"); +const exceptions_1 = require("../../exceptions"); +const util_1 = require("../../util/util"); +const common_1 = require("../../config/common"); +const api_1 = require("./api"); +const namespace_1 = require("./namespace"); +const kubectl_1 = require("./kubectl"); +const kubernetes_1 = require("./kubernetes"); +const system_1 = require("./system"); +const helm_1 = require("./helm"); +const MAX_STORED_USERNAMES = 5; +/** + * Used by both the remote and local plugin + */ +function prepareNamespaces({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + const kubeContext = ctx.provider.config.context; + try { + // TODO: use API instead of kubectl (I just couldn't find which API call to make) + yield kubectl_1.kubectl(kubeContext).call(["version"]); + } + catch (err) { + // TODO: catch error properly + if (err.detail.output) { + throw new exceptions_1.DeploymentError(`Unable to connect to Kubernetes cluster. ` + + `Please make sure it is running, reachable and that you have the right context configured.`, { + kubeContext, + kubectlOutput: err.detail.output, + }); + } + throw err; + } + yield Bluebird.all([ + namespace_1.getMetadataNamespace(ctx, ctx.provider), + namespace_1.getAppNamespace(ctx, ctx.provider), + ]); + }); +} +function getRemoteEnvironmentStatus({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + const loggedIn = yield getLoginStatus({ ctx }); + if (!loggedIn) { + return { + ready: false, + needUserInput: true, + }; + } + yield prepareNamespaces({ ctx }); + return { + ready: true, + needUserInput: false, + }; + }); +} +exports.getRemoteEnvironmentStatus = getRemoteEnvironmentStatus; +function getLocalEnvironmentStatus({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + let ready = true; + let needUserInput = false; + yield prepareNamespaces({ ctx }); + // TODO: check if mkcert has been installed + // TODO: check if all certs have been generated + // check if system services are deployed + if (!system_1.isSystemGarden(ctx.provider)) { + const sysGarden = yield system_1.getSystemGarden(ctx.provider); + const sysStatus = yield sysGarden.actions.getStatus(); + const systemReady = sysStatus.providers[ctx.provider.config.name].ready && + lodash_1.every(lodash_1.values(sysStatus.services).map(s => s.state === "ready")); + if (!systemReady) { + ready = false; + } + } + return { + ready, + needUserInput, + }; + }); +} +exports.getLocalEnvironmentStatus = getLocalEnvironmentStatus; +function prepareRemoteEnvironment({ ctx, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const loggedIn = yield getLoginStatus({ ctx, logEntry }); + if (!loggedIn) { + yield login({ ctx, logEntry }); + } + return {}; + }); +} +exports.prepareRemoteEnvironment = prepareRemoteEnvironment; +function prepareLocalEnvironment({ ctx, force, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + // make sure system services are deployed + if (!system_1.isSystemGarden(ctx.provider)) { + yield configureSystemServices({ ctx, force, logEntry }); + } + // TODO: make sure all certs have been generated + return {}; + }); +} +exports.prepareLocalEnvironment = prepareLocalEnvironment; +function cleanupEnvironment({ ctx, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const api = new api_1.KubeApi(ctx.provider); + const namespace = yield namespace_1.getAppNamespace(ctx, ctx.provider); + const entry = logEntry && logEntry.info({ + section: "kubernetes", + msg: `Deleting namespace ${namespace} (this may take a while)`, + status: "active", + }); + try { + // Note: Need to call the delete method with an empty object + // TODO: any cast is required until https://github.com/kubernetes-client/javascript/issues/52 is fixed + yield api.core.deleteNamespace(namespace, {}); + } + catch (err) { + entry && entry.setError(err.message); + const availableNamespaces = yield namespace_1.getAllGardenNamespaces(api); + throw new exceptions_1.NotFoundError(err, { namespace, availableNamespaces }); + } + yield logout({ ctx, logEntry }); + // Wait until namespace has been deleted + const startTime = new Date().getTime(); + while (true) { + yield util_1.sleep(2000); + const nsNames = yield namespace_1.getAllGardenNamespaces(api); + if (!nsNames.includes(namespace)) { + break; + } + const now = new Date().getTime(); + if (now - startTime > kubectl_1.KUBECTL_DEFAULT_TIMEOUT * 1000) { + throw new exceptions_1.TimeoutError(`Timed out waiting for namespace ${namespace} delete to complete`, { namespace }); + } + } + return {}; + }); +} +exports.cleanupEnvironment = cleanupEnvironment; +function getLoginStatus({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + const localConfig = yield ctx.localConfigStore.get(); + let currentUsername; + if (localConfig.kubernetes) { + currentUsername = localConfig.kubernetes.username; + } + return !!currentUsername; + }); +} +function login({ ctx, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const entry = logEntry && logEntry.info({ section: "kubernetes", msg: "Logging in..." }); + const localConfig = yield ctx.localConfigStore.get(); + let currentUsername; + let prevUsernames = []; + if (localConfig.kubernetes) { + currentUsername = localConfig.kubernetes.username; + prevUsernames = localConfig.kubernetes["previous-usernames"] || []; + } + if (currentUsername) { + entry && entry.setDone({ + symbol: "info", + msg: `Already logged in as user ${currentUsername}`, + }); + return { loggedIn: true }; + } + const promptName = "username"; + const newUserOption = "Add new user"; + let ans; + const inputPrompt = () => __awaiter(this, void 0, void 0, function* () { + return inquirer.prompt({ + name: promptName, + message: "Enter username", + validate: input => { + try { + Joi.attempt(input.trim(), common_1.joiIdentifier()); + } + catch (err) { + return `Invalid username, please try again\nError: ${err.message}`; + } + return true; + }, + }); + }); + const choicesPrompt = () => __awaiter(this, void 0, void 0, function* () { + return inquirer.prompt({ + name: promptName, + type: "list", + message: "Log in as...", + choices: [...prevUsernames, new inquirer.Separator(), newUserOption], + }); + }); + if (prevUsernames.length > 0) { + ans = (yield choicesPrompt()); + if (ans.username === newUserOption) { + ans = (yield inputPrompt()); + } + } + else { + ans = (yield inputPrompt()); + } + const username = ans.username.trim(); + const newPrevUsernames = lodash_1.uniq([...prevUsernames, username].slice(-MAX_STORED_USERNAMES)); + yield ctx.localConfigStore.set([ + { keyPath: [kubernetes_1.name, "username"], value: username }, + { keyPath: [kubernetes_1.name, "previous-usernames"], value: newPrevUsernames }, + ]); + return { loggedIn: true }; + }); +} +function logout({ ctx, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const entry = logEntry && logEntry.info({ section: "kubernetes", msg: "Logging out..." }); + const localConfig = yield ctx.localConfigStore.get(); + const k8sConfig = localConfig.kubernetes || {}; + if (k8sConfig.username) { + yield ctx.localConfigStore.delete([kubernetes_1.name, "username"]); + entry && entry.setSuccess("Logged out"); + } + else { + entry && entry.setSuccess("Already logged out"); + } + }); +} +function configureSystemServices({ ctx, force, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const provider = ctx.provider; + const sysGarden = yield system_1.getSystemGarden(provider); + const sysCtx = sysGarden.getPluginContext(provider.name); + // TODO: need to add logic here to wait for tiller to be ready + yield helm_1.helm(sysCtx.provider, "init", "--wait", "--service-account", "default", "--upgrade"); + const sysStatus = yield getLocalEnvironmentStatus({ + ctx: sysCtx, + logEntry, + }); + yield prepareLocalEnvironment({ + ctx: sysCtx, + force, + status: sysStatus, + logEntry, + }); + // only deploy services if configured to do so (minikube bundles the required services as addons) + if (!provider.config._systemServices || provider.config._systemServices.length > 0) { + const results = yield sysGarden.actions.deployServices({ + serviceNames: provider.config._systemServices, + }); + const failed = lodash_1.values(results.taskResults).filter(r => !!r.error).length; + if (failed) { + throw new exceptions_1.PluginError(`local-kubernetes: ${failed} errors occurred when configuring environment`, { + results, + }); + } + } + }); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9pbml0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxxQ0FBb0M7QUFDcEMscUNBQW9DO0FBQ3BDLDJCQUEwQjtBQUMxQixtQ0FBNEM7QUFFNUMsaURBQTRGO0FBTzVGLDBDQUF1QztBQUN2QyxnREFBbUQ7QUFDbkQsK0JBQStCO0FBQy9CLDJDQUlvQjtBQUNwQix1Q0FBNEQ7QUFDNUQsNkNBQW1EO0FBQ25ELHFDQUEwRDtBQUcxRCxpQ0FBNkI7QUFFN0IsTUFBTSxvQkFBb0IsR0FBRyxDQUFDLENBQUE7QUFFOUI7O0dBRUc7QUFDSCxTQUFlLGlCQUFpQixDQUFDLEVBQUUsR0FBRyxFQUE4Qjs7UUFDbEUsTUFBTSxXQUFXLEdBQUcsR0FBRyxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFBO1FBRS9DLElBQUk7WUFDRixpRkFBaUY7WUFDakYsTUFBTSxpQkFBTyxDQUFDLFdBQVcsQ0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUE7U0FDN0M7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLDZCQUE2QjtZQUM3QixJQUFJLEdBQUcsQ0FBQyxNQUFNLENBQUMsTUFBTSxFQUFFO2dCQUNyQixNQUFNLElBQUksNEJBQWUsQ0FDdkIsMkNBQTJDO29CQUMzQywyRkFBMkYsRUFDM0Y7b0JBQ0UsV0FBVztvQkFDWCxhQUFhLEVBQUUsR0FBRyxDQUFDLE1BQU0sQ0FBQyxNQUFNO2lCQUNqQyxDQUNGLENBQUE7YUFDRjtZQUNELE1BQU0sR0FBRyxDQUFBO1NBQ1Y7UUFFRCxNQUFNLFFBQVEsQ0FBQyxHQUFHLENBQUM7WUFDakIsZ0NBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUM7WUFDdkMsMkJBQWUsQ0FBQyxHQUFHLEVBQUUsR0FBRyxDQUFDLFFBQVEsQ0FBQztTQUNuQyxDQUFDLENBQUE7SUFDSixDQUFDO0NBQUE7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LENBQUE7WUFFeEUsSUFBSSxNQUFNLEVBQUU7Z0JBQ1YsTUFBTSxJQUFJLHdCQUFXLENBQUMscUJBQXFCLE1BQU0sK0NBQStDLEVBQUU7b0JBQ2hHLE9BQU87aUJBQ1IsQ0FBQyxDQUFBO2FBQ0g7U0FDRjtJQUNILENBQUM7Q0FBQSIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvaW5pdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuaW1wb3J0ICogYXMgaW5xdWlyZXIgZnJvbSBcImlucXVpcmVyXCJcbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IHVuaXEsIGV2ZXJ5LCB2YWx1ZXMgfSBmcm9tIFwibG9kYXNoXCJcblxuaW1wb3J0IHsgRGVwbG95bWVudEVycm9yLCBOb3RGb3VuZEVycm9yLCBUaW1lb3V0RXJyb3IsIFBsdWdpbkVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHtcbiAgUHJlcGFyZUVudmlyb25tZW50UGFyYW1zLFxuICBDbGVhbnVwRW52aXJvbm1lbnRQYXJhbXMsXG4gIEdldEVudmlyb25tZW50U3RhdHVzUGFyYW1zLFxuICBQbHVnaW5BY3Rpb25QYXJhbXNCYXNlLFxufSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgam9pSWRlbnRpZmllciB9IGZyb20gXCIuLi8uLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IEt1YmVBcGkgfSBmcm9tIFwiLi9hcGlcIlxuaW1wb3J0IHtcbiAgZ2V0QXBwTmFtZXNwYWNlLFxuICBnZXRNZXRhZGF0YU5hbWVzcGFjZSxcbiAgZ2V0QWxsR2FyZGVuTmFtZXNwYWNlcyxcbn0gZnJvbSBcIi4vbmFtZXNwYWNlXCJcbmltcG9ydCB7IEtVQkVDVExfREVGQVVMVF9USU1FT1VULCBrdWJlY3RsIH0gZnJvbSBcIi4va3ViZWN0bFwiXG5pbXBvcnQgeyBuYW1lIGFzIHByb3ZpZGVyTmFtZSB9IGZyb20gXCIuL2t1YmVybmV0ZXNcIlxuaW1wb3J0IHsgaXNTeXN0ZW1HYXJkZW4sIGdldFN5c3RlbUdhcmRlbiB9IGZyb20gXCIuL3N5c3RlbVwiXG5pbXBvcnQgeyBQbHVnaW5Db250ZXh0IH0gZnJvbSBcIi4uLy4uL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7IExvZ0VudHJ5IH0gZnJvbSBcIi4uLy4uL2xvZ2dlci9sb2ctZW50cnlcIlxuaW1wb3J0IHsgaGVsbSB9IGZyb20gXCIuL2hlbG1cIlxuXG5jb25zdCBNQVhfU1RPUkVEX1VTRVJOQU1FUyA9IDVcblxuLyoqXG4gKiBVc2VkIGJ5IGJvdGggdGhlIHJlbW90ZSBhbmQgbG9jYWwgcGx1Z2luXG4gKi9cbmFzeW5jIGZ1bmN0aW9uIHByZXBhcmVOYW1lc3BhY2VzKHsgY3R4IH06IEdldEVudmlyb25tZW50U3RhdHVzUGFyYW1zKSB7XG4gIGNvbnN0IGt1YmVDb250ZXh0ID0gY3R4LnByb3ZpZGVyLmNvbmZpZy5jb250ZXh0XG5cbiAgdHJ5IHtcbiAgICAvLyBUT0RPOiB1c2UgQVBJIGluc3RlYWQgb2Yga3ViZWN0bCAoSSBqdXN0IGNvdWxkbid0IGZpbmQgd2hpY2ggQVBJIGNhbGwgdG8gbWFrZSlcbiAgICBhd2FpdCBrdWJlY3RsKGt1YmVDb250ZXh0KS5jYWxsKFtcInZlcnNpb25cIl0pXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIC8vIFRPRE86IGNhdGNoIGVycm9yIHByb3Blcmx5XG4gICAgaWYgKGVyci5kZXRhaWwub3V0cHV0KSB7XG4gICAgICB0aHJvdyBuZXcgRGVwbG95bWVudEVycm9yKFxuICAgICAgICBgVW5hYmxlIHRvIGNvbm5lY3QgdG8gS3ViZXJuZXRlcyBjbHVzdGVyLiBgICtcbiAgICAgICAgYFBsZWFzZSBtYWtlIHN1cmUgaXQgaXMgcnVubmluZywgcmVhY2hhYmxlIGFuZCB0aGF0IHlvdSBoYXZlIHRoZSByaWdodCBjb250ZXh0IGNvbmZpZ3VyZWQuYCxcbiAgICAgICAge1xuICAgICAgICAgIGt1YmVDb250ZXh0LFxuICAgICAgICAgIGt1YmVjdGxPdXRwdXQ6IGVyci5kZXRhaWwub3V0cHV0LFxuICAgICAgICB9LFxuICAgICAgKVxuICAgIH1cbiAgICB0aHJvdyBlcnJcbiAgfVxuXG4gIGF3YWl0IEJsdWViaXJkLmFsbChbXG4gICAgZ2V0TWV0YWRhdGFOYW1lc3BhY2UoY3R4LCBjdHgucHJvdmlkZXIpLFxuICAgIGdldEFwcE5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlciksXG4gIF0pXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRSZW1vdGVFbnZpcm9ubWVudFN0YXR1cyh7IGN0eCB9OiBHZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtcykge1xuICBjb25zdCBsb2dnZWRJbiA9IGF3YWl0IGdldExvZ2luU3RhdHVzKHsgY3R4IH0pXG5cbiAgaWYgKCFsb2dnZWRJbikge1xuICAgIHJldHVybiB7XG4gICAgICByZWFkeTogZmFsc2UsXG4gICAgICBuZWVkVXNlcklucHV0OiB0cnVlLFxuICAgIH1cbiAgfVxuXG4gIGF3YWl0IHByZXBhcmVOYW1lc3BhY2VzKHsgY3R4IH0pXG5cbiAgcmV0dXJuIHtcbiAgICByZWFkeTogdHJ1ZSxcbiAgICBuZWVkVXNlcklucHV0OiBmYWxzZSxcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZ2V0TG9jYWxFbnZpcm9ubWVudFN0YXR1cyh7IGN0eCB9OiBHZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtcykge1xuICBsZXQgcmVhZHkgPSB0cnVlXG4gIGxldCBuZWVkVXNlcklucHV0ID0gZmFsc2VcblxuICBhd2FpdCBwcmVwYXJlTmFtZXNwYWNlcyh7IGN0eCB9KVxuXG4gIC8vIFRPRE86IGNoZWNrIGlmIG1rY2VydCBoYXMgYmVlbiBpbnN0YWxsZWRcbiAgLy8gVE9ETzogY2hlY2sgaWYgYWxsIGNlcnRzIGhhdmUgYmVlbiBnZW5lcmF0ZWRcblxuICAvLyBjaGVjayBpZiBzeXN0ZW0gc2VydmljZXMgYXJlIGRlcGxveWVkXG4gIGlmICghaXNTeXN0ZW1HYXJkZW4oY3R4LnByb3ZpZGVyKSkge1xuICAgIGNvbnN0IHN5c0dhcmRlbiA9IGF3YWl0IGdldFN5c3RlbUdhcmRlbihjdHgucHJvdmlkZXIpXG4gICAgY29uc3Qgc3lzU3RhdHVzID0gYXdhaXQgc3lzR2FyZGVuLmFjdGlvbnMuZ2V0U3RhdHVzKClcblxuICAgIGNvbnN0IHN5c3RlbVJlYWR5ID0gc3lzU3RhdHVzLnByb3ZpZGVyc1tjdHgucHJvdmlkZXIuY29uZmlnLm5hbWVdLnJlYWR5ICYmXG4gICAgICBldmVyeSh2YWx1ZXMoc3lzU3RhdHVzLnNlcnZpY2VzKS5tYXAocyA9PiBzLnN0YXRlID09PSBcInJlYWR5XCIpKVxuXG4gICAgaWYgKCFzeXN0ZW1SZWFkeSkge1xuICAgICAgcmVhZHkgPSBmYWxzZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgcmVhZHksXG4gICAgbmVlZFVzZXJJbnB1dCxcbiAgfVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcHJlcGFyZVJlbW90ZUVudmlyb25tZW50KHsgY3R4LCBsb2dFbnRyeSB9OiBQcmVwYXJlRW52aXJvbm1lbnRQYXJhbXMpIHtcbiAgY29uc3QgbG9nZ2VkSW4gPSBhd2FpdCBnZXRMb2dpblN0YXR1cyh7IGN0eCwgbG9nRW50cnkgfSlcblxuICBpZiAoIWxvZ2dlZEluKSB7XG4gICAgYXdhaXQgbG9naW4oeyBjdHgsIGxvZ0VudHJ5IH0pXG4gIH1cblxuICByZXR1cm4ge31cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByZXBhcmVMb2NhbEVudmlyb25tZW50KHsgY3R4LCBmb3JjZSwgbG9nRW50cnkgfTogUHJlcGFyZUVudmlyb25tZW50UGFyYW1zKSB7XG4gIC8vIG1ha2Ugc3VyZSBzeXN0ZW0gc2VydmljZXMgYXJlIGRlcGxveWVkXG4gIGlmICghaXNTeXN0ZW1HYXJkZW4oY3R4LnByb3ZpZGVyKSkge1xuICAgIGF3YWl0IGNvbmZpZ3VyZVN5c3RlbVNlcnZpY2VzKHsgY3R4LCBmb3JjZSwgbG9nRW50cnkgfSlcbiAgfVxuXG4gIC8vIFRPRE86IG1ha2Ugc3VyZSBhbGwgY2VydHMgaGF2ZSBiZWVuIGdlbmVyYXRlZFxuICByZXR1cm4ge31cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNsZWFudXBFbnZpcm9ubWVudCh7IGN0eCwgbG9nRW50cnkgfTogQ2xlYW51cEVudmlyb25tZW50UGFyYW1zKSB7XG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKGN0eC5wcm92aWRlcilcbiAgY29uc3QgbmFtZXNwYWNlID0gYXdhaXQgZ2V0QXBwTmFtZXNwYWNlKGN0eCwgY3R4LnByb3ZpZGVyKVxuICBjb25zdCBlbnRyeSA9IGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LmluZm8oe1xuICAgIHNlY3Rpb246IFwia3ViZXJuZXRlc1wiLFxuICAgIG1zZzogYERlbGV0aW5nIG5hbWVzcGFjZSAke25hbWVzcGFjZX0gKHRoaXMgbWF5IHRha2UgYSB3aGlsZSlgLFxuICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgfSlcblxuICB0cnkge1xuICAgIC8vIE5vdGU6IE5lZWQgdG8gY2FsbCB0aGUgZGVsZXRlIG1ldGhvZCB3aXRoIGFuIGVtcHR5IG9iamVjdFxuICAgIC8vIFRPRE86IGFueSBjYXN0IGlzIHJlcXVpcmVkIHVudGlsIGh0dHBzOi8vZ2l0aHViLmNvbS9rdWJlcm5ldGVzLWNsaWVudC9qYXZhc2NyaXB0L2lzc3Vlcy81MiBpcyBmaXhlZFxuICAgIGF3YWl0IGFwaS5jb3JlLmRlbGV0ZU5hbWVzcGFjZShuYW1lc3BhY2UsIDxhbnk+e30pXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGVudHJ5ICYmIGVudHJ5LnNldEVycm9yKGVyci5tZXNzYWdlKVxuICAgIGNvbnN0IGF2YWlsYWJsZU5hbWVzcGFjZXMgPSBhd2FpdCBnZXRBbGxHYXJkZW5OYW1lc3BhY2VzKGFwaSlcbiAgICB0aHJvdyBuZXcgTm90Rm91bmRFcnJvcihlcnIsIHsgbmFtZXNwYWNlLCBhdmFpbGFibGVOYW1lc3BhY2VzIH0pXG4gIH1cblxuICBhd2FpdCBsb2dvdXQoeyBjdHgsIGxvZ0VudHJ5IH0pXG5cbiAgLy8gV2FpdCB1bnRpbCBuYW1lc3BhY2UgaGFzIGJlZW4gZGVsZXRlZFxuICBjb25zdCBzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKVxuICB3aGlsZSAodHJ1ZSkge1xuICAgIGF3YWl0IHNsZWVwKDIwMDApXG5cbiAgICBjb25zdCBuc05hbWVzID0gYXdhaXQgZ2V0QWxsR2FyZGVuTmFtZXNwYWNlcyhhcGkpXG4gICAgaWYgKCFuc05hbWVzLmluY2x1ZGVzKG5hbWVzcGFjZSkpIHtcbiAgICAgIGJyZWFrXG4gICAgfVxuXG4gICAgY29uc3Qgbm93ID0gbmV3IERhdGUoKS5nZXRUaW1lKClcbiAgICBpZiAobm93IC0gc3RhcnRUaW1lID4gS1VCRUNUTF9ERUZBVUxUX1RJTUVPVVQgKiAxMDAwKSB7XG4gICAgICB0aHJvdyBuZXcgVGltZW91dEVycm9yKFxuICAgICAgICBgVGltZWQgb3V0IHdhaXRpbmcgZm9yIG5hbWVzcGFjZSAke25hbWVzcGFjZX0gZGVsZXRlIHRvIGNvbXBsZXRlYCxcbiAgICAgICAgeyBuYW1lc3BhY2UgfSxcbiAgICAgIClcbiAgICB9XG4gIH1cblxuICByZXR1cm4ge31cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0TG9naW5TdGF0dXMoeyBjdHggfTogUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSkge1xuICBjb25zdCBsb2NhbENvbmZpZyA9IGF3YWl0IGN0eC5sb2NhbENvbmZpZ1N0b3JlLmdldCgpXG4gIGxldCBjdXJyZW50VXNlcm5hbWVcbiAgaWYgKGxvY2FsQ29uZmlnLmt1YmVybmV0ZXMpIHtcbiAgICBjdXJyZW50VXNlcm5hbWUgPSBsb2NhbENvbmZpZy5rdWJlcm5ldGVzLnVzZXJuYW1lXG4gIH1cbiAgcmV0dXJuICEhY3VycmVudFVzZXJuYW1lXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvZ2luKHsgY3R4LCBsb2dFbnRyeSB9OiBQbHVnaW5BY3Rpb25QYXJhbXNCYXNlKSB7XG4gIGNvbnN0IGVudHJ5ID0gbG9nRW50cnkgJiYgbG9nRW50cnkuaW5mbyh7IHNlY3Rpb246IFwia3ViZXJuZXRlc1wiLCBtc2c6IFwiTG9nZ2luZyBpbi4uLlwiIH0pXG4gIGNvbnN0IGxvY2FsQ29uZmlnID0gYXdhaXQgY3R4LmxvY2FsQ29uZmlnU3RvcmUuZ2V0KClcblxuICBsZXQgY3VycmVudFVzZXJuYW1lXG4gIGxldCBwcmV2VXNlcm5hbWVzOiBBcnJheTxzdHJpbmc+ID0gW11cblxuICBpZiAobG9jYWxDb25maWcua3ViZXJuZXRlcykge1xuICAgIGN1cnJlbnRVc2VybmFtZSA9IGxvY2FsQ29uZmlnLmt1YmVybmV0ZXMudXNlcm5hbWVcbiAgICBwcmV2VXNlcm5hbWVzID0gbG9jYWxDb25maWcua3ViZXJuZXRlc1tcInByZXZpb3VzLXVzZXJuYW1lc1wiXSB8fCBbXVxuICB9XG5cbiAgaWYgKGN1cnJlbnRVc2VybmFtZSkge1xuICAgIGVudHJ5ICYmIGVudHJ5LnNldERvbmUoe1xuICAgICAgc3ltYm9sOiBcImluZm9cIixcbiAgICAgIG1zZzogYEFscmVhZHkgbG9nZ2VkIGluIGFzIHVzZXIgJHtjdXJyZW50VXNlcm5hbWV9YCxcbiAgICB9KVxuXG4gICAgcmV0dXJuIHsgbG9nZ2VkSW46IHRydWUgfVxuICB9XG5cbiAgY29uc3QgcHJvbXB0TmFtZSA9IFwidXNlcm5hbWVcIlxuICBjb25zdCBuZXdVc2VyT3B0aW9uID0gXCJBZGQgbmV3IHVzZXJcIlxuICB0eXBlIEFucyA9IHsgW3Byb21wdE5hbWVdOiBzdHJpbmcgfVxuICBsZXQgYW5zOiBBbnNcblxuICBjb25zdCBpbnB1dFByb21wdCA9IGFzeW5jICgpID0+IHtcbiAgICByZXR1cm4gaW5xdWlyZXIucHJvbXB0KHtcbiAgICAgIG5hbWU6IHByb21wdE5hbWUsXG4gICAgICBtZXNzYWdlOiBcIkVudGVyIHVzZXJuYW1lXCIsXG4gICAgICB2YWxpZGF0ZTogaW5wdXQgPT4ge1xuICAgICAgICB0cnkge1xuICAgICAgICAgIEpvaS5hdHRlbXB0KGlucHV0LnRyaW0oKSwgam9pSWRlbnRpZmllcigpKVxuICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICByZXR1cm4gYEludmFsaWQgdXNlcm5hbWUsIHBsZWFzZSB0cnkgYWdhaW5cXG5FcnJvcjogJHtlcnIubWVzc2FnZX1gXG4gICAgICAgIH1cbiAgICAgICAgcmV0dXJuIHRydWVcbiAgICAgIH0sXG4gICAgfSlcbiAgfVxuICBjb25zdCBjaG9pY2VzUHJvbXB0ID0gYXN5bmMgKCkgPT4ge1xuICAgIHJldHVybiBpbnF1aXJlci5wcm9tcHQoe1xuICAgICAgbmFtZTogcHJvbXB0TmFtZSxcbiAgICAgIHR5cGU6IFwibGlzdFwiLFxuICAgICAgbWVzc2FnZTogXCJMb2cgaW4gYXMuLi5cIixcbiAgICAgIGNob2ljZXM6IFsuLi5wcmV2VXNlcm5hbWVzLCBuZXcgaW5xdWlyZXIuU2VwYXJhdG9yKCksIG5ld1VzZXJPcHRpb25dLFxuICAgIH0pXG4gIH1cbiAgaWYgKHByZXZVc2VybmFtZXMubGVuZ3RoID4gMCkge1xuICAgIGFucyA9IGF3YWl0IGNob2ljZXNQcm9tcHQoKSBhcyBBbnNcbiAgICBpZiAoYW5zLnVzZXJuYW1lID09PSBuZXdVc2VyT3B0aW9uKSB7XG4gICAgICBhbnMgPSBhd2FpdCBpbnB1dFByb21wdCgpIGFzIEFuc1xuICAgIH1cbiAgfSBlbHNlIHtcbiAgICBhbnMgPSBhd2FpdCBpbnB1dFByb21wdCgpIGFzIEFuc1xuICB9XG5cbiAgY29uc3QgdXNlcm5hbWUgPSBhbnMudXNlcm5hbWUudHJpbSgpXG4gIGNvbnN0IG5ld1ByZXZVc2VybmFtZXMgPSB1bmlxKFsuLi5wcmV2VXNlcm5hbWVzLCB1c2VybmFtZV0uc2xpY2UoLU1BWF9TVE9SRURfVVNFUk5BTUVTKSlcblxuICBhd2FpdCBjdHgubG9jYWxDb25maWdTdG9yZS5zZXQoW1xuICAgIHsga2V5UGF0aDogW3Byb3ZpZGVyTmFtZSwgXCJ1c2VybmFtZVwiXSwgdmFsdWU6IHVzZXJuYW1lIH0sXG4gICAgeyBrZXlQYXRoOiBbcHJvdmlkZXJOYW1lLCBcInByZXZpb3VzLXVzZXJuYW1lc1wiXSwgdmFsdWU6IG5ld1ByZXZVc2VybmFtZXMgfSxcbiAgXSlcblxuICByZXR1cm4geyBsb2dnZWRJbjogdHJ1ZSB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGxvZ291dCh7IGN0eCwgbG9nRW50cnkgfTogUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSkge1xuICBjb25zdCBlbnRyeSA9IGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LmluZm8oeyBzZWN0aW9uOiBcImt1YmVybmV0ZXNcIiwgbXNnOiBcIkxvZ2dpbmcgb3V0Li4uXCIgfSlcbiAgY29uc3QgbG9jYWxDb25maWcgPSBhd2FpdCBjdHgubG9jYWxDb25maWdTdG9yZS5nZXQoKVxuICBjb25zdCBrOHNDb25maWcgPSBsb2NhbENvbmZpZy5rdWJlcm5ldGVzIHx8IHt9XG5cbiAgaWYgKGs4c0NvbmZpZy51c2VybmFtZSkge1xuICAgIGF3YWl0IGN0eC5sb2NhbENvbmZpZ1N0b3JlLmRlbGV0ZShbcHJvdmlkZXJOYW1lLCBcInVzZXJuYW1lXCJdKVxuICAgIGVudHJ5ICYmIGVudHJ5LnNldFN1Y2Nlc3MoXCJMb2dnZWQgb3V0XCIpXG4gIH0gZWxzZSB7XG4gICAgZW50cnkgJiYgZW50cnkuc2V0U3VjY2VzcyhcIkFscmVhZHkgbG9nZ2VkIG91dFwiKVxuICB9XG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNvbmZpZ3VyZVN5c3RlbVNlcnZpY2VzKFxuICB7IGN0eCwgZm9yY2UsIGxvZ0VudHJ5IH06XG4gICAgeyBjdHg6IFBsdWdpbkNvbnRleHQsIGZvcmNlOiBib29sZWFuLCBsb2dFbnRyeT86IExvZ0VudHJ5IH0sXG4pIHtcbiAgY29uc3QgcHJvdmlkZXIgPSBjdHgucHJvdmlkZXJcbiAgY29uc3Qgc3lzR2FyZGVuID0gYXdhaXQgZ2V0U3lzdGVtR2FyZGVuKHByb3ZpZGVyKVxuICBjb25zdCBzeXNDdHggPSBzeXNHYXJkZW4uZ2V0UGx1Z2luQ29udGV4dChwcm92aWRlci5uYW1lKVxuXG4gIC8vIFRPRE86IG5lZWQgdG8gYWRkIGxvZ2ljIGhlcmUgdG8gd2FpdCBmb3IgdGlsbGVyIHRvIGJlIHJlYWR5XG4gIGF3YWl0IGhlbG0oc3lzQ3R4LnByb3ZpZGVyLFxuICAgIFwiaW5pdFwiLCBcIi0td2FpdFwiLFxuICAgIFwiLS1zZXJ2aWNlLWFjY291bnRcIiwgXCJkZWZhdWx0XCIsXG4gICAgXCItLXVwZ3JhZGVcIixcbiAgKVxuXG4gIGNvbnN0IHN5c1N0YXR1cyA9IGF3YWl0IGdldExvY2FsRW52aXJvbm1lbnRTdGF0dXMoe1xuICAgIGN0eDogc3lzQ3R4LFxuICAgIGxvZ0VudHJ5LFxuICB9KVxuXG4gIGF3YWl0IHByZXBhcmVMb2NhbEVudmlyb25tZW50KHtcbiAgICBjdHg6IHN5c0N0eCxcbiAgICBmb3JjZSxcbiAgICBzdGF0dXM6IHN5c1N0YXR1cyxcbiAgICBsb2dFbnRyeSxcbiAgfSlcblxuICAvLyBvbmx5IGRlcGxveSBzZXJ2aWNlcyBpZiBjb25maWd1cmVkIHRvIGRvIHNvIChtaW5pa3ViZSBidW5kbGVzIHRoZSByZXF1aXJlZCBzZXJ2aWNlcyBhcyBhZGRvbnMpXG4gIGlmICghcHJvdmlkZXIuY29uZmlnLl9zeXN0ZW1TZXJ2aWNlcyB8fCBwcm92aWRlci5jb25maWcuX3N5c3RlbVNlcnZpY2VzLmxlbmd0aCA+IDApIHtcbiAgICBjb25zdCByZXN1bHRzID0gYXdhaXQgc3lzR2FyZGVuLmFjdGlvbnMuZGVwbG95U2VydmljZXMoe1xuICAgICAgc2VydmljZU5hbWVzOiBwcm92aWRlci5jb25maWcuX3N5c3RlbVNlcnZpY2VzLFxuICAgIH0pXG5cbiAgICBjb25zdCBmYWlsZWQgPSB2YWx1ZXMocmVzdWx0cy50YXNrUmVzdWx0cykuZmlsdGVyKHIgPT4gISFyLmVycm9yKS5sZW5ndGhcblxuICAgIGlmIChmYWlsZWQpIHtcbiAgICAgIHRocm93IG5ldyBQbHVnaW5FcnJvcihgbG9jYWwta3ViZXJuZXRlczogJHtmYWlsZWR9IGVycm9ycyBvY2N1cnJlZCB3aGVuIGNvbmZpZ3VyaW5nIGVudmlyb25tZW50YCwge1xuICAgICAgICByZXN1bHRzLFxuICAgICAgfSlcbiAgICB9XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/kubectl.d.ts b/garden-service/build/plugins/kubernetes/kubectl.d.ts new file mode 100644 index 00000000000..f0e80de37bd --- /dev/null +++ b/garden-service/build/plugins/kubernetes/kubectl.d.ts @@ -0,0 +1,51 @@ +/// +import { ChildProcess } from "child_process"; +export interface KubectlParams { + data?: Buffer; + ignoreError?: boolean; + silent?: boolean; + timeout?: number; + tty?: boolean; +} +export interface KubectlOutput { + code: number; + output: string; + stdout?: string; + stderr?: string; +} +export interface ApplyOptions { + dryRun?: boolean; + force?: boolean; + pruneSelector?: string; + namespace?: string; +} +export declare const KUBECTL_DEFAULT_TIMEOUT = 300; +export declare class Kubectl { + context?: string; + namespace?: string; + configPath?: string; + constructor({ context, namespace, configPath }: { + context: string; + namespace?: string; + configPath?: string; + }); + call(args: string[], { data, ignoreError, silent, timeout }?: KubectlParams): Promise; + json(args: string[], opts?: KubectlParams): Promise; + tty(args: string[], opts?: KubectlParams): Promise; + spawn(args: string[]): ChildProcess; + private getExececutable; + private prepareArgs; +} +export declare function kubectl(context: string, namespace?: string): Kubectl; +export declare function apply(context: string, obj: object, params: ApplyOptions): Promise; +export declare function applyMany(context: string, objects: object[], { dryRun, force, namespace, pruneSelector }?: ApplyOptions): Promise; +export interface DeleteObjectsParams { + context: string; + namespace: string; + labelKey: string; + labelValue: string; + objectTypes: string[]; + includeUninitialized?: boolean; +} +export declare function deleteObjectsByLabel({ context, namespace, labelKey, labelValue, objectTypes, includeUninitialized, }: DeleteObjectsParams): Promise; +//# sourceMappingURL=kubectl.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/kubectl.js b/garden-service/build/plugins/kubernetes/kubectl.js new file mode 100644 index 00000000000..8b356905d49 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/kubectl.js @@ -0,0 +1,176 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const child_process_1 = require("child_process"); +const lodash_1 = require("lodash"); +const util_1 = require("../../util/util"); +const exceptions_1 = require("../../exceptions"); +const logger_1 = require("../../logger/logger"); +const os_1 = require("os"); +const hasAnsi = require("has-ansi"); +exports.KUBECTL_DEFAULT_TIMEOUT = 300; +class Kubectl { + // TODO: namespace should always be required + constructor({ context, namespace, configPath }) { + this.context = context; + this.namespace = namespace; + this.configPath = configPath; + } + call(args, { data, ignoreError = false, silent = true, timeout = exports.KUBECTL_DEFAULT_TIMEOUT } = {}) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: use the spawn helper from index.ts + const logger = logger_1.getLogger(); + const out = { + code: 0, + output: "", + stdout: "", + stderr: "", + }; + const preparedArgs = this.prepareArgs(args); + const proc = child_process_1.spawn(this.getExececutable(), preparedArgs); + proc.stdout.on("data", (s) => { + if (!silent) { + const str = s.toString(); + logger.info(hasAnsi(str) ? str : chalk_1.default.white(str)); + } + out.output += s; + out.stdout += s; + }); + proc.stderr.on("data", (s) => { + if (!silent) { + const str = s.toString(); + logger.info(hasAnsi(str) ? str : chalk_1.default.white(str)); + } + out.output += s; + out.stderr += s; + }); + if (data) { + proc.stdin.end(data); + } + return new Promise((resolve, reject) => { + let _timeout; + const _reject = (msg) => { + const dataStr = data ? data.toString() : null; + const details = lodash_1.extend({ args, preparedArgs, msg, data: dataStr }, out); + const err = new exceptions_1.RuntimeError(`Failed running 'kubectl ${preparedArgs.join(" ")}': ${out.output}`, details); + reject(err); + }; + if (timeout > 0) { + _timeout = setTimeout(() => { + proc.kill("SIGKILL"); + _reject(`kubectl timed out after ${timeout} seconds.`); + }, timeout * 1000); + } + proc.on("close", (code) => { + _timeout && clearTimeout(_timeout); + out.code = code; + if (code === 0 || ignoreError) { + resolve(out); + } + else { + _reject("Process exited with code " + code); + } + }); + }); + }); + } + json(args, opts = {}) { + return __awaiter(this, void 0, void 0, function* () { + if (!args.includes("--output=json")) { + args.push("--output=json"); + } + const result = yield this.call(args, opts); + return JSON.parse(result.output); + }); + } + tty(args, opts = {}) { + return __awaiter(this, void 0, void 0, function* () { + return util_1.spawnPty(this.getExececutable(), this.prepareArgs(args), opts); + }); + } + spawn(args) { + return child_process_1.spawn(this.getExececutable(), this.prepareArgs(args)); + } + getExececutable() { + // workaround for https://github.com/Microsoft/node-pty/issues/109 + return os_1.platform() === "win32" ? "kubectl.exe" : "kubectl"; + } + prepareArgs(args) { + const ops = []; + if (this.namespace) { + ops.push(`--namespace=${this.namespace}`); + } + if (this.context) { + ops.push(`--context=${this.context}`); + } + if (this.configPath) { + ops.push(`--kubeconfig=${this.configPath}`); + } + return ops.concat(args); + } +} +exports.Kubectl = Kubectl; +function kubectl(context, namespace) { + return new Kubectl({ context, namespace }); +} +exports.kubectl = kubectl; +function apply(context, obj, params) { + return __awaiter(this, void 0, void 0, function* () { + return applyMany(context, [obj], params); + }); +} +exports.apply = apply; +function applyMany(context, objects, { dryRun = false, force = false, namespace, pruneSelector } = {}) { + return __awaiter(this, void 0, void 0, function* () { + const data = Buffer.from(util_1.encodeYamlMulti(objects)); + let args = ["apply"]; + dryRun && args.push("--dry-run"); + force && args.push("--force"); + pruneSelector && args.push("--prune", "--selector", pruneSelector); + args.push("--output=json", "-f", "-"); + const result = yield kubectl(context, namespace).call(args, { data }); + try { + return JSON.parse(result.output); + } + catch (_) { + return result.output; + } + }); +} +exports.applyMany = applyMany; +function deleteObjectsByLabel({ context, namespace, labelKey, labelValue, objectTypes, includeUninitialized = false, }) { + return __awaiter(this, void 0, void 0, function* () { + let args = [ + "delete", + objectTypes.join(","), + "-l", + `${labelKey}=${labelValue}`, + ]; + includeUninitialized && args.push("--include-uninitialized"); + const result = yield kubectl(context, namespace).call(args); + try { + return JSON.parse(result.output); + } + catch (_) { + return result.output; + } + }); +} +exports.deleteObjectsByLabel = deleteObjectsByLabel; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9rdWJlY3RsLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxpQ0FBeUI7QUFDekIsaURBQW1EO0FBQ25ELG1DQUErQjtBQUMvQiwwQ0FBMkQ7QUFDM0QsaURBQStDO0FBQy9DLGdEQUErQztBQUMvQywyQkFBNkI7QUFDN0Isb0NBQW9DO0FBd0J2QixRQUFBLHVCQUF1QixHQUFHLEdBQUcsQ0FBQTtBQUUxQyxNQUFhLE9BQU87SUFLbEIsNENBQTRDO0lBQzVDLFlBQVksRUFBRSxPQUFPLEVBQUUsU0FBUyxFQUFFLFVBQVUsRUFBZ0U7UUFDMUcsSUFBSSxDQUFDLE9BQU8sR0FBRyxPQUFPLENBQUE7UUFDdEIsSUFBSSxDQUFDLFNBQVMsR0FBRyxTQUFTLENBQUE7UUFDMUIsSUFBSSxDQUFDLFVBQVUsR0FBRyxVQUFVLENBQUE7SUFDOUIsQ0FBQztJQUVLLElBQUksQ0FDUixJQUFjLEVBQ2QsRUFBRSxJQUFJLEVBQUUsV0FBVyxHQUFHLEtBQUssRUFBRSxNQUFNLEdBQUcsSUFBSSxFQUFFLE9BQU8sR0FBRywrQkFBdUIsS0FBb0IsRUFBRTs7WUFFbkcsMkNBQTJDO1lBQzNDLE1BQU0sTUFBTSxHQUFHLGtCQUFTLEVBQUUsQ0FBQTtZQUMxQixNQUFNLEdBQUcsR0FBa0I7Z0JBQ3pCLElBQUksRUFBRSxDQUFDO2dCQUNQLE1BQU0sRUFBRSxFQUFFO2dCQUNWLE1BQU0sRUFBRSxFQUFFO2dCQUNWLE1BQU0sRUFBRSxFQUFFO2FBQ1gsQ0FBQTtZQUVELE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUE7WUFDM0MsTUFBTSxJQUFJLEdBQUcscUJBQUssQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUUsWUFBWSxDQUFDLENBQUE7WUFFeEQsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksQ0FBQyxNQUFNLEVBQUU7b0JBQ1gsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO29CQUN4QixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxlQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7aUJBQ25EO2dCQUNELEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFBO2dCQUNmLEdBQUcsQ0FBQyxNQUFPLElBQUksQ0FBQyxDQUFBO1lBQ2xCLENBQUMsQ0FBQyxDQUFBO1lBRUYsSUFBSSxDQUFDLE1BQU0sQ0FBQyxFQUFFLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQyxFQUFFLEVBQUU7Z0JBQzNCLElBQUksQ0FBQyxNQUFNLEVBQUU7b0JBQ1gsTUFBTSxHQUFHLEdBQUcsQ0FBQyxDQUFDLFFBQVEsRUFBRSxDQUFBO29CQUN4QixNQUFNLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLENBQUMsR0FBRyxDQUFDLENBQUMsQ0FBQyxlQUFLLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUE7aUJBQ25EO2dCQUNELEdBQUcsQ0FBQyxNQUFNLElBQUksQ0FBQyxDQUFBO2dCQUNmLEdBQUcsQ0FBQyxNQUFPLElBQUksQ0FBQyxDQUFBO1lBQ2xCLENBQUMsQ0FBQyxDQUFBO1lBRUYsSUFBSSxJQUFJLEVBQUU7Z0JBQ1IsSUFBSSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUE7YUFDckI7WUFFRCxPQUFPLElBQUksT0FBTyxDQUFnQixDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsRUFBRTtnQkFDcEQsSUFBSSxRQUFRLENBQUE7Z0JBRVosTUFBTSxPQUFPLEdBQUcsQ0FBQyxHQUFXLEVBQUUsRUFBRTtvQkFDOUIsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtvQkFDN0MsTUFBTSxPQUFPLEdBQUcsZUFBTSxDQUFDLEVBQUUsSUFBSSxFQUFFLFlBQVksRUFBRSxHQUFHLEVBQUUsSUFBSSxFQUFFLE9BQU8sRUFBRSxFQUFPLEdBQUcsQ0FBQyxDQUFBO29CQUU1RSxNQUFNLEdBQUcsR0FBRyxJQUFJLHlCQUFZLENBQzFCLDJCQUEyQixZQUFZLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxNQUFNLEdBQUcsQ0FBQyxNQUFNLEVBQUUsRUFDbkUsT0FBTyxDQUNSLENBQUE7b0JBQ0QsTUFBTSxDQUFDLEdBQUcsQ0FBQyxDQUFBO2dCQUNiLENBQUMsQ0FBQTtnQkFFRCxJQUFJLE9BQU8sR0FBRyxDQUFDLEVBQUU7b0JBQ2YsUUFBUSxHQUFHLFVBQVUsQ0FBQyxHQUFHLEVBQUU7d0JBQ3pCLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7d0JBQ3BCLE9BQU8sQ0FBQywyQkFBMkIsT0FBTyxXQUFXLENBQUMsQ0FBQTtvQkFDeEQsQ0FBQyxFQUFFLE9BQU8sR0FBRyxJQUFJLENBQUMsQ0FBQTtpQkFDbkI7Z0JBRUQsSUFBSSxDQUFDLEVBQUUsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxJQUFJLEVBQUUsRUFBRTtvQkFDeEIsUUFBUSxJQUFJLFlBQVksQ0FBQyxRQUFRLENBQUMsQ0FBQTtvQkFDbEMsR0FBRyxDQUFDLElBQUksR0FBRyxJQUFJLENBQUE7b0JBRWYsSUFBSSxJQUFJLEtBQUssQ0FBQyxJQUFJLFdBQVcsRUFBRTt3QkFDN0IsT0FBTyxDQUFDLEdBQUcsQ0FBQyxDQUFBO3FCQUNiO3lCQUFNO3dCQUNMLE9BQU8sQ0FBQywyQkFBMkIsR0FBRyxJQUFJLENBQUMsQ0FBQTtxQkFDNUM7Z0JBQ0gsQ0FBQyxDQUFDLENBQUE7WUFDSixDQUFDLENBQUMsQ0FBQTtRQUNKLENBQUM7S0FBQTtJQUVLLElBQUksQ0FBQyxJQUFjLEVBQUUsT0FBc0IsRUFBRTs7WUFDakQsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsZUFBZSxDQUFDLEVBQUU7Z0JBQ25DLElBQUksQ0FBQyxJQUFJLENBQUMsZUFBZSxDQUFDLENBQUE7YUFDM0I7WUFFRCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxJQUFJLENBQUMsSUFBSSxFQUFFLElBQUksQ0FBQyxDQUFBO1lBRTFDLE9BQU8sSUFBSSxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsTUFBTSxDQUFDLENBQUE7UUFDbEMsQ0FBQztLQUFBO0lBRUssR0FBRyxDQUFDLElBQWMsRUFBRSxPQUFzQixFQUFFOztZQUNoRCxPQUFPLGVBQVEsQ0FBQyxJQUFJLENBQUMsZUFBZSxFQUFFLEVBQUUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxJQUFJLENBQUMsRUFBRSxJQUFJLENBQUMsQ0FBQTtRQUN2RSxDQUFDO0tBQUE7SUFFRCxLQUFLLENBQUMsSUFBYztRQUNsQixPQUFPLHFCQUFLLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxFQUFFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUM5RCxDQUFDO0lBRU8sZUFBZTtRQUNyQixrRUFBa0U7UUFDbEUsT0FBTyxhQUFRLEVBQUUsS0FBSyxPQUFPLENBQUMsQ0FBQyxDQUFDLGFBQWEsQ0FBQyxDQUFDLENBQUMsU0FBUyxDQUFBO0lBQzNELENBQUM7SUFFTyxXQUFXLENBQUMsSUFBYztRQUNoQyxNQUFNLEdBQUcsR0FBYSxFQUFFLENBQUE7UUFFeEIsSUFBSSxJQUFJLENBQUMsU0FBUyxFQUFFO1lBQ2xCLEdBQUcsQ0FBQyxJQUFJLENBQUMsZUFBZSxJQUFJLENBQUMsU0FBUyxFQUFFLENBQUMsQ0FBQTtTQUMxQztRQUVELElBQUksSUFBSSxDQUFDLE9BQU8sRUFBRTtZQUNoQixHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7U0FDdEM7UUFFRCxJQUFJLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDbkIsR0FBRyxDQUFDLElBQUksQ0FBQyxnQkFBZ0IsSUFBSSxDQUFDLFVBQVUsRUFBRSxDQUFDLENBQUE7U0FDNUM7UUFFRCxPQUFPLEdBQUcsQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUE7SUFDekIsQ0FBQztDQUNGO0FBNUhELDBCQTRIQztBQUVELFNBQWdCLE9BQU8sQ0FBQyxPQUFlLEVBQUUsU0FBa0I7SUFDekQsT0FBTyxJQUFJLE9BQU8sQ0FBQyxFQUFFLE9BQU8sRUFBRSxTQUFTLEVBQUUsQ0FBQyxDQUFBO0FBQzVDLENBQUM7QUFGRCwwQkFFQztBQUVELFNBQXNCLEtBQUssQ0FBQyxPQUFlLEVBQUUsR0FBVyxFQUFFLE1BQW9COztRQUM1RSxPQUFPLFNBQVMsQ0FBQyxPQUFPLEVBQUUsQ0FBQyxHQUFHLENBQUMsRUFBRSxNQUFNLENBQUMsQ0FBQTtJQUMxQyxDQUFDO0NBQUE7QUFGRCxzQkFFQztBQUVELFNBQXNCLFNBQVMsQ0FDN0IsT0FBZSxFQUFFLE9BQWlCLEVBQ2xDLEVBQUUsTUFBTSxHQUFHLEtBQUssRUFBRSxLQUFLLEdBQUcsS0FBSyxFQUFFLFNBQVMsRUFBRSxhQUFhLEtBQW1CLEVBQUU7O1FBRTlFLE1BQU0sSUFBSSxHQUFHLE1BQU0sQ0FBQyxJQUFJLENBQUMsc0JBQWUsQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFBO1FBRWxELElBQUksSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUE7UUFDcEIsTUFBTSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxDQUFDLENBQUE7UUFDaEMsS0FBSyxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxDQUFDLENBQUE7UUFDN0IsYUFBYSxJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMsU0FBUyxFQUFFLFlBQVksRUFBRSxhQUFhLENBQUMsQ0FBQTtRQUNsRSxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxJQUFJLEVBQUUsR0FBRyxDQUFDLENBQUE7UUFFckMsTUFBTSxNQUFNLEdBQUcsTUFBTSxPQUFPLENBQUMsT0FBTyxFQUFFLFNBQVMsQ0FBQyxDQUFDLElBQUksQ0FBQyxJQUFJLEVBQUUsRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO1FBRXJFLElBQUk7WUFDRixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1NBQ2pDO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUE7U0FDckI7SUFDSCxDQUFDO0NBQUE7QUFuQkQsOEJBbUJDO0FBV0QsU0FBc0Isb0JBQW9CLENBQ3hDLEVBQ0UsT0FBTyxFQUNQLFNBQVMsRUFDVCxRQUFRLEVBQ1IsVUFBVSxFQUNWLFdBQVcsRUFDWCxvQkFBb0IsR0FBRyxLQUFLLEdBQ1I7O1FBRXRCLElBQUksSUFBSSxHQUFHO1lBQ1QsUUFBUTtZQUNSLFdBQVcsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDO1lBQ3JCLElBQUk7WUFDSixHQUFHLFFBQVEsSUFBSSxVQUFVLEVBQUU7U0FDNUIsQ0FBQTtRQUVELG9CQUFvQixJQUFJLElBQUksQ0FBQyxJQUFJLENBQUMseUJBQXlCLENBQUMsQ0FBQTtRQUU1RCxNQUFNLE1BQU0sR0FBRyxNQUFNLE9BQU8sQ0FBQyxPQUFPLEVBQUUsU0FBUyxDQUFDLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFBO1FBRTNELElBQUk7WUFDRixPQUFPLElBQUksQ0FBQyxLQUFLLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxDQUFBO1NBQ2pDO1FBQUMsT0FBTyxDQUFDLEVBQUU7WUFDVixPQUFPLE1BQU0sQ0FBQyxNQUFNLENBQUE7U0FDckI7SUFDSCxDQUFDO0NBQUE7QUExQkQsb0RBMEJDIiwiZmlsZSI6InBsdWdpbnMva3ViZXJuZXRlcy9rdWJlY3RsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgQ2hpbGRQcm9jZXNzLCBzcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCJcbmltcG9ydCB7IGV4dGVuZCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgZW5jb2RlWWFtbE11bHRpLCBzcGF3blB0eSB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgUnVudGltZUVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgZ2V0TG9nZ2VyIH0gZnJvbSBcIi4uLy4uL2xvZ2dlci9sb2dnZXJcIlxuaW1wb3J0IHsgcGxhdGZvcm0gfSBmcm9tIFwib3NcIlxuaW1wb3J0IGhhc0Fuc2kgPSByZXF1aXJlKFwiaGFzLWFuc2lcIilcblxuZXhwb3J0IGludGVyZmFjZSBLdWJlY3RsUGFyYW1zIHtcbiAgZGF0YT86IEJ1ZmZlcixcbiAgaWdub3JlRXJyb3I/OiBib29sZWFuLFxuICBzaWxlbnQ/OiBib29sZWFuLFxuICB0aW1lb3V0PzogbnVtYmVyLFxuICB0dHk/OiBib29sZWFuLFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIEt1YmVjdGxPdXRwdXQge1xuICBjb2RlOiBudW1iZXIsXG4gIG91dHB1dDogc3RyaW5nLFxuICBzdGRvdXQ/OiBzdHJpbmcsXG4gIHN0ZGVycj86IHN0cmluZyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBBcHBseU9wdGlvbnMge1xuICBkcnlSdW4/OiBib29sZWFuLFxuICBmb3JjZT86IGJvb2xlYW4sXG4gIHBydW5lU2VsZWN0b3I/OiBzdHJpbmcsXG4gIG5hbWVzcGFjZT86IHN0cmluZyxcbn1cblxuZXhwb3J0IGNvbnN0IEtVQkVDVExfREVGQVVMVF9USU1FT1VUID0gMzAwXG5cbmV4cG9ydCBjbGFzcyBLdWJlY3RsIHtcbiAgcHVibGljIGNvbnRleHQ/OiBzdHJpbmdcbiAgcHVibGljIG5hbWVzcGFjZT86IHN0cmluZ1xuICBwdWJsaWMgY29uZmlnUGF0aD86IHN0cmluZ1xuXG4gIC8vIFRPRE86IG5hbWVzcGFjZSBzaG91bGQgYWx3YXlzIGJlIHJlcXVpcmVkXG4gIGNvbnN0cnVjdG9yKHsgY29udGV4dCwgbmFtZXNwYWNlLCBjb25maWdQYXRoIH06IHsgY29udGV4dDogc3RyaW5nLCBuYW1lc3BhY2U/OiBzdHJpbmcsIGNvbmZpZ1BhdGg/OiBzdHJpbmcgfSkge1xuICAgIHRoaXMuY29udGV4dCA9IGNvbnRleHRcbiAgICB0aGlzLm5hbWVzcGFjZSA9IG5hbWVzcGFjZVxuICAgIHRoaXMuY29uZmlnUGF0aCA9IGNvbmZpZ1BhdGhcbiAgfVxuXG4gIGFzeW5jIGNhbGwoXG4gICAgYXJnczogc3RyaW5nW10sXG4gICAgeyBkYXRhLCBpZ25vcmVFcnJvciA9IGZhbHNlLCBzaWxlbnQgPSB0cnVlLCB0aW1lb3V0ID0gS1VCRUNUTF9ERUZBVUxUX1RJTUVPVVQgfTogS3ViZWN0bFBhcmFtcyA9IHt9LFxuICApOiBQcm9taXNlPEt1YmVjdGxPdXRwdXQ+IHtcbiAgICAvLyBUT0RPOiB1c2UgdGhlIHNwYXduIGhlbHBlciBmcm9tIGluZGV4LnRzXG4gICAgY29uc3QgbG9nZ2VyID0gZ2V0TG9nZ2VyKClcbiAgICBjb25zdCBvdXQ6IEt1YmVjdGxPdXRwdXQgPSB7XG4gICAgICBjb2RlOiAwLFxuICAgICAgb3V0cHV0OiBcIlwiLFxuICAgICAgc3Rkb3V0OiBcIlwiLFxuICAgICAgc3RkZXJyOiBcIlwiLFxuICAgIH1cblxuICAgIGNvbnN0IHByZXBhcmVkQXJncyA9IHRoaXMucHJlcGFyZUFyZ3MoYXJncylcbiAgICBjb25zdCBwcm9jID0gc3Bhd24odGhpcy5nZXRFeGVjZWN1dGFibGUoKSwgcHJlcGFyZWRBcmdzKVxuXG4gICAgcHJvYy5zdGRvdXQub24oXCJkYXRhXCIsIChzKSA9PiB7XG4gICAgICBpZiAoIXNpbGVudCkge1xuICAgICAgICBjb25zdCBzdHIgPSBzLnRvU3RyaW5nKClcbiAgICAgICAgbG9nZ2VyLmluZm8oaGFzQW5zaShzdHIpID8gc3RyIDogY2hhbGsud2hpdGUoc3RyKSlcbiAgICAgIH1cbiAgICAgIG91dC5vdXRwdXQgKz0gc1xuICAgICAgb3V0LnN0ZG91dCEgKz0gc1xuICAgIH0pXG5cbiAgICBwcm9jLnN0ZGVyci5vbihcImRhdGFcIiwgKHMpID0+IHtcbiAgICAgIGlmICghc2lsZW50KSB7XG4gICAgICAgIGNvbnN0IHN0ciA9IHMudG9TdHJpbmcoKVxuICAgICAgICBsb2dnZXIuaW5mbyhoYXNBbnNpKHN0cikgPyBzdHIgOiBjaGFsay53aGl0ZShzdHIpKVxuICAgICAgfVxuICAgICAgb3V0Lm91dHB1dCArPSBzXG4gICAgICBvdXQuc3RkZXJyISArPSBzXG4gICAgfSlcblxuICAgIGlmIChkYXRhKSB7XG4gICAgICBwcm9jLnN0ZGluLmVuZChkYXRhKVxuICAgIH1cblxuICAgIHJldHVybiBuZXcgUHJvbWlzZTxLdWJlY3RsT3V0cHV0PigocmVzb2x2ZSwgcmVqZWN0KSA9PiB7XG4gICAgICBsZXQgX3RpbWVvdXRcblxuICAgICAgY29uc3QgX3JlamVjdCA9IChtc2c6IHN0cmluZykgPT4ge1xuICAgICAgICBjb25zdCBkYXRhU3RyID0gZGF0YSA/IGRhdGEudG9TdHJpbmcoKSA6IG51bGxcbiAgICAgICAgY29uc3QgZGV0YWlscyA9IGV4dGVuZCh7IGFyZ3MsIHByZXBhcmVkQXJncywgbXNnLCBkYXRhOiBkYXRhU3RyIH0sIDxhbnk+b3V0KVxuXG4gICAgICAgIGNvbnN0IGVyciA9IG5ldyBSdW50aW1lRXJyb3IoXG4gICAgICAgICAgYEZhaWxlZCBydW5uaW5nICdrdWJlY3RsICR7cHJlcGFyZWRBcmdzLmpvaW4oXCIgXCIpfSc6ICR7b3V0Lm91dHB1dH1gLFxuICAgICAgICAgIGRldGFpbHMsXG4gICAgICAgIClcbiAgICAgICAgcmVqZWN0KGVycilcbiAgICAgIH1cblxuICAgICAgaWYgKHRpbWVvdXQgPiAwKSB7XG4gICAgICAgIF90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgICAgcHJvYy5raWxsKFwiU0lHS0lMTFwiKVxuICAgICAgICAgIF9yZWplY3QoYGt1YmVjdGwgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dH0gc2Vjb25kcy5gKVxuICAgICAgICB9LCB0aW1lb3V0ICogMTAwMClcbiAgICAgIH1cblxuICAgICAgcHJvYy5vbihcImNsb3NlXCIsIChjb2RlKSA9PiB7XG4gICAgICAgIF90aW1lb3V0ICYmIGNsZWFyVGltZW91dChfdGltZW91dClcbiAgICAgICAgb3V0LmNvZGUgPSBjb2RlXG5cbiAgICAgICAgaWYgKGNvZGUgPT09IDAgfHwgaWdub3JlRXJyb3IpIHtcbiAgICAgICAgICByZXNvbHZlKG91dClcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBfcmVqZWN0KFwiUHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlIFwiICsgY29kZSlcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgYXN5bmMganNvbihhcmdzOiBzdHJpbmdbXSwgb3B0czogS3ViZWN0bFBhcmFtcyA9IHt9KTogUHJvbWlzZTxLdWJlY3RsT3V0cHV0PiB7XG4gICAgaWYgKCFhcmdzLmluY2x1ZGVzKFwiLS1vdXRwdXQ9anNvblwiKSkge1xuICAgICAgYXJncy5wdXNoKFwiLS1vdXRwdXQ9anNvblwiKVxuICAgIH1cblxuICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuY2FsbChhcmdzLCBvcHRzKVxuXG4gICAgcmV0dXJuIEpTT04ucGFyc2UocmVzdWx0Lm91dHB1dClcbiAgfVxuXG4gIGFzeW5jIHR0eShhcmdzOiBzdHJpbmdbXSwgb3B0czogS3ViZWN0bFBhcmFtcyA9IHt9KTogUHJvbWlzZTxLdWJlY3RsT3V0cHV0PiB7XG4gICAgcmV0dXJuIHNwYXduUHR5KHRoaXMuZ2V0RXhlY2VjdXRhYmxlKCksIHRoaXMucHJlcGFyZUFyZ3MoYXJncyksIG9wdHMpXG4gIH1cblxuICBzcGF3bihhcmdzOiBzdHJpbmdbXSk6IENoaWxkUHJvY2VzcyB7XG4gICAgcmV0dXJuIHNwYXduKHRoaXMuZ2V0RXhlY2VjdXRhYmxlKCksIHRoaXMucHJlcGFyZUFyZ3MoYXJncykpXG4gIH1cblxuICBwcml2YXRlIGdldEV4ZWNlY3V0YWJsZSgpIHtcbiAgICAvLyB3b3JrYXJvdW5kIGZvciBodHRwczovL2dpdGh1Yi5jb20vTWljcm9zb2Z0L25vZGUtcHR5L2lzc3Vlcy8xMDlcbiAgICByZXR1cm4gcGxhdGZvcm0oKSA9PT0gXCJ3aW4zMlwiID8gXCJrdWJlY3RsLmV4ZVwiIDogXCJrdWJlY3RsXCJcbiAgfVxuXG4gIHByaXZhdGUgcHJlcGFyZUFyZ3MoYXJnczogc3RyaW5nW10pIHtcbiAgICBjb25zdCBvcHM6IHN0cmluZ1tdID0gW11cblxuICAgIGlmICh0aGlzLm5hbWVzcGFjZSkge1xuICAgICAgb3BzLnB1c2goYC0tbmFtZXNwYWNlPSR7dGhpcy5uYW1lc3BhY2V9YClcbiAgICB9XG5cbiAgICBpZiAodGhpcy5jb250ZXh0KSB7XG4gICAgICBvcHMucHVzaChgLS1jb250ZXh0PSR7dGhpcy5jb250ZXh0fWApXG4gICAgfVxuXG4gICAgaWYgKHRoaXMuY29uZmlnUGF0aCkge1xuICAgICAgb3BzLnB1c2goYC0ta3ViZWNvbmZpZz0ke3RoaXMuY29uZmlnUGF0aH1gKVxuICAgIH1cblxuICAgIHJldHVybiBvcHMuY29uY2F0KGFyZ3MpXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGt1YmVjdGwoY29udGV4dDogc3RyaW5nLCBuYW1lc3BhY2U/OiBzdHJpbmcpIHtcbiAgcmV0dXJuIG5ldyBLdWJlY3RsKHsgY29udGV4dCwgbmFtZXNwYWNlIH0pXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcHBseShjb250ZXh0OiBzdHJpbmcsIG9iajogb2JqZWN0LCBwYXJhbXM6IEFwcGx5T3B0aW9ucykge1xuICByZXR1cm4gYXBwbHlNYW55KGNvbnRleHQsIFtvYmpdLCBwYXJhbXMpXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhcHBseU1hbnkoXG4gIGNvbnRleHQ6IHN0cmluZywgb2JqZWN0czogb2JqZWN0W10sXG4gIHsgZHJ5UnVuID0gZmFsc2UsIGZvcmNlID0gZmFsc2UsIG5hbWVzcGFjZSwgcHJ1bmVTZWxlY3RvciB9OiBBcHBseU9wdGlvbnMgPSB7fSxcbikge1xuICBjb25zdCBkYXRhID0gQnVmZmVyLmZyb20oZW5jb2RlWWFtbE11bHRpKG9iamVjdHMpKVxuXG4gIGxldCBhcmdzID0gW1wiYXBwbHlcIl1cbiAgZHJ5UnVuICYmIGFyZ3MucHVzaChcIi0tZHJ5LXJ1blwiKVxuICBmb3JjZSAmJiBhcmdzLnB1c2goXCItLWZvcmNlXCIpXG4gIHBydW5lU2VsZWN0b3IgJiYgYXJncy5wdXNoKFwiLS1wcnVuZVwiLCBcIi0tc2VsZWN0b3JcIiwgcHJ1bmVTZWxlY3RvcilcbiAgYXJncy5wdXNoKFwiLS1vdXRwdXQ9anNvblwiLCBcIi1mXCIsIFwiLVwiKVxuXG4gIGNvbnN0IHJlc3VsdCA9IGF3YWl0IGt1YmVjdGwoY29udGV4dCwgbmFtZXNwYWNlKS5jYWxsKGFyZ3MsIHsgZGF0YSB9KVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UocmVzdWx0Lm91dHB1dClcbiAgfSBjYXRjaCAoXykge1xuICAgIHJldHVybiByZXN1bHQub3V0cHV0XG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBEZWxldGVPYmplY3RzUGFyYW1zIHtcbiAgY29udGV4dDogc3RyaW5nLFxuICBuYW1lc3BhY2U6IHN0cmluZyxcbiAgbGFiZWxLZXk6IHN0cmluZyxcbiAgbGFiZWxWYWx1ZTogc3RyaW5nLFxuICBvYmplY3RUeXBlczogc3RyaW5nW10sXG4gIGluY2x1ZGVVbmluaXRpYWxpemVkPzogYm9vbGVhbixcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlbGV0ZU9iamVjdHNCeUxhYmVsKFxuICB7XG4gICAgY29udGV4dCxcbiAgICBuYW1lc3BhY2UsXG4gICAgbGFiZWxLZXksXG4gICAgbGFiZWxWYWx1ZSxcbiAgICBvYmplY3RUeXBlcyxcbiAgICBpbmNsdWRlVW5pbml0aWFsaXplZCA9IGZhbHNlLFxuICB9OiBEZWxldGVPYmplY3RzUGFyYW1zKSB7XG5cbiAgbGV0IGFyZ3MgPSBbXG4gICAgXCJkZWxldGVcIixcbiAgICBvYmplY3RUeXBlcy5qb2luKFwiLFwiKSxcbiAgICBcIi1sXCIsXG4gICAgYCR7bGFiZWxLZXl9PSR7bGFiZWxWYWx1ZX1gLFxuICBdXG5cbiAgaW5jbHVkZVVuaW5pdGlhbGl6ZWQgJiYgYXJncy5wdXNoKFwiLS1pbmNsdWRlLXVuaW5pdGlhbGl6ZWRcIilcblxuICBjb25zdCByZXN1bHQgPSBhd2FpdCBrdWJlY3RsKGNvbnRleHQsIG5hbWVzcGFjZSkuY2FsbChhcmdzKVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIEpTT04ucGFyc2UocmVzdWx0Lm91dHB1dClcbiAgfSBjYXRjaCAoXykge1xuICAgIHJldHVybiByZXN1bHQub3V0cHV0XG4gIH1cbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/kubernetes.d.ts b/garden-service/build/plugins/kubernetes/kubernetes.d.ts new file mode 100644 index 00000000000..7ca12366c3a --- /dev/null +++ b/garden-service/build/plugins/kubernetes/kubernetes.d.ts @@ -0,0 +1,36 @@ +import * as Joi from "joi"; +import { GardenPlugin } from "../../types/plugin/plugin"; +import { Provider, ProviderConfig } from "../../config/project"; +import { ContainerRegistryConfig } from "../container"; +export declare const name = "kubernetes"; +export interface SecretRef { + name: string; + namespace: string; +} +export interface IngressTlsCertificate { + name: string; + hostnames?: string[]; + secretRef: SecretRef; +} +export interface KubernetesBaseConfig extends ProviderConfig { + context: string; + defaultHostname?: string; + defaultUsername?: string; + forceSsl: boolean; + imagePullSecrets: SecretRef[]; + ingressHttpPort: number; + ingressHttpsPort: number; + ingressClass: string; + namespace?: string; + tlsCertificates: IngressTlsCertificate[]; +} +export interface KubernetesConfig extends KubernetesBaseConfig { + deploymentRegistry: ContainerRegistryConfig; +} +export declare type KubernetesProvider = Provider; +export declare const k8sContextSchema: Joi.StringSchema; +export declare const kubernetesConfigBase: Joi.ObjectSchema; +export declare function gardenPlugin({ config }: { + config: KubernetesConfig; +}): GardenPlugin; +//# sourceMappingURL=kubernetes.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/kubernetes.js b/garden-service/build/plugins/kubernetes/kubernetes.js new file mode 100644 index 00000000000..2a7a199ac05 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/kubernetes.js @@ -0,0 +1,128 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const dedent = require("dedent"); +const common_1 = require("../../config/common"); +const project_1 = require("../../config/project"); +const actions_1 = require("./actions"); +const deployment_1 = require("./deployment"); +const helm_1 = require("./helm"); +const secrets_1 = require("./secrets"); +const container_1 = require("../container"); +const init_1 = require("./init"); +exports.name = "kubernetes"; +exports.k8sContextSchema = Joi.string() + .required() + .description("The kubectl context to use to connect to the Kubernetes cluster.") + .example("my-dev-context"); +const secretRef = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("The name of the Kubernetes secret.") + .example("my-secret"), + namespace: common_1.joiIdentifier() + .default("default") + .description("The namespace where the secret is stored. " + + "If necessary, the secret may be copied to the appropriate namespace before use."), +}) + .description("Reference to a Kubernetes secret."); +const imagePullSecretsSchema = common_1.joiArray(secretRef) + .description(dedent ` + References to \`docker-registry\` secrets to use for authenticating with remote registries when pulling + images. This is necessary if you reference private images in your module configuration, and is required + when configuring a remote Kubernetes environment. + `); +const tlsCertificateSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier() + .required() + .description("A unique identifier for this certificate.") + .example("www") + .example("wildcard"), + hostnames: Joi.array().items(Joi.string().hostname()) + .description("A list of hostnames that this certificate should be used for. " + + "If you don't specify these, they will be automatically read from the certificate.") + .example(["www.mydomain.com"]), + secretRef: secretRef + .description("A reference to the Kubernetes secret that contains the TLS certificate and key for the domain.") + .example({ name: "my-tls-secret", namespace: "default" }), +}); +exports.kubernetesConfigBase = project_1.providerConfigBaseSchema + .keys({ + defaultHostname: Joi.string() + .description("A default hostname to use when no hostname is explicitly configured for a service.") + .example("api.mydomain.com"), + defaultUsername: common_1.joiIdentifier() + .description("Set a default username (used for namespacing within a cluster)."), + forceSsl: Joi.boolean() + .default(false) + .description("Require SSL on all services. If set to true, an error is raised when no certificate " + + "is available for a configured hostname."), + imagePullSecrets: imagePullSecretsSchema, + namespace: Joi.string() + .description("Specify which namespace to deploy services to (auto-generated by default). " + + "Note that the framework generates other namespaces as well with this name as a prefix."), + tlsCertificates: common_1.joiArray(tlsCertificateSchema) + .unique("name") + .description("One or more certificates to use for ingress."), +}); +const configSchema = exports.kubernetesConfigBase + .keys({ + context: exports.k8sContextSchema + .required(), + deploymentRegistry: container_1.containerRegistryConfigSchema, + ingressClass: Joi.string() + .default("nginx") + .description(dedent ` + The ingress class to use on configured Ingresses when deploying services. **Note that Garden + currently only supports the nginx ingress controller.** + `), + ingressHttpPort: Joi.number() + .default(80) + .description("The external HTTP port of the cluster's ingress controller."), + ingressHttpsPort: Joi.number() + .default(443) + .description("The external HTTPS port of the cluster's ingress controller."), + _system: Joi.any().meta({ internal: true }), +}); +function gardenPlugin({ config }) { + config = common_1.validate(config, configSchema, { context: "kubernetes provider config" }); + return { + config, + actions: { + getEnvironmentStatus: init_1.getRemoteEnvironmentStatus, + prepareEnvironment: init_1.prepareRemoteEnvironment, + cleanupEnvironment: init_1.cleanupEnvironment, + getSecret: secrets_1.getSecret, + setSecret: secrets_1.setSecret, + deleteSecret: secrets_1.deleteSecret, + }, + moduleActions: { + container: { + getServiceStatus: deployment_1.getContainerServiceStatus, + deployService: deployment_1.deployContainerService, + deleteService: actions_1.deleteService, + getServiceOutputs: actions_1.getServiceOutputs, + execInService: actions_1.execInService, + pushModule: deployment_1.pushModule, + runModule: actions_1.runModule, + testModule: actions_1.testModule, + runService: actions_1.runService, + getTestResult: actions_1.getTestResult, + getServiceLogs: actions_1.getServiceLogs, + }, + helm: helm_1.helmHandlers, + }, + }; +} +exports.gardenPlugin = gardenPlugin; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9rdWJlcm5ldGVzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBRUgsMkJBQTBCO0FBQzFCLGlDQUFpQztBQUVqQyxnREFJNEI7QUFFNUIsa0RBQXlGO0FBQ3pGLHVDQVNrQjtBQUNsQiw2Q0FBNEY7QUFDNUYsaUNBQXFDO0FBQ3JDLHVDQUE4RDtBQUM5RCw0Q0FBcUY7QUFDckYsaUNBQWlHO0FBRXBGLFFBQUEsSUFBSSxHQUFHLFlBQVksQ0FBQTtBQWdDbkIsUUFBQSxnQkFBZ0IsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFO0tBQ3pDLFFBQVEsRUFBRTtLQUNWLFdBQVcsQ0FBQyxrRUFBa0UsQ0FBQztLQUMvRSxPQUFPLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTtBQUU1QixNQUFNLFNBQVMsR0FBRyxHQUFHLENBQUMsTUFBTSxFQUFFO0tBQzNCLElBQUksQ0FBQztJQUNKLElBQUksRUFBRSxzQkFBYSxFQUFFO1NBQ2xCLFFBQVEsRUFBRTtTQUNWLFdBQVcsQ0FBQyxvQ0FBb0MsQ0FBQztTQUNqRCxPQUFPLENBQUMsV0FBVyxDQUFDO0lBQ3ZCLFNBQVMsRUFBRSxzQkFBYSxFQUFFO1NBQ3ZCLE9BQU8sQ0FBQyxTQUFTLENBQUM7U0FDbEIsV0FBVyxDQUNWLDRDQUE0QztRQUM1QyxpRkFBaUYsQ0FDbEY7Q0FDSixDQUFDO0tBQ0QsV0FBVyxDQUFDLG1DQUFtQyxDQUFDLENBQUE7QUFFbkQsTUFBTSxzQkFBc0IsR0FBRyxpQkFBUSxDQUFDLFNBQVMsQ0FBQztLQUMvQyxXQUFXLENBQUMsTUFBTSxDQUFBOzs7O0dBSWxCLENBQUMsQ0FBQTtBQUVKLE1BQU0sb0JBQW9CLEdBQUcsR0FBRyxDQUFDLE1BQU0sRUFBRTtLQUN0QyxJQUFJLENBQUM7SUFDSixJQUFJLEVBQUUsc0JBQWEsRUFBRTtTQUNsQixRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsMkNBQTJDLENBQUM7U0FDeEQsT0FBTyxDQUFD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VixTQUFTLEVBQVQsbUJBQVM7Z0JBQ1QsVUFBVSxFQUFWLG9CQUFVO2dCQUNWLFVBQVUsRUFBVixvQkFBVTtnQkFDVixhQUFhLEVBQWIsdUJBQWE7Z0JBQ2IsY0FBYyxFQUFkLHdCQUFjO2FBQ2Y7WUFDRCxJQUFJLEVBQUUsbUJBQVk7U0FDbkI7S0FDRixDQUFBO0FBQ0gsQ0FBQztBQTlCRCxvQ0E4QkMiLCJmaWxlIjoicGx1Z2lucy9rdWJlcm5ldGVzL2t1YmVybmV0ZXMuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IGRlZGVudCA9IHJlcXVpcmUoXCJkZWRlbnRcIilcblxuaW1wb3J0IHtcbiAgam9pQXJyYXksXG4gIGpvaUlkZW50aWZpZXIsXG4gIHZhbGlkYXRlLFxufSBmcm9tIFwiLi4vLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBHYXJkZW5QbHVnaW4gfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQgeyBQcm92aWRlciwgcHJvdmlkZXJDb25maWdCYXNlU2NoZW1hLCBQcm92aWRlckNvbmZpZyB9IGZyb20gXCIuLi8uLi9jb25maWcvcHJvamVjdFwiXG5pbXBvcnQge1xuICBkZWxldGVTZXJ2aWNlLFxuICBleGVjSW5TZXJ2aWNlLFxuICBnZXRTZXJ2aWNlTG9ncyxcbiAgZ2V0U2VydmljZU91dHB1dHMsXG4gIGdldFRlc3RSZXN1bHQsXG4gIHRlc3RNb2R1bGUsXG4gIHJ1bk1vZHVsZSxcbiAgcnVuU2VydmljZSxcbn0gZnJvbSBcIi4vYWN0aW9uc1wiXG5pbXBvcnQgeyBkZXBsb3lDb250YWluZXJTZXJ2aWNlLCBnZXRDb250YWluZXJTZXJ2aWNlU3RhdHVzLCBwdXNoTW9kdWxlIH0gZnJvbSBcIi4vZGVwbG95bWVudFwiXG5pbXBvcnQgeyBoZWxtSGFuZGxlcnMgfSBmcm9tIFwiLi9oZWxtXCJcbmltcG9ydCB7IGdldFNlY3JldCwgc2V0U2VjcmV0LCBkZWxldGVTZWNyZXQgfSBmcm9tIFwiLi9zZWNyZXRzXCJcbmltcG9ydCB7IGNvbnRhaW5lclJlZ2lzdHJ5Q29uZmlnU2NoZW1hLCBDb250YWluZXJSZWdpc3RyeUNvbmZpZyB9IGZyb20gXCIuLi9jb250YWluZXJcIlxuaW1wb3J0IHsgZ2V0UmVtb3RlRW52aXJvbm1lbnRTdGF0dXMsIHByZXBhcmVSZW1vdGVFbnZpcm9ubWVudCwgY2xlYW51cEVudmlyb25tZW50IH0gZnJvbSBcIi4vaW5pdFwiXG5cbmV4cG9ydCBjb25zdCBuYW1lID0gXCJrdWJlcm5ldGVzXCJcblxuZXhwb3J0IGludGVyZmFjZSBTZWNyZXRSZWYge1xuICBuYW1lOiBzdHJpbmdcbiAgbmFtZXNwYWNlOiBzdHJpbmdcbn1cblxuZXhwb3J0IGludGVyZmFjZSBJbmdyZXNzVGxzQ2VydGlmaWNhdGUge1xuICBuYW1lOiBzdHJpbmdcbiAgaG9zdG5hbWVzPzogc3RyaW5nW11cbiAgc2VjcmV0UmVmOiBTZWNyZXRSZWZcbn1cblxuZXhwb3J0IGludGVyZmFjZSBLdWJlcm5ldGVzQmFzZUNvbmZpZyBleHRlbmRzIFByb3ZpZGVyQ29uZmlnIHtcbiAgY29udGV4dDogc3RyaW5nXG4gIGRlZmF1bHRIb3N0bmFtZT86IHN0cmluZ1xuICBkZWZhdWx0VXNlcm5hbWU/OiBzdHJpbmdcbiAgZm9yY2VTc2w6IGJvb2xlYW5cbiAgaW1hZ2VQdWxsU2VjcmV0czogU2VjcmV0UmVmW11cbiAgaW5ncmVzc0h0dHBQb3J0OiBudW1iZXJcbiAgaW5ncmVzc0h0dHBzUG9ydDogbnVtYmVyXG4gIGluZ3Jlc3NDbGFzczogc3RyaW5nXG4gIG5hbWVzcGFjZT86IHN0cmluZ1xuICB0bHNDZXJ0aWZpY2F0ZXM6IEluZ3Jlc3NUbHNDZXJ0aWZpY2F0ZVtdXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgS3ViZXJuZXRlc0NvbmZpZyBleHRlbmRzIEt1YmVybmV0ZXNCYXNlQ29uZmlnIHtcbiAgZGVwbG95bWVudFJlZ2lzdHJ5OiBDb250YWluZXJSZWdpc3RyeUNvbmZpZ1xufVxuXG5leHBvcnQgdHlwZSBLdWJlcm5ldGVzUHJvdmlkZXIgPSBQcm92aWRlcjxLdWJlcm5ldGVzQ29uZmlnPlxuXG5leHBvcnQgY29uc3QgazhzQ29udGV4dFNjaGVtYSA9IEpvaS5zdHJpbmcoKVxuICAucmVxdWlyZWQoKVxuICAuZGVzY3JpcHRpb24oXCJUaGUga3ViZWN0bCBjb250ZXh0IHRvIHVzZSB0byBjb25uZWN0IHRvIHRoZSBLdWJlcm5ldGVzIGNsdXN0ZXIuXCIpXG4gIC5leGFtcGxlKFwibXktZGV2LWNvbnRleHRcIilcblxuY29uc3Qgc2VjcmV0UmVmID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBuYW1lOiBqb2lJZGVudGlmaWVyKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZSBvZiB0aGUgS3ViZXJuZXRlcyBzZWNyZXQuXCIpXG4gICAgICAuZXhhbXBsZShcIm15LXNlY3JldFwiKSxcbiAgICBuYW1lc3BhY2U6IGpvaUlkZW50aWZpZXIoKVxuICAgICAgLmRlZmF1bHQoXCJkZWZhdWx0XCIpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiVGhlIG5hbWVzcGFjZSB3aGVyZSB0aGUgc2VjcmV0IGlzIHN0b3JlZC4gXCIgK1xuICAgICAgICBcIklmIG5lY2Vzc2FyeSwgdGhlIHNlY3JldCBtYXkgYmUgY29waWVkIHRvIHRoZSBhcHByb3ByaWF0ZSBuYW1lc3BhY2UgYmVmb3JlIHVzZS5cIixcbiAgICAgICksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIlJlZmVyZW5jZSB0byBhIEt1YmVybmV0ZXMgc2VjcmV0LlwiKVxuXG5jb25zdCBpbWFnZVB1bGxTZWNyZXRzU2NoZW1hID0gam9pQXJyYXkoc2VjcmV0UmVmKVxuICAuZGVzY3JpcHRpb24oZGVkZW50YFxuICAgIFJlZmVyZW5jZXMgdG8gXFxgZG9ja2VyLXJlZ2lzdHJ5XFxgIHNlY3JldHMgdG8gdXNlIGZvciBhdXRoZW50aWNhdGluZyB3aXRoIHJlbW90ZSByZWdpc3RyaWVzIHdoZW4gcHVsbGluZ1xuICAgIGltYWdlcy4gVGhpcyBpcyBuZWNlc3NhcnkgaWYgeW91IHJlZmVyZW5jZSBwcml2YXRlIGltYWdlcyBpbiB5b3VyIG1vZHVsZSBjb25maWd1cmF0aW9uLCBhbmQgaXMgcmVxdWlyZWRcbiAgICB3aGVuIGNvbmZpZ3VyaW5nIGEgcmVtb3RlIEt1YmVybmV0ZXMgZW52aXJvbm1lbnQuXG4gIGApXG5cbmNvbnN0IHRsc0NlcnRpZmljYXRlU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBuYW1lOiBqb2lJZGVudGlmaWVyKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJBIHVuaXF1ZSBpZGVudGlmaWVyIGZvciB0aGlzIGNlcnRpZmljYXRlLlwiKVxuICAgICAgLmV4YW1wbGUoXCJ3d3dcIilcbiAgICAgIC5leGFtcGxlKFwid2lsZGNhcmRcIiksXG4gICAgaG9zdG5hbWVzOiBKb2kuYXJyYXkoKS5pdGVtcyhKb2kuc3RyaW5nKCkuaG9zdG5hbWUoKSlcbiAgICAgIC5kZXNjcmlwdGlvbihcbiAgICAgICAgXCJBIGxpc3Qgb2YgaG9zdG5hbWVzIHRoYXQgdGhpcyBjZXJ0aWZpY2F0ZSBzaG91bGQgYmUgdXNlZCBmb3IuIFwiICtcbiAgICAgICAgXCJJZiB5b3UgZG9uJ3Qgc3BlY2lmeSB0aGVzZSwgdGhleSB3aWxsIGJlIGF1dG9tYXRpY2FsbHkgcmVhZCBmcm9tIHRoZSBjZXJ0aWZpY2F0ZS5cIixcbiAgICAgIClcbiAgICAgIC5leGFtcGxlKFtcInd3dy5teWRvbWFpbi5jb21cIl0pLFxuICAgIHNlY3JldFJlZjogc2VjcmV0UmVmXG4gICAgICAuZGVzY3JpcHRpb24oXCJBIHJlZmVyZW5jZSB0byB0aGUgS3ViZXJuZXRlcyBzZWNyZXQgdGhhdCBjb250YWlucyB0aGUgVExTIGNlcnRpZmljYXRlIGFuZCBrZXkgZm9yIHRoZSBkb21haW4uXCIpXG4gICAgICAuZXhhbXBsZSh7IG5hbWU6IFwibXktdGxzLXNlY3JldFwiLCBuYW1lc3BhY2U6IFwiZGVmYXVsdFwiIH0pLFxuICB9KVxuXG5leHBvcnQgY29uc3Qga3ViZXJuZXRlc0NvbmZpZ0Jhc2UgPSBwcm92aWRlckNvbmZpZ0Jhc2VTY2hlbWFcbiAgLmtleXMoe1xuICAgIGRlZmF1bHRIb3N0bmFtZTogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJBIGRlZmF1bHQgaG9zdG5hbWUgdG8gdXNlIHdoZW4gbm8gaG9zdG5hbWUgaXMgZXhwbGljaXRseSBjb25maWd1cmVkIGZvciBhIHNlcnZpY2UuXCIpXG4gICAgICAuZXhhbXBsZShcImFwaS5teWRvbWFpbi5jb21cIiksXG4gICAgZGVmYXVsdFVzZXJuYW1lOiBqb2lJZGVudGlmaWVyKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNldCBhIGRlZmF1bHQgdXNlcm5hbWUgKHVzZWQgZm9yIG5hbWVzcGFjaW5nIHdpdGhpbiBhIGNsdXN0ZXIpLlwiKSxcbiAgICBmb3JjZVNzbDogSm9pLmJvb2xlYW4oKVxuICAgICAgLmRlZmF1bHQoZmFsc2UpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiUmVxdWlyZSBTU0wgb24gYWxsIHNlcnZpY2VzLiBJZiBzZXQgdG8gdHJ1ZSwgYW4gZXJyb3IgaXMgcmFpc2VkIHdoZW4gbm8gY2VydGlmaWNhdGUgXCIgK1xuICAgICAgICBcImlzIGF2YWlsYWJsZSBmb3IgYSBjb25maWd1cmVkIGhvc3RuYW1lLlwiLFxuICAgICAgKSxcbiAgICBpbWFnZVB1bGxTZWNyZXRzOiBpbWFnZVB1bGxTZWNyZXRzU2NoZW1hLFxuICAgIG5hbWVzcGFjZTogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiU3BlY2lmeSB3aGljaCBuYW1lc3BhY2UgdG8gZGVwbG95IHNlcnZpY2VzIHRvIChhdXRvLWdlbmVyYXRlZCBieSBkZWZhdWx0KS4gXCIgK1xuICAgICAgICBcIk5vdGUgdGhhdCB0aGUgZnJhbWV3b3JrIGdlbmVyYXRlcyBvdGhlciBuYW1lc3BhY2VzIGFzIHdlbGwgd2l0aCB0aGlzIG5hbWUgYXMgYSBwcmVmaXguXCIsXG4gICAgICApLFxuICAgIHRsc0NlcnRpZmljYXRlczogam9pQXJyYXkodGxzQ2VydGlmaWNhdGVTY2hlbWEpXG4gICAgICAudW5pcXVlKFwibmFtZVwiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiT25lIG9yIG1vcmUgY2VydGlmaWNhdGVzIHRvIHVzZSBmb3IgaW5ncmVzcy5cIiksXG4gIH0pXG5cbmNvbnN0IGNvbmZpZ1NjaGVtYSA9IGt1YmVybmV0ZXNDb25maWdCYXNlXG4gIC5rZXlzKHtcbiAgICBjb250ZXh0OiBrOHNDb250ZXh0U2NoZW1hXG4gICAgICAucmVxdWlyZWQoKSxcbiAgICBkZXBsb3ltZW50UmVnaXN0cnk6IGNvbnRhaW5lclJlZ2lzdHJ5Q29uZmlnU2NoZW1hLFxuICAgIGluZ3Jlc3NDbGFzczogSm9pLnN0cmluZygpXG4gICAgICAuZGVmYXVsdChcIm5naW54XCIpXG4gICAgICAuZGVzY3JpcHRpb24oZGVkZW50YFxuICAgICAgICBUaGUgaW5ncmVzcyBjbGFzcyB0byB1c2Ugb24gY29uZmlndXJlZCBJbmdyZXNzZXMgd2hlbiBkZXBsb3lpbmcgc2VydmljZXMuICoqTm90ZSB0aGF0IEdhcmRlblxuICAgICAgICBjdXJyZW50bHkgb25seSBzdXBwb3J0cyB0aGUgbmdpbnggaW5ncmVzcyBjb250cm9sbGVyLioqXG4gICAgICBgKSxcbiAgICBpbmdyZXNzSHR0cFBvcnQ6IEpvaS5udW1iZXIoKVxuICAgICAgLmRlZmF1bHQoODApXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgZXh0ZXJuYWwgSFRUUCBwb3J0IG9mIHRoZSBjbHVzdGVyJ3MgaW5ncmVzcyBjb250cm9sbGVyLlwiKSxcbiAgICBpbmdyZXNzSHR0cHNQb3J0OiBKb2kubnVtYmVyKClcbiAgICAgIC5kZWZhdWx0KDQ0MylcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBleHRlcm5hbCBIVFRQUyBwb3J0IG9mIHRoZSBjbHVzdGVyJ3MgaW5ncmVzcyBjb250cm9sbGVyLlwiKSxcbiAgICBfc3lzdGVtOiBKb2kuYW55KCkubWV0YSh7IGludGVybmFsOiB0cnVlIH0pLFxuICB9KVxuXG5leHBvcnQgZnVuY3Rpb24gZ2FyZGVuUGx1Z2luKHsgY29uZmlnIH06IHsgY29uZmlnOiBLdWJlcm5ldGVzQ29uZmlnIH0pOiBHYXJkZW5QbHVnaW4ge1xuICBjb25maWcgPSB2YWxpZGF0ZShjb25maWcsIGNvbmZpZ1NjaGVtYSwgeyBjb250ZXh0OiBcImt1YmVybmV0ZXMgcHJvdmlkZXIgY29uZmlnXCIgfSlcblxuICByZXR1cm4ge1xuICAgIGNvbmZpZyxcbiAgICBhY3Rpb25zOiB7XG4gICAgICBnZXRFbnZpcm9ubWVudFN0YXR1czogZ2V0UmVtb3RlRW52aXJvbm1lbnRTdGF0dXMsXG4gICAgICBwcmVwYXJlRW52aXJvbm1lbnQ6IHByZXBhcmVSZW1vdGVFbnZpcm9ubWVudCxcbiAgICAgIGNsZWFudXBFbnZpcm9ubWVudCxcbiAgICAgIGdldFNlY3JldCxcbiAgICAgIHNldFNlY3JldCxcbiAgICAgIGRlbGV0ZVNlY3JldCxcbiAgICB9LFxuICAgIG1vZHVsZUFjdGlvbnM6IHtcbiAgICAgIGNvbnRhaW5lcjoge1xuICAgICAgICBnZXRTZXJ2aWNlU3RhdHVzOiBnZXRDb250YWluZXJTZXJ2aWNlU3RhdHVzLFxuICAgICAgICBkZXBsb3lTZXJ2aWNlOiBkZXBsb3lDb250YWluZXJTZXJ2aWNlLFxuICAgICAgICBkZWxldGVTZXJ2aWNlLFxuICAgICAgICBnZXRTZXJ2aWNlT3V0cHV0cyxcbiAgICAgICAgZXhlY0luU2VydmljZSxcbiAgICAgICAgcHVzaE1vZHVsZSxcbiAgICAgICAgcnVuTW9kdWxlLFxuICAgICAgICB0ZXN0TW9kdWxlLFxuICAgICAgICBydW5TZXJ2aWNlLFxuICAgICAgICBnZXRUZXN0UmVzdWx0LFxuICAgICAgICBnZXRTZXJ2aWNlTG9ncyxcbiAgICAgIH0sXG4gICAgICBoZWxtOiBoZWxtSGFuZGxlcnMsXG4gICAgfSxcbiAgfVxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/local.d.ts b/garden-service/build/plugins/kubernetes/local.d.ts new file mode 100644 index 00000000000..ed7517403f7 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/local.d.ts @@ -0,0 +1,13 @@ +import { GardenPlugin } from "../../types/plugin/plugin"; +import { KubernetesBaseConfig } from "./kubernetes"; +export interface LocalKubernetesConfig extends KubernetesBaseConfig { + _system?: Symbol; + _systemServices?: string[]; +} +export declare const name = "local-kubernetes"; +export declare function gardenPlugin({ projectName, config, logEntry }: { + projectName: any; + config: any; + logEntry: any; +}): Promise; +//# sourceMappingURL=local.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/local.js b/garden-service/build/plugins/kubernetes/local.js new file mode 100644 index 00000000000..9f1bd8f72f8 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/local.js @@ -0,0 +1,147 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const execa = require("execa"); +const js_yaml_1 = require("js-yaml"); +const Joi = require("joi"); +const path_1 = require("path"); +const common_1 = require("../../config/common"); +const kubernetes_1 = require("./kubernetes"); +const fs_extra_1 = require("fs-extra"); +const os_1 = require("os"); +const init_1 = require("./init"); +// TODO: split this into separate plugins to handle Docker for Mac and Minikube +// note: this is in order of preference, in case neither is set as the current kubectl context +// and none is explicitly configured in the garden.yml +const supportedContexts = ["docker-for-desktop", "minikube"]; +const kubeConfigPath = path_1.join(os_1.homedir(), ".kube", "config"); +function getKubeConfig() { + return __awaiter(this, void 0, void 0, function* () { + try { + return js_yaml_1.safeLoad((yield fs_extra_1.readFile(kubeConfigPath)).toString()); + } + catch (_a) { + return {}; + } + }); +} +/** + * Automatically set docker environment variables for minikube + * TODO: it would be better to explicitly provide those to docker instead of using process.env + */ +function setMinikubeDockerEnv() { + return __awaiter(this, void 0, void 0, function* () { + const minikubeEnv = yield execa.stdout("minikube", ["docker-env", "--shell=bash"]); + for (const line of minikubeEnv.split("\n")) { + const matched = line.match(/^export (\w+)="(.+)"$/); + if (matched) { + process.env[matched[1]] = matched[2]; + } + } + }); +} +const configSchema = kubernetes_1.kubernetesConfigBase + .keys({ + ingressHostname: Joi.string() + .description("The hostname of the cluster's ingress controller."), + _system: Joi.any().meta({ internal: true }), + _systemServices: Joi.array().items(Joi.string()) + .meta({ internal: true }) + .description("The system services which should be automatically deployed to the cluster."), +}) + .description("The provider configuration for the local-kubernetes plugin."); +exports.name = "local-kubernetes"; +function gardenPlugin({ projectName, config, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + config = common_1.validate(config, configSchema, { context: "local-kubernetes provider config" }); + let context = config.context; + let defaultHostname = config.defaultHostname; + let systemServices; + if (!context) { + // automatically detect supported kubectl context if not explicitly configured + const kubeConfig = yield getKubeConfig(); + const currentContext = kubeConfig["current-context"]; + if (currentContext && supportedContexts.includes(currentContext)) { + // prefer current context if set and supported + context = currentContext; + logEntry.debug({ section: exports.name, msg: `Using current context: ${context}` }); + } + else if (kubeConfig.contexts) { + const availableContexts = kubeConfig.contexts.map(c => c.name); + for (const supportedContext of supportedContexts) { + if (availableContexts.includes(supportedContext)) { + context = supportedContext; + logEntry.debug({ section: exports.name, msg: `Using detected context: ${context}` }); + break; + } + } + } + } + if (!context) { + context = supportedContexts[0]; + logEntry.debug({ section: exports.name, msg: `No kubectl context auto-detected, using default: ${context}` }); + } + if (context === "minikube") { + yield execa("minikube", ["config", "set", "WantUpdateNotification", "false"]); + if (!defaultHostname) { + // use the nip.io service to give a hostname to the instance, if none is explicitly configured + const minikubeIp = yield execa.stdout("minikube", ["ip"]); + defaultHostname = `${projectName}.${minikubeIp}.nip.io`; + } + yield Promise.all([ + // TODO: wait for ingress addon to be ready, if it was previously disabled + execa("minikube", ["addons", "enable", "ingress"]), + setMinikubeDockerEnv(), + ]); + systemServices = []; + } + else { + if (!defaultHostname) { + defaultHostname = `${projectName}.local.app.garden`; + } + } + const k8sConfig = { + name: config.name, + context, + defaultHostname, + defaultUsername: "default", + deploymentRegistry: { + hostname: "foo.garden", + namespace: "_", + }, + forceSsl: false, + imagePullSecrets: config.imagePullSecrets, + ingressHttpPort: 80, + ingressHttpsPort: 443, + ingressClass: "nginx", + tlsCertificates: config.tlsCertificates, + // TODO: support SSL on local deployments + _system: config._system, + _systemServices: systemServices, + }; + const plugin = kubernetes_1.gardenPlugin({ config: k8sConfig }); + // override the environment configuration steps + plugin.actions.getEnvironmentStatus = init_1.getLocalEnvironmentStatus; + plugin.actions.prepareEnvironment = init_1.prepareLocalEnvironment; + // no need to push before deploying locally + delete plugin.moduleActions.container.pushModule; + return plugin; + }); +} +exports.gardenPlugin = gardenPlugin; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9sb2NhbC50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsK0JBQThCO0FBQzlCLHFDQUFrQztBQUNsQywyQkFBMEI7QUFDMUIsK0JBQTJCO0FBRTNCLGdEQUE4QztBQUM5Qyw2Q0FLcUI7QUFDckIsdUNBQW1DO0FBQ25DLDJCQUE0QjtBQUM1QixpQ0FBMkU7QUFFM0UsK0VBQStFO0FBRS9FLDhGQUE4RjtBQUM5RixzREFBc0Q7QUFDdEQsTUFBTSxpQkFBaUIsR0FBRyxDQUFDLG9CQUFvQixFQUFFLFVBQVUsQ0FBQyxDQUFBO0FBQzVELE1BQU0sY0FBYyxHQUFHLFdBQUksQ0FBQyxZQUFPLEVBQUUsRUFBRSxPQUFPLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFFekQsU0FBZSxhQUFhOztRQUMxQixJQUFJO1lBQ0YsT0FBTyxrQkFBUSxDQUFDLENBQUMsTUFBTSxtQkFBUSxDQUFDLGNBQWMsQ0FBQyxDQUFDLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQTtTQUM3RDtRQUFDLFdBQU07WUFDTixPQUFPLEVBQUUsQ0FBQTtTQUNWO0lBQ0gsQ0FBQztDQUFBO0FBRUQ7OztHQUdHO0FBQ0gsU0FBZSxvQkFBb0I7O1FBQ2pDLE1BQU0sV0FBVyxHQUFHLE1BQU0sS0FBSyxDQUFDLE1BQU0sQ0FBQyxVQUFVLEVBQUUsQ0FBQyxZQUFZLEVBQUUsY0FBYyxDQUFDLENBQUMsQ0FBQTtRQUNsRixLQUFLLE1BQU0sSUFBSSxJQUFJLFdBQVcsQ0FBQyxLQUFLLENBQUMsSUFBSSxDQUFDLEVBQUU7WUFDMUMsTUFBTSxPQUFPLEdBQUcsSUFBSSxDQUFDLEtBQUssQ0FBQyx1QkFBdUIsQ0FBQyxDQUFBO1lBQ25ELElBQUksT0FBTyxFQUFFO2dCQUNYLE9BQU8sQ0FBQyxHQUFHLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFDLEdBQUcsT0FBTyxDQUFDLENBQUMsQ0FBQyxDQUFBO2FBQ3JDO1NB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LENBQUMsU0FBUyxDQUFDLFVBQVUsQ0FBQTtRQUVqRCxPQUFPLE1BQU0sQ0FBQTtJQUNmLENBQUM7Q0FBQTtBQXRGRCxvQ0FzRkMiLCJmaWxlIjoicGx1Z2lucy9rdWJlcm5ldGVzL2xvY2FsLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIGV4ZWNhIGZyb20gXCJleGVjYVwiXG5pbXBvcnQgeyBzYWZlTG9hZCB9IGZyb20gXCJqcy15YW1sXCJcbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBHYXJkZW5QbHVnaW4gfSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQgeyB2YWxpZGF0ZSB9IGZyb20gXCIuLi8uLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7XG4gIGdhcmRlblBsdWdpbiBhcyBrOHNQbHVnaW4sXG4gIEt1YmVybmV0ZXNCYXNlQ29uZmlnLFxuICBrdWJlcm5ldGVzQ29uZmlnQmFzZSxcbiAgS3ViZXJuZXRlc0NvbmZpZyxcbn0gZnJvbSBcIi4va3ViZXJuZXRlc1wiXG5pbXBvcnQgeyByZWFkRmlsZSB9IGZyb20gXCJmcy1leHRyYVwiXG5pbXBvcnQgeyBob21lZGlyIH0gZnJvbSBcIm9zXCJcbmltcG9ydCB7IGdldExvY2FsRW52aXJvbm1lbnRTdGF0dXMsIHByZXBhcmVMb2NhbEVudmlyb25tZW50IH0gZnJvbSBcIi4vaW5pdFwiXG5cbi8vIFRPRE86IHNwbGl0IHRoaXMgaW50byBzZXBhcmF0ZSBwbHVnaW5zIHRvIGhhbmRsZSBEb2NrZXIgZm9yIE1hYyBhbmQgTWluaWt1YmVcblxuLy8gbm90ZTogdGhpcyBpcyBpbiBvcmRlciBvZiBwcmVmZXJlbmNlLCBpbiBjYXNlIG5laXRoZXIgaXMgc2V0IGFzIHRoZSBjdXJyZW50IGt1YmVjdGwgY29udGV4dFxuLy8gYW5kIG5vbmUgaXMgZXhwbGljaXRseSBjb25maWd1cmVkIGluIHRoZSBnYXJkZW4ueW1sXG5jb25zdCBzdXBwb3J0ZWRDb250ZXh0cyA9IFtcImRvY2tlci1mb3ItZGVza3RvcFwiLCBcIm1pbmlrdWJlXCJdXG5jb25zdCBrdWJlQ29uZmlnUGF0aCA9IGpvaW4oaG9tZWRpcigpLCBcIi5rdWJlXCIsIFwiY29uZmlnXCIpXG5cbmFzeW5jIGZ1bmN0aW9uIGdldEt1YmVDb25maWcoKTogUHJvbWlzZTxhbnk+IHtcbiAgdHJ5IHtcbiAgICByZXR1cm4gc2FmZUxvYWQoKGF3YWl0IHJlYWRGaWxlKGt1YmVDb25maWdQYXRoKSkudG9TdHJpbmcoKSlcbiAgfSBjYXRjaCB7XG4gICAgcmV0dXJuIHt9XG4gIH1cbn1cblxuLyoqXG4gKiBBdXRvbWF0aWNhbGx5IHNldCBkb2NrZXIgZW52aXJvbm1lbnQgdmFyaWFibGVzIGZvciBtaW5pa3ViZVxuICogVE9ETzogaXQgd291bGQgYmUgYmV0dGVyIHRvIGV4cGxpY2l0bHkgcHJvdmlkZSB0aG9zZSB0byBkb2NrZXIgaW5zdGVhZCBvZiB1c2luZyBwcm9jZXNzLmVudlxuICovXG5hc3luYyBmdW5jdGlvbiBzZXRNaW5pa3ViZURvY2tlckVudigpIHtcbiAgY29uc3QgbWluaWt1YmVFbnYgPSBhd2FpdCBleGVjYS5zdGRvdXQoXCJtaW5pa3ViZVwiLCBbXCJkb2NrZXItZW52XCIsIFwiLS1zaGVsbD1iYXNoXCJdKVxuICBmb3IgKGNvbnN0IGxpbmUgb2YgbWluaWt1YmVFbnYuc3BsaXQoXCJcXG5cIikpIHtcbiAgICBjb25zdCBtYXRjaGVkID0gbGluZS5tYXRjaCgvXmV4cG9ydCAoXFx3Kyk9XCIoLispXCIkLylcbiAgICBpZiAobWF0Y2hlZCkge1xuICAgICAgcHJvY2Vzcy5lbnZbbWF0Y2hlZFsxXV0gPSBtYXRjaGVkWzJdXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTG9jYWxLdWJlcm5ldGVzQ29uZmlnIGV4dGVuZHMgS3ViZXJuZXRlc0Jhc2VDb25maWcge1xuICBfc3lzdGVtPzogU3ltYm9sXG4gIF9zeXN0ZW1TZXJ2aWNlcz86IHN0cmluZ1tdXG59XG5cbmNvbnN0IGNvbmZpZ1NjaGVtYSA9IGt1YmVybmV0ZXNDb25maWdCYXNlXG4gIC5rZXlzKHtcbiAgICBpbmdyZXNzSG9zdG5hbWU6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGhvc3RuYW1lIG9mIHRoZSBjbHVzdGVyJ3MgaW5ncmVzcyBjb250cm9sbGVyLlwiKSxcbiAgICBfc3lzdGVtOiBKb2kuYW55KCkubWV0YSh7IGludGVybmFsOiB0cnVlIH0pLFxuICAgIF9zeXN0ZW1TZXJ2aWNlczogSm9pLmFycmF5KCkuaXRlbXMoSm9pLnN0cmluZygpKVxuICAgICAgLm1ldGEoeyBpbnRlcm5hbDogdHJ1ZSB9KVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHN5c3RlbSBzZXJ2aWNlcyB3aGljaCBzaG91bGQgYmUgYXV0b21hdGljYWxseSBkZXBsb3llZCB0byB0aGUgY2x1c3Rlci5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIlRoZSBwcm92aWRlciBjb25maWd1cmF0aW9uIGZvciB0aGUgbG9jYWwta3ViZXJuZXRlcyBwbHVnaW4uXCIpXG5cbmV4cG9ydCBjb25zdCBuYW1lID0gXCJsb2NhbC1rdWJlcm5ldGVzXCJcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdhcmRlblBsdWdpbih7IHByb2plY3ROYW1lLCBjb25maWcsIGxvZ0VudHJ5IH0pOiBQcm9taXNlPEdhcmRlblBsdWdpbj4ge1xuICBjb25maWcgPSB2YWxpZGF0ZShjb25maWcsIGNvbmZpZ1NjaGVtYSwgeyBjb250ZXh0OiBcImxvY2FsLWt1YmVybmV0ZXMgcHJvdmlkZXIgY29uZmlnXCIgfSlcblxuICBsZXQgY29udGV4dCA9IGNvbmZpZy5jb250ZXh0XG4gIGxldCBkZWZhdWx0SG9zdG5hbWUgPSBjb25maWcuZGVmYXVsdEhvc3RuYW1lXG4gIGxldCBzeXN0ZW1TZXJ2aWNlc1xuXG4gIGlmICghY29udGV4dCkge1xuICAgIC8vIGF1dG9tYXRpY2FsbHkgZGV0ZWN0IHN1cHBvcnRlZCBrdWJlY3RsIGNvbnRleHQgaWYgbm90IGV4cGxpY2l0bHkgY29uZmlndXJlZFxuICAgIGNvbnN0IGt1YmVDb25maWcgPSBhd2FpdCBnZXRLdWJlQ29uZmlnKClcbiAgICBjb25zdCBjdXJyZW50Q29udGV4dCA9IGt1YmVDb25maWdbXCJjdXJyZW50LWNvbnRleHRcIl1cblxuICAgIGlmIChjdXJyZW50Q29udGV4dCAmJiBzdXBwb3J0ZWRDb250ZXh0cy5pbmNsdWRlcyhjdXJyZW50Q29udGV4dCkpIHtcbiAgICAgIC8vIHByZWZlciBjdXJyZW50IGNvbnRleHQgaWYgc2V0IGFuZCBzdXBwb3J0ZWRcbiAgICAgIGNvbnRleHQgPSBjdXJyZW50Q29udGV4dFxuICAgICAgbG9nRW50cnkuZGVidWcoeyBzZWN0aW9uOiBuYW1lLCBtc2c6IGBVc2luZyBjdXJyZW50IGNvbnRleHQ6ICR7Y29udGV4dH1gIH0pXG4gICAgfSBlbHNlIGlmIChrdWJlQ29uZmlnLmNvbnRleHRzKSB7XG4gICAgICBjb25zdCBhdmFpbGFibGVDb250ZXh0cyA9IGt1YmVDb25maWcuY29udGV4dHMubWFwKGMgPT4gYy5uYW1lKVxuXG4gICAgICBmb3IgKGNvbnN0IHN1cHBvcnRlZENvbnRleHQgb2Ygc3VwcG9ydGVkQ29udGV4dHMpIHtcbiAgICAgICAgaWYgKGF2YWlsYWJsZUNvbnRleHRzLmluY2x1ZGVzKHN1cHBvcnRlZENvbnRleHQpKSB7XG4gICAgICAgICAgY29udGV4dCA9IHN1cHBvcnRlZENvbnRleHRcbiAgICAgICAgICBsb2dFbnRyeS5kZWJ1Zyh7IHNlY3Rpb246IG5hbWUsIG1zZzogYFVzaW5nIGRldGVjdGVkIGNvbnRleHQ6ICR7Y29udGV4dH1gIH0pXG4gICAgICAgICAgYnJlYWtcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGlmICghY29udGV4dCkge1xuICAgIGNvbnRleHQgPSBzdXBwb3J0ZWRDb250ZXh0c1swXVxuICAgIGxvZ0VudHJ5LmRlYnVnKHsgc2VjdGlvbjogbmFtZSwgbXNnOiBgTm8ga3ViZWN0bCBjb250ZXh0IGF1dG8tZGV0ZWN0ZWQsIHVzaW5nIGRlZmF1bHQ6ICR7Y29udGV4dH1gIH0pXG4gIH1cblxuICBpZiAoY29udGV4dCA9PT0gXCJtaW5pa3ViZVwiKSB7XG4gICAgYXdhaXQgZXhlY2EoXCJtaW5pa3ViZVwiLCBbXCJjb25maWdcIiwgXCJzZXRcIiwgXCJXYW50VXBkYXRlTm90aWZpY2F0aW9uXCIsIFwiZmFsc2VcIl0pXG5cbiAgICBpZiAoIWRlZmF1bHRIb3N0bmFtZSkge1xuICAgICAgLy8gdXNlIHRoZSBuaXAuaW8gc2VydmljZSB0byBnaXZlIGEgaG9zdG5hbWUgdG8gdGhlIGluc3RhbmNlLCBpZiBub25lIGlzIGV4cGxpY2l0bHkgY29uZmlndXJlZFxuICAgICAgY29uc3QgbWluaWt1YmVJcCA9IGF3YWl0IGV4ZWNhLnN0ZG91dChcIm1pbmlrdWJlXCIsIFtcImlwXCJdKVxuICAgICAgZGVmYXVsdEhvc3RuYW1lID0gYCR7cHJvamVjdE5hbWV9LiR7bWluaWt1YmVJcH0ubmlwLmlvYFxuICAgIH1cblxuICAgIGF3YWl0IFByb21pc2UuYWxsKFtcbiAgICAgIC8vIFRPRE86IHdhaXQgZm9yIGluZ3Jlc3MgYWRkb24gdG8gYmUgcmVhZHksIGlmIGl0IHdhcyBwcmV2aW91c2x5IGRpc2FibGVkXG4gICAgICBleGVjYShcIm1pbmlrdWJlXCIsIFtcImFkZG9uc1wiLCBcImVuYWJsZVwiLCBcImluZ3Jlc3NcIl0pLFxuICAgICAgc2V0TWluaWt1YmVEb2NrZXJFbnYoKSxcbiAgICBdKVxuXG4gICAgc3lzdGVtU2VydmljZXMgPSBbXVxuICB9IGVsc2Uge1xuICAgIGlmICghZGVmYXVsdEhvc3RuYW1lKSB7XG4gICAgICBkZWZhdWx0SG9zdG5hbWUgPSBgJHtwcm9qZWN0TmFtZX0ubG9jYWwuYXBwLmdhcmRlbmBcbiAgICB9XG4gIH1cblxuICBjb25zdCBrOHNDb25maWc6IEt1YmVybmV0ZXNDb25maWcgPSB7XG4gICAgbmFtZTogY29uZmlnLm5hbWUsXG4gICAgY29udGV4dCxcbiAgICBkZWZhdWx0SG9zdG5hbWUsXG4gICAgZGVmYXVsdFVzZXJuYW1lOiBcImRlZmF1bHRcIixcbiAgICBkZXBsb3ltZW50UmVnaXN0cnk6IHtcbiAgICAgIGhvc3RuYW1lOiBcImZvby5nYXJkZW5cIiwgICAvLyB0aGlzIGlzIG5vdCB1c2VkIGJ5IHRoaXMgcGx1Z2luLCBidXQgcmVxdWlyZWQgYnkgdGhlIGJhc2UgcGx1Z2luXG4gICAgICBuYW1lc3BhY2U6IFwiX1wiLFxuICAgIH0sXG4gICAgZm9yY2VTc2w6IGZhbHNlLFxuICAgIGltYWdlUHVsbFNlY3JldHM6IGNvbmZpZy5pbWFnZVB1bGxTZWNyZXRzLFxuICAgIGluZ3Jlc3NIdHRwUG9ydDogODAsXG4gICAgaW5ncmVzc0h0dHBzUG9ydDogNDQzLFxuICAgIGluZ3Jlc3NDbGFzczogXCJuZ2lueFwiLFxuICAgIHRsc0NlcnRpZmljYXRlczogY29uZmlnLnRsc0NlcnRpZmljYXRlcyxcbiAgICAvLyBUT0RPOiBzdXBwb3J0IFNTTCBvbiBsb2NhbCBkZXBsb3ltZW50c1xuICAgIF9zeXN0ZW06IGNvbmZpZy5fc3lzdGVtLFxuICAgIF9zeXN0ZW1TZXJ2aWNlczogc3lzdGVtU2VydmljZXMsXG4gIH1cblxuICBjb25zdCBwbHVnaW4gPSBrOHNQbHVnaW4oeyBjb25maWc6IGs4c0NvbmZpZyB9KVxuXG4gIC8vIG92ZXJyaWRlIHRoZSBlbnZpcm9ubWVudCBjb25maWd1cmF0aW9uIHN0ZXBzXG4gIHBsdWdpbi5hY3Rpb25zIS5nZXRFbnZpcm9ubWVudFN0YXR1cyA9IGdldExvY2FsRW52aXJvbm1lbnRTdGF0dXNcbiAgcGx1Z2luLmFjdGlvbnMhLnByZXBhcmVFbnZpcm9ubWVudCA9IHByZXBhcmVMb2NhbEVudmlyb25tZW50XG5cbiAgLy8gbm8gbmVlZCB0byBwdXNoIGJlZm9yZSBkZXBsb3lpbmcgbG9jYWxseVxuICBkZWxldGUgcGx1Z2luLm1vZHVsZUFjdGlvbnMhLmNvbnRhaW5lci5wdXNoTW9kdWxlXG5cbiAgcmV0dXJuIHBsdWdpblxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/namespace.d.ts b/garden-service/build/plugins/kubernetes/namespace.d.ts new file mode 100644 index 00000000000..6ea6c81207a --- /dev/null +++ b/garden-service/build/plugins/kubernetes/namespace.d.ts @@ -0,0 +1,14 @@ +import { PluginContext } from "../../plugin-context"; +import { KubeApi } from "./api"; +import { KubernetesProvider } from "./kubernetes"; +export declare function ensureNamespace(api: KubeApi, namespace: string): Promise; +export declare function getNamespace({ ctx, provider, suffix, skipCreate }: { + ctx: PluginContext; + provider: KubernetesProvider; + suffix?: string; + skipCreate?: boolean; +}): Promise; +export declare function getAppNamespace(ctx: PluginContext, provider: KubernetesProvider): Promise; +export declare function getMetadataNamespace(ctx: PluginContext, provider: KubernetesProvider): Promise; +export declare function getAllGardenNamespaces(api: KubeApi): Promise; +//# sourceMappingURL=namespace.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/namespace.js b/garden-service/build/plugins/kubernetes/namespace.js new file mode 100644 index 00000000000..32631ad1c12 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/namespace.js @@ -0,0 +1,99 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const api_1 = require("./api"); +const kubernetes_1 = require("./kubernetes"); +const exceptions_1 = require("../../exceptions"); +const created = {}; +function ensureNamespace(api, namespace) { + return __awaiter(this, void 0, void 0, function* () { + if (!created[namespace]) { + const namespacesStatus = yield api.core.listNamespace(); + for (const n of namespacesStatus.body.items) { + if (n.status.phase === "Active") { + created[n.metadata.name] = true; + } + } + if (!created[namespace]) { + // TODO: the types for all the create functions in the library are currently broken + yield api.core.createNamespace({ + apiVersion: "v1", + kind: "Namespace", + metadata: { + name: namespace, + annotations: { + "garden.io/generated": "true", + }, + }, + }); + created[namespace] = true; + } + } + }); +} +exports.ensureNamespace = ensureNamespace; +function getNamespace({ ctx, provider, suffix, skipCreate }) { + return __awaiter(this, void 0, void 0, function* () { + let namespace; + if (provider.config.namespace) { + namespace = provider.config.namespace; + } + else { + const localConfig = yield ctx.localConfigStore.get(); + const k8sConfig = localConfig.kubernetes || {}; + let { username, ["previous-usernames"]: previousUsernames } = k8sConfig; + if (!username) { + username = provider.config.defaultUsername; + } + if (!username) { + throw new exceptions_1.AuthenticationError(`User not logged into provider ${kubernetes_1.name}. Please specify defaultUsername in provider ` + + `config or run garden init.`, { previousUsernames, provider: kubernetes_1.name }); + } + namespace = `garden--${username}--${ctx.projectName}`; + } + if (suffix) { + namespace = `${namespace}--${suffix}`; + } + if (!skipCreate) { + const api = new api_1.KubeApi(provider); + yield ensureNamespace(api, namespace); + } + return namespace; + }); +} +exports.getNamespace = getNamespace; +function getAppNamespace(ctx, provider) { + return __awaiter(this, void 0, void 0, function* () { + return getNamespace({ ctx, provider }); + }); +} +exports.getAppNamespace = getAppNamespace; +function getMetadataNamespace(ctx, provider) { + return getNamespace({ ctx, provider, suffix: "metadata" }); +} +exports.getMetadataNamespace = getMetadataNamespace; +function getAllGardenNamespaces(api) { + return __awaiter(this, void 0, void 0, function* () { + const allNamespaces = yield api.core.listNamespace(); + return allNamespaces.body.items + .map(n => n.metadata.name) + .filter(n => n.startsWith("garden--")); + }); +} +exports.getAllGardenNamespaces = getAllGardenNamespaces; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9uYW1lc3BhY2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUdILCtCQUErQjtBQUUvQiw2Q0FBbUQ7QUFDbkQsaURBQXNEO0FBRXRELE1BQU0sT0FBTyxHQUFnQyxFQUFFLENBQUE7QUFFL0MsU0FBc0IsZUFBZSxDQUFDLEdBQVksRUFBRSxTQUFpQjs7UUFDbkUsSUFBSSxDQUFDLE9BQU8sQ0FBQyxTQUFTLENBQUMsRUFBRTtZQUN2QixNQUFNLGdCQUFnQixHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLEVBQUUsQ0FBQTtZQUV2RCxLQUFLLE1BQU0sQ0FBQyxJQUFJLGdCQUFnQixDQUFDLElBQUksQ0FBQyxLQUFLLEVBQUU7Z0JBQzNDLElBQUksQ0FBQyxDQUFDLE1BQU0sQ0FBQyxLQUFLLEtBQUssUUFBUSxFQUFFO29CQUMvQixPQUFPLENBQUMsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsR0FBRyxJQUFJLENBQUE7aUJBQ2hDO2FBQ0Y7WUFFRCxJQUFJLENBQUMsT0FBTyxDQUFDLFNBQVMsQ0FBQyxFQUFFO2dCQUN2QixtRkFBbUY7Z0JBQ25GLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQU07b0JBQ2xDLFVBQVUsRUFBRSxJQUFJO29CQUNoQixJQUFJLEVBQUUsV0FBVztvQkFDakIsUUFBUSxFQUFFO3dCQUNSLElBQUksRUFBRSxTQUFTO3dCQUNmLFdBQVcsRUFBRTs0QkFDWCxxQkFBcUIsRUFBRSxNQUFNO3lCQUM5QjtxQkFDRjtpQkFDRixDQUFDLENBQUE7Z0JBQ0YsT0FBTyxDQUFDLFNBQVMsQ0FBQyxHQUFHLElBQUksQ0FBQTthQUMxQjtTQUNGO0lBQ0gsQ0FBQztDQUFBO0FBekJELDBDQXlCQztBQUVELFNBQXNCLFlBQVksQ0FDaEMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLE1BQU0sRUFBRSxVQUFVLEVBQzBEOztRQUU3RixJQUFJLFNBQVMsQ0FBQTtRQUViLElBQUksUUFBUSxDQUFDLE1BQU0sQ0FBQyxTQUFTLEVBQUU7WUFDN0IsU0FBUyxHQUFHLFFBQVEsQ0FBQyxNQUFNLENBQUMsU0FBUyxDQUFBO1NBQ3RDO2FBQU07WUFDTCxNQUFNLFdBQVcsR0FBRyxNQUFNLEdBQUcsQ0FBQyxnQkFBZ0IsQ0FBQyxHQUFHLEVBQUUsQ0FBQTtZQUNwRCxNQUFNLFNBQVMsR0FBRyxXQUFXLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQTtZQUM5QyxJQUFJLEVBQUUsUUFBUSxFQUFFLENBQUMsb0JBQW9CLENBQUMsRUFBRSxpQkFBaUIsRUFBRSxHQUFHLFNBQVMsQ0FBQTtZQUV2RSxJQUFJLENBQUMsUUFBUSxFQUFFO2dCQUNiLFFBQVEsR0FBRyxRQUFRLENBQUMsTUFBTSxDQUFDLGVBQWUsQ0FBQTthQUMzQztZQUVELElBQUksQ0FBQyxRQUFRLEVBQUU7Z0JBQ2IsTUFBTSxJQUFJLGdDQUFtQixDQUMzQixpQ0FBaUMsaUJBQVksK0NBQStDO29CQUM1Riw0QkFBNEIsRUFDNUIsRUFBRSxpQkFBaUIsRUFBRSxRQUFRLEVBQUUsaUJBQVksRUFBRSxDQUM5QyxDQUFBO2FBQ0Y7WUFFRCxTQUFTLEdBQUcsV0FBVyxRQUFRLEtBQUssR0FBRyxDQUFDLFdBQVcsRUFBRSxDQUFBO1NBQ3REO1FBRUQsSUFBSSxNQUFNLEVBQUU7WUFDVixTQUFTLEdBQUcsR0FBRyxTQUFTLEtBQUssTUFBTSxFQUFFLENBQUE7U0FDdEM7UUFFRCxJQUFJLENBQUMsVUFBVSxFQUFFO1lBQ2YsTUFBTSxHQUFHLEdBQUcsSUFBSSxhQUFPLENBQUMsUUFBUSxDQUFDLENBQUE7WUFDakMsTUFBTSxlQUFlLENBQUMsR0FBRyxFQUFFLFNBQVMsQ0FBQyxDQUFBO1NBQ3RDO1FBRUQsT0FBTyxTQUFTLENBQUE7SUFDbEIsQ0FBQztDQUFBO0FBdENELG9DQXNDQztBQUVELFNBQXNCLGVBQWUsQ0FBQyxHQUFrQixFQUFFLFFBQTRCOztRQUNwRixPQUFPLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFBO0lBQ3hDLENBQUM7Q0FBQTtBQUZELDBDQUVDO0FBRUQsU0FBZ0Isb0JBQW9CLENBQUMsR0FBa0IsRUFBRSxRQUE0QjtJQUNuRixPQUFPLFlBQVksQ0FBQyxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxDQUFDLENBQUE7QUFDNUQsQ0FBQztBQUZELG9EQUVDO0FBRUQsU0FBc0Isc0JBQXNCLENBQUMsR0FBWTs7UUFDdkQsTUFBTSxhQUFhLEdBQUcsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFBO1FBQ3BELE9BQU8sYUFBYSxDQUFDLElBQUksQ0FBQyxLQUFLO2FBQzVCLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDO2FBQ3pCLE1BQU0sQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FBQTtJQUMxQyxDQUFDO0NBQUE7QUFMRCx3REFLQyIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvbmFtZXNwYWNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IFBsdWdpbkNvbnRleHQgfSBmcm9tIFwiLi4vLi4vcGx1Z2luLWNvbnRleHRcIlxuaW1wb3J0IHsgS3ViZUFwaSB9IGZyb20gXCIuL2FwaVwiXG5pbXBvcnQgeyBLdWJlcm5ldGVzUHJvdmlkZXIgfSBmcm9tIFwiLi9rdWJlcm5ldGVzXCJcbmltcG9ydCB7IG5hbWUgYXMgcHJvdmlkZXJOYW1lIH0gZnJvbSBcIi4va3ViZXJuZXRlc1wiXG5pbXBvcnQgeyBBdXRoZW50aWNhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuXG5jb25zdCBjcmVhdGVkOiB7IFtuYW1lOiBzdHJpbmddOiBib29sZWFuIH0gPSB7fVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZW5zdXJlTmFtZXNwYWNlKGFwaTogS3ViZUFwaSwgbmFtZXNwYWNlOiBzdHJpbmcpIHtcbiAgaWYgKCFjcmVhdGVkW25hbWVzcGFjZV0pIHtcbiAgICBjb25zdCBuYW1lc3BhY2VzU3RhdHVzID0gYXdhaXQgYXBpLmNvcmUubGlzdE5hbWVzcGFjZSgpXG5cbiAgICBmb3IgKGNvbnN0IG4gb2YgbmFtZXNwYWNlc1N0YXR1cy5ib2R5Lml0ZW1zKSB7XG4gICAgICBpZiAobi5zdGF0dXMucGhhc2UgPT09IFwiQWN0aXZlXCIpIHtcbiAgICAgICAgY3JlYXRlZFtuLm1ldGFkYXRhLm5hbWVdID0gdHJ1ZVxuICAgICAgfVxuICAgIH1cblxuICAgIGlmICghY3JlYXRlZFtuYW1lc3BhY2VdKSB7XG4gICAgICAvLyBUT0RPOiB0aGUgdHlwZXMgZm9yIGFsbCB0aGUgY3JlYXRlIGZ1bmN0aW9ucyBpbiB0aGUgbGlicmFyeSBhcmUgY3VycmVudGx5IGJyb2tlblxuICAgICAgYXdhaXQgYXBpLmNvcmUuY3JlYXRlTmFtZXNwYWNlKDxhbnk+e1xuICAgICAgICBhcGlWZXJzaW9uOiBcInYxXCIsXG4gICAgICAgIGtpbmQ6IFwiTmFtZXNwYWNlXCIsXG4gICAgICAgIG1ldGFkYXRhOiB7XG4gICAgICAgICAgbmFtZTogbmFtZXNwYWNlLFxuICAgICAgICAgIGFubm90YXRpb25zOiB7XG4gICAgICAgICAgICBcImdhcmRlbi5pby9nZW5lcmF0ZWRcIjogXCJ0cnVlXCIsXG4gICAgICAgICAgfSxcbiAgICAgICAgfSxcbiAgICAgIH0pXG4gICAgICBjcmVhdGVkW25hbWVzcGFjZV0gPSB0cnVlXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXROYW1lc3BhY2UoXG4gIHsgY3R4LCBwcm92aWRlciwgc3VmZml4LCBza2lwQ3JlYXRlIH06XG4gICAgeyBjdHg6IFBsdWdpbkNvbnRleHQsIHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIsIHN1ZmZpeD86IHN0cmluZywgc2tpcENyZWF0ZT86IGJvb2xlYW4gfSxcbik6IFByb21pc2U8c3RyaW5nPiB7XG4gIGxldCBuYW1lc3BhY2VcblxuICBpZiAocHJvdmlkZXIuY29uZmlnLm5hbWVzcGFjZSkge1xuICAgIG5hbWVzcGFjZSA9IHByb3ZpZGVyLmNvbmZpZy5uYW1lc3BhY2VcbiAgfSBlbHNlIHtcbiAgICBjb25zdCBsb2NhbENvbmZpZyA9IGF3YWl0IGN0eC5sb2NhbENvbmZpZ1N0b3JlLmdldCgpXG4gICAgY29uc3QgazhzQ29uZmlnID0gbG9jYWxDb25maWcua3ViZXJuZXRlcyB8fCB7fVxuICAgIGxldCB7IHVzZXJuYW1lLCBbXCJwcmV2aW91cy11c2VybmFtZXNcIl06IHByZXZpb3VzVXNlcm5hbWVzIH0gPSBrOHNDb25maWdcblxuICAgIGlmICghdXNlcm5hbWUpIHtcbiAgICAgIHVzZXJuYW1lID0gcHJvdmlkZXIuY29uZmlnLmRlZmF1bHRVc2VybmFtZVxuICAgIH1cblxuICAgIGlmICghdXNlcm5hbWUpIHtcbiAgICAgIHRocm93IG5ldyBBdXRoZW50aWNhdGlvbkVycm9yKFxuICAgICAgICBgVXNlciBub3QgbG9nZ2VkIGludG8gcHJvdmlkZXIgJHtwcm92aWRlck5hbWV9LiBQbGVhc2Ugc3BlY2lmeSBkZWZhdWx0VXNlcm5hbWUgaW4gcHJvdmlkZXIgYCArXG4gICAgICAgIGBjb25maWcgb3IgcnVuIGdhcmRlbiBpbml0LmAsXG4gICAgICAgIHsgcHJldmlvdXNVc2VybmFtZXMsIHByb3ZpZGVyOiBwcm92aWRlck5hbWUgfSxcbiAgICAgIClcbiAgICB9XG5cbiAgICBuYW1lc3BhY2UgPSBgZ2FyZGVuLS0ke3VzZXJuYW1lfS0tJHtjdHgucHJvamVjdE5hbWV9YFxuICB9XG5cbiAgaWYgKHN1ZmZpeCkge1xuICAgIG5hbWVzcGFjZSA9IGAke25hbWVzcGFjZX0tLSR7c3VmZml4fWBcbiAgfVxuXG4gIGlmICghc2tpcENyZWF0ZSkge1xuICAgIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKHByb3ZpZGVyKVxuICAgIGF3YWl0IGVuc3VyZU5hbWVzcGFjZShhcGksIG5hbWVzcGFjZSlcbiAgfVxuXG4gIHJldHVybiBuYW1lc3BhY2Vcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFwcE5hbWVzcGFjZShjdHg6IFBsdWdpbkNvbnRleHQsIHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIpIHtcbiAgcmV0dXJuIGdldE5hbWVzcGFjZSh7IGN0eCwgcHJvdmlkZXIgfSlcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1ldGFkYXRhTmFtZXNwYWNlKGN0eDogUGx1Z2luQ29udGV4dCwgcHJvdmlkZXI6IEt1YmVybmV0ZXNQcm92aWRlcikge1xuICByZXR1cm4gZ2V0TmFtZXNwYWNlKHsgY3R4LCBwcm92aWRlciwgc3VmZml4OiBcIm1ldGFkYXRhXCIgfSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldEFsbEdhcmRlbk5hbWVzcGFjZXMoYXBpOiBLdWJlQXBpKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBjb25zdCBhbGxOYW1lc3BhY2VzID0gYXdhaXQgYXBpLmNvcmUubGlzdE5hbWVzcGFjZSgpXG4gIHJldHVybiBhbGxOYW1lc3BhY2VzLmJvZHkuaXRlbXNcbiAgICAubWFwKG4gPT4gbi5tZXRhZGF0YS5uYW1lKVxuICAgIC5maWx0ZXIobiA9PiBuLnN0YXJ0c1dpdGgoXCJnYXJkZW4tLVwiKSlcbn1cbiJdfQ== diff --git a/garden-service/build/plugins/kubernetes/secrets.d.ts b/garden-service/build/plugins/kubernetes/secrets.d.ts new file mode 100644 index 00000000000..722b390e43b --- /dev/null +++ b/garden-service/build/plugins/kubernetes/secrets.d.ts @@ -0,0 +1,17 @@ +import { KubeApi } from "./api"; +import { SecretRef } from "./kubernetes"; +import { GetSecretParams, SetSecretParams, DeleteSecretParams } from "../../types/plugin/params"; +export declare function getSecret({ ctx, key }: GetSecretParams): Promise<{ + value: string; +} | { + value: null; +}>; +export declare function setSecret({ ctx, key, value }: SetSecretParams): Promise<{}>; +export declare function deleteSecret({ ctx, key }: DeleteSecretParams): Promise<{ + found: boolean; +}>; +/** + * Make sure the specified secret exists in the target namespace, copying it if necessary. + */ +export declare function ensureSecret(api: KubeApi, secretRef: SecretRef, targetNamespace: string): Promise; +//# sourceMappingURL=secrets.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/secrets.js b/garden-service/build/plugins/kubernetes/secrets.js new file mode 100644 index 00000000000..f8dc20db483 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/secrets.js @@ -0,0 +1,123 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const api_1 = require("./api"); +const exceptions_1 = require("../../exceptions"); +const namespace_1 = require("./namespace"); +function getSecret({ ctx, key }) { + return __awaiter(this, void 0, void 0, function* () { + const api = new api_1.KubeApi(ctx.provider); + const ns = yield namespace_1.getMetadataNamespace(ctx, ctx.provider); + try { + const res = yield api.core.readNamespacedSecret(key, ns); + return { value: Buffer.from(res.body.data.value, "base64").toString() }; + } + catch (err) { + if (err.code === 404) { + return { value: null }; + } + else { + throw err; + } + } + }); +} +exports.getSecret = getSecret; +function setSecret({ ctx, key, value }) { + return __awaiter(this, void 0, void 0, function* () { + // we store configuration in a separate metadata namespace, so that configs aren't cleared when wiping the namespace + const api = new api_1.KubeApi(ctx.provider); + const ns = yield namespace_1.getMetadataNamespace(ctx, ctx.provider); + const body = { + body: { + apiVersion: "v1", + kind: "Secret", + metadata: { + name: key, + annotations: { + "garden.io/generated": "true", + }, + }, + type: "generic", + stringData: { value }, + }, + }; + try { + yield api.core.createNamespacedSecret(ns, body); + } + catch (err) { + if (err.code === 409) { + yield api.core.patchNamespacedSecret(key, ns, body); + } + else { + throw err; + } + } + return {}; + }); +} +exports.setSecret = setSecret; +function deleteSecret({ ctx, key }) { + return __awaiter(this, void 0, void 0, function* () { + const api = new api_1.KubeApi(ctx.provider); + const ns = yield namespace_1.getMetadataNamespace(ctx, ctx.provider); + try { + yield api.core.deleteNamespacedSecret(key, ns, {}); + } + catch (err) { + if (err.code === 404) { + return { found: false }; + } + else { + throw err; + } + } + return { found: true }; + }); +} +exports.deleteSecret = deleteSecret; +/** + * Make sure the specified secret exists in the target namespace, copying it if necessary. + */ +function ensureSecret(api, secretRef, targetNamespace) { + return __awaiter(this, void 0, void 0, function* () { + let secret; + try { + secret = (yield api.core.readNamespacedSecret(secretRef.name, secretRef.namespace)).body; + } + catch (err) { + if (err.code === 404) { + throw new exceptions_1.ConfigurationError(`Could not find secret '${secretRef.name}' in namespace '${secretRef.namespace}'. ` + + `Have you correctly configured your secrets?`, { + secretRef, + }); + } + else { + throw err; + } + } + if (secretRef.namespace === targetNamespace) { + return; + } + delete secret.metadata.resourceVersion; + secret.metadata.namespace = targetNamespace; + yield api.upsert("Secret", targetNamespace, secret); + }); +} +exports.ensureSecret = ensureSecret; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9zZWNyZXRzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFJSCwrQkFBK0I7QUFFL0IsaURBQXFEO0FBRXJELDJDQUFrRDtBQUVsRCxTQUFzQixTQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFtQjs7UUFDM0QsTUFBTSxHQUFHLEdBQUcsSUFBSSxhQUFPLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxDQUFBO1FBQ3JDLE1BQU0sRUFBRSxHQUFHLE1BQU0sZ0NBQW9CLENBQUMsR0FBRyxFQUFFLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQTtRQUV4RCxJQUFJO1lBQ0YsTUFBTSxHQUFHLEdBQUcsTUFBTSxHQUFHLENBQUMsSUFBSSxDQUFDLG9CQUFvQixDQUFDLEdBQUcsRUFBRSxFQUFFLENBQUMsQ0FBQTtZQUN4RCxPQUFPLEVBQUUsS0FBSyxFQUFFLE1BQU0sQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLFFBQVEsQ0FBQyxDQUFDLFFBQVEsRUFBRSxFQUFFLENBQUE7U0FDeEU7UUFBQyxPQUFPLEdBQUcsRUFBRTtZQUNaLElBQUksR0FBRyxDQUFDLElBQUksS0FBSyxHQUFHLEVBQUU7Z0JBQ3BCLE9BQU8sRUFBRSxLQUFLLEVBQUUsSUFBSSxFQUFFLENBQUE7YUFDdkI7aUJBQU07Z0JBQ0wsTUFBTSxHQUFHLENBQUE7YUFDVjtTQUNGO0lBQ0gsQ0FBQztDQUFBO0FBZEQsOEJBY0M7QUFFRCxTQUFzQixTQUFTLENBQUMsRUFBRSxHQUFHLEVBQUUsR0FBRyxFQUFFLEtBQUssRUFBbUI7O1FBQ2xFLG9IQUFvSDtRQUNwSCxNQUFNLEdBQUcsR0FBRyxJQUFJLGFBQU8sQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLENBQUE7UUFDckMsTUFBTSxFQUFFLEdBQUcsTUFBTSxnQ0FBb0IsQ0FBQyxHQUFHLEVBQUUsR0FB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KlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgVjFTZWNyZXQgfSBmcm9tIFwiQGt1YmVybmV0ZXMvY2xpZW50LW5vZGVcIlxuXG5pbXBvcnQgeyBLdWJlQXBpIH0gZnJvbSBcIi4vYXBpXCJcbmltcG9ydCB7IFNlY3JldFJlZiB9IGZyb20gXCIuL2t1YmVybmV0ZXNcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uLy4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgR2V0U2VjcmV0UGFyYW1zLCBTZXRTZWNyZXRQYXJhbXMsIERlbGV0ZVNlY3JldFBhcmFtcyB9IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IGdldE1ldGFkYXRhTmFtZXNwYWNlIH0gZnJvbSBcIi4vbmFtZXNwYWNlXCJcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFNlY3JldCh7IGN0eCwga2V5IH06IEdldFNlY3JldFBhcmFtcykge1xuICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShjdHgucHJvdmlkZXIpXG4gIGNvbnN0IG5zID0gYXdhaXQgZ2V0TWV0YWRhdGFOYW1lc3BhY2UoY3R4LCBjdHgucHJvdmlkZXIpXG5cbiAgdHJ5IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhcGkuY29yZS5yZWFkTmFtZXNwYWNlZFNlY3JldChrZXksIG5zKVxuICAgIHJldHVybiB7IHZhbHVlOiBCdWZmZXIuZnJvbShyZXMuYm9keS5kYXRhLnZhbHVlLCBcImJhc2U2NFwiKS50b1N0cmluZygpIH1cbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5jb2RlID09PSA0MDQpIHtcbiAgICAgIHJldHVybiB7IHZhbHVlOiBudWxsIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBzZXRTZWNyZXQoeyBjdHgsIGtleSwgdmFsdWUgfTogU2V0U2VjcmV0UGFyYW1zKSB7XG4gIC8vIHdlIHN0b3JlIGNvbmZpZ3VyYXRpb24gaW4gYSBzZXBhcmF0ZSBtZXRhZGF0YSBuYW1lc3BhY2UsIHNvIHRoYXQgY29uZmlncyBhcmVuJ3QgY2xlYXJlZCB3aGVuIHdpcGluZyB0aGUgbmFtZXNwYWNlXG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKGN0eC5wcm92aWRlcilcbiAgY29uc3QgbnMgPSBhd2FpdCBnZXRNZXRhZGF0YU5hbWVzcGFjZShjdHgsIGN0eC5wcm92aWRlcilcbiAgY29uc3QgYm9keSA9IHtcbiAgICBib2R5OiB7XG4gICAgICBhcGlWZXJzaW9uOiBcInYxXCIsXG4gICAgICBraW5kOiBcIlNlY3JldFwiLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZToga2V5LFxuICAgICAgICBhbm5vdGF0aW9uczoge1xuICAgICAgICAgIFwiZ2FyZGVuLmlvL2dlbmVyYXRlZFwiOiBcInRydWVcIixcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgICB0eXBlOiBcImdlbmVyaWNcIixcbiAgICAgIHN0cmluZ0RhdGE6IHsgdmFsdWUgfSxcbiAgICB9LFxuICB9XG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBhcGkuY29yZS5jcmVhdGVOYW1lc3BhY2VkU2VjcmV0KG5zLCA8YW55PmJvZHkpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuY29kZSA9PT0gNDA5KSB7XG4gICAgICBhd2FpdCBhcGkuY29yZS5wYXRjaE5hbWVzcGFjZWRTZWNyZXQoa2V5LCBucywgYm9keSlcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHt9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkZWxldGVTZWNyZXQoeyBjdHgsIGtleSB9OiBEZWxldGVTZWNyZXRQYXJhbXMpIHtcbiAgY29uc3QgYXBpID0gbmV3IEt1YmVBcGkoY3R4LnByb3ZpZGVyKVxuICBjb25zdCBucyA9IGF3YWl0IGdldE1ldGFkYXRhTmFtZXNwYWNlKGN0eCwgY3R4LnByb3ZpZGVyKVxuXG4gIHRyeSB7XG4gICAgYXdhaXQgYXBpLmNvcmUuZGVsZXRlTmFtZXNwYWNlZFNlY3JldChrZXksIG5zLCA8YW55Pnt9KVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoZXJyLmNvZGUgPT09IDQwNCkge1xuICAgICAgcmV0dXJuIHsgZm91bmQ6IGZhbHNlIH1cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG4gIHJldHVybiB7IGZvdW5kOiB0cnVlIH1cbn1cblxuLyoqXG4gKiBNYWtlIHN1cmUgdGhlIHNwZWNpZmllZCBzZWNyZXQgZXhpc3RzIGluIHRoZSB0YXJnZXQgbmFtZXNwYWNlLCBjb3B5aW5nIGl0IGlmIG5lY2Vzc2FyeS5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGVuc3VyZVNlY3JldChhcGk6IEt1YmVBcGksIHNlY3JldFJlZjogU2VjcmV0UmVmLCB0YXJnZXROYW1lc3BhY2U6IHN0cmluZykge1xuICBsZXQgc2VjcmV0OiBWMVNlY3JldFxuXG4gIHRyeSB7XG4gICAgc2VjcmV0ID0gKGF3YWl0IGFwaS5jb3JlLnJlYWROYW1lc3BhY2VkU2VjcmV0KHNlY3JldFJlZi5uYW1lLCBzZWNyZXRSZWYubmFtZXNwYWNlKSkuYm9keVxuICB9IGNhdGNoIChlcnIpIHtcbiAgICBpZiAoZXJyLmNvZGUgPT09IDQwNCkge1xuICAgICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihcbiAgICAgICAgYENvdWxkIG5vdCBmaW5kIHNlY3JldCAnJHtzZWNyZXRSZWYubmFtZX0nIGluIG5hbWVzcGFjZSAnJHtzZWNyZXRSZWYubmFtZXNwYWNlfScuIGAgK1xuICAgICAgICBgSGF2ZSB5b3UgY29ycmVjdGx5IGNvbmZpZ3VyZWQgeW91ciBzZWNyZXRzP2AsXG4gICAgICAgIHtcbiAgICAgICAgICBzZWNyZXRSZWYsXG4gICAgICAgIH0sXG4gICAgICApXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGVyclxuICAgIH1cbiAgfVxuXG4gIGlmIChzZWNyZXRSZWYubmFtZXNwYWNlID09PSB0YXJnZXROYW1lc3BhY2UpIHtcbiAgICByZXR1cm5cbiAgfVxuXG4gIGRlbGV0ZSBzZWNyZXQubWV0YWRhdGEucmVzb3VyY2VWZXJzaW9uXG4gIHNlY3JldC5tZXRhZGF0YS5uYW1lc3BhY2UgPSB0YXJnZXROYW1lc3BhY2VcblxuICBhd2FpdCBhcGkudXBzZXJ0KFwiU2VjcmV0XCIsIHRhcmdldE5hbWVzcGFjZSwgc2VjcmV0KVxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/service.d.ts b/garden-service/build/plugins/kubernetes/service.d.ts new file mode 100644 index 00000000000..8281642a749 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/service.d.ts @@ -0,0 +1,3 @@ +import { ContainerService } from "../container"; +export declare function createServices(service: ContainerService, namespace: string): Promise; +//# sourceMappingURL=service.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/service.js b/garden-service/build/plugins/kubernetes/service.js new file mode 100644 index 00000000000..208293caf06 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/service.js @@ -0,0 +1,70 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +function createServices(service, namespace) { + return __awaiter(this, void 0, void 0, function* () { + const services = []; + const addService = (name, type, servicePorts) => { + services.push({ + apiVersion: "v1", + kind: "Service", + metadata: { + name, + annotations: {}, + namespace, + }, + spec: { + ports: servicePorts, + selector: { + service: service.name, + }, + type, + }, + }); + }; + // first add internally exposed (ClusterIP) service + const internalPorts = []; + const ports = service.spec.ports; + for (const portSpec of ports) { + internalPorts.push({ + name: portSpec.name, + protocol: portSpec.protocol, + targetPort: portSpec.containerPort, + port: portSpec.containerPort, + }); + } + if (internalPorts.length) { + addService(service.name, "ClusterIP", internalPorts); + } + // optionally add a NodePort service for externally open ports, if applicable + // TODO: explore nicer ways to do this + const exposedPorts = ports.filter(portSpec => portSpec.nodePort); + if (exposedPorts.length > 0) { + addService(service.name + "-nodeport", "NodePort", exposedPorts.map(portSpec => ({ + // TODO: do the parsing and defaults when loading the yaml + name: portSpec.name, + protocol: portSpec.protocol, + port: portSpec.containerPort, + nodePort: portSpec.nodePort, + }))); + } + return services; + }); +} +exports.createServices = createServices; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFJSCxTQUFzQixjQUFjLENBQUMsT0FBeUIsRUFBRSxTQUFpQjs7UUFDL0UsTUFBTSxRQUFRLEdBQVEsRUFBRSxDQUFBO1FBRXhCLE1BQU0sVUFBVSxHQUFHLENBQUMsSUFBWSxFQUFFLElBQVksRUFBRSxZQUFtQixFQUFFLEVBQUU7WUFDckUsUUFBUSxDQUFDLElBQUksQ0FBQztnQkFDWixVQUFVLEVBQUUsSUFBSTtnQkFDaEIsSUFBSSxFQUFFLFNBQVM7Z0JBQ2YsUUFBUSxFQUFFO29CQUNSLElBQUk7b0JBQ0osV0FBVyxFQUFFLEVBQUU7b0JBQ2YsU0FBUztpQkFDVjtnQkFDRCxJQUFJLEVBQUU7b0JBQ0osS0FBSyxFQUFFLFlBQVk7b0JBQ25CLFFBQVEsRUFBRTt3QkFDUixPQUFPLEVBQUUsT0FBTyxDQUFDLElBQUk7cUJBQ3RCO29CQUNELElBQUk7aUJBQ0w7YUFDRixDQUFDLENBQUE7UUFDSixDQUFDLENBQUE7UUFFRCxtREFBbUQ7UUFDbkQsTUFBTSxhQUFhLEdBQVEsRUFBRSxDQUFBO1FBQzdCLE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFBO1FBRWhDLEtBQUssTUFBTSxRQUFRLElBQUksS0FBSyxFQUFFO1lBQzVCLGFBQWEsQ0FBQyxJQUFJLENBQUM7Z0JBQ2pCLElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtnQkFDbkIsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2dCQUMzQixVQUFVLEVBQUUsUUFBUSxDQUFDLGFBQWE7Z0JBQ2xDLElBQUksRUFBRSxRQUFRLENBQUMsYUFBYTthQUM3QixDQUFDLENBQUE7U0FDSDtRQUVELElBQUksYUFBYSxDQUFDLE1BQU0sRUFBRTtZQUN4QixVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxXQUFXLEVBQUUsYUFBYSxDQUFDLENBQUE7U0FDckQ7UUFFRCw2RUFBNkU7UUFDN0Usc0NBQXNDO1FBQ3RDLE1BQU0sWUFBWSxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxRQUFRLENBQUMsUUFBUSxDQUFDLENBQUE7UUFFaEUsSUFBSSxZQUFZLENBQUMsTUFBTSxHQUFHLENBQUMsRUFBRTtZQUMzQixVQUFVLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxXQUFXLEVBQUUsVUFBVSxFQUFFLFlBQVksQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLEVBQUUsQ0FBQyxDQUFDO2dCQUMvRSwwREFBMEQ7Z0JBQzFELElBQUksRUFBRSxRQUFRLENBQUMsSUFBSTtnQkFDbkIsUUFBUSxFQUFFLFFBQVEsQ0FBQyxRQUFRO2dCQUMzQixJQUFJLEVBQUUsUUFBUSxDQUFDLGFBQWE7Z0JBQzVCLFFBQVEsRUFBRSxRQUFRLENBQUMsUUFBUTthQUM1QixDQUFDLENBQUMsQ0FBQyxDQUFBO1NBQ0w7UUFFRCxPQUFPLFFBQVEsQ0FBQTtJQUNqQixDQUFDO0NBQUE7QUF0REQsd0NBc0RDIiwiZmlsZSI6InBsdWdpbnMva3ViZXJuZXRlcy9zZXJ2aWNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IENvbnRhaW5lclNlcnZpY2UgfSBmcm9tIFwiLi4vY29udGFpbmVyXCJcblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNyZWF0ZVNlcnZpY2VzKHNlcnZpY2U6IENvbnRhaW5lclNlcnZpY2UsIG5hbWVzcGFjZTogc3RyaW5nKSB7XG4gIGNvbnN0IHNlcnZpY2VzOiBhbnkgPSBbXVxuXG4gIGNvbnN0IGFkZFNlcnZpY2UgPSAobmFtZTogc3RyaW5nLCB0eXBlOiBzdHJpbmcsIHNlcnZpY2VQb3J0czogYW55W10pID0+IHtcbiAgICBzZXJ2aWNlcy5wdXNoKHtcbiAgICAgIGFwaVZlcnNpb246IFwidjFcIixcbiAgICAgIGtpbmQ6IFwiU2VydmljZVwiLFxuICAgICAgbWV0YWRhdGE6IHtcbiAgICAgICAgbmFtZSxcbiAgICAgICAgYW5ub3RhdGlvbnM6IHt9LFxuICAgICAgICBuYW1lc3BhY2UsXG4gICAgICB9LFxuICAgICAgc3BlYzoge1xuICAgICAgICBwb3J0czogc2VydmljZVBvcnRzLFxuICAgICAgICBzZWxlY3Rvcjoge1xuICAgICAgICAgIHNlcnZpY2U6IHNlcnZpY2UubmFtZSxcbiAgICAgICAgfSxcbiAgICAgICAgdHlwZSxcbiAgICAgIH0sXG4gICAgfSlcbiAgfVxuXG4gIC8vIGZpcnN0IGFkZCBpbnRlcm5hbGx5IGV4cG9zZWQgKENsdXN0ZXJJUCkgc2VydmljZVxuICBjb25zdCBpbnRlcm5hbFBvcnRzOiBhbnkgPSBbXVxuICBjb25zdCBwb3J0cyA9IHNlcnZpY2Uuc3BlYy5wb3J0c1xuXG4gIGZvciAoY29uc3QgcG9ydFNwZWMgb2YgcG9ydHMpIHtcbiAgICBpbnRlcm5hbFBvcnRzLnB1c2goe1xuICAgICAgbmFtZTogcG9ydFNwZWMubmFtZSxcbiAgICAgIHByb3RvY29sOiBwb3J0U3BlYy5wcm90b2NvbCxcbiAgICAgIHRhcmdldFBvcnQ6IHBvcnRTcGVjLmNvbnRhaW5lclBvcnQsXG4gICAgICBwb3J0OiBwb3J0U3BlYy5jb250YWluZXJQb3J0LFxuICAgIH0pXG4gIH1cblxuICBpZiAoaW50ZXJuYWxQb3J0cy5sZW5ndGgpIHtcbiAgICBhZGRTZXJ2aWNlKHNlcnZpY2UubmFtZSwgXCJDbHVzdGVySVBcIiwgaW50ZXJuYWxQb3J0cylcbiAgfVxuXG4gIC8vIG9wdGlvbmFsbHkgYWRkIGEgTm9kZVBvcnQgc2VydmljZSBmb3IgZXh0ZXJuYWxseSBvcGVuIHBvcnRzLCBpZiBhcHBsaWNhYmxlXG4gIC8vIFRPRE86IGV4cGxvcmUgbmljZXIgd2F5cyB0byBkbyB0aGlzXG4gIGNvbnN0IGV4cG9zZWRQb3J0cyA9IHBvcnRzLmZpbHRlcihwb3J0U3BlYyA9PiBwb3J0U3BlYy5ub2RlUG9ydClcblxuICBpZiAoZXhwb3NlZFBvcnRzLmxlbmd0aCA+IDApIHtcbiAgICBhZGRTZXJ2aWNlKHNlcnZpY2UubmFtZSArIFwiLW5vZGVwb3J0XCIsIFwiTm9kZVBvcnRcIiwgZXhwb3NlZFBvcnRzLm1hcChwb3J0U3BlYyA9PiAoe1xuICAgICAgLy8gVE9ETzogZG8gdGhlIHBhcnNpbmcgYW5kIGRlZmF1bHRzIHdoZW4gbG9hZGluZyB0aGUgeWFtbFxuICAgICAgbmFtZTogcG9ydFNwZWMubmFtZSxcbiAgICAgIHByb3RvY29sOiBwb3J0U3BlYy5wcm90b2NvbCxcbiAgICAgIHBvcnQ6IHBvcnRTcGVjLmNvbnRhaW5lclBvcnQsXG4gICAgICBub2RlUG9ydDogcG9ydFNwZWMubm9kZVBvcnQsXG4gICAgfSkpKVxuICB9XG5cbiAgcmV0dXJuIHNlcnZpY2VzXG59XG4iXX0= diff --git a/garden-service/build/plugins/kubernetes/status.d.ts b/garden-service/build/plugins/kubernetes/status.d.ts new file mode 100644 index 00000000000..ce76b2e4b1a --- /dev/null +++ b/garden-service/build/plugins/kubernetes/status.d.ts @@ -0,0 +1,50 @@ +import { PluginContext } from "../../plugin-context"; +import { Service, ServiceState } from "../../types/service"; +import { KubeApi } from "./api"; +import { KubernetesObject } from "./helm"; +import { KubernetesProvider } from "./kubernetes"; +import { LogEntry } from "../../logger/log-entry"; +export interface RolloutStatus { + state: ServiceState; + obj: KubernetesObject; + lastMessage?: string; + lastError?: string; + resourceVersion?: number; +} +/** + * Check the rollout status for the given Deployment, DaemonSet or StatefulSet. + * + * NOTE: This mostly replicates the logic in `kubectl rollout status`. Using that directly here + * didn't pan out, since it doesn't look for events and just times out when errors occur during rollout. + */ +export declare function checkDeploymentStatus(api: KubeApi, namespace: string, obj: KubernetesObject, resourceVersion?: number): Promise; +/** + * Check if the specified Kubernetes objects are deployed and fully rolled out + */ +export declare function checkObjectStatus(api: KubeApi, namespace: string, objects: KubernetesObject[], prevStatuses?: RolloutStatus[]): Promise<{ + ready: boolean; + statuses: RolloutStatus[]; +}>; +interface WaitParams { + ctx: PluginContext; + provider: KubernetesProvider; + service: Service; + objects: KubernetesObject[]; + logEntry?: LogEntry; +} +/** + * Wait until the rollout is complete for each of the given Kubernetes objects + */ +export declare function waitForObjects({ ctx, provider, service, objects, logEntry }: WaitParams): Promise; +/** + * Check if each of the given Kubernetes objects matches what's installed in the cluster + */ +export declare function compareDeployedObjects(ctx: PluginContext, objects: KubernetesObject[]): Promise; +/** + * Recursively removes all null value properties from objects + */ +export declare function removeNull(value: T | Iterable): T | Iterable | { + [K in keyof T]: T[K]; +}; +export {}; +//# sourceMappingURL=status.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/status.js b/garden-service/build/plugins/kubernetes/status.js new file mode 100644 index 00000000000..4905ece5c35 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/status.js @@ -0,0 +1,374 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const exceptions_1 = require("../../exceptions"); +const util_1 = require("../../util/util"); +const api_1 = require("./api"); +const kubectl_1 = require("./kubectl"); +const namespace_1 = require("./namespace"); +const Bluebird = require("bluebird"); +const lodash_1 = require("lodash"); +const is_subset_1 = require("../../util/is-subset"); +// Handlers to check the rollout status for K8s objects where that applies. +// Using https://github.com/kubernetes/helm/blob/master/pkg/kube/wait.go as a reference here. +const objHandlers = { + DaemonSet: checkDeploymentStatus, + Deployment: checkDeploymentStatus, + StatefulSet: checkDeploymentStatus, + PersistentVolumeClaim: (api, namespace, obj) => __awaiter(this, void 0, void 0, function* () { + const res = yield api.core.readNamespacedPersistentVolumeClaim(obj.metadata.name, namespace); + const state = res.body.status.phase === "Bound" ? "ready" : "deploying"; + return { state, obj }; + }), + Pod: (api, namespace, obj) => __awaiter(this, void 0, void 0, function* () { + const res = yield api.core.readNamespacedPod(obj.metadata.name, namespace); + return checkPodStatus(obj, [res.body]); + }), + ReplicaSet: (api, namespace, obj) => __awaiter(this, void 0, void 0, function* () { + const res = yield api.core.listNamespacedPod(namespace, undefined, undefined, undefined, true, obj.spec.selector.matchLabels); + return checkPodStatus(obj, res.body.items); + }), + ReplicationController: (api, namespace, obj) => __awaiter(this, void 0, void 0, function* () { + const res = yield api.core.listNamespacedPod(namespace, undefined, undefined, undefined, true, obj.spec.selector); + return checkPodStatus(obj, res.body.items); + }), + Service: (api, namespace, obj) => __awaiter(this, void 0, void 0, function* () { + if (obj.spec.type === "ExternalName") { + return { state: "ready", obj }; + } + const status = yield api.core.readNamespacedService(obj.metadata.name, namespace); + if (obj.spec.clusterIP !== "None" && status.body.spec.clusterIP === "") { + return { state: "deploying", obj }; + } + if (obj.spec.type === "LoadBalancer" && !status.body.status.loadBalancer.ingress) { + return { state: "deploying", obj }; + } + return { state: "ready", obj }; + }), +}; +function checkPodStatus(obj, pods) { + return __awaiter(this, void 0, void 0, function* () { + for (const pod of pods) { + const ready = lodash_1.some(pod.status.conditions.map(c => c.type === "ready")); + if (!ready) { + return { state: "deploying", obj }; + } + } + return { state: "ready", obj }; + }); +} +/** + * Check the rollout status for the given Deployment, DaemonSet or StatefulSet. + * + * NOTE: This mostly replicates the logic in `kubectl rollout status`. Using that directly here + * didn't pan out, since it doesn't look for events and just times out when errors occur during rollout. + */ +function checkDeploymentStatus(api, namespace, obj, resourceVersion) { + return __awaiter(this, void 0, void 0, function* () { + // + const out = { + state: "unhealthy", + obj, + resourceVersion, + }; + let statusRes; + try { + statusRes = (yield api.readBySpec(namespace, obj)).body; + } + catch (err) { + if (err.code && err.code === 404) { + // service is not running + return out; + } + else { + throw err; + } + } + if (!resourceVersion) { + resourceVersion = out.resourceVersion = parseInt(statusRes.metadata.resourceVersion, 10); + } + // TODO: try to come up with something more efficient. may need to wait for newer k8s version. + // note: the resourceVersion parameter does not appear to work... + const eventsRes = yield api.core.listNamespacedEvent(namespace); + // const eventsRes = await this.kubeApi( + // "GET", + // [ + // "apis", apiSection, "v1beta1", + // "watch", + // "namespaces", namespace, + // type + "s", service.fullName, + // ], + // { resourceVersion, watch: "false" }, + // ) + // look for errors and warnings in the events for the service, abort if we find any + const events = eventsRes.body.items; + for (let event of events) { + const eventVersion = parseInt(event.metadata.resourceVersion, 10); + if (eventVersion <= resourceVersion || + (!event.metadata.name.startsWith(obj.metadata.name + ".") + && + !event.metadata.name.startsWith(obj.metadata.name + "-"))) { + continue; + } + if (eventVersion > resourceVersion) { + out.resourceVersion = eventVersion; + } + if (event.type === "Warning" || event.type === "Error") { + if (event.reason === "Unhealthy") { + // still waiting on readiness probe + continue; + } + out.state = "unhealthy"; + out.lastError = `${event.reason} - ${event.message}`; + return out; + } + let message = event.message; + if (event.reason === event.reason.toUpperCase()) { + // some events like ingress events are formatted this way + message = `${event.reason} ${message}`; + } + if (message) { + out.lastMessage = message; + } + } + // See `https://github.com/kubernetes/kubernetes/blob/master/pkg/kubectl/rollout_status.go` for a reference + // for this logic. + out.state = "ready"; + let statusMsg = ""; + if (statusRes.metadata.generation > statusRes.status.observedGeneration) { + statusMsg = `Waiting for spec update to be observed...`; + out.state = "deploying"; + } + else if (obj.kind === "DaemonSet") { + const status = statusRes.status; + const desired = status.desiredNumberScheduled || 0; + const updated = status.updatedNumberScheduled || 0; + const available = status.numberAvailable || 0; + if (updated < desired) { + statusMsg = `Waiting for rollout: ${updated} out of ${desired} new pods updated...`; + out.state = "deploying"; + } + else if (available < desired) { + statusMsg = `Waiting for rollout: ${available} out of ${desired} updated pods available...`; + out.state = "deploying"; + } + } + else if (obj.kind === "StatefulSet") { + const status = statusRes.status; + const statusSpec = statusRes.spec; + const replicas = status.replicas; + const updated = status.updatedReplicas || 0; + const ready = status.readyReplicas || 0; + if (replicas && ready < replicas) { + statusMsg = `Waiting for rollout: ${ready} out of ${replicas} new pods updated...`; + out.state = "deploying"; + } + else if (statusSpec.updateStrategy.type === "RollingUpdate" && statusSpec.updateStrategy.rollingUpdate) { + if (replicas && statusSpec.updateStrategy.rollingUpdate.partition) { + const desired = replicas - statusSpec.updateStrategy.rollingUpdate.partition; + if (updated < desired) { + statusMsg = + `Waiting for partitioned roll out to finish: ${updated} out of ${desired} new pods have been updated...`; + out.state = "deploying"; + } + } + } + else if (status.updateRevision !== status.currentRevision) { + statusMsg = `Waiting for rolling update to complete...`; + out.state = "deploying"; + } + } + else { + const status = statusRes.status; + const desired = 1; // TODO: service.count[env.name] || 1 + const updated = status.updatedReplicas || 0; + const replicas = status.replicas || 0; + const available = status.availableReplicas || 0; + if (updated < desired) { + statusMsg = `Waiting for rollout: ${updated} out of ${desired} new replicas updated...`; + out.state = "deploying"; + } + else if (replicas > updated) { + statusMsg = `Waiting for rollout: ${replicas - updated} old replicas pending termination...`; + out.state = "deploying"; + } + else if (available < updated) { + statusMsg = `Waiting for rollout: ${available} out of ${updated} updated replicas available...`; + out.state = "deploying"; + } + } + out.lastMessage = statusMsg; + return out; + }); +} +exports.checkDeploymentStatus = checkDeploymentStatus; +/** + * Check if the specified Kubernetes objects are deployed and fully rolled out + */ +function checkObjectStatus(api, namespace, objects, prevStatuses) { + return __awaiter(this, void 0, void 0, function* () { + let ready = true; + const statuses = yield Bluebird.map(objects, (obj, i) => __awaiter(this, void 0, void 0, function* () { + const handler = objHandlers[obj.kind]; + const prevStatus = prevStatuses && prevStatuses[i]; + const status = handler + ? yield handler(api, namespace, obj, prevStatus && prevStatus.resourceVersion) + // if there is no explicit handler to check the status, we assume there's no rollout phase to wait for + : { state: "ready", obj }; + if (status.state !== "ready") { + ready = false; + } + return status; + })); + return { ready, statuses }; + }); +} +exports.checkObjectStatus = checkObjectStatus; +/** + * Wait until the rollout is complete for each of the given Kubernetes objects + */ +function waitForObjects({ ctx, provider, service, objects, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + let loops = 0; + let lastMessage; + const startTime = new Date().getTime(); + logEntry && logEntry.verbose({ + symbol: "info", + section: service.name, + msg: `Waiting for service to be ready...`, + }); + const api = new api_1.KubeApi(provider); + const namespace = yield namespace_1.getAppNamespace(ctx, provider); + let prevStatuses = objects.map((obj) => ({ + state: "unknown", + obj, + })); + while (true) { + yield util_1.sleep(2000 + 1000 * loops); + const { ready, statuses } = yield checkObjectStatus(api, namespace, objects, prevStatuses); + for (const status of statuses) { + if (status.lastError) { + throw new exceptions_1.DeploymentError(`Error deploying ${service.name}: ${status.lastError}`, { + serviceName: service.name, + status, + }); + } + if (status.lastMessage && (!lastMessage || status.lastMessage !== lastMessage)) { + lastMessage = status.lastMessage; + logEntry && logEntry.verbose({ + symbol: "info", + section: service.name, + msg: status.lastMessage, + }); + } + } + prevStatuses = statuses; + if (ready) { + break; + } + const now = new Date().getTime(); + if (now - startTime > kubectl_1.KUBECTL_DEFAULT_TIMEOUT * 1000) { + throw new Error(`Timed out waiting for ${service.name} to deploy`); + } + } + logEntry && logEntry.verbose({ symbol: "info", section: service.name, msg: `Service deployed` }); + }); +} +exports.waitForObjects = waitForObjects; +/** + * Check if each of the given Kubernetes objects matches what's installed in the cluster + */ +function compareDeployedObjects(ctx, objects) { + return __awaiter(this, void 0, void 0, function* () { + const existingObjects = yield Bluebird.map(objects, obj => getDeployedObject(ctx, ctx.provider, obj)); + for (let [obj, existingSpec] of lodash_1.zip(objects, existingObjects)) { + if (existingSpec && obj) { + // the API version may implicitly change when deploying + existingSpec.apiVersion = obj.apiVersion; + // the namespace property is silently dropped when added to non-namespaced + if (obj.metadata.namespace && existingSpec.metadata.namespace === undefined) { + delete obj.metadata.namespace; + } + if (!existingSpec.metadata.annotations) { + existingSpec.metadata.annotations = {}; + } + // handle auto-filled properties (this is a bit of a design issue in the K8s API) + if (obj.kind === "Service" && obj.spec.clusterIP === "") { + delete obj.spec.clusterIP; + } + // handle properties that are omitted in the response because they have the default value + // (another design issue in the K8s API) + // NOTE: this approach won't fly in the long run, but hopefully we can climb out of this mess when + // `kubectl diff` is ready, or server-side apply/diff is ready + if (obj.kind === "DaemonSet") { + if (obj.spec.minReadySeconds === 0) { + delete obj.spec.minReadySeconds; + } + if (obj.spec.template.spec.hostNetwork === false) { + delete obj.spec.template.spec.hostNetwork; + } + } + // clean null values + obj = removeNull(obj); + } + if (!existingSpec || !is_subset_1.isSubset(existingSpec, obj)) { + // console.log(JSON.stringify(obj, null, 4)) + // console.log(JSON.stringify(existingSpec, null, 4)) + // console.log("----------------------------------------------------") + // throw new Error("bla") + return false; + } + } + return true; + }); +} +exports.compareDeployedObjects = compareDeployedObjects; +function getDeployedObject(ctx, provider, obj) { + return __awaiter(this, void 0, void 0, function* () { + const api = new api_1.KubeApi(provider); + const namespace = obj.metadata.namespace || (yield namespace_1.getAppNamespace(ctx, provider)); + try { + const res = yield api.readBySpec(namespace, obj); + return res.body; + } + catch (err) { + if (err.code === 404) { + return null; + } + else { + throw err; + } + } + }); +} +/** + * Recursively removes all null value properties from objects + */ +function removeNull(value) { + if (lodash_1.isArray(value)) { + return value.map(removeNull); + } + else if (lodash_1.isPlainObject(value)) { + return lodash_1.mapValues(lodash_1.pickBy(value, v => v !== null), removeNull); + } + else { + return value; + } +} +exports.removeNull = removeNull; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9zdGF0dXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlEQUFrRDtBQUdsRCwwQ0FBdUM7QUFDdkMsK0JBQStCO0FBQy9CLHVDQUFtRDtBQUNuRCwyQ0FBNkM7QUFDN0MscUNBQW9DO0FBWXBDLG1DQUE2RTtBQUc3RSxvREFBK0M7QUFjL0MsMkVBQTJFO0FBQzNFLDZGQUE2RjtBQUM3RixNQUFNLFdBQVcsR0FBbUM7SUFDbEQsU0FBUyxFQUFFLHFCQUFxQjtJQUNoQyxVQUFVLEVBQUUscUJBQXFCO0lBQ2pDLFdBQVcsRUFBRSxxQkFBcUI7SUFFbEMscUJBQXFCLEVBQUUsQ0FBTyxHQUFHLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ25ELE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxtQ0FBbUMsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQTtRQUM1RixNQUFNLEtBQUssR0FBaUIsR0FBRyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxLQUFLLE9BQU8sQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxXQUFXLENBQUE7UUFDckYsT0FBTyxFQUFFLEtBQUssRUFBRSxHQUFHLEVBQUUsQ0FBQTtJQUN2QixDQUFDLENBQUE7SUFFRCxHQUFHLEVBQUUsQ0FBTyxHQUFHLEVBQUUsU0FBUyxFQUFFLEdBQUcsRUFBRSxFQUFFO1FBQ2pDLE1BQU0sR0FBRyxHQUFHLE1BQU0sR0FBRyxDQUFDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxHQUFHLENBQUMsUUFBUSxDQUFDLElBQUksRUFBRSxTQUFTLENBQUMsQ0FBQTtRQUMxRSxPQUFPLGNBQWMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQTtJQUN4QyxDQUFDLENBQUE7SUFFRCxV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QUU7UUFDbEIsT0FBTyxLQUFLLENBQUMsR0FBRyxDQUFDLFVBQVUsQ0FBQyxDQUFBO0tBQzdCO1NBQU0sSUFBSSxzQkFBYSxDQUFDLEtBQUssQ0FBQyxFQUFFO1FBQy9CLE9BQWlDLGtCQUFTLENBQUMsZUFBTSxDQUFNLEtBQUssRUFBRSxDQUFDLENBQUMsRUFBRSxDQUFDLENBQUMsS0FBSyxJQUFJLENBQUMsRUFBRSxVQUFVLENBQUMsQ0FBQTtLQUM1RjtTQUFNO1FBQ0wsT0FBTyxLQUFLLENBQUE7S0FDYjtBQUNILENBQUM7QUFSRCxnQ0FRQyIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvc3RhdHVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IERlcGxveW1lbnRFcnJvciB9IGZyb20gXCIuLi8uLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IFBsdWdpbkNvbnRleHQgfSBmcm9tIFwiLi4vLi4vcGx1Z2luLWNvbnRleHRcIlxuaW1wb3J0IHsgU2VydmljZSwgU2VydmljZVN0YXRlIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHsgc2xlZXAgfSBmcm9tIFwiLi4vLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IEt1YmVBcGkgfSBmcm9tIFwiLi9hcGlcIlxuaW1wb3J0IHsgS1VCRUNUTF9ERUZBVUxUX1RJTUVPVVQgfSBmcm9tIFwiLi9rdWJlY3RsXCJcbmltcG9ydCB7IGdldEFwcE5hbWVzcGFjZSB9IGZyb20gXCIuL25hbWVzcGFjZVwiXG5pbXBvcnQgKiBhcyBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuaW1wb3J0IHsgS3ViZXJuZXRlc09iamVjdCB9IGZyb20gXCIuL2hlbG1cIlxuaW1wb3J0IHtcbiAgVjFQb2QsXG4gIFYxRGVwbG95bWVudCxcbiAgVjFEYWVtb25TZXQsXG4gIFYxRGFlbW9uU2V0U3RhdHVzLFxuICBWMVN0YXRlZnVsU2V0U3RhdHVzLFxuICBWMVN0YXRlZnVsU2V0LFxuICBWMVN0YXRlZnVsU2V0U3BlYyxcbiAgVjFEZXBsb3ltZW50U3RhdHVzLFxufSBmcm9tIFwiQGt1YmVybmV0ZXMvY2xpZW50LW5vZGVcIlxuaW1wb3J0IHsgc29tZSwgemlwLCBpc0FycmF5LCBpc1BsYWluT2JqZWN0LCBwaWNrQnksIG1hcFZhbHVlcyB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgS3ViZXJuZXRlc1Byb3ZpZGVyIH0gZnJvbSBcIi4va3ViZXJuZXRlc1wiXG5pbXBvcnQgeyBMb2dFbnRyeSB9IGZyb20gXCIuLi8uLi9sb2dnZXIvbG9nLWVudHJ5XCJcbmltcG9ydCB7IGlzU3Vic2V0IH0gZnJvbSBcIi4uLy4uL3V0aWwvaXMtc3Vic2V0XCJcblxuZXhwb3J0IGludGVyZmFjZSBSb2xsb3V0U3RhdHVzIHtcbiAgc3RhdGU6IFNlcnZpY2VTdGF0ZVxuICBvYmo6IEt1YmVybmV0ZXNPYmplY3RcbiAgbGFzdE1lc3NhZ2U/OiBzdHJpbmdcbiAgbGFzdEVycm9yPzogc3RyaW5nXG4gIHJlc291cmNlVmVyc2lvbj86IG51bWJlclxufVxuXG5pbnRlcmZhY2UgT2JqSGFuZGxlciB7XG4gIChhcGk6IEt1YmVBcGksIG5hbWVzcGFjZTogc3RyaW5nLCBvYmo6IEt1YmVybmV0ZXNPYmplY3QsIHJlc291cmNlVmVyc2lvbj86IG51bWJlcik6IFByb21pc2U8Um9sbG91dFN0YXR1cz5cbn1cblxuLy8gSGFuZGxlcnMgdG8gY2hlY2sgdGhlIHJvbGxvdXQgc3RhdHVzIGZvciBLOHMgb2JqZWN0cyB3aGVyZSB0aGF0IGFwcGxpZXMuXG4vLyBVc2luZyBodHRwczovL2dpdGh1Yi5jb20va3ViZXJuZXRlcy9oZWxtL2Jsb2IvbWFzdGVyL3BrZy9rdWJlL3dhaXQuZ28gYXMgYSByZWZlcmVuY2UgaGVyZS5cbmNvbnN0IG9iakhhbmRsZXJzOiB7IFtraW5kOiBzdHJpbmddOiBPYmpIYW5kbGVyIH0gPSB7XG4gIERhZW1vblNldDogY2hlY2tEZXBsb3ltZW50U3RhdHVzLFxuICBEZXBsb3ltZW50OiBjaGVja0RlcGxveW1lbnRTdGF0dXMsXG4gIFN0YXRlZnVsU2V0OiBjaGVja0RlcGxveW1lbnRTdGF0dXMsXG5cbiAgUGVyc2lzdGVudFZvbHVtZUNsYWltOiBhc3luYyAoYXBpLCBuYW1lc3BhY2UsIG9iaikgPT4ge1xuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGFwaS5jb3JlLnJlYWROYW1lc3BhY2VkUGVyc2lzdGVudFZvbHVtZUNsYWltKG9iai5tZXRhZGF0YS5uYW1lLCBuYW1lc3BhY2UpXG4gICAgY29uc3Qgc3RhdGU6IFNlcnZpY2VTdGF0ZSA9IHJlcy5ib2R5LnN0YXR1cy5waGFzZSA9PT0gXCJCb3VuZFwiID8gXCJyZWFkeVwiIDogXCJkZXBsb3lpbmdcIlxuICAgIHJldHVybiB7IHN0YXRlLCBvYmogfVxuICB9LFxuXG4gIFBvZDogYXN5bmMgKGFwaSwgbmFtZXNwYWNlLCBvYmopID0+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhcGkuY29yZS5yZWFkTmFtZXNwYWNlZFBvZChvYmoubWV0YWRhdGEubmFtZSwgbmFtZXNwYWNlKVxuICAgIHJldHVybiBjaGVja1BvZFN0YXR1cyhvYmosIFtyZXMuYm9keV0pXG4gIH0sXG5cbiAgUmVwbGljYVNldDogYXN5bmMgKGFwaSwgbmFtZXNwYWNlLCBvYmopID0+IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhcGkuY29yZS5saXN0TmFtZXNwYWNlZFBvZChcbiAgICAgIG5hbWVzcGFjZSwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHVuZGVmaW5lZCwgdHJ1ZSwgb2JqLnNwZWMuc2VsZWN0b3IubWF0Y2hMYWJlbHMsXG4gICAgKVxuICAgIHJldHVybiBjaGVja1BvZFN0YXR1cyhvYmosIHJlcy5ib2R5Lml0ZW1zKVxuICB9LFxuICBSZXBsaWNhdGlvbkNvbnRyb2xsZXI6IGFzeW5jIChhcGksIG5hbWVzcGFjZSwgb2JqKSA9PiB7XG4gICAgY29uc3QgcmVzID0gYXdhaXQgYXBpLmNvcmUubGlzdE5hbWVzcGFjZWRQb2QoXG4gICAgICBuYW1lc3BhY2UsIHVuZGVmaW5lZCwgdW5kZWZpbmVkLCB1bmRlZmluZWQsIHRydWUsIG9iai5zcGVjLnNlbGVjdG9yLFxuICAgIClcbiAgICByZXR1cm4gY2hlY2tQb2RTdGF0dXMob2JqLCByZXMuYm9keS5pdGVtcylcbiAgfSxcblxuICBTZXJ2aWNlOiBhc3luYyAoYXBpLCBuYW1lc3BhY2UsIG9iaikgPT4ge1xuICAgIGlmIChvYmouc3BlYy50eXBlID09PSBcIkV4dGVybmFsTmFtZVwiKSB7XG4gICAgICByZXR1cm4geyBzdGF0ZTogXCJyZWFkeVwiLCBvYmogfVxuICAgIH1cblxuICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGFwaS5jb3JlLnJlYWROYW1lc3BhY2VkU2VydmljZShvYmoubWV0YWRhdGEubmFtZSwgbmFtZXNwYWNlKVxuXG4gICAgaWYgKG9iai5zcGVjLmNsdXN0ZXJJUCAhPT0gXCJOb25lXCIgJiYgc3RhdHVzLmJvZHkuc3BlYy5jbHVzdGVySVAgPT09IFwiXCIpIHtcbiAgICAgIHJldHVybiB7IHN0YXRlOiBcImRlcGxveWluZ1wiLCBvYmogfVxuICAgIH1cblxuICAgIGlmIChvYmouc3BlYy50eXBlID09PSBcIkxvYWRCYWxhbmNlclwiICYmICFzdGF0dXMuYm9keS5zdGF0dXMubG9hZEJhbGFuY2VyLmluZ3Jlc3MpIHtcbiAgICAgIHJldHVybiB7IHN0YXRlOiBcImRlcGxveWluZ1wiLCBvYmogfVxuICAgIH1cblxuICAgIHJldHVybiB7IHN0YXRlOiBcInJlYWR5XCIsIG9iaiB9XG4gIH0sXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGNoZWNrUG9kU3RhdHVzKG9iajogS3ViZXJuZXRlc09iamVjdCwgcG9kczogVjFQb2RbXSk6IFByb21pc2U8Um9sbG91dFN0YXR1cz4ge1xuICBmb3IgKGNvbnN0IHBvZCBvZiBwb2RzKSB7XG4gICAgY29uc3QgcmVhZHkgPSBzb21lKHBvZC5zdGF0dXMuY29uZGl0aW9ucy5tYXAoYyA9PiBjLnR5cGUgPT09IFwicmVhZHlcIikpXG4gICAgaWYgKCFyZWFkeSkge1xuICAgICAgcmV0dXJuIHsgc3RhdGU6IFwiZGVwbG95aW5nXCIsIG9iaiB9XG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHsgc3RhdGU6IFwicmVhZHlcIiwgb2JqIH1cbn1cblxuLyoqXG4gKiBDaGVjayB0aGUgcm9sbG91dCBzdGF0dXMgZm9yIHRoZSBnaXZlbiBEZXBsb3ltZW50LCBEYWVtb25TZXQgb3IgU3RhdGVmdWxTZXQuXG4gKlxuICogTk9URTogVGhpcyBtb3N0bHkgcmVwbGljYXRlcyB0aGUgbG9naWMgaW4gYGt1YmVjdGwgcm9sbG91dCBzdGF0dXNgLiBVc2luZyB0aGF0IGRpcmVjdGx5IGhlcmVcbiAqIGRpZG4ndCBwYW4gb3V0LCBzaW5jZSBpdCBkb2Vzbid0IGxvb2sgZm9yIGV2ZW50cyBhbmQganVzdCB0aW1lcyBvdXQgd2hlbiBlcnJvcnMgb2NjdXIgZHVyaW5nIHJvbGxvdXQuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBjaGVja0RlcGxveW1lbnRTdGF0dXMoXG4gIGFwaTogS3ViZUFwaSwgbmFtZXNwYWNlOiBzdHJpbmcsIG9iajogS3ViZXJuZXRlc09iamVjdCwgcmVzb3VyY2VWZXJzaW9uPzogbnVtYmVyLFxuKTogUHJvbWlzZTxSb2xsb3V0U3RhdHVzPiB7XG4gIC8vXG4gIGNvbnN0IG91dDogUm9sbG91dFN0YXR1cyA9IHtcbiAgICBzdGF0ZTogXCJ1bmhlYWx0aHlcIixcbiAgICBvYmosXG4gICAgcmVzb3VyY2VWZXJzaW9uLFxuICB9XG5cbiAgbGV0IHN0YXR1c1JlczogVjFEZXBsb3ltZW50IHwgVjFEYWVtb25TZXQgfCBWMVN0YXRlZnVsU2V0XG5cbiAgdHJ5IHtcbiAgICBzdGF0dXNSZXMgPSA8VjFEZXBsb3ltZW50IHwgVjFEYWVtb25TZXQgfCBWMVN0YXRlZnVsU2V0Pihhd2FpdCBhcGkucmVhZEJ5U3BlYyhuYW1lc3BhY2UsIG9iaikpLmJvZHlcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5jb2RlICYmIGVyci5jb2RlID09PSA0MDQpIHtcbiAgICAgIC8vIHNlcnZpY2UgaXMgbm90IHJ1bm5pbmdcbiAgICAgIHJldHVybiBvdXRcbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgaWYgKCFyZXNvdXJjZVZlcnNpb24pIHtcbiAgICByZXNvdXJjZVZlcnNpb24gPSBvdXQucmVzb3VyY2VWZXJzaW9uID0gcGFyc2VJbnQoc3RhdHVzUmVzLm1ldGFkYXRhLnJlc291cmNlVmVyc2lvbiwgMTApXG4gIH1cblxuICAvLyBUT0RPOiB0cnkgdG8gY29tZSB1cCB3aXRoIHNvbWV0aGluZyBtb3JlIGVmZmljaWVudC4gbWF5IG5lZWQgdG8gd2FpdCBmb3IgbmV3ZXIgazhzIHZlcnNpb24uXG4gIC8vIG5vdGU6IHRoZSByZXNvdXJjZVZlcnNpb24gcGFyYW1ldGVyIGRvZXMgbm90IGFwcGVhciB0byB3b3JrLi4uXG4gIGNvbnN0IGV2ZW50c1JlcyA9IGF3YWl0IGFwaS5jb3JlLmxpc3ROYW1lc3BhY2VkRXZlbnQobmFtZXNwYWNlKVxuXG4gIC8vIGNvbnN0IGV2ZW50c1JlcyA9IGF3YWl0IHRoaXMua3ViZUFwaShcbiAgLy8gICBcIkdFVFwiLFxuICAvLyAgIFtcbiAgLy8gICAgIFwiYXBpc1wiLCBhcGlTZWN0aW9uLCBcInYxYmV0YTFcIixcbiAgLy8gICAgIFwid2F0Y2hcIixcbiAgLy8gICAgIFwibmFtZXNwYWNlc1wiLCBuYW1lc3BhY2UsXG4gIC8vICAgICB0eXBlICsgXCJzXCIsIHNlcnZpY2UuZnVsbE5hbWUsXG4gIC8vICAgXSxcbiAgLy8gICB7IHJlc291cmNlVmVyc2lvbiwgd2F0Y2g6IFwiZmFsc2VcIiB9LFxuICAvLyApXG5cbiAgLy8gbG9vayBmb3IgZXJyb3JzIGFuZCB3YXJuaW5ncyBpbiB0aGUgZXZlbnRzIGZvciB0aGUgc2VydmljZSwgYWJvcnQgaWYgd2UgZmluZCBhbnlcbiAgY29uc3QgZXZlbnRzID0gZXZlbnRzUmVzLmJvZHkuaXRlbXNcblxuICBmb3IgKGxldCBldmVudCBvZiBldmVudHMpIHtcbiAgICBjb25zdCBldmVudFZlcnNpb24gPSBwYXJzZUludChldmVudC5tZXRhZGF0YS5yZXNvdXJjZVZlcnNpb24sIDEwKVxuXG4gICAgaWYgKFxuICAgICAgZXZlbnRWZXJzaW9uIDw9IDxudW1iZXI+cmVzb3VyY2VWZXJzaW9uIHx8XG4gICAgICAoXG4gICAgICAgICFldmVudC5tZXRhZGF0YS5uYW1lLnN0YXJ0c1dpdGgob2JqLm1ldGFkYXRhLm5hbWUgKyBcIi5cIilcbiAgICAgICAgJiZcbiAgICAgICAgIWV2ZW50Lm1ldGFkYXRhLm5hbWUuc3RhcnRzV2l0aChvYmoubWV0YWRhdGEubmFtZSArIFwiLVwiKVxuICAgICAgKVxuICAgICkge1xuICAgICAgY29udGludWVcbiAgICB9XG5cbiAgICBpZiAoZXZlbnRWZXJzaW9uID4gPG51bWJlcj5yZXNvdXJjZVZlcnNpb24pIHtcbiAgICAgIG91dC5yZXNvdXJjZVZlcnNpb24gPSBldmVudFZlcnNpb25cbiAgICB9XG5cbiAgICBpZiAoZXZlbnQudHlwZSA9PT0gXCJXYXJuaW5nXCIgfHwgZXZlbnQudHlwZSA9PT0gXCJFcnJvclwiKSB7XG4gICAgICBpZiAoZXZlbnQucmVhc29uID09PSBcIlVuaGVhbHRoeVwiKSB7XG4gICAgICAgIC8vIHN0aWxsIHdhaXRpbmcgb24gcmVhZGluZXNzIHByb2JlXG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG4gICAgICBvdXQuc3RhdGUgPSBcInVuaGVhbHRoeVwiXG4gICAgICBvdXQubGFzdEVycm9yID0gYCR7ZXZlbnQucmVhc29ufSAtICR7ZXZlbnQubWVzc2FnZX1gXG4gICAgICByZXR1cm4gb3V0XG4gICAgfVxuXG4gICAgbGV0IG1lc3NhZ2UgPSBldmVudC5tZXNzYWdlXG5cbiAgICBpZiAoZXZlbnQucmVhc29uID09PSBldmVudC5yZWFzb24udG9VcHBlckNhc2UoKSkge1xuICAgICAgLy8gc29tZSBldmVudHMgbGlrZSBpbmdyZXNzIGV2ZW50cyBhcmUgZm9ybWF0dGVkIHRoaXMgd2F5XG4gICAgICBtZXNzYWdlID0gYCR7ZXZlbnQucmVhc29ufSAke21lc3NhZ2V9YFxuICAgIH1cblxuICAgIGlmIChtZXNzYWdlKSB7XG4gICAgICBvdXQubGFzdE1lc3NhZ2UgPSBtZXNzYWdlXG4gICAgfVxuICB9XG5cbiAgLy8gU2VlIGBodHRwczovL2dpdGh1Yi5jb20va3ViZXJuZXRlcy9rdWJlcm5ldGVzL2Jsb2IvbWFzdGVyL3BrZy9rdWJlY3RsL3JvbGxvdXRfc3RhdHVzLmdvYCBmb3IgYSByZWZlcmVuY2VcbiAgLy8gZm9yIHRoaXMgbG9naWMuXG4gIG91dC5zdGF0ZSA9IFwicmVhZHlcIlxuICBsZXQgc3RhdHVzTXNnID0gXCJcIlxuXG4gIGlmIChzdGF0dXNSZXMubWV0YWRhdGEuZ2VuZXJhdGlvbiA+IHN0YXR1c1Jlcy5zdGF0dXMub2JzZXJ2ZWRHZW5lcmF0aW9uKSB7XG4gICAgc3RhdHVzTXNnID0gYFdhaXRpbmcgZm9yIHNwZWMgdXBkYXRlIHRvIGJlIG9ic2VydmVkLi4uYFxuICAgIG91dC5zdGF0ZSA9IFwiZGVwbG95aW5nXCJcbiAgfSBlbHNlIGlmIChvYmoua2luZCA9PT0gXCJEYWVtb25TZXRcIikge1xuICAgIGNvbnN0IHN0YXR1cyA9IDxWMURhZW1vblNldFN0YXR1cz5zdGF0dXNSZXMuc3RhdHVzXG5cbiAgICBjb25zdCBkZXNpcmVkID0gc3RhdHVzLmRlc2lyZWROdW1iZXJTY2hlZHVsZWQgfHwgMFxuICAgIGNvbnN0IHVwZGF0ZWQgPSBzdGF0dXMudXBkYXRlZE51bWJlclNjaGVkdWxlZCB8fCAwXG4gICAgY29uc3QgYXZhaWxhYmxlID0gc3RhdHVzLm51bWJlckF2YWlsYWJsZSB8fCAwXG5cbiAgICBpZiAodXBkYXRlZCA8IGRlc2lyZWQpIHtcbiAgICAgIHN0YXR1c01zZyA9IGBXYWl0aW5nIGZvciByb2xsb3V0OiAke3VwZGF0ZWR9IG91dCBvZiAke2Rlc2lyZWR9IG5ldyBwb2RzIHVwZGF0ZWQuLi5gXG4gICAgICBvdXQuc3RhdGUgPSBcImRlcGxveWluZ1wiXG4gICAgfSBlbHNlIGlmIChhdmFpbGFibGUgPCBkZXNpcmVkKSB7XG4gICAgICBzdGF0dXNNc2cgPSBgV2FpdGluZyBmb3Igcm9sbG91dDogJHthdmFpbGFibGV9IG91dCBvZiAke2Rlc2lyZWR9IHVwZGF0ZWQgcG9kcyBhdmFpbGFibGUuLi5gXG4gICAgICBvdXQuc3RhdGUgPSBcImRlcGxveWluZ1wiXG4gICAgfVxuICB9IGVsc2UgaWYgKG9iai5raW5kID09PSBcIlN0YXRlZnVsU2V0XCIpIHtcbiAgICBjb25zdCBzdGF0dXMgPSA8VjFTdGF0ZWZ1bFNldFN0YXR1cz5zdGF0dXNSZXMuc3RhdHVzXG4gICAgY29uc3Qgc3RhdHVzU3BlYyA9IDxWMVN0YXRlZnVsU2V0U3BlYz5zdGF0dXNSZXMuc3BlY1xuXG4gICAgY29uc3QgcmVwbGljYXMgPSBzdGF0dXMucmVwbGljYXNcbiAgICBjb25zdCB1cGRhdGVkID0gc3RhdHVzLnVwZGF0ZWRSZXBsaWNhcyB8fCAwXG4gICAgY29uc3QgcmVhZHkgPSBzdGF0dXMucmVhZHlSZXBsaWNhcyB8fCAwXG5cbiAgICBpZiAocmVwbGljYXMgJiYgcmVhZHkgPCByZXBsaWNhcykge1xuICAgICAgc3RhdHVzTXNnID0gYFdhaXRpbmcgZm9yIHJvbGxvdXQ6ICR7cmVhZHl9IG91dCBvZiAke3JlcGxpY2FzfSBuZXcgcG9kcyB1cGRhdGVkLi4uYFxuICAgICAgb3V0LnN0YXRlID0gXCJkZXBsb3lpbmdcIlxuICAgIH0gZWxzZSBpZiAoc3RhdHVzU3BlYy51cGRhdGVTdHJhdGVneS50eXBlID09PSBcIlJvbGxpbmdVcGRhdGVcIiAmJiBzdGF0dXNTcGVjLnVwZGF0ZVN0cmF0ZWd5LnJvbGxpbmdVcGRhdGUpIHtcbiAgICAgIGlmIChyZXBsaWNhcyAmJiBzdGF0dXNTcGVjLnVwZGF0ZVN0cmF0ZWd5LnJvbGxpbmdVcGRhdGUucGFydGl0aW9uKSB7XG4gICAgICAgIGNvbnN0IGRlc2lyZWQgPSByZXBsaWNhcyAtIHN0YXR1c1NwZWMudXBkYXRlU3RyYXRlZ3kucm9sbGluZ1VwZGF0ZS5wYXJ0aXRpb25cbiAgICAgICAgaWYgKHVwZGF0ZWQgPCBkZXNpcmVkKSB7XG4gICAgICAgICAgc3RhdHVzTXNnID1cbiAgICAgICAgICAgIGBXYWl0aW5nIGZvciBwYXJ0aXRpb25lZCByb2xsIG91dCB0byBmaW5pc2g6ICR7dXBkYXRlZH0gb3V0IG9mICR7ZGVzaXJlZH0gbmV3IHBvZHMgaGF2ZSBiZWVuIHVwZGF0ZWQuLi5gXG4gICAgICAgICAgb3V0LnN0YXRlID0gXCJkZXBsb3lpbmdcIlxuICAgICAgICB9XG4gICAgICB9XG4gICAgfSBlbHNlIGlmIChzdGF0dXMudXBkYXRlUmV2aXNpb24gIT09IHN0YXR1cy5jdXJyZW50UmV2aXNpb24pIHtcbiAgICAgIHN0YXR1c01zZyA9IGBXYWl0aW5nIGZvciByb2xsaW5nIHVwZGF0ZSB0byBjb21wbGV0ZS4uLmBcbiAgICAgIG91dC5zdGF0ZSA9IFwiZGVwbG95aW5nXCJcbiAgICB9XG4gIH0gZWxzZSB7XG4gICAgY29uc3Qgc3RhdHVzID0gPFYxRGVwbG95bWVudFN0YXR1cz5zdGF0dXNSZXMuc3RhdHVzXG5cbiAgICBjb25zdCBkZXNpcmVkID0gMSAvLyBUT0RPOiBzZXJ2aWNlLmNvdW50W2Vudi5uYW1lXSB8fCAxXG4gICAgY29uc3QgdXBkYXRlZCA9IHN0YXR1cy51cGRhdGVkUmVwbGljYXMgfHwgMFxuICAgIGNvbnN0IHJlcGxpY2FzID0gc3RhdHVzLnJlcGxpY2FzIHx8IDBcbiAgICBjb25zdCBhdmFpbGFibGUgPSBzdGF0dXMuYXZhaWxhYmxlUmVwbGljYXMgfHwgMFxuXG4gICAgaWYgKHVwZGF0ZWQgPCBkZXNpcmVkKSB7XG4gICAgICBzdGF0dXNNc2cgPSBgV2FpdGluZyBmb3Igcm9sbG91dDogJHt1cGRhdGVkfSBvdXQgb2YgJHtkZXNpcmVkfSBuZXcgcmVwbGljYXMgdXBkYXRlZC4uLmBcbiAgICAgIG91dC5zdGF0ZSA9IFwiZGVwbG95aW5nXCJcbiAgICB9IGVsc2UgaWYgKHJlcGxpY2FzID4gdXBkYXRlZCkge1xuICAgICAgc3RhdHVzTXNnID0gYFdhaXRpbmcgZm9yIHJvbGxvdXQ6ICR7cmVwbGljYXMgLSB1cGRhdGVkfSBvbGQgcmVwbGljYXMgcGVuZGluZyB0ZXJtaW5hdGlvbi4uLmBcbiAgICAgIG91dC5zdGF0ZSA9IFwiZGVwbG95aW5nXCJcbiAgICB9IGVsc2UgaWYgKGF2YWlsYWJsZSA8IHVwZGF0ZWQpIHtcbiAgICAgIHN0YXR1c01zZyA9IGBXYWl0aW5nIGZvciByb2xsb3V0OiAke2F2YWlsYWJsZX0gb3V0IG9mICR7dXBkYXRlZH0gdXBkYXRlZCByZXBsaWNhcyBhdmFpbGFibGUuLi5gXG4gICAgICBvdXQuc3RhdGUgPSBcImRlcGxveWluZ1wiXG4gICAgfVxuICB9XG5cbiAgb3V0Lmxhc3RNZXNzYWdlID0gc3RhdHVzTXNnXG5cbiAgcmV0dXJuIG91dFxufVxuXG4vKipcbiAqIENoZWNrIGlmIHRoZSBzcGVjaWZpZWQgS3ViZXJuZXRlcyBvYmplY3RzIGFyZSBkZXBsb3llZCBhbmQgZnVsbHkgcm9sbGVkIG91dFxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY2hlY2tPYmplY3RTdGF0dXMoXG4gIGFwaTogS3ViZUFwaSwgbmFtZXNwYWNlOiBzdHJpbmcsIG9iamVjdHM6IEt1YmVybmV0ZXNPYmplY3RbXSwgcHJldlN0YXR1c2VzPzogUm9sbG91dFN0YXR1c1tdLFxuKSB7XG4gIGxldCByZWFkeSA9IHRydWVcblxuICBjb25zdCBzdGF0dXNlczogUm9sbG91dFN0YXR1c1tdID0gYXdhaXQgQmx1ZWJpcmQubWFwKG9iamVjdHMsIGFzeW5jIChvYmosIGkpID0+IHtcbiAgICBjb25zdCBoYW5kbGVyID0gb2JqSGFuZGxlcnNbb2JqLmtpbmRdXG4gICAgY29uc3QgcHJldlN0YXR1cyA9IHByZXZTdGF0dXNlcyAmJiBwcmV2U3RhdHVzZXNbaV1cbiAgICBjb25zdCBzdGF0dXM6IFJvbGxvdXRTdGF0dXMgPSBoYW5kbGVyXG4gICAgICA/IGF3YWl0IGhhbmRsZXIoYXBpLCBuYW1lc3BhY2UsIG9iaiwgcHJldlN0YXR1cyAmJiBwcmV2U3RhdHVzLnJlc291cmNlVmVyc2lvbilcbiAgICAgIC8vIGlmIHRoZXJlIGlzIG5vIGV4cGxpY2l0IGhhbmRsZXIgdG8gY2hlY2sgdGhlIHN0YXR1cywgd2UgYXNzdW1lIHRoZXJlJ3Mgbm8gcm9sbG91dCBwaGFzZSB0byB3YWl0IGZvclxuICAgICAgOiB7IHN0YXRlOiBcInJlYWR5XCIsIG9iaiB9XG5cbiAgICBpZiAoc3RhdHVzLnN0YXRlICE9PSBcInJlYWR5XCIpIHtcbiAgICAgIHJlYWR5ID0gZmFsc2VcbiAgICB9XG5cbiAgICByZXR1cm4gc3RhdHVzXG4gIH0pXG5cbiAgcmV0dXJuIHsgcmVhZHksIHN0YXR1c2VzIH1cbn1cblxuaW50ZXJmYWNlIFdhaXRQYXJhbXMge1xuICBjdHg6IFBsdWdpbkNvbnRleHQsXG4gIHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIsXG4gIHNlcnZpY2U6IFNlcnZpY2UsXG4gIG9iamVjdHM6IEt1YmVybmV0ZXNPYmplY3RbXSxcbiAgbG9nRW50cnk/OiBMb2dFbnRyeSxcbn1cblxuLyoqXG4gKiBXYWl0IHVudGlsIHRoZSByb2xsb3V0IGlzIGNvbXBsZXRlIGZvciBlYWNoIG9mIHRoZSBnaXZlbiBLdWJlcm5ldGVzIG9iamVjdHNcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdhaXRGb3JPYmplY3RzKHsgY3R4LCBwcm92aWRlciwgc2VydmljZSwgb2JqZWN0cywgbG9nRW50cnkgfTogV2FpdFBhcmFtcykge1xuICBsZXQgbG9vcHMgPSAwXG4gIGxldCBsYXN0TWVzc2FnZVxuICBjb25zdCBzdGFydFRpbWUgPSBuZXcgRGF0ZSgpLmdldFRpbWUoKVxuXG4gIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LnZlcmJvc2Uoe1xuICAgIHN5bWJvbDogXCJpbmZvXCIsXG4gICAgc2VjdGlvbjogc2VydmljZS5uYW1lLFxuICAgIG1zZzogYFdhaXRpbmcgZm9yIHNlcnZpY2UgdG8gYmUgcmVhZHkuLi5gLFxuICB9KVxuXG4gIGNvbnN0IGFwaSA9IG5ldyBLdWJlQXBpKHByb3ZpZGVyKVxuICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBwcm92aWRlcilcbiAgbGV0IHByZXZTdGF0dXNlczogUm9sbG91dFN0YXR1c1tdID0gb2JqZWN0cy5tYXAoKG9iaikgPT4gKHtcbiAgICBzdGF0ZTogPFNlcnZpY2VTdGF0ZT5cInVua25vd25cIixcbiAgICBvYmosXG4gIH0pKVxuXG4gIHdoaWxlICh0cnVlKSB7XG4gICAgYXdhaXQgc2xlZXAoMjAwMCArIDEwMDAgKiBsb29wcylcblxuICAgIGNvbnN0IHsgcmVhZHksIHN0YXR1c2VzIH0gPSBhd2FpdCBjaGVja09iamVjdFN0YXR1cyhhcGksIG5hbWVzcGFjZSwgb2JqZWN0cywgcHJldlN0YXR1c2VzKVxuXG4gICAgZm9yIChjb25zdCBzdGF0dXMgb2Ygc3RhdHVzZXMpIHtcbiAgICAgIGlmIChzdGF0dXMubGFzdEVycm9yKSB7XG4gICAgICAgIHRocm93IG5ldyBEZXBsb3ltZW50RXJyb3IoYEVycm9yIGRlcGxveWluZyAke3NlcnZpY2UubmFtZX06ICR7c3RhdHVzLmxhc3RFcnJvcn1gLCB7XG4gICAgICAgICAgc2VydmljZU5hbWU6IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICBzdGF0dXMsXG4gICAgICAgIH0pXG4gICAgICB9XG5cbiAgICAgIGlmIChzdGF0dXMubGFzdE1lc3NhZ2UgJiYgKCFsYXN0TWVzc2FnZSB8fCBzdGF0dXMubGFzdE1lc3NhZ2UgIT09IGxhc3RNZXNzYWdlKSkge1xuICAgICAgICBsYXN0TWVzc2FnZSA9IHN0YXR1cy5sYXN0TWVzc2FnZVxuICAgICAgICBsb2dFbnRyeSAmJiBsb2dFbnRyeS52ZXJib3NlKHtcbiAgICAgICAgICBzeW1ib2w6IFwiaW5mb1wiLFxuICAgICAgICAgIHNlY3Rpb246IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICBtc2c6IHN0YXR1cy5sYXN0TWVzc2FnZSxcbiAgICAgICAgfSlcbiAgICAgIH1cbiAgICB9XG5cbiAgICBwcmV2U3RhdHVzZXMgPSBzdGF0dXNlc1xuXG4gICAgaWYgKHJlYWR5KSB7XG4gICAgICBicmVha1xuICAgIH1cblxuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCkuZ2V0VGltZSgpXG5cbiAgICBpZiAobm93IC0gc3RhcnRUaW1lID4gS1VCRUNUTF9ERUZBVUxUX1RJTUVPVVQgKiAxMDAwKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoYFRpbWVkIG91dCB3YWl0aW5nIGZvciAke3NlcnZpY2UubmFtZX0gdG8gZGVwbG95YClcbiAgICB9XG4gIH1cblxuICBsb2dFbnRyeSAmJiBsb2dFbnRyeS52ZXJib3NlKHsgc3ltYm9sOiBcImluZm9cIiwgc2VjdGlvbjogc2VydmljZS5uYW1lLCBtc2c6IGBTZXJ2aWNlIGRlcGxveWVkYCB9KVxufVxuXG4vKipcbiAqIENoZWNrIGlmIGVhY2ggb2YgdGhlIGdpdmVuIEt1YmVybmV0ZXMgb2JqZWN0cyBtYXRjaGVzIHdoYXQncyBpbnN0YWxsZWQgaW4gdGhlIGNsdXN0ZXJcbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGNvbXBhcmVEZXBsb3llZE9iamVjdHMoY3R4OiBQbHVnaW5Db250ZXh0LCBvYmplY3RzOiBLdWJlcm5ldGVzT2JqZWN0W10pOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgY29uc3QgZXhpc3RpbmdPYmplY3RzID0gYXdhaXQgQmx1ZWJpcmQubWFwKG9iamVjdHMsIG9iaiA9PiBnZXREZXBsb3llZE9iamVjdChjdHgsIGN0eC5wcm92aWRlciwgb2JqKSlcblxuICBmb3IgKGxldCBbb2JqLCBleGlzdGluZ1NwZWNdIG9mIHppcChvYmplY3RzLCBleGlzdGluZ09iamVjdHMpKSB7XG4gICAgaWYgKGV4aXN0aW5nU3BlYyAmJiBvYmopIHtcbiAgICAgIC8vIHRoZSBBUEkgdmVyc2lvbiBtYXkgaW1wbGljaXRseSBjaGFuZ2Ugd2hlbiBkZXBsb3lpbmdcbiAgICAgIGV4aXN0aW5nU3BlYy5hcGlWZXJzaW9uID0gb2JqLmFwaVZlcnNpb25cblxuICAgICAgLy8gdGhlIG5hbWVzcGFjZSBwcm9wZXJ0eSBpcyBzaWxlbnRseSBkcm9wcGVkIHdoZW4gYWRkZWQgdG8gbm9uLW5hbWVzcGFjZWRcbiAgICAgIGlmIChvYmoubWV0YWRhdGEubmFtZXNwYWNlICYmIGV4aXN0aW5nU3BlYy5tZXRhZGF0YS5uYW1lc3BhY2UgPT09IHVuZGVmaW5lZCkge1xuICAgICAgICBkZWxldGUgb2JqLm1ldGFkYXRhLm5hbWVzcGFjZVxuICAgICAgfVxuXG4gICAgICBpZiAoIWV4aXN0aW5nU3BlYy5tZXRhZGF0YS5hbm5vdGF0aW9ucykge1xuICAgICAgICBleGlzdGluZ1NwZWMubWV0YWRhdGEuYW5ub3RhdGlvbnMgPSB7fVxuICAgICAgfVxuXG4gICAgICAvLyBoYW5kbGUgYXV0by1maWxsZWQgcHJvcGVydGllcyAodGhpcyBpcyBhIGJpdCBvZiBhIGRlc2lnbiBpc3N1ZSBpbiB0aGUgSzhzIEFQSSlcbiAgICAgIGlmIChvYmoua2luZCA9PT0gXCJTZXJ2aWNlXCIgJiYgb2JqLnNwZWMuY2x1c3RlcklQID09PSBcIlwiKSB7XG4gICAgICAgIGRlbGV0ZSBvYmouc3BlYy5jbHVzdGVySVBcbiAgICAgIH1cblxuICAgICAgLy8gaGFuZGxlIHByb3BlcnRpZXMgdGhhdCBhcmUgb21pdHRlZCBpbiB0aGUgcmVzcG9uc2UgYmVjYXVzZSB0aGV5IGhhdmUgdGhlIGRlZmF1bHQgdmFsdWVcbiAgICAgIC8vIChhbm90aGVyIGRlc2lnbiBpc3N1ZSBpbiB0aGUgSzhzIEFQSSlcbiAgICAgIC8vIE5PVEU6IHRoaXMgYXBwcm9hY2ggd29uJ3QgZmx5IGluIHRoZSBsb25nIHJ1biwgYnV0IGhvcGVmdWxseSB3ZSBjYW4gY2xpbWIgb3V0IG9mIHRoaXMgbWVzcyB3aGVuXG4gICAgICAvLyAgICAgICBga3ViZWN0bCBkaWZmYCBpcyByZWFkeSwgb3Igc2VydmVyLXNpZGUgYXBwbHkvZGlmZiBpcyByZWFkeVxuICAgICAgaWYgKG9iai5raW5kID09PSBcIkRhZW1vblNldFwiKSB7XG4gICAgICAgIGlmIChvYmouc3BlYy5taW5SZWFkeVNlY29uZHMgPT09IDApIHtcbiAgICAgICAgICBkZWxldGUgb2JqLnNwZWMubWluUmVhZHlTZWNvbmRzXG4gICAgICAgIH1cbiAgICAgICAgaWYgKG9iai5zcGVjLnRlbXBsYXRlLnNwZWMuaG9zdE5ldHdvcmsgPT09IGZhbHNlKSB7XG4gICAgICAgICAgZGVsZXRlIG9iai5zcGVjLnRlbXBsYXRlLnNwZWMuaG9zdE5ldHdvcmtcbiAgICAgICAgfVxuICAgICAgfVxuXG4gICAgICAvLyBjbGVhbiBudWxsIHZhbHVlc1xuICAgICAgb2JqID0gPEt1YmVybmV0ZXNPYmplY3Q+cmVtb3ZlTnVsbChvYmopXG4gICAgfVxuXG4gICAgaWYgKCFleGlzdGluZ1NwZWMgfHwgIWlzU3Vic2V0KGV4aXN0aW5nU3BlYywgb2JqKSkge1xuICAgICAgLy8gY29uc29sZS5sb2coSlNPTi5zdHJpbmdpZnkob2JqLCBudWxsLCA0KSlcbiAgICAgIC8vIGNvbnNvbGUubG9nKEpTT04uc3RyaW5naWZ5KGV4aXN0aW5nU3BlYywgbnVsbCwgNCkpXG4gICAgICAvLyBjb25zb2xlLmxvZyhcIi0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cIilcbiAgICAgIC8vIHRocm93IG5ldyBFcnJvcihcImJsYVwiKVxuICAgICAgcmV0dXJuIGZhbHNlXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIHRydWVcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0RGVwbG95ZWRPYmplY3QoY3R4OiBQbHVnaW5Db250ZXh0LCBwcm92aWRlcjogS3ViZXJuZXRlc1Byb3ZpZGVyLCBvYmo6IEt1YmVybmV0ZXNPYmplY3QpIHtcbiAgY29uc3QgYXBpID0gbmV3IEt1YmVBcGkocHJvdmlkZXIpXG4gIGNvbnN0IG5hbWVzcGFjZSA9IG9iai5tZXRhZGF0YS5uYW1lc3BhY2UgfHwgYXdhaXQgZ2V0QXBwTmFtZXNwYWNlKGN0eCwgcHJvdmlkZXIpXG5cbiAgdHJ5IHtcbiAgICBjb25zdCByZXMgPSBhd2FpdCBhcGkucmVhZEJ5U3BlYyhuYW1lc3BhY2UsIG9iailcbiAgICByZXR1cm4gcmVzLmJvZHlcbiAgfSBjYXRjaCAoZXJyKSB7XG4gICAgaWYgKGVyci5jb2RlID09PSA0MDQpIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfSBlbHNlIHtcbiAgICAgIHRocm93IGVyclxuICAgIH1cbiAgfVxufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IHJlbW92ZXMgYWxsIG51bGwgdmFsdWUgcHJvcGVydGllcyBmcm9tIG9iamVjdHNcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHJlbW92ZU51bGw8VD4odmFsdWU6IFQgfCBJdGVyYWJsZTxUPik6IFQgfCBJdGVyYWJsZTxUPiB8IHsgW0sgaW4ga2V5b2YgVF06IFRbS10gfSB7XG4gIGlmIChpc0FycmF5KHZhbHVlKSkge1xuICAgIHJldHVybiB2YWx1ZS5tYXAocmVtb3ZlTnVsbClcbiAgfSBlbHNlIGlmIChpc1BsYWluT2JqZWN0KHZhbHVlKSkge1xuICAgIHJldHVybiA8eyBbSyBpbiBrZXlvZiBUXTogVFtLXSB9Pm1hcFZhbHVlcyhwaWNrQnkoPGFueT52YWx1ZSwgdiA9PiB2ICE9PSBudWxsKSwgcmVtb3ZlTnVsbClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gdmFsdWVcbiAgfVxufVxuIl19 diff --git a/garden-service/build/plugins/kubernetes/system.d.ts b/garden-service/build/plugins/kubernetes/system.d.ts new file mode 100644 index 00000000000..40d23f2dab3 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/system.d.ts @@ -0,0 +1,7 @@ +import { Garden } from "../../garden"; +import { KubernetesProvider } from "./kubernetes"; +export declare const GARDEN_SYSTEM_NAMESPACE = "garden-system"; +export declare const systemSymbol: unique symbol; +export declare function isSystemGarden(provider: KubernetesProvider): boolean; +export declare function getSystemGarden(provider: KubernetesProvider): Promise; +//# sourceMappingURL=system.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/kubernetes/system.js b/garden-service/build/plugins/kubernetes/system.js new file mode 100644 index 00000000000..bae2ed37744 --- /dev/null +++ b/garden-service/build/plugins/kubernetes/system.js @@ -0,0 +1,64 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const constants_1 = require("../../constants"); +const garden_1 = require("../../garden"); +exports.GARDEN_SYSTEM_NAMESPACE = "garden-system"; +const systemProjectPath = path_1.join(constants_1.STATIC_DIR, "kubernetes", "system"); +exports.systemSymbol = Symbol(); +function isSystemGarden(provider) { + return provider.config._system === exports.systemSymbol; +} +exports.isSystemGarden = isSystemGarden; +function getSystemGarden(provider) { + return __awaiter(this, void 0, void 0, function* () { + return garden_1.Garden.factory(systemProjectPath, { + env: "default", + config: { + version: "0", + dirname: "system", + path: systemProjectPath, + project: { + name: "garden-system", + environmentDefaults: { + providers: [], + variables: {}, + }, + defaultEnvironment: "default", + environments: [ + { + name: "default", + providers: [ + { + name: "local-kubernetes", + context: provider.config.context, + namespace: exports.GARDEN_SYSTEM_NAMESPACE, + _system: exports.systemSymbol, + }, + ], + variables: {}, + }, + ], + }, + }, + }); + }); +} +exports.getSystemGarden = getSystemGarden; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMva3ViZXJuZXRlcy9zeXN0ZW0udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILCtCQUEyQjtBQUMzQiwrQ0FBNEM7QUFDNUMseUNBQXFDO0FBR3hCLFFBQUEsdUJBQXVCLEdBQUcsZUFBZSxDQUFBO0FBRXRELE1BQU0saUJBQWlCLEdBQUcsV0FBSSxDQUFDLHNCQUFVLEVBQUUsWUFBWSxFQUFFLFFBQVEsQ0FBQyxDQUFBO0FBQ3JELFFBQUEsWUFBWSxHQUFHLE1BQU0sRUFBRSxDQUFBO0FBRXBDLFNBQWdCLGNBQWMsQ0FBQyxRQUE0QjtJQUN6RCxPQUFPLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTyxLQUFLLG9CQUFZLENBQUE7QUFDakQsQ0FBQztBQUZELHdDQUVDO0FBRUQsU0FBc0IsZUFBZSxDQUFDLFFBQTRCOztRQUNoRSxPQUFPLGVBQU0sQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUU7WUFDdkMsR0FBRyxFQUFFLFNBQVM7WUFDZCxNQUFNLEVBQUU7Z0JBQ04sT0FBTyxFQUFFLEdBQUc7Z0JBQ1osT0FBTyxFQUFFLFFBQVE7Z0JBQ2pCLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLE9BQU8sRUFBRTtvQkFDUCxJQUFJLEVBQUUsZUFBZTtvQkFDckIsbUJBQW1CLEVBQUU7d0JBQ25CLFNBQVMsRUFBRSxFQUFFO3dCQUNiLFNBQVMsRUFBRSxFQUFFO3FCQUNkO29CQUNELGtCQUFrQixFQUFFLFNBQVM7b0JBQzdCLFlBQVksRUFBRTt3QkFDWjs0QkFDRSxJQUFJLEVBQUUsU0FBUzs0QkFDZixTQUFTLEVBQUU7Z0NBQ1Q7b0NBQ0UsSUFBSSxFQUFFLGtCQUFrQjtvQ0FDeEIsT0FBTyxFQUFFLFFBQVEsQ0FBQyxNQUFNLENBQUMsT0FBTztvQ0FDaEMsU0FBUyxFQUFFLCtCQUF1QjtvQ0FDbEMsT0FBTyxFQUFFLG9CQUFZO2lDQUN0Qjs2QkFDRjs0QkFDRCxTQUFTLEVBQUUsRUFBRTt5QkFDZDtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFBO0lBQ0osQ0FBQztDQUFBO0FBL0JELDBDQStCQyIsImZpbGUiOiJwbHVnaW5zL2t1YmVybmV0ZXMvc3lzdGVtLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBTVEFUSUNfRElSIH0gZnJvbSBcIi4uLy4uL2NvbnN0YW50c1wiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vLi4vZ2FyZGVuXCJcbmltcG9ydCB7IEt1YmVybmV0ZXNQcm92aWRlciB9IGZyb20gXCIuL2t1YmVybmV0ZXNcIlxuXG5leHBvcnQgY29uc3QgR0FSREVOX1NZU1RFTV9OQU1FU1BBQ0UgPSBcImdhcmRlbi1zeXN0ZW1cIlxuXG5jb25zdCBzeXN0ZW1Qcm9qZWN0UGF0aCA9IGpvaW4oU1RBVElDX0RJUiwgXCJrdWJlcm5ldGVzXCIsIFwic3lzdGVtXCIpXG5leHBvcnQgY29uc3Qgc3lzdGVtU3ltYm9sID0gU3ltYm9sKClcblxuZXhwb3J0IGZ1bmN0aW9uIGlzU3lzdGVtR2FyZGVuKHByb3ZpZGVyOiBLdWJlcm5ldGVzUHJvdmlkZXIpOiBib29sZWFuIHtcbiAgcmV0dXJuIHByb3ZpZGVyLmNvbmZpZy5fc3lzdGVtID09PSBzeXN0ZW1TeW1ib2xcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldFN5c3RlbUdhcmRlbihwcm92aWRlcjogS3ViZXJuZXRlc1Byb3ZpZGVyKTogUHJvbWlzZTxHYXJkZW4+IHtcbiAgcmV0dXJuIEdhcmRlbi5mYWN0b3J5KHN5c3RlbVByb2plY3RQYXRoLCB7XG4gICAgZW52OiBcImRlZmF1bHRcIixcbiAgICBjb25maWc6IHtcbiAgICAgIHZlcnNpb246IFwiMFwiLFxuICAgICAgZGlybmFtZTogXCJzeXN0ZW1cIixcbiAgICAgIHBhdGg6IHN5c3RlbVByb2plY3RQYXRoLFxuICAgICAgcHJvamVjdDoge1xuICAgICAgICBuYW1lOiBcImdhcmRlbi1zeXN0ZW1cIixcbiAgICAgICAgZW52aXJvbm1lbnREZWZhdWx0czoge1xuICAgICAgICAgIHByb3ZpZGVyczogW10sXG4gICAgICAgICAgdmFyaWFibGVzOiB7fSxcbiAgICAgICAgfSxcbiAgICAgICAgZGVmYXVsdEVudmlyb25tZW50OiBcImRlZmF1bHRcIixcbiAgICAgICAgZW52aXJvbm1lbnRzOiBbXG4gICAgICAgICAge1xuICAgICAgICAgICAgbmFtZTogXCJkZWZhdWx0XCIsXG4gICAgICAgICAgICBwcm92aWRlcnM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG5hbWU6IFwibG9jYWwta3ViZXJuZXRlc1wiLFxuICAgICAgICAgICAgICAgIGNvbnRleHQ6IHByb3ZpZGVyLmNvbmZpZy5jb250ZXh0LFxuICAgICAgICAgICAgICAgIG5hbWVzcGFjZTogR0FSREVOX1NZU1RFTV9OQU1FU1BBQ0UsXG4gICAgICAgICAgICAgICAgX3N5c3RlbTogc3lzdGVtU3ltYm9sLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHZhcmlhYmxlczoge30sXG4gICAgICAgICAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfSlcbn1cbiJdfQ== diff --git a/garden-service/build/plugins/local/local-docker-swarm.d.ts b/garden-service/build/plugins/local/local-docker-swarm.d.ts new file mode 100644 index 00000000000..a84cbe3d56c --- /dev/null +++ b/garden-service/build/plugins/local/local-docker-swarm.d.ts @@ -0,0 +1,3 @@ +import { GardenPlugin } from "../../types/plugin/plugin"; +export declare const gardenPlugin: () => GardenPlugin; +//# sourceMappingURL=local-docker-swarm.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/local/local-docker-swarm.js b/garden-service/build/plugins/local/local-docker-swarm.js new file mode 100644 index 00000000000..51a98c6f456 --- /dev/null +++ b/garden-service/build/plugins/local/local-docker-swarm.js @@ -0,0 +1,302 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Docker = require("dockerode"); +const child_process_promise_1 = require("child-process-promise"); +const exceptions_1 = require("../../exceptions"); +const container_1 = require("../container"); +const lodash_1 = require("lodash"); +const util_1 = require("../../util/util"); +// should this be configurable and/or global across providers? +const DEPLOY_TIMEOUT = 30; +const pluginName = "local-docker-swarm"; +exports.gardenPlugin = () => ({ + actions: { + getEnvironmentStatus, + prepareEnvironment, + }, + moduleActions: { + container: { + getServiceStatus, + deployService({ ctx, module, service, runtimeContext, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: split this method up and test + const { versionString } = service.module.version; + logEntry && logEntry.info({ section: service.name, msg: `Deploying version ${versionString}` }); + const identifier = yield container_1.helpers.getLocalImageId(module); + const ports = service.spec.ports.map(p => { + const port = { + Protocol: p.protocol ? p.protocol.toLowerCase() : "tcp", + TargetPort: p.containerPort, + }; + if (p.hostPort) { + port.PublishedPort = p.hostPort; + } + }); + const envVars = lodash_1.map(Object.assign({}, runtimeContext.envVars, service.spec.env), (v, k) => `${k}=${v}`); + const volumeMounts = service.spec.volumes.map(v => { + // TODO-LOW: Support named volumes + if (v.hostPath) { + return { + Type: "bind", + Source: v.hostPath, + Target: v.containerPath, + }; + } + else { + return { + Type: "tmpfs", + Target: v.containerPath, + }; + } + }); + const opts = { + Name: getSwarmServiceName(ctx, service.name), + Labels: { + environment: ctx.environment.name, + provider: pluginName, + }, + TaskTemplate: { + ContainerSpec: { + Image: identifier, + Command: service.spec.command, + Env: envVars, + Mounts: volumeMounts, + }, + Resources: { + Limits: {}, + Reservations: {}, + }, + RestartPolicy: {}, + Placement: {}, + }, + Mode: { + Replicated: { + Replicas: 1, + }, + }, + UpdateConfig: { + Parallelism: 1, + }, + IngressSpec: { + Ports: ports, + }, + }; + const docker = getDocker(); + const serviceStatus = yield getServiceStatus({ ctx, service, module, runtimeContext, logEntry }); + let swarmServiceStatus; + let serviceId; + if (serviceStatus.providerId) { + const swarmService = yield docker.getService(serviceStatus.providerId); + swarmServiceStatus = yield swarmService.inspect(); + opts.version = parseInt(swarmServiceStatus.Version.Index, 10); + logEntry && logEntry.verbose({ + section: service.name, + msg: `Updating existing Swarm service (version ${opts.version})`, + }); + yield swarmService.update(opts); + serviceId = serviceStatus.providerId; + } + else { + logEntry && logEntry.verbose({ + section: service.name, + msg: `Creating new Swarm service`, + }); + const swarmService = yield docker.createService(opts); + serviceId = swarmService.ID; + } + // Wait for service to be ready + const start = new Date().getTime(); + while (true) { + yield util_1.sleep(1000); + const { lastState, lastError } = yield getServiceState(serviceId); + if (lastError) { + throw new exceptions_1.DeploymentError(`Service ${service.name} ${lastState}: ${lastError}`, { + service, + state: lastState, + error: lastError, + }); + } + if (mapContainerState(lastState) === "ready") { + break; + } + if (new Date().getTime() - start > DEPLOY_TIMEOUT * 1000) { + throw new exceptions_1.DeploymentError(`Timed out deploying ${service.name} (status: ${lastState}`, { + service, + state: lastState, + }); + } + } + logEntry && logEntry.info({ + section: service.name, + msg: `Ready`, + }); + return getServiceStatus({ ctx, module, service, runtimeContext, logEntry }); + }); + }, + getServiceOutputs({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + return { + host: getSwarmServiceName(ctx, service.name), + }; + }); + }, + execInService({ ctx, service, command, runtimeContext, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const status = yield getServiceStatus({ + ctx, + service, + module: service.module, + runtimeContext, + logEntry, + }); + if (!status.state || status.state !== "ready") { + throw new exceptions_1.DeploymentError(`Service ${service.name} is not running`, { + name: service.name, + state: status.state, + }); + } + // This is ugly, but dockerode doesn't have this, or at least it's too cumbersome to implement. + const swarmServiceName = getSwarmServiceName(ctx, service.name); + const servicePsCommand = [ + "docker", "service", "ps", + "-f", `'name=${swarmServiceName}.1'`, + "-f", `'desired-state=running'`, + swarmServiceName, + "-q", + ]; + let res = yield child_process_promise_1.exec(servicePsCommand.join(" ")); + const serviceContainerId = `${swarmServiceName}.1.${res.stdout.trim()}`; + const execCommand = ["docker", "exec", serviceContainerId, ...command]; + res = yield child_process_promise_1.exec(execCommand.join(" ")); + return { code: 0, output: "", stdout: res.stdout, stderr: res.stderr }; + }); + }, + }, + }, +}); +function getEnvironmentStatus() { + return __awaiter(this, void 0, void 0, function* () { + const docker = getDocker(); + try { + yield docker.swarmInspect(); + return { + ready: true, + }; + } + catch (err) { + if (err.statusCode === 503) { + // swarm has not been initialized + return { + ready: false, + services: [], + }; + } + else { + throw err; + } + } + }); +} +function prepareEnvironment() { + return __awaiter(this, void 0, void 0, function* () { + yield getDocker().swarmInit({}); + return {}; + }); +} +function getServiceStatus({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + const docker = getDocker(); + const swarmServiceName = getSwarmServiceName(ctx, service.name); + const swarmService = docker.getService(swarmServiceName); + let swarmServiceStatus; + try { + swarmServiceStatus = yield swarmService.inspect(); + } + catch (err) { + if (err.statusCode === 404) { + // service does not exist + return {}; + } + else { + throw err; + } + } + const image = swarmServiceStatus.Spec.TaskTemplate.ContainerSpec.Image; + const version = image.split(":")[1]; + const { lastState, lastError } = yield getServiceState(swarmServiceStatus.ID); + return { + providerId: swarmServiceStatus.ID, + version, + runningReplicas: swarmServiceStatus.Spec.Mode.Replicated.Replicas, + state: mapContainerState(lastState), + lastError: lastError || undefined, + createdAt: swarmServiceStatus.CreatedAt, + updatedAt: swarmServiceStatus.UpdatedAt, + }; + }); +} +function getDocker() { + return new Docker(); +} +// see schema in https://docs.docker.com/engine/api/v1.35/#operation/TaskList +const taskStateMap = { + new: "deploying", + allocated: "deploying", + pending: "deploying", + assigned: "deploying", + accepted: "deploying", + preparing: "deploying", + starting: "deploying", + running: "ready", + ready: "ready", + complete: "stopped", + shutdown: "stopped", + failed: "unhealthy", + rejected: "unhealthy", +}; +function mapContainerState(lastState) { + return lastState ? taskStateMap[lastState] : undefined; +} +function getSwarmServiceName(ctx, serviceName) { + return `${ctx.projectName}--${serviceName}`; +} +function getServiceTask(serviceId) { + return __awaiter(this, void 0, void 0, function* () { + let tasks = yield getDocker().listTasks({ + // Service: this.getSwarmServiceName(service.name), + }); + // For whatever (presumably totally reasonable) reason, the filter option above does not work. + tasks = tasks.filter(t => t.ServiceID === serviceId); + tasks = lodash_1.sortBy(tasks, ["CreatedAt"]).reverse(); + return tasks[0]; + }); +} +function getServiceState(serviceId) { + return __awaiter(this, void 0, void 0, function* () { + const task = yield getServiceTask(serviceId); + let lastState; + let lastError; + if (task) { + lastState = task.Status.State; + lastError = task.Status.Err || null; + } + return { lastState, lastError }; + }); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvbG9jYWwvbG9jYWwtZG9ja2VyLXN3YXJtLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxvQ0FBbUM7QUFDbkMsaUVBQTRDO0FBQzVDLGlEQUFrRDtBQVdsRCw0Q0FHcUI7QUFDckIsbUNBR2U7QUFDZiwwQ0FBdUM7QUFHdkMsOERBQThEO0FBQzlELE1BQU0sY0FBYyxHQUFHLEVBQUUsQ0FBQTtBQUV6QixNQUFNLFVBQVUsR0FBRyxvQkFBb0IsQ0FBQTtBQUUxQixRQUFBLFlBQVksR0FBRyxHQUFpQixFQUFFLENBQUMsQ0FBQztJQUMvQyxPQUFPLEVBQUU7UUFDUCxvQkFBb0I7UUFDcEIsa0JBQWtCO0tBQ25CO0lBQ0QsYUFBYSxFQUFFO1FBQ2IsU0FBUyxFQUFFO1lBQ1QsZ0JBQWdCO1lBRVYsYUFBYSxDQUNqQixFQUFFLEdBQUcsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLGNBQWMsRUFBRSxRQUFRLEVBQXdDOztvQkFFeEYsc0NBQXNDO29CQUN0QyxNQUFNLEVBQUUsYUFBYSxFQUFFLEdBQUcsT0FBTyxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUE7b0JBRWhELFFBQVEsSUFBSSxRQUFRLENBQUMsSUFBSSxDQUFDLEVBQUUsT0FBTyxFQUFFLE9BQU8sQ0FBQyxJQUFJLEVBQUUsR0FBRyxFQUFFLHFCQUFxQixhQUFhLEVBQUUsRUFBRSxDQUFDLENBQUE7b0JBRS9GLE1BQU0sVUFBVSxHQUFHLE1BQU0sbUJBQU8sQ0FBQyxlQUFlLENBQUMsTUFBTSxDQUFDLENBQUE7b0JBQ3hELE1BQU0sS0FBSyxHQUFHLE9BQU8sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRTt3QkFDdkMsTUFBTSxJQUFJLEdBQVE7NEJBQ2hCLFFBQVEsRUFBRSxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLFdBQVcsRUFBRSxDQUFD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O1FBQ3RDLG1EQUFtRDtTQUNwRCxDQUFDLENBQUE7UUFDRiw4RkFBOEY7UUFDOUYsS0FBSyxHQUFHLEtBQUssQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsU0FBUyxLQUFLLFNBQVMsQ0FBQyxDQUFBO1FBQ3BELEtBQUssR0FBRyxlQUFNLENBQUMsS0FBSyxFQUFFLENBQUMsV0FBVyxDQUFDLENBQUMsQ0FBQyxPQUFPLEVBQUUsQ0FBQTtRQUU5QyxPQUFPLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQTtJQUNqQixDQUFDO0NBQUE7QUFFRCxTQUFlLGVBQWUsQ0FBQyxTQUFpQjs7UUFDOUMsTUFBTSxJQUFJLEdBQUcsTUFBTSxjQUFjLENBQUMsU0FBUyxDQUFDLENBQUE7UUFFNUMsSUFBSSxTQUFTLENBQUE7UUFDYixJQUFJLFNBQVMsQ0FBQTtRQUViLElBQUksSUFBSSxFQUFFO1lBQ1IsU0FBUyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFBO1lBQzdCLFNBQVMsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsSUFBSSxJQUFJLENBQUE7U0FDcEM7UUFFRCxPQUFPLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxDQUFBO0lBQ2pDLENBQUM7Q0FBQSIsImZpbGUiOiJwbHVnaW5zL2xvY2FsL2xvY2FsLWRvY2tlci1zd2FybS5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBEb2NrZXIgZnJvbSBcImRvY2tlcm9kZVwiXG5pbXBvcnQgeyBleGVjIH0gZnJvbSBcImNoaWxkLXByb2Nlc3MtcHJvbWlzZVwiXG5pbXBvcnQgeyBEZXBsb3ltZW50RXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBQbHVnaW5Db250ZXh0IH0gZnJvbSBcIi4uLy4uL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7XG4gIEdhcmRlblBsdWdpbixcbn0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9wbHVnaW5cIlxuaW1wb3J0IHtcbiAgRGVwbG95U2VydmljZVBhcmFtcyxcbiAgRXhlY0luU2VydmljZVBhcmFtcyxcbiAgR2V0U2VydmljZU91dHB1dHNQYXJhbXMsXG4gIEdldFNlcnZpY2VTdGF0dXNQYXJhbXMsXG59IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7XG4gIGhlbHBlcnMsXG4gIENvbnRhaW5lck1vZHVsZSxcbn0gZnJvbSBcIi4uL2NvbnRhaW5lclwiXG5pbXBvcnQge1xuICBtYXAsXG4gIHNvcnRCeSxcbn0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyBzbGVlcCB9IGZyb20gXCIuLi8uLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgU2VydmljZVN0YXRlLCBTZXJ2aWNlU3RhdHVzIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuXG4vLyBzaG91bGQgdGhpcyBiZSBjb25maWd1cmFibGUgYW5kL29yIGdsb2JhbCBhY3Jvc3MgcHJvdmlkZXJzP1xuY29uc3QgREVQTE9ZX1RJTUVPVVQgPSAzMFxuXG5jb25zdCBwbHVnaW5OYW1lID0gXCJsb2NhbC1kb2NrZXItc3dhcm1cIlxuXG5leHBvcnQgY29uc3QgZ2FyZGVuUGx1Z2luID0gKCk6IEdhcmRlblBsdWdpbiA9PiAoe1xuICBhY3Rpb25zOiB7XG4gICAgZ2V0RW52aXJvbm1lbnRTdGF0dXMsXG4gICAgcHJlcGFyZUVudmlyb25tZW50LFxuICB9LFxuICBtb2R1bGVBY3Rpb25zOiB7XG4gICAgY29udGFpbmVyOiB7XG4gICAgICBnZXRTZXJ2aWNlU3RhdHVzLFxuXG4gICAgICBhc3luYyBkZXBsb3lTZXJ2aWNlKFxuICAgICAgICB7IGN0eCwgbW9kdWxlLCBzZXJ2aWNlLCBydW50aW1lQ29udGV4dCwgbG9nRW50cnkgfTogRGVwbG95U2VydmljZVBhcmFtczxDb250YWluZXJNb2R1bGU+LFxuICAgICAgKSB7XG4gICAgICAgIC8vIFRPRE86IHNwbGl0IHRoaXMgbWV0aG9kIHVwIGFuZCB0ZXN0XG4gICAgICAgIGNvbnN0IHsgdmVyc2lvblN0cmluZyB9ID0gc2VydmljZS5tb2R1bGUudmVyc2lvblxuXG4gICAgICAgIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LmluZm8oeyBzZWN0aW9uOiBzZXJ2aWNlLm5hbWUsIG1zZzogYERlcGxveWluZyB2ZXJzaW9uICR7dmVyc2lvblN0cmluZ31gIH0pXG5cbiAgICAgICAgY29uc3QgaWRlbnRpZmllciA9IGF3YWl0IGhlbHBlcnMuZ2V0TG9jYWxJbWFnZUlkKG1vZHVsZSlcbiAgICAgICAgY29uc3QgcG9ydHMgPSBzZXJ2aWNlLnNwZWMucG9ydHMubWFwKHAgPT4ge1xuICAgICAgICAgIGNvbnN0IHBvcnQ6IGFueSA9IHtcbiAgICAgICAgICAgIFByb3RvY29sOiBwLnByb3RvY29sID8gcC5wcm90b2NvbC50b0xvd2VyQ2FzZSgpIDogXCJ0Y3BcIixcbiAgICAgICAgICAgIFRhcmdldFBvcnQ6IHAuY29udGFpbmVyUG9ydCxcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAocC5ob3N0UG9ydCkge1xuICAgICAgICAgICAgcG9ydC5QdWJsaXNoZWRQb3J0ID0gcC5ob3N0UG9ydFxuICAgICAgICAgIH1cbiAgICAgICAgfSlcblxuICAgICAgICBjb25zdCBlbnZWYXJzID0gbWFwKHsgLi4ucnVudGltZUNvbnRleHQuZW52VmFycywgLi4uc2VydmljZS5zcGVjLmVudiB9LCAodiwgaykgPT4gYCR7a309JHt2fWApXG5cbiAgICAgICAgY29uc3Qgdm9sdW1lTW91bnRzID0gc2VydmljZS5zcGVjLnZvbHVtZXMubWFwKHYgPT4ge1xuICAgICAgICAgIC8vIFRPRE8tTE9XOiBTdXBwb3J0IG5hbWVkIHZvbHVtZXNcbiAgICAgICAgICBpZiAodi5ob3N0UGF0aCkge1xuICAgICAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICAgICAgVHlwZTogXCJiaW5kXCIsXG4gICAgICAgICAgICAgIFNvdXJjZTogdi5ob3N0UGF0aCxcbiAgICAgICAgICAgICAgVGFyZ2V0OiB2LmNvbnRhaW5lclBhdGgsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICAgIHJldHVybiB7XG4gICAgICAgICAgICAgIFR5cGU6IFwidG1wZnNcIixcbiAgICAgICAgICAgICAgVGFyZ2V0OiB2LmNvbnRhaW5lclBhdGgsXG4gICAgICAgICAgICB9XG4gICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIGNvbnN0IG9wdHM6IGFueSA9IHtcbiAgICAgICAgICBOYW1lOiBnZXRTd2FybVNlcnZpY2VOYW1lKGN0eCwgc2VydmljZS5uYW1lKSxcbiAgICAgICAgICBMYWJlbHM6IHtcbiAgICAgICAgICAgIGVudmlyb25tZW50OiBjdHguZW52aXJvbm1lbnQubmFtZSxcbiAgICAgICAgICAgIHByb3ZpZGVyOiBwbHVnaW5OYW1lLFxuICAgICAgICAgIH0sXG4gICAgICAgICAgVGFza1RlbXBsYXRlOiB7XG4gICAgICAgICAgICBDb250YWluZXJTcGVjOiB7XG4gICAgICAgICAgICAgIEltYWdlOiBpZGVudGlmaWVyLFxuICAgICAgICAgICAgICBDb21tYW5kOiBzZXJ2aWNlLnNwZWMuY29tbWFuZCxcbiAgICAgICAgICAgICAgRW52OiBlbnZWYXJzLFxuICAgICAgICAgICAgICBNb3VudHM6IHZvbHVtZU1vdW50cyxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBSZXNvdXJjZXM6IHtcbiAgICAgICAgICAgICAgTGltaXRzOiB7fSxcbiAgICAgICAgICAgICAgUmVzZXJ2YXRpb25zOiB7fSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgICBSZXN0YXJ0UG9saWN5OiB7fSxcbiAgICAgICAgICAgIFBsYWNlbWVudDoge30sXG4gICAgICAgICAgfSxcbiAgICAgICAgICBNb2RlOiB7XG4gICAgICAgICAgICBSZXBsaWNhdGVkOiB7XG4gICAgICAgICAgICAgIFJlcGxpY2FzOiAxLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIFVwZGF0ZUNvbmZpZzoge1xuICAgICAgICAgICAgUGFyYWxsZWxpc206IDEsXG4gICAgICAgICAgfSxcbiAgICAgICAgICBJbmdyZXNzU3BlYzoge1xuICAgICAgICAgICAgUG9ydHM6IHBvcnRzLFxuICAgICAgICAgIH0sXG4gICAgICAgIH1cblxuICAgICAgICBjb25zdCBkb2NrZXIgPSBnZXREb2NrZXIoKVxuICAgICAgICBjb25zdCBzZXJ2aWNlU3RhdHVzID0gYXdhaXQgZ2V0U2VydmljZVN0YXR1cyh7IGN0eCwgc2VydmljZSwgbW9kdWxlLCBydW50aW1lQ29udGV4dCwgbG9nRW50cnkgfSlcbiAgICAgICAgbGV0IHN3YXJtU2VydmljZVN0YXR1c1xuICAgICAgICBsZXQgc2VydmljZUlkXG5cbiAgICAgICAgaWYgKHNlcnZpY2VTdGF0dXMucHJvdmlkZXJJZCkge1xuICAgICAgICAgIGNvbnN0IHN3YXJtU2VydmljZSA9IGF3YWl0IGRvY2tlci5nZXRTZXJ2aWNlKHNlcnZpY2VTdGF0dXMucHJvdmlkZXJJZClcbiAgICAgICAgICBzd2FybVNlcnZpY2VTdGF0dXMgPSBhd2FpdCBzd2FybVNlcnZpY2UuaW5zcGVjdCgpXG4gICAgICAgICAgb3B0cy52ZXJzaW9uID0gcGFyc2VJbnQoc3dhcm1TZXJ2aWNlU3RhdHVzLlZlcnNpb24uSW5kZXgsIDEwKVxuICAgICAgICAgIGxvZ0VudHJ5ICYmIGxvZ0VudHJ5LnZlcmJvc2Uoe1xuICAgICAgICAgICAgc2VjdGlvbjogc2VydmljZS5uYW1lLFxuICAgICAgICAgICAgbXNnOiBgVXBkYXRpbmcgZXhpc3RpbmcgU3dhcm0gc2VydmljZSAodmVyc2lvbiAke29wdHMudmVyc2lvbn0pYCxcbiAgICAgICAgICB9KVxuICAgICAgICAgIGF3YWl0IHN3YXJtU2VydmljZS51cGRhdGUob3B0cylcbiAgICAgICAgICBzZXJ2aWNlSWQgPSBzZXJ2aWNlU3RhdHVzLnByb3ZpZGVySWRcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBsb2dFbnRyeSAmJiBsb2dFbnRyeS52ZXJib3NlKHtcbiAgICAgICAgICAgIHNlY3Rpb246IHNlcnZpY2UubmFtZSxcbiAgICAgICAgICAgIG1zZzogYENyZWF0aW5nIG5ldyBTd2FybSBzZXJ2aWNlYCxcbiAgICAgICAgICB9KVxuICAgICAgICAgIGNvbnN0IHN3YXJtU2VydmljZSA9IGF3YWl0IGRvY2tlci5jcmVhdGVTZXJ2aWNlKG9wdHMpXG4gICAgICAgICAgc2VydmljZUlkID0gc3dhcm1TZXJ2aWNlLklEXG4gICAgICAgIH1cblxuICAgICAgICAvLyBXYWl0IGZvciBzZXJ2aWNlIHRvIGJlIHJlYWR5XG4gICAgICAgIGNvbnN0IHN0YXJ0ID0gbmV3IERhdGUoKS5nZXRUaW1lKClcblxuICAgICAgICB3aGlsZSAodHJ1ZSkge1xuICAgICAgICAgIGF3YWl0IHNsZWVwKDEwMDApXG5cbiAgICAgICAgICBjb25zdCB7IGxhc3RTdGF0ZSwgbGFzdEVycm9yIH0gPSBhd2FpdCBnZXRTZXJ2aWNlU3RhdGUoc2VydmljZUlkKVxuXG4gICAgICAgICAgaWYgKGxhc3RFcnJvcikge1xuICAgICAgICAgICAgdGhyb3cgbmV3IERlcGxveW1lbnRFcnJvcihgU2VydmljZSAke3NlcnZpY2UubmFtZX0gJHtsYXN0U3RhdGV9OiAke2xhc3RFcnJvcn1gLCB7XG4gICAgICAgICAgICAgIHNlcnZpY2UsXG4gICAgICAgICAgICAgIHN0YXRlOiBsYXN0U3RhdGUsXG4gICAgICAgICAgICAgIGVycm9yOiBsYXN0RXJyb3IsXG4gICAgICAgICAgICB9KVxuICAgICAgICAgIH1cblxuICAgICAgICAgIGlmIChtYXBDb250YWluZXJTdGF0ZShsYXN0U3RhdGUpID09PSBcInJlYWR5XCIpIHtcbiAgICAgICAgICAgIGJyZWFrXG4gICAgICAgICAgfVxuXG4gICAgICAgICAgaWYgKG5ldyBEYXRlKCkuZ2V0VGltZSgpIC0gc3RhcnQgPiBERVBMT1lfVElNRU9VVCAqIDEwMDApIHtcbiAgICAgICAgICAgIHRocm93IG5ldyBEZXBsb3ltZW50RXJyb3IoYFRpbWVkIG91dCBkZXBsb3lpbmcgJHtzZXJ2aWNlLm5hbWV9IChzdGF0dXM6ICR7bGFzdFN0YXRlfWAsIHtcbiAgICAgICAgICAgICAgc2VydmljZSxcbiAgICAgICAgICAgICAgc3RhdGU6IGxhc3RTdGF0ZSxcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgICAgbG9nRW50cnkgJiYgbG9nRW50cnkuaW5mbyh7XG4gICAgICAgICAgc2VjdGlvbjogc2VydmljZS5uYW1lLFxuICAgICAgICAgIG1zZzogYFJlYWR5YCxcbiAgICAgICAgfSlcblxuICAgICAgICByZXR1cm4gZ2V0U2VydmljZVN0YXR1cyh7IGN0eCwgbW9kdWxlLCBzZXJ2aWNlLCBydW50aW1lQ29udGV4dCwgbG9nRW50cnkgfSlcbiAgICAgIH0sXG5cbiAgICAgIGFzeW5jIGdldFNlcnZpY2VPdXRwdXRzKHsgY3R4LCBzZXJ2aWNlIH06IEdldFNlcnZpY2VPdXRwdXRzUGFyYW1zPENvbnRhaW5lck1vZHVsZT4pIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBob3N0OiBnZXRTd2FybVNlcnZpY2VOYW1lKGN0eCwgc2VydmljZS5uYW1lKSxcbiAgICAgICAgfVxuICAgICAgfSxcblxuICAgICAgYXN5bmMgZXhlY0luU2VydmljZShcbiAgICAgICAgeyBjdHgsIHNlcnZpY2UsIGNvbW1hbmQsIHJ1bnRpbWVDb250ZXh0LCBsb2dFbnRyeSB9OiBFeGVjSW5TZXJ2aWNlUGFyYW1zPENvbnRhaW5lck1vZHVsZT4sXG4gICAgICApIHtcbiAgICAgICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgZ2V0U2VydmljZVN0YXR1cyh7XG4gICAgICAgICAgY3R4LFxuICAgICAgICAgIHNlcnZpY2UsXG4gICAgICAgICAgbW9kdWxlOiBzZXJ2aWNlLm1vZHVsZSxcbiAgICAgICAgICBydW50aW1lQ29udGV4dCxcbiAgICAgICAgICBsb2dFbnRyeSxcbiAgICAgICAgfSlcblxuICAgICAgICBpZiAoIXN0YXR1cy5zdGF0ZSB8fCBzdGF0dXMuc3RhdGUgIT09IFwicmVhZHlcIikge1xuICAgICAgICAgIHRocm93IG5ldyBEZXBsb3ltZW50RXJyb3IoYFNlcnZpY2UgJHtzZXJ2aWNlLm5hbWV9IGlzIG5vdCBydW5uaW5nYCwge1xuICAgICAgICAgICAgbmFtZTogc2VydmljZS5uYW1lLFxuICAgICAgICAgICAgc3RhdGU6IHN0YXR1cy5zdGF0ZSxcbiAgICAgICAgICB9KVxuICAgICAgICB9XG5cbiAgICAgICAgLy8gVGhpcyBpcyB1Z2x5LCBidXQgZG9ja2Vyb2RlIGRvZXNuJ3QgaGF2ZSB0aGlzLCBvciBhdCBsZWFzdCBpdCdzIHRvbyBjdW1iZXJzb21lIHRvIGltcGxlbWVudC5cbiAgICAgICAgY29uc3Qgc3dhcm1TZXJ2aWNlTmFtZSA9IGdldFN3YXJtU2VydmljZU5hbWUoY3R4LCBzZXJ2aWNlLm5hbWUpXG4gICAgICAgIGNvbnN0IHNlcnZpY2VQc0NvbW1hbmQgPSBbXG4gICAgICAgICAgXCJkb2NrZXJcIiwgXCJzZXJ2aWNlXCIsIFwicHNcIixcbiAgICAgICAgICBcIi1mXCIsIGAnbmFtZT0ke3N3YXJtU2VydmljZU5hbWV9LjEnYCxcbiAgICAgICAgICBcIi1mXCIsIGAnZGVzaXJlZC1zdGF0ZT1ydW5uaW5nJ2AsXG4gICAgICAgICAgc3dhcm1TZXJ2aWNlTmFtZSxcbiAgICAgICAgICBcIi1xXCIsXG4gICAgICAgIF1cbiAgICAgICAgbGV0IHJlcyA9IGF3YWl0IGV4ZWMoc2VydmljZVBzQ29tbWFuZC5qb2luKFwiIFwiKSlcbiAgICAgICAgY29uc3Qgc2VydmljZUNvbnRhaW5lcklkID0gYCR7c3dhcm1TZXJ2aWNlTmFtZX0uMS4ke3Jlcy5zdGRvdXQudHJpbSgpfWBcblxuICAgICAgICBjb25zdCBleGVjQ29tbWFuZCA9IFtcImRvY2tlclwiLCBcImV4ZWNcIiwgc2VydmljZUNvbnRhaW5lcklkLCAuLi5jb21tYW5kXVxuICAgICAgICByZXMgPSBhd2FpdCBleGVjKGV4ZWNDb21tYW5kLmpvaW4oXCIgXCIpKVxuXG4gICAgICAgIHJldHVybiB7IGNvZGU6IDAsIG91dHB1dDogXCJcIiwgc3Rkb3V0OiByZXMuc3Rkb3V0LCBzdGRlcnI6IHJlcy5zdGRlcnIgfVxuICAgICAgfSxcbiAgICB9LFxuICB9LFxufSlcblxuYXN5bmMgZnVuY3Rpb24gZ2V0RW52aXJvbm1lbnRTdGF0dXMoKSB7XG4gIGNvbnN0IGRvY2tlciA9IGdldERvY2tlcigpXG5cbiAgdHJ5IHtcbiAgICBhd2FpdCBkb2NrZXIuc3dhcm1JbnNwZWN0KClcblxuICAgIHJldHVybiB7XG4gICAgICByZWFkeTogdHJ1ZSxcbiAgICB9XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuc3RhdHVzQ29kZSA9PT0gNTAzKSB7XG4gICAgICAvLyBzd2FybSBoYXMgbm90IGJlZW4gaW5pdGlhbGl6ZWRcbiAgICAgIHJldHVybiB7XG4gICAgICAgIHJlYWR5OiBmYWxzZSxcbiAgICAgICAgc2VydmljZXM6IFtdLFxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gcHJlcGFyZUVudmlyb25tZW50KCkge1xuICBhd2FpdCBnZXREb2NrZXIoKS5zd2FybUluaXQoe30pXG4gIHJldHVybiB7fVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRTZXJ2aWNlU3RhdHVzKHsgY3R4LCBzZXJ2aWNlIH06IEdldFNlcnZpY2VTdGF0dXNQYXJhbXM8Q29udGFpbmVyTW9kdWxlPik6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICBjb25zdCBkb2NrZXIgPSBnZXREb2NrZXIoKVxuICBjb25zdCBzd2FybVNlcnZpY2VOYW1lID0gZ2V0U3dhcm1TZXJ2aWNlTmFtZShjdHgsIHNlcnZpY2UubmFtZSlcbiAgY29uc3Qgc3dhcm1TZXJ2aWNlID0gZG9ja2VyLmdldFNlcnZpY2Uoc3dhcm1TZXJ2aWNlTmFtZSlcblxuICBsZXQgc3dhcm1TZXJ2aWNlU3RhdHVzXG5cbiAgdHJ5IHtcbiAgICBzd2FybVNlcnZpY2VTdGF0dXMgPSBhd2FpdCBzd2FybVNlcnZpY2UuaW5zcGVjdCgpXG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuc3RhdHVzQ29kZSA9PT0gNDA0KSB7XG4gICAgICAvLyBzZXJ2aWNlIGRvZXMgbm90IGV4aXN0XG4gICAgICByZXR1cm4ge31cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgY29uc3QgaW1hZ2UgPSBzd2FybVNlcnZpY2VTdGF0dXMuU3BlYy5UYXNrVGVtcGxhdGUuQ29udGFpbmVyU3BlYy5JbWFnZVxuICBjb25zdCB2ZXJzaW9uID0gaW1hZ2Uuc3BsaXQoXCI6XCIpWzFdXG5cbiAgY29uc3QgeyBsYXN0U3RhdGUsIGxhc3RFcnJvciB9ID0gYXdhaXQgZ2V0U2VydmljZVN0YXRlKHN3YXJtU2VydmljZVN0YXR1cy5JRClcblxuICByZXR1cm4ge1xuICAgIHByb3ZpZGVySWQ6IHN3YXJtU2VydmljZVN0YXR1cy5JRCxcbiAgICB2ZXJzaW9uLFxuICAgIHJ1bm5pbmdSZXBsaWNhczogc3dhcm1TZXJ2aWNlU3RhdHVzLlNwZWMuTW9kZS5SZXBsaWNhdGVkLlJlcGxpY2FzLFxuICAgIHN0YXRlOiBtYXBDb250YWluZXJTdGF0ZShsYXN0U3RhdGUpLFxuICAgIGxhc3RFcnJvcjogbGFzdEVycm9yIHx8IHVuZGVmaW5lZCxcbiAgICBjcmVhdGVkQXQ6IHN3YXJtU2VydmljZVN0YXR1cy5DcmVhdGVkQXQsXG4gICAgdXBkYXRlZEF0OiBzd2FybVNlcnZpY2VTdGF0dXMuVXBkYXRlZEF0LFxuICB9XG59XG5cbmZ1bmN0aW9uIGdldERvY2tlcigpIHtcbiAgcmV0dXJuIG5ldyBEb2NrZXIoKVxufVxuXG4vLyBzZWUgc2NoZW1hIGluIGh0dHBzOi8vZG9jcy5kb2NrZXIuY29tL2VuZ2luZS9hcGkvdjEuMzUvI29wZXJhdGlvbi9UYXNrTGlzdFxuY29uc3QgdGFza1N0YXRlTWFwOiB7IFtrZXk6IHN0cmluZ106IFNlcnZpY2VTdGF0ZSB9ID0ge1xuICBuZXc6IFwiZGVwbG95aW5nXCIsXG4gIGFsbG9jYXRlZDogXCJkZXBsb3lpbmdcIixcbiAgcGVuZGluZzogXCJkZXBsb3lpbmdcIixcbiAgYXNzaWduZWQ6IFwiZGVwbG95aW5nXCIsXG4gIGFjY2VwdGVkOiBcImRlcGxveWluZ1wiLFxuICBwcmVwYXJpbmc6IFwiZGVwbG95aW5nXCIsXG4gIHN0YXJ0aW5nOiBcImRlcGxveWluZ1wiLFxuICBydW5uaW5nOiBcInJlYWR5XCIsXG4gIHJlYWR5OiBcInJlYWR5XCIsXG4gIGNvbXBsZXRlOiBcInN0b3BwZWRcIixcbiAgc2h1dGRvd246IFwic3RvcHBlZFwiLFxuICBmYWlsZWQ6IFwidW5oZWFsdGh5XCIsXG4gIHJlamVjdGVkOiBcInVuaGVhbHRoeVwiLFxufVxuXG5mdW5jdGlvbiBtYXBDb250YWluZXJTdGF0ZShsYXN0U3RhdGU6IHN0cmluZyB8IHVuZGVmaW5lZCk6IFNlcnZpY2VTdGF0ZSB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBsYXN0U3RhdGUgPyB0YXNrU3RhdGVNYXBbbGFzdFN0YXRlXSA6IHVuZGVmaW5lZFxufVxuXG5mdW5jdGlvbiBnZXRTd2FybVNlcnZpY2VOYW1lKGN0eDogUGx1Z2luQ29udGV4dCwgc2VydmljZU5hbWU6IHN0cmluZykge1xuICByZXR1cm4gYCR7Y3R4LnByb2plY3ROYW1lfS0tJHtzZXJ2aWNlTmFtZX1gXG59XG5cbmFzeW5jIGZ1bmN0aW9uIGdldFNlcnZpY2VUYXNrKHNlcnZpY2VJZDogc3RyaW5nKSB7XG4gIGxldCB0YXNrcyA9IGF3YWl0IGdldERvY2tlcigpLmxpc3RUYXNrcyh7XG4gICAgLy8gU2VydmljZTogdGhpcy5nZXRTd2FybVNlcnZpY2VOYW1lKHNlcnZpY2UubmFtZSksXG4gIH0pXG4gIC8vIEZvciB3aGF0ZXZlciAocHJlc3VtYWJseSB0b3RhbGx5IHJlYXNvbmFibGUpIHJlYXNvbiwgdGhlIGZpbHRlciBvcHRpb24gYWJvdmUgZG9lcyBub3Qgd29yay5cbiAgdGFza3MgPSB0YXNrcy5maWx0ZXIodCA9PiB0LlNlcnZpY2VJRCA9PT0gc2VydmljZUlkKVxuICB0YXNrcyA9IHNvcnRCeSh0YXNrcywgW1wiQ3JlYXRlZEF0XCJdKS5yZXZlcnNlKClcblxuICByZXR1cm4gdGFza3NbMF1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0U2VydmljZVN0YXRlKHNlcnZpY2VJZDogc3RyaW5nKSB7XG4gIGNvbnN0IHRhc2sgPSBhd2FpdCBnZXRTZXJ2aWNlVGFzayhzZXJ2aWNlSWQpXG5cbiAgbGV0IGxhc3RTdGF0ZVxuICBsZXQgbGFzdEVycm9yXG5cbiAgaWYgKHRhc2spIHtcbiAgICBsYXN0U3RhdGUgPSB0YXNrLlN0YXR1cy5TdGF0ZVxuICAgIGxhc3RFcnJvciA9IHRhc2suU3RhdHVzLkVyciB8fCBudWxsXG4gIH1cblxuICByZXR1cm4geyBsYXN0U3RhdGUsIGxhc3RFcnJvciB9XG59XG4iXX0= diff --git a/garden-service/build/plugins/local/local-google-cloud-functions.d.ts b/garden-service/build/plugins/local/local-google-cloud-functions.d.ts new file mode 100644 index 00000000000..57dc9b1c48b --- /dev/null +++ b/garden-service/build/plugins/local/local-google-cloud-functions.d.ts @@ -0,0 +1,3 @@ +import { GardenPlugin } from "../../types/plugin/plugin"; +export declare const gardenPlugin: () => GardenPlugin; +//# sourceMappingURL=local-google-cloud-functions.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/local/local-google-cloud-functions.js b/garden-service/build/plugins/local/local-google-cloud-functions.js new file mode 100644 index 00000000000..bdabc119d98 --- /dev/null +++ b/garden-service/build/plugins/local/local-google-cloud-functions.js @@ -0,0 +1,102 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const path_1 = require("path"); +const google_cloud_functions_1 = require("../google/google-cloud-functions"); +const constants_1 = require("../../constants"); +const pluginName = "local-google-cloud-functions"; +const emulatorModuleName = "local-gcf-container"; +const baseContainerName = `${pluginName}--${emulatorModuleName}`; +const emulatorBaseModulePath = path_1.join(constants_1.STATIC_DIR, emulatorModuleName); +const emulatorPort = 8010; +exports.gardenPlugin = () => ({ + modules: [emulatorBaseModulePath], + moduleActions: { + "google-cloud-function": { + validate(params) { + return __awaiter(this, void 0, void 0, function* () { + const parsed = yield google_cloud_functions_1.parseGcfModule(params); + // convert the module and services to containers to run locally + const serviceConfigs = parsed.serviceConfigs.map((s) => { + const functionEntrypoint = s.spec.entrypoint || s.name; + const spec = { + name: s.name, + dependencies: s.dependencies, + outputs: { + ingress: `http://${s.name}:${emulatorPort}/local/local/${functionEntrypoint}`, + }, + command: ["/app/start.sh", functionEntrypoint], + daemon: false, + ingresses: [{ + name: "default", + hostname: s.spec.hostname, + port: "http", + path: "/", + }], + env: {}, + healthCheck: { tcpPort: "http" }, + ports: [ + { + name: "http", + protocol: "TCP", + containerPort: emulatorPort, + }, + ], + volumes: [], + }; + return { + name: spec.name, + dependencies: spec.dependencies, + outputs: spec.outputs, + spec, + }; + }); + return { + allowPublish: true, + build: { + command: [], + dependencies: parsed.build.dependencies.concat([{ + name: emulatorModuleName, + plugin: pluginName, + copy: [{ + source: "child/Dockerfile", + target: "Dockerfile", + }], + }]), + }, + name: parsed.name, + path: parsed.path, + type: "container", + variables: parsed.variables, + spec: { + buildArgs: { + baseImageName: `${baseContainerName}:\${modules.${baseContainerName}.version}`, + }, + image: `${parsed.name}:\${modules.${parsed.name}.version}`, + services: serviceConfigs.map(s => s.spec), + tests: [], + }, + serviceConfigs, + testConfigs: parsed.testConfigs, + }; + }); + }, + }, + }, +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvbG9jYWwvbG9jYWwtZ29vZ2xlLWNsb3VkLWZ1bmN0aW9ucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBR0gsK0JBQTJCO0FBQzNCLDZFQUd5QztBQUl6QywrQ0FBNEM7QUFPNUMsTUFBTSxVQUFVLEdBQUcsOEJBQThCLENBQUE7QUFDakQsTUFBTSxrQkFBa0IsR0FBRyxxQkFBcUIsQ0FBQTtBQUNoRCxNQUFNLGlCQUFpQixHQUFHLEdBQUcsVUFBVSxLQUFLLGtCQUFrQixFQUFFLENBQUE7QUFDaEUsTUFBTSxzQkFBc0IsR0FBRyxXQUFJLENBQUMsc0JBQVUsRUFBRSxrQkFBa0IsQ0FBQyxDQUFBO0FBQ25FLE1BQU0sWUFBWSxHQUFHLElBQUksQ0FBQTtBQUVaLFFBQUEsWUFBWSxHQUFHLEdBQWlCLEVBQUUsQ0FBQyxDQUFDO0lBQy9DLE9BQU8sRUFBRSxDQUFDLHNCQUFzQixDQUFDO0lBRWpDLGFBQWEsRUFBRTtRQUNiLHVCQUF1QixFQUFFO1lBQ2pCLFFBQVEsQ0FBQyxNQUF1Qzs7b0JBQ3BELE1BQU0sTUFBTSxHQUFHLE1BQU0sdUNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtvQkFFM0MsK0RBQStEO29CQUMvRCxNQUFNLGNBQWMsR0FBMEMsTUFBTSxDQUFDLGNBQWMsQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsRUFBRTt3QkFDNUYsTUFBTSxrQkFBa0IsR0FBRyxDQUFDLENBQUMsSUFBSSxDQUFDLFVBQVUsSUFBSSxDQUFDLENBQUMsSUFBSSxDQUFBO3dCQUV0RCxNQUFNLElBQUksR0FBRzs0QkFDWCxJQUFJLEVBQUUsQ0FBQyxDQUFDLElBQUk7NEJBQ1osWUFBWSxFQUFFLENBQUMsQ0FBQyxZQUFZOzRCQUM1QixPQUFPLEVBQUU7Z0NBQ1AsT0FBTyxFQUFFLFVBQVUsQ0FBQyxDQUFDLElBQUksSUFBSSxZQUFZLGdCQUFnQixrQkFBa0IsRUFBRTs2QkFDOUU7NEJBQ0QsT0FBTyxFQUFFLENBQUMsZUFBZSxFQUFFLGtCQUFrQixDQUFDOzRCQUM5QyxNQUFNLEVBQUUsS0FBSzs0QkFDYixTQUFTLEVBQUUsQ0FBQztvQ0FDVixJQUFJLEVBQUUsU0FBUztvQ0FDZixRQUFRLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxRQUFRO29DQUN6QixJQUFJLEVBQUUsTUFBTTtvQ0FDWixJQUFJLEVBQUUsR0FBRztpQ0FDVixDQUFDOzRCQUNGLEdBQUcsRUFBRSxFQUFFOzRCQUNQLFdBQVcsRUFBRSxFQUFFLE9BQU8sRUFBRSxNQUFNLEVBQUU7NEJBQ2hDLEtBQUssRUFBRTtnQ0FDTDtvQ0FDRSxJQUFJLEVBQUUsTUFBTTtvQ0FDWixRQUFRLEVBQXVCLEtBQUs7b0NBQ3BDLGFBQWEsRUFBRSxZQUFZO2lDQUM1Qjs2QkFDRjs0QkFDRCxPQUFPLEVBQUUsRUFBRTt5QkFDWixDQUFBO3dCQUVELE9BQU87NEJBQ0wsSUFBSSxFQUFFLElBQUksQ0FBQyxJQUFJOzRCQUNmLFlBQVksRUFBRSxJQUFJLENBQUMsWUFBWTs0QkFDL0IsT0FBTyxFQUFFLElBQUksQ0FBQyxPQUFPOzRCQUNyQixJQUFJO3lCQUNMLENBQUE7b0JBQ0gsQ0FBQyxDQUFDLENBQUE7b0JBRUYsT0FBTzt3QkFDTCxZQUFZLEVBQUUsSUFBSTt3QkFDbEIsS0FBSyxFQUFFOzRCQUNMLE9BQU8sRUFBRSxFQUFFOzRCQUNYLFlBQVksRUFBRSxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksQ0FBQyxNQUFNLENBQUMsQ0FBQztvQ0FDOUMsSUFBSSxFQUFFLGtCQUFrQjtvQ0FDeEIsTUFBTSxFQUFFLFVBQVU7b0NBQ2xCLElBQUksRUFBRSxDQUFDOzRDQUNMLE1BQU0sRUFBRSxrQkFBa0I7NENBQzFCLE1BQU0sRUFBRSxZQUFZO3lDQUNyQixDQUFDO2lDQUNILENBQUMsQ0FBQzt5QkFDSjt3QkFDRCxJQUFJLEVBQUUsTUFBTSxDQUFDLElBQUk7d0JBQ2pCLElBQUksRUFBRSxNQUFNLENBQUMsSUFBSTt3QkFDakIsSUFBSSxFQUFFLFdBQVc7d0JBQ2pCLFNBQVMsRUFBRSxNQUFNLENBQUMsU0FBUzt3QkFFM0IsSUFBSSxFQUFFOzRCQUNKLFNBQVMsRUFBRTtnQ0FDVCxhQUFhLEVBQUUsR0FBRyxpQkFBaUIsZUFBZSxpQkFBaUIsV0FBVzs2QkFDL0U7NEJBQ0QsS0FBSyxFQUFFLEdBQUcsTUFBTSxDQUFDLElBQUksZUFBZSxNQUFNLENBQUMsSUFBSSxXQUFXOzRCQUMxRCxRQUFRLEVBQUUsY0FBYyxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsRUFBRSxDQUF1QixDQUFDLENBQUMsSUFBSSxDQUFDOzRCQUMvRCxLQUFLLEVBQUUsRUFBRTt5QkFDVjt3QkFFRCxjQUFjO3dCQUNkLFdBQVcsRUFBRSxNQUFNLENBQUMsV0FBVztxQkFDaEMsQ0FBQTtnQkFDSCxDQUFDO2FBQUE7U0FDRjtLQUNGO0NBQ0YsQ0FBQyxDQUFBIiwiZmlsZSI6InBsdWdpbnMvbG9jYWwvbG9jYWwtZ29vZ2xlLWNsb3VkLWZ1bmN0aW9ucy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgeyBWYWxpZGF0ZU1vZHVsZVBhcmFtcyB9IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQge1xuICBHY2ZNb2R1bGUsXG4gIHBhcnNlR2NmTW9kdWxlLFxufSBmcm9tIFwiLi4vZ29vZ2xlL2dvb2dsZS1jbG91ZC1mdW5jdGlvbnNcIlxuaW1wb3J0IHtcbiAgR2FyZGVuUGx1Z2luLFxufSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BsdWdpblwiXG5pbXBvcnQgeyBTVEFUSUNfRElSIH0gZnJvbSBcIi4uLy4uL2NvbnN0YW50c1wiXG5pbXBvcnQgeyBTZXJ2aWNlQ29uZmlnIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9zZXJ2aWNlXCJcbmltcG9ydCB7XG4gIENvbnRhaW5lclNlcnZpY2VTcGVjLFxuICBTZXJ2aWNlUG9ydFByb3RvY29sLFxufSBmcm9tIFwiLi4vY29udGFpbmVyXCJcblxuY29uc3QgcGx1Z2luTmFtZSA9IFwibG9jYWwtZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uc1wiXG5jb25zdCBlbXVsYXRvck1vZHVsZU5hbWUgPSBcImxvY2FsLWdjZi1jb250YWluZXJcIlxuY29uc3QgYmFzZUNvbnRhaW5lck5hbWUgPSBgJHtwbHVnaW5OYW1lfS0tJHtlbXVsYXRvck1vZHVsZU5hbWV9YFxuY29uc3QgZW11bGF0b3JCYXNlTW9kdWxlUGF0aCA9IGpvaW4oU1RBVElDX0RJUiwgZW11bGF0b3JNb2R1bGVOYW1lKVxuY29uc3QgZW11bGF0b3JQb3J0ID0gODAxMFxuXG5leHBvcnQgY29uc3QgZ2FyZGVuUGx1Z2luID0gKCk6IEdhcmRlblBsdWdpbiA9PiAoe1xuICBtb2R1bGVzOiBbZW11bGF0b3JCYXNlTW9kdWxlUGF0aF0sXG5cbiAgbW9kdWxlQWN0aW9uczoge1xuICAgIFwiZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uXCI6IHtcbiAgICAgIGFzeW5jIHZhbGlkYXRlKHBhcmFtczogVmFsaWRhdGVNb2R1bGVQYXJhbXM8R2NmTW9kdWxlPikge1xuICAgICAgICBjb25zdCBwYXJzZWQgPSBhd2FpdCBwYXJzZUdjZk1vZHVsZShwYXJhbXMpXG5cbiAgICAgICAgLy8gY29udmVydCB0aGUgbW9kdWxlIGFuZCBzZXJ2aWNlcyB0byBjb250YWluZXJzIHRvIHJ1biBsb2NhbGx5XG4gICAgICAgIGNvbnN0IHNlcnZpY2VDb25maWdzOiBTZXJ2aWNlQ29uZmlnPENvbnRhaW5lclNlcnZpY2VTcGVjPltdID0gcGFyc2VkLnNlcnZpY2VDb25maWdzLm1hcCgocykgPT4ge1xuICAgICAgICAgIGNvbnN0IGZ1bmN0aW9uRW50cnlwb2ludCA9IHMuc3BlYy5lbnRyeXBvaW50IHx8IHMubmFtZVxuXG4gICAgICAgICAgY29uc3Qgc3BlYyA9IHtcbiAgICAgICAgICAgIG5hbWU6IHMubmFtZSxcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczogcy5kZXBlbmRlbmNpZXMsXG4gICAgICAgICAgICBvdXRwdXRzOiB7XG4gICAgICAgICAgICAgIGluZ3Jlc3M6IGBodHRwOi8vJHtzLm5hbWV9OiR7ZW11bGF0b3JQb3J0fS9sb2NhbC9sb2NhbC8ke2Z1bmN0aW9uRW50cnlwb2ludH1gLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIGNvbW1hbmQ6IFtcIi9hcHAvc3RhcnQuc2hcIiwgZnVuY3Rpb25FbnRyeXBvaW50XSxcbiAgICAgICAgICAgIGRhZW1vbjogZmFsc2UsXG4gICAgICAgICAgICBpbmdyZXNzZXM6IFt7XG4gICAgICAgICAgICAgIG5hbWU6IFwiZGVmYXVsdFwiLFxuICAgICAgICAgICAgICBob3N0bmFtZTogcy5zcGVjLmhvc3RuYW1lLFxuICAgICAgICAgICAgICBwb3J0OiBcImh0dHBcIixcbiAgICAgICAgICAgICAgcGF0aDogXCIvXCIsXG4gICAgICAgICAgICB9XSxcbiAgICAgICAgICAgIGVudjoge30sXG4gICAgICAgICAgICBoZWFsdGhDaGVjazogeyB0Y3BQb3J0OiBcImh0dHBcIiB9LFxuICAgICAgICAgICAgcG9ydHM6IFtcbiAgICAgICAgICAgICAge1xuICAgICAgICAgICAgICAgIG5hbWU6IFwiaHR0cFwiLFxuICAgICAgICAgICAgICAgIHByb3RvY29sOiA8U2VydmljZVBvcnRQcm90b2NvbD5cIlRDUFwiLFxuICAgICAgICAgICAgICAgIGNvbnRhaW5lclBvcnQ6IGVtdWxhdG9yUG9ydCxcbiAgICAgICAgICAgICAgfSxcbiAgICAgICAgICAgIF0sXG4gICAgICAgICAgICB2b2x1bWVzOiBbXSxcbiAgICAgICAgICB9XG5cbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgbmFtZTogc3BlYy5uYW1lLFxuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBzcGVjLmRlcGVuZGVuY2llcyxcbiAgICAgICAgICAgIG91dHB1dHM6IHNwZWMub3V0cHV0cyxcbiAgICAgICAgICAgIHNwZWMsXG4gICAgICAgICAgfVxuICAgICAgICB9KVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYWxsb3dQdWJsaXNoOiB0cnVlLFxuICAgICAgICAgIGJ1aWxkOiB7XG4gICAgICAgICAgICBjb21tYW5kOiBbXSxcbiAgICAgICAgICAgIGRlcGVuZGVuY2llczogcGFyc2VkLmJ1aWxkLmRlcGVuZGVuY2llcy5jb25jYXQoW3tcbiAgICAgICAgICAgICAgbmFtZTogZW11bGF0b3JNb2R1bGVOYW1lLFxuICAgICAgICAgICAgICBwbHVnaW46IHBsdWdpbk5hbWUsXG4gICAgICAgICAgICAgIGNvcHk6IFt7XG4gICAgICAgICAgICAgICAgc291cmNlOiBcImNoaWxkL0RvY2tlcmZpbGVcIixcbiAgICAgICAgICAgICAgICB0YXJnZXQ6IFwiRG9ja2VyZmlsZVwiLFxuICAgICAgICAgICAgICB9XSxcbiAgICAgICAgICAgIH1dKSxcbiAgICAgICAgICB9LFxuICAgICAgICAgIG5hbWU6IHBhcnNlZC5uYW1lLFxuICAgICAgICAgIHBhdGg6IHBhcnNlZC5wYXRoLFxuICAgICAgICAgIHR5cGU6IFwiY29udGFpbmVyXCIsXG4gICAgICAgICAgdmFyaWFibGVzOiBwYXJzZWQudmFyaWFibGVzLFxuXG4gICAgICAgICAgc3BlYzoge1xuICAgICAgICAgICAgYnVpbGRBcmdzOiB7XG4gICAgICAgICAgICAgIGJhc2VJbWFnZU5hbWU6IGAke2Jhc2VDb250YWluZXJOYW1lfTpcXCR7bW9kdWxlcy4ke2Jhc2VDb250YWluZXJOYW1lfS52ZXJzaW9ufWAsXG4gICAgICAgICAgICB9LFxuICAgICAgICAgICAgaW1hZ2U6IGAke3BhcnNlZC5uYW1lfTpcXCR7bW9kdWxlcy4ke3BhcnNlZC5uYW1lfS52ZXJzaW9ufWAsXG4gICAgICAgICAgICBzZXJ2aWNlczogc2VydmljZUNvbmZpZ3MubWFwKHMgPT4gPENvbnRhaW5lclNlcnZpY2VTcGVjPnMuc3BlYyksXG4gICAgICAgICAgICB0ZXN0czogW10sXG4gICAgICAgICAgfSxcblxuICAgICAgICAgIHNlcnZpY2VDb25maWdzLFxuICAgICAgICAgIHRlc3RDb25maWdzOiBwYXJzZWQudGVzdENvbmZpZ3MsXG4gICAgICAgIH1cbiAgICAgIH0sXG4gICAgfSxcbiAgfSxcbn0pXG4iXX0= diff --git a/garden-service/build/plugins/npm-package.d.ts b/garden-service/build/plugins/npm-package.d.ts new file mode 100644 index 00000000000..7b648972366 --- /dev/null +++ b/garden-service/build/plugins/npm-package.d.ts @@ -0,0 +1,3 @@ +import { GardenPlugin } from "../types/plugin/plugin"; +export declare const gardenPlugin: () => GardenPlugin; +//# sourceMappingURL=npm-package.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/npm-package.js b/garden-service/build/plugins/npm-package.js new file mode 100644 index 00000000000..e92817baa0d --- /dev/null +++ b/garden-service/build/plugins/npm-package.js @@ -0,0 +1,17 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const generic_1 = require("./generic"); +exports.gardenPlugin = () => ({ + moduleActions: { + "npm-package": generic_1.genericPlugin.moduleActions.generic, + }, +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvbnBtLXBhY2thZ2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFHSCx1Q0FFa0I7QUFFTCxRQUFBLFlBQVksR0FBRyxHQUFpQixFQUFFLENBQUMsQ0FBQztJQUMvQyxhQUFhLEVBQUU7UUFDYixhQUFhLEVBQUUsdUJBQWEsQ0FBQyxhQUFjLENBQUMsT0FBTztLQUNwRDtDQUNGLENBQUMsQ0FBQSIsImZpbGUiOiJwbHVnaW5zL25wbS1wYWNrYWdlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IEdhcmRlblBsdWdpbiB9IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vcGx1Z2luXCJcbmltcG9ydCB7XG4gIGdlbmVyaWNQbHVnaW4sXG59IGZyb20gXCIuL2dlbmVyaWNcIlxuXG5leHBvcnQgY29uc3QgZ2FyZGVuUGx1Z2luID0gKCk6IEdhcmRlblBsdWdpbiA9PiAoe1xuICBtb2R1bGVBY3Rpb25zOiB7XG4gICAgXCJucG0tcGFja2FnZVwiOiBnZW5lcmljUGx1Z2luLm1vZHVsZUFjdGlvbnMhLmdlbmVyaWMsXG4gIH0sXG59KVxuIl19 diff --git a/garden-service/build/plugins/openfaas/openfaas.d.ts b/garden-service/build/plugins/openfaas/openfaas.d.ts new file mode 100644 index 00000000000..aded883d2b7 --- /dev/null +++ b/garden-service/build/plugins/openfaas/openfaas.d.ts @@ -0,0 +1,29 @@ +import * as Joi from "joi"; +import { Garden } from "../../garden"; +import { PluginContext } from "../../plugin-context"; +import { Module } from "../../types/module"; +import { Service } from "../../types/service"; +import { GenericModuleSpec, GenericTestSpec } from "../generic"; +import { BaseServiceSpec } from "../../config/service"; +import { GardenPlugin } from "../../types/plugin/plugin"; +import { Provider } from "../../config/project"; +export declare const stackFilename = "stack.yml"; +export declare const FAAS_CLI_IMAGE_ID = "openfaas/faas-cli:0.7.3"; +export interface OpenFaasModuleSpec extends GenericModuleSpec { + handler: string; + image: string; + lang: string; +} +export declare const openfaasModuleSpecSchame: Joi.ObjectSchema; +export interface OpenFaasModule extends Module { +} +export interface OpenFaasService extends Service { +} +export interface OpenFaasConfig extends Provider { + hostname: string; +} +export declare function gardenPlugin({ config }: { + config: OpenFaasConfig; +}): GardenPlugin; +export declare function getOpenFaasGarden(ctx: PluginContext): Promise; +//# sourceMappingURL=openfaas.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/openfaas/openfaas.js b/garden-service/build/plugins/openfaas/openfaas.js new file mode 100644 index 00000000000..8bba465c48d --- /dev/null +++ b/garden-service/build/plugins/openfaas/openfaas.js @@ -0,0 +1,383 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const path_1 = require("path"); +const url_1 = require("url"); +const constants_1 = require("../../constants"); +const exceptions_1 = require("../../exceptions"); +const garden_1 = require("../../garden"); +const common_1 = require("../../config/common"); +const generic_1 = require("../generic"); +const namespace_1 = require("../kubernetes/namespace"); +const lodash_1 = require("lodash"); +const util_1 = require("../../util/util"); +const execa = require("execa"); +const api_1 = require("../kubernetes/api"); +const status_1 = require("../kubernetes/status"); +const system_1 = require("../kubernetes/system"); +const project_1 = require("../../config/project"); +const dedent = require("dedent"); +const systemProjectPath = path_1.join(constants_1.STATIC_DIR, "openfaas", "system"); +exports.stackFilename = "stack.yml"; +exports.FAAS_CLI_IMAGE_ID = "openfaas/faas-cli:0.7.3"; +exports.openfaasModuleSpecSchame = generic_1.genericModuleSpecSchema + .keys({ + dependencies: common_1.joiArray(Joi.string()) + .description("The names of services/functions that this function depends on at runtime."), + handler: Joi.string() + .default(".") + .uri({ relativeOnly: true }) + .description("Specify which directory under the module contains the handler file/function."), + image: Joi.string() + .description("The image name to use for the built OpenFaaS container (defaults to the module name)"), + lang: Joi.string() + .required() + .description("The OpenFaaS language template to use to build this function."), +}) + .unknown(false) + .description("The module specification for an OpenFaaS module."); +const configSchema = project_1.providerConfigBaseSchema + .keys({ + hostname: Joi.string() + .hostname() + .description(dedent ` + The hostname to configure for the function gateway. + Defaults to the default hostname of the configured Kubernetes provider. + + Important: If you have other types of services, this should be different from their ingress hostnames, + or the other services should not expose paths under /function and /system to avoid routing conflicts.`) + .example("functions.mydomain.com"), +}); +function gardenPlugin({ config }) { + config = common_1.validate(config, configSchema, { context: "OpenFaaS provider config" }); + return { + modules: [path_1.join(constants_1.STATIC_DIR, "openfaas", "builder")], + actions: { + getEnvironmentStatus({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + const ofGarden = yield getOpenFaasGarden(ctx); + const status = yield ofGarden.actions.getStatus(); + const envReady = lodash_1.every(lodash_1.values(status.providers).map(s => s.ready)); + const servicesReady = lodash_1.every(lodash_1.values(status.services).map(s => s.state === "ready")); + return { + ready: envReady && servicesReady, + detail: status, + }; + }); + }, + prepareEnvironment({ ctx, force }) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: refactor to dedupe similar code in local-kubernetes + const ofGarden = yield getOpenFaasGarden(ctx); + yield ofGarden.actions.prepareEnvironment({ force }); + const results = yield ofGarden.actions.deployServices({}); + const failed = lodash_1.values(results.taskResults).filter(r => !!r.error).length; + if (failed) { + throw new exceptions_1.PluginError(`openfaas: ${failed} errors occurred when configuring environment`, { + results, + }); + } + return {}; + }); + }, + cleanupEnvironment({ ctx }) { + return __awaiter(this, void 0, void 0, function* () { + const ofGarden = yield getOpenFaasGarden(ctx); + return ofGarden.actions.cleanupEnvironment({}); + }); + }, + }, + moduleActions: { + openfaas: { + validate({ moduleConfig }) { + return __awaiter(this, void 0, void 0, function* () { + moduleConfig.spec = common_1.validate(moduleConfig.spec, exports.openfaasModuleSpecSchame, { context: `module ${moduleConfig.name}` }); + moduleConfig.build.command = [ + "faas-cli", + "build", + "-f", exports.stackFilename, + ]; + moduleConfig.build.dependencies.push({ + name: "builder", + plugin: "openfaas", + copy: [{ + source: "*", + target: ".", + }], + }); + moduleConfig.serviceConfigs = [{ + dependencies: [], + name: moduleConfig.name, + outputs: {}, + spec: { + name: moduleConfig.name, + dependencies: [], + outputs: {}, + }, + }]; + moduleConfig.testConfigs = moduleConfig.spec.tests.map(t => ({ + name: t.name, + dependencies: t.dependencies, + spec: t, + timeout: t.timeout, + })); + return moduleConfig; + }); + }, + getBuildStatus: generic_1.getGenericModuleBuildStatus, + build(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, module } = params; + // prepare the stack.yml file, before handing off the build to the generic handler + yield writeStackFile(ctx, module, {}); + return generic_1.buildGenericModule(params); + }); + }, + // TODO: design and implement a proper test flow for openfaas functions + testModule: generic_1.testGenericModule, + getServiceStatus, + getServiceOutputs({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + return { + endpoint: yield getInternalServiceUrl(ctx, service), + }; + }); + }, + deployService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, module, service, logEntry, runtimeContext } = params; + // write the stack file again with environment variables + yield writeStackFile(ctx, module, runtimeContext.envVars); + // use faas-cli to do the deployment + yield execa("faas-cli", ["deploy", "-f", exports.stackFilename], { cwd: module.buildPath }); + // wait until deployment is ready + const k8sProvider = getK8sProvider(ctx); + const namespace = yield namespace_1.getAppNamespace(ctx, k8sProvider); + const api = new api_1.KubeApi(k8sProvider); + const deployment = (yield api.apps.readNamespacedDeployment(service.name, namespace)).body; + yield status_1.waitForObjects({ ctx, provider: k8sProvider, service, logEntry, objects: [deployment] }); + // TODO: avoid duplicate work here + return getServiceStatus(params); + }); + }, + deleteService(params) { + return __awaiter(this, void 0, void 0, function* () { + const { ctx, logEntry, service, runtimeContext } = params; + let status; + let found = true; + try { + status = yield getServiceStatus({ + ctx, + service, + runtimeContext, + module: service.module, + }); + found = !!status.state; + yield execa("faas-cli", ["remove", "-f", exports.stackFilename], { cwd: service.module.buildPath }); + } + catch (err) { + found = false; + } + if (logEntry) { + found ? logEntry.setSuccess("Service deleted") : logEntry.setWarn("Service not deployed"); + } + return status; + }); + }, + }, + }, + }; +} +exports.gardenPlugin = gardenPlugin; +function writeStackFile(ctx, module, envVars) { + return __awaiter(this, void 0, void 0, function* () { + const image = getImageName(module); + const stackPath = path_1.join(module.buildPath, exports.stackFilename); + return util_1.dumpYaml(stackPath, { + provider: { + name: "faas", + gateway: getExternalGatewayUrl(ctx), + }, + functions: { + [module.name]: { + lang: module.spec.lang, + handler: module.spec.handler, + image, + environment: envVars, + }, + }, + }); + }); +} +function getServiceStatus({ ctx, service }) { + return __awaiter(this, void 0, void 0, function* () { + const k8sProvider = getK8sProvider(ctx); + const ingresses = [{ + hostname: getExternalGatewayHostname(ctx.provider, k8sProvider), + path: getServicePath(service), + port: k8sProvider.config.ingressHttpPort, + protocol: "http", + }]; + const namespace = yield namespace_1.getAppNamespace(ctx, k8sProvider); + const api = new api_1.KubeApi(k8sProvider); + let deployment; + try { + deployment = (yield api.apps.readNamespacedDeployment(service.name, namespace)).body; + } + catch (err) { + if (err.code === 404) { + return {}; + } + else { + throw err; + } + } + const container = util_1.findByName(deployment.spec.template.spec.containers, "hello-function"); + const version = util_1.findByName(container.env, "GARDEN_VERSION").value; + const status = yield status_1.checkDeploymentStatus(api, namespace, deployment); + return { + state: status.state, + version, + ingresses, + }; + }); +} +function getImageName(module) { + return `${module.name || module.spec.image}:${module.version.versionString}`; +} +// NOTE: we're currently not using the CRD/operator, but might change that in the future +// +// async function createFunctionObject(service: OpenFaasService, namespace: string): Promise { +// const image = await getImageName(service.module) +// return { +// apiVersion: "openfaas.com/v1alpha2", +// kind: "Function", +// metadata: { +// name: service.name, +// namespace, +// }, +// spec: { +// name: service.name, +// image, +// labels: { +// "com.openfaas.scale.min": "1", +// "com.openfaas.scale.max": "5", +// }, +// environment: { +// write_debug: "true", +// }, +// limits: { +// cpu: DEFAULT_CPU_LIMIT, +// memory: DEFAULT_MEMORY_LIMIT, +// }, +// requests: { +// cpu: DEFAULT_CPU_REQUEST, +// memory: DEFAULT_MEMORY_REQUEST, +// }, +// }, +// } +// } +function getK8sProvider(ctx) { + const provider = ctx.providers["local-kubernetes"] || ctx.providers.kubernetes; + if (!provider) { + throw new exceptions_1.ConfigurationError(`openfaas requires a kubernetes (or local-kubernetes) provider to be configured`, { + configuredProviders: Object.keys(ctx.providers), + }); + } + return provider; +} +function getServicePath(service) { + return path_1.join("/", "function", service.name); +} +function getInternalGatewayUrl(ctx) { + return __awaiter(this, void 0, void 0, function* () { + const k8sProvider = getK8sProvider(ctx); + const namespace = yield getOpenfaasNamespace(ctx, k8sProvider, true); + return `http://gateway.${namespace}.svc.cluster.local:8080`; + }); +} +function getExternalGatewayHostname(provider, k8sProvider) { + const hostname = provider.config.hostname || k8sProvider.config.defaultHostname; + if (!hostname) { + throw new exceptions_1.ConfigurationError(`openfaas: Must configure hostname if no default hostname is configured on Kubernetes provider.`, { + config: provider, + }); + } + return hostname; +} +function getExternalGatewayUrl(ctx) { + const k8sProvider = getK8sProvider(ctx); + const hostname = getExternalGatewayHostname(ctx.provider, k8sProvider); + const ingressPort = k8sProvider.config.ingressHttpPort; + return `http://${hostname}:${ingressPort}`; +} +function getInternalServiceUrl(ctx, service) { + return __awaiter(this, void 0, void 0, function* () { + return url_1.resolve(yield getInternalGatewayUrl(ctx), getServicePath(service)); + }); +} +function getOpenfaasNamespace(ctx, k8sProvider, skipCreate) { + return __awaiter(this, void 0, void 0, function* () { + return namespace_1.getNamespace({ ctx, provider: k8sProvider, skipCreate, suffix: "openfaas" }); + }); +} +function getOpenFaasGarden(ctx) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: figure out good way to retrieve namespace from kubernetes plugin through an exposed interface + // (maybe allow plugins to expose arbitrary data on the Provider object?) + const k8sProvider = getK8sProvider(ctx); + const namespace = yield getOpenfaasNamespace(ctx, k8sProvider, true); + const functionNamespace = yield namespace_1.getAppNamespace(ctx, k8sProvider); + const hostname = getExternalGatewayHostname(ctx.provider, k8sProvider); + // TODO: allow passing variables/parameters here to be parsed as part of the garden.yml project config + // (this would allow us to use a garden.yml for the project config, instead of speccing it here) + return garden_1.Garden.factory(systemProjectPath, { + env: "default", + config: { + version: "0", + dirname: "system", + path: systemProjectPath, + project: { + name: `${ctx.projectName}-openfaas`, + environmentDefaults: { + providers: [], + variables: {}, + }, + defaultEnvironment: "default", + environments: [ + { + name: "default", + providers: [ + Object.assign({}, k8sProvider.config, { namespace, + // TODO: this is clumsy, we should find a better way to configure this + _system: system_1.systemSymbol }), + ], + variables: { + "function-namespace": functionNamespace, + "gateway-hostname": hostname, + }, + }, + ], + }, + }, + }); + }); +} +exports.getOpenFaasGarden = getOpenFaasGarden; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvb3BlbmZhYXMvb3BlbmZhYXMudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILDJCQUEwQjtBQUMxQiwrQkFBMkI7QUFDM0IsNkJBQTJDO0FBQzNDLCtDQUE0QztBQUM1QyxpREFBa0U7QUFDbEUseUNBQXFDO0FBRXJDLGdEQUFzRTtBQWN0RSx3Q0FPbUI7QUFFbkIsdURBQXVFO0FBT3ZFLG1DQUFzQztBQUN0QywwQ0FBc0Q7QUFDdEQsK0JBQThCO0FBQzlCLDJDQUEyQztBQUMzQyxpREFBNEU7QUFDNUUsaURBQW1EO0FBR25ELGtEQUF5RTtBQUN6RSxpQ0FBaUM7QUFFakMsTUFBTSxpQkFBaUIsR0FBRyxXQUFJLENBQUMsc0JBQVUsRUFBRSxVQUFVLEVBQUUsUUFBUSxDQUFDLENBQUE7QUFDbkQsUUFBQSxhQUFhLEdBQUcsV0FBVyxDQUFBO0FBQzNCLFFBQUEsaUJBQWlCLEdBQUcseUJBQXlCLENBQUE7QUFRN0MsUUFBQSx3QkFBd0IsR0FBRyxpQ0FBdUI7S0FDNUQsSUFBSSxDQUFDO0lBQ0osWUFBWSxFQUFFLGlCQUFRLENBQUMsR0FBRyxDQUFDLE1BQU0sRUFBRSxDQUFDO1NBQ2pDLFdBQVcsQ0FBQywyRUFBMkUsQ0FBQztJQUMzRixPQUFPLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNsQixPQUFPLENBQUMsR0FBRyxDQUFDO1NBQ1osR0FBRyxDQUFPLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRyxDQUFDO1NBQ2xDLFdBQVcsQ0FBQyw4RUFBOEUsQ0FBQztJQUM5RixLQUFLLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNoQixXQUFXLENBQUMsc0ZBQXNGLENBQUM7SUFDdEcsSUFBSSxFQUFFLEdBQUcsQ0FBQyxNQUFNLEVBQUU7U0FDZixRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsK0RBQStELENBQUM7Q0FDaEYsQ0FBQztLQUNELE9BQU8sQ0FBQyxLQUFLLENBQUM7S0FD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QUFDLENBQUE7UUFDcEUsTUFBTSxpQkFBaUIsR0FBRyxNQUFNLDJCQUFlLENBQUMsR0FBRyxFQUFFLFdBQVcsQ0FBQyxDQUFBO1FBRWpFLE1BQU0sUUFBUSxHQUFHLDBCQUEwQixDQUFDLEdBQUcsQ0FBQyxRQUFRLEVBQUUsV0FBVyxDQUFDLENBQUE7UUFFdEUsc0dBQXNHO1FBQ3RHLGdHQUFnRztRQUNoRyxPQUFPLGVBQU0sQ0FBQyxPQUFPLENBQUMsaUJBQWlCLEVBQUU7WUFDdkMsR0FBRyxFQUFFLFNBQVM7WUFDZCxNQUFNLEVBQUU7Z0JBQ04sT0FBTyxFQUFFLEdBQUc7Z0JBQ1osT0FBTyxFQUFFLFFBQVE7Z0JBQ2pCLElBQUksRUFBRSxpQkFBaUI7Z0JBQ3ZCLE9BQU8sRUFBRTtvQkFDUCxJQUFJLEVBQUUsR0FBRyxHQUFHLENBQUMsV0FBVyxXQUFXO29CQUNuQyxtQkFBbUIsRUFBRTt3QkFDbkIsU0FBUyxFQUFFLEVBQUU7d0JBQ2IsU0FBUyxFQUFFLEVBQUU7cUJBQ2Q7b0JBQ0Qsa0JBQWtCLEVBQUUsU0FBUztvQkFDN0IsWUFBWSxFQUFFO3dCQUNaOzRCQUNFLElBQUksRUFBRSxTQUFTOzRCQUNmLFNBQVMsRUFBRTtrREFFSixXQUFXLENBQUMsTUFBTSxJQUNyQixTQUFTO29DQUNULHNFQUFzRTtvQ0FDdEUsT0FBTyxFQUFFLHFCQUFZOzZCQUV4Qjs0QkFDRCxTQUFTLEVBQUU7Z0NBQ1Qsb0JBQW9CLEVBQUUsaUJBQWlCO2dDQUN2QyxrQkFBa0IsRUFBRSxRQUFROzZCQUM3Qjt5QkFDRjtxQkFDRjtpQkFDRjthQUNGO1NBQ0YsQ0FBQyxDQUFBO0lBQ0osQ0FBQztDQUFBO0FBNUNELDhDQTRDQyIsImZpbGUiOiJwbHVnaW5zL29wZW5mYWFzL29wZW5mYWFzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyByZXNvbHZlIGFzIHVybFJlc29sdmUgfSBmcm9tIFwidXJsXCJcbmltcG9ydCB7IFNUQVRJQ19ESVIgfSBmcm9tIFwiLi4vLi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IFBsdWdpbkVycm9yLCBDb25maWd1cmF0aW9uRXJyb3IgfSBmcm9tIFwiLi4vLi4vZXhjZXB0aW9uc1wiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vLi4vZ2FyZGVuXCJcbmltcG9ydCB7IFBsdWdpbkNvbnRleHQgfSBmcm9tIFwiLi4vLi4vcGx1Z2luLWNvbnRleHRcIlxuaW1wb3J0IHsgam9pQXJyYXksIHZhbGlkYXRlLCBQcmltaXRpdmVNYXAgfSBmcm9tIFwiLi4vLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7IFZhbGlkYXRlTW9kdWxlUmVzdWx0IH0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9vdXRwdXRzXCJcbmltcG9ydCB7XG4gIFByZXBhcmVFbnZpcm9ubWVudFBhcmFtcyxcbiAgR2V0RW52aXJvbm1lbnRTdGF0dXNQYXJhbXMsXG4gIFZhbGlkYXRlTW9kdWxlUGFyYW1zLFxuICBEZWxldGVTZXJ2aWNlUGFyYW1zLFxufSBmcm9tIFwiLi4vLi4vdHlwZXMvcGx1Z2luL3BhcmFtc1wiXG5pbXBvcnQge1xuICBTZXJ2aWNlU3RhdHVzLFxuICBTZXJ2aWNlSW5ncmVzcyxcbiAgU2VydmljZSxcbn0gZnJvbSBcIi4uLy4uL3R5cGVzL3NlcnZpY2VcIlxuaW1wb3J0IHtcbiAgYnVpbGRHZW5lcmljTW9kdWxlLFxuICBHZW5lcmljTW9kdWxlU3BlYyxcbiAgZ2VuZXJpY01vZHVsZVNwZWNTY2hlbWEsXG4gIEdlbmVyaWNUZXN0U3BlYyxcbiAgdGVzdEdlbmVyaWNNb2R1bGUsXG4gIGdldEdlbmVyaWNNb2R1bGVCdWlsZFN0YXR1cyxcbn0gZnJvbSBcIi4uL2dlbmVyaWNcIlxuaW1wb3J0IHsgS3ViZXJuZXRlc1Byb3ZpZGVyIH0gZnJvbSBcIi4uL2t1YmVybmV0ZXMva3ViZXJuZXRlc1wiXG5pbXBvcnQgeyBnZXROYW1lc3BhY2UsIGdldEFwcE5hbWVzcGFjZSB9IGZyb20gXCIuLi9rdWJlcm5ldGVzL25hbWVzcGFjZVwiXG5pbXBvcnQge1xuICBEZXBsb3lTZXJ2aWNlUGFyYW1zLFxuICBHZXRTZXJ2aWNlU3RhdHVzUGFyYW1zLFxuICBCdWlsZE1vZHVsZVBhcmFtcyxcbiAgR2V0U2VydmljZU91dHB1dHNQYXJhbXMsXG59IGZyb20gXCIuLi8uLi90eXBlcy9wbHVnaW4vcGFyYW1zXCJcbmltcG9ydCB7IGV2ZXJ5LCB2YWx1ZXMgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7IGR1bXBZYW1sLCBmaW5kQnlOYW1lIH0gZnJvbSBcIi4uLy4uL3V0aWwvdXRpbFwiXG5pbXBvcnQgKiBhcyBleGVjYSBmcm9tIFwiZXhlY2FcIlxuaW1wb3J0IHsgS3ViZUFwaSB9IGZyb20gXCIuLi9rdWJlcm5ldGVzL2FwaVwiXG5pbXBvcnQgeyB3YWl0Rm9yT2JqZWN0cywgY2hlY2tEZXBsb3ltZW50U3RhdHVzIH0gZnJvbSBcIi4uL2t1YmVybmV0ZXMvc3RhdHVzXCJcbmltcG9ydCB7IHN5c3RlbVN5bWJvbCB9IGZyb20gXCIuLi9rdWJlcm5ldGVzL3N5c3RlbVwiXG5pbXBvcnQgeyBCYXNlU2VydmljZVNwZWMgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3NlcnZpY2VcIlxuaW1wb3J0IHsgR2FyZGVuUGx1Z2luIH0gZnJvbSBcIi4uLy4uL3R5cGVzL3BsdWdpbi9wbHVnaW5cIlxuaW1wb3J0IHsgUHJvdmlkZXIsIHByb3ZpZGVyQ29uZmlnQmFzZVNjaGVtYSB9IGZyb20gXCIuLi8uLi9jb25maWcvcHJvamVjdFwiXG5pbXBvcnQgZGVkZW50ID0gcmVxdWlyZShcImRlZGVudFwiKVxuXG5jb25zdCBzeXN0ZW1Qcm9qZWN0UGF0aCA9IGpvaW4oU1RBVElDX0RJUiwgXCJvcGVuZmFhc1wiLCBcInN5c3RlbVwiKVxuZXhwb3J0IGNvbnN0IHN0YWNrRmlsZW5hbWUgPSBcInN0YWNrLnltbFwiXG5leHBvcnQgY29uc3QgRkFBU19DTElfSU1BR0VfSUQgPSBcIm9wZW5mYWFzL2ZhYXMtY2xpOjAuNy4zXCJcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuRmFhc01vZHVsZVNwZWMgZXh0ZW5kcyBHZW5lcmljTW9kdWxlU3BlYyB7XG4gIGhhbmRsZXI6IHN0cmluZ1xuICBpbWFnZTogc3RyaW5nXG4gIGxhbmc6IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3Qgb3BlbmZhYXNNb2R1bGVTcGVjU2NoYW1lID0gZ2VuZXJpY01vZHVsZVNwZWNTY2hlbWFcbiAgLmtleXMoe1xuICAgIGRlcGVuZGVuY2llczogam9pQXJyYXkoSm9pLnN0cmluZygpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWVzIG9mIHNlcnZpY2VzL2Z1bmN0aW9ucyB0aGF0IHRoaXMgZnVuY3Rpb24gZGVwZW5kcyBvbiBhdCBydW50aW1lLlwiKSxcbiAgICBoYW5kbGVyOiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZWZhdWx0KFwiLlwiKVxuICAgICAgLnVyaSgoPGFueT57IHJlbGF0aXZlT25seTogdHJ1ZSB9KSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNwZWNpZnkgd2hpY2ggZGlyZWN0b3J5IHVuZGVyIHRoZSBtb2R1bGUgY29udGFpbnMgdGhlIGhhbmRsZXIgZmlsZS9mdW5jdGlvbi5cIiksXG4gICAgaW1hZ2U6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGltYWdlIG5hbWUgdG8gdXNlIGZvciB0aGUgYnVpbHQgT3BlbkZhYVMgY29udGFpbmVyIChkZWZhdWx0cyB0byB0aGUgbW9kdWxlIG5hbWUpXCIpLFxuICAgIGxhbmc6IEpvaS5zdHJpbmcoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBPcGVuRmFhUyBsYW5ndWFnZSB0ZW1wbGF0ZSB0byB1c2UgdG8gYnVpbGQgdGhpcyBmdW5jdGlvbi5cIiksXG4gIH0pXG4gIC51bmtub3duKGZhbHNlKVxuICAuZGVzY3JpcHRpb24oXCJUaGUgbW9kdWxlIHNwZWNpZmljYXRpb24gZm9yIGFuIE9wZW5GYWFTIG1vZHVsZS5cIilcblxuZXhwb3J0IGludGVyZmFjZSBPcGVuRmFhc01vZHVsZSBleHRlbmRzIE1vZHVsZTxPcGVuRmFhc01vZHVsZVNwZWMsIEJhc2VTZXJ2aWNlU3BlYywgR2VuZXJpY1Rlc3RTcGVjPiB7IH1cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkZhYXNTZXJ2aWNlIGV4dGVuZHMgU2VydmljZTxPcGVuRmFhc01vZHVsZT4geyB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgT3BlbkZhYXNDb25maWcgZXh0ZW5kcyBQcm92aWRlciB7XG4gIGhvc3RuYW1lOiBzdHJpbmdcbn1cblxuY29uc3QgY29uZmlnU2NoZW1hID0gcHJvdmlkZXJDb25maWdCYXNlU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBob3N0bmFtZTogSm9pLnN0cmluZygpXG4gICAgICAuaG9zdG5hbWUoKVxuICAgICAgLmRlc2NyaXB0aW9uKGRlZGVudGBcbiAgICAgICAgVGhlIGhvc3RuYW1lIHRvIGNvbmZpZ3VyZSBmb3IgdGhlIGZ1bmN0aW9uIGdhdGV3YXkuXG4gICAgICAgIERlZmF1bHRzIHRvIHRoZSBkZWZhdWx0IGhvc3RuYW1lIG9mIHRoZSBjb25maWd1cmVkIEt1YmVybmV0ZXMgcHJvdmlkZXIuXG5cbiAgICAgICAgSW1wb3J0YW50OiBJZiB5b3UgaGF2ZSBvdGhlciB0eXBlcyBvZiBzZXJ2aWNlcywgdGhpcyBzaG91bGQgYmUgZGlmZmVyZW50IGZyb20gdGhlaXIgaW5ncmVzcyBob3N0bmFtZXMsXG4gICAgICAgIG9yIHRoZSBvdGhlciBzZXJ2aWNlcyBzaG91bGQgbm90IGV4cG9zZSBwYXRocyB1bmRlciAvZnVuY3Rpb24gYW5kIC9zeXN0ZW0gdG8gYXZvaWQgcm91dGluZyBjb25mbGljdHMuYCxcbiAgICAgIClcbiAgICAgIC5leGFtcGxlKFwiZnVuY3Rpb25zLm15ZG9tYWluLmNvbVwiKSxcbiAgfSlcblxudHlwZSBPcGVuRmFhc1Byb3ZpZGVyID0gUHJvdmlkZXI8T3BlbkZhYXNDb25maWc+XG5cbmV4cG9ydCBmdW5jdGlvbiBnYXJkZW5QbHVnaW4oeyBjb25maWcgfTogeyBjb25maWc6IE9wZW5GYWFzQ29uZmlnIH0pOiBHYXJkZW5QbHVnaW4ge1xuICBjb25maWcgPSB2YWxpZGF0ZShjb25maWcsIGNvbmZpZ1NjaGVtYSwgeyBjb250ZXh0OiBcIk9wZW5GYWFTIHByb3ZpZGVyIGNvbmZpZ1wiIH0pXG5cbiAgcmV0dXJuIHtcbiAgICBtb2R1bGVzOiBbam9pbihTVEFUSUNfRElSLCBcIm9wZW5mYWFzXCIsIFwiYnVpbGRlclwiKV0sXG4gICAgYWN0aW9uczoge1xuICAgICAgYXN5bmMgZ2V0RW52aXJvbm1lbnRTdGF0dXMoeyBjdHggfTogR2V0RW52aXJvbm1lbnRTdGF0dXNQYXJhbXMpIHtcbiAgICAgICAgY29uc3Qgb2ZHYXJkZW4gPSBhd2FpdCBnZXRPcGVuRmFhc0dhcmRlbihjdHgpXG4gICAgICAgIGNvbnN0IHN0YXR1cyA9IGF3YWl0IG9mR2FyZGVuLmFjdGlvbnMuZ2V0U3RhdHVzKClcbiAgICAgICAgY29uc3QgZW52UmVhZHkgPSBldmVyeSh2YWx1ZXMoc3RhdHVzLnByb3ZpZGVycykubWFwKHMgPT4gcy5yZWFkeSkpXG4gICAgICAgIGNvbnN0IHNlcnZpY2VzUmVhZHkgPSBldmVyeSh2YWx1ZXMoc3RhdHVzLnNlcnZpY2VzKS5tYXAocyA9PiBzLnN0YXRlID09PSBcInJlYWR5XCIpKVxuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgcmVhZHk6IGVudlJlYWR5ICYmIHNlcnZpY2VzUmVhZHksXG4gICAgICAgICAgZGV0YWlsOiBzdGF0dXMsXG4gICAgICAgIH1cbiAgICAgIH0sXG5cbiAgICAgIGFzeW5jIHByZXBhcmVFbnZpcm9ubWVudCh7IGN0eCwgZm9yY2UgfTogUHJlcGFyZUVudmlyb25tZW50UGFyYW1zKSB7XG4gICAgICAgIC8vIFRPRE86IHJlZmFjdG9yIHRvIGRlZHVwZSBzaW1pbGFyIGNvZGUgaW4gbG9jYWwta3ViZXJuZXRlc1xuICAgICAgICBjb25zdCBvZkdhcmRlbiA9IGF3YWl0IGdldE9wZW5GYWFzR2FyZGVuKGN0eClcblxuICAgICAgICBhd2FpdCBvZkdhcmRlbi5hY3Rpb25zLnByZXBhcmVFbnZpcm9ubWVudCh7IGZvcmNlIH0pXG5cbiAgICAgICAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IG9mR2FyZGVuLmFjdGlvbnMuZGVwbG95U2VydmljZXMoe30pXG4gICAgICAgIGNvbnN0IGZhaWxlZCA9IHZhbHVlcyhyZXN1bHRzLnRhc2tSZXN1bHRzKS5maWx0ZXIociA9PiAhIXIuZXJyb3IpLmxlbmd0aFxuXG4gICAgICAgIGlmIChmYWlsZWQpIHtcbiAgICAgICAgICB0aHJvdyBuZXcgUGx1Z2luRXJyb3IoYG9wZW5mYWFzOiAke2ZhaWxlZH0gZXJyb3JzIG9jY3VycmVkIHdoZW4gY29uZmlndXJpbmcgZW52aXJvbm1lbnRgLCB7XG4gICAgICAgICAgICByZXN1bHRzLFxuICAgICAgICAgIH0pXG4gICAgICAgIH1cblxuICAgICAgICByZXR1cm4ge31cbiAgICAgIH0sXG5cbiAgICAgIGFzeW5jIGNsZWFudXBFbnZpcm9ubWVudCh7IGN0eCB9KSB7XG4gICAgICAgIGNvbnN0IG9mR2FyZGVuID0gYXdhaXQgZ2V0T3BlbkZhYXNHYXJkZW4oY3R4KVxuXG4gICAgICAgIHJldHVybiBvZkdhcmRlbi5hY3Rpb25zLmNsZWFudXBFbnZpcm9ubWVudCh7fSlcbiAgICAgIH0sXG4gICAgfSxcbiAgICBtb2R1bGVBY3Rpb25zOiB7XG4gICAgICBvcGVuZmFhczoge1xuICAgICAgICBhc3luYyB2YWxpZGF0ZSh7IG1vZHVsZUNvbmZpZyB9OiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxPcGVuRmFhc01vZHVsZT4pOiBQcm9taXNlPFZhbGlkYXRlTW9kdWxlUmVzdWx0PiB7XG4gICAgICAgICAgbW9kdWxlQ29uZmlnLnNwZWMgPSB2YWxpZGF0ZShcbiAgICAgICAgICAgIG1vZHVsZUNvbmZpZy5zcGVjLFxuICAgICAgICAgICAgb3BlbmZhYXNNb2R1bGVTcGVjU2NoYW1lLFxuICAgICAgICAgICAgeyBjb250ZXh0OiBgbW9kdWxlICR7bW9kdWxlQ29uZmlnLm5hbWV9YCB9LFxuICAgICAgICAgIClcblxuICAgICAgICAgIG1vZHVsZUNvbmZpZy5idWlsZC5jb21tYW5kID0gW1xuICAgICAgICAgICAgXCJmYWFzLWNsaVwiLFxuICAgICAgICAgICAgXCJidWlsZFwiLFxuICAgICAgICAgICAgXCItZlwiLCBzdGFja0ZpbGVuYW1lLFxuICAgICAgICAgIF1cblxuICAgICAgICAgIG1vZHVsZUNvbmZpZy5idWlsZC5kZXBlbmRlbmNpZXMucHVzaCh7XG4gICAgICAgICAgICBuYW1lOiBcImJ1aWxkZXJcIixcbiAgICAgICAgICAgIHBsdWdpbjogXCJvcGVuZmFhc1wiLFxuICAgICAgICAgICAgY29weTogW3tcbiAgICAgICAgICAgICAgc291cmNlOiBcIipcIixcbiAgICAgICAgICAgICAgdGFyZ2V0OiBcIi5cIixcbiAgICAgICAgICAgIH1dLFxuICAgICAgICAgIH0pXG5cbiAgICAgICAgICBtb2R1bGVDb25maWcuc2VydmljZUNvbmZpZ3MgPSBbe1xuICAgICAgICAgICAgZGVwZW5kZW5jaWVzOiBbXSxcbiAgICAgICAgICAgIG5hbWU6IG1vZHVsZUNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgb3V0cHV0czoge30sXG4gICAgICAgICAgICBzcGVjOiB7XG4gICAgICAgICAgICAgIG5hbWU6IG1vZHVsZUNvbmZpZy5uYW1lLFxuICAgICAgICAgICAgICBkZXBlbmRlbmNpZXM6IFtdLFxuICAgICAgICAgICAgICBvdXRwdXRzOiB7fSxcbiAgICAgICAgICAgIH0sXG4gICAgICAgICAgfV1cblxuICAgICAgICAgIG1vZHVsZUNvbmZpZy50ZXN0Q29uZmlncyA9IG1vZHVsZUNvbmZpZy5zcGVjLnRlc3RzLm1hcCh0ID0+ICh7XG4gICAgICAgICAgICBuYW1lOiB0Lm5hbWUsXG4gICAgICAgICAgICBkZXBlbmRlbmNpZXM6IHQuZGVwZW5kZW5jaWVzLFxuICAgICAgICAgICAgc3BlYzogdCxcbiAgICAgICAgICAgIHRpbWVvdXQ6IHQudGltZW91dCxcbiAgICAgICAgICB9KSlcblxuICAgICAgICAgIHJldHVybiBtb2R1bGVDb25maWdcbiAgICAgICAgfSxcblxuICAgICAgICBnZXRCdWlsZFN0YXR1czogZ2V0R2VuZXJpY01vZHVsZUJ1aWxkU3RhdHVzLFxuXG4gICAgICAgIGFzeW5jIGJ1aWxkKHBhcmFtczogQnVpbGRNb2R1bGVQYXJhbXM8T3BlbkZhYXNNb2R1bGU+KSB7XG4gICAgICAgICAgY29uc3QgeyBjdHgsIG1vZHVsZSB9ID0gcGFyYW1zXG5cbiAgICAgICAgICAvLyBwcmVwYXJlIHRoZSBzdGFjay55bWwgZmlsZSwgYmVmb3JlIGhhbmRpbmcgb2ZmIHRoZSBidWlsZCB0byB0aGUgZ2VuZXJpYyBoYW5kbGVyXG4gICAgICAgICAgYXdhaXQgd3JpdGVTdGFja0ZpbGUoY3R4LCBtb2R1bGUsIHt9KVxuXG4gICAgICAgICAgcmV0dXJuIGJ1aWxkR2VuZXJpY01vZHVsZShwYXJhbXMpXG4gICAgICAgIH0sXG5cbiAgICAgICAgLy8gVE9ETzogZGVzaWduIGFuZCBpbXBsZW1lbnQgYSBwcm9wZXIgdGVzdCBmbG93IGZvciBvcGVuZmFhcyBmdW5jdGlvbnNcbiAgICAgICAgdGVzdE1vZHVsZTogdGVzdEdlbmVyaWNNb2R1bGUsXG5cbiAgICAgICAgZ2V0U2VydmljZVN0YXR1cyxcblxuICAgICAgICBhc3luYyBnZXRTZXJ2aWNlT3V0cHV0cyh7IGN0eCwgc2VydmljZSB9OiBHZXRTZXJ2aWNlT3V0cHV0c1BhcmFtczxPcGVuRmFhc01vZHVsZT4pIHtcbiAgICAgICAgICByZXR1cm4ge1xuICAgICAgICAgICAgZW5kcG9pbnQ6IGF3YWl0IGdldEludGVybmFsU2VydmljZVVybChjdHgsIHNlcnZpY2UpLFxuICAgICAgICAgIH1cbiAgICAgICAgfSxcblxuICAgICAgICBhc3luYyBkZXBsb3lTZXJ2aWNlKHBhcmFtczogRGVwbG95U2VydmljZVBhcmFtczxPcGVuRmFhc01vZHVsZT4pOiBQcm9taXNlPFNlcnZpY2VTdGF0dXM+IHtcbiAgICAgICAgICBjb25zdCB7IGN0eCwgbW9kdWxlLCBzZXJ2aWNlLCBsb2dFbnRyeSwgcnVudGltZUNvbnRleHQgfSA9IHBhcmFtc1xuXG4gICAgICAgICAgLy8gd3JpdGUgdGhlIHN0YWNrIGZpbGUgYWdhaW4gd2l0aCBlbnZpcm9ubWVudCB2YXJpYWJsZXNcbiAgICAgICAgICBhd2FpdCB3cml0ZVN0YWNrRmlsZShjdHgsIG1vZHVsZSwgcnVudGltZUNvbnRleHQuZW52VmFycylcblxuICAgICAgICAgIC8vIHVzZSBmYWFzLWNsaSB0byBkbyB0aGUgZGVwbG95bWVudFxuICAgICAgICAgIGF3YWl0IGV4ZWNhKFwiZmFhcy1jbGlcIiwgW1wiZGVwbG95XCIsIFwiLWZcIiwgc3RhY2tGaWxlbmFtZV0sIHsgY3dkOiBtb2R1bGUuYnVpbGRQYXRoIH0pXG5cbiAgICAgICAgICAvLyB3YWl0IHVudGlsIGRlcGxveW1lbnQgaXMgcmVhZHlcbiAgICAgICAgICBjb25zdCBrOHNQcm92aWRlciA9IGdldEs4c1Byb3ZpZGVyKGN0eClcbiAgICAgICAgICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBrOHNQcm92aWRlcilcbiAgICAgICAgICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShrOHNQcm92aWRlcilcblxuICAgICAgICAgIGNvbnN0IGRlcGxveW1lbnQgPSAoYXdhaXQgYXBpLmFwcHMucmVhZE5hbWVzcGFjZWREZXBsb3ltZW50KHNlcnZpY2UubmFtZSwgbmFtZXNwYWNlKSkuYm9keVxuXG4gICAgICAgICAgYXdhaXQgd2FpdEZvck9iamVjdHMoeyBjdHgsIHByb3ZpZGVyOiBrOHNQcm92aWRlciwgc2VydmljZSwgbG9nRW50cnksIG9iamVjdHM6IFtkZXBsb3ltZW50XSB9KVxuXG4gICAgICAgICAgLy8gVE9ETzogYXZvaWQgZHVwbGljYXRlIHdvcmsgaGVyZVxuICAgICAgICAgIHJldHVybiBnZXRTZXJ2aWNlU3RhdHVzKHBhcmFtcylcbiAgICAgICAgfSxcblxuICAgICAgICBhc3luYyBkZWxldGVTZXJ2aWNlKHBhcmFtczogRGVsZXRlU2VydmljZVBhcmFtczxPcGVuRmFhc01vZHVsZT4pOiBQcm9taXNlPFNlcnZpY2VTdGF0dXM+IHtcbiAgICAgICAgICBjb25zdCB7IGN0eCwgbG9nRW50cnksIHNlcnZpY2UsIHJ1bnRpbWVDb250ZXh0IH0gPSBwYXJhbXNcbiAgICAgICAgICBsZXQgc3RhdHVzXG4gICAgICAgICAgbGV0IGZvdW5kID0gdHJ1ZVxuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHN0YXR1cyA9IGF3YWl0IGdldFNlcnZpY2VTdGF0dXMoe1xuICAgICAgICAgICAgICBjdHgsXG4gICAgICAgICAgICAgIHNlcnZpY2UsXG4gICAgICAgICAgICAgIHJ1bnRpbWVDb250ZXh0LFxuICAgICAgICAgICAgICBtb2R1bGU6IHNlcnZpY2UubW9kdWxlLFxuICAgICAgICAgICAgfSlcblxuICAgICAgICAgICAgZm91bmQgPSAhIXN0YXR1cy5zdGF0ZVxuXG4gICAgICAgICAgICBhd2FpdCBleGVjYShcImZhYXMtY2xpXCIsIFtcInJlbW92ZVwiLCBcIi1mXCIsIHN0YWNrRmlsZW5hbWVdLCB7IGN3ZDogc2VydmljZS5tb2R1bGUuYnVpbGRQYXRoIH0pXG5cbiAgICAgICAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgICAgICAgIGZvdW5kID0gZmFsc2VcbiAgICAgICAgICB9XG5cbiAgICAgICAgICBpZiAobG9nRW50cnkpIHtcbiAgICAgICAgICAgIGZvdW5kID8gbG9nRW50cnkuc2V0U3VjY2VzcyhcIlNlcnZpY2UgZGVsZXRlZFwiKSA6IGxvZ0VudHJ5LnNldFdhcm4oXCJTZXJ2aWNlIG5vdCBkZXBsb3llZFwiKVxuICAgICAgICAgIH1cblxuICAgICAgICAgIHJldHVybiBzdGF0dXNcbiAgICAgICAgfSxcbiAgICAgIH0sXG4gICAgfSxcbiAgfVxufVxuXG5hc3luYyBmdW5jdGlvbiB3cml0ZVN0YWNrRmlsZShcbiAgY3R4OiBQbHVnaW5Db250ZXh0LCBtb2R1bGU6IE9wZW5GYWFzTW9kdWxlLCBlbnZWYXJzOiBQcmltaXRpdmVNYXAsXG4pIHtcbiAgY29uc3QgaW1hZ2UgPSBnZXRJbWFnZU5hbWUobW9kdWxlKVxuXG4gIGNvbnN0IHN0YWNrUGF0aCA9IGpvaW4obW9kdWxlLmJ1aWxkUGF0aCwgc3RhY2tGaWxlbmFtZSlcblxuICByZXR1cm4gZHVtcFlhbWwoc3RhY2tQYXRoLCB7XG4gICAgcHJvdmlkZXI6IHtcbiAgICAgIG5hbWU6IFwiZmFhc1wiLFxuICAgICAgZ2F0ZXdheTogZ2V0RXh0ZXJuYWxHYXRld2F5VXJsKGN0eCksXG4gICAgfSxcbiAgICBmdW5jdGlvbnM6IHtcbiAgICAgIFttb2R1bGUubmFtZV06IHtcbiAgICAgICAgbGFuZzogbW9kdWxlLnNwZWMubGFuZyxcbiAgICAgICAgaGFuZGxlcjogbW9kdWxlLnNwZWMuaGFuZGxlcixcbiAgICAgICAgaW1hZ2UsXG4gICAgICAgIGVudmlyb25tZW50OiBlbnZWYXJzLFxuICAgICAgfSxcbiAgICB9LFxuICB9KVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRTZXJ2aWNlU3RhdHVzKHsgY3R4LCBzZXJ2aWNlIH06IEdldFNlcnZpY2VTdGF0dXNQYXJhbXM8T3BlbkZhYXNNb2R1bGU+KSB7XG4gIGNvbnN0IGs4c1Byb3ZpZGVyID0gZ2V0SzhzUHJvdmlkZXIoY3R4KVxuXG4gIGNvbnN0IGluZ3Jlc3NlczogU2VydmljZUluZ3Jlc3NbXSA9IFt7XG4gICAgaG9zdG5hbWU6IGdldEV4dGVybmFsR2F0ZXdheUhvc3RuYW1lKGN0eC5wcm92aWRlciwgazhzUHJvdmlkZXIpLFxuICAgIHBhdGg6IGdldFNlcnZpY2VQYXRoKHNlcnZpY2UpLFxuICAgIHBvcnQ6IGs4c1Byb3ZpZGVyLmNvbmZpZy5pbmdyZXNzSHR0cFBvcnQsXG4gICAgcHJvdG9jb2w6IFwiaHR0cFwiLFxuICB9XVxuXG4gIGNvbnN0IG5hbWVzcGFjZSA9IGF3YWl0IGdldEFwcE5hbWVzcGFjZShjdHgsIGs4c1Byb3ZpZGVyKVxuICBjb25zdCBhcGkgPSBuZXcgS3ViZUFwaShrOHNQcm92aWRlcilcblxuICBsZXQgZGVwbG95bWVudFxuXG4gIHRyeSB7XG4gICAgZGVwbG95bWVudCA9IChhd2FpdCBhcGkuYXBwcy5yZWFkTmFtZXNwYWNlZERlcGxveW1lbnQoc2VydmljZS5uYW1lLCBuYW1lc3BhY2UpKS5ib2R5XG4gIH0gY2F0Y2ggKGVycikge1xuICAgIGlmIChlcnIuY29kZSA9PT0gNDA0KSB7XG4gICAgICByZXR1cm4ge31cbiAgICB9IGVsc2Uge1xuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuICB9XG5cbiAgY29uc3QgY29udGFpbmVyOiBhbnkgPSBmaW5kQnlOYW1lKGRlcGxveW1lbnQuc3BlYy50ZW1wbGF0ZS5zcGVjLmNvbnRhaW5lcnMsIFwiaGVsbG8tZnVuY3Rpb25cIilcbiAgY29uc3QgdmVyc2lvbiA9IGZpbmRCeU5hbWU8YW55Pihjb250YWluZXIuZW52LCBcIkdBUkRFTl9WRVJTSU9OXCIpLnZhbHVlXG4gIGNvbnN0IHN0YXR1cyA9IGF3YWl0IGNoZWNrRGVwbG95bWVudFN0YXR1cyhhcGksIG5hbWVzcGFjZSwgZGVwbG95bWVudClcblxuICByZXR1cm4ge1xuICAgIHN0YXRlOiBzdGF0dXMuc3RhdGUsXG4gICAgdmVyc2lvbixcbiAgICBpbmdyZXNzZXMsXG4gIH1cbn1cblxuZnVuY3Rpb24gZ2V0SW1hZ2VOYW1lKG1vZHVsZTogT3BlbkZhYXNNb2R1bGUpIHtcbiAgcmV0dXJuIGAke21vZHVsZS5uYW1lIHx8IG1vZHVsZS5zcGVjLmltYWdlfToke21vZHVsZS52ZXJzaW9uLnZlcnNpb25TdHJpbmd9YFxufVxuXG4vLyBOT1RFOiB3ZSdyZSBjdXJyZW50bHkgbm90IHVzaW5nIHRoZSBDUkQvb3BlcmF0b3IsIGJ1dCBtaWdodCBjaGFuZ2UgdGhhdCBpbiB0aGUgZnV0dXJlXG4vL1xuLy8gYXN5bmMgZnVuY3Rpb24gY3JlYXRlRnVuY3Rpb25PYmplY3Qoc2VydmljZTogT3BlbkZhYXNTZXJ2aWNlLCBuYW1lc3BhY2U6IHN0cmluZyk6IFByb21pc2U8S3ViZXJuZXRlc09iamVjdD4ge1xuLy8gICBjb25zdCBpbWFnZSA9IGF3YWl0IGdldEltYWdlTmFtZShzZXJ2aWNlLm1vZHVsZSlcblxuLy8gICByZXR1cm4ge1xuLy8gICAgIGFwaVZlcnNpb246IFwib3BlbmZhYXMuY29tL3YxYWxwaGEyXCIsXG4vLyAgICAga2luZDogXCJGdW5jdGlvblwiLFxuLy8gICAgIG1ldGFkYXRhOiB7XG4vLyAgICAgICBuYW1lOiBzZXJ2aWNlLm5hbWUsXG4vLyAgICAgICBuYW1lc3BhY2UsXG4vLyAgICAgfSxcbi8vICAgICBzcGVjOiB7XG4vLyAgICAgICBuYW1lOiBzZXJ2aWNlLm5hbWUsXG4vLyAgICAgICBpbWFnZSxcbi8vICAgICAgIGxhYmVsczoge1xuLy8gICAgICAgICBcImNvbS5vcGVuZmFhcy5zY2FsZS5taW5cIjogXCIxXCIsXG4vLyAgICAgICAgIFwiY29tLm9wZW5mYWFzLnNjYWxlLm1heFwiOiBcIjVcIixcbi8vICAgICAgIH0sXG4vLyAgICAgICBlbnZpcm9ubWVudDoge1xuLy8gICAgICAgICB3cml0ZV9kZWJ1ZzogXCJ0cnVlXCIsXG4vLyAgICAgICB9LFxuLy8gICAgICAgbGltaXRzOiB7XG4vLyAgICAgICAgIGNwdTogREVGQVVMVF9DUFVfTElNSVQsXG4vLyAgICAgICAgIG1lbW9yeTogREVGQVVMVF9NRU1PUllfTElNSVQsXG4vLyAgICAgICB9LFxuLy8gICAgICAgcmVxdWVzdHM6IHtcbi8vICAgICAgICAgY3B1OiBERUZBVUxUX0NQVV9SRVFVRVNULFxuLy8gICAgICAgICBtZW1vcnk6IERFRkFVTFRfTUVNT1JZX1JFUVVFU1QsXG4vLyAgICAgICB9LFxuLy8gICAgIH0sXG4vLyAgIH1cbi8vIH1cblxuZnVuY3Rpb24gZ2V0SzhzUHJvdmlkZXIoY3R4OiBQbHVnaW5Db250ZXh0KTogS3ViZXJuZXRlc1Byb3ZpZGVyIHtcbiAgY29uc3QgcHJvdmlkZXIgPSBjdHgucHJvdmlkZXJzW1wibG9jYWwta3ViZXJuZXRlc1wiXSB8fCBjdHgucHJvdmlkZXJzLmt1YmVybmV0ZXNcblxuICBpZiAoIXByb3ZpZGVyKSB7XG4gICAgdGhyb3cgbmV3IENvbmZpZ3VyYXRpb25FcnJvcihgb3BlbmZhYXMgcmVxdWlyZXMgYSBrdWJlcm5ldGVzIChvciBsb2NhbC1rdWJlcm5ldGVzKSBwcm92aWRlciB0byBiZSBjb25maWd1cmVkYCwge1xuICAgICAgY29uZmlndXJlZFByb3ZpZGVyczogT2JqZWN0LmtleXMoY3R4LnByb3ZpZGVycyksXG4gICAgfSlcbiAgfVxuXG4gIHJldHVybiBwcm92aWRlclxufVxuXG5mdW5jdGlvbiBnZXRTZXJ2aWNlUGF0aChzZXJ2aWNlOiBPcGVuRmFhc1NlcnZpY2UpIHtcbiAgcmV0dXJuIGpvaW4oXCIvXCIsIFwiZnVuY3Rpb25cIiwgc2VydmljZS5uYW1lKVxufVxuXG5hc3luYyBmdW5jdGlvbiBnZXRJbnRlcm5hbEdhdGV3YXlVcmwoY3R4OiBQbHVnaW5Db250ZXh0KSB7XG4gIGNvbnN0IGs4c1Byb3ZpZGVyID0gZ2V0SzhzUHJvdmlkZXIoY3R4KVxuICBjb25zdCBuYW1lc3BhY2UgPSBhd2FpdCBnZXRPcGVuZmFhc05hbWVzcGFjZShjdHgsIGs4c1Byb3ZpZGVyLCB0cnVlKVxuICByZXR1cm4gYGh0dHA6Ly9nYXRld2F5LiR7bmFtZXNwYWNlfS5zdmMuY2x1c3Rlci5sb2NhbDo4MDgwYFxufVxuXG5mdW5jdGlvbiBnZXRFeHRlcm5hbEdhdGV3YXlIb3N0bmFtZShwcm92aWRlcjogT3BlbkZhYXNQcm92aWRlciwgazhzUHJvdmlkZXI6IEt1YmVybmV0ZXNQcm92aWRlcikge1xuICBjb25zdCBob3N0bmFtZSA9IHByb3ZpZGVyLmNvbmZpZy5ob3N0bmFtZSB8fCBrOHNQcm92aWRlci5jb25maWcuZGVmYXVsdEhvc3RuYW1lXG5cbiAgaWYgKCFob3N0bmFtZSkge1xuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXG4gICAgICBgb3BlbmZhYXM6IE11c3QgY29uZmlndXJlIGhvc3RuYW1lIGlmIG5vIGRlZmF1bHQgaG9zdG5hbWUgaXMgY29uZmlndXJlZCBvbiBLdWJlcm5ldGVzIHByb3ZpZGVyLmAsXG4gICAgICB7XG4gICAgICAgIGNvbmZpZzogcHJvdmlkZXIsXG4gICAgICB9LFxuICAgIClcbiAgfVxuXG4gIHJldHVybiBob3N0bmFtZVxufVxuXG5mdW5jdGlvbiBnZXRFeHRlcm5hbEdhdGV3YXlVcmwoY3R4OiBQbHVnaW5Db250ZXh0KSB7XG4gIGNvbnN0IGs4c1Byb3ZpZGVyID0gZ2V0SzhzUHJvdmlkZXIoY3R4KVxuICBjb25zdCBob3N0bmFtZSA9IGdldEV4dGVybmFsR2F0ZXdheUhvc3RuYW1lKGN0eC5wcm92aWRlciwgazhzUHJvdmlkZXIpXG4gIGNvbnN0IGluZ3Jlc3NQb3J0ID0gazhzUHJvdmlkZXIuY29uZmlnLmluZ3Jlc3NIdHRwUG9ydFxuICByZXR1cm4gYGh0dHA6Ly8ke2hvc3RuYW1lfToke2luZ3Jlc3NQb3J0fWBcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0SW50ZXJuYWxTZXJ2aWNlVXJsKGN0eDogUGx1Z2luQ29udGV4dCwgc2VydmljZTogT3BlbkZhYXNTZXJ2aWNlKSB7XG4gIHJldHVybiB1cmxSZXNvbHZlKGF3YWl0IGdldEludGVybmFsR2F0ZXdheVVybChjdHgpLCBnZXRTZXJ2aWNlUGF0aChzZXJ2aWNlKSlcbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0T3BlbmZhYXNOYW1lc3BhY2UoY3R4OiBQbHVnaW5Db250ZXh0LCBrOHNQcm92aWRlcjogS3ViZXJuZXRlc1Byb3ZpZGVyLCBza2lwQ3JlYXRlPzogYm9vbGVhbikge1xuICByZXR1cm4gZ2V0TmFtZXNwYWNlKHsgY3R4LCBwcm92aWRlcjogazhzUHJvdmlkZXIsIHNraXBDcmVhdGUsIHN1ZmZpeDogXCJvcGVuZmFhc1wiIH0pXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRPcGVuRmFhc0dhcmRlbihjdHg6IFBsdWdpbkNvbnRleHQpOiBQcm9taXNlPEdhcmRlbj4ge1xuICAvLyBUT0RPOiBmaWd1cmUgb3V0IGdvb2Qgd2F5IHRvIHJldHJpZXZlIG5hbWVzcGFjZSBmcm9tIGt1YmVybmV0ZXMgcGx1Z2luIHRocm91Z2ggYW4gZXhwb3NlZCBpbnRlcmZhY2VcbiAgLy8gKG1heWJlIGFsbG93IHBsdWdpbnMgdG8gZXhwb3NlIGFyYml0cmFyeSBkYXRhIG9uIHRoZSBQcm92aWRlciBvYmplY3Q/KVxuICBjb25zdCBrOHNQcm92aWRlciA9IGdldEs4c1Byb3ZpZGVyKGN0eClcbiAgY29uc3QgbmFtZXNwYWNlID0gYXdhaXQgZ2V0T3BlbmZhYXNOYW1lc3BhY2UoY3R4LCBrOHNQcm92aWRlciwgdHJ1ZSlcbiAgY29uc3QgZnVuY3Rpb25OYW1lc3BhY2UgPSBhd2FpdCBnZXRBcHBOYW1lc3BhY2UoY3R4LCBrOHNQcm92aWRlcilcblxuICBjb25zdCBob3N0bmFtZSA9IGdldEV4dGVybmFsR2F0ZXdheUhvc3RuYW1lKGN0eC5wcm92aWRlciwgazhzUHJvdmlkZXIpXG5cbiAgLy8gVE9ETzogYWxsb3cgcGFzc2luZyB2YXJpYWJsZXMvcGFyYW1ldGVycyBoZXJlIHRvIGJlIHBhcnNlZCBhcyBwYXJ0IG9mIHRoZSBnYXJkZW4ueW1sIHByb2plY3QgY29uZmlnXG4gIC8vICh0aGlzIHdvdWxkIGFsbG93IHVzIHRvIHVzZSBhIGdhcmRlbi55bWwgZm9yIHRoZSBwcm9qZWN0IGNvbmZpZywgaW5zdGVhZCBvZiBzcGVjY2luZyBpdCBoZXJlKVxuICByZXR1cm4gR2FyZGVuLmZhY3Rvcnkoc3lzdGVtUHJvamVjdFBhdGgsIHtcbiAgICBlbnY6IFwiZGVmYXVsdFwiLFxuICAgIGNvbmZpZzoge1xuICAgICAgdmVyc2lvbjogXCIwXCIsXG4gICAgICBkaXJuYW1lOiBcInN5c3RlbVwiLFxuICAgICAgcGF0aDogc3lzdGVtUHJvamVjdFBhdGgsXG4gICAgICBwcm9qZWN0OiB7XG4gICAgICAgIG5hbWU6IGAke2N0eC5wcm9qZWN0TmFtZX0tb3BlbmZhYXNgLFxuICAgICAgICBlbnZpcm9ubWVudERlZmF1bHRzOiB7XG4gICAgICAgICAgcHJvdmlkZXJzOiBbXSxcbiAgICAgICAgICB2YXJpYWJsZXM6IHt9LFxuICAgICAgICB9LFxuICAgICAgICBkZWZhdWx0RW52aXJvbm1lbnQ6IFwiZGVmYXVsdFwiLFxuICAgICAgICBlbnZpcm9ubWVudHM6IFtcbiAgICAgICAgICB7XG4gICAgICAgICAgICBuYW1lOiBcImRlZmF1bHRcIixcbiAgICAgICAgICAgIHByb3ZpZGVyczogW1xuICAgICAgICAgICAgICB7XG4gICAgICAgICAgICAgICAgLi4uazhzUHJvdmlkZXIuY29uZmlnLFxuICAgICAgICAgICAgICAgIG5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgICAvLyBUT0RPOiB0aGlzIGlzIGNsdW1zeSwgd2Ugc2hvdWxkIGZpbmQgYSBiZXR0ZXIgd2F5IHRvIGNvbmZpZ3VyZSB0aGlzXG4gICAgICAgICAgICAgICAgX3N5c3RlbTogc3lzdGVtU3ltYm9sLFxuICAgICAgICAgICAgICB9LFxuICAgICAgICAgICAgXSxcbiAgICAgICAgICAgIHZhcmlhYmxlczoge1xuICAgICAgICAgICAgICBcImZ1bmN0aW9uLW5hbWVzcGFjZVwiOiBmdW5jdGlvbk5hbWVzcGFjZSxcbiAgICAgICAgICAgICAgXCJnYXRld2F5LWhvc3RuYW1lXCI6IGhvc3RuYW1lLFxuICAgICAgICAgICAgfSxcbiAgICAgICAgICB9LFxuICAgICAgICBdLFxuICAgICAgfSxcbiAgICB9LFxuICB9KVxufVxuIl19 diff --git a/garden-service/build/plugins/plugins.d.ts b/garden-service/build/plugins/plugins.d.ts new file mode 100644 index 00000000000..cee71b1c584 --- /dev/null +++ b/garden-service/build/plugins/plugins.d.ts @@ -0,0 +1,15 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +export declare const builtinPlugins: import("_").Dictionary; +export declare const fixedPlugins: string[]; +//# sourceMappingURL=plugins.d.ts.map \ No newline at end of file diff --git a/garden-service/build/plugins/plugins.js b/garden-service/build/plugins/plugins.js new file mode 100644 index 00000000000..13c49132c4d --- /dev/null +++ b/garden-service/build/plugins/plugins.js @@ -0,0 +1,38 @@ +"use strict"; +Object.defineProperty(exports, "__esModule", { value: true }); +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +const lodash_1 = require("lodash"); +const generic = require("./generic"); +const container = require("./container"); +const gcf = require("./google/google-cloud-functions"); +const localGcf = require("./local/local-google-cloud-functions"); +const kubernetes = require("./kubernetes/kubernetes"); +const localKubernetes = require("./kubernetes/local"); +const npmPackage = require("./npm-package"); +const gae = require("./google/google-app-engine"); +const openfaas = require("./openfaas/openfaas"); +// These plugins are always registered +exports.builtinPlugins = lodash_1.mapValues({ + generic, + container, + "google-cloud-functions": gcf, + "local-google-cloud-functions": localGcf, + kubernetes, + "local-kubernetes": localKubernetes, + "npm-package": npmPackage, + "google-app-engine": gae, + openfaas, +}, (m => m.gardenPlugin)); +// These plugins are always loaded +exports.fixedPlugins = [ + "generic", + "container", +]; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInBsdWdpbnMvcGx1Z2lucy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOztBQUFBOzs7Ozs7R0FNRztBQUNILG1DQUFrQztBQUVsQyxNQUFNLE9BQU8sR0FBRyxPQUFPLENBQUMsV0FBVyxDQUFDLENBQUE7QUFDcEMsTUFBTSxTQUFTLEdBQUcsT0FBTyxDQUFDLGFBQWEsQ0FBQyxDQUFBO0FBQ3hDLE1BQU0sR0FBRyxHQUFHLE9BQU8sQ0FBQyxpQ0FBaUMsQ0FBQyxDQUFBO0FBQ3RELE1BQU0sUUFBUSxHQUFHLE9BQU8sQ0FBQyxzQ0FBc0MsQ0FBQyxDQUFBO0FBQ2hFLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyx5QkFBeUIsQ0FBQyxDQUFBO0FBQ3JELE1BQU0sZUFBZSxHQUFHLE9BQU8sQ0FBQyxvQkFBb0IsQ0FBQyxDQUFBO0FBQ3JELE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQTtBQUMzQyxNQUFNLEdBQUcsR0FBRyxPQUFPLENBQUMsNEJBQTRCLENBQUMsQ0FBQTtBQUNqRCxNQUFNLFFBQVEsR0FBRyxPQUFPLENBQUMscUJBQXFCLENBQUMsQ0FBQTtBQUUvQyxzQ0FBc0M7QUFDekIsUUFBQSxjQUFjLEdBQUcsa0JBQVMsQ0FBQztJQUN0QyxPQUFPO0lBQ1AsU0FBUztJQUNULHdCQUF3QixFQUFFLEdBQUc7SUFDN0IsOEJBQThCLEVBQUUsUUFBUTtJQUN4QyxVQUFVO0lBQ1Ysa0JBQWtCLEVBQUUsZUFBZTtJQUNuQyxhQUFhLEVBQUUsVUFBVTtJQUN6QixtQkFBbUIsRUFBRSxHQUFHO0lBQ3hCLFFBQVE7Q0FDVCxFQUFFLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsWUFBWSxDQUFDLENBQUMsQ0FBQTtBQUV6QixrQ0FBa0M7QUFDckIsUUFBQSxZQUFZLEdBQUc7SUFDMUIsU0FBUztJQUNULFdBQVc7Q0FDWixDQUFBIiwiZmlsZSI6InBsdWdpbnMvcGx1Z2lucy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuaW1wb3J0IHsgbWFwVmFsdWVzIH0gZnJvbSBcImxvZGFzaFwiXG5cbmNvbnN0IGdlbmVyaWMgPSByZXF1aXJlKFwiLi9nZW5lcmljXCIpXG5jb25zdCBjb250YWluZXIgPSByZXF1aXJlKFwiLi9jb250YWluZXJcIilcbmNvbnN0IGdjZiA9IHJlcXVpcmUoXCIuL2dvb2dsZS9nb29nbGUtY2xvdWQtZnVuY3Rpb25zXCIpXG5jb25zdCBsb2NhbEdjZiA9IHJlcXVpcmUoXCIuL2xvY2FsL2xvY2FsLWdvb2dsZS1jbG91ZC1mdW5jdGlvbnNcIilcbmNvbnN0IGt1YmVybmV0ZXMgPSByZXF1aXJlKFwiLi9rdWJlcm5ldGVzL2t1YmVybmV0ZXNcIilcbmNvbnN0IGxvY2FsS3ViZXJuZXRlcyA9IHJlcXVpcmUoXCIuL2t1YmVybmV0ZXMvbG9jYWxcIilcbmNvbnN0IG5wbVBhY2thZ2UgPSByZXF1aXJlKFwiLi9ucG0tcGFja2FnZVwiKVxuY29uc3QgZ2FlID0gcmVxdWlyZShcIi4vZ29vZ2xlL2dvb2dsZS1hcHAtZW5naW5lXCIpXG5jb25zdCBvcGVuZmFhcyA9IHJlcXVpcmUoXCIuL29wZW5mYWFzL29wZW5mYWFzXCIpXG5cbi8vIFRoZXNlIHBsdWdpbnMgYXJlIGFsd2F5cyByZWdpc3RlcmVkXG5leHBvcnQgY29uc3QgYnVpbHRpblBsdWdpbnMgPSBtYXBWYWx1ZXMoe1xuICBnZW5lcmljLFxuICBjb250YWluZXIsXG4gIFwiZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uc1wiOiBnY2YsXG4gIFwibG9jYWwtZ29vZ2xlLWNsb3VkLWZ1bmN0aW9uc1wiOiBsb2NhbEdjZixcbiAga3ViZXJuZXRlcyxcbiAgXCJsb2NhbC1rdWJlcm5ldGVzXCI6IGxvY2FsS3ViZXJuZXRlcyxcbiAgXCJucG0tcGFja2FnZVwiOiBucG1QYWNrYWdlLFxuICBcImdvb2dsZS1hcHAtZW5naW5lXCI6IGdhZSxcbiAgb3BlbmZhYXMsXG59LCAobSA9PiBtLmdhcmRlblBsdWdpbikpXG5cbi8vIFRoZXNlIHBsdWdpbnMgYXJlIGFsd2F5cyBsb2FkZWRcbmV4cG9ydCBjb25zdCBmaXhlZFBsdWdpbnMgPSBbXG4gIFwiZ2VuZXJpY1wiLFxuICBcImNvbnRhaW5lclwiLFxuXVxuIl19 diff --git a/garden-service/build/process.d.ts b/garden-service/build/process.d.ts new file mode 100644 index 00000000000..fcdd8d1b3be --- /dev/null +++ b/garden-service/build/process.d.ts @@ -0,0 +1,26 @@ +import { Module } from "./types/module"; +import { Service } from "./types/service"; +import { Task } from "./tasks/base"; +import { TaskResults } from "./task-graph"; +import { Garden } from "./garden"; +export declare type ProcessHandler = (module: Module) => Promise; +interface ProcessParams { + garden: Garden; + watch: boolean; + handler: ProcessHandler; + changeHandler?: ProcessHandler; +} +export interface ProcessModulesParams extends ProcessParams { + modules: Module[]; +} +export interface ProcessServicesParams extends ProcessParams { + services: Service[]; +} +export interface ProcessResults { + taskResults: TaskResults; + restartRequired?: boolean; +} +export declare function processServices({ garden, services, watch, handler, changeHandler }: ProcessServicesParams): Promise; +export declare function processModules({ garden, modules, watch, handler, changeHandler }: ProcessModulesParams): Promise; +export {}; +//# sourceMappingURL=process.d.ts.map \ No newline at end of file diff --git a/garden-service/build/process.js b/garden-service/build/process.js new file mode 100644 index 00000000000..3581b0ff0f0 --- /dev/null +++ b/garden-service/build/process.js @@ -0,0 +1,83 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const watch_1 = require("./watch"); +const util_1 = require("./util/util"); +const ext_source_util_1 = require("./util/ext-source-util"); +function processServices({ garden, services, watch, handler, changeHandler }) { + return __awaiter(this, void 0, void 0, function* () { + const modules = Array.from(new Set(services.map(s => s.module))); + return processModules({ + modules, + garden, + watch, + handler, + changeHandler, + }); + }); +} +exports.processServices = processServices; +function processModules({ garden, modules, watch, handler, changeHandler }) { + return __awaiter(this, void 0, void 0, function* () { + for (const module of modules) { + const tasks = yield handler(module); + if (ext_source_util_1.isModuleLinked(module, garden)) { + garden.log.info(chalk_1.default.gray(`Reading module ${chalk_1.default.cyan(module.name)} from linked local path ${chalk_1.default.white(module.path)}`)); + } + yield Bluebird.map(tasks, t => garden.addTask(t)); + } + const results = yield garden.processTasks(); + if (!watch) { + return { + taskResults: results, + restartRequired: false, + }; + } + if (!changeHandler) { + changeHandler = handler; + } + const watcher = new watch_1.FSWatcher(garden); + const restartPromise = new Promise((resolve) => __awaiter(this, void 0, void 0, function* () { + yield watcher.watchModules(modules, (changedModule, configChanged) => __awaiter(this, void 0, void 0, function* () { + if (configChanged) { + garden.log.debug({ msg: `Config changed, reloading.` }); + resolve(); + return; + } + if (changedModule) { + garden.log.debug({ msg: `Files changed for module ${changedModule.name}` }); + yield Bluebird.map(changeHandler(changedModule), (task) => garden.addTask(task)); + } + yield garden.processTasks(); + })); + util_1.registerCleanupFunction("clearAutoReloadWatches", () => { + watcher.close(); + }); + })); + yield restartPromise; + watcher.close(); + return { + taskResults: {}, + restartRequired: true, + }; + }); +} +exports.processModules = processModules; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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OEJBQXVCLENBQUMsd0JBQXdCLEVBQUUsR0FBRyxFQUFFO2dCQUNyRCxPQUFPLENBQUMsS0FBSyxFQUFFLENBQUE7WUFDakIsQ0FBQyxDQUFDLENBQUE7UUFDSixDQUFDLENBQUEsQ0FBQyxDQUFBO1FBRUYsTUFBTSxjQUFjLENBQUE7UUFDcEIsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO1FBRWYsT0FBTztZQUNMLFdBQVcsRUFBRSxFQUFFO1lBQ2YsZUFBZSxFQUFFLElBQUk7U0FDdEIsQ0FBQTtJQUVILENBQUM7Q0FBQTtBQTNERCx3Q0EyREMiLCJmaWxlIjoicHJvY2Vzcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgQmx1ZWJpcmQgPSByZXF1aXJlKFwiYmx1ZWJpcmRcIilcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7IFNlcnZpY2UgfSBmcm9tIFwiLi90eXBlcy9zZXJ2aWNlXCJcbmltcG9ydCB7IFRhc2sgfSBmcm9tIFwiLi90YXNrcy9iYXNlXCJcbmltcG9ydCB7IFRhc2tSZXN1bHRzIH0gZnJvbSBcIi4vdGFzay1ncmFwaFwiXG5pbXBvcnQgeyBGU1dhdGNoZXIgfSBmcm9tIFwiLi93YXRjaFwiXG5pbXBvcnQgeyByZWdpc3RlckNsZWFudXBGdW5jdGlvbiB9IGZyb20gXCIuL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBpc01vZHVsZUxpbmtlZCB9IGZyb20gXCIuL3V0aWwvZXh0LXNvdXJjZS11dGlsXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuL2dhcmRlblwiXG5cbmV4cG9ydCB0eXBlIFByb2Nlc3NIYW5kbGVyID0gKG1vZHVsZTogTW9kdWxlKSA9PiBQcm9taXNlPFRhc2tbXT5cblxuaW50ZXJmYWNlIFByb2Nlc3NQYXJhbXMge1xuICBnYXJkZW46IEdhcmRlbixcbiAgd2F0Y2g6IGJvb2xlYW5cbiAgaGFuZGxlcjogUHJvY2Vzc0hhbmRsZXJcbiAgLy8gdXNlIHRoaXMgaWYgdGhlIGJlaGF2aW9yIHNob3VsZCBiZSBkaWZmZXJlbnQgb24gd2F0Y2hlciBjaGFuZ2VzIHRoYW4gb24gaW5pdGlhbCBwcm9jZXNzaW5nXG4gIGNoYW5nZUhhbmRsZXI/OiBQcm9jZXNzSGFuZGxlclxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFByb2Nlc3NNb2R1bGVzUGFyYW1zIGV4dGVuZHMgUHJvY2Vzc1BhcmFtcyB7XG4gIG1vZHVsZXM6IE1vZHVsZVtdXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJvY2Vzc1NlcnZpY2VzUGFyYW1zIGV4dGVuZHMgUHJvY2Vzc1BhcmFtcyB7XG4gIHNlcnZpY2VzOiBTZXJ2aWNlW11cbn1cblxuZXhwb3J0IGludGVyZmFjZSBQcm9jZXNzUmVzdWx0cyB7XG4gIHRhc2tSZXN1bHRzOiBUYXNrUmVzdWx0c1xuICByZXN0YXJ0UmVxdWlyZWQ/OiBib29sZWFuXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcm9jZXNzU2VydmljZXMoXG4gIHsgZ2FyZGVuLCBzZXJ2aWNlcywgd2F0Y2gsIGhhbmRsZXIsIGNoYW5nZUhhbmRsZXIgfTogUHJvY2Vzc1NlcnZpY2VzUGFyYW1zLFxuKTogUHJvbWlzZTxQcm9jZXNzUmVzdWx0cz4ge1xuXG4gIGNvbnN0IG1vZHVsZXMgPSBBcnJheS5mcm9tKG5ldyBTZXQoc2VydmljZXMubWFwKHMgPT4gcy5tb2R1bGUpKSlcblxuICByZXR1cm4gcHJvY2Vzc01vZHVsZXMoe1xuICAgIG1vZHVsZXMsXG4gICAgZ2FyZGVuLFxuICAgIHdhdGNoLFxuICAgIGhhbmRsZXIsXG4gICAgY2hhbmdlSGFuZGxlcixcbiAgfSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHByb2Nlc3NNb2R1bGVzKFxuICB7IGdhcmRlbiwgbW9kdWxlcywgd2F0Y2gsIGhhbmRsZXIsIGNoYW5nZUhhbmRsZXIgfTogUHJvY2Vzc01vZHVsZXNQYXJhbXMsXG4pOiBQcm9taXNlPFByb2Nlc3NSZXN1bHRzPiB7XG4gIGZvciAoY29uc3QgbW9kdWxlIG9mIG1vZHVsZXMpIHtcbiAgICBjb25zdCB0YXNrcyA9IGF3YWl0IGhhbmRsZXIobW9kdWxlKVxuICAgIGlmIChpc01vZHVsZUxpbmtlZChtb2R1bGUsIGdhcmRlbikpIHtcbiAgICAgIGdhcmRlbi5sb2cuaW5mbyhcbiAgICAgICAgY2hhbGsuZ3JheShgUmVhZGluZyBtb2R1bGUgJHtjaGFsay5jeWFuKG1vZHVsZS5uYW1lKX0gZnJvbSBsaW5rZWQgbG9jYWwgcGF0aCAke2NoYWxrLndoaXRlKG1vZHVsZS5wYXRoKX1gKSxcbiAgICAgIClcbiAgICB9XG4gICAgYXdhaXQgQmx1ZWJpcmQubWFwKHRhc2tzLCB0ID0+IGdhcmRlbi5hZGRUYXNrKHQpKVxuICB9XG5cbiAgY29uc3QgcmVzdWx0cyA9IGF3YWl0IGdhcmRlbi5wcm9jZXNzVGFza3MoKVxuXG4gIGlmICghd2F0Y2gpIHtcbiAgICByZXR1cm4ge1xuICAgICAgdGFza1Jlc3VsdHM6IHJlc3VsdHMsXG4gICAgICByZXN0YXJ0UmVxdWlyZWQ6IGZhbHNlLFxuICAgIH1cbiAgfVxuXG4gIGlmICghY2hhbmdlSGFuZGxlcikge1xuICAgIGNoYW5nZUhhbmRsZXIgPSBoYW5kbGVyXG4gIH1cblxuICBjb25zdCB3YXRjaGVyID0gbmV3IEZTV2F0Y2hlcihnYXJkZW4pXG5cbiAgY29uc3QgcmVzdGFydFByb21pc2UgPSBuZXcgUHJvbWlzZShhc3luYyAocmVzb2x2ZSkgPT4ge1xuICAgIGF3YWl0IHdhdGNoZXIud2F0Y2hNb2R1bGVzKG1vZHVsZXMsXG4gICAgICBhc3luYyAoY2hhbmdlZE1vZHVsZTogTW9kdWxlIHwgbnVsbCwgY29uZmlnQ2hhbmdlZDogYm9vbGVhbikgPT4ge1xuICAgICAgICBpZiAoY29uZmlnQ2hhbmdlZCkge1xuICAgICAgICAgIGdhcmRlbi5sb2cuZGVidWcoeyBtc2c6IGBDb25maWcgY2hhbmdlZCwgcmVsb2FkaW5nLmAgfSlcbiAgICAgICAgICByZXNvbHZlKClcbiAgICAgICAgICByZXR1cm5cbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChjaGFuZ2VkTW9kdWxlKSB7XG4gICAgICAgICAgZ2FyZGVuLmxvZy5kZWJ1Zyh7IG1zZzogYEZpbGVzIGNoYW5nZWQgZm9yIG1vZHVsZSAke2NoYW5nZWRNb2R1bGUubmFtZX1gIH0pXG5cbiAgICAgICAgICBhd2FpdCBCbHVlYmlyZC5tYXAoY2hhbmdlSGFuZGxlciEoY2hhbmdlZE1vZHVsZSksICh0YXNrKSA9PiBnYXJkZW4uYWRkVGFzayh0YXNrKSlcbiAgICAgICAgfVxuXG4gICAgICAgIGF3YWl0IGdhcmRlbi5wcm9jZXNzVGFza3MoKVxuICAgICAgfSlcblxuICAgIHJlZ2lzdGVyQ2xlYW51cEZ1bmN0aW9uKFwiY2xlYXJBdXRvUmVsb2FkV2F0Y2hlc1wiLCAoKSA9PiB7XG4gICAgICB3YXRjaGVyLmNsb3NlKClcbiAgICB9KVxuICB9KVxuXG4gIGF3YWl0IHJlc3RhcnRQcm9taXNlXG4gIHdhdGNoZXIuY2xvc2UoKVxuXG4gIHJldHVybiB7XG4gICAgdGFza1Jlc3VsdHM6IHt9LCAvLyBUT0RPOiBSZXR1cm4gbGF0ZXN0IHJlc3VsdHMgZm9yIGVhY2ggdGFzayBiYXNlS2V5IHByb2Nlc3NlZCBiZXR3ZWVuIHJlc3RhcnRzP1xuICAgIHJlc3RhcnRSZXF1aXJlZDogdHJ1ZSxcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/task-graph.d.ts b/garden-service/build/task-graph.d.ts new file mode 100644 index 00000000000..b0e123280c5 --- /dev/null +++ b/garden-service/build/task-graph.d.ts @@ -0,0 +1,41 @@ +import { Task } from "./tasks/base"; +import { Garden } from "./garden"; +export interface TaskResult { + type: string; + description: string; + output?: any; + dependencyResults?: TaskResults; + error?: Error; +} +export interface TaskResults { + [baseKey: string]: TaskResult; +} +export declare const DEFAULT_CONCURRENCY = 4; +export declare class TaskGraph { + private garden; + private concurrency; + private roots; + private index; + private inProgress; + private logEntryMap; + private resultCache; + private opQueue; + constructor(garden: Garden, concurrency?: number); + addTask(task: Task): Promise; + processTasks(): Promise; + private addTaskInternal; + private getNode; + private processTasksInternal; + private completeTask; + private getPredecessor; + private addDependencies; + private addDependants; + private inherit; + private remove; + private cancelDependants; + private logTask; + private logTaskComplete; + private initLogging; + private logTaskError; +} +//# sourceMappingURL=task-graph.d.ts.map \ No newline at end of file diff --git a/garden-service/build/task-graph.js b/garden-service/build/task-graph.js new file mode 100644 index 00000000000..b5bd0e5c840 --- /dev/null +++ b/garden-service/build/task-graph.js @@ -0,0 +1,378 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const PQueue = require("p-queue"); +const chalk_1 = require("chalk"); +const lodash_1 = require("lodash"); +const base_1 = require("./tasks/base"); +const exceptions_1 = require("./exceptions"); +class TaskGraphError extends Error { +} +exports.DEFAULT_CONCURRENCY = 4; +class TaskGraph { + constructor(garden, concurrency = exports.DEFAULT_CONCURRENCY) { + this.garden = garden; + this.concurrency = concurrency; + this.roots = new TaskNodeMap(); + this.index = new TaskNodeMap(); + this.inProgress = new TaskNodeMap(); + this.resultCache = new ResultCache(); + this.opQueue = new PQueue({ concurrency: 1 }); + this.logEntryMap = {}; + } + addTask(task) { + return __awaiter(this, void 0, void 0, function* () { + return this.opQueue.add(() => this.addTaskInternal(task)); + }); + } + processTasks() { + return __awaiter(this, void 0, void 0, function* () { + return this.opQueue.add(() => this.processTasksInternal()); + }); + } + addTaskInternal(task) { + return __awaiter(this, void 0, void 0, function* () { + const predecessor = this.getPredecessor(task); + let node = this.getNode(task); + if (predecessor) { + /* + predecessor is already in the graph, having the same baseKey as task, + but a different key (see the getPredecessor method below). + */ + if (this.inProgress.contains(predecessor)) { + this.index.addNode(node); + /* + We transition + [dependencies] > predecessor > [dependants] + to + [dependencies] > predecessor > node > [dependants] + */ + this.inherit(predecessor, node); + return; + } + else { + node = predecessor; // No need to add a new TaskNode. + } + } + this.index.addNode(node); + yield this.addDependencies(node); + if (node.getDependencies().length === 0) { + this.roots.addNode(node); + } + else { + yield this.addDependants(node); + } + }); + } + getNode(task) { + const existing = this.index.getNode(task); + return existing || new TaskNode(task); + } + /* + Process the graph until it's complete + */ + processTasksInternal() { + return __awaiter(this, void 0, void 0, function* () { + const _this = this; + const results = {}; + const loop = () => __awaiter(this, void 0, void 0, function* () { + if (_this.index.length === 0) { + // done! + this.logEntryMap.counter && this.logEntryMap.counter.setDone({ symbol: "info" }); + return; + } + const batch = _this.roots.getNodes() + .filter(n => !this.inProgress.contains(n)) + .slice(0, _this.concurrency - this.inProgress.length); + batch.forEach(n => this.inProgress.addNode(n)); + this.initLogging(); + return Bluebird.map(batch, (node) => __awaiter(this, void 0, void 0, function* () { + const task = node.task; + const type = node.getType(); + const baseKey = node.getBaseKey(); + const description = node.getDescription(); + let result; + try { + this.logTask(node); + this.logEntryMap.inProgress.setState(inProgressToStr(this.inProgress.getNodes())); + const dependencyBaseKeys = (yield task.getDependencies()) + .map(dep => dep.getBaseKey()); + const dependencyResults = lodash_1.merge(this.resultCache.pick(dependencyBaseKeys), lodash_1.pick(results, dependencyBaseKeys)); + try { + result = yield node.process(dependencyResults); + } + catch (error) { + result = { type, description, error }; + this.logTaskError(node, error); + this.cancelDependants(node); + } + finally { + results[baseKey] = result; + this.resultCache.put(baseKey, task.version.versionString, result); + } + } + finally { + this.completeTask(node, !result.error); + } + return loop(); + })); + }); + yield loop(); + return results; + }); + } + completeTask(node, success) { + if (node.getDependencies().length > 0) { + throw new TaskGraphError(`Task ${node.getKey()} still has unprocessed dependencies`); + } + for (let d of node.getDependants()) { + d.removeDependency(node); + if (d.getDependencies().length === 0) { + this.roots.addNode(d); + } + } + this.remove(node); + this.logTaskComplete(node, success); + } + getPredecessor(task) { + const key = task.getKey(); + const baseKey = task.getBaseKey(); + const predecessors = this.index.getNodes() + .filter(n => n.getBaseKey() === baseKey && n.getKey() !== key) + .reverse(); + return predecessors[0] || null; + } + addDependencies(node) { + return __awaiter(this, void 0, void 0, function* () { + const task = node.task; + for (const d of yield task.getDependencies()) { + if (!d.force && this.resultCache.get(d.getBaseKey(), d.version.versionString)) { + continue; + } + const dependency = this.getPredecessor(d) || this.getNode(d); + this.index.addNode(dependency); + node.addDependency(dependency); + } + }); + } + addDependants(node) { + return __awaiter(this, void 0, void 0, function* () { + const nodeDependencies = node.getDependencies(); + for (const d of nodeDependencies) { + const dependant = this.getPredecessor(d.task) || d; + yield this.addTaskInternal(dependant.task); + dependant.addDependant(node); + } + }); + } + inherit(oldNode, newNode) { + oldNode.getDependants().forEach(node => { + newNode.addDependant(node); + oldNode.removeDependant(node); + node.removeDependency(oldNode); + node.addDependency(newNode); + }); + newNode.addDependency(oldNode); + oldNode.addDependant(newNode); + } + // Should only be called when node is not a dependant for any task. + remove(node) { + this.roots.removeNode(node); + this.index.removeNode(node); + this.inProgress.removeNode(node); + } + // Recursively remove node's dependants, without removing node. + cancelDependants(node) { + const remover = (n) => { + for (const dependant of n.getDependants()) { + this.logTaskComplete(n, false); + remover(dependant); + } + this.remove(n); + }; + for (const dependant of node.getDependants()) { + node.removeDependant(dependant); + remover(dependant); + } + } + // Logging + logTask(node) { + const entry = this.garden.log.debug({ + section: "tasks", + msg: `Processing task ${taskStyle(node.getKey())}`, + status: "active", + }); + this.logEntryMap[node.getKey()] = entry; + } + logTaskComplete(node, success) { + const entry = this.logEntryMap[node.getKey()]; + if (entry) { + success ? entry.setSuccess() : entry.setError(); + } + this.logEntryMap.counter.setState(remainingTasksToStr(this.index.length)); + } + initLogging() { + if (!Object.keys(this.logEntryMap).length) { + const header = this.garden.log.debug("Processing tasks..."); + const counter = this.garden.log.debug({ + msg: remainingTasksToStr(this.index.length), + status: "active", + }); + const inProgress = this.garden.log.debug(inProgressToStr(this.inProgress.getNodes())); + this.logEntryMap = Object.assign({}, this.logEntryMap, { header, + counter, + inProgress }); + } + } + logTaskError(node, err) { + const divider = lodash_1.padEnd("", 80, "—"); + const error = exceptions_1.toGardenError(err); + const msg = `\nFailed ${node.getDescription()}. Here is the output:\n${divider}\n${error.message}\n${divider}\n`; + this.garden.log.error({ msg, error }); + } +} +exports.TaskGraph = TaskGraph; +function getIndexKey(task) { + const key = task.getKey(); + if (!task.type || !key || task.type.length === 0 || key.length === 0) { + throw new base_1.TaskDefinitionError("Tasks must define a type and a key"); + } + return key; +} +class TaskNodeMap { + constructor() { + this.index = new Map(); + this.length = 0; + } + getNode(task) { + const indexKey = getIndexKey(task); + const element = this.index.get(indexKey); + return element; + } + addNode(node) { + const indexKey = node.getKey(); + if (!this.index.get(indexKey)) { + this.index.set(indexKey, node); + this.length++; + } + } + removeNode(node) { + if (this.index.delete(node.getKey())) { + this.length--; + } + } + getNodes() { + return Array.from(this.index.values()); + } + contains(node) { + return this.index.has(node.getKey()); + } +} +class TaskNode { + constructor(task) { + this.task = task; + this.dependencies = new TaskNodeMap(); + this.dependants = new TaskNodeMap(); + } + addDependency(node) { + this.dependencies.addNode(node); + } + addDependant(node) { + this.dependants.addNode(node); + } + removeDependency(node) { + this.dependencies.removeNode(node); + } + removeDependant(node) { + this.dependants.removeNode(node); + } + getDependencies() { + return this.dependencies.getNodes(); + } + getDependants() { + return this.dependants.getNodes(); + } + getBaseKey() { + return this.task.getBaseKey(); + } + getKey() { + return getIndexKey(this.task); + } + getDescription() { + return this.task.getDescription(); + } + getType() { + return this.task.type; + } + // For testing/debugging purposes + inspect() { + return { + key: this.getKey(), + dependencies: this.getDependencies().map(d => d.getKey()), + dependants: this.getDependants().map(d => d.getKey()), + }; + } + process(dependencyResults) { + return __awaiter(this, void 0, void 0, function* () { + const output = yield this.task.process(dependencyResults); + return { + type: this.getType(), + description: this.getDescription(), + output, + dependencyResults, + }; + }); + } +} +class ResultCache { + constructor() { + this.cache = {}; + } + put(baseKey, versionString, result) { + this.cache[baseKey] = { result, versionString }; + } + get(baseKey, versionString) { + const r = this.cache[baseKey]; + return (r && r.versionString === versionString && !r.result.error) ? r.result : null; + } + getNewest(baseKey) { + const r = this.cache[baseKey]; + return (r && !r.result.error) ? r.result : null; + } + // Returns newest cached results, if any, for baseKeys + pick(baseKeys) { + const results = {}; + for (const baseKey of baseKeys) { + const cachedResult = this.getNewest(baseKey); + if (cachedResult) { + results[baseKey] = cachedResult; + } + } + return results; + } +} +const taskStyle = chalk_1.default.cyan.bold; +function inProgressToStr(nodes) { + return `Currently in progress [${nodes.map(n => taskStyle(n.getKey())).join(", ")}]`; +} +function remainingTasksToStr(num) { + const style = num === 0 ? chalk_1.default.green : chalk_1.default.yellow; + return `Remaining tasks ${style.bold(String(num))}`; +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQyxDQUFDLElBQUksQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUE7SUFDakQsQ0FBQztJQUVELHNEQUFzRDtJQUN0RCxJQUFJLENBQUMsUUFBa0I7UUFDckIsTUFBTSxPQUFPLEdBQWdCLEVBQUUsQ0FBQTtRQUUvQixLQUFLLE1BQU0sT0FBTyxJQUFJLFFBQVEsRUFBRTtZQUM5QixNQUFNLFlBQVksR0FBRyxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFBO1lBQzVDLElBQUksWUFBWSxFQUFFO2dCQUNoQixPQUFPLENBQUMsT0FBTyxDQUFDLEdBQUcsWUFBWSxDQUFBO2FBQ2hDO1NBQ0Y7UUFFRCxPQUFPLE9BQU8sQ0FBQTtJQUNoQixDQUFDO0NBRUY7QUFJRCxNQUFNLFNBQVMsR0FBRyxlQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQTtBQUVqQyxTQUFTLGVBQWUsQ0FBQyxLQUFLO0lBQzVCLE9BQU8sMEJBQTBCLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxTQUFTLENBQUMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQTtBQUN0RixDQUFDO0FBRUQsU0FBUyxtQkFBbUIsQ0FBQyxHQUFHO0lBQzlCLE1BQU0sS0FBSyxHQUFHLEdBQUcsS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGVBQUssQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLGVBQUssQ0FBQyxNQUFNLENBQUE7SUFDcEQsT0FBTyxtQkFBbUIsS0FBSyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLENBQUMsRUFBRSxDQUFBO0FBQ3JELENBQUMiLCJmaWxlIjoidGFzay1ncmFwaC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBCbHVlYmlyZCBmcm9tIFwiYmx1ZWJpcmRcIlxuaW1wb3J0ICogYXMgUFF1ZXVlIGZyb20gXCJwLXF1ZXVlXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgbWVyZ2UsIHBhZEVuZCwgcGljayB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgVGFzaywgVGFza0RlZmluaXRpb25FcnJvciB9IGZyb20gXCIuL3Rhc2tzL2Jhc2VcIlxuXG5pbXBvcnQgeyBMb2dFbnRyeSB9IGZyb20gXCIuL2xvZ2dlci9sb2ctZW50cnlcIlxuaW1wb3J0IHsgdG9HYXJkZW5FcnJvciB9IGZyb20gXCIuL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4vZ2FyZGVuXCJcblxuY2xhc3MgVGFza0dyYXBoRXJyb3IgZXh0ZW5kcyBFcnJvciB7IH1cblxuZXhwb3J0IGludGVyZmFjZSBUYXNrUmVzdWx0IHtcbiAgdHlwZTogc3RyaW5nXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmdcbiAgb3V0cHV0PzogYW55XG4gIGRlcGVuZGVuY3lSZXN1bHRzPzogVGFza1Jlc3VsdHNcbiAgZXJyb3I/OiBFcnJvclxufVxuXG4vKlxuICBXaGVuIG11bHRpcGxlIHRhc2tzIHdpdGggdGhlIHNhbWUgYmFzZUtleSBhcmUgY29tcGxldGVkIGR1cmluZyBhIGNhbGwgdG8gcHJvY2Vzc1Rhc2tzLFxuICB0aGUgcmVzdWx0IGZyb20gdGhlIGxhc3QgcHJvY2Vzc2VkIGlzIHVzZWQgKGhlbmNlIG9ubHkgb25lIGtleS12YWx1ZSBwYWlyIGhlcmUgcGVyIGJhc2VLZXkpLlxuICovXG5leHBvcnQgaW50ZXJmYWNlIFRhc2tSZXN1bHRzIHtcbiAgW2Jhc2VLZXk6IHN0cmluZ106IFRhc2tSZXN1bHRcbn1cblxuZXhwb3J0IGNvbnN0IERFRkFVTFRfQ09OQ1VSUkVOQ1kgPSA0XG5cbmV4cG9ydCBjbGFzcyBUYXNrR3JhcGgge1xuICBwcml2YXRlIHJvb3RzOiBUYXNrTm9kZU1hcFxuICBwcml2YXRlIGluZGV4OiBUYXNrTm9kZU1hcFxuXG4gIHByaXZhdGUgaW5Qcm9ncmVzczogVGFza05vZGVNYXBcbiAgcHJpdmF0ZSBsb2dFbnRyeU1hcDogTG9nRW50cnlNYXBcblxuICBwcml2YXRlIHJlc3VsdENhY2hlOiBSZXN1bHRDYWNoZVxuICBwcml2YXRlIG9wUXVldWU6IFBRdWV1ZVxuXG4gIGNvbnN0cnVjdG9yKHByaXZhdGUgZ2FyZGVuOiBHYXJkZW4sIHByaXZhdGUgY29uY3VycmVuY3k6IG51bWJlciA9IERFRkFVTFRfQ09OQ1VSUkVOQ1kpIHtcbiAgICB0aGlzLnJvb3RzID0gbmV3IFRhc2tOb2RlTWFwKClcbiAgICB0aGlzLmluZGV4ID0gbmV3IFRhc2tOb2RlTWFwKClcbiAgICB0aGlzLmluUHJvZ3Jlc3MgPSBuZXcgVGFza05vZGVNYXAoKVxuICAgIHRoaXMucmVzdWx0Q2FjaGUgPSBuZXcgUmVzdWx0Q2FjaGUoKVxuICAgIHRoaXMub3BRdWV1ZSA9IG5ldyBQUXVldWUoeyBjb25jdXJyZW5jeTogMSB9KVxuICAgIHRoaXMubG9nRW50cnlNYXAgPSB7fVxuICB9XG5cbiAgYXN5bmMgYWRkVGFzayh0YXNrOiBUYXNrKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIHRoaXMub3BRdWV1ZS5hZGQoKCkgPT4gdGhpcy5hZGRUYXNrSW50ZXJuYWwodGFzaykpXG4gIH1cblxuICBhc3luYyBwcm9jZXNzVGFza3MoKTogUHJvbWlzZTxUYXNrUmVzdWx0cz4ge1xuICAgIHJldHVybiB0aGlzLm9wUXVldWUuYWRkKCgpID0+IHRoaXMucHJvY2Vzc1Rhc2tzSW50ZXJuYWwoKSlcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRkVGFza0ludGVybmFsKHRhc2s6IFRhc2spIHtcbiAgICBjb25zdCBwcmVkZWNlc3NvciA9IHRoaXMuZ2V0UHJlZGVjZXNzb3IodGFzaylcbiAgICBsZXQgbm9kZSA9IHRoaXMuZ2V0Tm9kZSh0YXNrKVxuXG4gICAgaWYgKHByZWRlY2Vzc29yKSB7XG4gICAgICAvKlxuICAgICAgICBwcmVkZWNlc3NvciBpcyBhbHJlYWR5IGluIHRoZSBncmFwaCwgaGF2aW5nIHRoZSBzYW1lIGJhc2VLZXkgYXMgdGFzayxcbiAgICAgICAgYnV0IGEgZGlmZmVyZW50IGtleSAoc2VlIHRoZSBnZXRQcmVkZWNlc3NvciBtZXRob2QgYmVsb3cpLlxuICAgICAgKi9cbiAgICAgIGlmICh0aGlzLmluUHJvZ3Jlc3MuY29udGFpbnMocHJlZGVjZXNzb3IpKSB7XG4gICAgICAgIHRoaXMuaW5kZXguYWRkTm9kZShub2RlKVxuICAgICAgICAvKlxuICAgICAgICAgIFdlIHRyYW5zaXRpb25cbiAgICAgICAgICAgIFtkZXBlbmRlbmNpZXNdID4gcHJlZGVjZXNzb3IgPiBbZGVwZW5kYW50c11cbiAgICAgICAgICB0b1xuICAgICAgICAgICAgW2RlcGVuZGVuY2llc10gPiBwcmVkZWNlc3NvciA+IG5vZGUgPiBbZGVwZW5kYW50c11cbiAgICAgICAgICovXG4gICAgICAgIHRoaXMuaW5oZXJpdChwcmVkZWNlc3Nvciwgbm9kZSlcbiAgICAgICAgcmV0dXJuXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBub2RlID0gcHJlZGVjZXNzb3IgLy8gTm8gbmVlZCB0byBhZGQgYSBuZXcgVGFza05vZGUuXG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5pbmRleC5hZGROb2RlKG5vZGUpXG4gICAgYXdhaXQgdGhpcy5hZGREZXBlbmRlbmNpZXMobm9kZSlcblxuICAgIGlmIChub2RlLmdldERlcGVuZGVuY2llcygpLmxlbmd0aCA9PT0gMCkge1xuICAgICAgdGhpcy5yb290cy5hZGROb2RlKG5vZGUpXG4gICAgfSBlbHNlIHtcbiAgICAgIGF3YWl0IHRoaXMuYWRkRGVwZW5kYW50cyhub2RlKVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgZ2V0Tm9kZSh0YXNrOiBUYXNrKTogVGFza05vZGUge1xuICAgIGNvbnN0IGV4aXN0aW5nID0gdGhpcy5pbmRleC5nZXROb2RlKHRhc2spXG4gICAgcmV0dXJuIGV4aXN0aW5nIHx8IG5ldyBUYXNrTm9kZSh0YXNrKVxuICB9XG4gIC8qXG4gICAgUHJvY2VzcyB0aGUgZ3JhcGggdW50aWwgaXQncyBjb21wbGV0ZVxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBwcm9jZXNzVGFza3NJbnRlcm5hbCgpOiBQcm9taXNlPFRhc2tSZXN1bHRzPiB7XG4gICAgY29uc3QgX3RoaXMgPSB0aGlzXG4gICAgY29uc3QgcmVzdWx0czogVGFza1Jlc3VsdHMgPSB7fVxuXG4gICAgY29uc3QgbG9vcCA9IGFzeW5jICgpID0+IHtcbiAgICAgIGlmIChfdGhpcy5pbmRleC5sZW5ndGggPT09IDApIHtcbiAgICAgICAgLy8gZG9uZSFcbiAgICAgICAgdGhpcy5sb2dFbnRyeU1hcC5jb3VudGVyICYmIHRoaXMubG9nRW50cnlNYXAuY291bnRlci5zZXREb25lKHsgc3ltYm9sOiBcImluZm9cIiB9KVxuICAgICAgICByZXR1cm5cbiAgICAgIH1cblxuICAgICAgY29uc3QgYmF0Y2ggPSBfdGhpcy5yb290cy5nZXROb2RlcygpXG4gICAgICAgIC5maWx0ZXIobiA9PiAhdGhpcy5pblByb2dyZXNzLmNvbnRhaW5zKG4pKVxuICAgICAgICAuc2xpY2UoMCwgX3RoaXMuY29uY3VycmVuY3kgLSB0aGlzLmluUHJvZ3Jlc3MubGVuZ3RoKVxuXG4gICAgICBiYXRjaC5mb3JFYWNoKG4gPT4gdGhpcy5pblByb2dyZXNzLmFkZE5vZGUobikpXG5cbiAgICAgIHRoaXMuaW5pdExvZ2dpbmcoKVxuXG4gICAgICByZXR1cm4gQmx1ZWJpcmQubWFwKGJhdGNoLCBhc3luYyAobm9kZTogVGFza05vZGUpID0+IHtcbiAgICAgICAgY29uc3QgdGFzayA9IG5vZGUudGFza1xuICAgICAgICBjb25zdCB0eXBlID0gbm9kZS5nZXRUeXBlKClcbiAgICAgICAgY29uc3QgYmFzZUtleSA9IG5vZGUuZ2V0QmFzZUtleSgpXG4gICAgICAgIGNvbnN0IGRlc2NyaXB0aW9uID0gbm9kZS5nZXREZXNjcmlwdGlvbigpXG4gICAgICAgIGxldCByZXN1bHRcblxuICAgICAgICB0cnkge1xuICAgICAgICAgIHRoaXMubG9nVGFzayhub2RlKVxuICAgICAgICAgIHRoaXMubG9nRW50cnlNYXAuaW5Qcm9ncmVzcy5zZXRTdGF0ZShpblByb2dyZXNzVG9TdHIodGhpcy5pblByb2dyZXNzLmdldE5vZGVzKCkpKVxuXG4gICAgICAgICAgY29uc3QgZGVwZW5kZW5jeUJhc2VLZXlzID0gKGF3YWl0IHRhc2suZ2V0RGVwZW5kZW5jaWVzKCkpXG4gICAgICAgICAgICAubWFwKGRlcCA9PiBkZXAuZ2V0QmFzZUtleSgpKVxuXG4gICAgICAgICAgY29uc3QgZGVwZW5kZW5jeVJlc3VsdHMgPSBtZXJnZShcbiAgICAgICAgICAgIHRoaXMucmVzdWx0Q2FjaGUucGljayhkZXBlbmRlbmN5QmFzZUtleXMpLFxuICAgICAgICAgICAgcGljayhyZXN1bHRzLCBkZXBlbmRlbmN5QmFzZUtleXMpKVxuXG4gICAgICAgICAgdHJ5IHtcbiAgICAgICAgICAgIHJlc3VsdCA9IGF3YWl0IG5vZGUucHJvY2VzcyhkZXBlbmRlbmN5UmVzdWx0cylcbiAgICAgICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICAgICAgcmVzdWx0ID0geyB0eXBlLCBkZXNjcmlwdGlvbiwgZXJyb3IgfVxuICAgICAgICAgICAgdGhpcy5sb2dUYXNrRXJyb3Iobm9kZSwgZXJyb3IpXG4gICAgICAgICAgICB0aGlzLmNhbmNlbERlcGVuZGFudHMobm9kZSlcbiAgICAgICAgICB9IGZpbmFsbHkge1xuICAgICAgICAgICAgcmVzdWx0c1tiYXNlS2V5XSA9IHJlc3VsdFxuICAgICAgICAgICAgdGhpcy5yZXN1bHRDYWNoZS5wdXQoYmFzZUtleSwgdGFzay52ZXJzaW9uLnZlcnNpb25TdHJpbmcsIHJlc3VsdClcbiAgICAgICAgICB9XG4gICAgICAgIH0gZmluYWxseSB7XG4gICAgICAgICAgdGhpcy5jb21wbGV0ZVRhc2sobm9kZSwgIXJlc3VsdC5lcnJvcilcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBsb29wKClcbiAgICAgIH0pXG4gICAgfVxuXG4gICAgYXdhaXQgbG9vcCgpXG5cbiAgICByZXR1cm4gcmVzdWx0c1xuICB9XG5cbiAgcHJpdmF0ZSBjb21wbGV0ZVRhc2sobm9kZTogVGFza05vZGUsIHN1Y2Nlc3M6IGJvb2xlYW4pIHtcbiAgICBpZiAobm9kZS5nZXREZXBlbmRlbmNpZXMoKS5sZW5ndGggPiAwKSB7XG4gICAgICB0aHJvdyBuZXcgVGFza0dyYXBoRXJyb3IoYFRhc2sgJHtub2RlLmdldEtleSgpfSBzdGlsbCBoYXMgdW5wcm9jZXNzZWQgZGVwZW5kZW5jaWVzYClcbiAgICB9XG5cbiAgICBmb3IgKGxldCBkIG9mIG5vZGUuZ2V0RGVwZW5kYW50cygpKSB7XG4gICAgICBkLnJlbW92ZURlcGVuZGVuY3kobm9kZSlcblxuICAgICAgaWYgKGQuZ2V0RGVwZW5kZW5jaWVzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIHRoaXMucm9vdHMuYWRkTm9kZShkKVxuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMucmVtb3ZlKG5vZGUpXG4gICAgdGhpcy5sb2dUYXNrQ29tcGxldGUobm9kZSwgc3VjY2VzcylcbiAgfVxuXG4gIHByaXZhdGUgZ2V0UHJlZGVjZXNzb3IodGFzazogVGFzayk6IFRhc2tOb2RlIHwgbnVsbCB7XG4gICAgY29uc3Qga2V5ID0gdGFzay5nZXRLZXkoKVxuICAgIGNvbnN0IGJhc2VLZXkgPSB0YXNrLmdldEJhc2VLZXkoKVxuICAgIGNvbnN0IHByZWRlY2Vzc29ycyA9IHRoaXMuaW5kZXguZ2V0Tm9kZXMoKVxuICAgICAgLmZpbHRlcihuID0+IG4uZ2V0QmFzZUtleSgpID09PSBiYXNlS2V5ICYmIG4uZ2V0S2V5KCkgIT09IGtleSlcbiAgICAgIC5yZXZlcnNlKClcbiAgICByZXR1cm4gcHJlZGVjZXNzb3JzWzBdIHx8IG51bGxcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRkRGVwZW5kZW5jaWVzKG5vZGU6IFRhc2tOb2RlKSB7XG4gICAgY29uc3QgdGFzayA9IG5vZGUudGFza1xuICAgIGZvciAoY29uc3QgZCBvZiBhd2FpdCB0YXNrLmdldERlcGVuZGVuY2llcygpKSB7XG5cbiAgICAgIGlmICghZC5mb3JjZSAmJiB0aGlzLnJlc3VsdENhY2hlLmdldChkLmdldEJhc2VLZXkoKSwgZC52ZXJzaW9uLnZlcnNpb25TdHJpbmcpKSB7XG4gICAgICAgIGNvbnRpbnVlXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRlcGVuZGVuY3kgPSB0aGlzLmdldFByZWRlY2Vzc29yKGQpIHx8IHRoaXMuZ2V0Tm9kZShkKVxuICAgICAgdGhpcy5pbmRleC5hZGROb2RlKGRlcGVuZGVuY3kpXG4gICAgICBub2RlLmFkZERlcGVuZGVuY3koZGVwZW5kZW5jeSlcblxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgYWRkRGVwZW5kYW50cyhub2RlOiBUYXNrTm9kZSkge1xuICAgIGNvbnN0IG5vZGVEZXBlbmRlbmNpZXMgPSBub2RlLmdldERlcGVuZGVuY2llcygpXG4gICAgZm9yIChjb25zdCBkIG9mIG5vZGVEZXBlbmRlbmNpZXMpIHtcbiAgICAgIGNvbnN0IGRlcGVuZGFudCA9IHRoaXMuZ2V0UHJlZGVjZXNzb3IoZC50YXNrKSB8fCBkXG4gICAgICBhd2FpdCB0aGlzLmFkZFRhc2tJbnRlcm5hbChkZXBlbmRhbnQudGFzaylcbiAgICAgIGRlcGVuZGFudC5hZGREZXBlbmRhbnQobm9kZSlcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGluaGVyaXQob2xkTm9kZTogVGFza05vZGUsIG5ld05vZGU6IFRhc2tOb2RlKSB7XG4gICAgb2xkTm9kZS5nZXREZXBlbmRhbnRzKCkuZm9yRWFjaChub2RlID0+IHtcbiAgICAgIG5ld05vZGUuYWRkRGVwZW5kYW50KG5vZGUpXG4gICAgICBvbGROb2RlLnJlbW92ZURlcGVuZGFudChub2RlKVxuICAgICAgbm9kZS5yZW1vdmVEZXBlbmRlbmN5KG9sZE5vZGUpXG4gICAgICBub2RlLmFkZERlcGVuZGVuY3kobmV3Tm9kZSlcbiAgICB9KVxuXG4gICAgbmV3Tm9kZS5hZGREZXBlbmRlbmN5KG9sZE5vZGUpXG4gICAgb2xkTm9kZS5hZGREZXBlbmRhbnQobmV3Tm9kZSlcbiAgfVxuXG4gIC8vIFNob3VsZCBvbmx5IGJlIGNhbGxlZCB3aGVuIG5vZGUgaXMgbm90IGEgZGVwZW5kYW50IGZvciBhbnkgdGFzay5cbiAgcHJpdmF0ZSByZW1vdmUobm9kZTogVGFza05vZGUpIHtcbiAgICB0aGlzLnJvb3RzLnJlbW92ZU5vZGUobm9kZSlcbiAgICB0aGlzLmluZGV4LnJlbW92ZU5vZGUobm9kZSlcbiAgICB0aGlzLmluUHJvZ3Jlc3MucmVtb3ZlTm9kZShub2RlKVxuICB9XG5cbiAgLy8gUmVjdXJzaXZlbHkgcmVtb3ZlIG5vZGUncyBkZXBlbmRhbnRzLCB3aXRob3V0IHJlbW92aW5nIG5vZGUuXG4gIHByaXZhdGUgY2FuY2VsRGVwZW5kYW50cyhub2RlOiBUYXNrTm9kZSkge1xuICAgIGNvbnN0IHJlbW92ZXIgPSAobikgPT4ge1xuICAgICAgZm9yIChjb25zdCBkZXBlbmRhbnQgb2Ygbi5nZXREZXBlbmRhbnRzKCkpIHtcbiAgICAgICAgdGhpcy5sb2dUYXNrQ29tcGxldGUobiwgZmFsc2UpXG4gICAgICAgIHJlbW92ZXIoZGVwZW5kYW50KVxuICAgICAgfVxuICAgICAgdGhpcy5yZW1vdmUobilcbiAgICB9XG5cbiAgICBmb3IgKGNvbnN0IGRlcGVuZGFudCBvZiBub2RlLmdldERlcGVuZGFudHMoKSkge1xuICAgICAgbm9kZS5yZW1vdmVEZXBlbmRhbnQoZGVwZW5kYW50KVxuICAgICAgcmVtb3ZlcihkZXBlbmRhbnQpXG4gICAgfVxuICB9XG5cbiAgLy8gTG9nZ2luZ1xuICBwcml2YXRlIGxvZ1Rhc2sobm9kZTogVGFza05vZGUpIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuZ2FyZGVuLmxvZy5kZWJ1Zyh7XG4gICAgICBzZWN0aW9uOiBcInRhc2tzXCIsXG4gICAgICBtc2c6IGBQcm9jZXNzaW5nIHRhc2sgJHt0YXNrU3R5bGUobm9kZS5nZXRLZXkoKSl9YCxcbiAgICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgICB9KVxuICAgIHRoaXMubG9nRW50cnlNYXBbbm9kZS5nZXRLZXkoKV0gPSBlbnRyeVxuICB9XG5cbiAgcHJpdmF0ZSBsb2dUYXNrQ29tcGxldGUobm9kZTogVGFza05vZGUsIHN1Y2Nlc3M6IGJvb2xlYW4pIHtcbiAgICBjb25zdCBlbnRyeSA9IHRoaXMubG9nRW50cnlNYXBbbm9kZS5nZXRLZXkoKV1cbiAgICBpZiAoZW50cnkpIHtcbiAgICAgIHN1Y2Nlc3MgPyBlbnRyeS5zZXRTdWNjZXNzKCkgOiBlbnRyeS5zZXRFcnJvcigpXG4gICAgfVxuICAgIHRoaXMubG9nRW50cnlNYXAuY291bnRlci5zZXRTdGF0ZShyZW1haW5pbmdUYXNrc1RvU3RyKHRoaXMuaW5kZXgubGVuZ3RoKSlcbiAgfVxuXG4gIHByaXZhdGUgaW5pdExvZ2dpbmcoKSB7XG4gICAgaWYgKCFPYmplY3Qua2V5cyh0aGlzLmxvZ0VudHJ5TWFwKS5sZW5ndGgpIHtcbiAgICAgIGNvbnN0IGhlYWRlciA9IHRoaXMuZ2FyZGVuLmxvZy5kZWJ1ZyhcIlByb2Nlc3NpbmcgdGFza3MuLi5cIilcbiAgICAgIGNvbnN0IGNvdW50ZXIgPSB0aGlzLmdhcmRlbi5sb2cuZGVidWcoe1xuICAgICAgICBtc2c6IHJlbWFpbmluZ1Rhc2tzVG9TdHIodGhpcy5pbmRleC5sZW5ndGgpLFxuICAgICAgICBzdGF0dXM6IFwiYWN0aXZlXCIsXG4gICAgICB9KVxuICAgICAgY29uc3QgaW5Qcm9ncmVzcyA9IHRoaXMuZ2FyZGVuLmxvZy5kZWJ1ZyhpblByb2dyZXNzVG9TdHIodGhpcy5pblByb2dyZXNzLmdldE5vZGVzKCkpKVxuICAgICAgdGhpcy5sb2dFbnRyeU1hcCA9IHtcbiAgICAgICAgLi4udGhpcy5sb2dFbnRyeU1hcCxcbiAgICAgICAgaGVhZGVyLFxuICAgICAgICBjb3VudGVyLFxuICAgICAgICBpblByb2dyZXNzLFxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIHByaXZhdGUgbG9nVGFza0Vycm9yKG5vZGU6IFRhc2tOb2RlLCBlcnIpIHtcbiAgICBjb25zdCBkaXZpZGVyID0gcGFkRW5kKFwiXCIsIDgwLCBcIuKAlFwiKVxuICAgIGNvbnN0IGVycm9yID0gdG9HYXJkZW5FcnJvcihlcnIpXG4gICAgY29uc3QgbXNnID0gYFxcbkZhaWxlZCAke25vZGUuZ2V0RGVzY3JpcHRpb24oKX0uIEhlcmUgaXMgdGhlIG91dHB1dDpcXG4ke2RpdmlkZXJ9XFxuJHtlcnJvci5tZXNzYWdlfVxcbiR7ZGl2aWRlcn1cXG5gXG4gICAgdGhpcy5nYXJkZW4ubG9nLmVycm9yKHsgbXNnLCBlcnJvciB9KVxuICB9XG59XG5cbmZ1bmN0aW9uIGdldEluZGV4S2V5KHRhc2s6IFRhc2spIHtcbiAgY29uc3Qga2V5ID0gdGFzay5nZXRLZXkoKVxuXG4gIGlmICghdGFzay50eXBlIHx8ICFrZXkgfHwgdGFzay50eXBlLmxlbmd0aCA9PT0gMCB8fCBrZXkubGVuZ3RoID09PSAwKSB7XG4gICAgdGhyb3cgbmV3IFRhc2tEZWZpbml0aW9uRXJyb3IoXCJUYXNrcyBtdXN0IGRlZmluZSBhIHR5cGUgYW5kIGEga2V5XCIpXG4gIH1cblxuICByZXR1cm4ga2V5XG59XG5cbmNsYXNzIFRhc2tOb2RlTWFwIHtcbiAgLy8gTWFwIGlzIHVzZWQgaGVyZSB0byBmYWNpbGl0YXRlIGluLW9yZGVyIHRyYXZlcnNhbC5cbiAgaW5kZXg6IE1hcDxzdHJpbmcsIFRhc2tOb2RlPlxuICBsZW5ndGg6IG51bWJlclxuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuaW5kZXggPSBuZXcgTWFwKClcbiAgICB0aGlzLmxlbmd0aCA9IDBcbiAgfVxuXG4gIGdldE5vZGUodGFzazogVGFzaykge1xuICAgIGNvbnN0IGluZGV4S2V5ID0gZ2V0SW5kZXhLZXkodGFzaylcbiAgICBjb25zdCBlbGVtZW50ID0gdGhpcy5pbmRleC5nZXQoaW5kZXhLZXkpXG4gICAgcmV0dXJuIGVsZW1lbnRcbiAgfVxuXG4gIGFkZE5vZGUobm9kZTogVGFza05vZGUpOiB2b2lkIHtcbiAgICBjb25zdCBpbmRleEtleSA9IG5vZGUuZ2V0S2V5KClcblxuICAgIGlmICghdGhpcy5pbmRleC5nZXQoaW5kZXhLZXkpKSB7XG4gICAgICB0aGlzLmluZGV4LnNldChpbmRleEtleSwgbm9kZSlcbiAgICAgIHRoaXMubGVuZ3RoKytcbiAgICB9XG4gIH1cblxuICByZW1vdmVOb2RlKG5vZGU6IFRhc2tOb2RlKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuaW5kZXguZGVsZXRlKG5vZGUuZ2V0S2V5KCkpKSB7XG4gICAgICB0aGlzLmxlbmd0aC0tXG4gICAgfVxuICB9XG5cbiAgZ2V0Tm9kZXMoKTogVGFza05vZGVbXSB7XG4gICAgcmV0dXJuIEFycmF5LmZyb20odGhpcy5pbmRleC52YWx1ZXMoKSlcbiAgfVxuXG4gIGNvbnRhaW5zKG5vZGU6IFRhc2tOb2RlKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuaW5kZXguaGFzKG5vZGUuZ2V0S2V5KCkpXG4gIH1cblxufVxuXG5jbGFzcyBUYXNrTm9kZSB7XG4gIHRhc2s6IFRhc2tcblxuICBwcml2YXRlIGRlcGVuZGVuY2llczogVGFza05vZGVNYXBcbiAgcHJpdmF0ZSBkZXBlbmRhbnRzOiBUYXNrTm9kZU1hcFxuXG4gIGNvbnN0cnVjdG9yKHRhc2s6IFRhc2spIHtcbiAgICB0aGlzLnRhc2sgPSB0YXNrXG4gICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBuZXcgVGFza05vZGVNYXAoKVxuICAgIHRoaXMuZGVwZW5kYW50cyA9IG5ldyBUYXNrTm9kZU1hcCgpXG4gIH1cblxuICBhZGREZXBlbmRlbmN5KG5vZGU6IFRhc2tOb2RlKSB7XG4gICAgdGhpcy5kZXBlbmRlbmNpZXMuYWRkTm9kZShub2RlKVxuICB9XG5cbiAgYWRkRGVwZW5kYW50KG5vZGU6IFRhc2tOb2RlKSB7XG4gICAgdGhpcy5kZXBlbmRhbnRzLmFkZE5vZGUobm9kZSlcbiAgfVxuXG4gIHJlbW92ZURlcGVuZGVuY3kobm9kZTogVGFza05vZGUpIHtcbiAgICB0aGlzLmRlcGVuZGVuY2llcy5yZW1vdmVOb2RlKG5vZGUpXG4gIH1cblxuICByZW1vdmVEZXBlbmRhbnQobm9kZTogVGFza05vZGUpIHtcbiAgICB0aGlzLmRlcGVuZGFudHMucmVtb3ZlTm9kZShub2RlKVxuICB9XG5cbiAgZ2V0RGVwZW5kZW5jaWVzKCkge1xuICAgIHJldHVybiB0aGlzLmRlcGVuZGVuY2llcy5nZXROb2RlcygpXG4gIH1cblxuICBnZXREZXBlbmRhbnRzKCkge1xuICAgIHJldHVybiB0aGlzLmRlcGVuZGFudHMuZ2V0Tm9kZXMoKVxuICB9XG5cbiAgZ2V0QmFzZUtleSgpIHtcbiAgICByZXR1cm4gdGhpcy50YXNrLmdldEJhc2VLZXkoKVxuICB9XG5cbiAgZ2V0S2V5KCkge1xuICAgIHJldHVybiBnZXRJbmRleEtleSh0aGlzLnRhc2spXG4gIH1cblxuICBnZXREZXNjcmlwdGlvbigpIHtcbiAgICByZXR1cm4gdGhpcy50YXNrLmdldERlc2NyaXB0aW9uKClcbiAgfVxuXG4gIGdldFR5cGUoKSB7XG4gICAgcmV0dXJuIHRoaXMudGFzay50eXBlXG4gIH1cblxuICAvLyBGb3IgdGVzdGluZy9kZWJ1Z2dpbmcgcHVycG9zZXNcbiAgaW5zcGVjdCgpOiBvYmplY3Qge1xuICAgIHJldHVybiB7XG4gICAgICBrZXk6IHRoaXMuZ2V0S2V5KCksXG4gICAgICBkZXBlbmRlbmNpZXM6IHRoaXMuZ2V0RGVwZW5kZW5jaWVzKCkubWFwKGQgPT4gZC5nZXRLZXkoKSksXG4gICAgICBkZXBlbmRhbnRzOiB0aGlzLmdldERlcGVuZGFudHMoKS5tYXAoZCA9PiBkLmdldEtleSgpKSxcbiAgICB9XG4gIH1cblxuICBhc3luYyBwcm9jZXNzKGRlcGVuZGVuY3lSZXN1bHRzOiBUYXNrUmVzdWx0cykge1xuICAgIGNvbnN0IG91dHB1dCA9IGF3YWl0IHRoaXMudGFzay5wcm9jZXNzKGRlcGVuZGVuY3lSZXN1bHRzKVxuXG4gICAgcmV0dXJuIHtcbiAgICAgIHR5cGU6IHRoaXMuZ2V0VHlwZSgpLFxuICAgICAgZGVzY3JpcHRpb246IHRoaXMuZ2V0RGVzY3JpcHRpb24oKSxcbiAgICAgIG91dHB1dCxcbiAgICAgIGRlcGVuZGVuY3lSZXN1bHRzLFxuICAgIH1cbiAgfVxufVxuXG5pbnRlcmZhY2UgQ2FjaGVkUmVzdWx0IHtcbiAgcmVzdWx0OiBUYXNrUmVzdWx0LFxuICB2ZXJzaW9uU3RyaW5nOiBzdHJpbmdcbn1cblxuY2xhc3MgUmVzdWx0Q2FjaGUge1xuICAvKlxuICAgIEJ5IGRlc2lnbiwgYXQgbW9zdCBvbmUgVGFza1Jlc3VsdCAodGhlIG1vc3QgcmVjZW50bHkgcHJvY2Vzc2VkKSBpcyBjYWNoZWQgZm9yIGEgZ2l2ZW4gYmFzZUtleS5cblxuICAgIEludmFyaWFudDogTm8gY29uY3VycmVudCBjYWxscyBhcmUgbWFkZSB0byB0aGlzIGNsYXNzJyBpbnN0YW5jZSBtZXRob2RzLCBzaW5jZSB0aGV5XG4gICAgb25seSBoYXBwZW4gd2l0aGluIFRhc2tHcmFwaCdzIGFkZFRhc2tJbnRlcm5hbCBhbmQgcHJvY2Vzc1Rhc2tzSW50ZXJuYWwgbWV0aG9kcyxcbiAgICB3aGljaCBhcmUgbmV2ZXIgZXhlY3V0ZWQgY29uY3VycmVudGx5LCBzaW5jZSB0aGV5IGFyZSBleGVjdXRlZCBzZXF1ZW50aWFsbHkgYnkgdGhlXG4gICAgb3BlcmF0aW9uIHF1ZXVlLlxuICAqL1xuICBwcml2YXRlIGNhY2hlOiB7IFtrZXk6IHN0cmluZ106IENhY2hlZFJlc3VsdCB9XG5cbiAgY29uc3RydWN0b3IoKSB7XG4gICAgdGhpcy5jYWNoZSA9IHt9XG4gIH1cblxuICBwdXQoYmFzZUtleTogc3RyaW5nLCB2ZXJzaW9uU3RyaW5nOiBzdHJpbmcsIHJlc3VsdDogVGFza1Jlc3VsdCk6IHZvaWQge1xuICAgIHRoaXMuY2FjaGVbYmFzZUtleV0gPSB7IHJlc3VsdCwgdmVyc2lvblN0cmluZyB9XG4gIH1cblxuICBnZXQoYmFzZUtleTogc3RyaW5nLCB2ZXJzaW9uU3RyaW5nOiBzdHJpbmcpOiBUYXNrUmVzdWx0IHwgbnVsbCB7XG4gICAgY29uc3QgciA9IHRoaXMuY2FjaGVbYmFzZUtleV1cbiAgICByZXR1cm4gKHIgJiYgci52ZXJzaW9uU3RyaW5nID09PSB2ZXJzaW9uU3RyaW5nICYmICFyLnJlc3VsdC5lcnJvcikgPyByLnJlc3VsdCA6IG51bGxcbiAgfVxuXG4gIGdldE5ld2VzdChiYXNlS2V5OiBzdHJpbmcpOiBUYXNrUmVzdWx0IHwgbnVsbCB7XG4gICAgY29uc3QgciA9IHRoaXMuY2FjaGVbYmFzZUtleV1cbiAgICByZXR1cm4gKHIgJiYgIXIucmVzdWx0LmVycm9yKSA/IHIucmVzdWx0IDogbnVsbFxuICB9XG5cbiAgLy8gUmV0dXJucyBuZXdlc3QgY2FjaGVkIHJlc3VsdHMsIGlmIGFueSwgZm9yIGJhc2VLZXlzXG4gIHBpY2soYmFzZUtleXM6IHN0cmluZ1tdKTogVGFza1Jlc3VsdHMge1xuICAgIGNvbnN0IHJlc3VsdHM6IFRhc2tSZXN1bHRzID0ge31cblxuICAgIGZvciAoY29uc3QgYmFzZUtleSBvZiBiYXNlS2V5cykge1xuICAgICAgY29uc3QgY2FjaGVkUmVzdWx0ID0gdGhpcy5nZXROZXdlc3QoYmFzZUtleSlcbiAgICAgIGlmIChjYWNoZWRSZXN1bHQpIHtcbiAgICAgICAgcmVzdWx0c1tiYXNlS2V5XSA9IGNhY2hlZFJlc3VsdFxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRzXG4gIH1cblxufVxuXG5pbnRlcmZhY2UgTG9nRW50cnlNYXAgeyBba2V5OiBzdHJpbmddOiBMb2dFbnRyeSB9XG5cbmNvbnN0IHRhc2tTdHlsZSA9IGNoYWxrLmN5YW4uYm9sZFxuXG5mdW5jdGlvbiBpblByb2dyZXNzVG9TdHIobm9kZXMpIHtcbiAgcmV0dXJuIGBDdXJyZW50bHkgaW4gcHJvZ3Jlc3MgWyR7bm9kZXMubWFwKG4gPT4gdGFza1N0eWxlKG4uZ2V0S2V5KCkpKS5qb2luKFwiLCBcIil9XWBcbn1cblxuZnVuY3Rpb24gcmVtYWluaW5nVGFza3NUb1N0cihudW0pIHtcbiAgY29uc3Qgc3R5bGUgPSBudW0gPT09IDAgPyBjaGFsay5ncmVlbiA6IGNoYWxrLnllbGxvd1xuICByZXR1cm4gYFJlbWFpbmluZyB0YXNrcyAke3N0eWxlLmJvbGQoU3RyaW5nKG51bSkpfWBcbn1cbiJdfQ== diff --git a/garden-service/build/tasks/base.d.ts b/garden-service/build/tasks/base.d.ts new file mode 100644 index 00000000000..03d0e35a001 --- /dev/null +++ b/garden-service/build/tasks/base.d.ts @@ -0,0 +1,26 @@ +import { TaskResults } from "../task-graph"; +import { ModuleVersion } from "../vcs/base"; +import { Garden } from "../garden"; +export declare class TaskDefinitionError extends Error { +} +export interface TaskParams { + garden: Garden; + force?: boolean; + version: ModuleVersion; +} +export declare abstract class Task { + abstract type: string; + garden: Garden; + id: string; + force: boolean; + version: ModuleVersion; + dependencies: Task[]; + constructor(initArgs: TaskParams); + getDependencies(): Promise; + protected abstract getName(): string; + getBaseKey(): string; + getKey(): string; + abstract getDescription(): string; + abstract process(dependencyResults: TaskResults): Promise; +} +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/base.js b/garden-service/build/tasks/base.js new file mode 100644 index 00000000000..23417d3fc27 --- /dev/null +++ b/garden-service/build/tasks/base.js @@ -0,0 +1,44 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const uuid_1 = require("uuid"); +class TaskDefinitionError extends Error { +} +exports.TaskDefinitionError = TaskDefinitionError; +class Task { + constructor(initArgs) { + this.garden = initArgs.garden; + this.dependencies = []; + this.id = uuid_1.v1(); // uuidv1 is timestamp-based + this.force = !!initArgs.force; + this.version = initArgs.version; + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + return this.dependencies; + }); + } + getBaseKey() { + return `${this.type}.${this.getName()}`; + } + getKey() { + return `${this.getBaseKey()}.${this.id}`; + } +} +exports.Task = Task; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRhc2tzL2Jhc2UudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUlILCtCQUFtQztBQUduQyxNQUFhLG1CQUFvQixTQUFRLEtBQUs7Q0FBSTtBQUFsRCxrREFBa0Q7QUFRbEQsTUFBc0IsSUFBSTtJQVN4QixZQUFZLFFBQW9CO1FBQzlCLElBQUksQ0FBQyxNQUFNLEdBQUcsUUFBUSxDQUFDLE1BQU0sQ0FBQTtRQUM3QixJQUFJLENBQUMsWUFBWSxHQUFHLEVBQUUsQ0FBQTtRQUN0QixJQUFJLENBQUMsRUFBRSxHQUFHLFNBQU0sRUFBRSxDQUFBLENBQUMsNEJBQTRCO1FBQy9DLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxDQUFDLFFBQVEsQ0FBQyxLQUFLLENBQUE7UUFDN0IsSUFBSSxDQUFDLE9BQU8sR0FBRyxRQUFRLENBQUMsT0FBTyxDQUFBO0lBQ2pDLENBQUM7SUFFSyxlQUFlOztZQUNuQixPQUFPLElBQUksQ0FBQyxZQUFZLENBQUE7UUFDMUIsQ0FBQztLQUFBO0lBSUQsVUFBVTtRQUNSLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxJQUFJLElBQUksQ0FBQyxPQUFPLEVBQUUsRUFBRSxDQUFBO0lBQ3pDLENBQUM7SUFFRCxNQUFNO1FBQ0osT0FBTyxHQUFHLElBQUksQ0FBQyxVQUFVLEVBQUUsSUFBSSxJQUFJLENBQUMsRUFBRSxFQUFFLENBQUE7SUFDMUMsQ0FBQztDQUtGO0FBbENELG9CQWtDQyIsImZpbGUiOiJ0YXNrcy9iYXNlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IFRhc2tSZXN1bHRzIH0gZnJvbSBcIi4uL3Rhc2stZ3JhcGhcIlxuaW1wb3J0IHsgTW9kdWxlVmVyc2lvbiB9IGZyb20gXCIuLi92Y3MvYmFzZVwiXG5pbXBvcnQgeyB2MSBhcyB1dWlkdjEgfSBmcm9tIFwidXVpZFwiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vZ2FyZGVuXCJcblxuZXhwb3J0IGNsYXNzIFRhc2tEZWZpbml0aW9uRXJyb3IgZXh0ZW5kcyBFcnJvciB7IH1cblxuZXhwb3J0IGludGVyZmFjZSBUYXNrUGFyYW1zIHtcbiAgZ2FyZGVuOiBHYXJkZW5cbiAgZm9yY2U/OiBib29sZWFuXG4gIHZlcnNpb246IE1vZHVsZVZlcnNpb25cbn1cblxuZXhwb3J0IGFic3RyYWN0IGNsYXNzIFRhc2sge1xuICBhYnN0cmFjdCB0eXBlOiBzdHJpbmdcbiAgZ2FyZGVuOiBHYXJkZW5cbiAgaWQ6IHN0cmluZ1xuICBmb3JjZTogYm9vbGVhblxuICB2ZXJzaW9uOiBNb2R1bGVWZXJzaW9uXG5cbiAgZGVwZW5kZW5jaWVzOiBUYXNrW11cblxuICBjb25zdHJ1Y3Rvcihpbml0QXJnczogVGFza1BhcmFtcykge1xuICAgIHRoaXMuZ2FyZGVuID0gaW5pdEFyZ3MuZ2FyZGVuXG4gICAgdGhpcy5kZXBlbmRlbmNpZXMgPSBbXVxuICAgIHRoaXMuaWQgPSB1dWlkdjEoKSAvLyB1dWlkdjEgaXMgdGltZXN0YW1wLWJhc2VkXG4gICAgdGhpcy5mb3JjZSA9ICEhaW5pdEFyZ3MuZm9yY2VcbiAgICB0aGlzLnZlcnNpb24gPSBpbml0QXJncy52ZXJzaW9uXG4gIH1cblxuICBhc3luYyBnZXREZXBlbmRlbmNpZXMoKTogUHJvbWlzZTxUYXNrW10+IHtcbiAgICByZXR1cm4gdGhpcy5kZXBlbmRlbmNpZXNcbiAgfVxuXG4gIHByb3RlY3RlZCBhYnN0cmFjdCBnZXROYW1lKCk6IHN0cmluZ1xuXG4gIGdldEJhc2VLZXkoKTogc3RyaW5nIHtcbiAgICByZXR1cm4gYCR7dGhpcy50eXBlfS4ke3RoaXMuZ2V0TmFtZSgpfWBcbiAgfVxuXG4gIGdldEtleSgpOiBzdHJpbmcge1xuICAgIHJldHVybiBgJHt0aGlzLmdldEJhc2VLZXkoKX0uJHt0aGlzLmlkfWBcbiAgfVxuXG4gIGFic3RyYWN0IGdldERlc2NyaXB0aW9uKCk6IHN0cmluZ1xuXG4gIGFic3RyYWN0IGFzeW5jIHByb2Nlc3MoZGVwZW5kZW5jeVJlc3VsdHM6IFRhc2tSZXN1bHRzKTogUHJvbWlzZTxhbnk+XG59XG4iXX0= diff --git a/garden-service/build/tasks/build.d.ts b/garden-service/build/tasks/build.d.ts new file mode 100644 index 00000000000..31bcf3f099a --- /dev/null +++ b/garden-service/build/tasks/build.d.ts @@ -0,0 +1,19 @@ +import { Module } from "../types/module"; +import { BuildResult } from "../types/plugin/outputs"; +import { Task } from "../tasks/base"; +import { Garden } from "../garden"; +export interface BuildTaskParams { + garden: Garden; + module: Module; + force: boolean; +} +export declare class BuildTask extends Task { + type: string; + private module; + constructor({ garden, force, module }: BuildTaskParams); + getDependencies(): Promise; + protected getName(): string; + getDescription(): string; + process(): Promise; +} +//# sourceMappingURL=build.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/build.js b/garden-service/build/tasks/build.js new file mode 100644 index 00000000000..8b6bf24bd89 --- /dev/null +++ b/garden-service/build/tasks/build.js @@ -0,0 +1,76 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const base_1 = require("../tasks/base"); +class BuildTask extends base_1.Task { + constructor({ garden, force, module }) { + super({ garden, force, version: module.version }); + this.type = "build"; + this.module = module; + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + const deps = yield this.garden.resolveModuleDependencies(this.module.build.dependencies, []); + return Bluebird.map(deps, (m) => __awaiter(this, void 0, void 0, function* () { + return new BuildTask({ + garden: this.garden, + module: m, + force: this.force, + }); + })); + }); + } + getName() { + return this.module.name; + } + getDescription() { + return `building ${this.module.name}`; + } + process() { + return __awaiter(this, void 0, void 0, function* () { + const module = this.module; + if (!this.force && (yield this.garden.actions.getBuildStatus({ module })).ready) { + // this is necessary in case other modules depend on files from this one + yield this.garden.buildDir.syncDependencyProducts(this.module); + return { fresh: false }; + } + const logEntry = this.garden.log.info({ + section: this.module.name, + msg: "Building", + status: "active", + }); + let result; + try { + result = yield this.garden.actions.build({ + module, + logEntry, + }); + } + catch (err) { + logEntry.setError(); + throw err; + } + logEntry.setSuccess({ msg: chalk_1.default.green(`Done (took ${logEntry.getDuration(1)} sec)`), append: true }); + return result; + }); + } +} +exports.BuildTask = BuildTask; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRhc2tzL2J1aWxkLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7Ozs7Ozs7Ozs7QUFFSCxxQ0FBb0M7QUFDcEMsaUNBQXlCO0FBR3pCLHdDQUFvQztBQVNwQyxNQUFhLFNBQVUsU0FBUSxXQUFJO0lBS2pDLFlBQVksRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBbUI7UUFDcEQsS0FBSyxDQUFDLEVBQUUsTUFBTSxFQUFFLEtBQUssRUFBRSxPQUFPLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUE7UUFMbkQsU0FBSSxHQUFHLE9BQU8sQ0FBQTtRQU1aLElBQUksQ0FBQyxNQUFNLEdBQUcsTUFBTSxDQUFBO0lBQ3RCLENBQUM7SUFFSyxlQUFlOztZQUNuQixNQUFNLElBQUksR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMseUJBQXlCLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxFQUFFLEVBQUUsQ0FBQyxDQUFBO1lBQzVGLE9BQU8sUUFBUSxDQUFDLEdBQUcsQ0FBQyxJQUFJLEVBQUUsQ0FBTyxDQUFTLEVBQUUsRUFBRTtnQkFDNUMsT0FBTyxJQUFJLFNBQVMsQ0FBQztvQkFDbkIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO29CQUNuQixNQUFNLEVBQUUsQ0FBQztvQkFDVCxLQUFLLEVBQUUsSUFBSSxDQUFDLEtBQUs7aUJBQ2xCLENBQUMsQ0FBQTtZQUNKLENBQUMsQ0FBQSxDQUFDLENBQUE7UUFDSixDQUFDO0tBQUE7SUFFUyxPQUFPO1FBQ2YsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQTtJQUN6QixDQUFDO0lBRUQsY0FBYztRQUNaLE9BQU8sWUFBWSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksRUFBRSxDQUFBO0lBQ3ZDLENBQUM7SUFFSyxPQUFPOztZQUNYLE1BQU0sTUFBTSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUE7WUFFMUIsSUFBSSxDQUFDLElBQUksQ0FBQyxLQUFLLElBQUksQ0FBQyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGNBQWMsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQyxLQUFLLEVBQUU7Z0JBQy9FLHdFQUF3RTtnQkFDeEUsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsTUFBTSxDQUFDLENBQUE7Z0JBQzlELE9BQU8sRUFBRSxLQUFLLEVBQUUsS0FBSyxFQUFFLENBQUE7YUFDeEI7WUFFRCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7Z0JBQ3BDLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUk7Z0JBQ3pCLEdBQUcsRUFBRSxVQUFVO2dCQUNmLE1BQU0sRUFBRSxRQUFRO2FBQ2pCLENBQUMsQ0FBQTtZQUVGLElBQUksTUFBbUIsQ0FBQTtZQUN2QixJQUFJO2dCQUNGLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLEtBQUssQ0FBQztvQkFDdkMsTUFBTTtvQkFDTixRQUFRO2lCQUNULENBQUMsQ0FBQTthQUNIO1lBQUMsT0FBTyxHQUFHLEVBQUU7Z0JBQ1osUUFBUSxDQUFDLFFBQVEsRUFBRSxDQUFBO2dCQUNuQixNQUFNLEdBQUcsQ0FBQTthQUNWO1lBRUQsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxlQUFLLENBQUMsS0FBSyxDQUFDLGNBQWMsUUFBUSxDQUFDLFdBQVcsQ0FBQyxDQUFDLENBQUMsT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7WUFDckcsT0FBTyxNQUFNLENBQUE7UUFDZixDQUFDO0tBQUE7Q0FDRjtBQTFERCw4QkEwREMiLCJmaWxlIjoidGFza3MvYnVpbGQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBCdWlsZFJlc3VsdCB9IGZyb20gXCIuLi90eXBlcy9wbHVnaW4vb3V0cHV0c1wiXG5pbXBvcnQgeyBUYXNrIH0gZnJvbSBcIi4uL3Rhc2tzL2Jhc2VcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4uL2dhcmRlblwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRUYXNrUGFyYW1zIHtcbiAgZ2FyZGVuOiBHYXJkZW5cbiAgbW9kdWxlOiBNb2R1bGVcbiAgZm9yY2U6IGJvb2xlYW5cbn1cblxuZXhwb3J0IGNsYXNzIEJ1aWxkVGFzayBleHRlbmRzIFRhc2sge1xuICB0eXBlID0gXCJidWlsZFwiXG5cbiAgcHJpdmF0ZSBtb2R1bGU6IE1vZHVsZVxuXG4gIGNvbnN0cnVjdG9yKHsgZ2FyZGVuLCBmb3JjZSwgbW9kdWxlIH06IEJ1aWxkVGFza1BhcmFtcykge1xuICAgIHN1cGVyKHsgZ2FyZGVuLCBmb3JjZSwgdmVyc2lvbjogbW9kdWxlLnZlcnNpb24gfSlcbiAgICB0aGlzLm1vZHVsZSA9IG1vZHVsZVxuICB9XG5cbiAgYXN5bmMgZ2V0RGVwZW5kZW5jaWVzKCk6IFByb21pc2U8QnVpbGRUYXNrW10+IHtcbiAgICBjb25zdCBkZXBzID0gYXdhaXQgdGhpcy5nYXJkZW4ucmVzb2x2ZU1vZHVsZURlcGVuZGVuY2llcyh0aGlzLm1vZHVsZS5idWlsZC5kZXBlbmRlbmNpZXMsIFtdKVxuICAgIHJldHVybiBCbHVlYmlyZC5tYXAoZGVwcywgYXN5bmMgKG06IE1vZHVsZSkgPT4ge1xuICAgICAgcmV0dXJuIG5ldyBCdWlsZFRhc2soe1xuICAgICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgICBtb2R1bGU6IG0sXG4gICAgICAgIGZvcmNlOiB0aGlzLmZvcmNlLFxuICAgICAgfSlcbiAgICB9KVxuICB9XG5cbiAgcHJvdGVjdGVkIGdldE5hbWUoKSB7XG4gICAgcmV0dXJuIHRoaXMubW9kdWxlLm5hbWVcbiAgfVxuXG4gIGdldERlc2NyaXB0aW9uKCkge1xuICAgIHJldHVybiBgYnVpbGRpbmcgJHt0aGlzLm1vZHVsZS5uYW1lfWBcbiAgfVxuXG4gIGFzeW5jIHByb2Nlc3MoKTogUHJvbWlzZTxCdWlsZFJlc3VsdD4ge1xuICAgIGNvbnN0IG1vZHVsZSA9IHRoaXMubW9kdWxlXG5cbiAgICBpZiAoIXRoaXMuZm9yY2UgJiYgKGF3YWl0IHRoaXMuZ2FyZGVuLmFjdGlvbnMuZ2V0QnVpbGRTdGF0dXMoeyBtb2R1bGUgfSkpLnJlYWR5KSB7XG4gICAgICAvLyB0aGlzIGlzIG5lY2Vzc2FyeSBpbiBjYXNlIG90aGVyIG1vZHVsZXMgZGVwZW5kIG9uIGZpbGVzIGZyb20gdGhpcyBvbmVcbiAgICAgIGF3YWl0IHRoaXMuZ2FyZGVuLmJ1aWxkRGlyLnN5bmNEZXBlbmRlbmN5UHJvZHVjdHModGhpcy5tb2R1bGUpXG4gICAgICByZXR1cm4geyBmcmVzaDogZmFsc2UgfVxuICAgIH1cblxuICAgIGNvbnN0IGxvZ0VudHJ5ID0gdGhpcy5nYXJkZW4ubG9nLmluZm8oe1xuICAgICAgc2VjdGlvbjogdGhpcy5tb2R1bGUubmFtZSxcbiAgICAgIG1zZzogXCJCdWlsZGluZ1wiLFxuICAgICAgc3RhdHVzOiBcImFjdGl2ZVwiLFxuICAgIH0pXG5cbiAgICBsZXQgcmVzdWx0OiBCdWlsZFJlc3VsdFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmdhcmRlbi5hY3Rpb25zLmJ1aWxkKHtcbiAgICAgICAgbW9kdWxlLFxuICAgICAgICBsb2dFbnRyeSxcbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dFbnRyeS5zZXRFcnJvcigpXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG5cbiAgICBsb2dFbnRyeS5zZXRTdWNjZXNzKHsgbXNnOiBjaGFsay5ncmVlbihgRG9uZSAodG9vayAke2xvZ0VudHJ5LmdldER1cmF0aW9uKDEpfSBzZWMpYCksIGFwcGVuZDogdHJ1ZSB9KVxuICAgIHJldHVybiByZXN1bHRcbiAgfVxufVxuIl19 diff --git a/garden-service/build/tasks/deploy.d.ts b/garden-service/build/tasks/deploy.d.ts new file mode 100644 index 00000000000..13dfd2fb9ce --- /dev/null +++ b/garden-service/build/tasks/deploy.d.ts @@ -0,0 +1,32 @@ +import { LogEntry } from "../logger/log-entry"; +import { Task } from "./base"; +import { Service, ServiceStatus } from "../types/service"; +import { Module } from "../types/module"; +import { Garden } from "../garden"; +export interface DeployTaskParams { + garden: Garden; + service: Service; + force: boolean; + forceBuild: boolean; + logEntry?: LogEntry; +} +export declare class DeployTask extends Task { + type: string; + private service; + private forceBuild; + private logEntry?; + constructor({ garden, service, force, forceBuild, logEntry }: DeployTaskParams); + getDependencies(): Promise; + protected getName(): string; + getDescription(): string; + process(): Promise; +} +export declare function getDeployTasks({ garden, module, serviceNames, force, forceBuild, includeDependants }: { + garden: Garden; + module: Module; + serviceNames?: string[] | null; + force?: boolean; + forceBuild?: boolean; + includeDependants?: boolean; +}): Promise; +//# sourceMappingURL=deploy.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/deploy.js b/garden-service/build/tasks/deploy.js new file mode 100644 index 00000000000..7ab1d285a21 --- /dev/null +++ b/garden-service/build/tasks/deploy.js @@ -0,0 +1,115 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const base_1 = require("./base"); +const service_1 = require("../types/service"); +const watch_1 = require("../watch"); +const util_1 = require("../util/util"); +const push_1 = require("./push"); +class DeployTask extends base_1.Task { + constructor({ garden, service, force, forceBuild, logEntry }) { + super({ garden, force, version: service.module.version }); + this.type = "deploy"; + this.service = service; + this.forceBuild = forceBuild; + this.logEntry = logEntry; + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + const serviceDeps = this.service.config.dependencies; + const services = yield this.garden.getServices(serviceDeps); + const deps = yield Bluebird.map(services, (service) => __awaiter(this, void 0, void 0, function* () { + return new DeployTask({ + garden: this.garden, + service, + force: false, + forceBuild: this.forceBuild, + }); + })); + deps.push(new push_1.PushTask({ + garden: this.garden, + module: this.service.module, + forceBuild: this.forceBuild, + })); + return deps; + }); + } + getName() { + return this.service.name; + } + getDescription() { + return `deploying service ${this.service.name} (from module ${this.service.module.name})`; + } + process() { + return __awaiter(this, void 0, void 0, function* () { + const logEntry = (this.logEntry || this.garden.log).info({ + section: this.service.name, + msg: "Checking status", + status: "active", + }); + // TODO: get version from build task results + const { versionString } = yield this.service.module.version; + const status = yield this.garden.actions.getServiceStatus({ service: this.service, logEntry }); + if (!this.force && + versionString === status.version && + status.state === "ready") { + // already deployed and ready + logEntry.setSuccess({ + msg: `Version ${versionString} already deployed`, + append: true, + }); + return status; + } + logEntry.setState("Deploying"); + const dependencies = yield this.garden.getServices(this.service.config.dependencies); + let result; + try { + result = yield this.garden.actions.deployService({ + service: this.service, + runtimeContext: yield service_1.prepareRuntimeContext(this.garden, this.service.module, dependencies), + logEntry, + force: this.force, + }); + } + catch (err) { + logEntry.setError(); + throw err; + } + logEntry.setSuccess({ msg: chalk_1.default.green(`Ready`), append: true }); + return result; + }); + } +} +exports.DeployTask = DeployTask; +function getDeployTasks({ garden, module, serviceNames, force = false, forceBuild = false, includeDependants = false }) { + return __awaiter(this, void 0, void 0, function* () { + const modulesToProcess = includeDependants + ? (yield watch_1.withDependants(garden, [module], yield watch_1.computeAutoReloadDependants(garden))) + : [module]; + const moduleServices = lodash_1.flatten(yield Bluebird.map(modulesToProcess, m => garden.getServices(util_1.getNames(m.serviceConfigs)))); + const servicesToProcess = serviceNames + ? moduleServices.filter(s => serviceNames.includes(s.name)) + : moduleServices; + return servicesToProcess.map(service => new DeployTask({ garden, service, force, forceBuild })); + }); +} +exports.getDeployTasks = getDeployTasks; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFpQixHQUFHLEtBQUssRUFJekY7O1FBR0gsTUFBTSxnQkFBZ0IsR0FBRyxpQkFBaUI7WUFDeEMsQ0FBQyxDQUFDLENBQUMsTUFBTSxzQkFBYyxDQUFDLE1BQU0sRUFBRSxDQUFDLE1BQU0sQ0FBQyxFQUFFLE1BQU0sbUNBQTJCLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQztZQUNyRixDQUFDLENBQUMsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUVaLE1BQU0sY0FBYyxHQUFHLGdCQUFPLENBQUMsTUFBTSxRQUFRLENBQUMsR0FBRyxDQUMvQyxnQkFBZ0IsRUFDaEIsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxNQUFNLENBQUMsV0FBVyxDQUFDLGVBQVEsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUE7UUFFdkQsTUFBTSxpQkFBaUIsR0FBRyxZQUFZO1lBQ3BDLENBQUMsQ0FBQyxjQUFjLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQyxFQUFFLENBQUMsWUFBWSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUM7WUFDM0QsQ0FBQyxDQUFDLGNBQWMsQ0FBQTtRQUVsQixPQUFPLGlCQUFpQixDQUFDLEdBQUcsQ0FBQyxPQUFPLENBQUMsRUFBRSxDQUFDLElBQUksVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLE9BQU8sRUFBRSxLQUFLLEVBQUUsVUFBVSxFQUFFLENBQUMsQ0FBQyxDQUFBO0lBQ2pHLENBQUM7Q0FBQTtBQXJCRCx3Q0FxQkMiLCJmaWxlIjoidGFza3MvZGVwbG95LmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGZsYXR0ZW4gfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCAqIGFzIEJsdWViaXJkIGZyb20gXCJibHVlYmlyZFwiXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcbmltcG9ydCB7IExvZ0VudHJ5IH0gZnJvbSBcIi4uL2xvZ2dlci9sb2ctZW50cnlcIlxuaW1wb3J0IHsgVGFzayB9IGZyb20gXCIuL2Jhc2VcIlxuaW1wb3J0IHtcbiAgU2VydmljZSxcbiAgU2VydmljZVN0YXR1cyxcbiAgcHJlcGFyZVJ1bnRpbWVDb250ZXh0LFxufSBmcm9tIFwiLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7IHdpdGhEZXBlbmRhbnRzLCBjb21wdXRlQXV0b1JlbG9hZERlcGVuZGFudHMgfSBmcm9tIFwiLi4vd2F0Y2hcIlxuaW1wb3J0IHsgZ2V0TmFtZXMgfSBmcm9tIFwiLi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuaW1wb3J0IHsgUHVzaFRhc2sgfSBmcm9tIFwiLi9wdXNoXCJcblxuZXhwb3J0IGludGVyZmFjZSBEZXBsb3lUYXNrUGFyYW1zIHtcbiAgZ2FyZGVuOiBHYXJkZW5cbiAgc2VydmljZTogU2VydmljZVxuICBmb3JjZTogYm9vbGVhblxuICBmb3JjZUJ1aWxkOiBib29sZWFuXG4gIGxvZ0VudHJ5PzogTG9nRW50cnlcbn1cblxuZXhwb3J0IGNsYXNzIERlcGxveVRhc2sgZXh0ZW5kcyBUYXNrIHtcbiAgdHlwZSA9IFwiZGVwbG95XCJcblxuICBwcml2YXRlIHNlcnZpY2U6IFNlcnZpY2VcbiAgcHJpdmF0ZSBmb3JjZUJ1aWxkOiBib29sZWFuXG4gIHByaXZhdGUgbG9nRW50cnk/OiBMb2dFbnRyeVxuXG4gIGNvbnN0cnVjdG9yKHsgZ2FyZGVuLCBzZXJ2aWNlLCBmb3JjZSwgZm9yY2VCdWlsZCwgbG9nRW50cnkgfTogRGVwbG95VGFza1BhcmFtcykge1xuICAgIHN1cGVyKHsgZ2FyZGVuLCBmb3JjZSwgdmVyc2lvbjogc2VydmljZS5tb2R1bGUudmVyc2lvbiB9KVxuICAgIHRoaXMuc2VydmljZSA9IHNlcnZpY2VcbiAgICB0aGlzLmZvcmNlQnVpbGQgPSBmb3JjZUJ1aWxkXG4gICAgdGhpcy5sb2dFbnRyeSA9IGxvZ0VudHJ5XG4gIH1cblxuICBhc3luYyBnZXREZXBlbmRlbmNpZXMoKSB7XG4gICAgY29uc3Qgc2VydmljZURlcHMgPSB0aGlzLnNlcnZpY2UuY29uZmlnLmRlcGVuZGVuY2llc1xuICAgIGNvbnN0IHNlcnZpY2VzID0gYXdhaXQgdGhpcy5nYXJkZW4uZ2V0U2VydmljZXMoc2VydmljZURlcHMpXG5cbiAgICBjb25zdCBkZXBzOiBUYXNrW10gPSBhd2FpdCBCbHVlYmlyZC5tYXAoc2VydmljZXMsIGFzeW5jIChzZXJ2aWNlKSA9PiB7XG4gICAgICByZXR1cm4gbmV3IERlcGxveVRhc2soe1xuICAgICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgICBzZXJ2aWNlLFxuICAgICAgICBmb3JjZTogZmFsc2UsXG4gICAgICAgIGZvcmNlQnVpbGQ6IHRoaXMuZm9yY2VCdWlsZCxcbiAgICAgIH0pXG4gICAgfSlcblxuICAgIGRlcHMucHVzaChuZXcgUHVzaFRhc2soe1xuICAgICAgZ2FyZGVuOiB0aGlzLmdhcmRlbixcbiAgICAgIG1vZHVsZTogdGhpcy5zZXJ2aWNlLm1vZHVsZSxcbiAgICAgIGZvcmNlQnVpbGQ6IHRoaXMuZm9yY2VCdWlsZCxcbiAgICB9KSlcblxuICAgIHJldHVybiBkZXBzXG4gIH1cblxuICBwcm90ZWN0ZWQgZ2V0TmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5zZXJ2aWNlLm5hbWVcbiAgfVxuXG4gIGdldERlc2NyaXB0aW9uKCkge1xuICAgIHJldHVybiBgZGVwbG95aW5nIHNlcnZpY2UgJHt0aGlzLnNlcnZpY2UubmFtZX0gKGZyb20gbW9kdWxlICR7dGhpcy5zZXJ2aWNlLm1vZHVsZS5uYW1lfSlgXG4gIH1cblxuICBhc3luYyBwcm9jZXNzKCk6IFByb21pc2U8U2VydmljZVN0YXR1cz4ge1xuICAgIGNvbnN0IGxvZ0VudHJ5ID0gKHRoaXMubG9nRW50cnkgfHwgdGhpcy5nYXJkZW4ubG9nKS5pbmZvKHtcbiAgICAgIHNlY3Rpb246IHRoaXMuc2VydmljZS5uYW1lLFxuICAgICAgbXNnOiBcIkNoZWNraW5nIHN0YXR1c1wiLFxuICAgICAgc3RhdHVzOiBcImFjdGl2ZVwiLFxuICAgIH0pXG5cbiAgICAvLyBUT0RPOiBnZXQgdmVyc2lvbiBmcm9tIGJ1aWxkIHRhc2sgcmVzdWx0c1xuICAgIGNvbnN0IHsgdmVyc2lvblN0cmluZyB9ID0gYXdhaXQgdGhpcy5zZXJ2aWNlLm1vZHVsZS52ZXJzaW9uXG4gICAgY29uc3Qgc3RhdHVzID0gYXdhaXQgdGhpcy5nYXJkZW4uYWN0aW9ucy5nZXRTZXJ2aWNlU3RhdHVzKHsgc2VydmljZTogdGhpcy5zZXJ2aWNlLCBsb2dFbnRyeSB9KVxuXG4gICAgaWYgKFxuICAgICAgIXRoaXMuZm9yY2UgJiZcbiAgICAgIHZlcnNpb25TdHJpbmcgPT09IHN0YXR1cy52ZXJzaW9uICYmXG4gICAgICBzdGF0dXMuc3RhdGUgPT09IFwicmVhZHlcIlxuICAgICkge1xuICAgICAgLy8gYWxyZWFkeSBkZXBsb3llZCBhbmQgcmVhZHlcbiAgICAgIGxvZ0VudHJ5LnNldFN1Y2Nlc3Moe1xuICAgICAgICBtc2c6IGBWZXJzaW9uICR7dmVyc2lvblN0cmluZ30gYWxyZWFkeSBkZXBsb3llZGAsXG4gICAgICAgIGFwcGVuZDogdHJ1ZSxcbiAgICAgIH0pXG4gICAgICByZXR1cm4gc3RhdHVzXG4gICAgfVxuXG4gICAgbG9nRW50cnkuc2V0U3RhdGUoXCJEZXBsb3lpbmdcIilcblxuICAgIGNvbnN0IGRlcGVuZGVuY2llcyA9IGF3YWl0IHRoaXMuZ2FyZGVuLmdldFNlcnZpY2VzKHRoaXMuc2VydmljZS5jb25maWcuZGVwZW5kZW5jaWVzKVxuXG4gICAgbGV0IHJlc3VsdDogU2VydmljZVN0YXR1c1xuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmdhcmRlbi5hY3Rpb25zLmRlcGxveVNlcnZpY2Uoe1xuICAgICAgICBzZXJ2aWNlOiB0aGlzLnNlcnZpY2UsXG4gICAgICAgIHJ1bnRpbWVDb250ZXh0OiBhd2FpdCBwcmVwYXJlUnVudGltZUNvbnRleHQodGhpcy5nYXJkZW4sIHRoaXMuc2VydmljZS5tb2R1bGUsIGRlcGVuZGVuY2llcyksXG4gICAgICAgIGxvZ0VudHJ5LFxuICAgICAgICBmb3JjZTogdGhpcy5mb3JjZSxcbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBsb2dFbnRyeS5zZXRFcnJvcigpXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG5cbiAgICBsb2dFbnRyeS5zZXRTdWNjZXNzKHsgbXNnOiBjaGFsay5ncmVlbihgUmVhZHlgKSwgYXBwZW5kOiB0cnVlIH0pXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXREZXBsb3lUYXNrcyhcbiAgeyBnYXJkZW4sIG1vZHVsZSwgc2VydmljZU5hbWVzLCBmb3JjZSA9IGZhbHNlLCBmb3JjZUJ1aWxkID0gZmFsc2UsIGluY2x1ZGVEZXBlbmRhbnRzID0gZmFsc2UgfTpcbiAgICB7XG4gICAgICBnYXJkZW46IEdhcmRlbiwgbW9kdWxlOiBNb2R1bGUsIHNlcnZpY2VOYW1lcz86IHN0cmluZ1tdIHwgbnVsbCxcbiAgICAgIGZvcmNlPzogYm9vbGVhbiwgZm9yY2VCdWlsZD86IGJvb2xlYW4sIGluY2x1ZGVEZXBlbmRhbnRzPzogYm9vbGVhbixcbiAgICB9LFxuKSB7XG5cbiAgY29uc3QgbW9kdWxlc1RvUHJvY2VzcyA9IGluY2x1ZGVEZXBlbmRhbnRzXG4gICAgPyAoYXdhaXQgd2l0aERlcGVuZGFudHMoZ2FyZGVuLCBbbW9kdWxlXSwgYXdhaXQgY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzKGdhcmRlbikpKVxuICAgIDogW21vZHVsZV1cblxuICBjb25zdCBtb2R1bGVTZXJ2aWNlcyA9IGZsYXR0ZW4oYXdhaXQgQmx1ZWJpcmQubWFwKFxuICAgIG1vZHVsZXNUb1Byb2Nlc3MsXG4gICAgbSA9PiBnYXJkZW4uZ2V0U2VydmljZXMoZ2V0TmFtZXMobS5zZXJ2aWNlQ29uZmlncykpKSlcblxuICBjb25zdCBzZXJ2aWNlc1RvUHJvY2VzcyA9IHNlcnZpY2VOYW1lc1xuICAgID8gbW9kdWxlU2VydmljZXMuZmlsdGVyKHMgPT4gc2VydmljZU5hbWVzLmluY2x1ZGVzKHMubmFtZSkpXG4gICAgOiBtb2R1bGVTZXJ2aWNlc1xuXG4gIHJldHVybiBzZXJ2aWNlc1RvUHJvY2Vzcy5tYXAoc2VydmljZSA9PiBuZXcgRGVwbG95VGFzayh7IGdhcmRlbiwgc2VydmljZSwgZm9yY2UsIGZvcmNlQnVpbGQgfSkpXG59XG4iXX0= diff --git a/garden-service/build/tasks/publish.d.ts b/garden-service/build/tasks/publish.d.ts new file mode 100644 index 00000000000..d1989991371 --- /dev/null +++ b/garden-service/build/tasks/publish.d.ts @@ -0,0 +1,21 @@ +import { BuildTask } from "./build"; +import { Module } from "../types/module"; +import { PublishResult } from "../types/plugin/outputs"; +import { Task } from "../tasks/base"; +import { Garden } from "../garden"; +export interface PublishTaskParams { + garden: Garden; + module: Module; + forceBuild: boolean; +} +export declare class PublishTask extends Task { + type: string; + private module; + private forceBuild; + constructor({ garden, module, forceBuild }: PublishTaskParams); + getDependencies(): Promise; + getName(): string; + getDescription(): string; + process(): Promise; +} +//# sourceMappingURL=publish.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/publish.js b/garden-service/build/tasks/publish.js new file mode 100644 index 00000000000..d644067a18c --- /dev/null +++ b/garden-service/build/tasks/publish.js @@ -0,0 +1,81 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const build_1 = require("./build"); +const base_1 = require("../tasks/base"); +class PublishTask extends base_1.Task { + constructor({ garden, module, forceBuild }) { + super({ garden, version: module.version }); + this.type = "publish"; + this.module = module; + this.forceBuild = forceBuild; + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + if (!this.module.allowPublish) { + return []; + } + return [new build_1.BuildTask({ + garden: this.garden, + module: this.module, + force: this.forceBuild, + })]; + }); + } + getName() { + return this.module.name; + } + getDescription() { + return `publishing module ${this.module.name}`; + } + process() { + return __awaiter(this, void 0, void 0, function* () { + if (!this.module.allowPublish) { + this.garden.log.info({ + section: this.module.name, + msg: "Publishing disabled", + status: "active", + }); + return { published: false }; + } + const logEntry = this.garden.log.info({ + section: this.module.name, + msg: "Publishing", + status: "active", + }); + let result; + try { + result = yield this.garden.actions.publishModule({ module: this.module, logEntry }); + } + catch (err) { + logEntry.setError(); + throw err; + } + if (result.published) { + logEntry.setSuccess({ msg: chalk_1.default.green(result.message || `Ready`), append: true }); + } + else { + logEntry.setWarn({ msg: result.message, append: true }); + } + return result; + }); + } +} +exports.PublishTask = PublishTask; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRhc2tzL3B1Ymxpc2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUF5QjtBQUN6QixtQ0FBbUM7QUFHbkMsd0NBQW9DO0FBU3BDLE1BQWEsV0FBWSxTQUFRLFdBQUk7SUFNbkMsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFxQjtRQUMzRCxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBTjVDLFNBQUksR0FBRyxTQUFTLENBQUE7UUFPZCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtJQUM5QixDQUFDO0lBRUssZUFBZTs7WUFDbkIsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFO2dCQUM3QixPQUFPLEVBQUUsQ0FBQTthQUNWO1lBQ0QsT0FBTyxDQUFDLElBQUksaUJBQVMsQ0FBQztvQkFDcEIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO29CQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07b0JBQ25CLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVTtpQkFDdkIsQ0FBQyxDQUFDLENBQUE7UUFDTCxDQUFDO0tBQUE7SUFFRCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQTtJQUN6QixDQUFDO0lBRUQsY0FBYztRQUNaLE9BQU8scUJBQXFCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDaEQsQ0FBQztJQUVLLE9BQU87O1lBQ1gsSUFBSSxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsWUFBWSxFQUFFO2dCQUM3QixJQUFJLENBQUMsTUFBTSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUM7b0JBQ25CLE9BQU8sRUFBRSxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUk7b0JBQ3pCLEdBQUcsRUFBRSxxQkFBcUI7b0JBQzFCLE1BQU0sRUFBRSxRQUFRO2lCQUNqQixDQUFDLENBQUE7Z0JBQ0YsT0FBTyxFQUFFLFNBQVMsRUFBRSxLQUFLLEVBQUUsQ0FBQTthQUM1QjtZQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztnQkFDcEMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSTtnQkFDekIsR0FBRyxFQUFFLFlBQVk7Z0JBQ2pCLE1BQU0sRUFBRSxRQUFRO2FBQ2pCLENBQUMsQ0FBQTtZQUVGLElBQUksTUFBcUIsQ0FBQTtZQUN6QixJQUFJO2dCQUNGLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLENBQUMsTUFBTSxFQUFFLFFBQVEsRUFBRSxDQUFDLENBQUE7YUFDcEY7WUFBQyxPQUFPLEdBQUcsRUFBRTtnQkFDWixRQUFRLENBQUMsUUFBUSxFQUFFLENBQUE7Z0JBQ25CLE1BQU0sR0FBRyxDQUFBO2FBQ1Y7WUFFRCxJQUFJLE1BQU0sQ0FBQyxTQUFTLEVBQUU7Z0JBQ3BCLFFBQVEsQ0FBQyxVQUFVLENBQUMsRUFBRSxHQUFHLEVBQUUsZUFBSyxDQUFDLEtBQUssQ0FBQyxNQUFNLENBQUMsT0FBTyxJQUFJLE9BQU8sQ0FBQyxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUsQ0FBQyxDQUFBO2FBQ25GO2lCQUFNO2dCQUNMLFFBQVEsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsTUFBTSxDQUFDLE9BQU8sRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFLENBQUMsQ0FBQTthQUN4RDtZQUVELE9BQU8sTUFBTSxDQUFBO1FBQ2YsQ0FBQztLQUFBO0NBQ0Y7QUEvREQsa0NBK0RDIiwiZmlsZSI6InRhc2tzL3B1Ymxpc2guanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IGNoYWxrIGZyb20gXCJjaGFsa1wiXG5pbXBvcnQgeyBCdWlsZFRhc2sgfSBmcm9tIFwiLi9idWlsZFwiXG5pbXBvcnQgeyBNb2R1bGUgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7IFB1Ymxpc2hSZXN1bHQgfSBmcm9tIFwiLi4vdHlwZXMvcGx1Z2luL291dHB1dHNcIlxuaW1wb3J0IHsgVGFzayB9IGZyb20gXCIuLi90YXNrcy9iYXNlXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuXG5leHBvcnQgaW50ZXJmYWNlIFB1Ymxpc2hUYXNrUGFyYW1zIHtcbiAgZ2FyZGVuOiBHYXJkZW5cbiAgbW9kdWxlOiBNb2R1bGVcbiAgZm9yY2VCdWlsZDogYm9vbGVhblxufVxuXG5leHBvcnQgY2xhc3MgUHVibGlzaFRhc2sgZXh0ZW5kcyBUYXNrIHtcbiAgdHlwZSA9IFwicHVibGlzaFwiXG5cbiAgcHJpdmF0ZSBtb2R1bGU6IE1vZHVsZVxuICBwcml2YXRlIGZvcmNlQnVpbGQ6IGJvb2xlYW5cblxuICBjb25zdHJ1Y3Rvcih7IGdhcmRlbiwgbW9kdWxlLCBmb3JjZUJ1aWxkIH06IFB1Ymxpc2hUYXNrUGFyYW1zKSB7XG4gICAgc3VwZXIoeyBnYXJkZW4sIHZlcnNpb246IG1vZHVsZS52ZXJzaW9uIH0pXG4gICAgdGhpcy5tb2R1bGUgPSBtb2R1bGVcbiAgICB0aGlzLmZvcmNlQnVpbGQgPSBmb3JjZUJ1aWxkXG4gIH1cblxuICBhc3luYyBnZXREZXBlbmRlbmNpZXMoKSB7XG4gICAgaWYgKCF0aGlzLm1vZHVsZS5hbGxvd1B1Ymxpc2gpIHtcbiAgICAgIHJldHVybiBbXVxuICAgIH1cbiAgICByZXR1cm4gW25ldyBCdWlsZFRhc2soe1xuICAgICAgZ2FyZGVuOiB0aGlzLmdhcmRlbixcbiAgICAgIG1vZHVsZTogdGhpcy5tb2R1bGUsXG4gICAgICBmb3JjZTogdGhpcy5mb3JjZUJ1aWxkLFxuICAgIH0pXVxuICB9XG5cbiAgZ2V0TmFtZSgpIHtcbiAgICByZXR1cm4gdGhpcy5tb2R1bGUubmFtZVxuICB9XG5cbiAgZ2V0RGVzY3JpcHRpb24oKSB7XG4gICAgcmV0dXJuIGBwdWJsaXNoaW5nIG1vZHVsZSAke3RoaXMubW9kdWxlLm5hbWV9YFxuICB9XG5cbiAgYXN5bmMgcHJvY2VzcygpOiBQcm9taXNlPFB1Ymxpc2hSZXN1bHQ+IHtcbiAgICBpZiAoIXRoaXMubW9kdWxlLmFsbG93UHVibGlzaCkge1xuICAgICAgdGhpcy5nYXJkZW4ubG9nLmluZm8oe1xuICAgICAgICBzZWN0aW9uOiB0aGlzLm1vZHVsZS5uYW1lLFxuICAgICAgICBtc2c6IFwiUHVibGlzaGluZyBkaXNhYmxlZFwiLFxuICAgICAgICBzdGF0dXM6IFwiYWN0aXZlXCIsXG4gICAgICB9KVxuICAgICAgcmV0dXJuIHsgcHVibGlzaGVkOiBmYWxzZSB9XG4gICAgfVxuXG4gICAgY29uc3QgbG9nRW50cnkgPSB0aGlzLmdhcmRlbi5sb2cuaW5mbyh7XG4gICAgICBzZWN0aW9uOiB0aGlzLm1vZHVsZS5uYW1lLFxuICAgICAgbXNnOiBcIlB1Ymxpc2hpbmdcIixcbiAgICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgICB9KVxuXG4gICAgbGV0IHJlc3VsdDogUHVibGlzaFJlc3VsdFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmdhcmRlbi5hY3Rpb25zLnB1Ymxpc2hNb2R1bGUoeyBtb2R1bGU6IHRoaXMubW9kdWxlLCBsb2dFbnRyeSB9KVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nRW50cnkuc2V0RXJyb3IoKVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5wdWJsaXNoZWQpIHtcbiAgICAgIGxvZ0VudHJ5LnNldFN1Y2Nlc3MoeyBtc2c6IGNoYWxrLmdyZWVuKHJlc3VsdC5tZXNzYWdlIHx8IGBSZWFkeWApLCBhcHBlbmQ6IHRydWUgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgbG9nRW50cnkuc2V0V2Fybih7IG1zZzogcmVzdWx0Lm1lc3NhZ2UsIGFwcGVuZDogdHJ1ZSB9KVxuICAgIH1cblxuICAgIHJldHVybiByZXN1bHRcbiAgfVxufVxuIl19 diff --git a/garden-service/build/tasks/push.d.ts b/garden-service/build/tasks/push.d.ts new file mode 100644 index 00000000000..b04b46dd3d8 --- /dev/null +++ b/garden-service/build/tasks/push.d.ts @@ -0,0 +1,21 @@ +import { BuildTask } from "./build"; +import { Module } from "../types/module"; +import { PushResult } from "../types/plugin/outputs"; +import { Task } from "../tasks/base"; +import { Garden } from "../garden"; +export interface PushTaskParams { + garden: Garden; + module: Module; + forceBuild: boolean; +} +export declare class PushTask extends Task { + type: string; + private module; + private forceBuild; + constructor({ garden, module, forceBuild }: PushTaskParams); + getDependencies(): Promise; + getName(): string; + getDescription(): string; + process(): Promise; +} +//# sourceMappingURL=push.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/push.js b/garden-service/build/tasks/push.js new file mode 100644 index 00000000000..a92625bcac7 --- /dev/null +++ b/garden-service/build/tasks/push.js @@ -0,0 +1,80 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chalk_1 = require("chalk"); +const build_1 = require("./build"); +const base_1 = require("../tasks/base"); +class PushTask extends base_1.Task { + constructor({ garden, module, forceBuild }) { + super({ garden, version: module.version }); + this.type = "push"; + this.module = module; + this.forceBuild = forceBuild; + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + return [new build_1.BuildTask({ + garden: this.garden, + module: this.module, + force: this.forceBuild, + })]; + }); + } + getName() { + return this.module.name; + } + getDescription() { + return `pushing module ${this.module.name}`; + } + process() { + return __awaiter(this, void 0, void 0, function* () { + // avoid logging stuff if there is no push handler + const defaultHandler = () => __awaiter(this, void 0, void 0, function* () { return ({ pushed: false }); }); + const handler = yield this.garden.getModuleActionHandler({ + moduleType: this.module.type, + actionType: "pushModule", + defaultHandler, + }); + if (handler === defaultHandler) { + return { pushed: false }; + } + const logEntry = this.garden.log.info({ + section: this.module.name, + msg: "Pushing", + status: "active", + }); + let result; + try { + result = yield this.garden.actions.pushModule({ module: this.module, logEntry }); + } + catch (err) { + logEntry.setError(); + throw err; + } + if (result.pushed) { + logEntry.setSuccess({ msg: chalk_1.default.green(result.message || `Ready`), append: true }); + } + else if (result.message) { + logEntry.setWarn({ msg: result.message, append: true }); + } + return result; + }); + } +} +exports.PushTask = PushTask; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRhc2tzL3B1c2gudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7Ozs7Ozs7OztBQUVILGlDQUF5QjtBQUN6QixtQ0FBbUM7QUFHbkMsd0NBQW9DO0FBU3BDLE1BQWEsUUFBUyxTQUFRLFdBQUk7SUFNaEMsWUFBWSxFQUFFLE1BQU0sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFrQjtRQUN4RCxLQUFLLENBQUMsRUFBRSxNQUFNLEVBQUUsT0FBTyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsQ0FBQyxDQUFBO1FBTjVDLFNBQUksR0FBRyxNQUFNLENBQUE7UUFPWCxJQUFJLENBQUMsTUFBTSxHQUFHLE1BQU0sQ0FBQTtRQUNwQixJQUFJLENBQUMsVUFBVSxHQUFHLFVBQVUsQ0FBQTtJQUM5QixDQUFDO0lBRUssZUFBZTs7WUFDbkIsT0FBTyxDQUFDLElBQUksaUJBQVMsQ0FBQztvQkFDcEIsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNO29CQUNuQixNQUFNLEVBQUUsSUFBSSxDQUFDLE1BQU07b0JBQ25CLEtBQUssRUFBRSxJQUFJLENBQUMsVUFBVTtpQkFDdkIsQ0FBQyxDQUFDLENBQUE7UUFDTCxDQUFDO0tBQUE7SUFFRCxPQUFPO1FBQ0wsT0FBTyxJQUFJLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQTtJQUN6QixDQUFDO0lBRUQsY0FBYztRQUNaLE9BQU8sa0JBQWtCLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLENBQUE7SUFDN0MsQ0FBQztJQUVLLE9BQU87O1lBQ1gsa0RBQWtEO1lBQ2xELE1BQU0sY0FBYyxHQUFHLEdBQVMsRUFBRSxnREFBQyxPQUFBLENBQUMsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFLENBQUMsQ0FBQSxHQUFBLENBQUE7WUFDdEQsTUFBTSxPQUFPLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLHNCQUFzQixDQUFDO2dCQUN2RCxVQUFVLEVBQUUsSUFBSSxDQUFDLE1BQU0sQ0FBQyxJQUFJO2dCQUM1QixVQUFVLEVBQUUsWUFBWTtnQkFDeEIsY0FBYzthQUNmLENBQUMsQ0FBQTtZQUVGLElBQUksT0FBTyxLQUFLLGNBQWMsRUFBRTtnQkFDOUIsT0FBTyxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUUsQ0FBQTthQUN6QjtZQUVELE1BQU0sUUFBUSxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQztnQkFDcEMsT0FBTyxFQUFFLElBQUksQ0FBQyxNQUFNLENBQUMsSUFBSTtnQkFDekIsR0FBRyxFQUFFLFNBQVM7Z0JBQ2QsTUFBTSxFQUFFLFFBQVE7YUFDakIsQ0FBQyxDQUFBO1lBRUYsSUFBSSxNQUFrQixDQUFBO1lBQ3RCLElBQUk7Z0JBQ0YsTUFBTSxHQUFHLE1BQU0sSUFBSSxDQUFDLE1BQU0sQ0FBQyxPQUFPLENBQUMsVUFBVSxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksQ0FBQyxNQUFNLEVBQUUsUUFBUSxFQUFFLENBQUMsQ0FBQTthQUNqRjtZQUFDLE9BQU8sR0FBRyxFQUFFO2dCQUNaLFFBQVEsQ0FBQyxRQUFRLEVBQUUsQ0FBQTtnQkFDbkIsTUFBTSxHQUFHLENBQUE7YUFDVjtZQUVELElBQUksTUFBTSxDQUFDLE1BQU0sRUFBRTtnQkFDakIsUUFBUSxDQUFDLFVBQVUsQ0FBQyxFQUFFLEdBQUcsRUFBRSxlQUFLLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxPQUFPLElBQUksT0FBTyxDQUFDLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7YUFDbkY7aUJBQU0sSUFBSSxNQUFNLENBQUMsT0FBTyxFQUFFO2dCQUN6QixRQUFRLENBQUMsT0FBTyxDQUFDLEVBQUUsR0FBRyxFQUFFLE1BQU0sQ0FBQyxPQUFPLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUE7YUFDeEQ7WUFFRCxPQUFPLE1BQU0sQ0FBQTtRQUNmLENBQUM7S0FBQTtDQUNGO0FBL0RELDRCQStEQyIsImZpbGUiOiJ0YXNrcy9wdXNoLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgQnVpbGRUYXNrIH0gZnJvbSBcIi4vYnVpbGRcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBQdXNoUmVzdWx0IH0gZnJvbSBcIi4uL3R5cGVzL3BsdWdpbi9vdXRwdXRzXCJcbmltcG9ydCB7IFRhc2sgfSBmcm9tIFwiLi4vdGFza3MvYmFzZVwiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vZ2FyZGVuXCJcblxuZXhwb3J0IGludGVyZmFjZSBQdXNoVGFza1BhcmFtcyB7XG4gIGdhcmRlbjogR2FyZGVuXG4gIG1vZHVsZTogTW9kdWxlXG4gIGZvcmNlQnVpbGQ6IGJvb2xlYW5cbn1cblxuZXhwb3J0IGNsYXNzIFB1c2hUYXNrIGV4dGVuZHMgVGFzayB7XG4gIHR5cGUgPSBcInB1c2hcIlxuXG4gIHByaXZhdGUgbW9kdWxlOiBNb2R1bGVcbiAgcHJpdmF0ZSBmb3JjZUJ1aWxkOiBib29sZWFuXG5cbiAgY29uc3RydWN0b3IoeyBnYXJkZW4sIG1vZHVsZSwgZm9yY2VCdWlsZCB9OiBQdXNoVGFza1BhcmFtcykge1xuICAgIHN1cGVyKHsgZ2FyZGVuLCB2ZXJzaW9uOiBtb2R1bGUudmVyc2lvbiB9KVxuICAgIHRoaXMubW9kdWxlID0gbW9kdWxlXG4gICAgdGhpcy5mb3JjZUJ1aWxkID0gZm9yY2VCdWlsZFxuICB9XG5cbiAgYXN5bmMgZ2V0RGVwZW5kZW5jaWVzKCkge1xuICAgIHJldHVybiBbbmV3IEJ1aWxkVGFzayh7XG4gICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgbW9kdWxlOiB0aGlzLm1vZHVsZSxcbiAgICAgIGZvcmNlOiB0aGlzLmZvcmNlQnVpbGQsXG4gICAgfSldXG4gIH1cblxuICBnZXROYW1lKCkge1xuICAgIHJldHVybiB0aGlzLm1vZHVsZS5uYW1lXG4gIH1cblxuICBnZXREZXNjcmlwdGlvbigpIHtcbiAgICByZXR1cm4gYHB1c2hpbmcgbW9kdWxlICR7dGhpcy5tb2R1bGUubmFtZX1gXG4gIH1cblxuICBhc3luYyBwcm9jZXNzKCk6IFByb21pc2U8UHVzaFJlc3VsdD4ge1xuICAgIC8vIGF2b2lkIGxvZ2dpbmcgc3R1ZmYgaWYgdGhlcmUgaXMgbm8gcHVzaCBoYW5kbGVyXG4gICAgY29uc3QgZGVmYXVsdEhhbmRsZXIgPSBhc3luYyAoKSA9PiAoeyBwdXNoZWQ6IGZhbHNlIH0pXG4gICAgY29uc3QgaGFuZGxlciA9IGF3YWl0IHRoaXMuZ2FyZGVuLmdldE1vZHVsZUFjdGlvbkhhbmRsZXIoe1xuICAgICAgbW9kdWxlVHlwZTogdGhpcy5tb2R1bGUudHlwZSxcbiAgICAgIGFjdGlvblR5cGU6IFwicHVzaE1vZHVsZVwiLFxuICAgICAgZGVmYXVsdEhhbmRsZXIsXG4gICAgfSlcblxuICAgIGlmIChoYW5kbGVyID09PSBkZWZhdWx0SGFuZGxlcikge1xuICAgICAgcmV0dXJuIHsgcHVzaGVkOiBmYWxzZSB9XG4gICAgfVxuXG4gICAgY29uc3QgbG9nRW50cnkgPSB0aGlzLmdhcmRlbi5sb2cuaW5mbyh7XG4gICAgICBzZWN0aW9uOiB0aGlzLm1vZHVsZS5uYW1lLFxuICAgICAgbXNnOiBcIlB1c2hpbmdcIixcbiAgICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgICB9KVxuXG4gICAgbGV0IHJlc3VsdDogUHVzaFJlc3VsdFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmdhcmRlbi5hY3Rpb25zLnB1c2hNb2R1bGUoeyBtb2R1bGU6IHRoaXMubW9kdWxlLCBsb2dFbnRyeSB9KVxuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgbG9nRW50cnkuc2V0RXJyb3IoKVxuICAgICAgdGhyb3cgZXJyXG4gICAgfVxuXG4gICAgaWYgKHJlc3VsdC5wdXNoZWQpIHtcbiAgICAgIGxvZ0VudHJ5LnNldFN1Y2Nlc3MoeyBtc2c6IGNoYWxrLmdyZWVuKHJlc3VsdC5tZXNzYWdlIHx8IGBSZWFkeWApLCBhcHBlbmQ6IHRydWUgfSlcbiAgICB9IGVsc2UgaWYgKHJlc3VsdC5tZXNzYWdlKSB7XG4gICAgICBsb2dFbnRyeS5zZXRXYXJuKHsgbXNnOiByZXN1bHQubWVzc2FnZSwgYXBwZW5kOiB0cnVlIH0pXG4gICAgfVxuXG4gICAgcmV0dXJuIHJlc3VsdFxuICB9XG59XG4iXX0= diff --git a/garden-service/build/tasks/test.d.ts b/garden-service/build/tasks/test.d.ts new file mode 100644 index 00000000000..4a6e5f15245 --- /dev/null +++ b/garden-service/build/tasks/test.d.ts @@ -0,0 +1,26 @@ +import { Module } from "../types/module"; +import { TestConfig } from "../config/test"; +import { TestResult } from "../types/plugin/outputs"; +import { Task, TaskParams } from "../tasks/base"; +import { Garden } from "../garden"; +export interface TestTaskParams { + garden: Garden; + module: Module; + testConfig: TestConfig; + force: boolean; + forceBuild: boolean; +} +export declare class TestTask extends Task { + type: string; + private module; + private testConfig; + private forceBuild; + constructor({ garden, module, testConfig, force, forceBuild, version }: TestTaskParams & TaskParams); + static factory(initArgs: TestTaskParams): Promise; + getDependencies(): Promise; + getName(): string; + getDescription(): string; + process(): Promise; + private getTestResult; +} +//# sourceMappingURL=test.d.ts.map \ No newline at end of file diff --git a/garden-service/build/tasks/test.js b/garden-service/build/tasks/test.js new file mode 100644 index 00000000000..f496f24f375 --- /dev/null +++ b/garden-service/build/tasks/test.js @@ -0,0 +1,146 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const chalk_1 = require("chalk"); +const build_1 = require("./build"); +const deploy_1 = require("./deploy"); +const base_1 = require("../tasks/base"); +const service_1 = require("../types/service"); +class TestError extends Error { + toString() { + return this.message; + } +} +class TestTask extends base_1.Task { + constructor({ garden, module, testConfig, force, forceBuild, version }) { + super({ garden, force, version }); + this.type = "test"; + this.module = module; + this.testConfig = testConfig; + this.force = force; + this.forceBuild = forceBuild; + } + static factory(initArgs) { + return __awaiter(this, void 0, void 0, function* () { + const { garden, module, testConfig } = initArgs; + const version = yield getTestVersion(garden, module, testConfig); + return new TestTask(Object.assign({}, initArgs, { version })); + }); + } + getDependencies() { + return __awaiter(this, void 0, void 0, function* () { + const testResult = yield this.getTestResult(); + if (testResult && testResult.success) { + return []; + } + const services = yield this.garden.getServices(this.testConfig.dependencies); + const deps = [new build_1.BuildTask({ + garden: this.garden, + module: this.module, + force: this.forceBuild, + })]; + for (const service of services) { + deps.push(new deploy_1.DeployTask({ + garden: this.garden, + service, + force: false, + forceBuild: this.forceBuild, + })); + } + return Bluebird.all(deps); + }); + } + getName() { + return `${this.module.name}.${this.testConfig.name}`; + } + getDescription() { + return `running ${this.testConfig.name} tests in module ${this.module.name}`; + } + process() { + return __awaiter(this, void 0, void 0, function* () { + // find out if module has already been tested + const testResult = yield this.getTestResult(); + if (testResult && testResult.success) { + const passedEntry = this.garden.log.info({ + section: this.module.name, + msg: `${this.testConfig.name} tests`, + }); + passedEntry.setSuccess({ msg: chalk_1.default.green("Already passed"), append: true }); + return testResult; + } + const entry = this.garden.log.info({ + section: this.module.name, + msg: `Running ${this.testConfig.name} tests`, + status: "active", + }); + const dependencies = yield getTestDependencies(this.garden, this.testConfig); + const runtimeContext = yield service_1.prepareRuntimeContext(this.garden, this.module, dependencies); + let result; + try { + result = yield this.garden.actions.testModule({ + interactive: false, + module: this.module, + runtimeContext, + silent: true, + testConfig: this.testConfig, + }); + } + catch (err) { + entry.setError(); + throw err; + } + if (result.success) { + entry.setSuccess({ msg: chalk_1.default.green(`Success`), append: true }); + } + else { + entry.setError({ msg: chalk_1.default.red(`Failed!`), append: true }); + throw new TestError(result.output); + } + return result; + }); + } + getTestResult() { + return __awaiter(this, void 0, void 0, function* () { + if (this.force) { + return null; + } + return this.garden.actions.getTestResult({ + module: this.module, + testName: this.testConfig.name, + version: this.version, + }); + }); + } +} +exports.TestTask = TestTask; +function getTestDependencies(garden, testConfig) { + return __awaiter(this, void 0, void 0, function* () { + return garden.getServices(testConfig.dependencies); + }); +} +/** + * Determine the version of the test run, based on the version of the module and each of its dependencies. + */ +function getTestVersion(garden, module, testConfig) { + return __awaiter(this, void 0, void 0, function* () { + const moduleDeps = yield garden.resolveModuleDependencies(module.build.dependencies, testConfig.dependencies); + return garden.resolveVersion(module.name, moduleDeps); + }); +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QkFBeUIsQ0FBQyxNQUFNLENBQUMsS0FBSyxDQUFDLFlBQVksRUFBRSxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUE7UUFDN0csT0FBTyxNQUFNLENBQUMsY0FBYyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsVUFBVSxDQUFDLENBQUE7SUFDdkQsQ0FBQztDQUFBIiwiZmlsZSI6InRhc2tzL3Rlc3QuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL3R5cGVzL21vZHVsZVwiXG5pbXBvcnQgeyBUZXN0Q29uZmlnIH0gZnJvbSBcIi4uL2NvbmZpZy90ZXN0XCJcbmltcG9ydCB7IE1vZHVsZVZlcnNpb24gfSBmcm9tIFwiLi4vdmNzL2Jhc2VcIlxuaW1wb3J0IHsgQnVpbGRUYXNrIH0gZnJvbSBcIi4vYnVpbGRcIlxuaW1wb3J0IHsgRGVwbG95VGFzayB9IGZyb20gXCIuL2RlcGxveVwiXG5pbXBvcnQgeyBUZXN0UmVzdWx0IH0gZnJvbSBcIi4uL3R5cGVzL3BsdWdpbi9vdXRwdXRzXCJcbmltcG9ydCB7IFRhc2ssIFRhc2tQYXJhbXMgfSBmcm9tIFwiLi4vdGFza3MvYmFzZVwiXG5pbXBvcnQgeyBwcmVwYXJlUnVudGltZUNvbnRleHQgfSBmcm9tIFwiLi4vdHlwZXMvc2VydmljZVwiXG5pbXBvcnQgeyBHYXJkZW4gfSBmcm9tIFwiLi4vZ2FyZGVuXCJcblxuY2xhc3MgVGVzdEVycm9yIGV4dGVuZHMgRXJyb3Ige1xuICB0b1N0cmluZygpIHtcbiAgICByZXR1cm4gdGhpcy5tZXNzYWdlXG4gIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBUZXN0VGFza1BhcmFtcyB7XG4gIGdhcmRlbjogR2FyZGVuXG4gIG1vZHVsZTogTW9kdWxlXG4gIHRlc3RDb25maWc6IFRlc3RDb25maWdcbiAgZm9yY2U6IGJvb2xlYW5cbiAgZm9yY2VCdWlsZDogYm9vbGVhblxufVxuXG5leHBvcnQgY2xhc3MgVGVzdFRhc2sgZXh0ZW5kcyBUYXNrIHtcbiAgdHlwZSA9IFwidGVzdFwiXG5cbiAgcHJpdmF0ZSBtb2R1bGU6IE1vZHVsZVxuICBwcml2YXRlIHRlc3RDb25maWc6IFRlc3RDb25maWdcbiAgcHJpdmF0ZSBmb3JjZUJ1aWxkOiBib29sZWFuXG5cbiAgY29uc3RydWN0b3IoeyBnYXJkZW4sIG1vZHVsZSwgdGVzdENvbmZpZywgZm9yY2UsIGZvcmNlQnVpbGQsIHZlcnNpb24gfTogVGVzdFRhc2tQYXJhbXMgJiBUYXNrUGFyYW1zKSB7XG4gICAgc3VwZXIoeyBnYXJkZW4sIGZvcmNlLCB2ZXJzaW9uIH0pXG4gICAgdGhpcy5tb2R1bGUgPSBtb2R1bGVcbiAgICB0aGlzLnRlc3RDb25maWcgPSB0ZXN0Q29uZmlnXG4gICAgdGhpcy5mb3JjZSA9IGZvcmNlXG4gICAgdGhpcy5mb3JjZUJ1aWxkID0gZm9yY2VCdWlsZFxuICB9XG5cbiAgc3RhdGljIGFzeW5jIGZhY3RvcnkoaW5pdEFyZ3M6IFRlc3RUYXNrUGFyYW1zKTogUHJvbWlzZTxUZXN0VGFzaz4ge1xuICAgIGNvbnN0IHsgZ2FyZGVuLCBtb2R1bGUsIHRlc3RDb25maWcgfSA9IGluaXRBcmdzXG4gICAgY29uc3QgdmVyc2lvbiA9IGF3YWl0IGdldFRlc3RWZXJzaW9uKGdhcmRlbiwgbW9kdWxlLCB0ZXN0Q29uZmlnKVxuICAgIHJldHVybiBuZXcgVGVzdFRhc2soeyAuLi5pbml0QXJncywgdmVyc2lvbiB9KVxuICB9XG5cbiAgYXN5bmMgZ2V0RGVwZW5kZW5jaWVzKCkge1xuICAgIGNvbnN0IHRlc3RSZXN1bHQgPSBhd2FpdCB0aGlzLmdldFRlc3RSZXN1bHQoKVxuXG4gICAgaWYgKHRlc3RSZXN1bHQgJiYgdGVzdFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICByZXR1cm4gW11cbiAgICB9XG5cbiAgICBjb25zdCBzZXJ2aWNlcyA9IGF3YWl0IHRoaXMuZ2FyZGVuLmdldFNlcnZpY2VzKHRoaXMudGVzdENvbmZpZy5kZXBlbmRlbmNpZXMpXG5cbiAgICBjb25zdCBkZXBzOiBUYXNrW10gPSBbbmV3IEJ1aWxkVGFzayh7XG4gICAgICBnYXJkZW46IHRoaXMuZ2FyZGVuLFxuICAgICAgbW9kdWxlOiB0aGlzLm1vZHVsZSxcbiAgICAgIGZvcmNlOiB0aGlzLmZvcmNlQnVpbGQsXG4gICAgfSldXG5cbiAgICBmb3IgKGNvbnN0IHNlcnZpY2Ugb2Ygc2VydmljZXMpIHtcbiAgICAgIGRlcHMucHVzaChuZXcgRGVwbG95VGFzayh7XG4gICAgICAgIGdhcmRlbjogdGhpcy5nYXJkZW4sXG4gICAgICAgIHNlcnZpY2UsXG4gICAgICAgIGZvcmNlOiBmYWxzZSxcbiAgICAgICAgZm9yY2VCdWlsZDogdGhpcy5mb3JjZUJ1aWxkLFxuICAgICAgfSkpXG4gICAgfVxuXG4gICAgcmV0dXJuIEJsdWViaXJkLmFsbChkZXBzKVxuICB9XG5cbiAgZ2V0TmFtZSgpIHtcbiAgICByZXR1cm4gYCR7dGhpcy5tb2R1bGUubmFtZX0uJHt0aGlzLnRlc3RDb25maWcubmFtZX1gXG4gIH1cblxuICBnZXREZXNjcmlwdGlvbigpIHtcbiAgICByZXR1cm4gYHJ1bm5pbmcgJHt0aGlzLnRlc3RDb25maWcubmFtZX0gdGVzdHMgaW4gbW9kdWxlICR7dGhpcy5tb2R1bGUubmFtZX1gXG4gIH1cblxuICBhc3luYyBwcm9jZXNzKCk6IFByb21pc2U8VGVzdFJlc3VsdD4ge1xuICAgIC8vIGZpbmQgb3V0IGlmIG1vZHVsZSBoYXMgYWxyZWFkeSBiZWVuIHRlc3RlZFxuICAgIGNvbnN0IHRlc3RSZXN1bHQgPSBhd2FpdCB0aGlzLmdldFRlc3RSZXN1bHQoKVxuXG4gICAgaWYgKHRlc3RSZXN1bHQgJiYgdGVzdFJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICBjb25zdCBwYXNzZWRFbnRyeSA9IHRoaXMuZ2FyZGVuLmxvZy5pbmZvKHtcbiAgICAgICAgc2VjdGlvbjogdGhpcy5tb2R1bGUubmFtZSxcbiAgICAgICAgbXNnOiBgJHt0aGlzLnRlc3RDb25maWcubmFtZX0gdGVzdHNgLFxuICAgICAgfSlcbiAgICAgIHBhc3NlZEVudHJ5LnNldFN1Y2Nlc3MoeyBtc2c6IGNoYWxrLmdyZWVuKFwiQWxyZWFkeSBwYXNzZWRcIiksIGFwcGVuZDogdHJ1ZSB9KVxuICAgICAgcmV0dXJuIHRlc3RSZXN1bHRcbiAgICB9XG5cbiAgICBjb25zdCBlbnRyeSA9IHRoaXMuZ2FyZGVuLmxvZy5pbmZvKHtcbiAgICAgIHNlY3Rpb246IHRoaXMubW9kdWxlLm5hbWUsXG4gICAgICBtc2c6IGBSdW5uaW5nICR7dGhpcy50ZXN0Q29uZmlnLm5hbWV9IHRlc3RzYCxcbiAgICAgIHN0YXR1czogXCJhY3RpdmVcIixcbiAgICB9KVxuXG4gICAgY29uc3QgZGVwZW5kZW5jaWVzID0gYXdhaXQgZ2V0VGVzdERlcGVuZGVuY2llcyh0aGlzLmdhcmRlbiwgdGhpcy50ZXN0Q29uZmlnKVxuICAgIGNvbnN0IHJ1bnRpbWVDb250ZXh0ID0gYXdhaXQgcHJlcGFyZVJ1bnRpbWVDb250ZXh0KHRoaXMuZ2FyZGVuLCB0aGlzLm1vZHVsZSwgZGVwZW5kZW5jaWVzKVxuXG4gICAgbGV0IHJlc3VsdDogVGVzdFJlc3VsdFxuICAgIHRyeSB7XG4gICAgICByZXN1bHQgPSBhd2FpdCB0aGlzLmdhcmRlbi5hY3Rpb25zLnRlc3RNb2R1bGUoe1xuICAgICAgICBpbnRlcmFjdGl2ZTogZmFsc2UsXG4gICAgICAgIG1vZHVsZTogdGhpcy5tb2R1bGUsXG4gICAgICAgIHJ1bnRpbWVDb250ZXh0LFxuICAgICAgICBzaWxlbnQ6IHRydWUsXG4gICAgICAgIHRlc3RDb25maWc6IHRoaXMudGVzdENvbmZpZyxcbiAgICAgIH0pXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBlbnRyeS5zZXRFcnJvcigpXG4gICAgICB0aHJvdyBlcnJcbiAgICB9XG4gICAgaWYgKHJlc3VsdC5zdWNjZXNzKSB7XG4gICAgICBlbnRyeS5zZXRTdWNjZXNzKHsgbXNnOiBjaGFsay5ncmVlbihgU3VjY2Vzc2ApLCBhcHBlbmQ6IHRydWUgfSlcbiAgICB9IGVsc2Uge1xuICAgICAgZW50cnkuc2V0RXJyb3IoeyBtc2c6IGNoYWxrLnJlZChgRmFpbGVkIWApLCBhcHBlbmQ6IHRydWUgfSlcbiAgICAgIHRocm93IG5ldyBUZXN0RXJyb3IocmVzdWx0Lm91dHB1dClcbiAgICB9XG5cbiAgICByZXR1cm4gcmVzdWx0XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGdldFRlc3RSZXN1bHQoKSB7XG4gICAgaWYgKHRoaXMuZm9yY2UpIHtcbiAgICAgIHJldHVybiBudWxsXG4gICAgfVxuXG4gICAgcmV0dXJuIHRoaXMuZ2FyZGVuLmFjdGlvbnMuZ2V0VGVzdFJlc3VsdCh7XG4gICAgICBtb2R1bGU6IHRoaXMubW9kdWxlLFxuICAgICAgdGVzdE5hbWU6IHRoaXMudGVzdENvbmZpZy5uYW1lLFxuICAgICAgdmVyc2lvbjogdGhpcy52ZXJzaW9uLFxuICAgIH0pXG4gIH1cbn1cblxuYXN5bmMgZnVuY3Rpb24gZ2V0VGVzdERlcGVuZGVuY2llcyhnYXJkZW46IEdhcmRlbiwgdGVzdENvbmZpZzogVGVzdENvbmZpZykge1xuICByZXR1cm4gZ2FyZGVuLmdldFNlcnZpY2VzKHRlc3RDb25maWcuZGVwZW5kZW5jaWVzKVxufVxuXG4vKipcbiAqIERldGVybWluZSB0aGUgdmVyc2lvbiBvZiB0aGUgdGVzdCBydW4sIGJhc2VkIG9uIHRoZSB2ZXJzaW9uIG9mIHRoZSBtb2R1bGUgYW5kIGVhY2ggb2YgaXRzIGRlcGVuZGVuY2llcy5cbiAqL1xuYXN5bmMgZnVuY3Rpb24gZ2V0VGVzdFZlcnNpb24oZ2FyZGVuOiBHYXJkZW4sIG1vZHVsZTogTW9kdWxlLCB0ZXN0Q29uZmlnOiBUZXN0Q29uZmlnKTogUHJvbWlzZTxNb2R1bGVWZXJzaW9uPiB7XG4gIGNvbnN0IG1vZHVsZURlcHMgPSBhd2FpdCBnYXJkZW4ucmVzb2x2ZU1vZHVsZURlcGVuZGVuY2llcyhtb2R1bGUuYnVpbGQuZGVwZW5kZW5jaWVzLCB0ZXN0Q29uZmlnLmRlcGVuZGVuY2llcylcbiAgcmV0dXJuIGdhcmRlbi5yZXNvbHZlVmVyc2lvbihtb2R1bGUubmFtZSwgbW9kdWxlRGVwcylcbn1cbiJdfQ== diff --git a/garden-service/build/template-string-parser.js b/garden-service/build/template-string-parser.js new file mode 100644 index 00000000000..4767ce995fc --- /dev/null +++ b/garden-service/build/template-string-parser.js @@ -0,0 +1,960 @@ +/* + * Generated by PEG.js 0.10.0. + * + * http://pegjs.org/ + */ + +"use strict"; + +function peg$subclass(child, parent) { + function ctor() { this.constructor = child; } + ctor.prototype = parent.prototype; + child.prototype = new ctor(); +} + +function peg$SyntaxError(message, expected, found, location) { + this.message = message; + this.expected = expected; + this.found = found; + this.location = location; + this.name = "SyntaxError"; + + if (typeof Error.captureStackTrace === "function") { + Error.captureStackTrace(this, peg$SyntaxError); + } +} + +peg$subclass(peg$SyntaxError, Error); + +peg$SyntaxError.buildMessage = function(expected, found) { + var DESCRIBE_EXPECTATION_FNS = { + literal: function(expectation) { + return "\"" + literalEscape(expectation.text) + "\""; + }, + + "class": function(expectation) { + var escapedParts = "", + i; + + for (i = 0; i < expectation.parts.length; i++) { + escapedParts += expectation.parts[i] instanceof Array + ? classEscape(expectation.parts[i][0]) + "-" + classEscape(expectation.parts[i][1]) + : classEscape(expectation.parts[i]); + } + + return "[" + (expectation.inverted ? "^" : "") + escapedParts + "]"; + }, + + any: function(expectation) { + return "any character"; + }, + + end: function(expectation) { + return "end of input"; + }, + + other: function(expectation) { + return expectation.description; + } + }; + + function hex(ch) { + return ch.charCodeAt(0).toString(16).toUpperCase(); + } + + function literalEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/"/g, '\\"') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function classEscape(s) { + return s + .replace(/\\/g, '\\\\') + .replace(/\]/g, '\\]') + .replace(/\^/g, '\\^') + .replace(/-/g, '\\-') + .replace(/\0/g, '\\0') + .replace(/\t/g, '\\t') + .replace(/\n/g, '\\n') + .replace(/\r/g, '\\r') + .replace(/[\x00-\x0F]/g, function(ch) { return '\\x0' + hex(ch); }) + .replace(/[\x10-\x1F\x7F-\x9F]/g, function(ch) { return '\\x' + hex(ch); }); + } + + function describeExpectation(expectation) { + return DESCRIBE_EXPECTATION_FNS[expectation.type](expectation); + } + + function describeExpected(expected) { + var descriptions = new Array(expected.length), + i, j; + + for (i = 0; i < expected.length; i++) { + descriptions[i] = describeExpectation(expected[i]); + } + + descriptions.sort(); + + if (descriptions.length > 0) { + for (i = 1, j = 1; i < descriptions.length; i++) { + if (descriptions[i - 1] !== descriptions[i]) { + descriptions[j] = descriptions[i]; + j++; + } + } + descriptions.length = j; + } + + switch (descriptions.length) { + case 1: + return descriptions[0]; + + case 2: + return descriptions[0] + " or " + descriptions[1]; + + default: + return descriptions.slice(0, -1).join(", ") + + ", or " + + descriptions[descriptions.length - 1]; + } + } + + function describeFound(found) { + return found ? "\"" + literalEscape(found) + "\"" : "end of input"; + } + + return "Expected " + describeExpected(expected) + " but " + describeFound(found) + " found."; +}; + +function peg$parse(input, options) { + options = options !== void 0 ? options : {}; + + var peg$FAILED = {}, + + peg$startRuleFunctions = { TemplateString: peg$parseTemplateString }, + peg$startRuleFunction = peg$parseTemplateString, + + peg$c0 = function(a, b) { return [...a, ...(b || [])] }, + peg$c1 = function(a, b, c) { return [a, ...b, ...(c || [])] }, + peg$c2 = peg$anyExpectation(), + peg$c3 = function() { return [text()] }, + peg$c4 = function(head, tail) { + const parts = [["", head]].concat(tail).map(p => p[1]) + return options.getKey(parts) + }, + peg$c5 = function(s) { + return options.resolve(s) + }, + peg$c6 = function() { + throw new options.TemplateStringError("Invalid template string: ..." + text()) + }, + peg$c7 = "${", + peg$c8 = peg$literalExpectation("${", false), + peg$c9 = "}", + peg$c10 = peg$literalExpectation("}", false), + peg$c11 = /^[a-zA-Z]/, + peg$c12 = peg$classExpectation([["a", "z"], ["A", "Z"]], false, false), + peg$c13 = /^[a-zA-Z0-9_\-]/, + peg$c14 = peg$classExpectation([["a", "z"], ["A", "Z"], ["0", "9"], "_", "-"], false, false), + peg$c15 = function() { return text() }, + peg$c16 = ".", + peg$c17 = peg$literalExpectation(".", false), + + peg$currPos = 0, + peg$savedPos = 0, + peg$posDetailsCache = [{ line: 1, column: 1 }], + peg$maxFailPos = 0, + peg$maxFailExpected = [], + peg$silentFails = 0, + + peg$result; + + if ("startRule" in options) { + if (!(options.startRule in peg$startRuleFunctions)) { + throw new Error("Can't start parsing from rule \"" + options.startRule + "\"."); + } + + peg$startRuleFunction = peg$startRuleFunctions[options.startRule]; + } + + function text() { + return input.substring(peg$savedPos, peg$currPos); + } + + function location() { + return peg$computeLocation(peg$savedPos, peg$currPos); + } + + function expected(description, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildStructuredError( + [peg$otherExpectation(description)], + input.substring(peg$savedPos, peg$currPos), + location + ); + } + + function error(message, location) { + location = location !== void 0 ? location : peg$computeLocation(peg$savedPos, peg$currPos) + + throw peg$buildSimpleError(message, location); + } + + function peg$literalExpectation(text, ignoreCase) { + return { type: "literal", text: text, ignoreCase: ignoreCase }; + } + + function peg$classExpectation(parts, inverted, ignoreCase) { + return { type: "class", parts: parts, inverted: inverted, ignoreCase: ignoreCase }; + } + + function peg$anyExpectation() { + return { type: "any" }; + } + + function peg$endExpectation() { + return { type: "end" }; + } + + function peg$otherExpectation(description) { + return { type: "other", description: description }; + } + + function peg$computePosDetails(pos) { + var details = peg$posDetailsCache[pos], p; + + if (details) { + return details; + } else { + p = pos - 1; + while (!peg$posDetailsCache[p]) { + p--; + } + + details = peg$posDetailsCache[p]; + details = { + line: details.line, + column: details.column + }; + + while (p < pos) { + if (input.charCodeAt(p) === 10) { + details.line++; + details.column = 1; + } else { + details.column++; + } + + p++; + } + + peg$posDetailsCache[pos] = details; + return details; + } + } + + function peg$computeLocation(startPos, endPos) { + var startPosDetails = peg$computePosDetails(startPos), + endPosDetails = peg$computePosDetails(endPos); + + return { + start: { + offset: startPos, + line: startPosDetails.line, + column: startPosDetails.column + }, + end: { + offset: endPos, + line: endPosDetails.line, + column: endPosDetails.column + } + }; + } + + function peg$fail(expected) { + if (peg$currPos < peg$maxFailPos) { return; } + + if (peg$currPos > peg$maxFailPos) { + peg$maxFailPos = peg$currPos; + peg$maxFailExpected = []; + } + + peg$maxFailExpected.push(expected); + } + + function peg$buildSimpleError(message, location) { + return new peg$SyntaxError(message, null, null, location); + } + + function peg$buildStructuredError(expected, found, location) { + return new peg$SyntaxError( + peg$SyntaxError.buildMessage(expected, found), + expected, + found, + location + ); + } + + function peg$parseTemplateString() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parseFormatString(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parseFormatString(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseTemplateString(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c0(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsePrefix(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseFormatString(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseFormatString(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseTemplateString(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c1(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseInvalidFormatString(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$currPos; + s2 = []; + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + } + if (s2 !== peg$FAILED) { + s1 = input.substring(s1, peg$currPos); + } else { + s1 = s2; + } + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c3(); + } + s0 = s1; + } + } + } + + return s0; + } + + function peg$parseNestedTemplateString() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + s1 = []; + s2 = peg$parseFormatString(); + if (s2 !== peg$FAILED) { + while (s2 !== peg$FAILED) { + s1.push(s2); + s2 = peg$parseFormatString(); + } + } else { + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseNestedTemplateString(); + if (s2 === peg$FAILED) { + s2 = null; + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c0(s1, s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parsePrefix(); + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$parseFormatString(); + if (s3 !== peg$FAILED) { + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$parseFormatString(); + } + } else { + s2 = peg$FAILED; + } + if (s2 !== peg$FAILED) { + s3 = peg$parseNestedTemplateString(); + if (s3 === peg$FAILED) { + s3 = null; + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c1(s1, s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$parseInvalidFormatString(); + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseSuffix(); + if (s1 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c3(); + } + s0 = s1; + } + } + } + + return s0; + } + + function peg$parseFormatString() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$parseFormatStart(); + if (s1 !== peg$FAILED) { + s2 = peg$parseIdentifier(); + if (s2 !== peg$FAILED) { + s3 = []; + s4 = peg$currPos; + s5 = peg$parseKeySeparator(); + if (s5 !== peg$FAILED) { + s6 = peg$parseIdentifier(); + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + while (s4 !== peg$FAILED) { + s3.push(s4); + s4 = peg$currPos; + s5 = peg$parseKeySeparator(); + if (s5 !== peg$FAILED) { + s6 = peg$parseIdentifier(); + if (s6 !== peg$FAILED) { + s5 = [s5, s6]; + s4 = s5; + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } else { + peg$currPos = s4; + s4 = peg$FAILED; + } + } + if (s3 !== peg$FAILED) { + s4 = peg$parseFormatEnd(); + if (s4 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c4(s2, s3); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + if (s0 === peg$FAILED) { + s0 = peg$currPos; + s1 = peg$parseFormatStart(); + if (s1 !== peg$FAILED) { + s2 = peg$parseNestedTemplateString(); + if (s2 !== peg$FAILED) { + s3 = peg$parseFormatEnd(); + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c5(s2); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } + + return s0; + } + + function peg$parseInvalidFormatString() { + var s0, s1, s2, s3, s4; + + s0 = peg$currPos; + s1 = peg$parsePrefix(); + if (s1 === peg$FAILED) { + s1 = null; + } + if (s1 !== peg$FAILED) { + s2 = peg$parseFormatStart(); + if (s2 !== peg$FAILED) { + s3 = []; + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + while (s4 !== peg$FAILED) { + s3.push(s4); + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c6(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseFormatStart() { + var s0; + + if (input.substr(peg$currPos, 2) === peg$c7) { + s0 = peg$c7; + peg$currPos += 2; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c8); } + } + + return s0; + } + + function peg$parseFormatEnd() { + var s0; + + if (input.charCodeAt(peg$currPos) === 125) { + s0 = peg$c9; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c10); } + } + + return s0; + } + + function peg$parseIdentifier() { + var s0, s1, s2, s3; + + s0 = peg$currPos; + if (peg$c11.test(input.charAt(peg$currPos))) { + s1 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s1 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c12); } + } + if (s1 !== peg$FAILED) { + s2 = []; + if (peg$c13.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c14); } + } + while (s3 !== peg$FAILED) { + s2.push(s3); + if (peg$c13.test(input.charAt(peg$currPos))) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c14); } + } + } + if (s2 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseKeySeparator() { + var s0; + + if (input.charCodeAt(peg$currPos) === 46) { + s0 = peg$c16; + peg$currPos++; + } else { + s0 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c17); } + } + + return s0; + } + + function peg$parsePrefix() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parseFormatStart(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parseFormatStart(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = void 0; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parseFormatStart(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = void 0; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + function peg$parseSuffix() { + var s0, s1, s2, s3, s4, s5, s6; + + s0 = peg$currPos; + s1 = peg$currPos; + peg$silentFails++; + s2 = peg$parseFormatEnd(); + peg$silentFails--; + if (s2 === peg$FAILED) { + s1 = void 0; + } else { + peg$currPos = s1; + s1 = peg$FAILED; + } + if (s1 !== peg$FAILED) { + s2 = []; + s3 = peg$currPos; + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parseFormatEnd(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = void 0; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + while (s3 !== peg$FAILED) { + s2.push(s3); + s3 = peg$currPos; + if (input.length > peg$currPos) { + s4 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s4 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s4 !== peg$FAILED) { + s5 = peg$currPos; + peg$silentFails++; + s6 = peg$parseFormatEnd(); + peg$silentFails--; + if (s6 === peg$FAILED) { + s5 = void 0; + } else { + peg$currPos = s5; + s5 = peg$FAILED; + } + if (s5 !== peg$FAILED) { + s4 = [s4, s5]; + s3 = s4; + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } else { + peg$currPos = s3; + s3 = peg$FAILED; + } + } + if (s2 !== peg$FAILED) { + if (input.length > peg$currPos) { + s3 = input.charAt(peg$currPos); + peg$currPos++; + } else { + s3 = peg$FAILED; + if (peg$silentFails === 0) { peg$fail(peg$c2); } + } + if (s3 !== peg$FAILED) { + peg$savedPos = s0; + s1 = peg$c15(); + s0 = s1; + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + } else { + peg$currPos = s0; + s0 = peg$FAILED; + } + + return s0; + } + + peg$result = peg$startRuleFunction(); + + if (peg$result !== peg$FAILED && peg$currPos === input.length) { + return peg$result; + } else { + if (peg$result !== peg$FAILED && peg$currPos < input.length) { + peg$fail(peg$endExpectation()); + } + + throw peg$buildStructuredError( + peg$maxFailExpected, + peg$maxFailPos < input.length ? input.charAt(peg$maxFailPos) : null, + peg$maxFailPos < input.length + ? peg$computeLocation(peg$maxFailPos, peg$maxFailPos + 1) + : peg$computeLocation(peg$maxFailPos, peg$maxFailPos) + ); + } +} + +module.exports = { + SyntaxError: peg$SyntaxError, + parse: peg$parse +}; diff --git a/garden-service/build/template-string.d.ts b/garden-service/build/template-string.d.ts new file mode 100644 index 00000000000..cba75cddd3d --- /dev/null +++ b/garden-service/build/template-string.d.ts @@ -0,0 +1,16 @@ +import { ConfigContext } from "./config/config-context"; +export declare type StringOrStringPromise = Promise | string; +/** + * Parse and resolve a templated string, with the given context. The template format is similar to native JS templated + * strings but only supports simple lookups from the given context, e.g. "prefix-${nested.key}-suffix", and not + * arbitrary JS code. + * + * The context should be a ConfigContext instance. The optional `stack` parameter is used to detect circular + * dependencies when resolving context variables. + */ +export declare function resolveTemplateString(string: string, context: ConfigContext, stack?: string[]): Promise; +/** + * Recursively parses and resolves all templated strings in the given object. + */ +export declare function resolveTemplateStrings(obj: T, context: ConfigContext): Promise; +//# sourceMappingURL=template-string.d.ts.map \ No newline at end of file diff --git a/garden-service/build/template-string.js b/garden-service/build/template-string.js new file mode 100644 index 00000000000..53f4e359cff --- /dev/null +++ b/garden-service/build/template-string.js @@ -0,0 +1,84 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const fs_extra_1 = require("fs-extra"); +const path_1 = require("path"); +const Bluebird = require("bluebird"); +const util_1 = require("./util/util"); +const exceptions_1 = require("./exceptions"); +class TemplateStringError extends exceptions_1.GardenBaseError { + constructor() { + super(...arguments); + this.type = "template-string"; + } +} +let _parser; +function getParser() { + return __awaiter(this, void 0, void 0, function* () { + if (!_parser) { + try { + _parser = require("./template-string-parser"); + } + catch (_err) { + // fallback for when running with ts-node or mocha + const peg = require("pegjs"); + const pegFilePath = path_1.resolve(__dirname, "template-string-parser.pegjs"); + const grammar = yield fs_extra_1.readFile(pegFilePath); + _parser = peg.generate(grammar.toString(), { trace: false }); + } + } + return _parser; + }); +} +/** + * Parse and resolve a templated string, with the given context. The template format is similar to native JS templated + * strings but only supports simple lookups from the given context, e.g. "prefix-${nested.key}-suffix", and not + * arbitrary JS code. + * + * The context should be a ConfigContext instance. The optional `stack` parameter is used to detect circular + * dependencies when resolving context variables. + */ +function resolveTemplateString(string, context, stack) { + return __awaiter(this, void 0, void 0, function* () { + const parser = yield getParser(); + const parsed = parser.parse(string, { + getKey: (key) => __awaiter(this, void 0, void 0, function* () { return context.resolve({ key, nodePath: [], stack }); }), + // need this to allow nested template strings + resolve: (parts) => __awaiter(this, void 0, void 0, function* () { + const s = (yield Bluebird.all(parts)).join(""); + return resolveTemplateString(`\$\{${s}\}`, context, stack); + }), + TemplateStringError, + }); + const resolved = yield Bluebird.all(parsed); + return resolved.join(""); + }); +} +exports.resolveTemplateString = resolveTemplateString; +/** + * Recursively parses and resolves all templated strings in the given object. + */ +function resolveTemplateStrings(obj, context) { + return __awaiter(this, void 0, void 0, function* () { + return util_1.asyncDeepMap(obj, (v) => typeof v === "string" ? resolveTemplateString(v, context) : v, + // need to iterate sequentially to catch potential circular dependencies + { concurrency: 1 }); + }); +} +exports.resolveTemplateStrings = resolveTemplateStrings; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInRlbXBsYXRlLXN0cmluZy50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsdUNBQW1DO0FBQ25DLCtCQUE4QjtBQUM5QixxQ0FBcUM7QUFDckMsc0NBQTBDO0FBQzFDLDZDQUE4QztBQUs5QyxNQUFNLG1CQUFvQixTQUFRLDRCQUFlO0lBQWpEOztRQUNFLFNBQUksR0FBRyxpQkFBaUIsQ0FBQTtJQUMxQixDQUFDO0NBQUE7QUFFRCxJQUFJLE9BQVksQ0FBQTtBQUVoQixTQUFlLFNBQVM7O1FBQ3RCLElBQUksQ0FBQyxPQUFPLEVBQUU7WUFDWixJQUFJO2dCQUNGLE9BQU8sR0FBRyxPQUFPLENBQUMsMEJBQTBCLENBQUMsQ0FBQTthQUM5QztZQUFDLE9BQU8sSUFBSSxFQUFFO2dCQUNiLGtEQUFrRDtnQkFDbEQsTUFBTSxHQUFHLEdBQUcsT0FBTyxDQUFDLE9BQU8sQ0FBQyxDQUFBO2dCQUM1QixNQUFNLFdBQVcsR0FBRyxjQUFPLENBQUMsU0FBUyxFQUFFLDhCQUE4QixDQUFDLENBQUE7Z0JBQ3RFLE1BQU0sT0FBTyxHQUFHLE1BQU0sbUJBQVEsQ0FBQyxXQUFXLENBQUMsQ0FBQTtnQkFDM0MsT0FBTyxHQUFHLEdBQUcsQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLFFBQVEsRUFBRSxFQUFFLEVBQUUsS0FBSyxFQUFFLEtBQUssRUFBRSxDQUFDLENBQUE7YUFDN0Q7U0FDRjtRQUVELE9BQU8sT0FBTyxDQUFBO0lBQ2hCLENBQUM7Q0FBQTtBQUVEOzs7Ozs7O0dBT0c7QUFDSCxTQUFzQixxQkFBcUIsQ0FBQyxNQUFjLEVBQUUsT0FBc0IsRUFBRSxLQUFnQjs7UUFDbEcsTUFBTSxNQUFNLEdBQUcsTUFBTSxTQUFTLEVBQUUsQ0FBQTtRQUNoQyxNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLE1BQU0sRUFBRTtZQUNsQyxNQUFNLEVBQUUsQ0FBTyxHQUFhLEVBQUUsRUFBRSxnREFBQyxPQUFBLE9BQU8sQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLEVBQUUsUUFBUSxFQUFFLEVBQUUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFBLEdBQUE7WUFDOUUsNkNBQTZDO1lBQzdDLE9BQU8sRUFBRSxDQUFPLEtBQThCLEVBQUUsRUFBRTtnQkFDaEQsTUFBTSxDQUFDLEdBQUcsQ0FBQyxNQUFNLFFBQVEsQ0FBQyxHQUFHLENBQUMsS0FBSyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7Z0JBQzlDLE9BQU8scUJBQXFCLENBQUMsT0FBTyxDQUFDLElBQUksRUFBRSxPQUFPLEVBQUUsS0FBSyxDQUFDLENBQUE7WUFDNUQsQ0FBQyxDQUFBO1lBQ0QsbUJBQW1CO1NBQ3BCLENBQUMsQ0FBQTtRQUVGLE1BQU0sUUFBUSxHQUFHLE1BQU0sUUFBUSxDQUFDLEdBQUcsQ0FBQyxNQUFNLENBQUMsQ0FBQTtRQUMzQyxPQUFPLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLENBQUE7SUFDMUIsQ0FBQztDQUFBO0FBZEQsc0RBY0M7QUFFRDs7R0FFRztBQUNILFNBQXNCLHNCQUFzQixDQUFtQixHQUFNLEVBQUUsT0FBc0I7O1FBQzNGLE9BQU8sbUJBQVksQ0FDakIsR0FBRyxFQUNILENBQUMsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxPQUFPLENBQUMsS0FBSyxRQUFRLENBQUMsQ0FBQyxDQUFDLHFCQUFxQixDQUFDLENBQUMsRUFBRSxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQztRQUNwRSx3RUFBd0U7UUFDeEUsRUFBRSxXQUFXLEVBQUUsQ0FBQyxFQUFFLENBQ25CLENBQUE7SUFDSCxDQUFDO0NBQUE7QUFQRCx3REFPQyIsImZpbGUiOiJ0ZW1wbGF0ZS1zdHJpbmcuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgcmVhZEZpbGUgfSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgcmVzb2x2ZSB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCBCbHVlYmlyZCA9IHJlcXVpcmUoXCJibHVlYmlyZFwiKVxuaW1wb3J0IHsgYXN5bmNEZWVwTWFwIH0gZnJvbSBcIi4vdXRpbC91dGlsXCJcbmltcG9ydCB7IEdhcmRlbkJhc2VFcnJvciB9IGZyb20gXCIuL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgQ29uZmlnQ29udGV4dCB9IGZyb20gXCIuL2NvbmZpZy9jb25maWctY29udGV4dFwiXG5cbmV4cG9ydCB0eXBlIFN0cmluZ09yU3RyaW5nUHJvbWlzZSA9IFByb21pc2U8c3RyaW5nPiB8IHN0cmluZ1xuXG5jbGFzcyBUZW1wbGF0ZVN0cmluZ0Vycm9yIGV4dGVuZHMgR2FyZGVuQmFzZUVycm9yIHtcbiAgdHlwZSA9IFwidGVtcGxhdGUtc3RyaW5nXCJcbn1cblxubGV0IF9wYXJzZXI6IGFueVxuXG5hc3luYyBmdW5jdGlvbiBnZXRQYXJzZXIoKSB7XG4gIGlmICghX3BhcnNlcikge1xuICAgIHRyeSB7XG4gICAgICBfcGFyc2VyID0gcmVxdWlyZShcIi4vdGVtcGxhdGUtc3RyaW5nLXBhcnNlclwiKVxuICAgIH0gY2F0Y2ggKF9lcnIpIHtcbiAgICAgIC8vIGZhbGxiYWNrIGZvciB3aGVuIHJ1bm5pbmcgd2l0aCB0cy1ub2RlIG9yIG1vY2hhXG4gICAgICBjb25zdCBwZWcgPSByZXF1aXJlKFwicGVnanNcIilcbiAgICAgIGNvbnN0IHBlZ0ZpbGVQYXRoID0gcmVzb2x2ZShfX2Rpcm5hbWUsIFwidGVtcGxhdGUtc3RyaW5nLXBhcnNlci5wZWdqc1wiKVxuICAgICAgY29uc3QgZ3JhbW1hciA9IGF3YWl0IHJlYWRGaWxlKHBlZ0ZpbGVQYXRoKVxuICAgICAgX3BhcnNlciA9IHBlZy5nZW5lcmF0ZShncmFtbWFyLnRvU3RyaW5nKCksIHsgdHJhY2U6IGZhbHNlIH0pXG4gICAgfVxuICB9XG5cbiAgcmV0dXJuIF9wYXJzZXJcbn1cblxuLyoqXG4gKiBQYXJzZSBhbmQgcmVzb2x2ZSBhIHRlbXBsYXRlZCBzdHJpbmcsIHdpdGggdGhlIGdpdmVuIGNvbnRleHQuIFRoZSB0ZW1wbGF0ZSBmb3JtYXQgaXMgc2ltaWxhciB0byBuYXRpdmUgSlMgdGVtcGxhdGVkXG4gKiBzdHJpbmdzIGJ1dCBvbmx5IHN1cHBvcnRzIHNpbXBsZSBsb29rdXBzIGZyb20gdGhlIGdpdmVuIGNvbnRleHQsIGUuZy4gXCJwcmVmaXgtJHtuZXN0ZWQua2V5fS1zdWZmaXhcIiwgYW5kIG5vdFxuICogYXJiaXRyYXJ5IEpTIGNvZGUuXG4gKlxuICogVGhlIGNvbnRleHQgc2hvdWxkIGJlIGEgQ29uZmlnQ29udGV4dCBpbnN0YW5jZS4gVGhlIG9wdGlvbmFsIGBzdGFja2AgcGFyYW1ldGVyIGlzIHVzZWQgdG8gZGV0ZWN0IGNpcmN1bGFyXG4gKiBkZXBlbmRlbmNpZXMgd2hlbiByZXNvbHZpbmcgY29udGV4dCB2YXJpYWJsZXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlVGVtcGxhdGVTdHJpbmcoc3RyaW5nOiBzdHJpbmcsIGNvbnRleHQ6IENvbmZpZ0NvbnRleHQsIHN0YWNrPzogc3RyaW5nW10pIHtcbiAgY29uc3QgcGFyc2VyID0gYXdhaXQgZ2V0UGFyc2VyKClcbiAgY29uc3QgcGFyc2VkID0gcGFyc2VyLnBhcnNlKHN0cmluZywge1xuICAgIGdldEtleTogYXN5bmMgKGtleTogc3RyaW5nW10pID0+IGNvbnRleHQucmVzb2x2ZSh7IGtleSwgbm9kZVBhdGg6IFtdLCBzdGFjayB9KSxcbiAgICAvLyBuZWVkIHRoaXMgdG8gYWxsb3cgbmVzdGVkIHRlbXBsYXRlIHN0cmluZ3NcbiAgICByZXNvbHZlOiBhc3luYyAocGFydHM6IFN0cmluZ09yU3RyaW5nUHJvbWlzZVtdKSA9PiB7XG4gICAgICBjb25zdCBzID0gKGF3YWl0IEJsdWViaXJkLmFsbChwYXJ0cykpLmpvaW4oXCJcIilcbiAgICAgIHJldHVybiByZXNvbHZlVGVtcGxhdGVTdHJpbmcoYFxcJFxceyR7c31cXH1gLCBjb250ZXh0LCBzdGFjaylcbiAgICB9LFxuICAgIFRlbXBsYXRlU3RyaW5nRXJyb3IsXG4gIH0pXG5cbiAgY29uc3QgcmVzb2x2ZWQgPSBhd2FpdCBCbHVlYmlyZC5hbGwocGFyc2VkKVxuICByZXR1cm4gcmVzb2x2ZWQuam9pbihcIlwiKVxufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IHBhcnNlcyBhbmQgcmVzb2x2ZXMgYWxsIHRlbXBsYXRlZCBzdHJpbmdzIGluIHRoZSBnaXZlbiBvYmplY3QuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiByZXNvbHZlVGVtcGxhdGVTdHJpbmdzPFQgZXh0ZW5kcyBvYmplY3Q+KG9iajogVCwgY29udGV4dDogQ29uZmlnQ29udGV4dCk6IFByb21pc2U8VD4ge1xuICByZXR1cm4gYXN5bmNEZWVwTWFwKFxuICAgIG9iaixcbiAgICAodikgPT4gdHlwZW9mIHYgPT09IFwic3RyaW5nXCIgPyByZXNvbHZlVGVtcGxhdGVTdHJpbmcodiwgY29udGV4dCkgOiB2LFxuICAgIC8vIG5lZWQgdG8gaXRlcmF0ZSBzZXF1ZW50aWFsbHkgdG8gY2F0Y2ggcG90ZW50aWFsIGNpcmN1bGFyIGRlcGVuZGVuY2llc1xuICAgIHsgY29uY3VycmVuY3k6IDEgfSxcbiAgKVxufVxuIl19 diff --git a/garden-service/build/types/module.d.ts b/garden-service/build/types/module.d.ts new file mode 100644 index 00000000000..666bcf44253 --- /dev/null +++ b/garden-service/build/types/module.d.ts @@ -0,0 +1,30 @@ +import { TestSpec } from "../config/test"; +import { ModuleSpec, ModuleConfig } from "../config/module"; +import { ServiceSpec } from "../config/service"; +import { ModuleVersion } from "../vcs/base"; +import { Garden } from "../garden"; +import { Service } from "./service"; +import * as Joi from "joi"; +export interface BuildCopySpec { + source: string; + target: string; +} +export interface Module extends ModuleConfig { + buildPath: string; + version: ModuleVersion; + services: Service>[]; + serviceNames: string[]; + serviceDependencyNames: string[]; + _ConfigType: ModuleConfig; +} +export declare const moduleSchema: Joi.ObjectSchema; +export interface ModuleMap { + [key: string]: T; +} +export interface ModuleConfigMap { + [key: string]: T; +} +export declare function moduleFromConfig(garden: Garden, config: ModuleConfig): Promise; +export declare function getModuleCacheContext(config: ModuleConfig): string[]; +export declare function getModuleKey(name: string, plugin?: string): string; +//# sourceMappingURL=module.d.ts.map \ No newline at end of file diff --git a/garden-service/build/types/module.js b/garden-service/build/types/module.js new file mode 100644 index 00000000000..2bc99d6c238 --- /dev/null +++ b/garden-service/build/types/module.js @@ -0,0 +1,63 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const util_1 = require("../util/util"); +const module_1 = require("../config/module"); +const base_1 = require("../vcs/base"); +const cache_1 = require("../cache"); +const service_1 = require("./service"); +const Joi = require("joi"); +const common_1 = require("../config/common"); +exports.moduleSchema = module_1.moduleConfigSchema + .keys({ + buildPath: Joi.string() + .required() + .uri({ relativeOnly: true }) + .description("The path to the build staging directory for the module."), + version: base_1.moduleVersionSchema + .required(), + services: common_1.joiArray(Joi.lazy(() => service_1.serviceSchema)) + .required() + .description("A list of all the services that the module provides."), + serviceNames: common_1.joiArray(common_1.joiIdentifier()) + .required() + .description("The names of the services that the module provides."), + serviceDependencyNames: common_1.joiArray(common_1.joiIdentifier()) + .required() + .description("The names of all the services that the services in this module depend on."), +}); +function moduleFromConfig(garden, config) { + return __awaiter(this, void 0, void 0, function* () { + const module = Object.assign({}, config, { buildPath: yield garden.buildDir.buildPath(config.name), version: yield garden.resolveVersion(config.name, config.build.dependencies), services: [], serviceNames: util_1.getNames(config.serviceConfigs), serviceDependencyNames: lodash_1.uniq(lodash_1.flatten(config.serviceConfigs + .map(serviceConfig => serviceConfig.dependencies) + .filter(deps => !!deps))), _ConfigType: config }); + module.services = config.serviceConfigs.map(serviceConfig => service_1.serviceFromConfig(module, serviceConfig)); + return module; + }); +} +exports.moduleFromConfig = moduleFromConfig; +function getModuleCacheContext(config) { + return cache_1.pathToCacheContext(config.path); +} +exports.getModuleCacheContext = getModuleCacheContext; +function getModuleKey(name, plugin) { + return plugin ? `${plugin}--${name}` : name; +} +exports.getModuleKey = getModuleKey; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInR5cGVzL21vZHVsZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiO0FBQUE7Ozs7OztHQU1HOzs7Ozs7Ozs7O0FBRUgsbUNBQXNDO0FBQ3RDLHVDQUF1QztBQUV2Qyw2Q0FBK0U7QUFFL0Usc0NBQWdFO0FBQ2hFLG9DQUE2QztBQUU3Qyx1Q0FBcUU7QUFDckUsMkJBQTBCO0FBQzFCLDZDQUEwRDtBQXNCN0MsUUFBQSxZQUFZLEdBQUcsMkJBQWtCO0tBQzNDLElBQUksQ0FBQztJQUNKLFNBQVMsRUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFO1NBQ3BCLFFBQVEsRUFBRTtTQUNWLEdBQUcsQ0FBTSxFQUFFLFlBQVksRUFBRSxJQUFJLEVBQUUsQ0FBQztTQUNoQyxXQUFXLENBQUMseURBQXlELENBQUM7SUFDekUsT0FBTyxFQUFFLDBCQUFtQjtTQUN6QixRQUFRLEVBQUU7SUFDYixRQUFRLEVBQUUsaUJBQVEsQ0FBQyxHQUFHLENBQUMsSUFBSSxDQUFDLEdBQUcsRUFBRSxDQUFDLHVCQUFhLENBQUMsQ0FBQztTQUM5QyxRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsc0RBQXNELENBQUM7SUFDdEUsWUFBWSxFQUFFLGlCQUFRLENBQUMsc0JBQWEsRUFBRSxDQUFDO1NBQ3BDLFFBQVEsRUFBRTtTQUNWLFdBQVcsQ0FBQyxxREFBcUQsQ0FBQztJQUNyRSxzQkFBc0IsRUFBRSxpQkFBUSxDQUFDLHNCQUFhLEVBQUUsQ0FBQztTQUM5QyxRQUFRLEVBQUU7U0FDVixXQUFXLENBQUMsMkVBQTJFLENBQUM7Q0FDNUYsQ0FBQyxDQUFBO0FBVUosU0FBc0IsZ0JBQWdCLENBQUMsTUFBYyxFQUFFLE1BQW9COztRQUN6RSxNQUFNLE1BQU0scUJBQ1AsTUFBTSxJQUVULFNBQVMsRUFBRSxNQUFNLE1BQU0sQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsRUFDdkQsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsSUFBSSxFQUFFLE1BQU0sQ0FBQyxLQUFLLENBQUMsWUFBWSxDQUFDLEVBRTVFLFFBQVEsRUFBRSxFQUFFLEVBQ1osWUFBWSxFQUFFLGVBQVEsQ0FBQyxNQUFNLENBQUMsY0FBYyxDQUFDLEVBQzdDLHNCQUFzQixFQUFFLGFBQUksQ0FBQyxnQkFBTyxDQUFDLE1BQU0sQ0FBQyxjQUFjO2lCQUN2RCxHQUFHLENBQUMsYUFBYSxDQUFDLEVBQUUsQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDO2lCQUNoRCxNQUFNLENBQUMsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDLENBQUMsSUFBSSxDQUFDLENBQUMsQ0FBQyxFQUUzQixXQUFXLEVBQUUsTUFBTSxHQUNwQixDQUFBO1FBRUQsTUFBTSxDQUFDLFFBQVEsR0FBRyxNQUFNLENBQUMsY0FBYyxDQUFDLEdBQUcsQ0FBQyxhQUFhLENBQUMsRUFBRSxDQUFDLDJCQUFpQixDQUFDLE1BQU0sRUFBRSxhQUFhLENBQUMsQ0FBQyxDQUFBO1FBRXRHLE9BQU8sTUFBTSxDQUFBO0lBQ2YsQ0FBQztDQUFBO0FBbkJELDRDQW1CQztBQUVELFNBQWdCLHFCQUFxQixDQUFDLE1BQW9CO0lBQ3hELE9BQU8sMEJBQWtCLENBQUMsTUFBTSxDQUFDLElBQUksQ0FBQyxDQUFBO0FBQ3hDLENBQUM7QUFGRCxzREFFQztBQUVELFNBQWdCLFlBQVksQ0FBQyxJQUFZLEVBQUUsTUFBZTtJQUN4RCxPQUFPLE1BQU0sQ0FBQyxDQUFDLENBQUMsR0FBRyxNQUFNLEtBQUssSUFBSSxFQUFFLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQTtBQUM3QyxDQUFDO0FBRkQsb0NBRUMiLCJmaWxlIjoidHlwZXMvbW9kdWxlLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGZsYXR0ZW4sIHVuaXEgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCB7IGdldE5hbWVzIH0gZnJvbSBcIi4uL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBUZXN0U3BlYyB9IGZyb20gXCIuLi9jb25maWcvdGVzdFwiXG5pbXBvcnQgeyBNb2R1bGVTcGVjLCBNb2R1bGVDb25maWcsIG1vZHVsZUNvbmZpZ1NjaGVtYSB9IGZyb20gXCIuLi9jb25maWcvbW9kdWxlXCJcbmltcG9ydCB7IFNlcnZpY2VTcGVjIH0gZnJvbSBcIi4uL2NvbmZpZy9zZXJ2aWNlXCJcbmltcG9ydCB7IE1vZHVsZVZlcnNpb24sIG1vZHVsZVZlcnNpb25TY2hlbWEgfSBmcm9tIFwiLi4vdmNzL2Jhc2VcIlxuaW1wb3J0IHsgcGF0aFRvQ2FjaGVDb250ZXh0IH0gZnJvbSBcIi4uL2NhY2hlXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuaW1wb3J0IHsgc2VydmljZUZyb21Db25maWcsIFNlcnZpY2UsIHNlcnZpY2VTY2hlbWEgfSBmcm9tIFwiLi9zZXJ2aWNlXCJcbmltcG9ydCAqIGFzIEpvaSBmcm9tIFwiam9pXCJcbmltcG9ydCB7IGpvaUFycmF5LCBqb2lJZGVudGlmaWVyIH0gZnJvbSBcIi4uL2NvbmZpZy9jb21tb25cIlxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkQ29weVNwZWMge1xuICBzb3VyY2U6IHN0cmluZ1xuICB0YXJnZXQ6IHN0cmluZ1xufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vZHVsZTxcbiAgTSBleHRlbmRzIE1vZHVsZVNwZWMgPSBhbnksXG4gIFMgZXh0ZW5kcyBTZXJ2aWNlU3BlYyA9IGFueSxcbiAgVCBleHRlbmRzIFRlc3RTcGVjID0gYW55LFxuICA+IGV4dGVuZHMgTW9kdWxlQ29uZmlnPE0sIFMsIFQ+IHtcbiAgYnVpbGRQYXRoOiBzdHJpbmdcbiAgdmVyc2lvbjogTW9kdWxlVmVyc2lvblxuXG4gIHNlcnZpY2VzOiBTZXJ2aWNlPE1vZHVsZTxNLCBTLCBUPj5bXVxuICBzZXJ2aWNlTmFtZXM6IHN0cmluZ1tdXG4gIHNlcnZpY2VEZXBlbmRlbmN5TmFtZXM6IHN0cmluZ1tdXG5cbiAgX0NvbmZpZ1R5cGU6IE1vZHVsZUNvbmZpZzxNLCBTLCBUPlxufVxuXG5leHBvcnQgY29uc3QgbW9kdWxlU2NoZW1hID0gbW9kdWxlQ29uZmlnU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBidWlsZFBhdGg6IEpvaS5zdHJpbmcoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC51cmkoPGFueT57IHJlbGF0aXZlT25seTogdHJ1ZSB9KVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHBhdGggdG8gdGhlIGJ1aWxkIHN0YWdpbmcgZGlyZWN0b3J5IGZvciB0aGUgbW9kdWxlLlwiKSxcbiAgICB2ZXJzaW9uOiBtb2R1bGVWZXJzaW9uU2NoZW1hXG4gICAgICAucmVxdWlyZWQoKSxcbiAgICBzZXJ2aWNlczogam9pQXJyYXkoSm9pLmxhenkoKCkgPT4gc2VydmljZVNjaGVtYSkpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSBsaXN0IG9mIGFsbCB0aGUgc2VydmljZXMgdGhhdCB0aGUgbW9kdWxlIHByb3ZpZGVzLlwiKSxcbiAgICBzZXJ2aWNlTmFtZXM6IGpvaUFycmF5KGpvaUlkZW50aWZpZXIoKSlcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZXMgb2YgdGhlIHNlcnZpY2VzIHRoYXQgdGhlIG1vZHVsZSBwcm92aWRlcy5cIiksXG4gICAgc2VydmljZURlcGVuZGVuY3lOYW1lczogam9pQXJyYXkoam9pSWRlbnRpZmllcigpKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lcyBvZiBhbGwgdGhlIHNlcnZpY2VzIHRoYXQgdGhlIHNlcnZpY2VzIGluIHRoaXMgbW9kdWxlIGRlcGVuZCBvbi5cIiksXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlTWFwPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IHtcbiAgW2tleTogc3RyaW5nXTogVFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vZHVsZUNvbmZpZ01hcDxUIGV4dGVuZHMgTW9kdWxlQ29uZmlnID0gTW9kdWxlQ29uZmlnPiB7XG4gIFtrZXk6IHN0cmluZ106IFRcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIG1vZHVsZUZyb21Db25maWcoZ2FyZGVuOiBHYXJkZW4sIGNvbmZpZzogTW9kdWxlQ29uZmlnKTogUHJvbWlzZTxNb2R1bGU+IHtcbiAgY29uc3QgbW9kdWxlOiBNb2R1bGUgPSB7XG4gICAgLi4uY29uZmlnLFxuXG4gICAgYnVpbGRQYXRoOiBhd2FpdCBnYXJkZW4uYnVpbGREaXIuYnVpbGRQYXRoKGNvbmZpZy5uYW1lKSxcbiAgICB2ZXJzaW9uOiBhd2FpdCBnYXJkZW4ucmVzb2x2ZVZlcnNpb24oY29uZmlnLm5hbWUsIGNvbmZpZy5idWlsZC5kZXBlbmRlbmNpZXMpLFxuXG4gICAgc2VydmljZXM6IFtdLFxuICAgIHNlcnZpY2VOYW1lczogZ2V0TmFtZXMoY29uZmlnLnNlcnZpY2VDb25maWdzKSxcbiAgICBzZXJ2aWNlRGVwZW5kZW5jeU5hbWVzOiB1bmlxKGZsYXR0ZW4oY29uZmlnLnNlcnZpY2VDb25maWdzXG4gICAgICAubWFwKHNlcnZpY2VDb25maWcgPT4gc2VydmljZUNvbmZpZy5kZXBlbmRlbmNpZXMpXG4gICAgICAuZmlsdGVyKGRlcHMgPT4gISFkZXBzKSkpLFxuXG4gICAgX0NvbmZpZ1R5cGU6IGNvbmZpZyxcbiAgfVxuXG4gIG1vZHVsZS5zZXJ2aWNlcyA9IGNvbmZpZy5zZXJ2aWNlQ29uZmlncy5tYXAoc2VydmljZUNvbmZpZyA9PiBzZXJ2aWNlRnJvbUNvbmZpZyhtb2R1bGUsIHNlcnZpY2VDb25maWcpKVxuXG4gIHJldHVybiBtb2R1bGVcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE1vZHVsZUNhY2hlQ29udGV4dChjb25maWc6IE1vZHVsZUNvbmZpZykge1xuICByZXR1cm4gcGF0aFRvQ2FjaGVDb250ZXh0KGNvbmZpZy5wYXRoKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0TW9kdWxlS2V5KG5hbWU6IHN0cmluZywgcGx1Z2luPzogc3RyaW5nKSB7XG4gIHJldHVybiBwbHVnaW4gPyBgJHtwbHVnaW59LS0ke25hbWV9YCA6IG5hbWVcbn1cbiJdfQ== diff --git a/garden-service/build/types/plugin/outputs.d.ts b/garden-service/build/types/plugin/outputs.d.ts new file mode 100644 index 00000000000..53c29aa9bfb --- /dev/null +++ b/garden-service/build/types/plugin/outputs.d.ts @@ -0,0 +1,121 @@ +import * as Joi from "joi"; +import { ModuleVersion } from "../../vcs/base"; +import { PrimitiveMap } from "../../config/common"; +import { Module } from "../module"; +import { ServiceStatus } from "../service"; +import { ModuleConfig } from "../../config/module"; +export interface EnvironmentStatus { + ready: boolean; + needUserInput?: boolean; + detail?: any; +} +export declare const environmentStatusSchema: Joi.ObjectSchema; +export declare type EnvironmentStatusMap = { + [key: string]: EnvironmentStatus; +}; +export interface PrepareEnvironmentResult { +} +export declare const prepareEnvironmentResultSchema: Joi.ObjectSchema; +export interface CleanupEnvironmentResult { +} +export declare const cleanupEnvironmentResultSchema: Joi.ObjectSchema; +export interface GetSecretResult { + value: string | null; +} +export declare const getSecretResultSchema: Joi.ObjectSchema; +export interface SetSecretResult { +} +export declare const setSecretResultSchema: Joi.ObjectSchema; +export interface DeleteSecretResult { + found: boolean; +} +export declare const deleteSecretResultSchema: Joi.ObjectSchema; +export interface ExecInServiceResult { + code: number; + output: string; + stdout?: string; + stderr?: string; +} +export declare const execInServiceResultSchema: Joi.ObjectSchema; +export interface ServiceLogEntry { + serviceName: string; + timestamp: Date; + msg: string; +} +export declare const serviceLogEntrySchema: Joi.ObjectSchema; +export interface GetServiceLogsResult { +} +export declare const getServiceLogsResultSchema: Joi.ObjectSchema; +export interface ModuleTypeDescription { + docs: string; + schema: object; +} +export declare const moduleTypeDescriptionSchema: Joi.ObjectSchema; +export declare type ValidateModuleResult = ModuleConfig; +export declare const validateModuleResultSchema: Joi.ObjectSchema; +export interface BuildResult { + buildLog?: string; + fetched?: boolean; + fresh?: boolean; + version?: string; + details?: any; +} +export declare const buildModuleResultSchema: Joi.ObjectSchema; +export interface PushResult { + pushed: boolean; + message?: string; +} +export declare const pushModuleResultSchema: Joi.ObjectSchema; +export interface PublishResult { + published: boolean; + message?: string; +} +export declare const publishModuleResultSchema: Joi.ObjectSchema; +export interface RunResult { + moduleName: string; + command: string[]; + version: ModuleVersion; + success: boolean; + startedAt: Date; + completedAt: Date; + output: string; +} +export declare const runResultSchema: Joi.ObjectSchema; +export interface TestResult extends RunResult { + testName: string; +} +export declare const testResultSchema: Joi.ObjectSchema; +export declare const getTestResultSchema: Joi.ObjectSchema; +export interface BuildStatus { + ready: boolean; +} +export declare const buildStatusSchema: Joi.ObjectSchema; +export interface PluginActionOutputs { + getEnvironmentStatus: Promise; + prepareEnvironment: Promise; + cleanupEnvironment: Promise; + getSecret: Promise; + setSecret: Promise; + deleteSecret: Promise; +} +export interface ServiceActionOutputs { + getServiceStatus: Promise; + deployService: Promise; + deleteService: Promise; + getServiceOutputs: Promise; + execInService: Promise; + getServiceLogs: Promise<{}>; + runService: Promise; +} +export interface ModuleActionOutputs extends ServiceActionOutputs { + describeType: Promise; + validate: Promise; + getBuildStatus: Promise; + build: Promise; + pushModule: Promise; + publishModule: Promise; + runModule: Promise; + testModule: Promise; + getTestResult: Promise; +} +//# sourceMappingURL=outputs.d.ts.map \ No newline at end of file diff --git a/garden-service/build/types/plugin/outputs.js b/garden-service/build/types/plugin/outputs.js new file mode 100644 index 00000000000..dc602ac6121 --- /dev/null +++ b/garden-service/build/types/plugin/outputs.js @@ -0,0 +1,145 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const base_1 = require("../../vcs/base"); +const module_1 = require("../../config/module"); +exports.environmentStatusSchema = Joi.object() + .keys({ + ready: Joi.boolean() + .required() + .description("Set to true if the environment is fully configured for a provider."), + needUserInput: Joi.boolean() + .description("Set to true if the environment needs user input to be initialized, " + + "and thus needs to be initialized via `garden init`."), + detail: Joi.object() + .meta({ extendable: true }) + .description("Use this to include additional information that is specific to the provider."), +}) + .description("Description of an environment's status for a provider."); +exports.prepareEnvironmentResultSchema = Joi.object().keys({}); +exports.cleanupEnvironmentResultSchema = Joi.object().keys({}); +exports.getSecretResultSchema = Joi.object() + .keys({ + value: Joi.string() + .allow(null) + .required() + .description("The config value found for the specified key (as string), or null if not found."), +}); +exports.setSecretResultSchema = Joi.object().keys({}); +exports.deleteSecretResultSchema = Joi.object() + .keys({ + found: Joi.boolean() + .required() + .description("Set to true if the key was deleted, false if it was not found."), +}); +exports.execInServiceResultSchema = Joi.object() + .keys({ + code: Joi.number() + .required() + .description("The exit code of the command executed in the service container."), + output: Joi.string() + .required() + .description("The output of the executed command."), + stdout: Joi.string() + .description("The stdout output of the executed command (if available)."), + stderr: Joi.string() + .description("The stderr output of the executed command (if available)."), +}); +exports.serviceLogEntrySchema = Joi.object() + .keys({ + serviceName: Joi.string() + .required() + .description("The name of the service the log entry originated from."), + timestamp: Joi.date() + .required() + .description("The time when the log entry was generated by the service."), + msg: Joi.string() + .required() + .description("The content of the log entry."), +}) + .description("A log entry returned by a getServiceLogs action handler."); +exports.getServiceLogsResultSchema = Joi.object().keys({}); +exports.moduleTypeDescriptionSchema = Joi.object() + .keys({ + docs: Joi.string() + .required() + .description("Documentation for the module type, in markdown format."), + schema: Joi.object() + .required() + .description("A valid OpenAPI schema describing the configuration keys for the `module` field in the module's `garden.yml`."), +}); +exports.validateModuleResultSchema = module_1.moduleConfigSchema; +exports.buildModuleResultSchema = Joi.object() + .keys({ + buildLog: Joi.string() + .allow("") + .description("The full log from the build."), + fetched: Joi.boolean() + .description("Set to true if the build was fetched from a remote registry."), + fresh: Joi.boolean() + .description("Set to true if the build was perfomed, false if it was already built, or fetched from a registry"), + version: Joi.string() + .description("The version that was built."), + details: Joi.object() + .description("Additional information, specific to the provider."), +}); +exports.pushModuleResultSchema = Joi.object() + .keys({ + pushed: Joi.boolean() + .required() + .description("Set to true if the module was pushed."), + message: Joi.string() + .description("Optional result message."), +}); +exports.publishModuleResultSchema = Joi.object() + .keys({ + published: Joi.boolean() + .required() + .description("Set to true if the module was published."), + message: Joi.string() + .description("Optional result message."), +}); +exports.runResultSchema = Joi.object() + .keys({ + moduleName: Joi.string() + .description("The name of the module that was run."), + command: Joi.array().items(Joi.string()) + .required() + .description("The command that was run in the module."), + version: base_1.moduleVersionSchema, + success: Joi.boolean() + .required() + .description("Whether the module was successfully run."), + startedAt: Joi.date() + .required() + .description("When the module run was started."), + completedAt: Joi.date() + .required() + .description("When the module run was completed."), + output: Joi.string() + .required() + .allow("") + .description("The output log from the run."), +}); +exports.testResultSchema = exports.runResultSchema + .keys({ + testName: Joi.string() + .required() + .description("The name of the test that was run."), +}); +exports.getTestResultSchema = exports.testResultSchema.allow(null); +exports.buildStatusSchema = Joi.object() + .keys({ + ready: Joi.boolean() + .required() + .description("Whether an up-to-date build is ready for the module."), +}); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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RUFBRSxHQUFHLENBQUMsTUFBTSxFQUFFO1NBQ25CLFFBQVEsRUFBRTtTQUNWLFdBQVcsQ0FBQyxvQ0FBb0MsQ0FBQztDQUNyRCxDQUFDLENBQUE7QUFFUyxRQUFBLG1CQUFtQixHQUFHLHdCQUFnQixDQUFDLEtBQUssQ0FBQyxJQUFJLENBQUMsQ0FBQTtBQU1sRCxRQUFBLGlCQUFpQixHQUFHLEdBQUcsQ0FBQyxNQUFNLEVBQUU7S0FDMUMsSUFBSSxDQUFDO0lBQ0osS0FBSyxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUU7U0FDakIsUUFBUSxFQUFFO1NBQ1YsV0FBVyxDQUFDLHNEQUFzRCxDQUFDO0NBQ3ZFLENBQUMsQ0FBQSIsImZpbGUiOiJ0eXBlcy9wbHVnaW4vb3V0cHV0cy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyBNb2R1bGVWZXJzaW9uLCBtb2R1bGVWZXJzaW9uU2NoZW1hIH0gZnJvbSBcIi4uLy4uL3Zjcy9iYXNlXCJcbmltcG9ydCB7IFByaW1pdGl2ZU1hcCB9IGZyb20gXCIuLi8uLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCB7IE1vZHVsZSB9IGZyb20gXCIuLi9tb2R1bGVcIlxuaW1wb3J0IHsgU2VydmljZVN0YXR1cyB9IGZyb20gXCIuLi9zZXJ2aWNlXCJcbmltcG9ydCB7IG1vZHVsZUNvbmZpZ1NjaGVtYSwgTW9kdWxlQ29uZmlnIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9tb2R1bGVcIlxuXG5leHBvcnQgaW50ZXJmYWNlIEVudmlyb25tZW50U3RhdHVzIHtcbiAgcmVhZHk6IGJvb2xlYW5cbiAgbmVlZFVzZXJJbnB1dD86IGJvb2xlYW5cbiAgZGV0YWlsPzogYW55XG59XG5cbmV4cG9ydCBjb25zdCBlbnZpcm9ubWVudFN0YXR1c1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgcmVhZHk6IEpvaS5ib29sZWFuKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJTZXQgdG8gdHJ1ZSBpZiB0aGUgZW52aXJvbm1lbnQgaXMgZnVsbHkgY29uZmlndXJlZCBmb3IgYSBwcm92aWRlci5cIiksXG4gICAgbmVlZFVzZXJJbnB1dDogSm9pLmJvb2xlYW4oKVxuICAgICAgLmRlc2NyaXB0aW9uKFxuICAgICAgICBcIlNldCB0byB0cnVlIGlmIHRoZSBlbnZpcm9ubWVudCBuZWVkcyB1c2VyIGlucHV0IHRvIGJlIGluaXRpYWxpemVkLCBcIiArXG4gICAgICAgIFwiYW5kIHRodXMgbmVlZHMgdG8gYmUgaW5pdGlhbGl6ZWQgdmlhIGBnYXJkZW4gaW5pdGAuXCIsXG4gICAgICApLFxuICAgIGRldGFpbDogSm9pLm9iamVjdCgpXG4gICAgICAubWV0YSh7IGV4dGVuZGFibGU6IHRydWUgfSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIlVzZSB0aGlzIHRvIGluY2x1ZGUgYWRkaXRpb25hbCBpbmZvcm1hdGlvbiB0aGF0IGlzIHNwZWNpZmljIHRvIHRoZSBwcm92aWRlci5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIkRlc2NyaXB0aW9uIG9mIGFuIGVudmlyb25tZW50J3Mgc3RhdHVzIGZvciBhIHByb3ZpZGVyLlwiKVxuXG5leHBvcnQgdHlwZSBFbnZpcm9ubWVudFN0YXR1c01hcCA9IHtcbiAgW2tleTogc3RyaW5nXTogRW52aXJvbm1lbnRTdGF0dXMsXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUHJlcGFyZUVudmlyb25tZW50UmVzdWx0IHsgfVxuXG5leHBvcnQgY29uc3QgcHJlcGFyZUVudmlyb25tZW50UmVzdWx0U2NoZW1hID0gSm9pLm9iamVjdCgpLmtleXMoe30pXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xlYW51cEVudmlyb25tZW50UmVzdWx0IHsgfVxuXG5leHBvcnQgY29uc3QgY2xlYW51cEVudmlyb25tZW50UmVzdWx0U2NoZW1hID0gSm9pLm9iamVjdCgpLmtleXMoe30pXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VjcmV0UmVzdWx0IHtcbiAgdmFsdWU6IHN0cmluZyB8IG51bGxcbn1cblxuZXhwb3J0IGNvbnN0IGdldFNlY3JldFJlc3VsdFNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgdmFsdWU6IEpvaS5zdHJpbmcoKVxuICAgICAgLmFsbG93KG51bGwpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGNvbmZpZyB2YWx1ZSBmb3VuZCBmb3IgdGhlIHNwZWNpZmllZCBrZXkgKGFzIHN0cmluZyksIG9yIG51bGwgaWYgbm90IGZvdW5kLlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBTZXRTZWNyZXRSZXN1bHQgeyB9XG5cbmV4cG9ydCBjb25zdCBzZXRTZWNyZXRSZXN1bHRTY2hlbWEgPSBKb2kub2JqZWN0KCkua2V5cyh7fSlcblxuZXhwb3J0IGludGVyZmFjZSBEZWxldGVTZWNyZXRSZXN1bHQge1xuICBmb3VuZDogYm9vbGVhblxufVxuXG5leHBvcnQgY29uc3QgZGVsZXRlU2VjcmV0UmVzdWx0U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBmb3VuZDogSm9pLmJvb2xlYW4oKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNldCB0byB0cnVlIGlmIHRoZSBrZXkgd2FzIGRlbGV0ZWQsIGZhbHNlIGlmIGl0IHdhcyBub3QgZm91bmQuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWNJblNlcnZpY2VSZXN1bHQge1xuICBjb2RlOiBudW1iZXJcbiAgb3V0cHV0OiBzdHJpbmdcbiAgc3Rkb3V0Pzogc3RyaW5nXG4gIHN0ZGVycj86IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3QgZXhlY0luU2VydmljZVJlc3VsdFNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgY29kZTogSm9pLm51bWJlcigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGV4aXQgY29kZSBvZiB0aGUgY29tbWFuZCBleGVjdXRlZCBpbiB0aGUgc2VydmljZSBjb250YWluZXIuXCIpLFxuICAgIG91dHB1dDogSm9pLnN0cmluZygpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG91dHB1dCBvZiB0aGUgZXhlY3V0ZWQgY29tbWFuZC5cIiksXG4gICAgc3Rkb3V0OiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBzdGRvdXQgb3V0cHV0IG9mIHRoZSBleGVjdXRlZCBjb21tYW5kIChpZiBhdmFpbGFibGUpLlwiKSxcbiAgICBzdGRlcnI6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHN0ZGVyciBvdXRwdXQgb2YgdGhlIGV4ZWN1dGVkIGNvbW1hbmQgKGlmIGF2YWlsYWJsZSkuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VMb2dFbnRyeSB7XG4gIHNlcnZpY2VOYW1lOiBzdHJpbmdcbiAgdGltZXN0YW1wOiBEYXRlXG4gIG1zZzogc3RyaW5nXG59XG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlTG9nRW50cnlTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIHNlcnZpY2VOYW1lOiBKb2kuc3RyaW5nKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZSBvZiB0aGUgc2VydmljZSB0aGUgbG9nIGVudHJ5IG9yaWdpbmF0ZWQgZnJvbS5cIiksXG4gICAgdGltZXN0YW1wOiBKb2kuZGF0ZSgpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHRpbWUgd2hlbiB0aGUgbG9nIGVudHJ5IHdhcyBnZW5lcmF0ZWQgYnkgdGhlIHNlcnZpY2UuXCIpLFxuICAgIG1zZzogSm9pLnN0cmluZygpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGNvbnRlbnQgb2YgdGhlIGxvZyBlbnRyeS5cIiksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIkEgbG9nIGVudHJ5IHJldHVybmVkIGJ5IGEgZ2V0U2VydmljZUxvZ3MgYWN0aW9uIGhhbmRsZXIuXCIpXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VydmljZUxvZ3NSZXN1bHQgeyB9XG5cbmV4cG9ydCBjb25zdCBnZXRTZXJ2aWNlTG9nc1Jlc3VsdFNjaGVtYSA9IEpvaS5vYmplY3QoKS5rZXlzKHt9KVxuXG5leHBvcnQgaW50ZXJmYWNlIE1vZHVsZVR5cGVEZXNjcmlwdGlvbiB7XG4gIGRvY3M6IHN0cmluZ1xuICBzY2hlbWE6IG9iamVjdFxufVxuXG5leHBvcnQgY29uc3QgbW9kdWxlVHlwZURlc2NyaXB0aW9uU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBkb2NzOiBKb2kuc3RyaW5nKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJEb2N1bWVudGF0aW9uIGZvciB0aGUgbW9kdWxlIHR5cGUsIGluIG1hcmtkb3duIGZvcm1hdC5cIiksXG4gICAgc2NoZW1hOiBKb2kub2JqZWN0KClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXG4gICAgICAgIFwiQSB2YWxpZCBPcGVuQVBJIHNjaGVtYSBkZXNjcmliaW5nIHRoZSBjb25maWd1cmF0aW9uIGtleXMgZm9yIHRoZSBgbW9kdWxlYCBmaWVsZCBpbiB0aGUgbW9kdWxlJ3MgYGdhcmRlbi55bWxgLlwiLFxuICAgICAgKSxcbiAgfSlcblxuZXhwb3J0IHR5cGUgVmFsaWRhdGVNb2R1bGVSZXN1bHQ8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gPVxuICBNb2R1bGVDb25maWc8VFtcInNwZWNcIl0sIFRbXCJzZXJ2aWNlQ29uZmlnc1wiXVswXVtcInNwZWNcIl0sIFRbXCJ0ZXN0Q29uZmlnc1wiXVswXVtcInNwZWNcIl0+XG5cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZU1vZHVsZVJlc3VsdFNjaGVtYSA9IG1vZHVsZUNvbmZpZ1NjaGVtYVxuXG5leHBvcnQgaW50ZXJmYWNlIEJ1aWxkUmVzdWx0IHtcbiAgYnVpbGRMb2c/OiBzdHJpbmdcbiAgZmV0Y2hlZD86IGJvb2xlYW5cbiAgZnJlc2g/OiBib29sZWFuXG4gIHZlcnNpb24/OiBzdHJpbmdcbiAgZGV0YWlscz86IGFueVxufVxuZXhwb3J0IGNvbnN0IGJ1aWxkTW9kdWxlUmVzdWx0U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBidWlsZExvZzogSm9pLnN0cmluZygpXG4gICAgICAuYWxsb3coXCJcIilcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBmdWxsIGxvZyBmcm9tIHRoZSBidWlsZC5cIiksXG4gICAgZmV0Y2hlZDogSm9pLmJvb2xlYW4oKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiU2V0IHRvIHRydWUgaWYgdGhlIGJ1aWxkIHdhcyBmZXRjaGVkIGZyb20gYSByZW1vdGUgcmVnaXN0cnkuXCIpLFxuICAgIGZyZXNoOiBKb2kuYm9vbGVhbigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJTZXQgdG8gdHJ1ZSBpZiB0aGUgYnVpbGQgd2FzIHBlcmZvbWVkLCBmYWxzZSBpZiBpdCB3YXMgYWxyZWFkeSBidWlsdCwgb3IgZmV0Y2hlZCBmcm9tIGEgcmVnaXN0cnlcIiksXG4gICAgdmVyc2lvbjogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgdmVyc2lvbiB0aGF0IHdhcyBidWlsdC5cIiksXG4gICAgZGV0YWlsczogSm9pLm9iamVjdCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJBZGRpdGlvbmFsIGluZm9ybWF0aW9uLCBzcGVjaWZpYyB0byB0aGUgcHJvdmlkZXIuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFB1c2hSZXN1bHQge1xuICBwdXNoZWQ6IGJvb2xlYW5cbiAgbWVzc2FnZT86IHN0cmluZ1xufVxuZXhwb3J0IGNvbnN0IHB1c2hNb2R1bGVSZXN1bHRTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIHB1c2hlZDogSm9pLmJvb2xlYW4oKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlNldCB0byB0cnVlIGlmIHRoZSBtb2R1bGUgd2FzIHB1c2hlZC5cIiksXG4gICAgbWVzc2FnZTogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJPcHRpb25hbCByZXN1bHQgbWVzc2FnZS5cIiksXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgUHVibGlzaFJlc3VsdCB7XG4gIHB1Ymxpc2hlZDogYm9vbGVhblxuICBtZXNzYWdlPzogc3RyaW5nXG59XG5leHBvcnQgY29uc3QgcHVibGlzaE1vZHVsZVJlc3VsdFNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgcHVibGlzaGVkOiBKb2kuYm9vbGVhbigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiU2V0IHRvIHRydWUgaWYgdGhlIG1vZHVsZSB3YXMgcHVibGlzaGVkLlwiKSxcbiAgICBtZXNzYWdlOiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIk9wdGlvbmFsIHJlc3VsdCBtZXNzYWdlLlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBSdW5SZXN1bHQge1xuICBtb2R1bGVOYW1lOiBzdHJpbmdcbiAgY29tbWFuZDogc3RyaW5nW11cbiAgdmVyc2lvbjogTW9kdWxlVmVyc2lvblxuICBzdWNjZXNzOiBib29sZWFuXG4gIHN0YXJ0ZWRBdDogRGF0ZVxuICBjb21wbGV0ZWRBdDogRGF0ZVxuICBvdXRwdXQ6IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3QgcnVuUmVzdWx0U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBtb2R1bGVOYW1lOiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBuYW1lIG9mIHRoZSBtb2R1bGUgdGhhdCB3YXMgcnVuLlwiKSxcbiAgICBjb21tYW5kOiBKb2kuYXJyYXkoKS5pdGVtcyhKb2kuc3RyaW5nKCkpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGNvbW1hbmQgdGhhdCB3YXMgcnVuIGluIHRoZSBtb2R1bGUuXCIpLFxuICAgIHZlcnNpb246IG1vZHVsZVZlcnNpb25TY2hlbWEsXG4gICAgc3VjY2VzczogSm9pLmJvb2xlYW4oKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIldoZXRoZXIgdGhlIG1vZHVsZSB3YXMgc3VjY2Vzc2Z1bGx5IHJ1bi5cIiksXG4gICAgc3RhcnRlZEF0OiBKb2kuZGF0ZSgpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiV2hlbiB0aGUgbW9kdWxlIHJ1biB3YXMgc3RhcnRlZC5cIiksXG4gICAgY29tcGxldGVkQXQ6IEpvaS5kYXRlKClcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJXaGVuIHRoZSBtb2R1bGUgcnVuIHdhcyBjb21wbGV0ZWQuXCIpLFxuICAgIG91dHB1dDogSm9pLnN0cmluZygpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmFsbG93KFwiXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgb3V0cHV0IGxvZyBmcm9tIHRoZSBydW4uXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFRlc3RSZXN1bHQgZXh0ZW5kcyBSdW5SZXN1bHQge1xuICB0ZXN0TmFtZTogc3RyaW5nXG59XG5cbmV4cG9ydCBjb25zdCB0ZXN0UmVzdWx0U2NoZW1hID0gcnVuUmVzdWx0U2NoZW1hXG4gIC5rZXlzKHtcbiAgICB0ZXN0TmFtZTogSm9pLnN0cmluZygpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG5hbWUgb2YgdGhlIHRlc3QgdGhhdCB3YXMgcnVuLlwiKSxcbiAgfSlcblxuZXhwb3J0IGNvbnN0IGdldFRlc3RSZXN1bHRTY2hlbWEgPSB0ZXN0UmVzdWx0U2NoZW1hLmFsbG93KG51bGwpXG5cbmV4cG9ydCBpbnRlcmZhY2UgQnVpbGRTdGF0dXMge1xuICByZWFkeTogYm9vbGVhblxufVxuXG5leHBvcnQgY29uc3QgYnVpbGRTdGF0dXNTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIHJlYWR5OiBKb2kuYm9vbGVhbigpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiV2hldGhlciBhbiB1cC10by1kYXRlIGJ1aWxkIGlzIHJlYWR5IGZvciB0aGUgbW9kdWxlLlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5BY3Rpb25PdXRwdXRzIHtcbiAgZ2V0RW52aXJvbm1lbnRTdGF0dXM6IFByb21pc2U8RW52aXJvbm1lbnRTdGF0dXM+XG4gIHByZXBhcmVFbnZpcm9ubWVudDogUHJvbWlzZTxQcmVwYXJlRW52aXJvbm1lbnRSZXN1bHQ+XG4gIGNsZWFudXBFbnZpcm9ubWVudDogUHJvbWlzZTxDbGVhbnVwRW52aXJvbm1lbnRSZXN1bHQ+XG5cbiAgZ2V0U2VjcmV0OiBQcm9taXNlPEdldFNlY3JldFJlc3VsdD5cbiAgc2V0U2VjcmV0OiBQcm9taXNlPFNldFNlY3JldFJlc3VsdD5cbiAgZGVsZXRlU2VjcmV0OiBQcm9taXNlPERlbGV0ZVNlY3JldFJlc3VsdD5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlQWN0aW9uT3V0cHV0cyB7XG4gIGdldFNlcnZpY2VTdGF0dXM6IFByb21pc2U8U2VydmljZVN0YXR1cz5cbiAgZGVwbG95U2VydmljZTogUHJvbWlzZTxTZXJ2aWNlU3RhdHVzPlxuICBkZWxldGVTZXJ2aWNlOiBQcm9taXNlPFNlcnZpY2VTdGF0dXM+XG4gIGdldFNlcnZpY2VPdXRwdXRzOiBQcm9taXNlPFByaW1pdGl2ZU1hcD5cbiAgZXhlY0luU2VydmljZTogUHJvbWlzZTxFeGVjSW5TZXJ2aWNlUmVzdWx0PlxuICBnZXRTZXJ2aWNlTG9nczogUHJvbWlzZTx7fT5cbiAgcnVuU2VydmljZTogUHJvbWlzZTxSdW5SZXN1bHQ+XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlQWN0aW9uT3V0cHV0cyBleHRlbmRzIFNlcnZpY2VBY3Rpb25PdXRwdXRzIHtcbiAgZGVzY3JpYmVUeXBlOiBQcm9taXNlPE1vZHVsZVR5cGVEZXNjcmlwdGlvbj5cbiAgdmFsaWRhdGU6IFByb21pc2U8VmFsaWRhdGVNb2R1bGVSZXN1bHQ+XG4gIGdldEJ1aWxkU3RhdHVzOiBQcm9taXNlPEJ1aWxkU3RhdHVzPlxuICBidWlsZDogUHJvbWlzZTxCdWlsZFJlc3VsdD5cbiAgcHVzaE1vZHVsZTogUHJvbWlzZTxQdXNoUmVzdWx0PlxuICBwdWJsaXNoTW9kdWxlOiBQcm9taXNlPFB1Ymxpc2hSZXN1bHQ+XG4gIHJ1bk1vZHVsZTogUHJvbWlzZTxSdW5SZXN1bHQ+XG4gIHRlc3RNb2R1bGU6IFByb21pc2U8VGVzdFJlc3VsdD5cbiAgZ2V0VGVzdFJlc3VsdDogUHJvbWlzZTxUZXN0UmVzdWx0IHwgbnVsbD5cbn1cbiJdfQ== diff --git a/garden-service/build/types/plugin/params.d.ts b/garden-service/build/types/plugin/params.d.ts new file mode 100644 index 00000000000..b8d3c0b9c8d --- /dev/null +++ b/garden-service/build/types/plugin/params.d.ts @@ -0,0 +1,160 @@ +import Stream from "ts-stream"; +import { LogEntry } from "../../logger/log-entry"; +import { PluginContext } from "../../plugin-context"; +import { ModuleVersion } from "../../vcs/base"; +import { Primitive } from "../../config/common"; +import { Module } from "../module"; +import { RuntimeContext, Service } from "../service"; +import { EnvironmentStatus, ServiceLogEntry } from "./outputs"; +import * as Joi from "joi"; +export interface PluginActionContextParams { + ctx: PluginContext; +} +export interface PluginActionParamsBase extends PluginActionContextParams { + logEntry?: LogEntry; +} +export interface PluginModuleActionParamsBase extends PluginActionParamsBase { + module: T; +} +export interface PluginServiceActionParamsBase extends PluginModuleActionParamsBase { + runtimeContext?: RuntimeContext; + service: Service; +} +/** + * Plugin actions + */ +export interface DescribeModuleTypeParams { +} +export declare const describeModuleTypeParamsSchema: Joi.ObjectSchema; +export interface ValidateModuleParams { + ctx: PluginContext; + logEntry?: LogEntry; + moduleConfig: T["_ConfigType"]; +} +export declare const validateModuleParamsSchema: Joi.ObjectSchema; +export interface GetEnvironmentStatusParams extends PluginActionParamsBase { +} +export declare const getEnvironmentStatusParamsSchema: Joi.ObjectSchema; +export interface PrepareEnvironmentParams extends PluginActionParamsBase { + status: EnvironmentStatus; + force: boolean; +} +export declare const prepareEnvironmentParamsSchema: Joi.ObjectSchema; +export interface CleanupEnvironmentParams extends PluginActionParamsBase { +} +export declare const cleanupEnvironmentParamsSchema: Joi.ObjectSchema; +export interface GetSecretParams extends PluginActionParamsBase { + key: string; +} +export declare const getSecretParamsSchema: Joi.ObjectSchema; +export interface SetSecretParams extends PluginActionParamsBase { + key: string; + value: Primitive; +} +export declare const setSecretParamsSchema: Joi.ObjectSchema; +export interface DeleteSecretParams extends PluginActionParamsBase { + key: string; +} +export declare const deleteSecretParamsSchema: Joi.ObjectSchema; +export interface PluginActionParams { + getEnvironmentStatus: GetEnvironmentStatusParams; + prepareEnvironment: PrepareEnvironmentParams; + cleanupEnvironment: CleanupEnvironmentParams; + getSecret: GetSecretParams; + setSecret: SetSecretParams; + deleteSecret: DeleteSecretParams; +} +/** + * Module actions + */ +export interface GetBuildStatusParams extends PluginModuleActionParamsBase { +} +export declare const getBuildStatusParamsSchema: Joi.ObjectSchema; +export interface BuildModuleParams extends PluginModuleActionParamsBase { +} +export declare const buildModuleParamsSchema: Joi.ObjectSchema; +export interface PushModuleParams extends PluginModuleActionParamsBase { +} +export declare const pushModuleParamsSchema: Joi.ObjectSchema; +export interface PublishModuleParams extends PluginModuleActionParamsBase { +} +export declare const publishModuleParamsSchema: Joi.ObjectSchema; +export interface RunModuleParams extends PluginModuleActionParamsBase { + command: string[]; + interactive: boolean; + runtimeContext: RuntimeContext; + silent: boolean; + timeout?: number; +} +export declare const runModuleParamsSchema: Joi.ObjectSchema; +export interface TestModuleParams extends PluginModuleActionParamsBase { + interactive: boolean; + runtimeContext: RuntimeContext; + silent: boolean; + testConfig: T["testConfigs"][0]; +} +export declare const testModuleParamsSchema: Joi.ObjectSchema; +export interface GetTestResultParams extends PluginModuleActionParamsBase { + testName: string; + version: ModuleVersion; +} +export declare const getTestResultParamsSchema: Joi.ObjectSchema; +/** + * Service actions + */ +export interface GetServiceStatusParams extends PluginServiceActionParamsBase { + runtimeContext: RuntimeContext; +} +export declare const getServiceStatusParamsSchema: Joi.ObjectSchema; +export interface DeployServiceParams extends PluginServiceActionParamsBase { + force: boolean; + runtimeContext: RuntimeContext; +} +export declare const deployServiceParamsSchema: Joi.ObjectSchema; +export interface DeleteServiceParams extends PluginServiceActionParamsBase { + runtimeContext: RuntimeContext; +} +export declare const deleteServiceParamsSchema: Joi.ObjectSchema; +export interface GetServiceOutputsParams extends PluginServiceActionParamsBase { +} +export declare const getServiceOutputsParamsSchema: Joi.ObjectSchema; +export interface ExecInServiceParams extends PluginServiceActionParamsBase { + command: string[]; + runtimeContext: RuntimeContext; +} +export declare const execInServiceParamsSchema: Joi.ObjectSchema; +export interface GetServiceLogsParams extends PluginServiceActionParamsBase { + runtimeContext: RuntimeContext; + stream: Stream; + tail: boolean; + startTime?: Date; +} +export declare const getServiceLogsParamsSchema: Joi.ObjectSchema; +export interface RunServiceParams extends PluginServiceActionParamsBase { + interactive: boolean; + runtimeContext: RuntimeContext; + silent: boolean; + timeout?: number; +} +export declare const runServiceParamsSchema: Joi.ObjectSchema; +export interface ServiceActionParams { + getServiceStatus: GetServiceStatusParams; + deployService: DeployServiceParams; + deleteService: DeleteServiceParams; + getServiceOutputs: GetServiceOutputsParams; + execInService: ExecInServiceParams; + getServiceLogs: GetServiceLogsParams; + runService: RunServiceParams; +} +export interface ModuleActionParams { + describeType: DescribeModuleTypeParams; + validate: ValidateModuleParams; + getBuildStatus: GetBuildStatusParams; + build: BuildModuleParams; + pushModule: PushModuleParams; + publishModule: PublishModuleParams; + runModule: RunModuleParams; + testModule: TestModuleParams; + getTestResult: GetTestResultParams; +} +//# sourceMappingURL=params.d.ts.map \ No newline at end of file diff --git a/garden-service/build/types/plugin/params.js b/garden-service/build/types/plugin/params.js new file mode 100644 index 00000000000..c5f5184e8a5 --- /dev/null +++ b/garden-service/build/types/plugin/params.js @@ -0,0 +1,133 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const plugin_context_1 = require("../../plugin-context"); +const base_1 = require("../../vcs/base"); +const common_1 = require("../../config/common"); +const module_1 = require("../module"); +const service_1 = require("../service"); +const outputs_1 = require("./outputs"); +const Joi = require("joi"); +const module_2 = require("../../config/module"); +const test_1 = require("../../config/test"); +// Note: not specifying this further because we will later remove it from the API +const logEntrySchema = Joi.object() + .description("Logging context handler that the handler can use to log messages and progress."); +const actionParamsSchema = Joi.object() + .keys({ + ctx: plugin_context_1.pluginContextSchema + .required(), + logEntry: logEntrySchema, +}); +const moduleActionParamsSchema = actionParamsSchema + .keys({ + module: module_1.moduleSchema, +}); +const serviceActionParamsSchema = moduleActionParamsSchema + .keys({ + runtimeContext: service_1.runtimeContextSchema + .optional(), + service: service_1.serviceSchema, +}); +exports.describeModuleTypeParamsSchema = Joi.object() + .keys({}); +exports.validateModuleParamsSchema = Joi.object() + .keys({ + ctx: plugin_context_1.pluginContextSchema + .required(), + logEntry: logEntrySchema, + moduleConfig: module_2.moduleConfigSchema + .required(), +}); +exports.getEnvironmentStatusParamsSchema = actionParamsSchema; +exports.prepareEnvironmentParamsSchema = actionParamsSchema + .keys({ + status: outputs_1.environmentStatusSchema, + force: Joi.boolean() + .description("Force re-configuration of the environment."), +}); +exports.cleanupEnvironmentParamsSchema = actionParamsSchema; +exports.getSecretParamsSchema = actionParamsSchema + .keys({ + key: Joi.string() + .description("A unique identifier for the secret."), +}); +exports.setSecretParamsSchema = exports.getSecretParamsSchema + .keys({ + value: common_1.joiPrimitive() + .description("The value of the secret."), +}); +exports.deleteSecretParamsSchema = exports.getSecretParamsSchema; +exports.getBuildStatusParamsSchema = moduleActionParamsSchema; +exports.buildModuleParamsSchema = moduleActionParamsSchema; +exports.pushModuleParamsSchema = moduleActionParamsSchema; +exports.publishModuleParamsSchema = moduleActionParamsSchema; +const runBaseParams = { + interactive: Joi.boolean() + .description("Whether to run the module interactively (i.e. attach to the terminal)."), + runtimeContext: service_1.runtimeContextSchema, + silent: Joi.boolean() + .description("Set to false if the output should not be logged to the console."), + timeout: Joi.number() + .optional() + .description("If set, how long to run the command before timing out."), +}; +const runModuleBaseSchema = moduleActionParamsSchema + .keys(runBaseParams); +exports.runModuleParamsSchema = runModuleBaseSchema + .keys({ + command: common_1.joiArray(Joi.string()) + .description("The command to run in the module."), +}); +exports.testModuleParamsSchema = runModuleBaseSchema + .keys({ + testConfig: test_1.testConfigSchema, +}); +exports.getTestResultParamsSchema = moduleActionParamsSchema + .keys({ + testName: Joi.string() + .description("A unique name to identify the test run."), + version: base_1.moduleVersionSchema, +}); +exports.getServiceStatusParamsSchema = serviceActionParamsSchema + .keys({ + runtimeContext: service_1.runtimeContextSchema, +}); +exports.deployServiceParamsSchema = serviceActionParamsSchema + .keys({ + force: Joi.boolean() + .description("Whether to force a re-deploy, even if the service is already deployed."), + runtimeContext: service_1.runtimeContextSchema, +}); +exports.deleteServiceParamsSchema = serviceActionParamsSchema + .keys({ + runtimeContext: service_1.runtimeContextSchema, +}); +exports.getServiceOutputsParamsSchema = serviceActionParamsSchema; +exports.execInServiceParamsSchema = serviceActionParamsSchema + .keys({ + command: common_1.joiArray(Joi.string()) + .description("The command to run alongside the service."), + runtimeContext: service_1.runtimeContextSchema, +}); +exports.getServiceLogsParamsSchema = serviceActionParamsSchema + .keys({ + runtimeContext: service_1.runtimeContextSchema, + stream: Joi.object() + .description("A Stream object, to write the logs to."), + tail: Joi.boolean() + .description("Whether to keep listening for logs until aborted."), + startTime: Joi.date() + .optional() + .description("If set, only return logs that are as new or newer than this date."), +}); +exports.runServiceParamsSchema = serviceActionParamsSchema + .keys(runBaseParams); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QUFBO0FBUVMsUUFBQSwwQkFBMEIsR0FBRyx5QkFBeUI7S0FDaEUsSUFBSSxDQUFDO0lBQ0osY0FBYyxFQUFFLDhCQUFvQjtJQUNwQyxNQUFNLEVBQUUsR0FBRyxDQUFDLE1BQU0sRUFBRTtTQUNqQixXQUFXLENBQUMsd0NBQXdDLENBQUM7SUFDeEQsSUFBSSxFQUFFLEdBQUcsQ0FBQyxPQUFPLEVBQUU7U0FDaEIsV0FBVyxDQUFDLG1EQUFtRCxDQUFDO0lBQ25FLFNBQVMsRUFBRSxHQUFHLENBQUMsSUFBSSxFQUFFO1NBQ2xCLFFBQVEsRUFBRTtTQUNWLFdBQVcsQ0FBQyxtRUFBbUUsQ0FBQztDQUNwRixDQUFDLENBQUE7QUFRUyxRQUFBLHNCQUFzQixHQUFHLHlCQUF5QjtLQUM1RCxJQUFJLENBQUMsYUFBYSxDQUFDLENBQUEiLCJmaWxlIjoidHlwZXMvcGx1Z2luL3BhcmFtcy5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgU3RyZWFtIGZyb20gXCJ0cy1zdHJlYW1cIlxuaW1wb3J0IHsgTG9nRW50cnkgfSBmcm9tIFwiLi4vLi4vbG9nZ2VyL2xvZy1lbnRyeVwiXG5pbXBvcnQgeyBQbHVnaW5Db250ZXh0LCBwbHVnaW5Db250ZXh0U2NoZW1hIH0gZnJvbSBcIi4uLy4uL3BsdWdpbi1jb250ZXh0XCJcbmltcG9ydCB7IE1vZHVsZVZlcnNpb24sIG1vZHVsZVZlcnNpb25TY2hlbWEgfSBmcm9tIFwiLi4vLi4vdmNzL2Jhc2VcIlxuaW1wb3J0IHsgUHJpbWl0aXZlLCBqb2lQcmltaXRpdmUsIGpvaUFycmF5IH0gZnJvbSBcIi4uLy4uL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgTW9kdWxlLCBtb2R1bGVTY2hlbWEgfSBmcm9tIFwiLi4vbW9kdWxlXCJcbmltcG9ydCB7IFJ1bnRpbWVDb250ZXh0LCBTZXJ2aWNlLCBzZXJ2aWNlU2NoZW1hLCBydW50aW1lQ29udGV4dFNjaGVtYSB9IGZyb20gXCIuLi9zZXJ2aWNlXCJcbmltcG9ydCB7IEVudmlyb25tZW50U3RhdHVzLCBTZXJ2aWNlTG9nRW50cnksIGVudmlyb25tZW50U3RhdHVzU2NoZW1hIH0gZnJvbSBcIi4vb3V0cHV0c1wiXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyBtb2R1bGVDb25maWdTY2hlbWEgfSBmcm9tIFwiLi4vLi4vY29uZmlnL21vZHVsZVwiXG5pbXBvcnQgeyB0ZXN0Q29uZmlnU2NoZW1hIH0gZnJvbSBcIi4uLy4uL2NvbmZpZy90ZXN0XCJcblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5BY3Rpb25Db250ZXh0UGFyYW1zIHtcbiAgY3R4OiBQbHVnaW5Db250ZXh0XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSBleHRlbmRzIFBsdWdpbkFjdGlvbkNvbnRleHRQYXJhbXMge1xuICBsb2dFbnRyeT86IExvZ0VudHJ5XG59XG5cbi8vIE5vdGU6IG5vdCBzcGVjaWZ5aW5nIHRoaXMgZnVydGhlciBiZWNhdXNlIHdlIHdpbGwgbGF0ZXIgcmVtb3ZlIGl0IGZyb20gdGhlIEFQSVxuY29uc3QgbG9nRW50cnlTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmRlc2NyaXB0aW9uKFwiTG9nZ2luZyBjb250ZXh0IGhhbmRsZXIgdGhhdCB0aGUgaGFuZGxlciBjYW4gdXNlIHRvIGxvZyBtZXNzYWdlcyBhbmQgcHJvZ3Jlc3MuXCIpXG5cbmNvbnN0IGFjdGlvblBhcmFtc1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgY3R4OiBwbHVnaW5Db250ZXh0U2NoZW1hXG4gICAgICAucmVxdWlyZWQoKSxcbiAgICBsb2dFbnRyeTogbG9nRW50cnlTY2hlbWEsXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luTW9kdWxlQWN0aW9uUGFyYW1zQmFzZTxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbkFjdGlvblBhcmFtc0Jhc2Uge1xuICBtb2R1bGU6IFRcbn1cbmNvbnN0IG1vZHVsZUFjdGlvblBhcmFtc1NjaGVtYSA9IGFjdGlvblBhcmFtc1NjaGVtYVxuICAua2V5cyh7XG4gICAgbW9kdWxlOiBtb2R1bGVTY2hlbWEsXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luU2VydmljZUFjdGlvblBhcmFtc0Jhc2U8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gZXh0ZW5kcyBQbHVnaW5Nb2R1bGVBY3Rpb25QYXJhbXNCYXNlPFQ+IHtcbiAgcnVudGltZUNvbnRleHQ/OiBSdW50aW1lQ29udGV4dFxuICBzZXJ2aWNlOiBTZXJ2aWNlPFQ+XG59XG5jb25zdCBzZXJ2aWNlQWN0aW9uUGFyYW1zU2NoZW1hID0gbW9kdWxlQWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBydW50aW1lQ29udGV4dDogcnVudGltZUNvbnRleHRTY2hlbWFcbiAgICAgIC5vcHRpb25hbCgpLFxuICAgIHNlcnZpY2U6IHNlcnZpY2VTY2hlbWEsXG4gIH0pXG5cbi8qKlxuICogUGx1Z2luIGFjdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBEZXNjcmliZU1vZHVsZVR5cGVQYXJhbXMgeyB9XG5leHBvcnQgY29uc3QgZGVzY3JpYmVNb2R1bGVUeXBlUGFyYW1zU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHt9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFZhbGlkYXRlTW9kdWxlUGFyYW1zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IHtcbiAgY3R4OiBQbHVnaW5Db250ZXh0XG4gIGxvZ0VudHJ5PzogTG9nRW50cnlcbiAgbW9kdWxlQ29uZmlnOiBUW1wiX0NvbmZpZ1R5cGVcIl1cbn1cbmV4cG9ydCBjb25zdCB2YWxpZGF0ZU1vZHVsZVBhcmFtc1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgY3R4OiBwbHVnaW5Db250ZXh0U2NoZW1hXG4gICAgICAucmVxdWlyZWQoKSxcbiAgICBsb2dFbnRyeTogbG9nRW50cnlTY2hlbWEsXG4gICAgbW9kdWxlQ29uZmlnOiBtb2R1bGVDb25maWdTY2hlbWFcbiAgICAgIC5yZXF1aXJlZCgpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIEdldEVudmlyb25tZW50U3RhdHVzUGFyYW1zIGV4dGVuZHMgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSB7IH1cbmV4cG9ydCBjb25zdCBnZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtc1NjaGVtYSA9IGFjdGlvblBhcmFtc1NjaGVtYVxuXG5leHBvcnQgaW50ZXJmYWNlIFByZXBhcmVFbnZpcm9ubWVudFBhcmFtcyBleHRlbmRzIFBsdWdpbkFjdGlvblBhcmFtc0Jhc2Uge1xuICBzdGF0dXM6IEVudmlyb25tZW50U3RhdHVzXG4gIGZvcmNlOiBib29sZWFuXG59XG5leHBvcnQgY29uc3QgcHJlcGFyZUVudmlyb25tZW50UGFyYW1zU2NoZW1hID0gYWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBzdGF0dXM6IGVudmlyb25tZW50U3RhdHVzU2NoZW1hLFxuICAgIGZvcmNlOiBKb2kuYm9vbGVhbigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJGb3JjZSByZS1jb25maWd1cmF0aW9uIG9mIHRoZSBlbnZpcm9ubWVudC5cIiksXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgQ2xlYW51cEVudmlyb25tZW50UGFyYW1zIGV4dGVuZHMgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSB7XG59XG5leHBvcnQgY29uc3QgY2xlYW51cEVudmlyb25tZW50UGFyYW1zU2NoZW1hID0gYWN0aW9uUGFyYW1zU2NoZW1hXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VjcmV0UGFyYW1zIGV4dGVuZHMgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSB7XG4gIGtleTogc3RyaW5nXG59XG5leHBvcnQgY29uc3QgZ2V0U2VjcmV0UGFyYW1zU2NoZW1hID0gYWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBrZXk6IEpvaS5zdHJpbmcoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSB1bmlxdWUgaWRlbnRpZmllciBmb3IgdGhlIHNlY3JldC5cIiksXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgU2V0U2VjcmV0UGFyYW1zIGV4dGVuZHMgUGx1Z2luQWN0aW9uUGFyYW1zQmFzZSB7XG4gIGtleTogc3RyaW5nXG4gIHZhbHVlOiBQcmltaXRpdmVcbn1cbmV4cG9ydCBjb25zdCBzZXRTZWNyZXRQYXJhbXNTY2hlbWEgPSBnZXRTZWNyZXRQYXJhbXNTY2hlbWFcbiAgLmtleXMoe1xuICAgIHZhbHVlOiBqb2lQcmltaXRpdmUoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHZhbHVlIG9mIHRoZSBzZWNyZXQuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIERlbGV0ZVNlY3JldFBhcmFtcyBleHRlbmRzIFBsdWdpbkFjdGlvblBhcmFtc0Jhc2Uge1xuICBrZXk6IHN0cmluZ1xufVxuZXhwb3J0IGNvbnN0IGRlbGV0ZVNlY3JldFBhcmFtc1NjaGVtYSA9IGdldFNlY3JldFBhcmFtc1NjaGVtYVxuXG5leHBvcnQgaW50ZXJmYWNlIFBsdWdpbkFjdGlvblBhcmFtcyB7XG4gIGdldEVudmlyb25tZW50U3RhdHVzOiBHZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtc1xuICBwcmVwYXJlRW52aXJvbm1lbnQ6IFByZXBhcmVFbnZpcm9ubWVudFBhcmFtc1xuICBjbGVhbnVwRW52aXJvbm1lbnQ6IENsZWFudXBFbnZpcm9ubWVudFBhcmFtc1xuXG4gIGdldFNlY3JldDogR2V0U2VjcmV0UGFyYW1zXG4gIHNldFNlY3JldDogU2V0U2VjcmV0UGFyYW1zXG4gIGRlbGV0ZVNlY3JldDogRGVsZXRlU2VjcmV0UGFyYW1zXG59XG5cbi8qKlxuICogTW9kdWxlIGFjdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRCdWlsZFN0YXR1c1BhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U8VD4geyB9XG5leHBvcnQgY29uc3QgZ2V0QnVpbGRTdGF0dXNQYXJhbXNTY2hlbWEgPSBtb2R1bGVBY3Rpb25QYXJhbXNTY2hlbWFcblxuZXhwb3J0IGludGVyZmFjZSBCdWlsZE1vZHVsZVBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U8VD4geyB9XG5leHBvcnQgY29uc3QgYnVpbGRNb2R1bGVQYXJhbXNTY2hlbWEgPSBtb2R1bGVBY3Rpb25QYXJhbXNTY2hlbWFcblxuZXhwb3J0IGludGVyZmFjZSBQdXNoTW9kdWxlUGFyYW1zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IGV4dGVuZHMgUGx1Z2luTW9kdWxlQWN0aW9uUGFyYW1zQmFzZTxUPiB7IH1cbmV4cG9ydCBjb25zdCBwdXNoTW9kdWxlUGFyYW1zU2NoZW1hID0gbW9kdWxlQWN0aW9uUGFyYW1zU2NoZW1hXG5cbmV4cG9ydCBpbnRlcmZhY2UgUHVibGlzaE1vZHVsZVBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U8VD4geyB9XG5leHBvcnQgY29uc3QgcHVibGlzaE1vZHVsZVBhcmFtc1NjaGVtYSA9IG1vZHVsZUFjdGlvblBhcmFtc1NjaGVtYVxuXG5leHBvcnQgaW50ZXJmYWNlIFJ1bk1vZHVsZVBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U8VD4ge1xuICBjb21tYW5kOiBzdHJpbmdbXVxuICBpbnRlcmFjdGl2ZTogYm9vbGVhblxuICBydW50aW1lQ29udGV4dDogUnVudGltZUNvbnRleHRcbiAgc2lsZW50OiBib29sZWFuXG4gIHRpbWVvdXQ/OiBudW1iZXJcbn1cbmNvbnN0IHJ1bkJhc2VQYXJhbXMgPSB7XG4gIGludGVyYWN0aXZlOiBKb2kuYm9vbGVhbigpXG4gICAgLmRlc2NyaXB0aW9uKFwiV2hldGhlciB0byBydW4gdGhlIG1vZHVsZSBpbnRlcmFjdGl2ZWx5IChpLmUuIGF0dGFjaCB0byB0aGUgdGVybWluYWwpLlwiKSxcbiAgcnVudGltZUNvbnRleHQ6IHJ1bnRpbWVDb250ZXh0U2NoZW1hLFxuICBzaWxlbnQ6IEpvaS5ib29sZWFuKClcbiAgICAuZGVzY3JpcHRpb24oXCJTZXQgdG8gZmFsc2UgaWYgdGhlIG91dHB1dCBzaG91bGQgbm90IGJlIGxvZ2dlZCB0byB0aGUgY29uc29sZS5cIiksXG4gIHRpbWVvdXQ6IEpvaS5udW1iZXIoKVxuICAgIC5vcHRpb25hbCgpXG4gICAgLmRlc2NyaXB0aW9uKFwiSWYgc2V0LCBob3cgbG9uZyB0byBydW4gdGhlIGNvbW1hbmQgYmVmb3JlIHRpbWluZyBvdXQuXCIpLFxufVxuY29uc3QgcnVuTW9kdWxlQmFzZVNjaGVtYSA9IG1vZHVsZUFjdGlvblBhcmFtc1NjaGVtYVxuICAua2V5cyhydW5CYXNlUGFyYW1zKVxuZXhwb3J0IGNvbnN0IHJ1bk1vZHVsZVBhcmFtc1NjaGVtYSA9IHJ1bk1vZHVsZUJhc2VTY2hlbWFcbiAgLmtleXMoe1xuICAgIGNvbW1hbmQ6IGpvaUFycmF5KEpvaS5zdHJpbmcoKSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBjb21tYW5kIHRvIHJ1biBpbiB0aGUgbW9kdWxlLlwiKSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBUZXN0TW9kdWxlUGFyYW1zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IGV4dGVuZHMgUGx1Z2luTW9kdWxlQWN0aW9uUGFyYW1zQmFzZTxUPiB7XG4gIGludGVyYWN0aXZlOiBib29sZWFuXG4gIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dFxuICBzaWxlbnQ6IGJvb2xlYW5cbiAgdGVzdENvbmZpZzogVFtcInRlc3RDb25maWdzXCJdWzBdXG59XG5leHBvcnQgY29uc3QgdGVzdE1vZHVsZVBhcmFtc1NjaGVtYSA9IHJ1bk1vZHVsZUJhc2VTY2hlbWFcbiAgLmtleXMoe1xuICAgIHRlc3RDb25maWc6IHRlc3RDb25maWdTY2hlbWEsXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0VGVzdFJlc3VsdFBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpbk1vZHVsZUFjdGlvblBhcmFtc0Jhc2U8VD4ge1xuICB0ZXN0TmFtZTogc3RyaW5nXG4gIHZlcnNpb246IE1vZHVsZVZlcnNpb25cbn1cbmV4cG9ydCBjb25zdCBnZXRUZXN0UmVzdWx0UGFyYW1zU2NoZW1hID0gbW9kdWxlQWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICB0ZXN0TmFtZTogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJBIHVuaXF1ZSBuYW1lIHRvIGlkZW50aWZ5IHRoZSB0ZXN0IHJ1bi5cIiksXG4gICAgdmVyc2lvbjogbW9kdWxlVmVyc2lvblNjaGVtYSxcbiAgfSlcblxuLyoqXG4gKiBTZXJ2aWNlIGFjdGlvbnNcbiAqL1xuZXhwb3J0IGludGVyZmFjZSBHZXRTZXJ2aWNlU3RhdHVzUGFyYW1zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IGV4dGVuZHMgUGx1Z2luU2VydmljZUFjdGlvblBhcmFtc0Jhc2U8VD4ge1xuICBydW50aW1lQ29udGV4dDogUnVudGltZUNvbnRleHRcbn1cbmV4cG9ydCBjb25zdCBnZXRTZXJ2aWNlU3RhdHVzUGFyYW1zU2NoZW1hID0gc2VydmljZUFjdGlvblBhcmFtc1NjaGVtYVxuICAua2V5cyh7XG4gICAgcnVudGltZUNvbnRleHQ6IHJ1bnRpbWVDb250ZXh0U2NoZW1hLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIERlcGxveVNlcnZpY2VQYXJhbXM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gZXh0ZW5kcyBQbHVnaW5TZXJ2aWNlQWN0aW9uUGFyYW1zQmFzZTxUPiB7XG4gIGZvcmNlOiBib29sZWFuXG4gIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dFxufVxuZXhwb3J0IGNvbnN0IGRlcGxveVNlcnZpY2VQYXJhbXNTY2hlbWEgPSBzZXJ2aWNlQWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBmb3JjZTogSm9pLmJvb2xlYW4oKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiV2hldGhlciB0byBmb3JjZSBhIHJlLWRlcGxveSwgZXZlbiBpZiB0aGUgc2VydmljZSBpcyBhbHJlYWR5IGRlcGxveWVkLlwiKSxcbiAgICBydW50aW1lQ29udGV4dDogcnVudGltZUNvbnRleHRTY2hlbWEsXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgRGVsZXRlU2VydmljZVBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpblNlcnZpY2VBY3Rpb25QYXJhbXNCYXNlPFQ+IHtcbiAgcnVudGltZUNvbnRleHQ6IFJ1bnRpbWVDb250ZXh0XG59XG5leHBvcnQgY29uc3QgZGVsZXRlU2VydmljZVBhcmFtc1NjaGVtYSA9IHNlcnZpY2VBY3Rpb25QYXJhbXNTY2hlbWFcbiAgLmtleXMoe1xuICAgIHJ1bnRpbWVDb250ZXh0OiBydW50aW1lQ29udGV4dFNjaGVtYSxcbiAgfSlcblxuZXhwb3J0IGludGVyZmFjZSBHZXRTZXJ2aWNlT3V0cHV0c1BhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiBleHRlbmRzIFBsdWdpblNlcnZpY2VBY3Rpb25QYXJhbXNCYXNlPFQ+IHsgfVxuZXhwb3J0IGNvbnN0IGdldFNlcnZpY2VPdXRwdXRzUGFyYW1zU2NoZW1hID0gc2VydmljZUFjdGlvblBhcmFtc1NjaGVtYVxuXG5leHBvcnQgaW50ZXJmYWNlIEV4ZWNJblNlcnZpY2VQYXJhbXM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gZXh0ZW5kcyBQbHVnaW5TZXJ2aWNlQWN0aW9uUGFyYW1zQmFzZTxUPiB7XG4gIGNvbW1hbmQ6IHN0cmluZ1tdXG4gIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dFxufVxuZXhwb3J0IGNvbnN0IGV4ZWNJblNlcnZpY2VQYXJhbXNTY2hlbWEgPSBzZXJ2aWNlQWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHtcbiAgICBjb21tYW5kOiBqb2lBcnJheShKb2kuc3RyaW5nKCkpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgY29tbWFuZCB0byBydW4gYWxvbmdzaWRlIHRoZSBzZXJ2aWNlLlwiKSxcbiAgICBydW50aW1lQ29udGV4dDogcnVudGltZUNvbnRleHRTY2hlbWEsXG4gIH0pXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2V0U2VydmljZUxvZ3NQYXJhbXM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gZXh0ZW5kcyBQbHVnaW5TZXJ2aWNlQWN0aW9uUGFyYW1zQmFzZTxUPiB7XG4gIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dFxuICBzdHJlYW06IFN0cmVhbTxTZXJ2aWNlTG9nRW50cnk+XG4gIHRhaWw6IGJvb2xlYW5cbiAgc3RhcnRUaW1lPzogRGF0ZVxufVxuZXhwb3J0IGNvbnN0IGdldFNlcnZpY2VMb2dzUGFyYW1zU2NoZW1hID0gc2VydmljZUFjdGlvblBhcmFtc1NjaGVtYVxuICAua2V5cyh7XG4gICAgcnVudGltZUNvbnRleHQ6IHJ1bnRpbWVDb250ZXh0U2NoZW1hLFxuICAgIHN0cmVhbTogSm9pLm9iamVjdCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJBIFN0cmVhbSBvYmplY3QsIHRvIHdyaXRlIHRoZSBsb2dzIHRvLlwiKSxcbiAgICB0YWlsOiBKb2kuYm9vbGVhbigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJXaGV0aGVyIHRvIGtlZXAgbGlzdGVuaW5nIGZvciBsb2dzIHVudGlsIGFib3J0ZWQuXCIpLFxuICAgIHN0YXJ0VGltZTogSm9pLmRhdGUoKVxuICAgICAgLm9wdGlvbmFsKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIklmIHNldCwgb25seSByZXR1cm4gbG9ncyB0aGF0IGFyZSBhcyBuZXcgb3IgbmV3ZXIgdGhhbiB0aGlzIGRhdGUuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFJ1blNlcnZpY2VQYXJhbXM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gZXh0ZW5kcyBQbHVnaW5TZXJ2aWNlQWN0aW9uUGFyYW1zQmFzZTxUPiB7XG4gIGludGVyYWN0aXZlOiBib29sZWFuXG4gIHJ1bnRpbWVDb250ZXh0OiBSdW50aW1lQ29udGV4dFxuICBzaWxlbnQ6IGJvb2xlYW5cbiAgdGltZW91dD86IG51bWJlclxufVxuZXhwb3J0IGNvbnN0IHJ1blNlcnZpY2VQYXJhbXNTY2hlbWEgPSBzZXJ2aWNlQWN0aW9uUGFyYW1zU2NoZW1hXG4gIC5rZXlzKHJ1bkJhc2VQYXJhbXMpXG5cbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZUFjdGlvblBhcmFtczxUIGV4dGVuZHMgTW9kdWxlID0gTW9kdWxlPiB7XG4gIGdldFNlcnZpY2VTdGF0dXM6IEdldFNlcnZpY2VTdGF0dXNQYXJhbXM8VD5cbiAgZGVwbG95U2VydmljZTogRGVwbG95U2VydmljZVBhcmFtczxUPlxuICBkZWxldGVTZXJ2aWNlOiBEZWxldGVTZXJ2aWNlUGFyYW1zPFQ+XG4gIGdldFNlcnZpY2VPdXRwdXRzOiBHZXRTZXJ2aWNlT3V0cHV0c1BhcmFtczxUPlxuICBleGVjSW5TZXJ2aWNlOiBFeGVjSW5TZXJ2aWNlUGFyYW1zPFQ+XG4gIGdldFNlcnZpY2VMb2dzOiBHZXRTZXJ2aWNlTG9nc1BhcmFtczxUPlxuICBydW5TZXJ2aWNlOiBSdW5TZXJ2aWNlUGFyYW1zPFQ+XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlQWN0aW9uUGFyYW1zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IHtcbiAgZGVzY3JpYmVUeXBlOiBEZXNjcmliZU1vZHVsZVR5cGVQYXJhbXMsXG4gIHZhbGlkYXRlOiBWYWxpZGF0ZU1vZHVsZVBhcmFtczxUPlxuICBnZXRCdWlsZFN0YXR1czogR2V0QnVpbGRTdGF0dXNQYXJhbXM8VD5cbiAgYnVpbGQ6IEJ1aWxkTW9kdWxlUGFyYW1zPFQ+XG4gIHB1c2hNb2R1bGU6IFB1c2hNb2R1bGVQYXJhbXM8VD5cbiAgcHVibGlzaE1vZHVsZTogUHVibGlzaE1vZHVsZVBhcmFtczxUPlxuICBydW5Nb2R1bGU6IFJ1bk1vZHVsZVBhcmFtczxUPlxuICB0ZXN0TW9kdWxlOiBUZXN0TW9kdWxlUGFyYW1zPFQ+XG4gIGdldFRlc3RSZXN1bHQ6IEdldFRlc3RSZXN1bHRQYXJhbXM8VD5cbn1cbiJdfQ== diff --git a/garden-service/build/types/plugin/plugin.d.ts b/garden-service/build/types/plugin/plugin.d.ts new file mode 100644 index 00000000000..3ba3811009b --- /dev/null +++ b/garden-service/build/types/plugin/plugin.d.ts @@ -0,0 +1,60 @@ +import * as Joi from "joi"; +import { Module } from "../module"; +import { LogNode } from "../../logger/log-node"; +import { Provider } from "../../config/project"; +import { ModuleActionOutputs, PluginActionOutputs, ServiceActionOutputs } from "./outputs"; +import { ModuleActionParams, PluginActionParams, ServiceActionParams } from "./params"; +export declare type PluginActions = { + [P in keyof PluginActionParams]: (params: PluginActionParams[P]) => PluginActionOutputs[P]; +}; +export declare type ServiceActions = { + [P in keyof ServiceActionParams]: (params: ServiceActionParams[P]) => ServiceActionOutputs[P]; +}; +export declare type ModuleActions = { + [P in keyof ModuleActionParams]: (params: ModuleActionParams[P]) => ModuleActionOutputs[P]; +}; +export declare type ModuleAndServiceActions = ModuleActions & ServiceActions; +export declare type PluginActionName = keyof PluginActions; +export declare type ServiceActionName = keyof ServiceActions; +export declare type ModuleActionName = keyof ModuleActions; +export interface PluginActionDescription { + description: string; + paramsSchema: Joi.Schema; + resultSchema: Joi.Schema; +} +export declare const pluginActionDescriptions: { + [P in PluginActionName]: PluginActionDescription; +}; +export declare const serviceActionDescriptions: { + [P in ServiceActionName]: PluginActionDescription; +}; +export declare const moduleActionDescriptions: { + [P in ModuleActionName | ServiceActionName]: PluginActionDescription; +}; +export declare const pluginActionNames: PluginActionName[]; +export declare const serviceActionNames: ServiceActionName[]; +export declare const moduleActionNames: ModuleActionName[]; +export interface GardenPlugin { + config?: object; + configKeys?: string[]; + modules?: string[]; + actions?: Partial; + moduleActions?: { + [moduleType: string]: Partial; + }; +} +export interface PluginFactoryParams { + config: T["config"]; + logEntry: LogNode; + projectName: string; +} +export interface PluginFactory { + (params: PluginFactoryParams): GardenPlugin | Promise; +} +export declare type RegisterPluginParam = string | PluginFactory; +export interface Plugins { + [name: string]: RegisterPluginParam; +} +export declare const pluginSchema: Joi.ObjectSchema; +export declare const pluginModuleSchema: Joi.ObjectSchema; +//# sourceMappingURL=plugin.d.ts.map \ No newline at end of file diff --git a/garden-service/build/types/plugin/plugin.js b/garden-service/build/types/plugin/plugin.js new file mode 100644 index 00000000000..e6d5f3a3fae --- /dev/null +++ b/garden-service/build/types/plugin/plugin.js @@ -0,0 +1,293 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const lodash_1 = require("lodash"); +const dedent = require("dedent"); +const common_1 = require("../../config/common"); +const service_1 = require("../service"); +const service_2 = require("../../config/service"); +const params_1 = require("./params"); +const outputs_1 = require("./outputs"); +const params_2 = require("./params"); +exports.pluginActionDescriptions = { + getEnvironmentStatus: { + description: dedent ` + Check if the current environment is ready for use by this plugin. Use this action in combination + with \`prepareEnvironment\`. + + Called before \`prepareEnvironment\`. If this returns \`ready: true\`, the + \`prepareEnvironment\` action is not called. + + If this returns \`needUserInput: true\`, the process may throw an error and guide the user to + run \`garden init\`, so that \`prepareEnvironment\` can safely ask for user input. Otherwise the + \`prepareEnvironment\` handler may be run implicitly ahead of actions like \`deployService\`, + \`runModule\` etc. + `, + paramsSchema: params_2.getEnvironmentStatusParamsSchema, + resultSchema: outputs_1.environmentStatusSchema, + }, + prepareEnvironment: { + description: dedent ` + Make sure the environment is set up for this plugin. Use this action to do any bootstrapping required + before deploying services. + + Called ahead of any service runtime actions (such as \`deployService\`, + \`runModule\` and \`testModule\`), unless \`getEnvironmentStatus\` returns \`ready: true\` or + \`needUserInput: true\`. + + Important: If your handler does require user input, please be sure to indicate that via the + \`getEnvironmentStatus\` handler. If this provider's \`getEnvironmentStatus\` returns \`needUserInput: true\`, + this is only called via the \`garden init\` command, so that the handler can safely request user input via + the CLI. + `, + paramsSchema: params_1.prepareEnvironmentParamsSchema, + resultSchema: outputs_1.prepareEnvironmentResultSchema, + }, + cleanupEnvironment: { + description: dedent ` + Clean up any runtime components, services etc. that this plugin has deployed in the environment. + + Like \`prepareEnvironment\`, this is executed sequentially, so handlers are allowed to request user input + if necessary. + + Called by the \`garden delete environment\` command. + `, + paramsSchema: params_1.cleanupEnvironmentParamsSchema, + resultSchema: outputs_1.cleanupEnvironmentResultSchema, + }, + getSecret: { + description: dedent ` + Retrieve a secret value for this plugin in the current environment (as set via \`setSecret\`). + `, + paramsSchema: params_1.getSecretParamsSchema, + resultSchema: outputs_1.getSecretResultSchema, + }, + setSecret: { + description: dedent ` + Set a secret for this plugin in the current environment. These variables are + not used by the Garden framework, but the plugin may expose them to services etc. at runtime + (e.g. as environment variables or mounted in containers). + `, + paramsSchema: params_1.setSecretParamsSchema, + resultSchema: outputs_1.setSecretResultSchema, + }, + deleteSecret: { + description: dedent ` + Remove a secret for this plugin in the current environment (as set via \`setSecret\`). + `, + paramsSchema: params_1.deleteSecretParamsSchema, + resultSchema: outputs_1.deleteSecretResultSchema, + }, +}; +exports.serviceActionDescriptions = { + getServiceStatus: { + description: dedent ` + Check and return the current runtime status of a service. + + Called ahead of any actions that expect a service to be running, as well as the + \`garden get status\` command. + `, + paramsSchema: params_1.getServiceStatusParamsSchema, + resultSchema: service_1.serviceStatusSchema, + }, + deployService: { + description: dedent ` + Deploy the specified service. This should wait until the service is ready and accessible, + and fail if the service doesn't reach a ready state. + + Called by the \`garden deploy\` and \`garden dev\` commands. + `, + paramsSchema: params_1.deployServiceParamsSchema, + resultSchema: service_1.serviceStatusSchema, + }, + deleteService: { + description: dedent ` + Terminate a deployed service. This should wait until the service is no longer running. + + Called by the \`garden delete service\` command. + `, + paramsSchema: params_1.deleteServiceParamsSchema, + resultSchema: service_1.serviceStatusSchema, + }, + getServiceOutputs: { + description: "DEPRECATED", + paramsSchema: params_1.getServiceOutputsParamsSchema, + resultSchema: service_2.serviceOutputsSchema, + }, + execInService: { + description: dedent ` + Execute the specified command next to a running service, e.g. in a service container. + + Called by the \`garden exec\` command. + `, + paramsSchema: params_1.execInServiceParamsSchema, + resultSchema: outputs_1.execInServiceResultSchema, + }, + getServiceLogs: { + description: dedent ` + Retrieve a stream of logs for the specified service, optionally waiting listening for new logs. + + Called by the \`garden logs\` command. + `, + paramsSchema: params_1.getServiceLogsParamsSchema, + resultSchema: outputs_1.getServiceLogsResultSchema, + }, + runService: { + description: dedent ` + Run an ad-hoc instance of the specified service. This should wait until the service completes + execution, and should ideally attach it to the terminal (i.e. pipe the output from the service + to the console, as well as pipe the input from the console to the running service). + + Called by the \`garden run service\` command. + `, + paramsSchema: params_1.runServiceParamsSchema, + resultSchema: outputs_1.runResultSchema, + }, +}; +exports.moduleActionDescriptions = Object.assign({ + // TODO: implement this method (it is currently not defined or used) + describeType: { + description: dedent ` + Return documentation and a schema description of the module type. + + The documentation should be in markdown format. A reference for the module type is automatically + generated based on the provided schema, and a section appended to the provided documentation. + + The schema should be a valid OpenAPI schema describing the configuration keys that the user + should use under the \`module\` key in a \`garden.yml\` configuration file. Note that the schema + should not specify the built-in fields (such as \`name\`, \`type\` and \`description\`). + + Used when auto-generating framework documentation. + `, + paramsSchema: params_1.describeModuleTypeParamsSchema, + resultSchema: outputs_1.moduleTypeDescriptionSchema, + }, validate: { + description: dedent ` + Validate and optionally transform the given module configuration. + + Note that this does not need to perform structural schema validation (the framework does that + automatically), but should in turn perform semantic validation to make sure the configuration is sane. + + This can and should also be used to further specify the semantics of the module, including service + configuration and test configuration. Since services and tests are not specified using built-in + framework configuration fields, this action needs to specify those via the \`serviceConfigs\` and + \`testConfigs\` output keys. + `, + paramsSchema: params_1.validateModuleParamsSchema, + resultSchema: outputs_1.validateModuleResultSchema, + }, getBuildStatus: { + description: dedent ` + Check and return the build status of a module, i.e. whether the current version been built. + + Called before running the \`build\` action, which is not run if this returns \`{ ready: true }\`. + `, + paramsSchema: params_1.getBuildStatusParamsSchema, + resultSchema: outputs_1.buildStatusSchema, + }, build: { + description: dedent ` + Build the current version of a module. This must wait until the build is complete before returning. + + Called ahead of a number of actions, including \`deployService\`, \`pushModule\` and \`publishModule\`. + `, + paramsSchema: params_1.buildModuleParamsSchema, + resultSchema: outputs_1.buildModuleResultSchema, + }, pushModule: { + description: dedent ` + Push the build for current version of a module to the deployment environment, making it accessible + to the development environment. An example being a container registry or artifact registry that's + available to the deployment environment when deploying. + + Note the distinction to \`publishModule\` which may, depending on the module type, work similarly but + is only called when explicitly calling the \`garden publish\`. + + This is usually not necessary for plugins that run locally. + + Called before the \`deployService\` action. + `, + paramsSchema: params_1.pushModuleParamsSchema, + resultSchema: outputs_1.pushModuleResultSchema, + }, publishModule: { + description: dedent ` + Publish a built module to a remote registry. + + Note the distinction to \`pushModule\` which may, depending on the module type, work similarly but + is automatically called ahead of \`deployService\`. + + Called by the \`garden publish\` command. + `, + paramsSchema: params_1.publishModuleParamsSchema, + resultSchema: outputs_1.publishModuleResultSchema, + }, runModule: { + description: dedent ` + Run an ad-hoc instance of the specified module. This should wait until the execution completes, + and should ideally attach it to the terminal (i.e. pipe the output from the service + to the console, as well as pipe the input from the console to the running service). + + Called by the \`garden run module\` command. + `, + paramsSchema: params_1.runModuleParamsSchema, + resultSchema: outputs_1.runResultSchema, + }, testModule: { + description: dedent ` + Run the specified test for a module. + + This should complete the test run and return the logs from the test run, and signal whether the + tests completed successfully. + + It should also store the test results and provide the accompanying \`getTestResult\` handler, + so that the same version does not need to be tested multiple times. + + Note that the version string provided to this handler may be a hash of the module's version, as + well as any runtime dependencies configured for the test, so it may not match the current version + of the module itself. + `, + paramsSchema: params_1.testModuleParamsSchema, + resultSchema: outputs_1.testResultSchema, + }, getTestResult: { + description: dedent ` + Retrieve the test result for the specified version. Use this along with the \`testModule\` handler + to avoid testing the same code repeatedly. + + Note that the version string provided to this handler may be a hash of the module's version, as + well as any runtime dependencies configured for the test, so it may not match the current version + of the module itself. + `, + paramsSchema: params_1.getTestResultParamsSchema, + resultSchema: outputs_1.getTestResultSchema, + } }, exports.serviceActionDescriptions); +exports.pluginActionNames = Object.keys(exports.pluginActionDescriptions); +exports.serviceActionNames = Object.keys(exports.serviceActionDescriptions); +exports.moduleActionNames = Object.keys(exports.moduleActionDescriptions); +exports.pluginSchema = Joi.object() + .keys({ + config: Joi.object() + .meta({ extendable: true }) + .description("Plugins may use this key to override or augment their configuration " + + "(as specified in the garden.yml provider configuration."), + modules: common_1.joiArray(Joi.string()) + .description("Plugins may optionally provide paths to Garden modules that are loaded as part of the plugin. " + + "This is useful, for example, to provide build dependencies for other modules " + + "or as part of the plugin operation."), + // TODO: document plugin actions further + actions: Joi.object().keys(lodash_1.mapValues(exports.pluginActionDescriptions, () => Joi.func())) + .description("A map of plugin action handlers provided by the plugin."), + moduleActions: common_1.joiIdentifierMap(Joi.object().keys(lodash_1.mapValues(exports.moduleActionDescriptions, () => Joi.func())).description("A map of module names and module action handlers provided by the plugin.")), +}) + .description("The schema for Garden plugins."); +exports.pluginModuleSchema = Joi.object() + .keys({ + name: common_1.joiIdentifier(), + gardenPlugin: Joi.func().required() + .description("The initialization function for the plugin. Should return a valid Garden plugin object."), +}) + .unknown(true) + .description("A module containing a Garden plugin."); + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInR5cGVzL3BsdWdpbi9wbHVnaW4udHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IjtBQUFBOzs7Ozs7R0FNRzs7QUFFSCwyQkFBMEI7QUFDMUIsbUNBQWtDO0FBQ2xDLGlDQUFpQztBQUNqQyxnREFJNEI7QUFFNUIsd0NBQWdEO0FBQ2hELGtEQUEyRDtBQUczRCxxQ0FzQmlCO0FBQ2pCLHVDQXFCa0I7QUFDbEIscUNBS2lCO0FBMEJKLFFBQUEsd0JBQXdCLEdBQXlEO0lBQzVGLG9CQUFvQixFQUFFO1FBQ3BCLFdBQVcsRUFBRSxNQUFNLENBQUE7Ozs7Ozs7Ozs7O0tBV2xCO1FBQ0QsWUFBWSxFQUFFLHlDQUFnQztRQUM5QyxZQUFZLEVBQUUsaUNBQXVCO0tBQ3RDO0lBQ0Qsa0JBQWtCLEVBQUU7UUFDbEIsV0FBVyxFQUFFLE1BQU0sQ0FBQTs7Ozs7Ozs7Ozs7O0tBWWxCO1FBQ0QsWUFBWSxFQUFFLHVDQUE4QjtRQUM1QyxZQUFZLEVBQUUsd0NBQThCO0tBQzdDO0lBQ0Qsa0JBQWtCLEVBQUU7UUFDbEIsV0FBVyxFQUFFLE1BQU0sQ0FBQTs7Ozs7OztLQU9sQjtRQUNELFlBQVksRUFBRSx1Q0FBOEI7UUFDNUMsWUFBWSxFQUFFLHdDQUE4QjtLQUM3QztJQUVELFNBQVMsRUFBRTtRQUNULFdBQVcsRUFBRSxNQUFNLENBQUE7O0tBRWxCO1FBQ0QsWUFBWSxFQUFFLDhCQUFxQjtRQUNuQyxZQUFZLEVBQUUsK0JBQXFCO0tBQ3BDO0lBQ0QsU0FBUyxFQUFFO1FBQ1QsV0FBVyxFQUFFLE1BQU0sQ0FBQTs7OztLQUlsQjtRQUNELFlBQVksRUFBRSw4QkFBcUI7UUFDbkMsWUFBWSxFQUFFLCtCQUFxQjtLQUNwQztJQUNELFlBQVksRUFBRTtRQUNaLFdBQVcsRUFBRSxNQUFNLENBQUE7O0tBRWxCO1FBQ0QsWUFBWSxFQUFFLGlDQUF3QjtRQUN0QyxZQUFZLEVBQUUsa0NBQXdCO0tBQ3ZDO0NBQ0YsQ0FBQTtBQUVZLFFBQUEseUJBQXlCLEdBQTBEO0lBQzlGLGdCQUFn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LENBQUMsSUFBSSxDQUFDO0tBQ2IsV0FBVyxDQUFDLHNDQUFzQyxDQUFDLENBQUEiLCJmaWxlIjoidHlwZXMvcGx1Z2luL3BsdWdpbi5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgKiBhcyBKb2kgZnJvbSBcImpvaVwiXG5pbXBvcnQgeyBtYXBWYWx1ZXMgfSBmcm9tIFwibG9kYXNoXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQge1xuICBqb2lBcnJheSxcbiAgam9pSWRlbnRpZmllcixcbiAgam9pSWRlbnRpZmllck1hcCxcbn0gZnJvbSBcIi4uLy4uL2NvbmZpZy9jb21tb25cIlxuaW1wb3J0IHsgTW9kdWxlIH0gZnJvbSBcIi4uL21vZHVsZVwiXG5pbXBvcnQgeyBzZXJ2aWNlU3RhdHVzU2NoZW1hIH0gZnJvbSBcIi4uL3NlcnZpY2VcIlxuaW1wb3J0IHsgc2VydmljZU91dHB1dHNTY2hlbWEgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3NlcnZpY2VcIlxuaW1wb3J0IHsgTG9nTm9kZSB9IGZyb20gXCIuLi8uLi9sb2dnZXIvbG9nLW5vZGVcIlxuaW1wb3J0IHsgUHJvdmlkZXIgfSBmcm9tIFwiLi4vLi4vY29uZmlnL3Byb2plY3RcIlxuaW1wb3J0IHtcbiAgcHJlcGFyZUVudmlyb25tZW50UGFyYW1zU2NoZW1hLFxuICBjbGVhbnVwRW52aXJvbm1lbnRQYXJhbXNTY2hlbWEsXG4gIGdldFNlY3JldFBhcmFtc1NjaGVtYSxcbiAgc2V0U2VjcmV0UGFyYW1zU2NoZW1hLFxuICBkZWxldGVTZWNyZXRQYXJhbXNTY2hlbWEsXG4gIGdldFNlcnZpY2VTdGF0dXNQYXJhbXNTY2hlbWEsXG4gIGRlcGxveVNlcnZpY2VQYXJhbXNTY2hlbWEsXG4gIGRlbGV0ZVNlcnZpY2VQYXJhbXNTY2hlbWEsXG4gIGdldFNlcnZpY2VPdXRwdXRzUGFyYW1zU2NoZW1hLFxuICBleGVjSW5TZXJ2aWNlUGFyYW1zU2NoZW1hLFxuICBnZXRTZXJ2aWNlTG9nc1BhcmFtc1NjaGVtYSxcbiAgcnVuU2VydmljZVBhcmFtc1NjaGVtYSxcbiAgZGVzY3JpYmVNb2R1bGVUeXBlUGFyYW1zU2NoZW1hLFxuICB2YWxpZGF0ZU1vZHVsZVBhcmFtc1NjaGVtYSxcbiAgZ2V0QnVpbGRTdGF0dXNQYXJhbXNTY2hlbWEsXG4gIGJ1aWxkTW9kdWxlUGFyYW1zU2NoZW1hLFxuICBwdXNoTW9kdWxlUGFyYW1zU2NoZW1hLFxuICBydW5Nb2R1bGVQYXJhbXNTY2hlbWEsXG4gIHRlc3RNb2R1bGVQYXJhbXNTY2hlbWEsXG4gIGdldFRlc3RSZXN1bHRQYXJhbXNTY2hlbWEsXG4gIHB1Ymxpc2hNb2R1bGVQYXJhbXNTY2hlbWEsXG59IGZyb20gXCIuL3BhcmFtc1wiXG5pbXBvcnQge1xuICBidWlsZE1vZHVsZVJlc3VsdFNjaGVtYSxcbiAgYnVpbGRTdGF0dXNTY2hlbWEsXG4gIHByZXBhcmVFbnZpcm9ubWVudFJlc3VsdFNjaGVtYSxcbiAgZGVsZXRlU2VjcmV0UmVzdWx0U2NoZW1hLFxuICBjbGVhbnVwRW52aXJvbm1lbnRSZXN1bHRTY2hlbWEsXG4gIGVudmlyb25tZW50U3RhdHVzU2NoZW1hLFxuICBleGVjSW5TZXJ2aWNlUmVzdWx0U2NoZW1hLFxuICBnZXRTZWNyZXRSZXN1bHRTY2hlbWEsXG4gIGdldFNlcnZpY2VMb2dzUmVzdWx0U2NoZW1hLFxuICBnZXRUZXN0UmVzdWx0U2NoZW1hLFxuICBNb2R1bGVBY3Rpb25PdXRwdXRzLFxuICBtb2R1bGVUeXBlRGVzY3JpcHRpb25TY2hlbWEsXG4gIFBsdWdpbkFjdGlvbk91dHB1dHMsXG4gIHB1c2hNb2R1bGVSZXN1bHRTY2hlbWEsXG4gIHJ1blJlc3VsdFNjaGVtYSxcbiAgU2VydmljZUFjdGlvbk91dHB1dHMsXG4gIHNldFNlY3JldFJlc3VsdFNjaGVtYSxcbiAgdGVzdFJlc3VsdFNjaGVtYSxcbiAgdmFsaWRhdGVNb2R1bGVSZXN1bHRTY2hlbWEsXG4gIHB1Ymxpc2hNb2R1bGVSZXN1bHRTY2hlbWEsXG59IGZyb20gXCIuL291dHB1dHNcIlxuaW1wb3J0IHtcbiAgTW9kdWxlQWN0aW9uUGFyYW1zLFxuICBQbHVnaW5BY3Rpb25QYXJhbXMsXG4gIFNlcnZpY2VBY3Rpb25QYXJhbXMsXG4gIGdldEVudmlyb25tZW50U3RhdHVzUGFyYW1zU2NoZW1hLFxufSBmcm9tIFwiLi9wYXJhbXNcIlxuXG5leHBvcnQgdHlwZSBQbHVnaW5BY3Rpb25zID0ge1xuICBbUCBpbiBrZXlvZiBQbHVnaW5BY3Rpb25QYXJhbXNdOiAocGFyYW1zOiBQbHVnaW5BY3Rpb25QYXJhbXNbUF0pID0+IFBsdWdpbkFjdGlvbk91dHB1dHNbUF1cbn1cblxuZXhwb3J0IHR5cGUgU2VydmljZUFjdGlvbnM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gPSB7XG4gIFtQIGluIGtleW9mIFNlcnZpY2VBY3Rpb25QYXJhbXM8VD5dOiAocGFyYW1zOiBTZXJ2aWNlQWN0aW9uUGFyYW1zPFQ+W1BdKSA9PiBTZXJ2aWNlQWN0aW9uT3V0cHV0c1tQXVxufVxuXG5leHBvcnQgdHlwZSBNb2R1bGVBY3Rpb25zPFQgZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+ID0ge1xuICBbUCBpbiBrZXlvZiBNb2R1bGVBY3Rpb25QYXJhbXM8VD5dOiAocGFyYW1zOiBNb2R1bGVBY3Rpb25QYXJhbXM8VD5bUF0pID0+IE1vZHVsZUFjdGlvbk91dHB1dHNbUF1cbn1cblxuZXhwb3J0IHR5cGUgTW9kdWxlQW5kU2VydmljZUFjdGlvbnM8VCBleHRlbmRzIE1vZHVsZSA9IE1vZHVsZT4gPSBNb2R1bGVBY3Rpb25zPFQ+ICYgU2VydmljZUFjdGlvbnM8VD5cblxuZXhwb3J0IHR5cGUgUGx1Z2luQWN0aW9uTmFtZSA9IGtleW9mIFBsdWdpbkFjdGlvbnNcbmV4cG9ydCB0eXBlIFNlcnZpY2VBY3Rpb25OYW1lID0ga2V5b2YgU2VydmljZUFjdGlvbnNcbmV4cG9ydCB0eXBlIE1vZHVsZUFjdGlvbk5hbWUgPSBrZXlvZiBNb2R1bGVBY3Rpb25zXG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luQWN0aW9uRGVzY3JpcHRpb24ge1xuICBkZXNjcmlwdGlvbjogc3RyaW5nXG4gIHBhcmFtc1NjaGVtYTogSm9pLlNjaGVtYVxuICByZXN1bHRTY2hlbWE6IEpvaS5TY2hlbWFcbn1cblxuZXhwb3J0IGNvbnN0IHBsdWdpbkFjdGlvbkRlc2NyaXB0aW9uczogeyBbUCBpbiBQbHVnaW5BY3Rpb25OYW1lXTogUGx1Z2luQWN0aW9uRGVzY3JpcHRpb24gfSA9IHtcbiAgZ2V0RW52aXJvbm1lbnRTdGF0dXM6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgQ2hlY2sgaWYgdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQgaXMgcmVhZHkgZm9yIHVzZSBieSB0aGlzIHBsdWdpbi4gVXNlIHRoaXMgYWN0aW9uIGluIGNvbWJpbmF0aW9uXG4gICAgICB3aXRoIFxcYHByZXBhcmVFbnZpcm9ubWVudFxcYC5cblxuICAgICAgQ2FsbGVkIGJlZm9yZSBcXGBwcmVwYXJlRW52aXJvbm1lbnRcXGAuIElmIHRoaXMgcmV0dXJucyBcXGByZWFkeTogdHJ1ZVxcYCwgdGhlXG4gICAgICBcXGBwcmVwYXJlRW52aXJvbm1lbnRcXGAgYWN0aW9uIGlzIG5vdCBjYWxsZWQuXG5cbiAgICAgIElmIHRoaXMgcmV0dXJucyBcXGBuZWVkVXNlcklucHV0OiB0cnVlXFxgLCB0aGUgcHJvY2VzcyBtYXkgdGhyb3cgYW4gZXJyb3IgYW5kIGd1aWRlIHRoZSB1c2VyIHRvXG4gICAgICBydW4gXFxgZ2FyZGVuIGluaXRcXGAsIHNvIHRoYXQgXFxgcHJlcGFyZUVudmlyb25tZW50XFxgIGNhbiBzYWZlbHkgYXNrIGZvciB1c2VyIGlucHV0LiBPdGhlcndpc2UgdGhlXG4gICAgICBcXGBwcmVwYXJlRW52aXJvbm1lbnRcXGAgaGFuZGxlciBtYXkgYmUgcnVuIGltcGxpY2l0bHkgYWhlYWQgb2YgYWN0aW9ucyBsaWtlIFxcYGRlcGxveVNlcnZpY2VcXGAsXG4gICAgICBcXGBydW5Nb2R1bGVcXGAgZXRjLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBnZXRFbnZpcm9ubWVudFN0YXR1c1BhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGVudmlyb25tZW50U3RhdHVzU2NoZW1hLFxuICB9LFxuICBwcmVwYXJlRW52aXJvbm1lbnQ6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgTWFrZSBzdXJlIHRoZSBlbnZpcm9ubWVudCBpcyBzZXQgdXAgZm9yIHRoaXMgcGx1Z2luLiBVc2UgdGhpcyBhY3Rpb24gdG8gZG8gYW55IGJvb3RzdHJhcHBpbmcgcmVxdWlyZWRcbiAgICAgIGJlZm9yZSBkZXBsb3lpbmcgc2VydmljZXMuXG5cbiAgICAgIENhbGxlZCBhaGVhZCBvZiBhbnkgc2VydmljZSBydW50aW1lIGFjdGlvbnMgKHN1Y2ggYXMgXFxgZGVwbG95U2VydmljZVxcYCxcbiAgICAgIFxcYHJ1bk1vZHVsZVxcYCBhbmQgXFxgdGVzdE1vZHVsZVxcYCksIHVubGVzcyBcXGBnZXRFbnZpcm9ubWVudFN0YXR1c1xcYCByZXR1cm5zIFxcYHJlYWR5OiB0cnVlXFxgIG9yXG4gICAgICBcXGBuZWVkVXNlcklucHV0OiB0cnVlXFxgLlxuXG4gICAgICBJbXBvcnRhbnQ6IElmIHlvdXIgaGFuZGxlciBkb2VzIHJlcXVpcmUgdXNlciBpbnB1dCwgcGxlYXNlIGJlIHN1cmUgdG8gaW5kaWNhdGUgdGhhdCB2aWEgdGhlXG4gICAgICBcXGBnZXRFbnZpcm9ubWVudFN0YXR1c1xcYCBoYW5kbGVyLiBJZiB0aGlzIHByb3ZpZGVyJ3MgXFxgZ2V0RW52aXJvbm1lbnRTdGF0dXNcXGAgcmV0dXJucyBcXGBuZWVkVXNlcklucHV0OiB0cnVlXFxgLFxuICAgICAgdGhpcyBpcyBvbmx5IGNhbGxlZCB2aWEgdGhlIFxcYGdhcmRlbiBpbml0XFxgIGNvbW1hbmQsIHNvIHRoYXQgdGhlIGhhbmRsZXIgY2FuIHNhZmVseSByZXF1ZXN0IHVzZXIgaW5wdXQgdmlhXG4gICAgICB0aGUgQ0xJLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBwcmVwYXJlRW52aXJvbm1lbnRQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiBwcmVwYXJlRW52aXJvbm1lbnRSZXN1bHRTY2hlbWEsXG4gIH0sXG4gIGNsZWFudXBFbnZpcm9ubWVudDoge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBDbGVhbiB1cCBhbnkgcnVudGltZSBjb21wb25lbnRzLCBzZXJ2aWNlcyBldGMuIHRoYXQgdGhpcyBwbHVnaW4gaGFzIGRlcGxveWVkIGluIHRoZSBlbnZpcm9ubWVudC5cblxuICAgICAgTGlrZSBcXGBwcmVwYXJlRW52aXJvbm1lbnRcXGAsIHRoaXMgaXMgZXhlY3V0ZWQgc2VxdWVudGlhbGx5LCBzbyBoYW5kbGVycyBhcmUgYWxsb3dlZCB0byByZXF1ZXN0IHVzZXIgaW5wdXRcbiAgICAgIGlmIG5lY2Vzc2FyeS5cblxuICAgICAgQ2FsbGVkIGJ5IHRoZSBcXGBnYXJkZW4gZGVsZXRlIGVudmlyb25tZW50XFxgIGNvbW1hbmQuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IGNsZWFudXBFbnZpcm9ubWVudFBhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGNsZWFudXBFbnZpcm9ubWVudFJlc3VsdFNjaGVtYSxcbiAgfSxcblxuICBnZXRTZWNyZXQ6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUmV0cmlldmUgYSBzZWNyZXQgdmFsdWUgZm9yIHRoaXMgcGx1Z2luIGluIHRoZSBjdXJyZW50IGVudmlyb25tZW50IChhcyBzZXQgdmlhIFxcYHNldFNlY3JldFxcYCkuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IGdldFNlY3JldFBhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGdldFNlY3JldFJlc3VsdFNjaGVtYSxcbiAgfSxcbiAgc2V0U2VjcmV0OiB7XG4gICAgZGVzY3JpcHRpb246IGRlZGVudGBcbiAgICAgIFNldCBhIHNlY3JldCBmb3IgdGhpcyBwbHVnaW4gaW4gdGhlIGN1cnJlbnQgZW52aXJvbm1lbnQuIFRoZXNlIHZhcmlhYmxlcyBhcmVcbiAgICAgIG5vdCB1c2VkIGJ5IHRoZSBHYXJkZW4gZnJhbWV3b3JrLCBidXQgdGhlIHBsdWdpbiBtYXkgZXhwb3NlIHRoZW0gdG8gc2VydmljZXMgZXRjLiBhdCBydW50aW1lXG4gICAgICAoZS5nLiBhcyBlbnZpcm9ubWVudCB2YXJpYWJsZXMgb3IgbW91bnRlZCBpbiBjb250YWluZXJzKS5cbiAgICBgLFxuICAgIHBhcmFtc1NjaGVtYTogc2V0U2VjcmV0UGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogc2V0U2VjcmV0UmVzdWx0U2NoZW1hLFxuICB9LFxuICBkZWxldGVTZWNyZXQ6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUmVtb3ZlIGEgc2VjcmV0IGZvciB0aGlzIHBsdWdpbiBpbiB0aGUgY3VycmVudCBlbnZpcm9ubWVudCAoYXMgc2V0IHZpYSBcXGBzZXRTZWNyZXRcXGApLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBkZWxldGVTZWNyZXRQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiBkZWxldGVTZWNyZXRSZXN1bHRTY2hlbWEsXG4gIH0sXG59XG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlQWN0aW9uRGVzY3JpcHRpb25zOiB7IFtQIGluIFNlcnZpY2VBY3Rpb25OYW1lXTogUGx1Z2luQWN0aW9uRGVzY3JpcHRpb24gfSA9IHtcbiAgZ2V0U2VydmljZVN0YXR1czoge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBDaGVjayBhbmQgcmV0dXJuIHRoZSBjdXJyZW50IHJ1bnRpbWUgc3RhdHVzIG9mIGEgc2VydmljZS5cblxuICAgICAgQ2FsbGVkIGFoZWFkIG9mIGFueSBhY3Rpb25zIHRoYXQgZXhwZWN0IGEgc2VydmljZSB0byBiZSBydW5uaW5nLCBhcyB3ZWxsIGFzIHRoZVxuICAgICAgXFxgZ2FyZGVuIGdldCBzdGF0dXNcXGAgY29tbWFuZC5cbiAgICBgLFxuICAgIHBhcmFtc1NjaGVtYTogZ2V0U2VydmljZVN0YXR1c1BhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IHNlcnZpY2VTdGF0dXNTY2hlbWEsXG4gIH0sXG4gIGRlcGxveVNlcnZpY2U6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgRGVwbG95IHRoZSBzcGVjaWZpZWQgc2VydmljZS4gVGhpcyBzaG91bGQgd2FpdCB1bnRpbCB0aGUgc2VydmljZSBpcyByZWFkeSBhbmQgYWNjZXNzaWJsZSxcbiAgICAgIGFuZCBmYWlsIGlmIHRoZSBzZXJ2aWNlIGRvZXNuJ3QgcmVhY2ggYSByZWFkeSBzdGF0ZS5cblxuICAgICAgQ2FsbGVkIGJ5IHRoZSBcXGBnYXJkZW4gZGVwbG95XFxgIGFuZCBcXGBnYXJkZW4gZGV2XFxgIGNvbW1hbmRzLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBkZXBsb3lTZXJ2aWNlUGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogc2VydmljZVN0YXR1c1NjaGVtYSxcbiAgfSxcbiAgZGVsZXRlU2VydmljZToge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBUZXJtaW5hdGUgYSBkZXBsb3llZCBzZXJ2aWNlLiBUaGlzIHNob3VsZCB3YWl0IHVudGlsIHRoZSBzZXJ2aWNlIGlzIG5vIGxvbmdlciBydW5uaW5nLlxuXG4gICAgICBDYWxsZWQgYnkgdGhlIFxcYGdhcmRlbiBkZWxldGUgc2VydmljZVxcYCBjb21tYW5kLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBkZWxldGVTZXJ2aWNlUGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogc2VydmljZVN0YXR1c1NjaGVtYSxcbiAgfSxcbiAgZ2V0U2VydmljZU91dHB1dHM6IHtcbiAgICBkZXNjcmlwdGlvbjogXCJERVBSRUNBVEVEXCIsXG4gICAgcGFyYW1zU2NoZW1hOiBnZXRTZXJ2aWNlT3V0cHV0c1BhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IHNlcnZpY2VPdXRwdXRzU2NoZW1hLFxuICB9LFxuICBleGVjSW5TZXJ2aWNlOiB7XG4gICAgZGVzY3JpcHRpb246IGRlZGVudGBcbiAgICAgIEV4ZWN1dGUgdGhlIHNwZWNpZmllZCBjb21tYW5kIG5leHQgdG8gYSBydW5uaW5nIHNlcnZpY2UsIGUuZy4gaW4gYSBzZXJ2aWNlIGNvbnRhaW5lci5cblxuICAgICAgQ2FsbGVkIGJ5IHRoZSBcXGBnYXJkZW4gZXhlY1xcYCBjb21tYW5kLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBleGVjSW5TZXJ2aWNlUGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogZXhlY0luU2VydmljZVJlc3VsdFNjaGVtYSxcbiAgfSxcbiAgZ2V0U2VydmljZUxvZ3M6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUmV0cmlldmUgYSBzdHJlYW0gb2YgbG9ncyBmb3IgdGhlIHNwZWNpZmllZCBzZXJ2aWNlLCBvcHRpb25hbGx5IHdhaXRpbmcgbGlzdGVuaW5nIGZvciBuZXcgbG9ncy5cblxuICAgICAgQ2FsbGVkIGJ5IHRoZSBcXGBnYXJkZW4gbG9nc1xcYCBjb21tYW5kLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBnZXRTZXJ2aWNlTG9nc1BhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGdldFNlcnZpY2VMb2dzUmVzdWx0U2NoZW1hLFxuICB9LFxuICBydW5TZXJ2aWNlOiB7XG4gICAgZGVzY3JpcHRpb246IGRlZGVudGBcbiAgICAgIFJ1biBhbiBhZC1ob2MgaW5zdGFuY2Ugb2YgdGhlIHNwZWNpZmllZCBzZXJ2aWNlLiBUaGlzIHNob3VsZCB3YWl0IHVudGlsIHRoZSBzZXJ2aWNlIGNvbXBsZXRlc1xuICAgICAgZXhlY3V0aW9uLCBhbmQgc2hvdWxkIGlkZWFsbHkgYXR0YWNoIGl0IHRvIHRoZSB0ZXJtaW5hbCAoaS5lLiBwaXBlIHRoZSBvdXRwdXQgZnJvbSB0aGUgc2VydmljZVxuICAgICAgdG8gdGhlIGNvbnNvbGUsIGFzIHdlbGwgYXMgcGlwZSB0aGUgaW5wdXQgZnJvbSB0aGUgY29uc29sZSB0byB0aGUgcnVubmluZyBzZXJ2aWNlKS5cblxuICAgICAgQ2FsbGVkIGJ5IHRoZSBcXGBnYXJkZW4gcnVuIHNlcnZpY2VcXGAgY29tbWFuZC5cbiAgICBgLFxuICAgIHBhcmFtc1NjaGVtYTogcnVuU2VydmljZVBhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IHJ1blJlc3VsdFNjaGVtYSxcbiAgfSxcbn1cblxuZXhwb3J0IGNvbnN0IG1vZHVsZUFjdGlvbkRlc2NyaXB0aW9uczogeyBbUCBpbiBNb2R1bGVBY3Rpb25OYW1lIHwgU2VydmljZUFjdGlvbk5hbWVdOiBQbHVnaW5BY3Rpb25EZXNjcmlwdGlvbiB9ID0ge1xuICAvLyBUT0RPOiBpbXBsZW1lbnQgdGhpcyBtZXRob2QgKGl0IGlzIGN1cnJlbnRseSBub3QgZGVmaW5lZCBvciB1c2VkKVxuICBkZXNjcmliZVR5cGU6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUmV0dXJuIGRvY3VtZW50YXRpb24gYW5kIGEgc2NoZW1hIGRlc2NyaXB0aW9uIG9mIHRoZSBtb2R1bGUgdHlwZS5cblxuICAgICAgVGhlIGRvY3VtZW50YXRpb24gc2hvdWxkIGJlIGluIG1hcmtkb3duIGZvcm1hdC4gQSByZWZlcmVuY2UgZm9yIHRoZSBtb2R1bGUgdHlwZSBpcyBhdXRvbWF0aWNhbGx5XG4gICAgICBnZW5lcmF0ZWQgYmFzZWQgb24gdGhlIHByb3ZpZGVkIHNjaGVtYSwgYW5kIGEgc2VjdGlvbiBhcHBlbmRlZCB0byB0aGUgcHJvdmlkZWQgZG9jdW1lbnRhdGlvbi5cblxuICAgICAgVGhlIHNjaGVtYSBzaG91bGQgYmUgYSB2YWxpZCBPcGVuQVBJIHNjaGVtYSBkZXNjcmliaW5nIHRoZSBjb25maWd1cmF0aW9uIGtleXMgdGhhdCB0aGUgdXNlclxuICAgICAgc2hvdWxkIHVzZSB1bmRlciB0aGUgXFxgbW9kdWxlXFxgIGtleSBpbiBhIFxcYGdhcmRlbi55bWxcXGAgY29uZmlndXJhdGlvbiBmaWxlLiBOb3RlIHRoYXQgdGhlIHNjaGVtYVxuICAgICAgc2hvdWxkIG5vdCBzcGVjaWZ5IHRoZSBidWlsdC1pbiBmaWVsZHMgKHN1Y2ggYXMgXFxgbmFtZVxcYCwgXFxgdHlwZVxcYCBhbmQgXFxgZGVzY3JpcHRpb25cXGApLlxuXG4gICAgICBVc2VkIHdoZW4gYXV0by1nZW5lcmF0aW5nIGZyYW1ld29yayBkb2N1bWVudGF0aW9uLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBkZXNjcmliZU1vZHVsZVR5cGVQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiBtb2R1bGVUeXBlRGVzY3JpcHRpb25TY2hlbWEsXG4gIH0sXG4gIHZhbGlkYXRlOiB7XG4gICAgZGVzY3JpcHRpb246IGRlZGVudGBcbiAgICAgIFZhbGlkYXRlIGFuZCBvcHRpb25hbGx5IHRyYW5zZm9ybSB0aGUgZ2l2ZW4gbW9kdWxlIGNvbmZpZ3VyYXRpb24uXG5cbiAgICAgIE5vdGUgdGhhdCB0aGlzIGRvZXMgbm90IG5lZWQgdG8gcGVyZm9ybSBzdHJ1Y3R1cmFsIHNjaGVtYSB2YWxpZGF0aW9uICh0aGUgZnJhbWV3b3JrIGRvZXMgdGhhdFxuICAgICAgYXV0b21hdGljYWxseSksIGJ1dCBzaG91bGQgaW4gdHVybiBwZXJmb3JtIHNlbWFudGljIHZhbGlkYXRpb24gdG8gbWFrZSBzdXJlIHRoZSBjb25maWd1cmF0aW9uIGlzIHNhbmUuXG5cbiAgICAgIFRoaXMgY2FuIGFuZCBzaG91bGQgYWxzbyBiZSB1c2VkIHRvIGZ1cnRoZXIgc3BlY2lmeSB0aGUgc2VtYW50aWNzIG9mIHRoZSBtb2R1bGUsIGluY2x1ZGluZyBzZXJ2aWNlXG4gICAgICBjb25maWd1cmF0aW9uIGFuZCB0ZXN0IGNvbmZpZ3VyYXRpb24uIFNpbmNlIHNlcnZpY2VzIGFuZCB0ZXN0cyBhcmUgbm90IHNwZWNpZmllZCB1c2luZyBidWlsdC1pblxuICAgICAgZnJhbWV3b3JrIGNvbmZpZ3VyYXRpb24gZmllbGRzLCB0aGlzIGFjdGlvbiBuZWVkcyB0byBzcGVjaWZ5IHRob3NlIHZpYSB0aGUgXFxgc2VydmljZUNvbmZpZ3NcXGAgYW5kXG4gICAgICBcXGB0ZXN0Q29uZmlnc1xcYMKgb3V0cHV0IGtleXMuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IHZhbGlkYXRlTW9kdWxlUGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogdmFsaWRhdGVNb2R1bGVSZXN1bHRTY2hlbWEsXG4gIH0sXG5cbiAgZ2V0QnVpbGRTdGF0dXM6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgQ2hlY2sgYW5kIHJldHVybiB0aGUgYnVpbGQgc3RhdHVzIG9mIGEgbW9kdWxlLCBpLmUuIHdoZXRoZXIgdGhlIGN1cnJlbnQgdmVyc2lvbiBiZWVuIGJ1aWx0LlxuXG4gICAgICBDYWxsZWQgYmVmb3JlIHJ1bm5pbmcgdGhlIFxcYGJ1aWxkXFxgIGFjdGlvbiwgd2hpY2ggaXMgbm90IHJ1biBpZiB0aGlzIHJldHVybnMgXFxgeyByZWFkeTogdHJ1ZSB9XFxgLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBnZXRCdWlsZFN0YXR1c1BhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGJ1aWxkU3RhdHVzU2NoZW1hLFxuICB9LFxuICBidWlsZDoge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBCdWlsZCB0aGUgY3VycmVudCB2ZXJzaW9uIG9mIGEgbW9kdWxlLiBUaGlzIG11c3Qgd2FpdCB1bnRpbCB0aGUgYnVpbGQgaXMgY29tcGxldGUgYmVmb3JlIHJldHVybmluZy5cblxuICAgICAgQ2FsbGVkIGFoZWFkIG9mIGEgbnVtYmVyIG9mIGFjdGlvbnMsIGluY2x1ZGluZyBcXGBkZXBsb3lTZXJ2aWNlXFxgLCBcXGBwdXNoTW9kdWxlXFxgIGFuZCBcXGBwdWJsaXNoTW9kdWxlXFxgLlxuICAgIGAsXG4gICAgcGFyYW1zU2NoZW1hOiBidWlsZE1vZHVsZVBhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IGJ1aWxkTW9kdWxlUmVzdWx0U2NoZW1hLFxuICB9LFxuXG4gIHB1c2hNb2R1bGU6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUHVzaCB0aGUgYnVpbGQgZm9yIGN1cnJlbnQgdmVyc2lvbiBvZiBhIG1vZHVsZSB0byB0aGUgZGVwbG95bWVudCBlbnZpcm9ubWVudCwgbWFraW5nIGl0IGFjY2Vzc2libGVcbiAgICAgIHRvIHRoZSBkZXZlbG9wbWVudCBlbnZpcm9ubWVudC4gQW4gZXhhbXBsZSBiZWluZyBhIGNvbnRhaW5lciByZWdpc3RyeSBvciBhcnRpZmFjdCByZWdpc3RyeSB0aGF0J3NcbiAgICAgIGF2YWlsYWJsZSB0byB0aGUgZGVwbG95bWVudCBlbnZpcm9ubWVudCB3aGVuIGRlcGxveWluZy5cblxuICAgICAgTm90ZSB0aGUgZGlzdGluY3Rpb24gdG8gXFxgcHVibGlzaE1vZHVsZVxcYCB3aGljaCBtYXksIGRlcGVuZGluZyBvbiB0aGUgbW9kdWxlIHR5cGUsIHdvcmsgc2ltaWxhcmx5IGJ1dFxuICAgICAgaXMgb25seSBjYWxsZWQgd2hlbiBleHBsaWNpdGx5IGNhbGxpbmcgdGhlIFxcYGdhcmRlbiBwdWJsaXNoXFxgLlxuXG4gICAgICBUaGlzIGlzIHVzdWFsbHkgbm90IG5lY2Vzc2FyeSBmb3IgcGx1Z2lucyB0aGF0IHJ1biBsb2NhbGx5LlxuXG4gICAgICBDYWxsZWQgYmVmb3JlIHRoZSBcXGBkZXBsb3lTZXJ2aWNlXFxgIGFjdGlvbi5cbiAgICBgLFxuICAgIHBhcmFtc1NjaGVtYTogcHVzaE1vZHVsZVBhcmFtc1NjaGVtYSxcbiAgICByZXN1bHRTY2hlbWE6IHB1c2hNb2R1bGVSZXN1bHRTY2hlbWEsXG4gIH0sXG5cbiAgcHVibGlzaE1vZHVsZToge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBQdWJsaXNoIGEgYnVpbHQgbW9kdWxlIHRvIGEgcmVtb3RlIHJlZ2lzdHJ5LlxuXG4gICAgICBOb3RlIHRoZSBkaXN0aW5jdGlvbiB0byBcXGBwdXNoTW9kdWxlXFxgIHdoaWNoIG1heSwgZGVwZW5kaW5nIG9uIHRoZSBtb2R1bGUgdHlwZSwgd29yayBzaW1pbGFybHkgYnV0XG4gICAgICBpcyBhdXRvbWF0aWNhbGx5IGNhbGxlZCBhaGVhZCBvZiBcXGBkZXBsb3lTZXJ2aWNlXFxgLlxuXG4gICAgICBDYWxsZWQgYnkgdGhlIFxcYGdhcmRlbiBwdWJsaXNoXFxgIGNvbW1hbmQuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IHB1Ymxpc2hNb2R1bGVQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiBwdWJsaXNoTW9kdWxlUmVzdWx0U2NoZW1hLFxuICB9LFxuXG4gIHJ1bk1vZHVsZToge1xuICAgIGRlc2NyaXB0aW9uOiBkZWRlbnRgXG4gICAgICBSdW4gYW4gYWQtaG9jIGluc3RhbmNlIG9mIHRoZSBzcGVjaWZpZWQgbW9kdWxlLiBUaGlzIHNob3VsZCB3YWl0IHVudGlsIHRoZSBleGVjdXRpb24gY29tcGxldGVzLFxuICAgICAgYW5kIHNob3VsZCBpZGVhbGx5IGF0dGFjaCBpdCB0byB0aGUgdGVybWluYWwgKGkuZS4gcGlwZSB0aGUgb3V0cHV0IGZyb20gdGhlIHNlcnZpY2VcbiAgICAgIHRvIHRoZSBjb25zb2xlLCBhcyB3ZWxsIGFzIHBpcGUgdGhlIGlucHV0IGZyb20gdGhlIGNvbnNvbGUgdG8gdGhlIHJ1bm5pbmcgc2VydmljZSkuXG5cbiAgICAgIENhbGxlZCBieSB0aGUgXFxgZ2FyZGVuIHJ1biBtb2R1bGVcXGAgY29tbWFuZC5cbiAgICBgLFxuICAgIHBhcmFtc1NjaGVtYTogcnVuTW9kdWxlUGFyYW1zU2NoZW1hLFxuICAgIHJlc3VsdFNjaGVtYTogcnVuUmVzdWx0U2NoZW1hLFxuICB9LFxuXG4gIHRlc3RNb2R1bGU6IHtcbiAgICBkZXNjcmlwdGlvbjogZGVkZW50YFxuICAgICAgUnVuIHRoZSBzcGVjaWZpZWQgdGVzdCBmb3IgYSBtb2R1bGUuXG5cbiAgICAgIFRoaXMgc2hvdWxkIGNvbXBsZXRlIHRoZSB0ZXN0IHJ1biBhbmQgcmV0dXJuIHRoZSBsb2dzIGZyb20gdGhlIHRlc3QgcnVuLCBhbmQgc2lnbmFsIHdoZXRoZXIgdGhlXG4gICAgICB0ZXN0cyBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5LlxuXG4gICAgICBJdCBzaG91bGQgYWxzbyBzdG9yZSB0aGUgdGVzdCByZXN1bHRzIGFuZCBwcm92aWRlIHRoZSBhY2NvbXBhbnlpbmcgXFxgZ2V0VGVzdFJlc3VsdFxcYCBoYW5kbGVyLFxuICAgICAgc28gdGhhdCB0aGUgc2FtZSB2ZXJzaW9uIGRvZXMgbm90IG5lZWQgdG8gYmUgdGVzdGVkIG11bHRpcGxlIHRpbWVzLlxuXG4gICAgICBOb3RlIHRoYXQgdGhlIHZlcnNpb24gc3RyaW5nIHByb3ZpZGVkIHRvIHRoaXMgaGFuZGxlciBtYXkgYmUgYSBoYXNoIG9mIHRoZSBtb2R1bGUncyB2ZXJzaW9uLCBhc1xuICAgICAgd2VsbCBhcyBhbnkgcnVudGltZSBkZXBlbmRlbmNpZXMgY29uZmlndXJlZCBmb3IgdGhlIHRlc3QsIHNvIGl0IG1heSBub3QgbWF0Y2ggdGhlIGN1cnJlbnQgdmVyc2lvblxuICAgICAgb2YgdGhlIG1vZHVsZSBpdHNlbGYuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IHRlc3RNb2R1bGVQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiB0ZXN0UmVzdWx0U2NoZW1hLFxuICB9LFxuICBnZXRUZXN0UmVzdWx0OiB7XG4gICAgZGVzY3JpcHRpb246IGRlZGVudGBcbiAgICAgIFJldHJpZXZlIHRoZSB0ZXN0IHJlc3VsdCBmb3IgdGhlIHNwZWNpZmllZCB2ZXJzaW9uLiBVc2UgdGhpcyBhbG9uZyB3aXRoIHRoZSBcXGB0ZXN0TW9kdWxlXFxgIGhhbmRsZXJcbiAgICAgIHRvIGF2b2lkIHRlc3RpbmcgdGhlIHNhbWUgY29kZSByZXBlYXRlZGx5LlxuXG4gICAgICBOb3RlIHRoYXQgdGhlIHZlcnNpb24gc3RyaW5nIHByb3ZpZGVkIHRvIHRoaXMgaGFuZGxlciBtYXkgYmUgYSBoYXNoIG9mIHRoZSBtb2R1bGUncyB2ZXJzaW9uLCBhc1xuICAgICAgd2VsbCBhcyBhbnkgcnVudGltZSBkZXBlbmRlbmNpZXMgY29uZmlndXJlZCBmb3IgdGhlIHRlc3QsIHNvIGl0IG1heSBub3QgbWF0Y2ggdGhlIGN1cnJlbnQgdmVyc2lvblxuICAgICAgb2YgdGhlIG1vZHVsZSBpdHNlbGYuXG4gICAgYCxcbiAgICBwYXJhbXNTY2hlbWE6IGdldFRlc3RSZXN1bHRQYXJhbXNTY2hlbWEsXG4gICAgcmVzdWx0U2NoZW1hOiBnZXRUZXN0UmVzdWx0U2NoZW1hLFxuICB9LFxuXG4gIC4uLnNlcnZpY2VBY3Rpb25EZXNjcmlwdGlvbnMsXG59XG5cbmV4cG9ydCBjb25zdCBwbHVnaW5BY3Rpb25OYW1lczogUGx1Z2luQWN0aW9uTmFtZVtdID0gPFBsdWdpbkFjdGlvbk5hbWVbXT5PYmplY3Qua2V5cyhwbHVnaW5BY3Rpb25EZXNjcmlwdGlvbnMpXG5leHBvcnQgY29uc3Qgc2VydmljZUFjdGlvbk5hbWVzOiBTZXJ2aWNlQWN0aW9uTmFtZVtdID0gPFNlcnZpY2VBY3Rpb25OYW1lW10+T2JqZWN0LmtleXMoc2VydmljZUFjdGlvbkRlc2NyaXB0aW9ucylcbmV4cG9ydCBjb25zdCBtb2R1bGVBY3Rpb25OYW1lczogTW9kdWxlQWN0aW9uTmFtZVtdID0gPE1vZHVsZUFjdGlvbk5hbWVbXT5PYmplY3Qua2V5cyhtb2R1bGVBY3Rpb25EZXNjcmlwdGlvbnMpXG5cbmV4cG9ydCBpbnRlcmZhY2UgR2FyZGVuUGx1Z2luIHtcbiAgY29uZmlnPzogb2JqZWN0XG4gIGNvbmZpZ0tleXM/OiBzdHJpbmdbXVxuXG4gIG1vZHVsZXM/OiBzdHJpbmdbXVxuXG4gIGFjdGlvbnM/OiBQYXJ0aWFsPFBsdWdpbkFjdGlvbnM+XG4gIG1vZHVsZUFjdGlvbnM/OiB7IFttb2R1bGVUeXBlOiBzdHJpbmddOiBQYXJ0aWFsPE1vZHVsZUFuZFNlcnZpY2VBY3Rpb25zPiB9XG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgUGx1Z2luRmFjdG9yeVBhcmFtczxUIGV4dGVuZHMgUHJvdmlkZXIgPSBhbnk+IHtcbiAgY29uZmlnOiBUW1wiY29uZmlnXCJdLFxuICBsb2dFbnRyeTogTG9nTm9kZSxcbiAgcHJvamVjdE5hbWU6IHN0cmluZyxcbn1cblxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5GYWN0b3J5PFQgZXh0ZW5kcyBQcm92aWRlciA9IGFueT4ge1xuICAocGFyYW1zOiBQbHVnaW5GYWN0b3J5UGFyYW1zPFQ+KTogR2FyZGVuUGx1Z2luIHwgUHJvbWlzZTxHYXJkZW5QbHVnaW4+XG59XG5leHBvcnQgdHlwZSBSZWdpc3RlclBsdWdpblBhcmFtID0gc3RyaW5nIHwgUGx1Z2luRmFjdG9yeVxuZXhwb3J0IGludGVyZmFjZSBQbHVnaW5zIHtcbiAgW25hbWU6IHN0cmluZ106IFJlZ2lzdGVyUGx1Z2luUGFyYW1cbn1cblxuZXhwb3J0IGNvbnN0IHBsdWdpblNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgY29uZmlnOiBKb2kub2JqZWN0KClcbiAgICAgIC5tZXRhKHsgZXh0ZW5kYWJsZTogdHJ1ZSB9KVxuICAgICAgLmRlc2NyaXB0aW9uKFxuICAgICAgICBcIlBsdWdpbnMgbWF5IHVzZSB0aGlzIGtleSB0byBvdmVycmlkZSBvciBhdWdtZW50IHRoZWlyIGNvbmZpZ3VyYXRpb24gXCIgK1xuICAgICAgICBcIihhcyBzcGVjaWZpZWQgaW4gdGhlIGdhcmRlbi55bWwgcHJvdmlkZXIgY29uZmlndXJhdGlvbi5cIixcbiAgICAgICksXG4gICAgbW9kdWxlczogam9pQXJyYXkoSm9pLnN0cmluZygpKVxuICAgICAgLmRlc2NyaXB0aW9uKFxuICAgICAgICBcIlBsdWdpbnMgbWF5IG9wdGlvbmFsbHkgcHJvdmlkZSBwYXRocyB0byBHYXJkZW4gbW9kdWxlcyB0aGF0IGFyZSBsb2FkZWQgYXMgcGFydCBvZiB0aGUgcGx1Z2luLiBcIiArXG4gICAgICAgIFwiVGhpcyBpcyB1c2VmdWwsIGZvciBleGFtcGxlLCB0byBwcm92aWRlIGJ1aWxkIGRlcGVuZGVuY2llcyBmb3Igb3RoZXIgbW9kdWxlcyBcIiArXG4gICAgICAgIFwib3IgYXMgcGFydCBvZiB0aGUgcGx1Z2luIG9wZXJhdGlvbi5cIixcbiAgICAgICksXG4gICAgLy8gVE9ETzogZG9jdW1lbnQgcGx1Z2luIGFjdGlvbnMgZnVydGhlclxuICAgIGFjdGlvbnM6IEpvaS5vYmplY3QoKS5rZXlzKG1hcFZhbHVlcyhwbHVnaW5BY3Rpb25EZXNjcmlwdGlvbnMsICgpID0+IEpvaS5mdW5jKCkpKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiQSBtYXAgb2YgcGx1Z2luIGFjdGlvbiBoYW5kbGVycyBwcm92aWRlZCBieSB0aGUgcGx1Z2luLlwiKSxcbiAgICBtb2R1bGVBY3Rpb25zOiBqb2lJZGVudGlmaWVyTWFwKFxuICAgICAgSm9pLm9iamVjdCgpLmtleXMobWFwVmFsdWVzKG1vZHVsZUFjdGlvbkRlc2NyaXB0aW9ucywgKCkgPT4gSm9pLmZ1bmMoKSksXG4gICAgICApLmRlc2NyaXB0aW9uKFwiQSBtYXAgb2YgbW9kdWxlIG5hbWVzIGFuZCBtb2R1bGUgYWN0aW9uIGhhbmRsZXJzIHByb3ZpZGVkIGJ5IHRoZSBwbHVnaW4uXCIpLFxuICAgICksXG4gIH0pXG4gIC5kZXNjcmlwdGlvbihcIlRoZSBzY2hlbWEgZm9yIEdhcmRlbiBwbHVnaW5zLlwiKVxuXG5leHBvcnQgY29uc3QgcGx1Z2luTW9kdWxlU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICBuYW1lOiBqb2lJZGVudGlmaWVyKCksXG4gICAgZ2FyZGVuUGx1Z2luOiBKb2kuZnVuYygpLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBpbml0aWFsaXphdGlvbiBmdW5jdGlvbiBmb3IgdGhlIHBsdWdpbi4gU2hvdWxkIHJldHVybiBhIHZhbGlkIEdhcmRlbiBwbHVnaW4gb2JqZWN0LlwiKSxcbiAgfSlcbiAgLnVua25vd24odHJ1ZSlcbiAgLmRlc2NyaXB0aW9uKFwiQSBtb2R1bGUgY29udGFpbmluZyBhIEdhcmRlbiBwbHVnaW4uXCIpXG4iXX0= diff --git a/garden-service/build/types/service.d.ts b/garden-service/build/types/service.d.ts new file mode 100644 index 00000000000..ff208796676 --- /dev/null +++ b/garden-service/build/types/service.d.ts @@ -0,0 +1,54 @@ +import * as Joi from "joi"; +import { PrimitiveMap } from "../config/common"; +import { Module } from "./module"; +import { ServiceConfig } from "../config/service"; +import { Garden } from "../garden"; +export interface Service { + name: string; + module: M; + config: M["serviceConfigs"][0]; + spec: M["serviceConfigs"][0]["spec"]; +} +export declare const serviceSchema: Joi.ObjectSchema; +export declare function serviceFromConfig(module: M, config: ServiceConfig): Service; +export declare type ServiceState = "ready" | "deploying" | "stopped" | "unhealthy" | "unknown" | "outdated" | "missing"; +export declare type ServiceProtocol = "http" | "https"; +export interface ServiceIngressSpec { + hostname?: string; + path: string; + port: number; + protocol: ServiceProtocol; +} +export interface ServiceIngress extends ServiceIngressSpec { + hostname: string; +} +export declare const ingressHostnameSchema: Joi.StringSchema; +export declare const serviceIngressSpecSchema: Joi.ObjectSchema; +export declare const serviceIngressSchema: Joi.ObjectSchema; +export interface ServiceStatus { + providerId?: string; + providerVersion?: string; + version?: string; + state?: ServiceState; + runningReplicas?: number; + ingresses?: ServiceIngress[]; + lastMessage?: string; + lastError?: string; + createdAt?: string; + updatedAt?: string; + detail?: any; +} +export declare const serviceStatusSchema: Joi.ObjectSchema; +export declare type RuntimeContext = { + envVars: PrimitiveMap; + dependencies: { + [name: string]: { + version: string; + outputs: PrimitiveMap; + }; + }; +}; +export declare const runtimeContextSchema: Joi.ObjectSchema; +export declare function prepareRuntimeContext(garden: Garden, module: Module, serviceDependencies: Service[]): Promise; +export declare function getIngressUrl(ingress: ServiceIngress): string; +//# sourceMappingURL=service.d.ts.map \ No newline at end of file diff --git a/garden-service/build/types/service.js b/garden-service/build/types/service.js new file mode 100644 index 00000000000..77233edad7c --- /dev/null +++ b/garden-service/build/types/service.js @@ -0,0 +1,181 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Joi = require("joi"); +const util_1 = require("../util/util"); +const common_1 = require("../config/common"); +const module_1 = require("./module"); +const service_1 = require("../config/service"); +const common_2 = require("../config/common"); +const dedent = require("dedent"); +const url_1 = require("url"); +const base_1 = require("../vcs/base"); +const normalizeUrl = require("normalize-url"); +exports.serviceSchema = Joi.object() + .options({ presence: "required" }) + .keys({ + name: common_1.joiIdentifier() + .description("The name of the service."), + module: Joi.object().unknown(true), + config: service_1.serviceConfigSchema, + spec: Joi.object() + .description("The raw configuration of the service (specific to each plugin)."), +}); +function serviceFromConfig(module, config) { + return { + name: config.name, + module, + config, + spec: config.spec, + }; +} +exports.serviceFromConfig = serviceFromConfig; +exports.ingressHostnameSchema = Joi.string() + .hostname() + .description(dedent ` + The hostname that should route to this service. Defaults to the default hostname configured + in the provider configuration. + + Note that if you're developing locally you may need to add this hostname to your hosts file. + `); +const portSchema = Joi.number() + .description(dedent ` + The port number that the service is exposed on internally. + This defaults to the first specified port for the service. + `); +exports.serviceIngressSpecSchema = Joi.object() + .keys({ + hostname: exports.ingressHostnameSchema, + port: portSchema, + path: Joi.string() + .default("/") + .description("The ingress path that should be matched to route to this service."), + protocol: Joi.string() + .only("http", "https") + .required() + .description("The protocol to use for the ingress."), +}); +exports.serviceIngressSchema = exports.serviceIngressSpecSchema + .keys({ + hostname: Joi.string() + .required() + .description("The hostname where the service can be accessed."), + port: portSchema + .required(), +}) + .description("A description of a deployed service ingress."); +exports.serviceStatusSchema = Joi.object() + .keys({ + providerId: Joi.string() + .description("The ID used for the service by the provider (if not the same as the service name)."), + providerVersion: Joi.string() + .description("The provider version of the deployed service (if different from the Garden module version."), + version: Joi.string() + .description("The Garden module version of the deployed service."), + state: Joi.string() + .only("ready", "deploying", "stopped", "unhealthy", "unknown", "outdated", "missing") + .default("unknown") + .description("The current deployment status of the service."), + runningReplicas: Joi.number() + .description("How many replicas of the service are currently running."), + ingresses: Joi.array() + .items(exports.serviceIngressSchema) + .description("List of currently deployed ingress endpoints for the service."), + lastMessage: Joi.string() + .allow("") + .description("Latest status message of the service (if any)."), + lastError: Joi.string() + .description("Latest error status message of the service (if any)."), + createdAt: Joi.string() + .description("When the service was first deployed by the provider."), + updatedAt: Joi.string() + .description("When the service was last updated by the provider."), + detail: Joi.object() + .meta({ extendable: true }) + .description("Additional detail, specific to the provider."), +}); +const runtimeDependencySchema = Joi.object() + .keys({ + version: base_1.moduleVersionSchema, + outputs: common_1.joiEnvVars() + .description("The outputs provided by the service (e.g. ingress URLs etc.)."), +}); +exports.runtimeContextSchema = Joi.object() + .options({ presence: "required" }) + .keys({ + envVars: Joi.object().pattern(/.+/, common_1.joiPrimitive()) + .default(() => ({}), "{}") + .unknown(false) + .description("Key/value map of environment variables. Keys must be valid POSIX environment variable names " + + "(must be uppercase) and values must be primitives."), + dependencies: common_1.joiIdentifierMap(runtimeDependencySchema) + .description("Map of all the services that this service or test depends on, and their metadata."), +}); +function prepareRuntimeContext(garden, module, serviceDependencies) { + return __awaiter(this, void 0, void 0, function* () { + const buildDepKeys = module.build.dependencies.map(dep => module_1.getModuleKey(dep.name, dep.plugin)); + const buildDependencies = yield garden.getModules(buildDepKeys); + const { versionString } = module.version; + const envVars = { + GARDEN_VERSION: versionString, + }; + for (const [key, value] of Object.entries(garden.environment.variables)) { + const envVarName = `GARDEN_VARIABLES_${key.replace(/-/g, "_").toUpperCase()}`; + envVars[envVarName] = value; + } + const deps = {}; + for (const m of buildDependencies) { + deps[m.name] = { + version: m.version.versionString, + outputs: {}, + }; + } + for (const dep of serviceDependencies) { + if (!deps[dep.name]) { + deps[dep.name] = { + version: dep.module.version.versionString, + outputs: {}, + }; + } + const depContext = deps[dep.name]; + const outputs = Object.assign({}, yield garden.actions.getServiceOutputs({ service: dep }), dep.config.outputs); + const serviceEnvName = util_1.getEnvVarName(dep.name); + common_2.validate(outputs, service_1.serviceOutputsSchema, { context: `outputs for service ${dep.name}` }); + for (const [key, value] of Object.entries(outputs)) { + const envVarName = `GARDEN_SERVICES_${serviceEnvName}_${key}`.toUpperCase(); + envVars[envVarName] = value; + depContext.outputs[key] = value; + } + } + return { + envVars, + dependencies: deps, + }; + }); +} +exports.prepareRuntimeContext = prepareRuntimeContext; +function getIngressUrl(ingress) { + return normalizeUrl(url_1.format({ + protocol: ingress.protocol, + hostname: ingress.hostname, + port: ingress.port, + pathname: ingress.path, + })); +} +exports.getIngressUrl = getIngressUrl; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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TyxDQUFDLEdBQUcsQ0FBQyxHQUFHLEtBQUssQ0FBQTthQUNoQztTQUNGO1FBRUQsT0FBTztZQUNMLE9BQU87WUFDUCxZQUFZLEVBQUUsSUFBSTtTQUNuQixDQUFBO0lBQ0gsQ0FBQztDQUFBO0FBbERELHNEQWtEQztBQUVELFNBQWdCLGFBQWEsQ0FBQyxPQUF1QjtJQUNuRCxPQUFPLFlBQVksQ0FBQyxZQUFNLENBQUM7UUFDekIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxRQUFRO1FBQzFCLFFBQVEsRUFBRSxPQUFPLENBQUMsUUFBUTtRQUMxQixJQUFJLEVBQUUsT0FBTyxDQUFDLElBQUk7UUFDbEIsUUFBUSxFQUFFLE9BQU8sQ0FBQyxJQUFJO0tBQ3ZCLENBQUMsQ0FBQyxDQUFBO0FBQ0wsQ0FBQztBQVBELHNDQU9DIiwiZmlsZSI6InR5cGVzL3NlcnZpY2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHsgZ2V0RW52VmFyTmFtZSB9IGZyb20gXCIuLi91dGlsL3V0aWxcIlxuaW1wb3J0IHsgUHJpbWl0aXZlTWFwLCBqb2lJZGVudGlmaWVyLCBqb2lFbnZWYXJzLCBqb2lJZGVudGlmaWVyTWFwLCBqb2lQcmltaXRpdmUgfSBmcm9tIFwiLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBNb2R1bGUsIGdldE1vZHVsZUtleSB9IGZyb20gXCIuL21vZHVsZVwiXG5pbXBvcnQgeyBzZXJ2aWNlT3V0cHV0c1NjaGVtYSwgU2VydmljZUNvbmZpZywgc2VydmljZUNvbmZpZ1NjaGVtYSB9IGZyb20gXCIuLi9jb25maWcvc2VydmljZVwiXG5pbXBvcnQgeyB2YWxpZGF0ZSB9IGZyb20gXCIuLi9jb25maWcvY29tbW9uXCJcbmltcG9ydCBkZWRlbnQgPSByZXF1aXJlKFwiZGVkZW50XCIpXG5pbXBvcnQgeyBmb3JtYXQgfSBmcm9tIFwidXJsXCJcbmltcG9ydCB7IG1vZHVsZVZlcnNpb25TY2hlbWEgfSBmcm9tIFwiLi4vdmNzL2Jhc2VcIlxuaW1wb3J0IHsgR2FyZGVuIH0gZnJvbSBcIi4uL2dhcmRlblwiXG5pbXBvcnQgbm9ybWFsaXplVXJsID0gcmVxdWlyZShcIm5vcm1hbGl6ZS11cmxcIilcblxuZXhwb3J0IGludGVyZmFjZSBTZXJ2aWNlPE0gZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+IHtcbiAgbmFtZTogc3RyaW5nXG4gIG1vZHVsZTogTVxuICBjb25maWc6IE1bXCJzZXJ2aWNlQ29uZmlnc1wiXVswXVxuICBzcGVjOiBNW1wic2VydmljZUNvbmZpZ3NcIl1bMF1bXCJzcGVjXCJdXG59XG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlU2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5vcHRpb25zKHsgcHJlc2VuY2U6IFwicmVxdWlyZWRcIiB9KVxuICAua2V5cyh7XG4gICAgbmFtZTogam9pSWRlbnRpZmllcigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgbmFtZSBvZiB0aGUgc2VydmljZS5cIiksXG4gICAgbW9kdWxlOiBKb2kub2JqZWN0KCkudW5rbm93bih0cnVlKSwgICAvLyBUaGlzIGNhdXNlcyBhIHN0YWNrIG92ZXJmbG93OiBKb2kubGF6eSgoKSA9PiBtb2R1bGVTY2hlbWEpLFxuICAgIGNvbmZpZzogc2VydmljZUNvbmZpZ1NjaGVtYSxcbiAgICBzcGVjOiBKb2kub2JqZWN0KClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSByYXcgY29uZmlndXJhdGlvbiBvZiB0aGUgc2VydmljZSAoc3BlY2lmaWMgdG8gZWFjaCBwbHVnaW4pLlwiKSxcbiAgfSlcblxuZXhwb3J0IGZ1bmN0aW9uIHNlcnZpY2VGcm9tQ29uZmlnPE0gZXh0ZW5kcyBNb2R1bGUgPSBNb2R1bGU+KG1vZHVsZTogTSwgY29uZmlnOiBTZXJ2aWNlQ29uZmlnKTogU2VydmljZTxNPiB7XG4gIHJldHVybiB7XG4gICAgbmFtZTogY29uZmlnLm5hbWUsXG4gICAgbW9kdWxlLFxuICAgIGNvbmZpZyxcbiAgICBzcGVjOiBjb25maWcuc3BlYyxcbiAgfVxufVxuXG5leHBvcnQgdHlwZSBTZXJ2aWNlU3RhdGUgPSBcInJlYWR5XCIgfCBcImRlcGxveWluZ1wiIHwgXCJzdG9wcGVkXCIgfCBcInVuaGVhbHRoeVwiIHwgXCJ1bmtub3duXCIgfCBcIm91dGRhdGVkXCIgfCBcIm1pc3NpbmdcIlxuXG4vLyBUT0RPOiBzdXBwb3J0IFRDUCwgVURQIGFuZCBnUlBDXG5leHBvcnQgdHlwZSBTZXJ2aWNlUHJvdG9jb2wgPSBcImh0dHBcIiB8IFwiaHR0cHNcIiAgLy8gfCBcInRjcFwiIHwgXCJ1ZHBcIlxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VJbmdyZXNzU3BlYyB7XG4gIGhvc3RuYW1lPzogc3RyaW5nXG4gIHBhdGg6IHN0cmluZ1xuICBwb3J0OiBudW1iZXJcbiAgcHJvdG9jb2w6IFNlcnZpY2VQcm90b2NvbFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFNlcnZpY2VJbmdyZXNzIGV4dGVuZHMgU2VydmljZUluZ3Jlc3NTcGVjIHtcbiAgaG9zdG5hbWU6IHN0cmluZ1xufVxuXG5leHBvcnQgY29uc3QgaW5ncmVzc0hvc3RuYW1lU2NoZW1hID0gSm9pLnN0cmluZygpXG4gIC5ob3N0bmFtZSgpXG4gIC5kZXNjcmlwdGlvbihkZWRlbnRgXG4gICAgVGhlIGhvc3RuYW1lIHRoYXQgc2hvdWxkIHJvdXRlIHRvIHRoaXMgc2VydmljZS4gRGVmYXVsdHMgdG8gdGhlIGRlZmF1bHQgaG9zdG5hbWUgY29uZmlndXJlZFxuICAgIGluIHRoZSBwcm92aWRlciBjb25maWd1cmF0aW9uLlxuXG4gICAgTm90ZSB0aGF0IGlmIHlvdSdyZSBkZXZlbG9waW5nIGxvY2FsbHkgeW91IG1heSBuZWVkIHRvIGFkZCB0aGlzIGhvc3RuYW1lIHRvIHlvdXIgaG9zdHMgZmlsZS5cbiAgYClcblxuY29uc3QgcG9ydFNjaGVtYSA9IEpvaS5udW1iZXIoKVxuICAuZGVzY3JpcHRpb24oZGVkZW50YFxuICAgIFRoZSBwb3J0IG51bWJlciB0aGF0IHRoZSBzZXJ2aWNlIGlzIGV4cG9zZWQgb24gaW50ZXJuYWxseS5cbiAgICBUaGlzIGRlZmF1bHRzIHRvIHRoZSBmaXJzdCBzcGVjaWZpZWQgcG9ydCBmb3IgdGhlIHNlcnZpY2UuXG4gIGApXG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlSW5ncmVzc1NwZWNTY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIGhvc3RuYW1lOiBpbmdyZXNzSG9zdG5hbWVTY2hlbWEsXG4gICAgcG9ydDogcG9ydFNjaGVtYSxcbiAgICBwYXRoOiBKb2kuc3RyaW5nKClcbiAgICAgIC5kZWZhdWx0KFwiL1wiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGluZ3Jlc3MgcGF0aCB0aGF0IHNob3VsZCBiZSBtYXRjaGVkIHRvIHJvdXRlIHRvIHRoaXMgc2VydmljZS5cIiksXG4gICAgcHJvdG9jb2w6IEpvaS5zdHJpbmcoKVxuICAgICAgLm9ubHkoXCJodHRwXCIsIFwiaHR0cHNcIilcbiAgICAgIC5yZXF1aXJlZCgpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcHJvdG9jb2wgdG8gdXNlIGZvciB0aGUgaW5ncmVzcy5cIiksXG4gIH0pXG5cbmV4cG9ydCBjb25zdCBzZXJ2aWNlSW5ncmVzc1NjaGVtYSA9IHNlcnZpY2VJbmdyZXNzU3BlY1NjaGVtYVxuICAua2V5cyh7XG4gICAgaG9zdG5hbWU6IEpvaS5zdHJpbmcoKVxuICAgICAgLnJlcXVpcmVkKClcbiAgICAgIC5kZXNjcmlwdGlvbihcIlRoZSBob3N0bmFtZSB3aGVyZSB0aGUgc2VydmljZSBjYW4gYmUgYWNjZXNzZWQuXCIpLFxuICAgIHBvcnQ6IHBvcnRTY2hlbWFcbiAgICAgIC5yZXF1aXJlZCgpLFxuICB9KVxuICAuZGVzY3JpcHRpb24oXCJBIGRlc2NyaXB0aW9uIG9mIGEgZGVwbG95ZWQgc2VydmljZSBpbmdyZXNzLlwiKVxuXG4vLyBUT0RPOiByZXZpc2UgdGhpcyBzY2hlbWFcbmV4cG9ydCBpbnRlcmZhY2UgU2VydmljZVN0YXR1cyB7XG4gIHByb3ZpZGVySWQ/OiBzdHJpbmdcbiAgcHJvdmlkZXJWZXJzaW9uPzogc3RyaW5nXG4gIHZlcnNpb24/OiBzdHJpbmdcbiAgc3RhdGU/OiBTZXJ2aWNlU3RhdGVcbiAgcnVubmluZ1JlcGxpY2FzPzogbnVtYmVyXG4gIGluZ3Jlc3Nlcz86IFNlcnZpY2VJbmdyZXNzW10sXG4gIGxhc3RNZXNzYWdlPzogc3RyaW5nXG4gIGxhc3RFcnJvcj86IHN0cmluZ1xuICBjcmVhdGVkQXQ/OiBzdHJpbmdcbiAgdXBkYXRlZEF0Pzogc3RyaW5nXG4gIGRldGFpbD86IGFueVxufVxuXG5leHBvcnQgY29uc3Qgc2VydmljZVN0YXR1c1NjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgcHJvdmlkZXJJZDogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgSUQgdXNlZCBmb3IgdGhlIHNlcnZpY2UgYnkgdGhlIHByb3ZpZGVyIChpZiBub3QgdGhlIHNhbWUgYXMgdGhlIHNlcnZpY2UgbmFtZSkuXCIpLFxuICAgIHByb3ZpZGVyVmVyc2lvbjogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgcHJvdmlkZXIgdmVyc2lvbiBvZiB0aGUgZGVwbG95ZWQgc2VydmljZSAoaWYgZGlmZmVyZW50IGZyb20gdGhlIEdhcmRlbiBtb2R1bGUgdmVyc2lvbi5cIiksXG4gICAgdmVyc2lvbjogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJUaGUgR2FyZGVuIG1vZHVsZSB2ZXJzaW9uIG9mIHRoZSBkZXBsb3llZCBzZXJ2aWNlLlwiKSxcbiAgICBzdGF0ZTogSm9pLnN0cmluZygpXG4gICAgICAub25seShcInJlYWR5XCIsIFwiZGVwbG95aW5nXCIsIFwic3RvcHBlZFwiLCBcInVuaGVhbHRoeVwiLCBcInVua25vd25cIiwgXCJvdXRkYXRlZFwiLCBcIm1pc3NpbmdcIilcbiAgICAgIC5kZWZhdWx0KFwidW5rbm93blwiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGN1cnJlbnQgZGVwbG95bWVudCBzdGF0dXMgb2YgdGhlIHNlcnZpY2UuXCIpLFxuICAgIHJ1bm5pbmdSZXBsaWNhczogSm9pLm51bWJlcigpXG4gICAgICAuZGVzY3JpcHRpb24oXCJIb3cgbWFueSByZXBsaWNhcyBvZiB0aGUgc2VydmljZSBhcmUgY3VycmVudGx5IHJ1bm5pbmcuXCIpLFxuICAgIGluZ3Jlc3NlczogSm9pLmFycmF5KClcbiAgICAgIC5pdGVtcyhzZXJ2aWNlSW5ncmVzc1NjaGVtYSlcbiAgICAgIC5kZXNjcmlwdGlvbihcIkxpc3Qgb2YgY3VycmVudGx5IGRlcGxveWVkIGluZ3Jlc3MgZW5kcG9pbnRzIGZvciB0aGUgc2VydmljZS5cIiksXG4gICAgbGFzdE1lc3NhZ2U6IEpvaS5zdHJpbmcoKVxuICAgICAgLmFsbG93KFwiXCIpXG4gICAgICAuZGVzY3JpcHRpb24oXCJMYXRlc3Qgc3RhdHVzIG1lc3NhZ2Ugb2YgdGhlIHNlcnZpY2UgKGlmIGFueSkuXCIpLFxuICAgIGxhc3RFcnJvcjogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJMYXRlc3QgZXJyb3Igc3RhdHVzIG1lc3NhZ2Ugb2YgdGhlIHNlcnZpY2UgKGlmIGFueSkuXCIpLFxuICAgIGNyZWF0ZWRBdDogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJXaGVuIHRoZSBzZXJ2aWNlIHdhcyBmaXJzdCBkZXBsb3llZCBieSB0aGUgcHJvdmlkZXIuXCIpLFxuICAgIHVwZGF0ZWRBdDogSm9pLnN0cmluZygpXG4gICAgICAuZGVzY3JpcHRpb24oXCJXaGVuIHRoZSBzZXJ2aWNlIHdhcyBsYXN0IHVwZGF0ZWQgYnkgdGhlIHByb3ZpZGVyLlwiKSxcbiAgICBkZXRhaWw6IEpvaS5vYmplY3QoKVxuICAgICAgLm1ldGEoeyBleHRlbmRhYmxlOiB0cnVlIH0pXG4gICAgICAuZGVzY3JpcHRpb24oXCJBZGRpdGlvbmFsIGRldGFpbCwgc3BlY2lmaWMgdG8gdGhlIHByb3ZpZGVyLlwiKSxcbiAgfSlcblxuZXhwb3J0IHR5cGUgUnVudGltZUNvbnRleHQgPSB7XG4gIGVudlZhcnM6IFByaW1pdGl2ZU1hcFxuICBkZXBlbmRlbmNpZXM6IHtcbiAgICBbbmFtZTogc3RyaW5nXToge1xuICAgICAgdmVyc2lvbjogc3RyaW5nLFxuICAgICAgb3V0cHV0czogUHJpbWl0aXZlTWFwLFxuICAgIH0sXG4gIH0sXG59XG5cbmNvbnN0IHJ1bnRpbWVEZXBlbmRlbmN5U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5rZXlzKHtcbiAgICB2ZXJzaW9uOiBtb2R1bGVWZXJzaW9uU2NoZW1hLFxuICAgIG91dHB1dHM6IGpvaUVudlZhcnMoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIG91dHB1dHMgcHJvdmlkZWQgYnkgdGhlIHNlcnZpY2UgKGUuZy4gaW5ncmVzcyBVUkxzIGV0Yy4pLlwiKSxcbiAgfSlcblxuZXhwb3J0IGNvbnN0IHJ1bnRpbWVDb250ZXh0U2NoZW1hID0gSm9pLm9iamVjdCgpXG4gIC5vcHRpb25zKHsgcHJlc2VuY2U6IFwicmVxdWlyZWRcIiB9KVxuICAua2V5cyh7XG4gICAgZW52VmFyczogSm9pLm9iamVjdCgpLnBhdHRlcm4oLy4rLywgam9pUHJpbWl0aXZlKCkpXG4gICAgICAuZGVmYXVsdCgoKSA9PiAoe30pLCBcInt9XCIpXG4gICAgICAudW5rbm93bihmYWxzZSlcbiAgICAgIC5kZXNjcmlwdGlvbihcbiAgICAgICAgXCJLZXkvdmFsdWUgbWFwIG9mIGVudmlyb25tZW50IHZhcmlhYmxlcy4gS2V5cyBtdXN0IGJlIHZhbGlkIFBPU0lYIGVudmlyb25tZW50IHZhcmlhYmxlIG5hbWVzIFwiICtcbiAgICAgICAgXCIobXVzdCBiZSB1cHBlcmNhc2UpIGFuZCB2YWx1ZXMgbXVzdCBiZSBwcmltaXRpdmVzLlwiLFxuICAgICAgKSxcbiAgICBkZXBlbmRlbmNpZXM6IGpvaUlkZW50aWZpZXJNYXAocnVudGltZURlcGVuZGVuY3lTY2hlbWEpXG4gICAgICAuZGVzY3JpcHRpb24oXCJNYXAgb2YgYWxsIHRoZSBzZXJ2aWNlcyB0aGF0IHRoaXMgc2VydmljZSBvciB0ZXN0IGRlcGVuZHMgb24sIGFuZCB0aGVpciBtZXRhZGF0YS5cIiksXG4gIH0pXG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBwcmVwYXJlUnVudGltZUNvbnRleHQoXG4gIGdhcmRlbjogR2FyZGVuLCBtb2R1bGU6IE1vZHVsZSwgc2VydmljZURlcGVuZGVuY2llczogU2VydmljZVtdLFxuKTogUHJvbWlzZTxSdW50aW1lQ29udGV4dD4ge1xuICBjb25zdCBidWlsZERlcEtleXMgPSBtb2R1bGUuYnVpbGQuZGVwZW5kZW5jaWVzLm1hcChkZXAgPT4gZ2V0TW9kdWxlS2V5KGRlcC5uYW1lLCBkZXAucGx1Z2luKSlcbiAgY29uc3QgYnVpbGREZXBlbmRlbmNpZXM6IE1vZHVsZVtdID0gYXdhaXQgZ2FyZGVuLmdldE1vZHVsZXMoYnVpbGREZXBLZXlzKVxuICBjb25zdCB7IHZlcnNpb25TdHJpbmcgfSA9IG1vZHVsZS52ZXJzaW9uXG4gIGNvbnN0IGVudlZhcnMgPSB7XG4gICAgR0FSREVOX1ZFUlNJT046IHZlcnNpb25TdHJpbmcsXG4gIH1cblxuICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhnYXJkZW4uZW52aXJvbm1lbnQudmFyaWFibGVzKSkge1xuICAgIGNvbnN0IGVudlZhck5hbWUgPSBgR0FSREVOX1ZBUklBQkxFU18ke2tleS5yZXBsYWNlKC8tL2csIFwiX1wiKS50b1VwcGVyQ2FzZSgpfWBcbiAgICBlbnZWYXJzW2VudlZhck5hbWVdID0gdmFsdWVcbiAgfVxuXG4gIGNvbnN0IGRlcHMgPSB7fVxuXG4gIGZvciAoY29uc3QgbSBvZiBidWlsZERlcGVuZGVuY2llcykge1xuICAgIGRlcHNbbS5uYW1lXSA9IHtcbiAgICAgIHZlcnNpb246IG0udmVyc2lvbi52ZXJzaW9uU3RyaW5nLFxuICAgICAgb3V0cHV0czoge30sXG4gICAgfVxuICB9XG5cbiAgZm9yIChjb25zdCBkZXAgb2Ygc2VydmljZURlcGVuZGVuY2llcykge1xuICAgIGlmICghZGVwc1tkZXAubmFtZV0pIHtcbiAgICAgIGRlcHNbZGVwLm5hbWVdID0ge1xuICAgICAgICB2ZXJzaW9uOiBkZXAubW9kdWxlLnZlcnNpb24udmVyc2lvblN0cmluZyxcbiAgICAgICAgb3V0cHV0czoge30sXG4gICAgICB9XG4gICAgfVxuICAgIGNvbnN0IGRlcENvbnRleHQgPSBkZXBzW2RlcC5uYW1lXVxuXG4gICAgY29uc3Qgb3V0cHV0cyA9IHsgLi4uYXdhaXQgZ2FyZGVuLmFjdGlvbnMuZ2V0U2VydmljZU91dHB1dHMoeyBzZXJ2aWNlOiBkZXAgfSksIC4uLmRlcC5jb25maWcub3V0cHV0cyB9XG4gICAgY29uc3Qgc2VydmljZUVudk5hbWUgPSBnZXRFbnZWYXJOYW1lKGRlcC5uYW1lKVxuXG4gICAgdmFsaWRhdGUob3V0cHV0cywgc2VydmljZU91dHB1dHNTY2hlbWEsIHsgY29udGV4dDogYG91dHB1dHMgZm9yIHNlcnZpY2UgJHtkZXAubmFtZX1gIH0pXG5cbiAgICBmb3IgKGNvbnN0IFtrZXksIHZhbHVlXSBvZiBPYmplY3QuZW50cmllcyhvdXRwdXRzKSkge1xuICAgICAgY29uc3QgZW52VmFyTmFtZSA9IGBHQVJERU5fU0VSVklDRVNfJHtzZXJ2aWNlRW52TmFtZX1fJHtrZXl9YC50b1VwcGVyQ2FzZSgpXG5cbiAgICAgIGVudlZhcnNbZW52VmFyTmFtZV0gPSB2YWx1ZVxuICAgICAgZGVwQ29udGV4dC5vdXRwdXRzW2tleV0gPSB2YWx1ZVxuICAgIH1cbiAgfVxuXG4gIHJldHVybiB7XG4gICAgZW52VmFycyxcbiAgICBkZXBlbmRlbmNpZXM6IGRlcHMsXG4gIH1cbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEluZ3Jlc3NVcmwoaW5ncmVzczogU2VydmljZUluZ3Jlc3MpIHtcbiAgcmV0dXJuIG5vcm1hbGl6ZVVybChmb3JtYXQoe1xuICAgIHByb3RvY29sOiBpbmdyZXNzLnByb3RvY29sLFxuICAgIGhvc3RuYW1lOiBpbmdyZXNzLmhvc3RuYW1lLFxuICAgIHBvcnQ6IGluZ3Jlc3MucG9ydCxcbiAgICBwYXRobmFtZTogaW5ncmVzcy5wYXRoLFxuICB9KSlcbn1cbiJdfQ== diff --git a/garden-service/build/util/detectCycles.d.ts b/garden-service/build/util/detectCycles.d.ts new file mode 100644 index 00000000000..cd9a9c7ee0c --- /dev/null +++ b/garden-service/build/util/detectCycles.d.ts @@ -0,0 +1,6 @@ +import { Module } from "../types/module"; +import { Service } from "../types/service"; +export declare type Cycle = string[]; +export declare function detectCircularDependencies(modules: Module[], services: Service[]): Promise; +export declare function detectCycles(graph: any, vertices: string[]): Cycle[]; +//# sourceMappingURL=detectCycles.d.ts.map \ No newline at end of file diff --git a/garden-service/build/util/detectCycles.js b/garden-service/build/util/detectCycles.js new file mode 100644 index 00000000000..20c6a0446ea --- /dev/null +++ b/garden-service/build/util/detectCycles.js @@ -0,0 +1,105 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const lodash_1 = require("lodash"); +const module_1 = require("../types/module"); +const exceptions_1 = require("../exceptions"); +/* + Implements a variation on the Floyd-Warshall algorithm to compute minimal cycles. + + This is approximately O(m^3) + O(s^3), where m is the number of modules and s is the number of services. + + Throws an error if cycles were found. +*/ +function detectCircularDependencies(modules, services) { + return __awaiter(this, void 0, void 0, function* () { + // Sparse matrices + const buildGraph = {}; + const serviceGraph = {}; + /* + There's no need to account for test dependencies here, since any circularities there + are accounted for via service dependencies. + */ + for (const module of modules) { + // Build dependencies + for (const buildDep of module.build.dependencies) { + const depName = module_1.getModuleKey(buildDep.name, buildDep.plugin); + lodash_1.set(buildGraph, [module.name, depName], { distance: 1, next: depName }); + } + // Service dependencies + for (const service of module.serviceConfigs || []) { + for (const depName of service.dependencies) { + lodash_1.set(serviceGraph, [service.name, depName], { distance: 1, next: depName }); + } + } + } + const serviceNames = services.map(s => s.name); + const buildCycles = detectCycles(buildGraph, modules.map(m => m.name)); + const serviceCycles = detectCycles(serviceGraph, serviceNames); + if (buildCycles.length > 0 || serviceCycles.length > 0) { + const detail = {}; + if (buildCycles.length > 0) { + detail["circular-build-dependencies"] = cyclesToString(buildCycles); + } + if (serviceCycles.length > 0) { + detail["circular-service-dependencies"] = cyclesToString(serviceCycles); + } + throw new exceptions_1.ConfigurationError("Circular dependencies detected", detail); + } + }); +} +exports.detectCircularDependencies = detectCircularDependencies; +function detectCycles(graph, vertices) { + // Compute shortest paths + for (const k of vertices) { + for (const i of vertices) { + for (const j of vertices) { + const distanceViaK = distance(graph, i, k) + distance(graph, k, j); + if (distanceViaK < distance(graph, i, j)) { + const nextViaK = next(graph, i, k); + lodash_1.set(graph, [i, j], { distance: distanceViaK, next: nextViaK }); + } + } + } + } + // Reconstruct cycles, if any + const cycleVertices = vertices.filter(v => next(graph, v, v)); + const cycles = cycleVertices.map(v => { + const cycle = [v]; + let nextInCycle = next(graph, v, v); + while (nextInCycle !== v) { + cycle.push(nextInCycle); + nextInCycle = next(graph, nextInCycle, v); + } + return cycle; + }); + return lodash_1.uniqWith(cycles, // The concat calls below are to prevent in-place sorting. + (c1, c2) => lodash_1.isEqual(c1.concat().sort(), c2.concat().sort())); +} +exports.detectCycles = detectCycles; +function distance(graph, source, destination) { + return lodash_1.get(graph, [source, destination, "distance"], Infinity); +} +function next(graph, source, destination) { + return lodash_1.get(graph, [source, destination, "next"]); +} +function cyclesToString(cycles) { + const cycleDescriptions = cycles.map(c => lodash_1.join(c.concat([c[0]]), " <- ")); + return cycleDescriptions.length === 1 ? cycleDescriptions[0] : cycleDescriptions; +} + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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QkM7QUFFRCxTQUFTLFFBQVEsQ0FBQyxLQUFLLEVBQUUsTUFBTSxFQUFFLFdBQVc7SUFDMUMsT0FBTyxZQUFHLENBQUMsS0FBSyxFQUFFLENBQUMsTUFBTSxFQUFFLFdBQVcsRUFBRSxVQUFVLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQTtBQUNoRSxDQUFDO0FBRUQsU0FBUyxJQUFJLENBQUMsS0FBSyxFQUFFLE1BQU0sRUFBRSxXQUFXO0lBQ3RDLE9BQU8sWUFBRyxDQUFDLEtBQUssRUFBRSxDQUFDLE1BQU0sRUFBRSxXQUFXLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQTtBQUNsRCxDQUFDO0FBRUQsU0FBUyxjQUFjLENBQUMsTUFBZTtJQUNyQyxNQUFNLGlCQUFpQixHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxhQUFJLENBQUMsQ0FBQyxDQUFDLE1BQU0sQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDLEVBQUUsTUFBTSxDQUFDLENBQUMsQ0FBQTtJQUN6RSxPQUFPLGlCQUFpQixDQUFDLE1BQU0sS0FBSyxDQUFDLENBQUMsQ0FBQyxDQUFDLGlCQUFpQixDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsQ0FBQyxpQkFBaUIsQ0FBQTtBQUNsRixDQUFDIiwiZmlsZSI6InV0aWwvZGV0ZWN0Q3ljbGVzLmpzIiwic291cmNlc0NvbnRlbnQiOlsiLypcbiAqIENvcHlyaWdodCAoQykgMjAxOCBHYXJkZW4gVGVjaG5vbG9naWVzLCBJbmMuIDxpbmZvQGdhcmRlbi5pbz5cbiAqXG4gKiBUaGlzIFNvdXJjZSBDb2RlIEZvcm0gaXMgc3ViamVjdCB0byB0aGUgdGVybXMgb2YgdGhlIE1vemlsbGEgUHVibGljXG4gKiBMaWNlbnNlLCB2LiAyLjAuIElmIGEgY29weSBvZiB0aGUgTVBMIHdhcyBub3QgZGlzdHJpYnV0ZWQgd2l0aCB0aGlzXG4gKiBmaWxlLCBZb3UgY2FuIG9idGFpbiBvbmUgYXQgaHR0cDovL21vemlsbGEub3JnL01QTC8yLjAvLlxuICovXG5cbmltcG9ydCB7IGdldCwgaXNFcXVhbCwgam9pbiwgc2V0LCB1bmlxV2l0aCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgTW9kdWxlLCBnZXRNb2R1bGVLZXkgfSBmcm9tIFwiLi4vdHlwZXMvbW9kdWxlXCJcbmltcG9ydCB7XG4gIENvbmZpZ3VyYXRpb25FcnJvcixcbn0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHsgU2VydmljZSB9IGZyb20gXCIuLi90eXBlcy9zZXJ2aWNlXCJcblxuZXhwb3J0IHR5cGUgQ3ljbGUgPSBzdHJpbmdbXVxuXG4vKlxuICBJbXBsZW1lbnRzIGEgdmFyaWF0aW9uIG9uIHRoZSBGbG95ZC1XYXJzaGFsbCBhbGdvcml0aG0gdG8gY29tcHV0ZSBtaW5pbWFsIGN5Y2xlcy5cblxuICBUaGlzIGlzIGFwcHJveGltYXRlbHkgTyhtXjMpICsgTyhzXjMpLCB3aGVyZSBtIGlzIHRoZSBudW1iZXIgb2YgbW9kdWxlcyBhbmQgcyBpcyB0aGUgbnVtYmVyIG9mIHNlcnZpY2VzLlxuXG4gIFRocm93cyBhbiBlcnJvciBpZiBjeWNsZXMgd2VyZSBmb3VuZC5cbiovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZGV0ZWN0Q2lyY3VsYXJEZXBlbmRlbmNpZXMobW9kdWxlczogTW9kdWxlW10sIHNlcnZpY2VzOiBTZXJ2aWNlW10pIHtcbiAgLy8gU3BhcnNlIG1hdHJpY2VzXG4gIGNvbnN0IGJ1aWxkR3JhcGggPSB7fVxuICBjb25zdCBzZXJ2aWNlR3JhcGggPSB7fVxuXG4gIC8qXG4gICAgVGhlcmUncyBubyBuZWVkIHRvIGFjY291bnQgZm9yIHRlc3QgZGVwZW5kZW5jaWVzIGhlcmUsIHNpbmNlIGFueSBjaXJjdWxhcml0aWVzIHRoZXJlXG4gICAgYXJlIGFjY291bnRlZCBmb3IgdmlhIHNlcnZpY2UgZGVwZW5kZW5jaWVzLlxuICAgICovXG4gIGZvciAoY29uc3QgbW9kdWxlIG9mIG1vZHVsZXMpIHtcbiAgICAvLyBCdWlsZCBkZXBlbmRlbmNpZXNcbiAgICBmb3IgKGNvbnN0IGJ1aWxkRGVwIG9mIG1vZHVsZS5idWlsZC5kZXBlbmRlbmNpZXMpIHtcbiAgICAgIGNvbnN0IGRlcE5hbWUgPSBnZXRNb2R1bGVLZXkoYnVpbGREZXAubmFtZSwgYnVpbGREZXAucGx1Z2luKVxuICAgICAgc2V0KGJ1aWxkR3JhcGgsIFttb2R1bGUubmFtZSwgZGVwTmFtZV0sIHsgZGlzdGFuY2U6IDEsIG5leHQ6IGRlcE5hbWUgfSlcbiAgICB9XG5cbiAgICAvLyBTZXJ2aWNlIGRlcGVuZGVuY2llc1xuICAgIGZvciAoY29uc3Qgc2VydmljZSBvZiBtb2R1bGUuc2VydmljZUNvbmZpZ3MgfHwgW10pIHtcbiAgICAgIGZvciAoY29uc3QgZGVwTmFtZSBvZiBzZXJ2aWNlLmRlcGVuZGVuY2llcykge1xuICAgICAgICBzZXQoc2VydmljZUdyYXBoLCBbc2VydmljZS5uYW1lLCBkZXBOYW1lXSwgeyBkaXN0YW5jZTogMSwgbmV4dDogZGVwTmFtZSB9KVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHNlcnZpY2VOYW1lcyA9IHNlcnZpY2VzLm1hcChzID0+IHMubmFtZSlcbiAgY29uc3QgYnVpbGRDeWNsZXMgPSBkZXRlY3RDeWNsZXMoYnVpbGRHcmFwaCwgbW9kdWxlcy5tYXAobSA9PiBtLm5hbWUpKVxuICBjb25zdCBzZXJ2aWNlQ3ljbGVzID0gZGV0ZWN0Q3ljbGVzKHNlcnZpY2VHcmFwaCwgc2VydmljZU5hbWVzKVxuXG4gIGlmIChidWlsZEN5Y2xlcy5sZW5ndGggPiAwIHx8IHNlcnZpY2VDeWNsZXMubGVuZ3RoID4gMCkge1xuICAgIGNvbnN0IGRldGFpbCA9IHt9XG5cbiAgICBpZiAoYnVpbGRDeWNsZXMubGVuZ3RoID4gMCkge1xuICAgICAgZGV0YWlsW1wiY2lyY3VsYXItYnVpbGQtZGVwZW5kZW5jaWVzXCJdID0gY3ljbGVzVG9TdHJpbmcoYnVpbGRDeWNsZXMpXG4gICAgfVxuXG4gICAgaWYgKHNlcnZpY2VDeWNsZXMubGVuZ3RoID4gMCkge1xuICAgICAgZGV0YWlsW1wiY2lyY3VsYXItc2VydmljZS1kZXBlbmRlbmNpZXNcIl0gPSBjeWNsZXNUb1N0cmluZyhzZXJ2aWNlQ3ljbGVzKVxuICAgIH1cblxuICAgIHRocm93IG5ldyBDb25maWd1cmF0aW9uRXJyb3IoXCJDaXJjdWxhciBkZXBlbmRlbmNpZXMgZGV0ZWN0ZWRcIiwgZGV0YWlsKVxuICB9XG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXRlY3RDeWNsZXMoZ3JhcGgsIHZlcnRpY2VzOiBzdHJpbmdbXSk6IEN5Y2xlW10ge1xuICAvLyBDb21wdXRlIHNob3J0ZXN0IHBhdGhzXG4gIGZvciAoY29uc3QgayBvZiB2ZXJ0aWNlcykge1xuICAgIGZvciAoY29uc3QgaSBvZiB2ZXJ0aWNlcykge1xuICAgICAgZm9yIChjb25zdCBqIG9mIHZlcnRpY2VzKSB7XG4gICAgICAgIGNvbnN0IGRpc3RhbmNlVmlhSzogbnVtYmVyID0gZGlzdGFuY2UoZ3JhcGgsIGksIGspICsgZGlzdGFuY2UoZ3JhcGgsIGssIGopXG4gICAgICAgIGlmIChkaXN0YW5jZVZpYUsgPCBkaXN0YW5jZShncmFwaCwgaSwgaikpIHtcbiAgICAgICAgICBjb25zdCBuZXh0VmlhSyA9IG5leHQoZ3JhcGgsIGksIGspXG4gICAgICAgICAgc2V0KGdyYXBoLCBbaSwgal0sIHsgZGlzdGFuY2U6IGRpc3RhbmNlVmlhSywgbmV4dDogbmV4dFZpYUsgfSlcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIC8vIFJlY29uc3RydWN0IGN5Y2xlcywgaWYgYW55XG4gIGNvbnN0IGN5Y2xlVmVydGljZXMgPSB2ZXJ0aWNlcy5maWx0ZXIodiA9PiBuZXh0KGdyYXBoLCB2LCB2KSlcbiAgY29uc3QgY3ljbGVzOiBDeWNsZVtdID0gY3ljbGVWZXJ0aWNlcy5tYXAodiA9PiB7XG4gICAgY29uc3QgY3ljbGUgPSBbdl1cbiAgICBsZXQgbmV4dEluQ3ljbGUgPSBuZXh0KGdyYXBoLCB2LCB2KSFcbiAgICB3aGlsZSAobmV4dEluQ3ljbGUgIT09IHYpIHtcbiAgICAgIGN5Y2xlLnB1c2gobmV4dEluQ3ljbGUpXG4gICAgICBuZXh0SW5DeWNsZSA9IG5leHQoZ3JhcGgsIG5leHRJbkN5Y2xlLCB2KSFcbiAgICB9XG4gICAgcmV0dXJuIGN5Y2xlXG4gIH0pXG5cbiAgcmV0dXJuIHVuaXFXaXRoKFxuICAgIGN5Y2xlcywgLy8gVGhlIGNvbmNhdCBjYWxscyBiZWxvdyBhcmUgdG8gcHJldmVudCBpbi1wbGFjZSBzb3J0aW5nLlxuICAgIChjMSwgYzIpID0+IGlzRXF1YWwoYzEuY29uY2F0KCkuc29ydCgpLCBjMi5jb25jYXQoKS5zb3J0KCkpKVxufVxuXG5mdW5jdGlvbiBkaXN0YW5jZShncmFwaCwgc291cmNlLCBkZXN0aW5hdGlvbik6IG51bWJlciB7XG4gIHJldHVybiBnZXQoZ3JhcGgsIFtzb3VyY2UsIGRlc3RpbmF0aW9uLCBcImRpc3RhbmNlXCJdLCBJbmZpbml0eSlcbn1cblxuZnVuY3Rpb24gbmV4dChncmFwaCwgc291cmNlLCBkZXN0aW5hdGlvbik6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gIHJldHVybiBnZXQoZ3JhcGgsIFtzb3VyY2UsIGRlc3RpbmF0aW9uLCBcIm5leHRcIl0pXG59XG5cbmZ1bmN0aW9uIGN5Y2xlc1RvU3RyaW5nKGN5Y2xlczogQ3ljbGVbXSkge1xuICBjb25zdCBjeWNsZURlc2NyaXB0aW9ucyA9IGN5Y2xlcy5tYXAoYyA9PiBqb2luKGMuY29uY2F0KFtjWzBdXSksIFwiIDwtIFwiKSlcbiAgcmV0dXJuIGN5Y2xlRGVzY3JpcHRpb25zLmxlbmd0aCA9PT0gMSA/IGN5Y2xlRGVzY3JpcHRpb25zWzBdIDogY3ljbGVEZXNjcmlwdGlvbnNcbn1cbiJdfQ== diff --git a/garden-service/build/util/ext-source-util.d.ts b/garden-service/build/util/ext-source-util.d.ts new file mode 100644 index 00000000000..e541fc69f0d --- /dev/null +++ b/garden-service/build/util/ext-source-util.d.ts @@ -0,0 +1,34 @@ +import { LinkedSource } from "../config-store"; +import { Module } from "../types/module"; +import { Garden } from "../garden"; +export declare type ExternalSourceType = "project" | "module"; +export declare function getRemoteSourcesDirname(type: ExternalSourceType): string; +/** + * A remote source dir name has the format 'source-name--HASH_OF_REPO_URL' + * so that we can detect if the repo url has changed + */ +export declare function getRemoteSourcePath({ name, url, sourceType }: { + name: string; + url: string; + sourceType: ExternalSourceType; +}): string; +export declare function hashRepoUrl(url: string): string; +export declare function hasRemoteSource(module: Module): boolean; +export declare function getConfigKey(type: ExternalSourceType): string; +/** + * Check if any module is linked, including those within an external project source. + * Returns true if module path is not under the project root or alternatively if the module is a Garden module. + */ +export declare function isModuleLinked(module: Module, garden: Garden): boolean; +export declare function getLinkedSources(garden: Garden, type: ExternalSourceType): Promise; +export declare function addLinkedSources({ garden, sourceType, sources }: { + garden: Garden; + sourceType: ExternalSourceType; + sources: LinkedSource[]; +}): Promise; +export declare function removeLinkedSources({ garden, sourceType, names }: { + garden: Garden; + sourceType: ExternalSourceType; + names: string[]; +}): Promise; +//# sourceMappingURL=ext-source-util.d.ts.map \ No newline at end of file diff --git a/garden-service/build/util/ext-source-util.js b/garden-service/build/util/ext-source-util.js new file mode 100644 index 00000000000..c6fe673fd18 --- /dev/null +++ b/garden-service/build/util/ext-source-util.js @@ -0,0 +1,99 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const crypto_1 = require("crypto"); +const lodash_1 = require("lodash"); +const chalk_1 = require("chalk"); +const pathIsInside = require("path-is-inside"); +const constants_1 = require("../constants"); +const config_store_1 = require("../config-store"); +const exceptions_1 = require("../exceptions"); +const path_1 = require("path"); +function getRemoteSourcesDirname(type) { + return type === "project" ? constants_1.PROJECT_SOURCES_DIR_NAME : constants_1.MODULE_SOURCES_DIR_NAME; +} +exports.getRemoteSourcesDirname = getRemoteSourcesDirname; +/** + * A remote source dir name has the format 'source-name--HASH_OF_REPO_URL' + * so that we can detect if the repo url has changed + */ +function getRemoteSourcePath({ name, url, sourceType }) { + const dirname = name + "--" + hashRepoUrl(url); + return path_1.join(getRemoteSourcesDirname(sourceType), dirname); +} +exports.getRemoteSourcePath = getRemoteSourcePath; +function hashRepoUrl(url) { + const urlHash = crypto_1.createHash("sha256"); + urlHash.update(url); + return urlHash.digest("hex").slice(0, 10); +} +exports.hashRepoUrl = hashRepoUrl; +function hasRemoteSource(module) { + return !!module.repositoryUrl; +} +exports.hasRemoteSource = hasRemoteSource; +function getConfigKey(type) { + return type === "project" ? config_store_1.localConfigKeys.linkedProjectSources : config_store_1.localConfigKeys.linkedModuleSources; +} +exports.getConfigKey = getConfigKey; +/** + * Check if any module is linked, including those within an external project source. + * Returns true if module path is not under the project root or alternatively if the module is a Garden module. + */ +function isModuleLinked(module, garden) { + const isPluginModule = !!module.plugin; + return !pathIsInside(module.path, garden.projectRoot) && !isPluginModule; +} +exports.isModuleLinked = isModuleLinked; +function getLinkedSources(garden, type) { + return __awaiter(this, void 0, void 0, function* () { + const localConfig = yield garden.localConfigStore.get(); + return (type === "project" + ? localConfig.linkedProjectSources + : localConfig.linkedModuleSources) || []; + }); +} +exports.getLinkedSources = getLinkedSources; +function addLinkedSources({ garden, sourceType, sources }) { + return __awaiter(this, void 0, void 0, function* () { + const linked = lodash_1.uniqBy([...yield getLinkedSources(garden, sourceType), ...sources], "name"); + yield garden.localConfigStore.set([getConfigKey(sourceType)], linked); + return linked; + }); +} +exports.addLinkedSources = addLinkedSources; +function removeLinkedSources({ garden, sourceType, names }) { + return __awaiter(this, void 0, void 0, function* () { + const currentlyLinked = yield getLinkedSources(garden, sourceType); + const currentNames = currentlyLinked.map(s => s.name); + for (const name of names) { + if (!currentNames.includes(name)) { + const msg = sourceType === "project" + ? `Source ${chalk_1.default.underline(name)} is not linked. Did you mean to unlink a module?` + : `Module ${chalk_1.default.underline(name)} is not linked. Did you mean to unlink a source?`; + const errorKey = sourceType === "project" ? "currentlyLinkedSources" : "currentlyLinkedModules"; + throw new exceptions_1.ParameterError(msg, { [errorKey]: currentNames, input: names }); + } + } + const linked = currentlyLinked.filter(({ name }) => !names.includes(name)); + yield garden.localConfigStore.set([getConfigKey(sourceType)], linked); + return linked; + }); +} +exports.removeLinkedSources = removeLinkedSources; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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dXRpbC9leHQtc291cmNlLXV0aWwuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJjcnlwdG9cIlxuaW1wb3J0IHsgdW5pcUJ5IH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgY2hhbGsgZnJvbSBcImNoYWxrXCJcbmltcG9ydCBwYXRoSXNJbnNpZGUgPSByZXF1aXJlKFwicGF0aC1pcy1pbnNpZGVcIilcblxuaW1wb3J0IHtcbiAgUFJPSkVDVF9TT1VSQ0VTX0RJUl9OQU1FLFxuICBNT0RVTEVfU09VUkNFU19ESVJfTkFNRSxcbn0gZnJvbSBcIi4uL2NvbnN0YW50c1wiXG5pbXBvcnQge1xuICBMaW5rZWRTb3VyY2UsXG4gIGxvY2FsQ29uZmlnS2V5cyxcbn0gZnJvbSBcIi4uL2NvbmZpZy1zdG9yZVwiXG5pbXBvcnQgeyBQYXJhbWV0ZXJFcnJvciB9IGZyb20gXCIuLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IE1vZHVsZSB9IGZyb20gXCIuLi90eXBlcy9tb2R1bGVcIlxuaW1wb3J0IHsgam9pbiB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuLi9nYXJkZW5cIlxuXG5leHBvcnQgdHlwZSBFeHRlcm5hbFNvdXJjZVR5cGUgPSBcInByb2plY3RcIiB8IFwibW9kdWxlXCJcblxuZXhwb3J0IGZ1bmN0aW9uIGdldFJlbW90ZVNvdXJjZXNEaXJuYW1lKHR5cGU6IEV4dGVybmFsU291cmNlVHlwZSk6IHN0cmluZyB7XG4gIHJldHVybiB0eXBlID09PSBcInByb2plY3RcIiA/IFBST0pFQ1RfU09VUkNFU19ESVJfTkFNRSA6IE1PRFVMRV9TT1VSQ0VTX0RJUl9OQU1FXG59XG5cbi8qKlxuICogQSByZW1vdGUgc291cmNlIGRpciBuYW1lIGhhcyB0aGUgZm9ybWF0ICdzb3VyY2UtbmFtZS0tSEFTSF9PRl9SRVBPX1VSTCdcbiAqIHNvIHRoYXQgd2UgY2FuIGRldGVjdCBpZiB0aGUgcmVwbyB1cmwgaGFzIGNoYW5nZWRcbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIGdldFJlbW90ZVNvdXJjZVBhdGgoeyBuYW1lLCB1cmwsIHNvdXJjZVR5cGUgfTpcbiAgeyBuYW1lOiBzdHJpbmcsIHVybDogc3RyaW5nLCBzb3VyY2VUeXBlOiBFeHRlcm5hbFNvdXJjZVR5cGUgfSkge1xuICBjb25zdCBkaXJuYW1lID0gbmFtZSArIFwiLS1cIiArIGhhc2hSZXBvVXJsKHVybClcbiAgcmV0dXJuIGpvaW4oZ2V0UmVtb3RlU291cmNlc0Rpcm5hbWUoc291cmNlVHlwZSksIGRpcm5hbWUpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoYXNoUmVwb1VybCh1cmw6IHN0cmluZykge1xuICBjb25zdCB1cmxIYXNoID0gY3JlYXRlSGFzaChcInNoYTI1NlwiKVxuICB1cmxIYXNoLnVwZGF0ZSh1cmwpXG4gIHJldHVybiB1cmxIYXNoLmRpZ2VzdChcImhleFwiKS5zbGljZSgwLCAxMClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGhhc1JlbW90ZVNvdXJjZShtb2R1bGU6IE1vZHVsZSk6IGJvb2xlYW4ge1xuICByZXR1cm4gISFtb2R1bGUucmVwb3NpdG9yeVVybFxufVxuZXhwb3J0IGZ1bmN0aW9uIGdldENvbmZpZ0tleSh0eXBlOiBFeHRlcm5hbFNvdXJjZVR5cGUpOiBzdHJpbmcge1xuICByZXR1cm4gdHlwZSA9PT0gXCJwcm9qZWN0XCIgPyBsb2NhbENvbmZpZ0tleXMubGlua2VkUHJvamVjdFNvdXJjZXMgOiBsb2NhbENvbmZpZ0tleXMubGlua2VkTW9kdWxlU291cmNlc1xufVxuXG4vKipcbiAqIENoZWNrIGlmIGFueSBtb2R1bGUgaXMgbGlua2VkLCBpbmNsdWRpbmcgdGhvc2Ugd2l0aGluIGFuIGV4dGVybmFsIHByb2plY3Qgc291cmNlLlxuICogUmV0dXJucyB0cnVlIGlmIG1vZHVsZSBwYXRoIGlzIG5vdCB1bmRlciB0aGUgcHJvamVjdCByb290IG9yIGFsdGVybmF0aXZlbHkgaWYgdGhlIG1vZHVsZSBpcyBhIEdhcmRlbiBtb2R1bGUuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBpc01vZHVsZUxpbmtlZChtb2R1bGU6IE1vZHVsZSwgZ2FyZGVuOiBHYXJkZW4pIHtcbiAgY29uc3QgaXNQbHVnaW5Nb2R1bGUgPSAhIW1vZHVsZS5wbHVnaW5cbiAgcmV0dXJuICFwYXRoSXNJbnNpZGUobW9kdWxlLnBhdGgsIGdhcmRlbi5wcm9qZWN0Um9vdCkgJiYgIWlzUGx1Z2luTW9kdWxlXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRMaW5rZWRTb3VyY2VzKFxuICBnYXJkZW46IEdhcmRlbixcbiAgdHlwZTogRXh0ZXJuYWxTb3VyY2VUeXBlLFxuKTogUHJvbWlzZTxMaW5rZWRTb3VyY2VbXT4ge1xuICBjb25zdCBsb2NhbENvbmZpZyA9IGF3YWl0IGdhcmRlbi5sb2NhbENvbmZpZ1N0b3JlLmdldCgpXG4gIHJldHVybiAodHlwZSA9PT0gXCJwcm9qZWN0XCJcbiAgICA/IGxvY2FsQ29uZmlnLmxpbmtlZFByb2plY3RTb3VyY2VzXG4gICAgOiBsb2NhbENvbmZpZy5saW5rZWRNb2R1bGVTb3VyY2VzKSB8fCBbXVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gYWRkTGlua2VkU291cmNlcyh7IGdhcmRlbiwgc291cmNlVHlwZSwgc291cmNlcyB9OiB7XG4gIGdhcmRlbjogR2FyZGVuLFxuICBzb3VyY2VUeXBlOiBFeHRlcm5hbFNvdXJjZVR5cGUsXG4gIHNvdXJjZXM6IExpbmtlZFNvdXJjZVtdLFxufSk6IFByb21pc2U8TGlua2VkU291cmNlW10+IHtcbiAgY29uc3QgbGlua2VkID0gdW5pcUJ5KFsuLi5hd2FpdCBnZXRMaW5rZWRTb3VyY2VzKGdhcmRlbiwgc291cmNlVHlwZSksIC4uLnNvdXJjZXNdLCBcIm5hbWVcIilcbiAgYXdhaXQgZ2FyZGVuLmxvY2FsQ29uZmlnU3RvcmUuc2V0KFtnZXRDb25maWdLZXkoc291cmNlVHlwZSldLCBsaW5rZWQpXG4gIHJldHVybiBsaW5rZWRcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlbW92ZUxpbmtlZFNvdXJjZXMoeyBnYXJkZW4sIHNvdXJjZVR5cGUsIG5hbWVzIH06IHtcbiAgZ2FyZGVuOiBHYXJkZW4sXG4gIHNvdXJjZVR5cGU6IEV4dGVybmFsU291cmNlVHlwZSxcbiAgbmFtZXM6IHN0cmluZ1tdLFxufSk6IFByb21pc2U8TGlua2VkU291cmNlW10+IHtcbiAgY29uc3QgY3VycmVudGx5TGlua2VkID0gYXdhaXQgZ2V0TGlua2VkU291cmNlcyhnYXJkZW4sIHNvdXJjZVR5cGUpXG4gIGNvbnN0IGN1cnJlbnROYW1lcyA9IGN1cnJlbnRseUxpbmtlZC5tYXAocyA9PiBzLm5hbWUpXG5cbiAgZm9yIChjb25zdCBuYW1lIG9mIG5hbWVzKSB7XG4gICAgaWYgKCFjdXJyZW50TmFtZXMuaW5jbHVkZXMobmFtZSkpIHtcbiAgICAgIGNvbnN0IG1zZyA9IHNvdXJjZVR5cGUgPT09IFwicHJvamVjdFwiXG4gICAgICAgID8gYFNvdXJjZSAke2NoYWxrLnVuZGVybGluZShuYW1lKX0gaXMgbm90IGxpbmtlZC4gRGlkIHlvdSBtZWFuIHRvIHVubGluayBhIG1vZHVsZT9gXG4gICAgICAgIDogYE1vZHVsZSAke2NoYWxrLnVuZGVybGluZShuYW1lKX0gaXMgbm90IGxpbmtlZC4gRGlkIHlvdSBtZWFuIHRvIHVubGluayBhIHNvdXJjZT9gXG4gICAgICBjb25zdCBlcnJvcktleSA9IHNvdXJjZVR5cGUgPT09IFwicHJvamVjdFwiID8gXCJjdXJyZW50bHlMaW5rZWRTb3VyY2VzXCIgOiBcImN1cnJlbnRseUxpbmtlZE1vZHVsZXNcIlxuXG4gICAgICB0aHJvdyBuZXcgUGFyYW1ldGVyRXJyb3IobXNnLCB7IFtlcnJvcktleV06IGN1cnJlbnROYW1lcywgaW5wdXQ6IG5hbWVzIH0pXG4gICAgfVxuICB9XG5cbiAgY29uc3QgbGlua2VkID0gY3VycmVudGx5TGlua2VkLmZpbHRlcigoeyBuYW1lIH0pID0+ICFuYW1lcy5pbmNsdWRlcyhuYW1lKSlcbiAgYXdhaXQgZ2FyZGVuLmxvY2FsQ29uZmlnU3RvcmUuc2V0KFtnZXRDb25maWdLZXkoc291cmNlVHlwZSldLCBsaW5rZWQpXG4gIHJldHVybiBsaW5rZWRcbn1cbiJdfQ== diff --git a/garden-service/build/util/is-subset.d.ts b/garden-service/build/util/is-subset.d.ts new file mode 100644 index 00000000000..7477db87f8c --- /dev/null +++ b/garden-service/build/util/is-subset.d.ts @@ -0,0 +1,19 @@ +/** + * Check if an object is contained within another object. + * + * Returns `true` if: + * - all enumerable keys of *subset* are also enumerable in *superset*, and + * - every value assigned to an enumerable key of *subset* strictly equals + * the value assigned to the same key of *superset* – or is a subset of it. + * + * @param {Object} superset + * @param {Object} subset + * + * @returns {Boolean} + * + * @module is-subset + * @function default + * @alias isSubset + */ +export declare const isSubset: (superset: any, subset: any) => boolean; +//# sourceMappingURL=is-subset.d.ts.map \ No newline at end of file diff --git a/garden-service/build/util/is-subset.js b/garden-service/build/util/is-subset.js new file mode 100644 index 00000000000..375764872e8 --- /dev/null +++ b/garden-service/build/util/is-subset.js @@ -0,0 +1,45 @@ +"use strict"; +// NOTE: copied this from the is-subset package to avoid issues with their package manifest +// (https://github.com/studio-b12/is-subset/pull/9) +Object.defineProperty(exports, "__esModule", { value: true }); +/** + * Check if an object is contained within another object. + * + * Returns `true` if: + * - all enumerable keys of *subset* are also enumerable in *superset*, and + * - every value assigned to an enumerable key of *subset* strictly equals + * the value assigned to the same key of *superset* – or is a subset of it. + * + * @param {Object} superset + * @param {Object} subset + * + * @returns {Boolean} + * + * @module is-subset + * @function default + * @alias isSubset + */ +exports.isSubset = (superset, subset) => { + if ((typeof superset !== "object" || superset === null) || + (typeof subset !== "object" || subset === null)) { + return false; + } + if ((superset instanceof Date || subset instanceof Date)) { + return superset.valueOf() === subset.valueOf(); + } + return Object.keys(subset).every((key) => { + if (!superset.propertyIsEnumerable(key)) { + return false; + } + const subsetItem = subset[key]; + const supersetItem = superset[key]; + if ((typeof subsetItem === "object" && subsetItem !== null) ? + !exports.isSubset(supersetItem, subsetItem) : + supersetItem !== subsetItem) { + return false; + } + return true; + }); +}; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInV0aWwvaXMtc3Vic2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQSwyRkFBMkY7QUFDM0YsbURBQW1EOztBQUVuRDs7Ozs7Ozs7Ozs7Ozs7OztHQWdCRztBQUVVLFFBQUEsUUFBUSxHQUFHLENBQUMsUUFBUSxFQUFFLE1BQU0sRUFBRSxFQUFFO0lBQzNDLElBQ0UsQ0FBQyxPQUFPLFFBQVEsS0FBSyxRQUFRLElBQUksUUFBUSxLQUFLLElBQUksQ0FBQztRQUNuRCxDQUFDLE9BQU8sTUFBTSxLQUFLLFFBQVEsSUFBSSxNQUFNLEtBQUssSUFBSSxDQUFDLEVBQy9DO1FBQUUsT0FBTyxLQUFLLENBQUE7S0FBRTtJQUVsQixJQUNFLENBQUMsUUFBUSxZQUFZLElBQUksSUFBSSxNQUFNLFlBQVksSUFBSSxDQUFDLEVBQ3BEO1FBQUUsT0FBTyxRQUFRLENBQUMsT0FBTyxFQUFFLEtBQUssTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFBO0tBQUU7SUFFcEQsT0FBTyxNQUFNLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEtBQUssQ0FBQyxDQUFDLEdBQUcsRUFBRSxFQUFFO1FBQ3ZDLElBQUksQ0FBQyxRQUFRLENBQUMsb0JBQW9CLENBQUMsR0FBRyxDQUFDLEVBQUU7WUFBRSxPQUFPLEtBQUssQ0FBQTtTQUFFO1FBRXpELE1BQU0sVUFBVSxHQUFHLE1BQU0sQ0FBQyxHQUFHLENBQUMsQ0FBQTtRQUM5QixNQUFNLFlBQVksR0FBRyxRQUFRLENBQUMsR0FBRyxDQUFDLENBQUE7UUFDbEMsSUFDRSxDQUFDLE9BQU8sVUFBVSxLQUFLLFFBQVEsSUFBSSxVQUFVLEtBQUssSUFBSSxDQUFDLENBQUMsQ0FBQztZQUN2RCxDQUFDLGdCQUFRLENBQUMsWUFBWSxFQUFFLFVBQVUsQ0FBQyxDQUFDLENBQUM7WUFDckMsWUFBWSxLQUFLLFVBQVUsRUFDN0I7WUFBRSxPQUFPLEtBQUssQ0FBQTtTQUFFO1FBRWxCLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQyxDQUFDLENBQUE7QUFDSixDQUFDLENBQUEiLCJmaWxlIjoidXRpbC9pcy1zdWJzZXQuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvLyBOT1RFOiBjb3BpZWQgdGhpcyBmcm9tIHRoZSBpcy1zdWJzZXQgcGFja2FnZSB0byBhdm9pZCBpc3N1ZXMgd2l0aCB0aGVpciBwYWNrYWdlIG1hbmlmZXN0XG4vLyAoaHR0cHM6Ly9naXRodWIuY29tL3N0dWRpby1iMTIvaXMtc3Vic2V0L3B1bGwvOSlcblxuLyoqXG4gKiBDaGVjayBpZiBhbiBvYmplY3QgaXMgY29udGFpbmVkIHdpdGhpbiBhbm90aGVyIG9iamVjdC5cbiAqXG4gKiBSZXR1cm5zIGB0cnVlYCBpZjpcbiAqIC0gYWxsIGVudW1lcmFibGUga2V5cyBvZiAqc3Vic2V0KiBhcmUgYWxzbyBlbnVtZXJhYmxlIGluICpzdXBlcnNldCosIGFuZFxuICogLSBldmVyeSB2YWx1ZSBhc3NpZ25lZCB0byBhbiBlbnVtZXJhYmxlIGtleSBvZiAqc3Vic2V0KiBzdHJpY3RseSBlcXVhbHNcbiAqICAgdGhlIHZhbHVlIGFzc2lnbmVkIHRvIHRoZSBzYW1lIGtleSBvZiAqc3VwZXJzZXQqIOKAkyBvciBpcyBhIHN1YnNldCBvZiBpdC5cbiAqXG4gKiBAcGFyYW0gIHtPYmplY3R9ICBzdXBlcnNldFxuICogQHBhcmFtICB7T2JqZWN0fSAgc3Vic2V0XG4gKlxuICogQHJldHVybnMgIHtCb29sZWFufVxuICpcbiAqIEBtb2R1bGUgICAgaXMtc3Vic2V0XG4gKiBAZnVuY3Rpb24gIGRlZmF1bHRcbiAqIEBhbGlhcyAgICAgaXNTdWJzZXRcbiAqL1xuXG5leHBvcnQgY29uc3QgaXNTdWJzZXQgPSAoc3VwZXJzZXQsIHN1YnNldCkgPT4ge1xuICBpZiAoXG4gICAgKHR5cGVvZiBzdXBlcnNldCAhPT0gXCJvYmplY3RcIiB8fCBzdXBlcnNldCA9PT0gbnVsbCkgfHxcbiAgICAodHlwZW9mIHN1YnNldCAhPT0gXCJvYmplY3RcIiB8fCBzdWJzZXQgPT09IG51bGwpXG4gICkgeyByZXR1cm4gZmFsc2UgfVxuXG4gIGlmIChcbiAgICAoc3VwZXJzZXQgaW5zdGFuY2VvZiBEYXRlIHx8IHN1YnNldCBpbnN0YW5jZW9mIERhdGUpXG4gICkgeyByZXR1cm4gc3VwZXJzZXQudmFsdWVPZigpID09PSBzdWJzZXQudmFsdWVPZigpIH1cblxuICByZXR1cm4gT2JqZWN0LmtleXMoc3Vic2V0KS5ldmVyeSgoa2V5KSA9PiB7XG4gICAgaWYgKCFzdXBlcnNldC5wcm9wZXJ0eUlzRW51bWVyYWJsZShrZXkpKSB7IHJldHVybiBmYWxzZSB9XG5cbiAgICBjb25zdCBzdWJzZXRJdGVtID0gc3Vic2V0W2tleV1cbiAgICBjb25zdCBzdXBlcnNldEl0ZW0gPSBzdXBlcnNldFtrZXldXG4gICAgaWYgKFxuICAgICAgKHR5cGVvZiBzdWJzZXRJdGVtID09PSBcIm9iamVjdFwiICYmIHN1YnNldEl0ZW0gIT09IG51bGwpID9cbiAgICAgICAgIWlzU3Vic2V0KHN1cGVyc2V0SXRlbSwgc3Vic2V0SXRlbSkgOlxuICAgICAgICBzdXBlcnNldEl0ZW0gIT09IHN1YnNldEl0ZW1cbiAgICApIHsgcmV0dXJuIGZhbHNlIH1cblxuICAgIHJldHVybiB0cnVlXG4gIH0pXG59XG4iXX0= diff --git a/garden-service/build/util/keyed-set.d.ts b/garden-service/build/util/keyed-set.d.ts new file mode 100644 index 00000000000..018fdcf7cd0 --- /dev/null +++ b/garden-service/build/util/keyed-set.d.ts @@ -0,0 +1,13 @@ +export declare class KeyedSet { + private keyFn; + private map; + constructor(keyFn: (V: any) => string); + add(entry: V): KeyedSet; + delete(entry: V): boolean; + has(entry: V): boolean; + hasKey(key: string): boolean; + entries(): V[]; + size(): number; + clear(): void; +} +//# sourceMappingURL=keyed-set.d.ts.map \ No newline at end of file diff --git a/garden-service/build/util/keyed-set.js b/garden-service/build/util/keyed-set.js new file mode 100644 index 00000000000..568e5583f50 --- /dev/null +++ b/garden-service/build/util/keyed-set.js @@ -0,0 +1,46 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +Object.defineProperty(exports, "__esModule", { value: true }); +/* + A simple set data structure that uses a custom key function for equality comparisons. + + Useful for sets of non-scalar entries, where the built-in Set data structure's === comparison is not suitable. +*/ +class KeyedSet { + constructor(keyFn) { + this.keyFn = keyFn; + this.map = new Map(); + } + add(entry) { + this.map.set(this.keyFn(entry), entry); + return this; + } + delete(entry) { + return this.map.delete(this.keyFn(entry)); + } + has(entry) { + return this.map.has(this.keyFn(entry)); + } + hasKey(key) { + return this.map.has(key); + } + // Returns set members in insertion order. + entries() { + return Array.from(this.map.values()); + } + size() { + return this.map.size; + } + clear() { + this.map = new Map(); + } +} +exports.KeyedSet = KeyedSet; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,eyJ2ZXJzaW9uIjozLCJzb3VyY2VzIjpbInV0aWwva2V5ZWQtc2V0LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7QUFBQTs7Ozs7O0dBTUc7O0FBRUg7Ozs7RUFJRTtBQUNGLE1BQWEsUUFBUTtJQUduQixZQUFvQixLQUFvQjtRQUFwQixVQUFLLEdBQUwsS0FBSyxDQUFlO1FBQ3RDLElBQUksQ0FBQyxHQUFHLEdBQUcsSUFBSSxHQUFHLEVBQUUsQ0FBQTtJQUN0QixDQUFDO0lBRUQsR0FBRyxDQUFDLEtBQVE7UUFDVixJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxFQUFFLEtBQUssQ0FBQyxDQUFBO1FBQ3RDLE9BQU8sSUFBSSxDQUFBO0lBQ2IsQ0FBQztJQUVELE1BQU0sQ0FBQyxLQUFRO1FBQ2IsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDM0MsQ0FBQztJQUVELEdBQUcsQ0FBQyxLQUFRO1FBQ1YsT0FBTyxJQUFJLENBQUMsR0FBRyxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFDLENBQUE7SUFDeEMsQ0FBQztJQUVELE1BQU0sQ0FBQyxHQUFXO1FBQ2hCLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxHQUFHLENBQUMsR0FBRyxDQUFDLENBQUE7SUFDMUIsQ0FBQztJQUVELDBDQUEwQztJQUMxQyxPQUFPO1FBQ0wsT0FBTyxLQUFLLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsTUFBTSxFQUFFLENBQUMsQ0FBQTtJQUN0QyxDQUFDO0lBRUQsSUFBSTtRQUNGLE9BQU8sSUFBSSxDQUFDLEdBQUcsQ0FBQyxJQUFJLENBQUE7SUFDdEIsQ0FBQztJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsR0FBRyxHQUFHLElBQUksR0FBRyxFQUFFLENBQUE7SUFDdEIsQ0FBQztDQUVGO0FBckNELDRCQXFDQyIsImZpbGUiOiJ1dGlsL2tleWVkLXNldC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG4vKlxuICBBIHNpbXBsZSBzZXQgZGF0YSBzdHJ1Y3R1cmUgdGhhdCB1c2VzIGEgY3VzdG9tIGtleSBmdW5jdGlvbiBmb3IgZXF1YWxpdHkgY29tcGFyaXNvbnMuXG5cbiAgVXNlZnVsIGZvciBzZXRzIG9mIG5vbi1zY2FsYXIgZW50cmllcywgd2hlcmUgdGhlIGJ1aWx0LWluIFNldCBkYXRhIHN0cnVjdHVyZSdzID09PSBjb21wYXJpc29uIGlzIG5vdCBzdWl0YWJsZS5cbiovXG5leHBvcnQgY2xhc3MgS2V5ZWRTZXQ8Vj4ge1xuICBwcml2YXRlIG1hcDogTWFwPHN0cmluZywgVj5cblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGtleUZuOiAoVikgPT4gc3RyaW5nKSB7XG4gICAgdGhpcy5tYXAgPSBuZXcgTWFwKClcbiAgfVxuXG4gIGFkZChlbnRyeTogVik6IEtleWVkU2V0PFY+IHtcbiAgICB0aGlzLm1hcC5zZXQodGhpcy5rZXlGbihlbnRyeSksIGVudHJ5KVxuICAgIHJldHVybiB0aGlzXG4gIH1cblxuICBkZWxldGUoZW50cnk6IFYpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5tYXAuZGVsZXRlKHRoaXMua2V5Rm4oZW50cnkpKVxuICB9XG5cbiAgaGFzKGVudHJ5OiBWKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMubWFwLmhhcyh0aGlzLmtleUZuKGVudHJ5KSlcbiAgfVxuXG4gIGhhc0tleShrZXk6IHN0cmluZyk6IGJvb2xlYW4ge1xuICAgIHJldHVybiB0aGlzLm1hcC5oYXMoa2V5KVxuICB9XG5cbiAgLy8gUmV0dXJucyBzZXQgbWVtYmVycyBpbiBpbnNlcnRpb24gb3JkZXIuXG4gIGVudHJpZXMoKTogVltdIHtcbiAgICByZXR1cm4gQXJyYXkuZnJvbSh0aGlzLm1hcC52YWx1ZXMoKSlcbiAgfVxuXG4gIHNpemUoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5tYXAuc2l6ZVxuICB9XG5cbiAgY2xlYXIoKTogdm9pZCB7XG4gICAgdGhpcy5tYXAgPSBuZXcgTWFwKClcbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/util/util.d.ts b/garden-service/build/util/util.d.ts new file mode 100644 index 00000000000..1389312f3bd --- /dev/null +++ b/garden-service/build/util/util.d.ts @@ -0,0 +1,111 @@ +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +/// +import Bluebird = require("bluebird"); +import { ResolvableProps } from "bluebird"; +import * as klaw from "klaw"; +export declare type HookCallback = (callback?: () => void) => void; +export declare type Omit = Pick>; +export declare type Diff = T extends U ? never : T; +export declare type Nullable = { + [P in keyof T]: T[P] | null; +}; +export declare type DeepPartial = { + [P in keyof T]?: T[P] extends Array ? Array> : T[P] extends ReadonlyArray ? ReadonlyArray> : DeepPartial; +}; +export declare type Unpacked = T extends (infer U)[] ? U : T extends (...args: any[]) => infer V ? V : T extends Promise ? W : T; +export declare function shutdown(code: any): void; +export declare function registerCleanupFunction(name: string, func: HookCallback): void; +export declare function scanDirectory(path: string, opts?: klaw.Options): AsyncIterableIterator; +export declare function getChildDirNames(parentDir: string): Promise; +export declare function getIgnorer(rootPath: string): Promise; +export declare function sleep(msec: any): Promise<{}>; +export interface SpawnParams { + timeout?: number; + cwd?: string; + data?: Buffer; + ignoreError?: boolean; + env?: { + [key: string]: string | undefined; + }; +} +export interface SpawnPtyParams extends SpawnParams { + silent?: boolean; + tty?: boolean; + bufferOutput?: boolean; +} +export interface SpawnOutput { + code: number; + output: string; + stdout?: string; + stderr?: string; + proc: any; +} +export declare function spawn(cmd: string, args: string[], { timeout, cwd, data, ignoreError, env }?: SpawnParams): Promise; +export declare function spawnPty(cmd: string, args: string[], { silent, tty, timeout, cwd, bufferOutput, data, ignoreError, }?: SpawnPtyParams): Bluebird; +export declare function dumpYaml(yamlPath: any, data: any): Promise; +/** + * Encode multiple objects as one multi-doc YAML file + */ +export declare function encodeYamlMulti(objects: object[]): string; +/** + * Encode and write multiple objects as a multi-doc YAML file + */ +export declare function dumpYamlMulti(yamlPath: string, objects: object[]): Promise; +/** + * Splits the input string on the first occurrence of `delimiter`. + */ +export declare function splitFirst(s: string, delimiter: string): string[]; +/** + * Recursively resolves all promises in the given input, + * walking through all object keys and array items. + */ +export declare function deepResolve(value: T | Iterable | Iterable> | ResolvableProps): Promise | { + [K in keyof T]: T[K]; +}>; +/** + * Recursively maps over all keys in the input and resolves the resulting promises, + * walking through all object keys and array items. + */ +export declare function asyncDeepMap(obj: T, mapper: (value: any) => Promise, options?: Bluebird.ConcurrencyOption): Promise; +export declare function omitUndefined(o: object): import("_").Dictionary; +export declare function serializeObject(o: any): string; +export declare function deserializeObject(s: string): any; +export declare function serializeValues(o: { + [key: string]: any; +}): { + [key: string]: string; +}; +export declare function deserializeValues(o: object): object; +export declare function getEnumKeys(Enum: any): string[]; +export declare function highlightYaml(s: string): string; +export declare function loadYamlFile(path: string): Promise; +export interface ObjectWithName { + name: string; +} +export declare function getNames(array: T[]): string[]; +export declare function findByName(array: T[], name: string): T | undefined; +/** + * Converts a Windows-style path to a cygwin style path (e.g. C:\some\folder -> /cygdrive/c/some/folder). + */ +export declare function toCygwinPath(path: string): string; +/** + * Converts a string identifier to the appropriate casing and style for use in environment variable names. + * (e.g. "my-service" -> "MY_SERVICE") + */ +export declare function getEnvVarName(identifier: string): string; +/** + * Picks the specified keys from the given object, and throws an error if one or more keys are not found. + */ +export declare function pickKeys(obj: T, keys: U[], description?: string): Pick; +//# sourceMappingURL=util.d.ts.map \ No newline at end of file diff --git a/garden-service/build/util/util.js b/garden-service/build/util/util.js new file mode 100644 index 00000000000..af4ed0444c2 --- /dev/null +++ b/garden-service/build/util/util.js @@ -0,0 +1,423 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __await = (this && this.__await) || function (v) { return this instanceof __await ? (this.v = v, this) : new __await(v); } +var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _arguments, generator) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var g = generator.apply(thisArg, _arguments || []), i, q = []; + return i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i; + function verb(n) { if (g[n]) i[n] = function (v) { return new Promise(function (a, b) { q.push([n, v, a, b]) > 1 || resume(n, v); }); }; } + function resume(n, v) { try { step(g[n](v)); } catch (e) { settle(q[0][3], e); } } + function step(r) { r.value instanceof __await ? Promise.resolve(r.value.v).then(fulfill, reject) : settle(q[0][2], r); } + function fulfill(value) { resume("next", value); } + function reject(value) { resume("throw", value); } + function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); } +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const pty = require("node-pty-prebuilt"); +const exitHook = require("async-exit-hook"); +const klaw = require("klaw"); +const yaml = require("js-yaml"); +const Cryo = require("cryo"); +const child_process_1 = require("child_process"); +const fs_extra_1 = require("fs-extra"); +const path_1 = require("path"); +const lodash_1 = require("lodash"); +const exceptions_1 = require("../exceptions"); +const stream_1 = require("stream"); +const lodash_2 = require("lodash"); +const cli_highlight_1 = require("cli-highlight"); +const chalk_1 = require("chalk"); +const hasAnsi = require("has-ansi"); +const js_yaml_1 = require("js-yaml"); +const constants_1 = require("../constants"); +// NOTE: Importing from ignore/ignore doesn't work on Windows +const ignore = require("ignore"); +// shim to allow async generator functions +if (typeof Symbol.asyncIterator === "undefined") { + Symbol.asyncIterator = Symbol("asyncIterator"); +} +const exitHookNames = []; // For debugging/testing/inspection purposes +function shutdown(code) { + // This is a good place to log exitHookNames if needed. + process.exit(code); +} +exports.shutdown = shutdown; +function registerCleanupFunction(name, func) { + exitHookNames.push(name); + exitHook(func); +} +exports.registerCleanupFunction = registerCleanupFunction; +/* + Warning: Don't make any async calls in the loop body when using this function, since this may cause + funky concurrency behavior. + */ +function scanDirectory(path, opts) { + return __asyncGenerator(this, arguments, function* scanDirectory_1() { + let done = false; + let resolver; + let rejecter; + klaw(path, opts) + .on("data", (item) => { + if (item.path !== path) { + resolver(item); + } + }) + .on("error", (err) => { + rejecter(err); + }) + .on("end", () => { + done = true; + resolver(); + }); + // a nice little trick to turn the stream into an async generator + while (!done) { + const promise = new Promise((resolve, reject) => { + resolver = resolve; + rejecter = reject; + }); + yield yield __await(yield __await(promise)); + } + }); +} +exports.scanDirectory = scanDirectory; +function getChildDirNames(parentDir) { + return __awaiter(this, void 0, void 0, function* () { + var e_1, _a; + let dirNames = []; + // Filter on hidden dirs by default. We could make the filter function a param if needed later + const filter = (item) => !path_1.basename(item).startsWith("."); + try { + for (var _b = __asyncValues(scanDirectory(parentDir, { depthLimit: 0, filter })), _c; _c = yield _b.next(), !_c.done;) { + const item = _c.value; + if (!item || !item.stats.isDirectory()) { + continue; + } + dirNames.push(path_1.basename(item.path)); + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); + } + finally { if (e_1) throw e_1.error; } + } + return dirNames; + }); +} +exports.getChildDirNames = getChildDirNames; +function getIgnorer(rootPath) { + return __awaiter(this, void 0, void 0, function* () { + // TODO: this doesn't handle nested .gitignore files, we should revisit + const gitignorePath = path_1.join(rootPath, ".gitignore"); + const gardenignorePath = path_1.join(rootPath, ".gardenignore"); + const ig = ignore(); + if (yield fs_extra_1.pathExists(gitignorePath)) { + ig.add((yield fs_extra_1.readFile(gitignorePath)).toString()); + } + if (yield fs_extra_1.pathExists(gardenignorePath)) { + ig.add((yield fs_extra_1.readFile(gardenignorePath)).toString()); + } + // should we be adding this (or more) by default? + ig.add([ + "node_modules", + ".git", + constants_1.GARDEN_DIR_NAME, + ]); + return ig; + }); +} +exports.getIgnorer = getIgnorer; +function sleep(msec) { + return __awaiter(this, void 0, void 0, function* () { + return new Promise(resolve => setTimeout(resolve, msec)); + }); +} +exports.sleep = sleep; +function spawn(cmd, args, { timeout = 0, cwd, data, ignoreError = false, env } = {}) { + const proc = child_process_1.spawn(cmd, args, { cwd, env }); + const result = { + code: 0, + output: "", + stdout: "", + stderr: "", + proc, + }; + proc.stdout.on("data", (s) => { + result.output += s; + result.stdout += s; + }); + proc.stderr.on("data", (s) => { + result.output += s; + result.stderr += s; + }); + if (data) { + proc.stdin.end(data); + } + return new Promise((resolve, reject) => { + let _timeout; + const _reject = (msg) => { + const err = new Error(msg); + lodash_2.extend(err, result); + reject(err); + }; + if (timeout > 0) { + _timeout = setTimeout(() => { + proc.kill("SIGKILL"); + _reject(`kubectl timed out after ${timeout} seconds.`); + }, timeout * 1000); + } + proc.on("close", (code) => { + _timeout && clearTimeout(_timeout); + result.code = code; + if (code === 0 || ignoreError) { + resolve(result); + } + else { + _reject("Process exited with code " + code); + } + }); + }); +} +exports.spawn = spawn; +function spawnPty(cmd, args, { silent = false, tty = false, timeout = 0, cwd, bufferOutput = true, data, ignoreError = false, } = {}) { + let _process = process; + let proc = pty.spawn(cmd, args, { + cwd, + name: "xterm-color", + cols: _process.stdout.columns, + rows: _process.stdout.rows, + }); + _process.stdin.setEncoding("utf8"); + // raw mode is not available if we're running without a TTY + tty && _process.stdin.setRawMode && _process.stdin.setRawMode(true); + const result = { + code: 0, + output: "", + proc, + }; + proc.on("data", (output) => { + const str = output.toString(); + if (bufferOutput) { + result.output += str; + } + if (!silent) { + process.stdout.write(hasAnsi(str) ? str : chalk_1.default.white(str)); + } + }); + if (data) { + const bufferStream = new stream_1.PassThrough(); + bufferStream.end(data + "\n\0"); + bufferStream.pipe(proc); + proc.end(); + } + if (tty) { + process.stdin.pipe(proc); + } + return new Bluebird((resolve, _reject) => { + let _timeout; + const reject = (err) => { + err.output = result.output; + err.proc = result.proc; + console.log(err.output); + _reject(err); + }; + if (timeout > 0) { + _timeout = setTimeout(() => { + proc.kill("SIGKILL"); + const err = new exceptions_1.TimeoutError(`${cmd} command timed out after ${timeout} seconds.`, { cmd, timeout }); + reject(err); + }, timeout * 1000); + } + proc.on("exit", (code) => { + _timeout && clearTimeout(_timeout); + // make sure raw input is decoupled + tty && _process.stdin.setRawMode && _process.stdin.setRawMode(false); + result.code = code; + if (code === 0 || ignoreError) { + resolve(result); + } + else { + const err = new Error("Process exited with code " + code); + err.code = code; + reject(err); + } + }); + }); +} +exports.spawnPty = spawnPty; +function dumpYaml(yamlPath, data) { + return __awaiter(this, void 0, void 0, function* () { + return fs_extra_1.writeFile(yamlPath, yaml.safeDump(data, { noRefs: true })); + }); +} +exports.dumpYaml = dumpYaml; +/** + * Encode multiple objects as one multi-doc YAML file + */ +function encodeYamlMulti(objects) { + return objects.map(s => js_yaml_1.safeDump(s) + "---\n").join(""); +} +exports.encodeYamlMulti = encodeYamlMulti; +/** + * Encode and write multiple objects as a multi-doc YAML file + */ +function dumpYamlMulti(yamlPath, objects) { + return __awaiter(this, void 0, void 0, function* () { + return fs_extra_1.writeFile(yamlPath, encodeYamlMulti(objects)); + }); +} +exports.dumpYamlMulti = dumpYamlMulti; +/** + * Splits the input string on the first occurrence of `delimiter`. + */ +function splitFirst(s, delimiter) { + const parts = s.split(delimiter); + return [parts[0], parts.slice(1).join(delimiter)]; +} +exports.splitFirst = splitFirst; +/** + * Recursively resolves all promises in the given input, + * walking through all object keys and array items. + */ +function deepResolve(value) { + return __awaiter(this, void 0, void 0, function* () { + if (lodash_2.isArray(value)) { + return yield Bluebird.map(value, deepResolve); + } + else if (lodash_2.isPlainObject(value)) { + return yield Bluebird.props(lodash_2.mapValues(value, deepResolve)); + } + else { + return Promise.resolve(value); + } + }); +} +exports.deepResolve = deepResolve; +/** + * Recursively maps over all keys in the input and resolves the resulting promises, + * walking through all object keys and array items. + */ +function asyncDeepMap(obj, mapper, options) { + return __awaiter(this, void 0, void 0, function* () { + if (lodash_2.isArray(obj)) { + return Bluebird.map(obj, v => asyncDeepMap(v, mapper, options), options); + } + else if (lodash_2.isPlainObject(obj)) { + return lodash_1.fromPairs(yield Bluebird.map(Object.entries(obj), ([key, value]) => __awaiter(this, void 0, void 0, function* () { return [key, yield asyncDeepMap(value, mapper, options)]; }), options)); + } + else { + return mapper(obj); + } + }); +} +exports.asyncDeepMap = asyncDeepMap; +function omitUndefined(o) { + return lodash_2.pickBy(o, (v) => v !== undefined); +} +exports.omitUndefined = omitUndefined; +function serializeObject(o) { + return Buffer.from(Cryo.stringify(o)).toString("base64"); +} +exports.serializeObject = serializeObject; +function deserializeObject(s) { + return Cryo.parse(Buffer.from(s, "base64")); +} +exports.deserializeObject = deserializeObject; +function serializeValues(o) { + return lodash_2.mapValues(o, serializeObject); +} +exports.serializeValues = serializeValues; +function deserializeValues(o) { + return lodash_2.mapValues(o, deserializeObject); +} +exports.deserializeValues = deserializeValues; +function getEnumKeys(Enum) { + return Object.values(Enum).filter(k => typeof k === "string"); +} +exports.getEnumKeys = getEnumKeys; +function highlightYaml(s) { + return cli_highlight_1.default(s, { + language: "yaml", + theme: { + keyword: chalk_1.default.white.italic, + literal: chalk_1.default.white.italic, + string: chalk_1.default.white, + }, + }); +} +exports.highlightYaml = highlightYaml; +function loadYamlFile(path) { + return __awaiter(this, void 0, void 0, function* () { + const fileData = yield fs_extra_1.readFile(path); + return yaml.safeLoad(fileData.toString()); + }); +} +exports.loadYamlFile = loadYamlFile; +function getNames(array) { + return array.map(v => v.name); +} +exports.getNames = getNames; +function findByName(array, name) { + return lodash_1.find(array, ["name", name]); +} +exports.findByName = findByName; +/** + * Converts a Windows-style path to a cygwin style path (e.g. C:\some\folder -> /cygdrive/c/some/folder). + */ +function toCygwinPath(path) { + const parsed = path_1.win32.parse(path); + const drive = parsed.root.split(":")[0].toLowerCase(); + const dirs = parsed.dir.split(path_1.win32.sep).slice(1); + const cygpath = path_1.posix.join("/cygdrive", drive, ...dirs, parsed.base); + // make sure trailing slash is retained + return path.endsWith(path_1.win32.sep) ? cygpath + path_1.posix.sep : cygpath; +} +exports.toCygwinPath = toCygwinPath; +/** + * Converts a string identifier to the appropriate casing and style for use in environment variable names. + * (e.g. "my-service" -> "MY_SERVICE") + */ +function getEnvVarName(identifier) { + return identifier.replace("-", "_").toUpperCase(); +} +exports.getEnvVarName = getEnvVarName; +/** + * Picks the specified keys from the given object, and throws an error if one or more keys are not found. + */ +function pickKeys(obj, keys, description = "key") { + const picked = lodash_1.pick(obj, ...keys); + const missing = lodash_1.difference(keys, Object.keys(picked)); + if (missing.length) { + throw new exceptions_1.ParameterError(`Could not find ${description}(s): ${missing.map((k, _) => k).join(", ")}`, { + missing, + available: Object.keys(obj), + }); + } + return picked; +} +exports.pickKeys = pickKeys; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q25HLE9BQU87WUFDUCxTQUFTLEVBQUUsTUFBTSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUM7U0FDNUIsQ0FBQyxDQUFBO0tBQ0g7SUFFRCxPQUFPLE1BQU0sQ0FBQTtBQUNmLENBQUM7QUFiRCw0QkFhQyIsImZpbGUiOiJ1dGlsL3V0aWwuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IEJsdWViaXJkID0gcmVxdWlyZShcImJsdWViaXJkXCIpXG5pbXBvcnQgeyBSZXNvbHZhYmxlUHJvcHMgfSBmcm9tIFwiYmx1ZWJpcmRcIlxuY29uc3QgcHR5ID0gcmVxdWlyZShcIm5vZGUtcHR5LXByZWJ1aWx0XCIpXG5pbXBvcnQgKiBhcyBleGl0SG9vayBmcm9tIFwiYXN5bmMtZXhpdC1ob29rXCJcbmltcG9ydCAqIGFzIGtsYXcgZnJvbSBcImtsYXdcIlxuaW1wb3J0ICogYXMgeWFtbCBmcm9tIFwianMteWFtbFwiXG5pbXBvcnQgKiBhcyBDcnlvIGZyb20gXCJjcnlvXCJcbmltcG9ydCB7IHNwYXduIGFzIF9zcGF3biB9IGZyb20gXCJjaGlsZF9wcm9jZXNzXCJcbmltcG9ydCB7IHBhdGhFeGlzdHMsIHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgam9pbiwgYmFzZW5hbWUsIHdpbjMyLCBwb3NpeCB9IGZyb20gXCJwYXRoXCJcbmltcG9ydCB7IGZpbmQsIHBpY2ssIGRpZmZlcmVuY2UsIGZyb21QYWlycyB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgVGltZW91dEVycm9yLCBQYXJhbWV0ZXJFcnJvciB9IGZyb20gXCIuLi9leGNlcHRpb25zXCJcbmltcG9ydCB7IFBhc3NUaHJvdWdoIH0gZnJvbSBcInN0cmVhbVwiXG5pbXBvcnQgeyBpc0FycmF5LCBpc1BsYWluT2JqZWN0LCBleHRlbmQsIG1hcFZhbHVlcywgcGlja0J5IH0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgaGlnaGxpZ2h0IGZyb20gXCJjbGktaGlnaGxpZ2h0XCJcbmltcG9ydCBjaGFsayBmcm9tIFwiY2hhbGtcIlxuaW1wb3J0IGhhc0Fuc2kgPSByZXF1aXJlKFwiaGFzLWFuc2lcIilcbmltcG9ydCB7IHNhZmVEdW1wIH0gZnJvbSBcImpzLXlhbWxcIlxuaW1wb3J0IHsgR0FSREVOX0RJUl9OQU1FIH0gZnJvbSBcIi4uL2NvbnN0YW50c1wiXG4vLyBOT1RFOiBJbXBvcnRpbmcgZnJvbSBpZ25vcmUvaWdub3JlIGRvZXNuJ3Qgd29yayBvbiBXaW5kb3dzXG5jb25zdCBpZ25vcmUgPSByZXF1aXJlKFwiaWdub3JlXCIpXG5cbi8vIHNoaW0gdG8gYWxsb3cgYXN5bmMgZ2VuZXJhdG9yIGZ1bmN0aW9uc1xuaWYgKHR5cGVvZiAoU3ltYm9sIGFzIGFueSkuYXN5bmNJdGVyYXRvciA9PT0gXCJ1bmRlZmluZWRcIikge1xuICAoU3ltYm9sIGFzIGFueSkuYXN5bmNJdGVyYXRvciA9IFN5bWJvbChcImFzeW5jSXRlcmF0b3JcIilcbn1cblxuZXhwb3J0IHR5cGUgSG9va0NhbGxiYWNrID0gKGNhbGxiYWNrPzogKCkgPT4gdm9pZCkgPT4gdm9pZFxuXG5jb25zdCBleGl0SG9va05hbWVzOiBzdHJpbmdbXSA9IFtdIC8vIEZvciBkZWJ1Z2dpbmcvdGVzdGluZy9pbnNwZWN0aW9uIHB1cnBvc2VzXG5cbmV4cG9ydCB0eXBlIE9taXQ8VCwgSyBleHRlbmRzIGtleW9mIFQ+ID0gUGljazxULCBFeGNsdWRlPGtleW9mIFQsIEs+PlxuZXhwb3J0IHR5cGUgRGlmZjxULCBVPiA9IFQgZXh0ZW5kcyBVID8gbmV2ZXIgOiBUXG5leHBvcnQgdHlwZSBOdWxsYWJsZTxUPiA9IHsgW1AgaW4ga2V5b2YgVF06IFRbUF0gfCBudWxsIH1cbi8vIEZyb206IGh0dHBzOi8vc3RhY2tvdmVyZmxvdy5jb20vYS80OTkzNjY4Ni81NjI5OTQwXG5leHBvcnQgdHlwZSBEZWVwUGFydGlhbDxUPiA9IHtcbiAgW1AgaW4ga2V5b2YgVF0/OiBUW1BdIGV4dGVuZHMgQXJyYXk8aW5mZXIgVT4gPyBBcnJheTxEZWVwUGFydGlhbDxVPj5cbiAgOiBUW1BdIGV4dGVuZHMgUmVhZG9ubHlBcnJheTxpbmZlciBWPiA/IFJlYWRvbmx5QXJyYXk8RGVlcFBhcnRpYWw8Vj4+XG4gIDogRGVlcFBhcnRpYWw8VFtQXT5cbn1cbmV4cG9ydCB0eXBlIFVucGFja2VkPFQ+ID1cbiAgVCBleHRlbmRzIChpbmZlciBVKVtdID8gVVxuICA6IFQgZXh0ZW5kcyAoLi4uYXJnczogYW55W10pID0+IGluZmVyIFYgPyBWXG4gIDogVCBleHRlbmRzIFByb21pc2U8aW5mZXIgVz4gPyBXXG4gIDogVFxuXG5leHBvcnQgZnVuY3Rpb24gc2h1dGRvd24oY29kZSkge1xuICAvLyBUaGlzIGlzIGEgZ29vZCBwbGFjZSB0byBsb2cgZXhpdEhvb2tOYW1lcyBpZiBuZWVkZWQuXG4gIHByb2Nlc3MuZXhpdChjb2RlKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gcmVnaXN0ZXJDbGVhbnVwRnVuY3Rpb24obmFtZTogc3RyaW5nLCBmdW5jOiBIb29rQ2FsbGJhY2spIHtcbiAgZXhpdEhvb2tOYW1lcy5wdXNoKG5hbWUpXG4gIGV4aXRIb29rKGZ1bmMpXG59XG5cbi8qXG4gIFdhcm5pbmc6IERvbid0IG1ha2UgYW55IGFzeW5jIGNhbGxzIGluIHRoZSBsb29wIGJvZHkgd2hlbiB1c2luZyB0aGlzIGZ1bmN0aW9uLCBzaW5jZSB0aGlzIG1heSBjYXVzZVxuICBmdW5reSBjb25jdXJyZW5jeSBiZWhhdmlvci5cbiAgKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiogc2NhbkRpcmVjdG9yeShwYXRoOiBzdHJpbmcsIG9wdHM/OiBrbGF3Lk9wdGlvbnMpOiBBc3luY0l0ZXJhYmxlSXRlcmF0b3I8a2xhdy5JdGVtPiB7XG4gIGxldCBkb25lID0gZmFsc2VcbiAgbGV0IHJlc29sdmVyXG4gIGxldCByZWplY3RlclxuXG4gIGtsYXcocGF0aCwgb3B0cylcbiAgICAub24oXCJkYXRhXCIsIChpdGVtKSA9PiB7XG4gICAgICBpZiAoaXRlbS5wYXRoICE9PSBwYXRoKSB7XG4gICAgICAgIHJlc29sdmVyKGl0ZW0pXG4gICAgICB9XG4gICAgfSlcbiAgICAub24oXCJlcnJvclwiLCAoZXJyKSA9PiB7XG4gICAgICByZWplY3RlcihlcnIpXG4gICAgfSlcbiAgICAub24oXCJlbmRcIiwgKCkgPT4ge1xuICAgICAgZG9uZSA9IHRydWVcbiAgICAgIHJlc29sdmVyKClcbiAgICB9KVxuXG4gIC8vIGEgbmljZSBsaXR0bGUgdHJpY2sgdG8gdHVybiB0aGUgc3RyZWFtIGludG8gYW4gYXN5bmMgZ2VuZXJhdG9yXG4gIHdoaWxlICghZG9uZSkge1xuICAgIGNvbnN0IHByb21pc2U6IFByb21pc2U8a2xhdy5JdGVtPiA9IG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICAgIHJlc29sdmVyID0gcmVzb2x2ZVxuICAgICAgcmVqZWN0ZXIgPSByZWplY3RcbiAgICB9KVxuXG4gICAgeWllbGQgYXdhaXQgcHJvbWlzZVxuICB9XG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBnZXRDaGlsZERpck5hbWVzKHBhcmVudERpcjogc3RyaW5nKTogUHJvbWlzZTxzdHJpbmdbXT4ge1xuICBsZXQgZGlyTmFtZXM6IHN0cmluZ1tdID0gW11cbiAgLy8gRmlsdGVyIG9uIGhpZGRlbiBkaXJzIGJ5IGRlZmF1bHQuIFdlIGNvdWxkIG1ha2UgdGhlIGZpbHRlciBmdW5jdGlvbiBhIHBhcmFtIGlmIG5lZWRlZCBsYXRlclxuICBjb25zdCBmaWx0ZXIgPSAoaXRlbTogc3RyaW5nKSA9PiAhYmFzZW5hbWUoaXRlbSkuc3RhcnRzV2l0aChcIi5cIilcblxuICBmb3IgYXdhaXQgKGNvbnN0IGl0ZW0gb2Ygc2NhbkRpcmVjdG9yeShwYXJlbnREaXIsIHsgZGVwdGhMaW1pdDogMCwgZmlsdGVyIH0pKSB7XG4gICAgaWYgKCFpdGVtIHx8ICFpdGVtLnN0YXRzLmlzRGlyZWN0b3J5KCkpIHtcbiAgICAgIGNvbnRpbnVlXG4gICAgfVxuICAgIGRpck5hbWVzLnB1c2goYmFzZW5hbWUoaXRlbS5wYXRoKSlcbiAgfVxuICByZXR1cm4gZGlyTmFtZXNcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGdldElnbm9yZXIocm9vdFBhdGg6IHN0cmluZykge1xuICAvLyBUT0RPOiB0aGlzIGRvZXNuJ3QgaGFuZGxlIG5lc3RlZCAuZ2l0aWdub3JlIGZpbGVzLCB3ZSBzaG91bGQgcmV2aXNpdFxuICBjb25zdCBnaXRpZ25vcmVQYXRoID0gam9pbihyb290UGF0aCwgXCIuZ2l0aWdub3JlXCIpXG4gIGNvbnN0IGdhcmRlbmlnbm9yZVBhdGggPSBqb2luKHJvb3RQYXRoLCBcIi5nYXJkZW5pZ25vcmVcIilcbiAgY29uc3QgaWcgPSBpZ25vcmUoKVxuXG4gIGlmIChhd2FpdCBwYXRoRXhpc3RzKGdpdGlnbm9yZVBhdGgpKSB7XG4gICAgaWcuYWRkKChhd2FpdCByZWFkRmlsZShnaXRpZ25vcmVQYXRoKSkudG9TdHJpbmcoKSlcbiAgfVxuXG4gIGlmIChhd2FpdCBwYXRoRXhpc3RzKGdhcmRlbmlnbm9yZVBhdGgpKSB7XG4gICAgaWcuYWRkKChhd2FpdCByZWFkRmlsZShnYXJkZW5pZ25vcmVQYXRoKSkudG9TdHJpbmcoKSlcbiAgfVxuXG4gIC8vIHNob3VsZCB3ZSBiZSBhZGRpbmcgdGhpcyAob3IgbW9yZSkgYnkgZGVmYXVsdD9cbiAgaWcuYWRkKFtcbiAgICBcIm5vZGVfbW9kdWxlc1wiLFxuICAgIFwiLmdpdFwiLFxuICAgIEdBUkRFTl9ESVJfTkFNRSxcbiAgXSlcblxuICByZXR1cm4gaWdcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHNsZWVwKG1zZWMpIHtcbiAgcmV0dXJuIG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBtc2VjKSlcbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcGF3blBhcmFtcyB7XG4gIHRpbWVvdXQ/OiBudW1iZXJcbiAgY3dkPzogc3RyaW5nXG4gIGRhdGE/OiBCdWZmZXJcbiAgaWdub3JlRXJyb3I/OiBib29sZWFuXG4gIGVudj86IHsgW2tleTogc3RyaW5nXTogc3RyaW5nIHwgdW5kZWZpbmVkIH1cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcGF3blB0eVBhcmFtcyBleHRlbmRzIFNwYXduUGFyYW1zIHtcbiAgc2lsZW50PzogYm9vbGVhblxuICB0dHk/OiBib29sZWFuXG4gIGJ1ZmZlck91dHB1dD86IGJvb2xlYW5cbn1cblxuZXhwb3J0IGludGVyZmFjZSBTcGF3bk91dHB1dCB7XG4gIGNvZGU6IG51bWJlclxuICBvdXRwdXQ6IHN0cmluZ1xuICBzdGRvdXQ/OiBzdHJpbmdcbiAgc3RkZXJyPzogc3RyaW5nXG4gIHByb2M6IGFueVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3Bhd24oXG4gIGNtZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSxcbiAgeyB0aW1lb3V0ID0gMCwgY3dkLCBkYXRhLCBpZ25vcmVFcnJvciA9IGZhbHNlLCBlbnYgfTogU3Bhd25QYXJhbXMgPSB7fSxcbikge1xuICBjb25zdCBwcm9jID0gX3NwYXduKGNtZCwgYXJncywgeyBjd2QsIGVudiB9KVxuXG4gIGNvbnN0IHJlc3VsdDogU3Bhd25PdXRwdXQgPSB7XG4gICAgY29kZTogMCxcbiAgICBvdXRwdXQ6IFwiXCIsXG4gICAgc3Rkb3V0OiBcIlwiLFxuICAgIHN0ZGVycjogXCJcIixcbiAgICBwcm9jLFxuICB9XG5cbiAgcHJvYy5zdGRvdXQub24oXCJkYXRhXCIsIChzKSA9PiB7XG4gICAgcmVzdWx0Lm91dHB1dCArPSBzXG4gICAgcmVzdWx0LnN0ZG91dCEgKz0gc1xuICB9KVxuXG4gIHByb2Muc3RkZXJyLm9uKFwiZGF0YVwiLCAocykgPT4ge1xuICAgIHJlc3VsdC5vdXRwdXQgKz0gc1xuICAgIHJlc3VsdC5zdGRlcnIhICs9IHNcbiAgfSlcblxuICBpZiAoZGF0YSkge1xuICAgIHByb2Muc3RkaW4uZW5kKGRhdGEpXG4gIH1cblxuICByZXR1cm4gbmV3IFByb21pc2U8U3Bhd25PdXRwdXQ+KChyZXNvbHZlLCByZWplY3QpID0+IHtcbiAgICBsZXQgX3RpbWVvdXRcblxuICAgIGNvbnN0IF9yZWplY3QgPSAobXNnOiBzdHJpbmcpID0+IHtcbiAgICAgIGNvbnN0IGVyciA9IG5ldyBFcnJvcihtc2cpXG4gICAgICBleHRlbmQoZXJyLCA8YW55PnJlc3VsdClcbiAgICAgIHJlamVjdChlcnIpXG4gICAgfVxuXG4gICAgaWYgKHRpbWVvdXQgPiAwKSB7XG4gICAgICBfdGltZW91dCA9IHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgICBwcm9jLmtpbGwoXCJTSUdLSUxMXCIpXG4gICAgICAgIF9yZWplY3QoYGt1YmVjdGwgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dH0gc2Vjb25kcy5gKVxuICAgICAgfSwgdGltZW91dCAqIDEwMDApXG4gICAgfVxuXG4gICAgcHJvYy5vbihcImNsb3NlXCIsIChjb2RlKSA9PiB7XG4gICAgICBfdGltZW91dCAmJiBjbGVhclRpbWVvdXQoX3RpbWVvdXQpXG4gICAgICByZXN1bHQuY29kZSA9IGNvZGVcblxuICAgICAgaWYgKGNvZGUgPT09IDAgfHwgaWdub3JlRXJyb3IpIHtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBfcmVqZWN0KFwiUHJvY2VzcyBleGl0ZWQgd2l0aCBjb2RlIFwiICsgY29kZSlcbiAgICAgIH1cbiAgICB9KVxuICB9KVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc3Bhd25QdHkoXG4gIGNtZDogc3RyaW5nLCBhcmdzOiBzdHJpbmdbXSxcbiAge1xuICAgIHNpbGVudCA9IGZhbHNlLCB0dHkgPSBmYWxzZSwgdGltZW91dCA9IDAsIGN3ZCxcbiAgICBidWZmZXJPdXRwdXQgPSB0cnVlLCBkYXRhLCBpZ25vcmVFcnJvciA9IGZhbHNlLFxuICB9OiBTcGF3blB0eVBhcmFtcyA9IHt9LFxuKTogQmx1ZWJpcmQ8YW55PiB7XG4gIGxldCBfcHJvY2VzcyA9IDxhbnk+cHJvY2Vzc1xuXG4gIGxldCBwcm9jOiBhbnkgPSBwdHkuc3Bhd24oY21kLCBhcmdzLCB7XG4gICAgY3dkLFxuICAgIG5hbWU6IFwieHRlcm0tY29sb3JcIixcbiAgICBjb2xzOiBfcHJvY2Vzcy5zdGRvdXQuY29sdW1ucyxcbiAgICByb3dzOiBfcHJvY2Vzcy5zdGRvdXQucm93cyxcbiAgfSlcblxuICBfcHJvY2Vzcy5zdGRpbi5zZXRFbmNvZGluZyhcInV0ZjhcIilcblxuICAvLyByYXcgbW9kZSBpcyBub3QgYXZhaWxhYmxlIGlmIHdlJ3JlIHJ1bm5pbmcgd2l0aG91dCBhIFRUWVxuICB0dHkgJiYgX3Byb2Nlc3Muc3RkaW4uc2V0UmF3TW9kZSAmJiBfcHJvY2Vzcy5zdGRpbi5zZXRSYXdNb2RlKHRydWUpXG5cbiAgY29uc3QgcmVzdWx0OiBTcGF3bk91dHB1dCA9IHtcbiAgICBjb2RlOiAwLFxuICAgIG91dHB1dDogXCJcIixcbiAgICBwcm9jLFxuICB9XG5cbiAgcHJvYy5vbihcImRhdGFcIiwgKG91dHB1dCkgPT4ge1xuICAgIGNvbnN0IHN0ciA9IG91dHB1dC50b1N0cmluZygpXG5cbiAgICBpZiAoYnVmZmVyT3V0cHV0KSB7XG4gICAgICByZXN1bHQub3V0cHV0ICs9IHN0clxuICAgIH1cblxuICAgIGlmICghc2lsZW50KSB7XG4gICAgICBwcm9jZXNzLnN0ZG91dC53cml0ZShoYXNBbnNpKHN0cikgPyBzdHIgOiBjaGFsay53aGl0ZShzdHIpKVxuICAgIH1cbiAgfSlcblxuICBpZiAoZGF0YSkge1xuICAgIGNvbnN0IGJ1ZmZlclN0cmVhbSA9IG5ldyBQYXNzVGhyb3VnaCgpXG4gICAgYnVmZmVyU3RyZWFtLmVuZChkYXRhICsgXCJcXG5cXDBcIilcbiAgICBidWZmZXJTdHJlYW0ucGlwZShwcm9jKVxuICAgIHByb2MuZW5kKClcbiAgfVxuXG4gIGlmICh0dHkpIHtcbiAgICBwcm9jZXNzLnN0ZGluLnBpcGUocHJvYylcbiAgfVxuXG4gIHJldHVybiBuZXcgQmx1ZWJpcmQoKHJlc29sdmUsIF9yZWplY3QpID0+IHtcbiAgICBsZXQgX3RpbWVvdXRcblxuICAgIGNvbnN0IHJlamVjdCA9IChlcnI6IGFueSkgPT4ge1xuICAgICAgZXJyLm91dHB1dCA9IHJlc3VsdC5vdXRwdXRcbiAgICAgIGVyci5wcm9jID0gcmVzdWx0LnByb2NcbiAgICAgIGNvbnNvbGUubG9nKGVyci5vdXRwdXQpXG4gICAgICBfcmVqZWN0KGVycilcbiAgICB9XG5cbiAgICBpZiAodGltZW91dCA+IDApIHtcbiAgICAgIF90aW1lb3V0ID0gc2V0VGltZW91dCgoKSA9PiB7XG4gICAgICAgIHByb2Mua2lsbChcIlNJR0tJTExcIilcbiAgICAgICAgY29uc3QgZXJyID0gbmV3IFRpbWVvdXRFcnJvcihgJHtjbWR9IGNvbW1hbmQgdGltZWQgb3V0IGFmdGVyICR7dGltZW91dH0gc2Vjb25kcy5gLCB7IGNtZCwgdGltZW91dCB9KVxuICAgICAgICByZWplY3QoZXJyKVxuICAgICAgfSwgdGltZW91dCAqIDEwMDApXG4gICAgfVxuXG4gICAgcHJvYy5vbihcImV4aXRcIiwgKGNvZGUpID0+IHtcbiAgICAgIF90aW1lb3V0ICYmIGNsZWFyVGltZW91dChfdGltZW91dClcblxuICAgICAgLy8gbWFrZSBzdXJlIHJhdyBpbnB1dCBpcyBkZWNvdXBsZWRcbiAgICAgIHR0eSAmJiBfcHJvY2Vzcy5zdGRpbi5zZXRSYXdNb2RlICYmIF9wcm9jZXNzLnN0ZGluLnNldFJhd01vZGUoZmFsc2UpXG4gICAgICByZXN1bHQuY29kZSA9IGNvZGVcblxuICAgICAgaWYgKGNvZGUgPT09IDAgfHwgaWdub3JlRXJyb3IpIHtcbiAgICAgICAgcmVzb2x2ZShyZXN1bHQpXG4gICAgICB9IGVsc2Uge1xuICAgICAgICBjb25zdCBlcnI6IGFueSA9IG5ldyBFcnJvcihcIlByb2Nlc3MgZXhpdGVkIHdpdGggY29kZSBcIiArIGNvZGUpXG4gICAgICAgIGVyci5jb2RlID0gY29kZVxuICAgICAgICByZWplY3QoZXJyKVxuICAgICAgfVxuICAgIH0pXG4gIH0pXG59XG5cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBkdW1wWWFtbCh5YW1sUGF0aCwgZGF0YSkge1xuICByZXR1cm4gd3JpdGVGaWxlKHlhbWxQYXRoLCB5YW1sLnNhZmVEdW1wKGRhdGEsIHsgbm9SZWZzOiB0cnVlIH0pKVxufVxuXG4vKipcbiAqIEVuY29kZSBtdWx0aXBsZSBvYmplY3RzIGFzIG9uZSBtdWx0aS1kb2MgWUFNTCBmaWxlXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBlbmNvZGVZYW1sTXVsdGkob2JqZWN0czogb2JqZWN0W10pIHtcbiAgcmV0dXJuIG9iamVjdHMubWFwKHMgPT4gc2FmZUR1bXAocykgKyBcIi0tLVxcblwiKS5qb2luKFwiXCIpXG59XG5cbi8qKlxuICogRW5jb2RlIGFuZCB3cml0ZSBtdWx0aXBsZSBvYmplY3RzIGFzIGEgbXVsdGktZG9jIFlBTUwgZmlsZVxuICovXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gZHVtcFlhbWxNdWx0aSh5YW1sUGF0aDogc3RyaW5nLCBvYmplY3RzOiBvYmplY3RbXSkge1xuICByZXR1cm4gd3JpdGVGaWxlKHlhbWxQYXRoLCBlbmNvZGVZYW1sTXVsdGkob2JqZWN0cykpXG59XG5cbi8qKlxuICogU3BsaXRzIHRoZSBpbnB1dCBzdHJpbmcgb24gdGhlIGZpcnN0IG9jY3VycmVuY2Ugb2YgYGRlbGltaXRlcmAuXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBzcGxpdEZpcnN0KHM6IHN0cmluZywgZGVsaW1pdGVyOiBzdHJpbmcpIHtcbiAgY29uc3QgcGFydHMgPSBzLnNwbGl0KGRlbGltaXRlcilcbiAgcmV0dXJuIFtwYXJ0c1swXSwgcGFydHMuc2xpY2UoMSkuam9pbihkZWxpbWl0ZXIpXVxufVxuXG4vKipcbiAqIFJlY3Vyc2l2ZWx5IHJlc29sdmVzIGFsbCBwcm9taXNlcyBpbiB0aGUgZ2l2ZW4gaW5wdXQsXG4gKiB3YWxraW5nIHRocm91Z2ggYWxsIG9iamVjdCBrZXlzIGFuZCBhcnJheSBpdGVtcy5cbiAqL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGRlZXBSZXNvbHZlPFQ+KFxuICB2YWx1ZTogVCB8IEl0ZXJhYmxlPFQ+IHwgSXRlcmFibGU8UHJvbWlzZUxpa2U8VD4+IHwgUmVzb2x2YWJsZVByb3BzPFQ+LFxuKTogUHJvbWlzZTxUIHwgSXRlcmFibGU8VD4gfCB7IFtLIGluIGtleW9mIFRdOiBUW0tdIH0+IHtcbiAgaWYgKGlzQXJyYXkodmFsdWUpKSB7XG4gICAgcmV0dXJuIGF3YWl0IEJsdWViaXJkLm1hcCh2YWx1ZSwgZGVlcFJlc29sdmUpXG4gIH0gZWxzZSBpZiAoaXNQbGFpbk9iamVjdCh2YWx1ZSkpIHtcbiAgICByZXR1cm4gYXdhaXQgQmx1ZWJpcmQucHJvcHMoPFJlc29sdmFibGVQcm9wczxUPj5tYXBWYWx1ZXMoPFJlc29sdmFibGVQcm9wczxUPj52YWx1ZSwgZGVlcFJlc29sdmUpKVxuICB9IGVsc2Uge1xuICAgIHJldHVybiBQcm9taXNlLnJlc29sdmUoPFQ+dmFsdWUpXG4gIH1cbn1cblxuLyoqXG4gKiBSZWN1cnNpdmVseSBtYXBzIG92ZXIgYWxsIGtleXMgaW4gdGhlIGlucHV0IGFuZCByZXNvbHZlcyB0aGUgcmVzdWx0aW5nIHByb21pc2VzLFxuICogd2Fsa2luZyB0aHJvdWdoIGFsbCBvYmplY3Qga2V5cyBhbmQgYXJyYXkgaXRlbXMuXG4gKi9cbmV4cG9ydCBhc3luYyBmdW5jdGlvbiBhc3luY0RlZXBNYXA8VD4oXG4gIG9iajogVCwgbWFwcGVyOiAodmFsdWUpID0+IFByb21pc2U8YW55Piwgb3B0aW9ucz86IEJsdWViaXJkLkNvbmN1cnJlbmN5T3B0aW9uLFxuKTogUHJvbWlzZTxUPiB7XG4gIGlmIChpc0FycmF5KG9iaikpIHtcbiAgICByZXR1cm4gPGFueT5CbHVlYmlyZC5tYXAob2JqLCB2ID0+IGFzeW5jRGVlcE1hcCh2LCBtYXBwZXIsIG9wdGlvbnMpLCBvcHRpb25zKVxuICB9IGVsc2UgaWYgKGlzUGxhaW5PYmplY3Qob2JqKSkge1xuICAgIHJldHVybiA8VD5mcm9tUGFpcnMoXG4gICAgICBhd2FpdCBCbHVlYmlyZC5tYXAoXG4gICAgICAgIE9iamVjdC5lbnRyaWVzKG9iaiksXG4gICAgICAgIGFzeW5jIChba2V5LCB2YWx1ZV0pID0+IFtrZXksIGF3YWl0IGFzeW5jRGVlcE1hcCh2YWx1ZSwgbWFwcGVyLCBvcHRpb25zKV0sXG4gICAgICAgIG9wdGlvbnMsXG4gICAgICApLFxuICAgIClcbiAgfSBlbHNlIHtcbiAgICByZXR1cm4gbWFwcGVyKG9iailcbiAgfVxufVxuXG5leHBvcnQgZnVuY3Rpb24gb21pdFVuZGVmaW5lZChvOiBvYmplY3QpIHtcbiAgcmV0dXJuIHBpY2tCeShvLCAodjogYW55KSA9PiB2ICE9PSB1bmRlZmluZWQpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBzZXJpYWxpemVPYmplY3QobzogYW55KTogc3RyaW5nIHtcbiAgcmV0dXJuIEJ1ZmZlci5mcm9tKENyeW8uc3RyaW5naWZ5KG8pKS50b1N0cmluZyhcImJhc2U2NFwiKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZGVzZXJpYWxpemVPYmplY3Qoczogc3RyaW5nKSB7XG4gIHJldHVybiBDcnlvLnBhcnNlKEJ1ZmZlci5mcm9tKHMsIFwiYmFzZTY0XCIpKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gc2VyaWFsaXplVmFsdWVzKG86IHsgW2tleTogc3RyaW5nXTogYW55IH0pOiB7IFtrZXk6IHN0cmluZ106IHN0cmluZyB9IHtcbiAgcmV0dXJuIG1hcFZhbHVlcyhvLCBzZXJpYWxpemVPYmplY3QpXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBkZXNlcmlhbGl6ZVZhbHVlcyhvOiBvYmplY3QpIHtcbiAgcmV0dXJuIG1hcFZhbHVlcyhvLCBkZXNlcmlhbGl6ZU9iamVjdClcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldEVudW1LZXlzKEVudW0pIHtcbiAgcmV0dXJuIE9iamVjdC52YWx1ZXMoRW51bSkuZmlsdGVyKGsgPT4gdHlwZW9mIGsgPT09IFwic3RyaW5nXCIpIGFzIHN0cmluZ1tdXG59XG5cbmV4cG9ydCBmdW5jdGlvbiBoaWdobGlnaHRZYW1sKHM6IHN0cmluZykge1xuICByZXR1cm4gaGlnaGxpZ2h0KHMsIHtcbiAgICBsYW5ndWFnZTogXCJ5YW1sXCIsXG4gICAgdGhlbWU6IHtcbiAgICAgIGtleXdvcmQ6IGNoYWxrLndoaXRlLml0YWxpYyxcbiAgICAgIGxpdGVyYWw6IGNoYWxrLndoaXRlLml0YWxpYyxcbiAgICAgIHN0cmluZzogY2hhbGsud2hpdGUsXG4gICAgfSxcbiAgfSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIGxvYWRZYW1sRmlsZShwYXRoOiBzdHJpbmcpOiBQcm9taXNlPGFueT4ge1xuICBjb25zdCBmaWxlRGF0YSA9IGF3YWl0IHJlYWRGaWxlKHBhdGgpXG4gIHJldHVybiB5YW1sLnNhZmVMb2FkKGZpbGVEYXRhLnRvU3RyaW5nKCkpXG59XG5cbmV4cG9ydCBpbnRlcmZhY2UgT2JqZWN0V2l0aE5hbWUge1xuICBuYW1lOiBzdHJpbmdcbn1cblxuZXhwb3J0IGZ1bmN0aW9uIGdldE5hbWVzPFQgZXh0ZW5kcyBPYmplY3RXaXRoTmFtZT4oYXJyYXk6IFRbXSkge1xuICByZXR1cm4gYXJyYXkubWFwKHYgPT4gdi5uYW1lKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZmluZEJ5TmFtZTxUPihhcnJheTogVFtdLCBuYW1lOiBzdHJpbmcpOiBUIHwgdW5kZWZpbmVkIHtcbiAgcmV0dXJuIGZpbmQoYXJyYXksIFtcIm5hbWVcIiwgbmFtZV0pXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBXaW5kb3dzLXN0eWxlIHBhdGggdG8gYSBjeWd3aW4gc3R5bGUgcGF0aCAoZS5nLiBDOlxcc29tZVxcZm9sZGVyIC0+IC9jeWdkcml2ZS9jL3NvbWUvZm9sZGVyKS5cbiAqL1xuZXhwb3J0IGZ1bmN0aW9uIHRvQ3lnd2luUGF0aChwYXRoOiBzdHJpbmcpIHtcbiAgY29uc3QgcGFyc2VkID0gd2luMzIucGFyc2UocGF0aClcbiAgY29uc3QgZHJpdmUgPSBwYXJzZWQucm9vdC5zcGxpdChcIjpcIilbMF0udG9Mb3dlckNhc2UoKVxuICBjb25zdCBkaXJzID0gcGFyc2VkLmRpci5zcGxpdCh3aW4zMi5zZXApLnNsaWNlKDEpXG4gIGNvbnN0IGN5Z3BhdGggPSBwb3NpeC5qb2luKFwiL2N5Z2RyaXZlXCIsIGRyaXZlLCAuLi5kaXJzLCBwYXJzZWQuYmFzZSlcblxuICAvLyBtYWtlIHN1cmUgdHJhaWxpbmcgc2xhc2ggaXMgcmV0YWluZWRcbiAgcmV0dXJuIHBhdGguZW5kc1dpdGgod2luMzIuc2VwKSA/IGN5Z3BhdGggKyBwb3NpeC5zZXAgOiBjeWdwYXRoXG59XG5cbi8qKlxuICogQ29udmVydHMgYSBzdHJpbmcgaWRlbnRpZmllciB0byB0aGUgYXBwcm9wcmlhdGUgY2FzaW5nIGFuZCBzdHlsZSBmb3IgdXNlIGluIGVudmlyb25tZW50IHZhcmlhYmxlIG5hbWVzLlxuICogKGUuZy4gXCJteS1zZXJ2aWNlXCIgLT4gXCJNWV9TRVJWSUNFXCIpXG4gKi9cbmV4cG9ydCBmdW5jdGlvbiBnZXRFbnZWYXJOYW1lKGlkZW50aWZpZXI6IHN0cmluZykge1xuICByZXR1cm4gaWRlbnRpZmllci5yZXBsYWNlKFwiLVwiLCBcIl9cIikudG9VcHBlckNhc2UoKVxufVxuXG4vKipcbiAqIFBpY2tzIHRoZSBzcGVjaWZpZWQga2V5cyBmcm9tIHRoZSBnaXZlbiBvYmplY3QsIGFuZCB0aHJvd3MgYW4gZXJyb3IgaWYgb25lIG9yIG1vcmUga2V5cyBhcmUgbm90IGZvdW5kLlxuICovXG5leHBvcnQgZnVuY3Rpb24gcGlja0tleXM8VCBleHRlbmRzIG9iamVjdCwgVSBleHRlbmRzIGtleW9mIFQ+KG9iajogVCwga2V5czogVVtdLCBkZXNjcmlwdGlvbiA9IFwia2V5XCIpOiBQaWNrPFQsIFU+IHtcbiAgY29uc3QgcGlja2VkID0gcGljayhvYmosIC4uLmtleXMpXG5cbiAgY29uc3QgbWlzc2luZyA9IGRpZmZlcmVuY2UoPHN0cmluZ1tdPmtleXMsIE9iamVjdC5rZXlzKHBpY2tlZCkpXG5cbiAgaWYgKG1pc3NpbmcubGVuZ3RoKSB7XG4gICAgdGhyb3cgbmV3IFBhcmFtZXRlckVycm9yKGBDb3VsZCBub3QgZmluZCAke2Rlc2NyaXB0aW9ufShzKTogJHttaXNzaW5nLm1hcCgoaywgXykgPT4gaykuam9pbihcIiwgXCIpfWAsIHtcbiAgICAgIG1pc3NpbmcsXG4gICAgICBhdmFpbGFibGU6IE9iamVjdC5rZXlzKG9iaiksXG4gICAgfSlcbiAgfVxuXG4gIHJldHVybiBwaWNrZWRcbn1cbiJdfQ== diff --git a/garden-service/build/vcs/base.d.ts b/garden-service/build/vcs/base.d.ts new file mode 100644 index 00000000000..35746e5279e --- /dev/null +++ b/garden-service/build/vcs/base.d.ts @@ -0,0 +1,43 @@ +import * as Joi from "joi"; +import { ExternalSourceType } from "../util/ext-source-util"; +import { ModuleConfig } from "../config/module"; +import { LogNode } from "../logger/log-node"; +export declare const NEW_MODULE_VERSION = "0000000000"; +export interface TreeVersion { + latestCommit: string; + dirtyTimestamp: number | null; +} +export interface TreeVersions { + [moduleName: string]: TreeVersion; +} +export interface ModuleVersion { + versionString: string; + dirtyTimestamp: number | null; + dependencyVersions: TreeVersions; +} +export declare const treeVersionSchema: Joi.ObjectSchema; +export declare const moduleVersionSchema: Joi.ObjectSchema; +export interface RemoteSourceParams { + url: string; + name: string; + sourceType: ExternalSourceType; + logEntry: LogNode; +} +export declare abstract class VcsHandler { + protected projectRoot: string; + constructor(projectRoot: string); + abstract name: string; + abstract getTreeVersion(path: string): Promise; + abstract ensureRemoteSource(params: RemoteSourceParams): Promise; + abstract updateRemoteSource(params: RemoteSourceParams): any; + resolveTreeVersion(path: string): Promise; + resolveVersion(moduleConfig: ModuleConfig, dependencies: ModuleConfig[]): Promise; + getRemoteSourcesDirname(type: ExternalSourceType): string; + getRemoteSourcePath(name: any, url: any, sourceType: any): string; +} +export declare function readTreeVersionFile(path: string): Promise; +export declare function writeTreeVersionFile(path: string, version: TreeVersion): Promise; +export declare function readModuleVersionFile(path: string): Promise; +export declare function writeModuleVersionFile(path: string, version: ModuleVersion): Promise; +export declare function getVersionString(treeVersion: TreeVersion): string; +//# sourceMappingURL=base.d.ts.map \ No newline at end of file diff --git a/garden-service/build/vcs/base.js b/garden-service/build/vcs/base.js new file mode 100644 index 00000000000..d50088d8b6f --- /dev/null +++ b/garden-service/build/vcs/base.js @@ -0,0 +1,191 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const Bluebird = require("bluebird"); +const lodash_1 = require("lodash"); +const crypto_1 = require("crypto"); +const Joi = require("joi"); +const common_1 = require("../config/common"); +const path_1 = require("path"); +const constants_1 = require("../constants"); +const fs_extra_1 = require("fs-extra"); +const exceptions_1 = require("../exceptions"); +const ext_source_util_1 = require("../util/ext-source-util"); +exports.NEW_MODULE_VERSION = "0000000000"; +const versionStringSchema = Joi.string() + .required() + .description("String representation of the module version."); +const dirtyTimestampSchema = Joi.number() + .allow(null) + .required() + .description("Set to the last modified time (as UNIX timestamp) if the module contains uncommitted changes, otherwise null."); +exports.treeVersionSchema = Joi.object() + .keys({ + latestCommit: Joi.string() + .required() + .description("The latest commit hash of the module source."), + dirtyTimestamp: dirtyTimestampSchema, +}); +exports.moduleVersionSchema = Joi.object() + .keys({ + versionString: versionStringSchema, + dirtyTimestamp: dirtyTimestampSchema, + dependencyVersions: Joi.object() + .pattern(/.+/, exports.treeVersionSchema) + .default(() => ({}), "{}") + .description("The version of each of the dependencies of the module."), +}); +class VcsHandler { + constructor(projectRoot) { + this.projectRoot = projectRoot; + } + resolveTreeVersion(path) { + return __awaiter(this, void 0, void 0, function* () { + // the version file is used internally to specify versions outside of source control + const versionFilePath = path_1.join(path, constants_1.GARDEN_VERSIONFILE_NAME); + const fileVersion = yield readTreeVersionFile(versionFilePath); + return fileVersion || this.getTreeVersion(path); + }); + } + resolveVersion(moduleConfig, dependencies) { + return __awaiter(this, void 0, void 0, function* () { + const treeVersion = yield this.resolveTreeVersion(moduleConfig.path); + common_1.validate(treeVersion, exports.treeVersionSchema, { + context: `${this.name} tree version for module at ${moduleConfig.path}`, + }); + if (dependencies.length === 0) { + return { + versionString: getVersionString(treeVersion), + dirtyTimestamp: treeVersion.dirtyTimestamp, + dependencyVersions: {}, + }; + } + const namedDependencyVersions = yield Bluebird.map(dependencies, (m) => __awaiter(this, void 0, void 0, function* () { return (Object.assign({ name: m.name }, yield this.resolveTreeVersion(m.path))); })); + const dependencyVersions = lodash_1.mapValues(lodash_1.keyBy(namedDependencyVersions, "name"), v => lodash_1.omit(v, "name")); + // keep the module at the top of the chain, dependencies sorted by name + const sortedDependencies = lodash_1.sortBy(namedDependencyVersions, "name"); + const allVersions = [Object.assign({ name: moduleConfig.name }, treeVersion)].concat(sortedDependencies); + const dirtyVersions = allVersions.filter(v => !!v.dirtyTimestamp); + if (dirtyVersions.length > 0) { + // if any modules are dirty, we resolve with the one(s) with the most recent timestamp + const latestDirty = []; + for (const v of lodash_1.orderBy(dirtyVersions, "dirtyTimestamp", "desc")) { + if (latestDirty.length === 0 || v.dirtyTimestamp === latestDirty[0].dirtyTimestamp) { + latestDirty.push(v); + } + else { + break; + } + } + const dirtyTimestamp = latestDirty[0].dirtyTimestamp; + if (latestDirty.length > 1) { + // if the last modified timestamp is common across multiple modules, hash their versions + const versionString = `${hashVersions(latestDirty)}-${dirtyTimestamp}`; + return { + versionString, + dirtyTimestamp, + dependencyVersions, + }; + } + else { + // if there's just one module that was most recently modified, return that version + return { + versionString: getVersionString(latestDirty[0]), + dirtyTimestamp, + dependencyVersions, + }; + } + } + else { + // otherwise derive the version from all the modules + const versionString = hashVersions(allVersions); + return { + versionString, + dirtyTimestamp: null, + dependencyVersions, + }; + } + }); + } + getRemoteSourcesDirname(type) { + return ext_source_util_1.getRemoteSourcesDirname(type); + } + getRemoteSourcePath(name, url, sourceType) { + return ext_source_util_1.getRemoteSourcePath({ name, url, sourceType }); + } +} +exports.VcsHandler = VcsHandler; +function hashVersions(versions) { + const versionHash = crypto_1.createHash("sha256"); + versionHash.update(versions.map(v => `${v.name}_${v.latestCommit}`).join(".")); + // this format is kinda arbitrary, but prefixing the "v" is useful to visually spot hashed versions + return "v" + versionHash.digest("hex").slice(0, 10); +} +function readVersionFile(path, schema) { + return __awaiter(this, void 0, void 0, function* () { + if (!(yield fs_extra_1.pathExists(path))) { + return null; + } + // this is used internally to specify version outside of source control + const versionFileContents = (yield fs_extra_1.readFile(path)).toString().trim(); + if (!versionFileContents) { + return null; + } + try { + return common_1.validate(JSON.parse(versionFileContents), schema); + } + catch (error) { + throw new exceptions_1.ConfigurationError(`Unable to parse ${path} as valid version file`, { + path, + versionFileContents, + error, + }); + } + }); +} +function readTreeVersionFile(path) { + return __awaiter(this, void 0, void 0, function* () { + return readVersionFile(path, exports.treeVersionSchema); + }); +} +exports.readTreeVersionFile = readTreeVersionFile; +function writeTreeVersionFile(path, version) { + return __awaiter(this, void 0, void 0, function* () { + yield fs_extra_1.writeFile(path, JSON.stringify(version)); + }); +} +exports.writeTreeVersionFile = writeTreeVersionFile; +function readModuleVersionFile(path) { + return __awaiter(this, void 0, void 0, function* () { + return readVersionFile(path, exports.moduleVersionSchema); + }); +} +exports.readModuleVersionFile = readModuleVersionFile; +function writeModuleVersionFile(path, version) { + return __awaiter(this, void 0, void 0, function* () { + yield fs_extra_1.writeFile(path, JSON.stringify(version)); + }); +} +exports.writeModuleVersionFile = writeModuleVersionFile; +function getVersionString(treeVersion) { + return treeVersion.dirtyTimestamp + ? `${treeVersion.latestCommit}-${treeVersion.dirtyTimestamp}` + : treeVersion.latestCommit; +} +exports.getVersionString = getVersionString; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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RUFBRSxPQUFzQjs7UUFDL0UsTUFBTSxvQkFBUyxDQUFDLElBQUksRUFBRSxJQUFJLENBQUMsU0FBUyxDQUFDLE9BQU8sQ0FBQyxDQUFDLENBQUE7SUFDaEQsQ0FBQztDQUFBO0FBRkQsd0RBRUM7QUFFRCxTQUFnQixnQkFBZ0IsQ0FBQyxXQUF3QjtJQUN2RCxPQUFPLFdBQVcsQ0FBQyxjQUFjO1FBQy9CLENBQUMsQ0FBQyxHQUFHLFdBQVcsQ0FBQyxZQUFZLElBQUksV0FBVyxDQUFDLGNBQWMsRUFBRTtRQUM3RCxDQUFDLENBQUMsV0FBVyxDQUFDLFlBQVksQ0FBQTtBQUM5QixDQUFDO0FBSkQsNENBSUMiLCJmaWxlIjoidmNzL2Jhc2UuanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0ICogYXMgQmx1ZWJpcmQgZnJvbSBcImJsdWViaXJkXCJcbmltcG9ydCB7IG1hcFZhbHVlcywga2V5QnksIHNvcnRCeSwgb3JkZXJCeSwgb21pdCB9IGZyb20gXCJsb2Rhc2hcIlxuaW1wb3J0IHsgY3JlYXRlSGFzaCB9IGZyb20gXCJjcnlwdG9cIlxuaW1wb3J0ICogYXMgSm9pIGZyb20gXCJqb2lcIlxuaW1wb3J0IHsgdmFsaWRhdGUgfSBmcm9tIFwiLi4vY29uZmlnL2NvbW1vblwiXG5pbXBvcnQgeyBqb2luIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHsgR0FSREVOX1ZFUlNJT05GSUxFX05BTUUgfSBmcm9tIFwiLi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IHBhdGhFeGlzdHMsIHJlYWRGaWxlLCB3cml0ZUZpbGUgfSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IHsgQ29uZmlndXJhdGlvbkVycm9yIH0gZnJvbSBcIi4uL2V4Y2VwdGlvbnNcIlxuaW1wb3J0IHtcbiAgRXh0ZXJuYWxTb3VyY2VUeXBlLFxuICBnZXRSZW1vdGVTb3VyY2VzRGlybmFtZSxcbiAgZ2V0UmVtb3RlU291cmNlUGF0aCxcbn0gZnJvbSBcIi4uL3V0aWwvZXh0LXNvdXJjZS11dGlsXCJcbmltcG9ydCB7IE1vZHVsZUNvbmZpZyB9IGZyb20gXCIuLi9jb25maWcvbW9kdWxlXCJcbmltcG9ydCB7IExvZ05vZGUgfSBmcm9tIFwiLi4vbG9nZ2VyL2xvZy1ub2RlXCJcblxuZXhwb3J0IGNvbnN0IE5FV19NT0RVTEVfVkVSU0lPTiA9IFwiMDAwMDAwMDAwMFwiXG5cbmV4cG9ydCBpbnRlcmZhY2UgVHJlZVZlcnNpb24ge1xuICBsYXRlc3RDb21taXQ6IHN0cmluZ1xuICBkaXJ0eVRpbWVzdGFtcDogbnVtYmVyIHwgbnVsbFxufVxuXG5leHBvcnQgaW50ZXJmYWNlIFRyZWVWZXJzaW9ucyB7IFttb2R1bGVOYW1lOiBzdHJpbmddOiBUcmVlVmVyc2lvbiB9XG5cbmV4cG9ydCBpbnRlcmZhY2UgTW9kdWxlVmVyc2lvbiB7XG4gIHZlcnNpb25TdHJpbmc6IHN0cmluZ1xuICBkaXJ0eVRpbWVzdGFtcDogbnVtYmVyIHwgbnVsbFxuICBkZXBlbmRlbmN5VmVyc2lvbnM6IFRyZWVWZXJzaW9uc1xufVxuXG5pbnRlcmZhY2UgTmFtZWRUcmVlVmVyc2lvbiBleHRlbmRzIFRyZWVWZXJzaW9uIHtcbiAgbmFtZTogc3RyaW5nXG59XG5cbmNvbnN0IHZlcnNpb25TdHJpbmdTY2hlbWEgPSBKb2kuc3RyaW5nKClcbiAgLnJlcXVpcmVkKClcbiAgLmRlc2NyaXB0aW9uKFwiU3RyaW5nIHJlcHJlc2VudGF0aW9uIG9mIHRoZSBtb2R1bGUgdmVyc2lvbi5cIilcblxuY29uc3QgZGlydHlUaW1lc3RhbXBTY2hlbWEgPSBKb2kubnVtYmVyKClcbiAgLmFsbG93KG51bGwpXG4gIC5yZXF1aXJlZCgpXG4gIC5kZXNjcmlwdGlvbihcbiAgICBcIlNldCB0byB0aGUgbGFzdCBtb2RpZmllZCB0aW1lIChhcyBVTklYIHRpbWVzdGFtcCkgaWYgdGhlIG1vZHVsZSBjb250YWlucyB1bmNvbW1pdHRlZCBjaGFuZ2VzLCBvdGhlcndpc2UgbnVsbC5cIixcbiAgKVxuXG5leHBvcnQgY29uc3QgdHJlZVZlcnNpb25TY2hlbWEgPSBKb2kub2JqZWN0KClcbiAgLmtleXMoe1xuICAgIGxhdGVzdENvbW1pdDogSm9pLnN0cmluZygpXG4gICAgICAucmVxdWlyZWQoKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIGxhdGVzdCBjb21taXQgaGFzaCBvZiB0aGUgbW9kdWxlIHNvdXJjZS5cIiksXG4gICAgZGlydHlUaW1lc3RhbXA6IGRpcnR5VGltZXN0YW1wU2NoZW1hLFxuICB9KVxuXG5leHBvcnQgY29uc3QgbW9kdWxlVmVyc2lvblNjaGVtYSA9IEpvaS5vYmplY3QoKVxuICAua2V5cyh7XG4gICAgdmVyc2lvblN0cmluZzogdmVyc2lvblN0cmluZ1NjaGVtYSxcbiAgICBkaXJ0eVRpbWVzdGFtcDogZGlydHlUaW1lc3RhbXBTY2hlbWEsXG4gICAgZGVwZW5kZW5jeVZlcnNpb25zOiBKb2kub2JqZWN0KClcbiAgICAgIC5wYXR0ZXJuKC8uKy8sIHRyZWVWZXJzaW9uU2NoZW1hKVxuICAgICAgLmRlZmF1bHQoKCkgPT4gKHt9KSwgXCJ7fVwiKVxuICAgICAgLmRlc2NyaXB0aW9uKFwiVGhlIHZlcnNpb24gb2YgZWFjaCBvZiB0aGUgZGVwZW5kZW5jaWVzIG9mIHRoZSBtb2R1bGUuXCIpLFxuICB9KVxuXG5leHBvcnQgaW50ZXJmYWNlIFJlbW90ZVNvdXJjZVBhcmFtcyB7XG4gIHVybDogc3RyaW5nLFxuICBuYW1lOiBzdHJpbmcsXG4gIHNvdXJjZVR5cGU6IEV4dGVybmFsU291cmNlVHlwZSxcbiAgbG9nRW50cnk6IExvZ05vZGUsXG59XG5cbmV4cG9ydCBhYnN0cmFjdCBjbGFzcyBWY3NIYW5kbGVyIHtcbiAgY29uc3RydWN0b3IocHJvdGVjdGVkIHByb2plY3RSb290OiBzdHJpbmcpIHsgfVxuXG4gIGFic3RyYWN0IG5hbWU6IHN0cmluZ1xuICBhYnN0cmFjdCBhc3luYyBnZXRUcmVlVmVyc2lvbihwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFRyZWVWZXJzaW9uPlxuICBhYnN0cmFjdCBhc3luYyBlbnN1cmVSZW1vdGVTb3VyY2UocGFyYW1zOiBSZW1vdGVTb3VyY2VQYXJhbXMpOiBQcm9taXNlPHN0cmluZz5cbiAgYWJzdHJhY3QgYXN5bmMgdXBkYXRlUmVtb3RlU291cmNlKHBhcmFtczogUmVtb3RlU291cmNlUGFyYW1zKVxuXG4gIGFzeW5jIHJlc29sdmVUcmVlVmVyc2lvbihwYXRoOiBzdHJpbmcpOiBQcm9taXNlPFRyZWVWZXJzaW9uPiB7XG4gICAgLy8gdGhlIHZlcnNpb24gZmlsZSBpcyB1c2VkIGludGVybmFsbHkgdG8gc3BlY2lmeSB2ZXJzaW9ucyBvdXRzaWRlIG9mIHNvdXJjZSBjb250cm9sXG4gICAgY29uc3QgdmVyc2lvbkZpbGVQYXRoID0gam9pbihwYXRoLCBHQVJERU5fVkVSU0lPTkZJTEVfTkFNRSlcbiAgICBjb25zdCBmaWxlVmVyc2lvbiA9IGF3YWl0IHJlYWRUcmVlVmVyc2lvbkZpbGUodmVyc2lvbkZpbGVQYXRoKVxuICAgIHJldHVybiBmaWxlVmVyc2lvbiB8fCB0aGlzLmdldFRyZWVWZXJzaW9uKHBhdGgpXG4gIH1cblxuICBhc3luYyByZXNvbHZlVmVyc2lvbihtb2R1bGVDb25maWc6IE1vZHVsZUNvbmZpZywgZGVwZW5kZW5jaWVzOiBNb2R1bGVDb25maWdbXSk6IFByb21pc2U8TW9kdWxlVmVyc2lvbj4ge1xuICAgIGNvbnN0IHRyZWVWZXJzaW9uID0gYXdhaXQgdGhpcy5yZXNvbHZlVHJlZVZlcnNpb24obW9kdWxlQ29uZmlnLnBhdGgpXG5cbiAgICB2YWxpZGF0ZSh0cmVlVmVyc2lvbiwgdHJlZVZlcnNpb25TY2hlbWEsIHtcbiAgICAgIGNvbnRleHQ6IGAke3RoaXMubmFtZX0gdHJlZSB2ZXJzaW9uIGZvciBtb2R1bGUgYXQgJHttb2R1bGVDb25maWcucGF0aH1gLFxuICAgIH0pXG5cbiAgICBpZiAoZGVwZW5kZW5jaWVzLmxlbmd0aCA9PT0gMCkge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgdmVyc2lvblN0cmluZzogZ2V0VmVyc2lvblN0cmluZyh0cmVlVmVyc2lvbiksXG4gICAgICAgIGRpcnR5VGltZXN0YW1wOiB0cmVlVmVyc2lvbi5kaXJ0eVRpbWVzdGFtcCxcbiAgICAgICAgZGVwZW5kZW5jeVZlcnNpb25zOiB7fSxcbiAgICAgIH1cbiAgICB9XG5cbiAgICBjb25zdCBuYW1lZERlcGVuZGVuY3lWZXJzaW9ucyA9IGF3YWl0IEJsdWViaXJkLm1hcChcbiAgICAgIGRlcGVuZGVuY2llcyxcbiAgICAgIGFzeW5jIChtOiBNb2R1bGVDb25maWcpID0+ICh7IG5hbWU6IG0ubmFtZSwgLi4uYXdhaXQgdGhpcy5yZXNvbHZlVHJlZVZlcnNpb24obS5wYXRoKSB9KSxcbiAgICApXG4gICAgY29uc3QgZGVwZW5kZW5jeVZlcnNpb25zID0gbWFwVmFsdWVzKGtleUJ5KG5hbWVkRGVwZW5kZW5jeVZlcnNpb25zLCBcIm5hbWVcIiksIHYgPT4gb21pdCh2LCBcIm5hbWVcIikpXG5cbiAgICAvLyBrZWVwIHRoZSBtb2R1bGUgYXQgdGhlIHRvcCBvZiB0aGUgY2hhaW4sIGRlcGVuZGVuY2llcyBzb3J0ZWQgYnkgbmFtZVxuICAgIGNvbnN0IHNvcnRlZERlcGVuZGVuY2llcyA9IHNvcnRCeShuYW1lZERlcGVuZGVuY3lWZXJzaW9ucywgXCJuYW1lXCIpXG4gICAgY29uc3QgYWxsVmVyc2lvbnM6IE5hbWVkVHJlZVZlcnNpb25bXSA9IFt7IG5hbWU6IG1vZHVsZUNvbmZpZy5uYW1lLCAuLi50cmVlVmVyc2lvbiB9XS5jb25jYXQoc29ydGVkRGVwZW5kZW5jaWVzKVxuXG4gICAgY29uc3QgZGlydHlWZXJzaW9ucyA9IGFsbFZlcnNpb25zLmZpbHRlcih2ID0+ICEhdi5kaXJ0eVRpbWVzdGFtcClcblxuICAgIGlmIChkaXJ0eVZlcnNpb25zLmxlbmd0aCA+IDApIHtcbiAgICAgIC8vIGlmIGFueSBtb2R1bGVzIGFyZSBkaXJ0eSwgd2UgcmVzb2x2ZSB3aXRoIHRoZSBvbmUocykgd2l0aCB0aGUgbW9zdCByZWNlbnQgdGltZXN0YW1wXG4gICAgICBjb25zdCBsYXRlc3REaXJ0eTogTmFtZWRUcmVlVmVyc2lvbltdID0gW11cblxuICAgICAgZm9yIChjb25zdCB2IG9mIG9yZGVyQnkoZGlydHlWZXJzaW9ucywgXCJkaXJ0eVRpbWVzdGFtcFwiLCBcImRlc2NcIikpIHtcbiAgICAgICAgaWYgKGxhdGVzdERpcnR5Lmxlbmd0aCA9PT0gMCB8fCB2LmRpcnR5VGltZXN0YW1wID09PSBsYXRlc3REaXJ0eVswXS5kaXJ0eVRpbWVzdGFtcCkge1xuICAgICAgICAgIGxhdGVzdERpcnR5LnB1c2godilcbiAgICAgICAgfSBlbHNlIHtcbiAgICAgICAgICBicmVha1xuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGRpcnR5VGltZXN0YW1wID0gbGF0ZXN0RGlydHlbMF0uZGlydHlUaW1lc3RhbXBcblxuICAgICAgaWYgKGxhdGVzdERpcnR5Lmxlbmd0aCA+IDEpIHtcbiAgICAgICAgLy8gaWYgdGhlIGxhc3QgbW9kaWZpZWQgdGltZXN0YW1wIGlzIGNvbW1vbiBhY3Jvc3MgbXVsdGlwbGUgbW9kdWxlcywgaGFzaCB0aGVpciB2ZXJzaW9uc1xuICAgICAgICBjb25zdCB2ZXJzaW9uU3RyaW5nID0gYCR7aGFzaFZlcnNpb25zKGxhdGVzdERpcnR5KX0tJHtkaXJ0eVRpbWVzdGFtcH1gXG5cbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICB2ZXJzaW9uU3RyaW5nLFxuICAgICAgICAgIGRpcnR5VGltZXN0YW1wLFxuICAgICAgICAgIGRlcGVuZGVuY3lWZXJzaW9ucyxcbiAgICAgICAgfVxuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gaWYgdGhlcmUncyBqdXN0IG9uZSBtb2R1bGUgdGhhdCB3YXMgbW9zdCByZWNlbnRseSBtb2RpZmllZCwgcmV0dXJuIHRoYXQgdmVyc2lvblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIHZlcnNpb25TdHJpbmc6IGdldFZlcnNpb25TdHJpbmcobGF0ZXN0RGlydHlbMF0pLFxuICAgICAgICAgIGRpcnR5VGltZXN0YW1wLFxuICAgICAgICAgIGRlcGVuZGVuY3lWZXJzaW9ucyxcbiAgICAgICAgfVxuICAgICAgfVxuICAgIH0gZWxzZSB7XG4gICAgICAvLyBvdGhlcndpc2UgZGVyaXZlIHRoZSB2ZXJzaW9uIGZyb20gYWxsIHRoZSBtb2R1bGVzXG4gICAgICBjb25zdCB2ZXJzaW9uU3RyaW5nID0gaGFzaFZlcnNpb25zKGFsbFZlcnNpb25zKVxuXG4gICAgICByZXR1cm4ge1xuICAgICAgICB2ZXJzaW9uU3RyaW5nLFxuICAgICAgICBkaXJ0eVRpbWVzdGFtcDogbnVsbCxcbiAgICAgICAgZGVwZW5kZW5jeVZlcnNpb25zLFxuICAgICAgfVxuICAgIH1cbiAgfVxuXG4gIGdldFJlbW90ZVNvdXJjZXNEaXJuYW1lKHR5cGU6IEV4dGVybmFsU291cmNlVHlwZSkge1xuICAgIHJldHVybiBnZXRSZW1vdGVTb3VyY2VzRGlybmFtZSh0eXBlKVxuICB9XG5cbiAgZ2V0UmVtb3RlU291cmNlUGF0aChuYW1lLCB1cmwsIHNvdXJjZVR5cGUpIHtcbiAgICByZXR1cm4gZ2V0UmVtb3RlU291cmNlUGF0aCh7IG5hbWUsIHVybCwgc291cmNlVHlwZSB9KVxuICB9XG59XG5cbmZ1bmN0aW9uIGhhc2hWZXJzaW9ucyh2ZXJzaW9uczogTmFtZWRUcmVlVmVyc2lvbltdKSB7XG4gIGNvbnN0IHZlcnNpb25IYXNoID0gY3JlYXRlSGFzaChcInNoYTI1NlwiKVxuICB2ZXJzaW9uSGFzaC51cGRhdGUodmVyc2lvbnMubWFwKHYgPT4gYCR7di5uYW1lfV8ke3YubGF0ZXN0Q29tbWl0fWApLmpvaW4oXCIuXCIpKVxuICAvLyB0aGlzIGZvcm1hdCBpcyBraW5kYSBhcmJpdHJhcnksIGJ1dCBwcmVmaXhpbmcgdGhlIFwidlwiIGlzIHVzZWZ1bCB0byB2aXN1YWxseSBzcG90IGhhc2hlZCB2ZXJzaW9uc1xuICByZXR1cm4gXCJ2XCIgKyB2ZXJzaW9uSGFzaC5kaWdlc3QoXCJoZXhcIikuc2xpY2UoMCwgMTApXG59XG5cbmFzeW5jIGZ1bmN0aW9uIHJlYWRWZXJzaW9uRmlsZShwYXRoOiBzdHJpbmcsIHNjaGVtYSk6IFByb21pc2U8YW55PiB7XG4gIGlmICghKGF3YWl0IHBhdGhFeGlzdHMocGF0aCkpKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIC8vIHRoaXMgaXMgdXNlZCBpbnRlcm5hbGx5IHRvIHNwZWNpZnkgdmVyc2lvbiBvdXRzaWRlIG9mIHNvdXJjZSBjb250cm9sXG4gIGNvbnN0IHZlcnNpb25GaWxlQ29udGVudHMgPSAoYXdhaXQgcmVhZEZpbGUocGF0aCkpLnRvU3RyaW5nKCkudHJpbSgpXG5cbiAgaWYgKCF2ZXJzaW9uRmlsZUNvbnRlbnRzKSB7XG4gICAgcmV0dXJuIG51bGxcbiAgfVxuXG4gIHRyeSB7XG4gICAgcmV0dXJuIHZhbGlkYXRlKEpTT04ucGFyc2UodmVyc2lvbkZpbGVDb250ZW50cyksIHNjaGVtYSlcbiAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICB0aHJvdyBuZXcgQ29uZmlndXJhdGlvbkVycm9yKFxuICAgICAgYFVuYWJsZSB0byBwYXJzZSAke3BhdGh9IGFzIHZhbGlkIHZlcnNpb24gZmlsZWAsXG4gICAgICB7XG4gICAgICAgIHBhdGgsXG4gICAgICAgIHZlcnNpb25GaWxlQ29udGVudHMsXG4gICAgICAgIGVycm9yLFxuICAgICAgfSxcbiAgICApXG4gIH1cbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHJlYWRUcmVlVmVyc2lvbkZpbGUocGF0aDogc3RyaW5nKTogUHJvbWlzZTxUcmVlVmVyc2lvbiB8IG51bGw+IHtcbiAgcmV0dXJuIHJlYWRWZXJzaW9uRmlsZShwYXRoLCB0cmVlVmVyc2lvblNjaGVtYSlcbn1cblxuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdyaXRlVHJlZVZlcnNpb25GaWxlKHBhdGg6IHN0cmluZywgdmVyc2lvbjogVHJlZVZlcnNpb24pIHtcbiAgYXdhaXQgd3JpdGVGaWxlKHBhdGgsIEpTT04uc3RyaW5naWZ5KHZlcnNpb24pKVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gcmVhZE1vZHVsZVZlcnNpb25GaWxlKHBhdGg6IHN0cmluZyk6IFByb21pc2U8TW9kdWxlVmVyc2lvbiB8IG51bGw+IHtcbiAgcmV0dXJuIHJlYWRWZXJzaW9uRmlsZShwYXRoLCBtb2R1bGVWZXJzaW9uU2NoZW1hKVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gd3JpdGVNb2R1bGVWZXJzaW9uRmlsZShwYXRoOiBzdHJpbmcsIHZlcnNpb246IE1vZHVsZVZlcnNpb24pIHtcbiAgYXdhaXQgd3JpdGVGaWxlKHBhdGgsIEpTT04uc3RyaW5naWZ5KHZlcnNpb24pKVxufVxuXG5leHBvcnQgZnVuY3Rpb24gZ2V0VmVyc2lvblN0cmluZyh0cmVlVmVyc2lvbjogVHJlZVZlcnNpb24pIHtcbiAgcmV0dXJuIHRyZWVWZXJzaW9uLmRpcnR5VGltZXN0YW1wXG4gICAgPyBgJHt0cmVlVmVyc2lvbi5sYXRlc3RDb21taXR9LSR7dHJlZVZlcnNpb24uZGlydHlUaW1lc3RhbXB9YFxuICAgIDogdHJlZVZlcnNpb24ubGF0ZXN0Q29tbWl0XG59XG4iXX0= diff --git a/garden-service/build/vcs/git.d.ts b/garden-service/build/vcs/git.d.ts new file mode 100644 index 00000000000..fa37c0abd56 --- /dev/null +++ b/garden-service/build/vcs/git.d.ts @@ -0,0 +1,14 @@ +import { VcsHandler, RemoteSourceParams } from "./base"; +export declare const helpers: { + gitCli: (cwd: string) => (cmd: string, args: string[]) => Promise; +}; +export declare class GitHandler extends VcsHandler { + name: string; + getTreeVersion(path: string): Promise<{ + latestCommit: any; + dirtyTimestamp: number | null; + }>; + ensureRemoteSource({ url, name, logEntry, sourceType }: RemoteSourceParams): Promise; + updateRemoteSource({ url, name, sourceType, logEntry }: RemoteSourceParams): Promise; +} +//# sourceMappingURL=git.d.ts.map \ No newline at end of file diff --git a/garden-service/build/vcs/git.js b/garden-service/build/vcs/git.js new file mode 100644 index 00000000000..88364acee4f --- /dev/null +++ b/garden-service/build/vcs/git.js @@ -0,0 +1,136 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const execa = require("execa"); +const path_1 = require("path"); +const fs_extra_1 = require("fs-extra"); +const Bluebird = require("bluebird"); +const base_1 = require("./base"); +exports.helpers = { + gitCli: (cwd) => { + return (cmd, args) => __awaiter(this, void 0, void 0, function* () { + return execa.stdout("git", [cmd, ...args], { cwd }); + }); + }, +}; +function getGitUrlParts(url) { + const parts = url.split("#"); + return { repositoryUrl: parts[0], hash: parts[1] }; +} +function parseRefList(res) { + const refList = res.split("\n").map(str => { + const parts = str.split("\n"); + return { commitId: parts[0], ref: parts[1] }; + }); + return refList[0].commitId; +} +// TODO Consider moving git commands to separate (and testable) functions +class GitHandler extends base_1.VcsHandler { + constructor() { + super(...arguments); + this.name = "git"; + } + getTreeVersion(path) { + return __awaiter(this, void 0, void 0, function* () { + const git = exports.helpers.gitCli(path); + let commitHash; + try { + commitHash = (yield git("rev-list", [ + "--max-count=1", + "--abbrev-commit", + "--abbrev=10", + "HEAD", + ])) || base_1.NEW_MODULE_VERSION; + } + catch (err) { + if (err.code === 128) { + // not in a repo root, return default version + commitHash = base_1.NEW_MODULE_VERSION; + } + } + let latestDirty = 0; + const res = (yield git("diff-index", ["--name-only", "HEAD", path])) + "\n" + + (yield git("ls-files", ["--other", "--exclude-standard", path])); + const dirtyFiles = res.split("\n").filter((f) => f.length > 0); + // for dirty trees, we append the last modified time of last modified or added file + if (dirtyFiles.length) { + const repoRoot = yield git("rev-parse", ["--show-toplevel"]); + const stats = yield Bluebird.map(dirtyFiles, file => path_1.join(repoRoot, file)) + .filter((file) => fs_extra_1.pathExists(file)) + .map((file) => fs_extra_1.stat(file)); + let mtimes = stats.map((s) => Math.round(s.mtime.getTime() / 1000)); + let latest = mtimes.sort().slice(-1)[0]; + if (latest > latestDirty) { + latestDirty = latest; + } + } + return { + latestCommit: commitHash, + dirtyTimestamp: latestDirty || null, + }; + }); + } + // TODO Better auth handling + ensureRemoteSource({ url, name, logEntry, sourceType }) { + return __awaiter(this, void 0, void 0, function* () { + const remoteSourcesPath = path_1.join(this.projectRoot, this.getRemoteSourcesDirname(sourceType)); + yield fs_extra_1.ensureDir(remoteSourcesPath); + const git = exports.helpers.gitCli(remoteSourcesPath); + const absPath = path_1.join(this.projectRoot, this.getRemoteSourcePath(name, url, sourceType)); + const isCloned = yield fs_extra_1.pathExists(absPath); + if (!isCloned) { + const entry = logEntry.info({ section: name, msg: `Fetching from ${url}`, status: "active" }); + const { repositoryUrl, hash } = getGitUrlParts(url); + const cmdOpts = ["--depth=1"]; + if (hash) { + cmdOpts.push("--branch=hash"); + } + yield git("clone", [...cmdOpts, repositoryUrl, absPath]); + entry.setSuccess(); + } + return absPath; + }); + } + updateRemoteSource({ url, name, sourceType, logEntry }) { + return __awaiter(this, void 0, void 0, function* () { + const absPath = path_1.join(this.projectRoot, this.getRemoteSourcePath(name, url, sourceType)); + const git = exports.helpers.gitCli(absPath); + const { repositoryUrl, hash } = getGitUrlParts(url); + yield this.ensureRemoteSource({ url, name, sourceType, logEntry }); + const entry = logEntry.info({ section: name, msg: "Getting remote state", status: "active" }); + yield git("remote", ["update"]); + const listRemoteArgs = hash ? [repositoryUrl, hash] : [repositoryUrl]; + const showRefArgs = hash ? [hash] : []; + const remoteCommitId = parseRefList(yield git("ls-remote", listRemoteArgs)); + const localCommitId = parseRefList(yield git("show-ref", ["--hash", ...showRefArgs])); + if (localCommitId !== remoteCommitId) { + entry.setState(`Fetching from ${url}`); + const fetchArgs = hash ? ["origin", hash] : ["origin"]; + const resetArgs = hash ? [`origin/${hash}`] : ["origin"]; + yield git("fetch", ["--depth=1", ...fetchArgs]); + yield git("reset", ["--hard", ...resetArgs]); + entry.setSuccess("Source updated"); + } + else { + entry.setSuccess("Source already up to date"); + } + }); + } +} +exports.GitHandler = GitHandler; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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Q0FBQyxDQUFDLENBQUMsQ0FBQyxVQUFVLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsUUFBUSxDQUFDLENBQUE7Z0JBQ3hELE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLFdBQVcsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUE7Z0JBQy9DLE1BQU0sR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLFFBQVEsRUFBRSxHQUFHLFNBQVMsQ0FBQyxDQUFDLENBQUE7Z0JBRTVDLEtBQUssQ0FBQyxVQUFVLENBQUMsZ0JBQWdCLENBQUMsQ0FBQTthQUNuQztpQkFBTTtnQkFDTCxLQUFLLENBQUMsVUFBVSxDQUFDLDJCQUEyQixDQUFDLENBQUE7YUFDOUM7UUFDSCxDQUFDO0tBQUE7Q0FFRjtBQXZHRCxnQ0F1R0MiLCJmaWxlIjoidmNzL2dpdC5qcyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKEMpIDIwMTggR2FyZGVuIFRlY2hub2xvZ2llcywgSW5jLiA8aW5mb0BnYXJkZW4uaW8+XG4gKlxuICogVGhpcyBTb3VyY2UgQ29kZSBGb3JtIGlzIHN1YmplY3QgdG8gdGhlIHRlcm1zIG9mIHRoZSBNb3ppbGxhIFB1YmxpY1xuICogTGljZW5zZSwgdi4gMi4wLiBJZiBhIGNvcHkgb2YgdGhlIE1QTCB3YXMgbm90IGRpc3RyaWJ1dGVkIHdpdGggdGhpc1xuICogZmlsZSwgWW91IGNhbiBvYnRhaW4gb25lIGF0IGh0dHA6Ly9tb3ppbGxhLm9yZy9NUEwvMi4wLy5cbiAqL1xuXG5pbXBvcnQgZXhlY2EgPSByZXF1aXJlKFwiZXhlY2FcIilcbmltcG9ydCB7IGpvaW4gfSBmcm9tIFwicGF0aFwiXG5pbXBvcnQgeyBlbnN1cmVEaXIsIHBhdGhFeGlzdHMsIHN0YXQgfSBmcm9tIFwiZnMtZXh0cmFcIlxuaW1wb3J0IEJsdWViaXJkID0gcmVxdWlyZShcImJsdWViaXJkXCIpXG5cbmltcG9ydCB7IE5FV19NT0RVTEVfVkVSU0lPTiwgVmNzSGFuZGxlciwgUmVtb3RlU291cmNlUGFyYW1zIH0gZnJvbSBcIi4vYmFzZVwiXG5cbmV4cG9ydCBjb25zdCBoZWxwZXJzID0ge1xuICBnaXRDbGk6IChjd2Q6IHN0cmluZyk6IChjbWQ6IHN0cmluZywgYXJnczogc3RyaW5nW10pID0+IFByb21pc2U8c3RyaW5nPiA9PiB7XG4gICAgcmV0dXJuIGFzeW5jIChjbWQsIGFyZ3MpID0+IHtcbiAgICAgIHJldHVybiBleGVjYS5zdGRvdXQoXCJnaXRcIiwgW2NtZCwgLi4uYXJnc10sIHsgY3dkIH0pXG4gICAgfVxuICB9LFxufVxuXG5mdW5jdGlvbiBnZXRHaXRVcmxQYXJ0cyh1cmw6IHN0cmluZykge1xuICBjb25zdCBwYXJ0cyA9IHVybC5zcGxpdChcIiNcIilcbiAgcmV0dXJuIHsgcmVwb3NpdG9yeVVybDogcGFydHNbMF0sIGhhc2g6IHBhcnRzWzFdIH1cbn1cblxuZnVuY3Rpb24gcGFyc2VSZWZMaXN0KHJlczogc3RyaW5nKTogc3RyaW5nIHtcbiAgY29uc3QgcmVmTGlzdCA9IHJlcy5zcGxpdChcIlxcblwiKS5tYXAoc3RyID0+IHtcbiAgICBjb25zdCBwYXJ0cyA9IHN0ci5zcGxpdChcIlxcblwiKVxuICAgIHJldHVybiB7IGNvbW1pdElkOiBwYXJ0c1swXSwgcmVmOiBwYXJ0c1sxXSB9XG4gIH0pXG4gIHJldHVybiByZWZMaXN0WzBdLmNvbW1pdElkXG59XG5cbi8vIFRPRE8gQ29uc2lkZXIgbW92aW5nIGdpdCBjb21tYW5kcyB0byBzZXBhcmF0ZSAoYW5kIHRlc3RhYmxlKSBmdW5jdGlvbnNcbmV4cG9ydCBjbGFzcyBHaXRIYW5kbGVyIGV4dGVuZHMgVmNzSGFuZGxlciB7XG4gIG5hbWUgPSBcImdpdFwiXG5cbiAgYXN5bmMgZ2V0VHJlZVZlcnNpb24ocGF0aDogc3RyaW5nKSB7XG4gICAgY29uc3QgZ2l0ID0gaGVscGVycy5naXRDbGkocGF0aClcblxuICAgIGxldCBjb21taXRIYXNoXG4gICAgdHJ5IHtcbiAgICAgIGNvbW1pdEhhc2ggPSBhd2FpdCBnaXQoXCJyZXYtbGlzdFwiLCBbXG4gICAgICAgIFwiLS1tYXgtY291bnQ9MVwiLFxuICAgICAgICBcIi0tYWJicmV2LWNvbW1pdFwiLFxuICAgICAgICBcIi0tYWJicmV2PTEwXCIsXG4gICAgICAgIFwiSEVBRFwiLFxuICAgICAgXSkgfHwgTkVXX01PRFVMRV9WRVJTSU9OXG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBpZiAoZXJyLmNvZGUgPT09IDEyOCkge1xuICAgICAgICAvLyBub3QgaW4gYSByZXBvIHJvb3QsIHJldHVybiBkZWZhdWx0IHZlcnNpb25cbiAgICAgICAgY29tbWl0SGFzaCA9IE5FV19NT0RVTEVfVkVSU0lPTlxuICAgICAgfVxuICAgIH1cblxuICAgIGxldCBsYXRlc3REaXJ0eSA9IDBcblxuICAgIGNvbnN0IHJlcyA9IGF3YWl0IGdpdChcImRpZmYtaW5kZXhcIiwgW1wiLS1uYW1lLW9ubHlcIiwgXCJIRUFEXCIsIHBhdGhdKSArIFwiXFxuXCJcbiAgICAgICsgYXdhaXQgZ2l0KFwibHMtZmlsZXNcIiwgW1wiLS1vdGhlclwiLCBcIi0tZXhjbHVkZS1zdGFuZGFyZFwiLCBwYXRoXSlcblxuICAgIGNvbnN0IGRpcnR5RmlsZXM6IHN0cmluZ1tdID0gcmVzLnNwbGl0KFwiXFxuXCIpLmZpbHRlcigoZikgPT4gZi5sZW5ndGggPiAwKVxuICAgIC8vIGZvciBkaXJ0eSB0cmVlcywgd2UgYXBwZW5kIHRoZSBsYXN0IG1vZGlmaWVkIHRpbWUgb2YgbGFzdCBtb2RpZmllZCBvciBhZGRlZCBmaWxlXG4gICAgaWYgKGRpcnR5RmlsZXMubGVuZ3RoKSB7XG4gICAgICBjb25zdCByZXBvUm9vdCA9IGF3YWl0IGdpdChcInJldi1wYXJzZVwiLCBbXCItLXNob3ctdG9wbGV2ZWxcIl0pXG4gICAgICBjb25zdCBzdGF0cyA9IGF3YWl0IEJsdWViaXJkLm1hcChkaXJ0eUZpbGVzLCBmaWxlID0+IGpvaW4ocmVwb1Jvb3QsIGZpbGUpKVxuICAgICAgICAuZmlsdGVyKChmaWxlOiBzdHJpbmcpID0+IHBhdGhFeGlzdHMoZmlsZSkpXG4gICAgICAgIC5tYXAoKGZpbGU6IHN0cmluZykgPT4gc3RhdChmaWxlKSlcblxuICAgICAgbGV0IG10aW1lcyA9IHN0YXRzLm1hcCgocykgPT4gTWF0aC5yb3VuZChzLm10aW1lLmdldFRpbWUoKSAvIDEwMDApKVxuICAgICAgbGV0IGxhdGVzdCA9IG10aW1lcy5zb3J0KCkuc2xpY2UoLTEpWzBdXG5cbiAgICAgIGlmIChsYXRlc3QgPiBsYXRlc3REaXJ0eSkge1xuICAgICAgICBsYXRlc3REaXJ0eSA9IGxhdGVzdFxuICAgICAgfVxuICAgIH1cblxuICAgIHJldHVybiB7XG4gICAgICBsYXRlc3RDb21taXQ6IGNvbW1pdEhhc2gsXG4gICAgICBkaXJ0eVRpbWVzdGFtcDogbGF0ZXN0RGlydHkgfHwgbnVsbCxcbiAgICB9XG4gIH1cblxuICAvLyBUT0RPIEJldHRlciBhdXRoIGhhbmRsaW5nXG4gIGFzeW5jIGVuc3VyZVJlbW90ZVNvdXJjZSh7IHVybCwgbmFtZSwgbG9nRW50cnksIHNvdXJjZVR5cGUgfTogUmVtb3RlU291cmNlUGFyYW1zKTogUHJvbWlzZTxzdHJpbmc+IHtcbiAgICBjb25zdCByZW1vdGVTb3VyY2VzUGF0aCA9IGpvaW4odGhpcy5wcm9qZWN0Um9vdCwgdGhpcy5nZXRSZW1vdGVTb3VyY2VzRGlybmFtZShzb3VyY2VUeXBlKSlcbiAgICBhd2FpdCBlbnN1cmVEaXIocmVtb3RlU291cmNlc1BhdGgpXG4gICAgY29uc3QgZ2l0ID0gaGVscGVycy5naXRDbGkocmVtb3RlU291cmNlc1BhdGgpXG5cbiAgICBjb25zdCBhYnNQYXRoID0gam9pbih0aGlzLnByb2plY3RSb290LCB0aGlzLmdldFJlbW90ZVNvdXJjZVBhdGgobmFtZSwgdXJsLCBzb3VyY2VUeXBlKSlcbiAgICBjb25zdCBpc0Nsb25lZCA9IGF3YWl0IHBhdGhFeGlzdHMoYWJzUGF0aClcblxuICAgIGlmICghaXNDbG9uZWQpIHtcbiAgICAgIGNvbnN0IGVudHJ5ID0gbG9nRW50cnkuaW5mbyh7IHNlY3Rpb246IG5hbWUsIG1zZzogYEZldGNoaW5nIGZyb20gJHt1cmx9YCwgc3RhdHVzOiBcImFjdGl2ZVwiIH0pXG4gICAgICBjb25zdCB7IHJlcG9zaXRvcnlVcmwsIGhhc2ggfSA9IGdldEdpdFVybFBhcnRzKHVybClcblxuICAgICAgY29uc3QgY21kT3B0cyA9IFtcIi0tZGVwdGg9MVwiXVxuICAgICAgaWYgKGhhc2gpIHtcbiAgICAgICAgY21kT3B0cy5wdXNoKFwiLS1icmFuY2g9aGFzaFwiKVxuICAgICAgfVxuXG4gICAgICBhd2FpdCBnaXQoXCJjbG9uZVwiLCBbLi4uY21kT3B0cywgcmVwb3NpdG9yeVVybCwgYWJzUGF0aF0pXG5cbiAgICAgIGVudHJ5LnNldFN1Y2Nlc3MoKVxuICAgIH1cblxuICAgIHJldHVybiBhYnNQYXRoXG4gIH1cblxuICBhc3luYyB1cGRhdGVSZW1vdGVTb3VyY2UoeyB1cmwsIG5hbWUsIHNvdXJjZVR5cGUsIGxvZ0VudHJ5IH06IFJlbW90ZVNvdXJjZVBhcmFtcykge1xuICAgIGNvbnN0IGFic1BhdGggPSBqb2luKHRoaXMucHJvamVjdFJvb3QsIHRoaXMuZ2V0UmVtb3RlU291cmNlUGF0aChuYW1lLCB1cmwsIHNvdXJjZVR5cGUpKVxuICAgIGNvbnN0IGdpdCA9IGhlbHBlcnMuZ2l0Q2xpKGFic1BhdGgpXG4gICAgY29uc3QgeyByZXBvc2l0b3J5VXJsLCBoYXNoIH0gPSBnZXRHaXRVcmxQYXJ0cyh1cmwpXG5cbiAgICBhd2FpdCB0aGlzLmVuc3VyZVJlbW90ZVNvdXJjZSh7IHVybCwgbmFtZSwgc291cmNlVHlwZSwgbG9nRW50cnkgfSlcblxuICAgIGNvbnN0IGVudHJ5ID0gbG9nRW50cnkuaW5mbyh7IHNlY3Rpb246IG5hbWUsIG1zZzogXCJHZXR0aW5nIHJlbW90ZSBzdGF0ZVwiLCBzdGF0dXM6IFwiYWN0aXZlXCIgfSlcbiAgICBhd2FpdCBnaXQoXCJyZW1vdGVcIiwgW1widXBkYXRlXCJdKVxuXG4gICAgY29uc3QgbGlzdFJlbW90ZUFyZ3MgPSBoYXNoID8gW3JlcG9zaXRvcnlVcmwsIGhhc2hdIDogW3JlcG9zaXRvcnlVcmxdXG4gICAgY29uc3Qgc2hvd1JlZkFyZ3MgPSBoYXNoID8gW2hhc2hdIDogW11cbiAgICBjb25zdCByZW1vdGVDb21taXRJZCA9IHBhcnNlUmVmTGlzdChhd2FpdCBnaXQoXCJscy1yZW1vdGVcIiwgbGlzdFJlbW90ZUFyZ3MpKVxuICAgIGNvbnN0IGxvY2FsQ29tbWl0SWQgPSBwYXJzZVJlZkxpc3QoYXdhaXQgZ2l0KFwic2hvdy1yZWZcIiwgW1wiLS1oYXNoXCIsIC4uLnNob3dSZWZBcmdzXSkpXG5cbiAgICBpZiAobG9jYWxDb21taXRJZCAhPT0gcmVtb3RlQ29tbWl0SWQpIHtcbiAgICAgIGVudHJ5LnNldFN0YXRlKGBGZXRjaGluZyBmcm9tICR7dXJsfWApXG5cbiAgICAgIGNvbnN0IGZldGNoQXJncyA9IGhhc2ggPyBbXCJvcmlnaW5cIiwgaGFzaF0gOiBbXCJvcmlnaW5cIl1cbiAgICAgIGNvbnN0IHJlc2V0QXJncyA9IGhhc2ggPyBbYG9yaWdpbi8ke2hhc2h9YF0gOiBbXCJvcmlnaW5cIl1cbiAgICAgIGF3YWl0IGdpdChcImZldGNoXCIsIFtcIi0tZGVwdGg9MVwiLCAuLi5mZXRjaEFyZ3NdKVxuICAgICAgYXdhaXQgZ2l0KFwicmVzZXRcIiwgW1wiLS1oYXJkXCIsIC4uLnJlc2V0QXJnc10pXG5cbiAgICAgIGVudHJ5LnNldFN1Y2Nlc3MoXCJTb3VyY2UgdXBkYXRlZFwiKVxuICAgIH0gZWxzZSB7XG4gICAgICBlbnRyeS5zZXRTdWNjZXNzKFwiU291cmNlIGFscmVhZHkgdXAgdG8gZGF0ZVwiKVxuICAgIH1cbiAgfVxuXG59XG4iXX0= diff --git a/garden-service/build/watch.d.ts b/garden-service/build/watch.d.ts new file mode 100644 index 00000000000..e8687bff296 --- /dev/null +++ b/garden-service/build/watch.d.ts @@ -0,0 +1,21 @@ +import { Module } from "./types/module"; +import { Garden } from "./garden"; +export declare type AutoReloadDependants = { + [key: string]: Module[]; +}; +export declare type ChangeHandler = (module: Module | null, configChanged: boolean) => Promise; +export declare function withDependants(garden: Garden, modules: Module[], autoReloadDependants: AutoReloadDependants): Promise; +export declare function computeAutoReloadDependants(garden: Garden): Promise; +export declare class FSWatcher { + private garden; + private watcher; + constructor(garden: Garden); + watchModules(modules: Module[], changeHandler: ChangeHandler): Promise; + private makeFileChangedHandler; + private makeDirAddedHandler; + private makeDirRemovedHandler; + private invalidateCached; + private invalidateCachedForAll; + close(): void; +} +//# sourceMappingURL=watch.d.ts.map \ No newline at end of file diff --git a/garden-service/build/watch.js b/garden-service/build/watch.js new file mode 100644 index 00000000000..0882c056dde --- /dev/null +++ b/garden-service/build/watch.js @@ -0,0 +1,197 @@ +"use strict"; +/* + * Copyright (C) 2018 Garden Technologies, Inc. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + */ +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __asyncValues = (this && this.__asyncValues) || function (o) { + if (!Symbol.asyncIterator) throw new TypeError("Symbol.asyncIterator is not defined."); + var m = o[Symbol.asyncIterator], i; + return m ? m.call(o) : (o = typeof __values === "function" ? __values(o) : o[Symbol.iterator](), i = {}, verb("next"), verb("throw"), verb("return"), i[Symbol.asyncIterator] = function () { return this; }, i); + function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; } + function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); } +}; +Object.defineProperty(exports, "__esModule", { value: true }); +const chokidar_1 = require("chokidar"); +const lodash_1 = require("lodash"); +const path_1 = require("path"); +const cache_1 = require("./cache"); +const module_1 = require("./types/module"); +const util_1 = require("./util/util"); +const constants_1 = require("./constants"); +/* + Resolves to modules and their build & service dependant modules (recursively). + Each module is represented at most once in the output. +*/ +function withDependants(garden, modules, autoReloadDependants) { + return __awaiter(this, void 0, void 0, function* () { + const moduleSet = new Set(); + const scanner = (module) => { + moduleSet.add(module.name); + for (const dependant of (autoReloadDependants[module.name] || [])) { + if (!moduleSet.has(dependant.name)) { + scanner(dependant); + } + } + }; + for (const m of modules) { + scanner(m); + } + // we retrieve the modules again to be sure we have the latest versions + return garden.getModules(Array.from(moduleSet)); + }); +} +exports.withDependants = withDependants; +function computeAutoReloadDependants(garden) { + return __awaiter(this, void 0, void 0, function* () { + const dependants = {}; + for (const module of yield garden.getModules()) { + const depModules = yield uniqueDependencyModules(garden, module); + for (const dep of depModules) { + lodash_1.set(dependants, [dep.name, module.name], module); + } + } + return lodash_1.mapValues(dependants, lodash_1.values); + }); +} +exports.computeAutoReloadDependants = computeAutoReloadDependants; +function uniqueDependencyModules(garden, module) { + return __awaiter(this, void 0, void 0, function* () { + const buildDeps = module.build.dependencies.map(d => module_1.getModuleKey(d.name, d.plugin)); + const serviceDeps = (yield garden.getServices(module.serviceDependencyNames)).map(s => s.module.name); + return garden.getModules(lodash_1.uniq(buildDeps.concat(serviceDeps))); + }); +} +class FSWatcher { + constructor(garden) { + this.garden = garden; + } + watchModules(modules, changeHandler) { + return __awaiter(this, void 0, void 0, function* () { + const projectRoot = this.garden.projectRoot; + const ignorer = yield util_1.getIgnorer(projectRoot); + const onFileChanged = this.makeFileChangedHandler(modules, changeHandler); + this.watcher = chokidar_1.watch(projectRoot, { + ignored: (path, _) => { + const relpath = path_1.relative(projectRoot, path); + return relpath && ignorer.ignores(relpath); + }, + ignoreInitial: true, + persistent: true, + }); + this.watcher + .on("add", onFileChanged) + .on("change", onFileChanged) + .on("unlink", onFileChanged); + this.watcher + .on("addDir", yield this.makeDirAddedHandler(modules, changeHandler, ignorer)) + .on("unlinkDir", this.makeDirRemovedHandler(modules, changeHandler)); + }); + } + makeFileChangedHandler(modules, changeHandler) { + return (filePath) => __awaiter(this, void 0, void 0, function* () { + const filename = path_1.basename(filePath); + if (filename === "garden.yml" || filename === ".gitignore" || filename === ".gardenignore") { + yield this.invalidateCachedForAll(); + return changeHandler(null, true); + } + const changedModule = modules.find(m => filePath.startsWith(m.path)) || null; + if (changedModule) { + this.invalidateCached(changedModule); + } + return changeHandler(changedModule, false); + }); + } + makeDirAddedHandler(modules, changeHandler, ignorer) { + return __awaiter(this, void 0, void 0, function* () { + const scanOpts = { + filter: (path) => { + const relPath = path_1.relative(this.garden.projectRoot, path); + return !ignorer.ignores(relPath); + }, + }; + return (dirPath) => __awaiter(this, void 0, void 0, function* () { + var e_1, _a; + let configChanged = false; + try { + for (var _b = __asyncValues(util_1.scanDirectory(dirPath, scanOpts)), _c; _c = yield _b.next(), !_c.done;) { + const node = _c.value; + if (!node) { + continue; + } + if (path_1.parse(node.path).base === constants_1.MODULE_CONFIG_FILENAME) { + configChanged = true; + } + } + } + catch (e_1_1) { e_1 = { error: e_1_1 }; } + finally { + try { + if (_c && !_c.done && (_a = _b.return)) yield _a.call(_b); + } + finally { if (e_1) throw e_1.error; } + } + if (configChanged) { + // The added/removed dir contains one or more garden.yml files + yield this.invalidateCachedForAll(); + return changeHandler(null, true); + } + const changedModule = modules.find(m => dirPath.startsWith(m.path)) || null; + if (changedModule) { + this.invalidateCached(changedModule); + return changeHandler(changedModule, false); + } + }); + }); + } + makeDirRemovedHandler(modules, changeHandler) { + return (dirPath) => __awaiter(this, void 0, void 0, function* () { + let changedModule = null; + for (const module of modules) { + if (module.path.startsWith(dirPath)) { + // at least one module's root dir was removed + yield this.invalidateCachedForAll(); + return changeHandler(null, true); + } + if (dirPath.startsWith(module.path)) { + // removed dir is a subdir of changedModule's root dir + if (!changedModule || module.path.startsWith(changedModule.path)) { + changedModule = module; + } + } + } + if (changedModule) { + this.invalidateCached(changedModule); + return changeHandler(changedModule, false); + } + }); + } + invalidateCached(module) { + // invalidate the cache for anything attached to the module path or upwards in the directory tree + const cacheContext = cache_1.pathToCacheContext(module.path); + this.garden.cache.invalidateUp(cacheContext); + } + invalidateCachedForAll() { + return __awaiter(this, void 0, void 0, function* () { + for (const module of yield this.garden.getModules()) { + this.invalidateCached(module); + } + }); + } + close() { + this.watcher.close(); + } +} +exports.FSWatcher = FSWatcher; + +//# sourceMappingURL=data:application/json;charset=utf8;base64,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YSxFQUFFO2dCQUNqQixJQUFJLENBQUMsZ0JBQWdCLENBQUMsYUFBYSxDQUFDLENBQUE7Z0JBQ3BDLE9BQU8sYUFBYSxDQUFDLGFBQWEsRUFBRSxLQUFLLENBQUMsQ0FBQTthQUMzQztRQUNILENBQUMsQ0FBQSxDQUFBO0lBRUgsQ0FBQztJQUVPLGdCQUFnQixDQUFDLE1BQWM7UUFDckMsaUdBQWlHO1FBQ2pHLE1BQU0sWUFBWSxHQUFHLDBCQUFrQixDQUFDLE1BQU0sQ0FBQyxJQUFJLENBQUMsQ0FBQTtRQUNwRCxJQUFJLENBQUMsTUFBTSxDQUFDLEtBQUssQ0FBQyxZQUFZLENBQUMsWUFBWSxDQUFDLENBQUE7SUFDOUMsQ0FBQztJQUVhLHNCQUFzQjs7WUFDbEMsS0FBSyxNQUFNLE1BQU0sSUFBSSxNQUFNLElBQUksQ0FBQyxNQUFNLENBQUMsVUFBVSxFQUFFLEVBQUU7Z0JBQ25ELElBQUksQ0FBQyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQTthQUM5QjtRQUNILENBQUM7S0FBQTtJQUVELEtBQUs7UUFDSCxJQUFJLENBQUMsT0FBTyxDQUFDLEtBQUssRUFBRSxDQUFBO0lBQ3RCLENBQUM7Q0FFRjtBQTlJRCw4QkE4SUMiLCJmaWxlIjoid2F0Y2guanMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChDKSAyMDE4IEdhcmRlbiBUZWNobm9sb2dpZXMsIEluYy4gPGluZm9AZ2FyZGVuLmlvPlxuICpcbiAqIFRoaXMgU291cmNlIENvZGUgRm9ybSBpcyBzdWJqZWN0IHRvIHRoZSB0ZXJtcyBvZiB0aGUgTW96aWxsYSBQdWJsaWNcbiAqIExpY2Vuc2UsIHYuIDIuMC4gSWYgYSBjb3B5IG9mIHRoZSBNUEwgd2FzIG5vdCBkaXN0cmlidXRlZCB3aXRoIHRoaXNcbiAqIGZpbGUsIFlvdSBjYW4gb2J0YWluIG9uZSBhdCBodHRwOi8vbW96aWxsYS5vcmcvTVBMLzIuMC8uXG4gKi9cblxuaW1wb3J0IHsgd2F0Y2ggfSBmcm9tIFwiY2hva2lkYXJcIlxuaW1wb3J0IHtcbiAgbWFwVmFsdWVzLFxuICBzZXQsXG4gIHVuaXEsXG4gIHZhbHVlcyxcbn0gZnJvbSBcImxvZGFzaFwiXG5pbXBvcnQgeyBiYXNlbmFtZSwgcGFyc2UsIHJlbGF0aXZlIH0gZnJvbSBcInBhdGhcIlxuaW1wb3J0IHsgcGF0aFRvQ2FjaGVDb250ZXh0IH0gZnJvbSBcIi4vY2FjaGVcIlxuaW1wb3J0IHsgTW9kdWxlLCBnZXRNb2R1bGVLZXkgfSBmcm9tIFwiLi90eXBlcy9tb2R1bGVcIlxuaW1wb3J0IHsgZ2V0SWdub3Jlciwgc2NhbkRpcmVjdG9yeSB9IGZyb20gXCIuL3V0aWwvdXRpbFwiXG5pbXBvcnQgeyBNT0RVTEVfQ09ORklHX0ZJTEVOQU1FIH0gZnJvbSBcIi4vY29uc3RhbnRzXCJcbmltcG9ydCB7IEdhcmRlbiB9IGZyb20gXCIuL2dhcmRlblwiXG5cbmV4cG9ydCB0eXBlIEF1dG9SZWxvYWREZXBlbmRhbnRzID0geyBba2V5OiBzdHJpbmddOiBNb2R1bGVbXSB9XG5leHBvcnQgdHlwZSBDaGFuZ2VIYW5kbGVyID0gKG1vZHVsZTogTW9kdWxlIHwgbnVsbCwgY29uZmlnQ2hhbmdlZDogYm9vbGVhbikgPT4gUHJvbWlzZTx2b2lkPlxuXG4vKlxuICBSZXNvbHZlcyB0byBtb2R1bGVzIGFuZCB0aGVpciBidWlsZCAmIHNlcnZpY2UgZGVwZW5kYW50IG1vZHVsZXMgKHJlY3Vyc2l2ZWx5KS5cbiAgRWFjaCBtb2R1bGUgaXMgcmVwcmVzZW50ZWQgYXQgbW9zdCBvbmNlIGluIHRoZSBvdXRwdXQuXG4qL1xuZXhwb3J0IGFzeW5jIGZ1bmN0aW9uIHdpdGhEZXBlbmRhbnRzKFxuICBnYXJkZW46IEdhcmRlbixcbiAgbW9kdWxlczogTW9kdWxlW10sXG4gIGF1dG9SZWxvYWREZXBlbmRhbnRzOiBBdXRvUmVsb2FkRGVwZW5kYW50cyxcbik6IFByb21pc2U8TW9kdWxlW10+IHtcbiAgY29uc3QgbW9kdWxlU2V0ID0gbmV3IFNldDxzdHJpbmc+KClcblxuICBjb25zdCBzY2FubmVyID0gKG1vZHVsZTogTW9kdWxlKSA9PiB7XG4gICAgbW9kdWxlU2V0LmFkZChtb2R1bGUubmFtZSlcbiAgICBmb3IgKGNvbnN0IGRlcGVuZGFudCBvZiAoYXV0b1JlbG9hZERlcGVuZGFudHNbbW9kdWxlLm5hbWVdIHx8IFtdKSkge1xuICAgICAgaWYgKCFtb2R1bGVTZXQuaGFzKGRlcGVuZGFudC5uYW1lKSkge1xuICAgICAgICBzY2FubmVyKGRlcGVuZGFudClcbiAgICAgIH1cbiAgICB9XG4gIH1cbiAgZm9yIChjb25zdCBtIG9mIG1vZHVsZXMpIHtcbiAgICBzY2FubmVyKG0pXG4gIH1cblxuICAvLyB3ZSByZXRyaWV2ZSB0aGUgbW9kdWxlcyBhZ2FpbiB0byBiZSBzdXJlIHdlIGhhdmUgdGhlIGxhdGVzdCB2ZXJzaW9uc1xuICByZXR1cm4gZ2FyZGVuLmdldE1vZHVsZXMoQXJyYXkuZnJvbShtb2R1bGVTZXQpKVxufVxuXG5leHBvcnQgYXN5bmMgZnVuY3Rpb24gY29tcHV0ZUF1dG9SZWxvYWREZXBlbmRhbnRzKGdhcmRlbjogR2FyZGVuKTogUHJvbWlzZTxBdXRvUmVsb2FkRGVwZW5kYW50cz4ge1xuICBjb25zdCBkZXBlbmRhbnRzID0ge31cblxuICBmb3IgKGNvbnN0IG1vZHVsZSBvZiBhd2FpdCBnYXJkZW4uZ2V0TW9kdWxlcygpKSB7XG4gICAgY29uc3QgZGVwTW9kdWxlczogTW9kdWxlW10gPSBhd2FpdCB1bmlxdWVEZXBlbmRlbmN5TW9kdWxlcyhnYXJkZW4sIG1vZHVsZSlcbiAgICBmb3IgKGNvbnN0IGRlcCBvZiBkZXBNb2R1bGVzKSB7XG4gICAgICBzZXQoZGVwZW5kYW50cywgW2RlcC5uYW1lLCBtb2R1bGUubmFtZV0sIG1vZHVsZSlcbiAgICB9XG4gIH1cblxuICByZXR1cm4gbWFwVmFsdWVzKGRlcGVuZGFudHMsIHZhbHVlcylcbn1cblxuYXN5bmMgZnVuY3Rpb24gdW5pcXVlRGVwZW5kZW5jeU1vZHVsZXMoZ2FyZGVuOiBHYXJkZW4sIG1vZHVsZTogTW9kdWxlKTogUHJvbWlzZTxNb2R1bGVbXT4ge1xuICBjb25zdCBidWlsZERlcHMgPSBtb2R1bGUuYnVpbGQuZGVwZW5kZW5jaWVzLm1hcChkID0+IGdldE1vZHVsZUtleShkLm5hbWUsIGQucGx1Z2luKSlcbiAgY29uc3Qgc2VydmljZURlcHMgPSAoYXdhaXQgZ2FyZGVuLmdldFNlcnZpY2VzKG1vZHVsZS5zZXJ2aWNlRGVwZW5kZW5jeU5hbWVzKSkubWFwKHMgPT4gcy5tb2R1bGUubmFtZSlcbiAgcmV0dXJuIGdhcmRlbi5nZXRNb2R1bGVzKHVuaXEoYnVpbGREZXBzLmNvbmNhdChzZXJ2aWNlRGVwcykpKVxufVxuXG5leHBvcnQgY2xhc3MgRlNXYXRjaGVyIHtcbiAgcHJpdmF0ZSB3YXRjaGVyXG5cbiAgY29uc3RydWN0b3IocHJpdmF0ZSBnYXJkZW46IEdhcmRlbikge1xuICB9XG5cbiAgYXN5bmMgd2F0Y2hNb2R1bGVzKG1vZHVsZXM6IE1vZHVsZVtdLCBjaGFuZ2VIYW5kbGVyOiBDaGFuZ2VIYW5kbGVyKSB7XG5cbiAgICBjb25zdCBwcm9qZWN0Um9vdCA9IHRoaXMuZ2FyZGVuLnByb2plY3RSb290XG4gICAgY29uc3QgaWdub3JlciA9IGF3YWl0IGdldElnbm9yZXIocHJvamVjdFJvb3QpXG5cbiAgICBjb25zdCBvbkZpbGVDaGFuZ2VkID0gdGhpcy5tYWtlRmlsZUNoYW5nZWRIYW5kbGVyKG1vZHVsZXMsIGNoYW5nZUhhbmRsZXIpXG5cbiAgICB0aGlzLndhdGNoZXIgPSB3YXRjaChwcm9qZWN0Um9vdCwge1xuICAgICAgaWdub3JlZDogKHBhdGgsIF8pID0+IHtcbiAgICAgICAgY29uc3QgcmVscGF0aCA9IHJlbGF0aXZlKHByb2plY3RSb290LCBwYXRoKVxuICAgICAgICByZXR1cm4gcmVscGF0aCAmJiBpZ25vcmVyLmlnbm9yZXMocmVscGF0aClcbiAgICAgIH0sXG4gICAgICBpZ25vcmVJbml0aWFsOiB0cnVlLFxuICAgICAgcGVyc2lzdGVudDogdHJ1ZSxcbiAgICB9KVxuXG4gICAgdGhpcy53YXRjaGVyXG4gICAgICAub24oXCJhZGRcIiwgb25GaWxlQ2hhbmdlZClcbiAgICAgIC5vbihcImNoYW5nZVwiLCBvbkZpbGVDaGFuZ2VkKVxuICAgICAgLm9uKFwidW5saW5rXCIsIG9uRmlsZUNoYW5nZWQpXG5cbiAgICB0aGlzLndhdGNoZXJcbiAgICAgIC5vbihcImFkZERpclwiLCBhd2FpdCB0aGlzLm1ha2VEaXJBZGRlZEhhbmRsZXIobW9kdWxlcywgY2hhbmdlSGFuZGxlciwgaWdub3JlcikpXG4gICAgICAub24oXCJ1bmxpbmtEaXJcIiwgdGhpcy5tYWtlRGlyUmVtb3ZlZEhhbmRsZXIobW9kdWxlcywgY2hhbmdlSGFuZGxlcikpXG5cbiAgfVxuXG4gIHByaXZhdGUgbWFrZUZpbGVDaGFuZ2VkSGFuZGxlcihtb2R1bGVzOiBNb2R1bGVbXSwgY2hhbmdlSGFuZGxlcjogQ2hhbmdlSGFuZGxlcikge1xuXG4gICAgcmV0dXJuIGFzeW5jIChmaWxlUGF0aDogc3RyaW5nKSA9PiB7XG5cbiAgICAgIGNvbnN0IGZpbGVuYW1lID0gYmFzZW5hbWUoZmlsZVBhdGgpXG4gICAgICBpZiAoZmlsZW5hbWUgPT09IFwiZ2FyZGVuLnltbFwiIHx8IGZpbGVuYW1lID09PSBcIi5naXRpZ25vcmVcIiB8fCBmaWxlbmFtZSA9PT0gXCIuZ2FyZGVuaWdub3JlXCIpIHtcbiAgICAgICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlQ2FjaGVkRm9yQWxsKClcbiAgICAgICAgcmV0dXJuIGNoYW5nZUhhbmRsZXIobnVsbCwgdHJ1ZSlcbiAgICAgIH1cblxuICAgICAgY29uc3QgY2hhbmdlZE1vZHVsZSA9IG1vZHVsZXMuZmluZChtID0+IGZpbGVQYXRoLnN0YXJ0c1dpdGgobS5wYXRoKSkgfHwgbnVsbFxuXG4gICAgICBpZiAoY2hhbmdlZE1vZHVsZSkge1xuICAgICAgICB0aGlzLmludmFsaWRhdGVDYWNoZWQoY2hhbmdlZE1vZHVsZSlcbiAgICAgIH1cblxuICAgICAgcmV0dXJuIGNoYW5nZUhhbmRsZXIoY2hhbmdlZE1vZHVsZSwgZmFsc2UpXG5cbiAgICB9XG5cbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgbWFrZURpckFkZGVkSGFuZGxlcihtb2R1bGVzOiBNb2R1bGVbXSwgY2hhbmdlSGFuZGxlcjogQ2hhbmdlSGFuZGxlciwgaWdub3Jlcikge1xuXG4gICAgY29uc3Qgc2Nhbk9wdHMgPSB7XG4gICAgICBmaWx0ZXI6IChwYXRoKSA9PiB7XG4gICAgICAgIGNvbnN0IHJlbFBhdGggPSByZWxhdGl2ZSh0aGlzLmdhcmRlbi5wcm9qZWN0Um9vdCwgcGF0aClcbiAgICAgICAgcmV0dXJuICFpZ25vcmVyLmlnbm9yZXMocmVsUGF0aClcbiAgICAgIH0sXG4gICAgfVxuXG4gICAgcmV0dXJuIGFzeW5jIChkaXJQYXRoOiBzdHJpbmcpID0+IHtcblxuICAgICAgbGV0IGNvbmZpZ0NoYW5nZWQgPSBmYWxzZVxuXG4gICAgICBmb3IgYXdhaXQgKGNvbnN0IG5vZGUgb2Ygc2NhbkRpcmVjdG9yeShkaXJQYXRoLCBzY2FuT3B0cykpIHtcbiAgICAgICAgaWYgKCFub2RlKSB7XG4gICAgICAgICAgY29udGludWVcbiAgICAgICAgfVxuXG4gICAgICAgIGlmIChwYXJzZShub2RlLnBhdGgpLmJhc2UgPT09IE1PRFVMRV9DT05GSUdfRklMRU5BTUUpIHtcbiAgICAgICAgICBjb25maWdDaGFuZ2VkID0gdHJ1ZVxuICAgICAgICB9XG4gICAgICB9XG5cbiAgICAgIGlmIChjb25maWdDaGFuZ2VkKSB7XG4gICAgICAgIC8vIFRoZSBhZGRlZC9yZW1vdmVkIGRpciBjb250YWlucyBvbmUgb3IgbW9yZSBnYXJkZW4ueW1sIGZpbGVzXG4gICAgICAgIGF3YWl0IHRoaXMuaW52YWxpZGF0ZUNhY2hlZEZvckFsbCgpXG4gICAgICAgIHJldHVybiBjaGFuZ2VIYW5kbGVyKG51bGwsIHRydWUpXG4gICAgICB9XG5cbiAgICAgIGNvbnN0IGNoYW5nZWRNb2R1bGUgPSBtb2R1bGVzLmZpbmQobSA9PiBkaXJQYXRoLnN0YXJ0c1dpdGgobS5wYXRoKSkgfHwgbnVsbFxuXG4gICAgICBpZiAoY2hhbmdlZE1vZHVsZSkge1xuICAgICAgICB0aGlzLmludmFsaWRhdGVDYWNoZWQoY2hhbmdlZE1vZHVsZSlcbiAgICAgICAgcmV0dXJuIGNoYW5nZUhhbmRsZXIoY2hhbmdlZE1vZHVsZSwgZmFsc2UpXG4gICAgICB9XG5cbiAgICB9XG5cbiAgfVxuXG4gIHByaXZhdGUgbWFrZURpclJlbW92ZWRIYW5kbGVyKG1vZHVsZXM6IE1vZHVsZVtdLCBjaGFuZ2VIYW5kbGVyOiBDaGFuZ2VIYW5kbGVyKSB7XG5cbiAgICByZXR1cm4gYXN5bmMgKGRpclBhdGg6IHN0cmluZykgPT4ge1xuXG4gICAgICBsZXQgY2hhbmdlZE1vZHVsZTogTW9kdWxlIHwgbnVsbCA9IG51bGxcblxuICAgICAgZm9yIChjb25zdCBtb2R1bGUgb2YgbW9kdWxlcykge1xuXG4gICAgICAgIGlmIChtb2R1bGUucGF0aC5zdGFydHNXaXRoKGRpclBhdGgpKSB7XG4gICAgICAgICAgLy8gYXQgbGVhc3Qgb25lIG1vZHVsZSdzIHJvb3QgZGlyIHdhcyByZW1vdmVkXG4gICAgICAgICAgYXdhaXQgdGhpcy5pbnZhbGlkYXRlQ2FjaGVkRm9yQWxsKClcbiAgICAgICAgICByZXR1cm4gY2hhbmdlSGFuZGxlcihudWxsLCB0cnVlKVxuICAgICAgICB9XG5cbiAgICAgICAgaWYgKGRpclBhdGguc3RhcnRzV2l0aChtb2R1bGUucGF0aCkpIHtcbiAgICAgICAgICAvLyByZW1vdmVkIGRpciBpcyBhIHN1YmRpciBvZiBjaGFuZ2VkTW9kdWxlJ3Mgcm9vdCBkaXJcbiAgICAgICAgICBpZiAoIWNoYW5nZWRNb2R1bGUgfHwgbW9kdWxlLnBhdGguc3RhcnRzV2l0aChjaGFuZ2VkTW9kdWxlLnBhdGgpKSB7XG4gICAgICAgICAgICBjaGFuZ2VkTW9kdWxlID0gbW9kdWxlXG4gICAgICAgICAgfVxuICAgICAgICB9XG5cbiAgICAgIH1cblxuICAgICAgaWYgKGNoYW5nZWRNb2R1bGUpIHtcbiAgICAgICAgdGhpcy5pbnZhbGlkYXRlQ2FjaGVkKGNoYW5nZWRNb2R1bGUpXG4gICAgICAgIHJldHVybiBjaGFuZ2VIYW5kbGVyKGNoYW5nZWRNb2R1bGUsIGZhbHNlKVxuICAgICAgfVxuICAgIH1cblxuICB9XG5cbiAgcHJpdmF0ZSBpbnZhbGlkYXRlQ2FjaGVkKG1vZHVsZTogTW9kdWxlKSB7XG4gICAgLy8gaW52YWxpZGF0ZSB0aGUgY2FjaGUgZm9yIGFueXRoaW5nIGF0dGFjaGVkIHRvIHRoZSBtb2R1bGUgcGF0aCBvciB1cHdhcmRzIGluIHRoZSBkaXJlY3RvcnkgdHJlZVxuICAgIGNvbnN0IGNhY2hlQ29udGV4dCA9IHBhdGhUb0NhY2hlQ29udGV4dChtb2R1bGUucGF0aClcbiAgICB0aGlzLmdhcmRlbi5jYWNoZS5pbnZhbGlkYXRlVXAoY2FjaGVDb250ZXh0KVxuICB9XG5cbiAgcHJpdmF0ZSBhc3luYyBpbnZhbGlkYXRlQ2FjaGVkRm9yQWxsKCkge1xuICAgIGZvciAoY29uc3QgbW9kdWxlIG9mIGF3YWl0IHRoaXMuZ2FyZGVuLmdldE1vZHVsZXMoKSkge1xuICAgICAgdGhpcy5pbnZhbGlkYXRlQ2FjaGVkKG1vZHVsZSlcbiAgICB9XG4gIH1cblxuICBjbG9zZSgpOiB2b2lkIHtcbiAgICB0aGlzLndhdGNoZXIuY2xvc2UoKVxuICB9XG5cbn1cbiJdfQ== diff --git a/garden-service/static/kubernetes/system/ingress-controller/.garden-version b/garden-service/static/kubernetes/system/ingress-controller/.garden-version new file mode 100644 index 00000000000..5994253a808 --- /dev/null +++ b/garden-service/static/kubernetes/system/ingress-controller/.garden-version @@ -0,0 +1,4 @@ +{ + "latestCommit": "4f4a7af951", + "dirtyTimestamp": null +} diff --git a/garden-service/static/kubernetes/system/kubernetes-dashboard/.garden-version b/garden-service/static/kubernetes/system/kubernetes-dashboard/.garden-version new file mode 100644 index 00000000000..5994253a808 --- /dev/null +++ b/garden-service/static/kubernetes/system/kubernetes-dashboard/.garden-version @@ -0,0 +1,4 @@ +{ + "latestCommit": "4f4a7af951", + "dirtyTimestamp": null +} diff --git a/garden-service/static/local-gcf-container/.garden-version b/garden-service/static/local-gcf-container/.garden-version new file mode 100644 index 00000000000..5994253a808 --- /dev/null +++ b/garden-service/static/local-gcf-container/.garden-version @@ -0,0 +1,4 @@ +{ + "latestCommit": "4f4a7af951", + "dirtyTimestamp": null +} diff --git a/garden-service/static/openfaas/builder/.garden-version b/garden-service/static/openfaas/builder/.garden-version new file mode 100644 index 00000000000..5994253a808 --- /dev/null +++ b/garden-service/static/openfaas/builder/.garden-version @@ -0,0 +1,4 @@ +{ + "latestCommit": "4f4a7af951", + "dirtyTimestamp": null +} diff --git a/garden-service/static/openfaas/system/openfaas-system/.garden-version b/garden-service/static/openfaas/system/openfaas-system/.garden-version new file mode 100644 index 00000000000..5994253a808 --- /dev/null +++ b/garden-service/static/openfaas/system/openfaas-system/.garden-version @@ -0,0 +1,4 @@ +{ + "latestCommit": "4f4a7af951", + "dirtyTimestamp": null +} diff --git a/package.json b/package.json index fd88b26ab6a..a22aba0e6d0 100644 --- a/package.json +++ b/package.json @@ -60,4 +60,4 @@ }, "snyk": true, "dependencies": {} -} \ No newline at end of file +}