diff --git a/infra-templates/alidns/0/README.md b/infra-templates/alidns/0/README.md new file mode 100644 index 0000000..dcc201f --- /dev/null +++ b/infra-templates/alidns/0/README.md @@ -0,0 +1,40 @@ +## Alibaba Cloud DNS + +Rancher External DNS service powered by Alibaba Cloud DNS + +#### Usage + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + +`io.rancher.service.external_dns_name_template` +Custom DNS name template that overrides global custom DNS name template (see below) of default DNS name template for a specific service + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/alidns/0/docker-compose.yml b/infra-templates/alidns/0/docker-compose.yml new file mode 100644 index 0000000..7f468c3 --- /dev/null +++ b/infra-templates/alidns/0/docker-compose.yml @@ -0,0 +1,14 @@ +alidns: + image: rancher/external-dns:v0.7.4 + command: -provider=alidns + expose: + - 1000 + environment: + ALICLOUD_ACCESS_KEY_ID: ${ALICLOUD_ACCESS_KEY_ID} + ALICLOUD_ACCESS_KEY_SECRET: ${ALICLOUD_ACCESS_KEY_SECRET} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/alidns/0/rancher-compose.yml b/infra-templates/alidns/0/rancher-compose.yml new file mode 100644 index 0000000..8e4270e --- /dev/null +++ b/infra-templates/alidns/0/rancher-compose.yml @@ -0,0 +1,48 @@ +# notemplating +.catalog: + name: "Alibaba Cloud DNS" + version: "v0.1.0" + description: "Rancher External DNS service powered by Alibaba Cloud" + minimum_rancher_version: v1.6.8-rc1 + questions: + - variable: "ALICLOUD_ACCESS_KEY_ID" + label: "Access Key ID" + description: "Access key id for your Alibaba Cloud account" + type: "string" + required: true + - variable: "ALICLOUD_ACCESS_KEY_SECRET" + label: "Access Key Secret" + description: "Access key secret for your Alibaba Cloud account" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Domain" + description: "The DNS zone (domain) managed by Alibaba Cloud. DNS entries will be created for ..." + type: "string" + required: true + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds" + type: "int" + default: 600 + min: 1 + max: 86400 + required: false + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the domain) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +alidns: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/alidns/catalogIcon-alidns.png b/infra-templates/alidns/catalogIcon-alidns.png new file mode 100644 index 0000000..630ba36 Binary files /dev/null and b/infra-templates/alidns/catalogIcon-alidns.png differ diff --git a/infra-templates/alidns/config.yml b/infra-templates/alidns/config.yml new file mode 100644 index 0000000..fb9788c --- /dev/null +++ b/infra-templates/alidns/config.yml @@ -0,0 +1,7 @@ +name: Alibaba Cloud DNS +description: | + Rancher External DNS service powered by Alibaba Cloud +version: v0.1.0 +category: External DNS +labels: + io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/infra-templates/cloudflare/0/rancher-compose.yml b/infra-templates/cloudflare/0/rancher-compose.yml index 18053a4..9ca5703 100644 --- a/infra-templates/cloudflare/0/rancher-compose.yml +++ b/infra-templates/cloudflare/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.1.9-rancher1" description: "Rancher External DNS service powered by CloudFlare. Requires Rancher version 0.44.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "CLOUDFLARE_EMAIL" label: "CloudFlare email address" diff --git a/infra-templates/cloudflare/1/rancher-compose.yml b/infra-templates/cloudflare/1/rancher-compose.yml index 57749e1..5f8f265 100644 --- a/infra-templates/cloudflare/1/rancher-compose.yml +++ b/infra-templates/cloudflare/1/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.2.1-rancher1" description: "Rancher External DNS service powered by CloudFlare. Requires Rancher version 0.44.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "CLOUDFLARE_EMAIL" label: "CloudFlare email address" diff --git a/infra-templates/cloudflare/2/rancher-compose.yml b/infra-templates/cloudflare/2/rancher-compose.yml index 8753d40..cf90dba 100644 --- a/infra-templates/cloudflare/2/rancher-compose.yml +++ b/infra-templates/cloudflare/2/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.4.0-rancher1" description: "Rancher External DNS service powered by CloudFlare. Requires Rancher version 0.44.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "CLOUDFLARE_EMAIL" label: "CloudFlare email address" diff --git a/infra-templates/cloudflare/3/rancher-compose.yml b/infra-templates/cloudflare/3/rancher-compose.yml index 73ec3f3..50d766a 100644 --- a/infra-templates/cloudflare/3/rancher-compose.yml +++ b/infra-templates/cloudflare/3/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.6.0-rancher1" description: "Rancher External DNS service powered by CloudFlare. Requires Rancher version v1.1.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.5.99 questions: - variable: "CLOUDFLARE_EMAIL" label: "CloudFlare email address" diff --git a/infra-templates/cloudflare/4/README.md b/infra-templates/cloudflare/4/README.md new file mode 100644 index 0000000..84dba81 --- /dev/null +++ b/infra-templates/cloudflare/4/README.md @@ -0,0 +1,36 @@ +## CloudFlare DNS + +Rancher External DNS service powered by CloudFlare DNS + +#### Changelog + +##### v0.6.0 + +* Reduces the overall rate of API requests to the DNS provider +* Adds support for custom DNS naming convention +* Stack, service and environment names used in service DNS names are now sanitized to conform with RFC 1123. Characters other than `a-z`, `A-Z`, `0-9` or `dash` are replaced by dashes. +* For internal use the service creates TXT records to track the FQDNs it manages. These TXT records are named `external-dns-.` and should not be deleted. + +#### Usage + +##### Upgrade Notes +While upgrading from a version lower than v0.6.0 the TTL configuration value should not be changed. You may change it once the upgrade has been completed. + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the **same** domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that are allowed by your provider in DNS names. diff --git a/infra-templates/cloudflare/4/docker-compose.yml b/infra-templates/cloudflare/4/docker-compose.yml new file mode 100644 index 0000000..bc46199 --- /dev/null +++ b/infra-templates/cloudflare/4/docker-compose.yml @@ -0,0 +1,14 @@ +cloudflare: + image: rancher/external-dns:v0.6.0 + command: -provider=cloudflare + expose: + - 1000 + environment: + CLOUDFLARE_EMAIL: ${CLOUDFLARE_EMAIL} + CLOUDFLARE_KEY: ${CLOUDFLARE_KEY} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/cloudflare/4/rancher-compose.yml b/infra-templates/cloudflare/4/rancher-compose.yml new file mode 100644 index 0000000..40a4fdf --- /dev/null +++ b/infra-templates/cloudflare/4/rancher-compose.yml @@ -0,0 +1,48 @@ +# notemplating +.catalog: + name: "CloudFlare DNS" + version: "v0.6.0-rancher2" + description: "Rancher External DNS service powered by CloudFlare. Requires Rancher version v1.1.0" + minimum_rancher_version: v1.6.0-rc1 + questions: + - variable: "CLOUDFLARE_EMAIL" + label: "CloudFlare email address" + description: "Email address associated with your CloudFlare account" + type: "string" + required: true + - variable: "CLOUDFLARE_KEY" + label: "CloudFlare API key" + description: "API key for your CloudFlare account" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Domain Name" + description: "The domain name managed by CloudFlare." + type: "string" + required: true + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds (minimum 120)" + type: "int" + default: 120 + min: 120 + max: 3600 + required: false + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the domain) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +cloudflare: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/cloudflare/config.yml b/infra-templates/cloudflare/config.yml index 45af600..deb2170 100644 --- a/infra-templates/cloudflare/config.yml +++ b/infra-templates/cloudflare/config.yml @@ -1,7 +1,7 @@ name: CloudFlare DNS description: | Rancher External DNS service powered by CloudFlare -version: v0.6.0-rancher1 +version: v0.6.0-rancher2 category: External DNS labels: io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/infra-templates/digitalocean-dns/0/rancher-compose.yml b/infra-templates/digitalocean-dns/0/rancher-compose.yml index aa72b16..6bda39c 100644 --- a/infra-templates/digitalocean-dns/0/rancher-compose.yml +++ b/infra-templates/digitalocean-dns/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.6.2-rancher1" description: "Rancher External DNS service powered by DigitalOcean" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.4.99 questions: - variable: "DO_PAT" label: "DigitalOcean Personal Access Token" diff --git a/infra-templates/digitalocean-dns/1/README.md b/infra-templates/digitalocean-dns/1/README.md new file mode 100644 index 0000000..a808387 --- /dev/null +++ b/infra-templates/digitalocean-dns/1/README.md @@ -0,0 +1,48 @@ +## DigitalOcean DNS + +Rancher External DNS service powered by DigitalOcean + +#### Changelog + +Initial version + +#### Usage + +##### DigitalOcean DNS record TTL +The DigitalOcean API currently does not support per-record TTL setting. You should configure the global TTL setting for the domain manually and set it to a low value (e.g. 60). + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the same domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/digitalocean-dns/1/docker-compose.yml b/infra-templates/digitalocean-dns/1/docker-compose.yml new file mode 100644 index 0000000..1e2db53 --- /dev/null +++ b/infra-templates/digitalocean-dns/1/docker-compose.yml @@ -0,0 +1,13 @@ +digitalocean: + image: rancher/external-dns:v0.6.3 + command: -provider=digitalocean + expose: + - 1000 + environment: + DO_PAT: ${DO_PAT} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: 300 + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/digitalocean-dns/1/rancher-compose.yml b/infra-templates/digitalocean-dns/1/rancher-compose.yml new file mode 100644 index 0000000..4666dd7 --- /dev/null +++ b/infra-templates/digitalocean-dns/1/rancher-compose.yml @@ -0,0 +1,35 @@ +.catalog: + name: "DigitalOcean DNS" + version: "v0.6.3" + description: "Rancher External DNS service powered by DigitalOcean" + minimum_rancher_version: v1.5.0 + maximum_rancher_version: v1.5.0 + questions: + - variable: "DO_PAT" + label: "DigitalOcean Personal Access Token" + description: "Enter your personal access token" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Domain Name" + description: "The domain name managed by DigitalOcean." + type: "string" + required: true + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the domain) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +digitalocean: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/digitalocean-dns/2/README.md b/infra-templates/digitalocean-dns/2/README.md new file mode 100644 index 0000000..013559c --- /dev/null +++ b/infra-templates/digitalocean-dns/2/README.md @@ -0,0 +1,53 @@ +## DigitalOcean DNS + +Rancher External DNS service powered by DigitalOcean + +#### Changelog + +##### v0.6.4 + +* Adds support for overriding name template for specific services by setting io.rancher.service.external_dns_name_template label to it in docker-compose.yml + +#### Usage + +##### DigitalOcean DNS record TTL +The DigitalOcean API currently does not support per-record TTL setting. You should configure the global TTL setting for the domain manually and set it to a low value (e.g. 60). + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the same domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + +`io.rancher.service.external_dns_name_template` +Custom DNS name template that overrides global custom DNS name template (see below) of default DNS name template for a specific service + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/digitalocean-dns/2/docker-compose.yml b/infra-templates/digitalocean-dns/2/docker-compose.yml new file mode 100644 index 0000000..1564ee2 --- /dev/null +++ b/infra-templates/digitalocean-dns/2/docker-compose.yml @@ -0,0 +1,13 @@ +digitalocean: + image: rancher/external-dns:v0.6.4 + command: -provider=digitalocean + expose: + - 1000 + environment: + DO_PAT: ${DO_PAT} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: 300 + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/digitalocean-dns/2/rancher-compose.yml b/infra-templates/digitalocean-dns/2/rancher-compose.yml new file mode 100644 index 0000000..a7949fc --- /dev/null +++ b/infra-templates/digitalocean-dns/2/rancher-compose.yml @@ -0,0 +1,35 @@ +.catalog: + name: "DigitalOcean DNS" + version: "v0.6.4" + description: "Rancher External DNS service powered by DigitalOcean" + minimum_rancher_version: v1.5.0 + maximum_rancher_version: v1.5.99 + questions: + - variable: "DO_PAT" + label: "DigitalOcean Personal Access Token" + description: "Enter your personal access token" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Domain Name" + description: "The domain name managed by DigitalOcean." + type: "string" + required: true + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the domain) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +digitalocean: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/digitalocean-dns/3/README.md b/infra-templates/digitalocean-dns/3/README.md new file mode 100644 index 0000000..013559c --- /dev/null +++ b/infra-templates/digitalocean-dns/3/README.md @@ -0,0 +1,53 @@ +## DigitalOcean DNS + +Rancher External DNS service powered by DigitalOcean + +#### Changelog + +##### v0.6.4 + +* Adds support for overriding name template for specific services by setting io.rancher.service.external_dns_name_template label to it in docker-compose.yml + +#### Usage + +##### DigitalOcean DNS record TTL +The DigitalOcean API currently does not support per-record TTL setting. You should configure the global TTL setting for the domain manually and set it to a low value (e.g. 60). + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the same domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + +`io.rancher.service.external_dns_name_template` +Custom DNS name template that overrides global custom DNS name template (see below) of default DNS name template for a specific service + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/digitalocean-dns/3/docker-compose.yml b/infra-templates/digitalocean-dns/3/docker-compose.yml new file mode 100644 index 0000000..1564ee2 --- /dev/null +++ b/infra-templates/digitalocean-dns/3/docker-compose.yml @@ -0,0 +1,13 @@ +digitalocean: + image: rancher/external-dns:v0.6.4 + command: -provider=digitalocean + expose: + - 1000 + environment: + DO_PAT: ${DO_PAT} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: 300 + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/digitalocean-dns/3/rancher-compose.yml b/infra-templates/digitalocean-dns/3/rancher-compose.yml new file mode 100644 index 0000000..64d5f43 --- /dev/null +++ b/infra-templates/digitalocean-dns/3/rancher-compose.yml @@ -0,0 +1,35 @@ +# notemplating +.catalog: + name: "DigitalOcean DNS" + version: "v0.6.4.1" + description: "Rancher External DNS service powered by DigitalOcean" + minimum_rancher_version: v1.6.0-rc1 + questions: + - variable: "DO_PAT" + label: "DigitalOcean Personal Access Token" + description: "Enter your personal access token" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Domain Name" + description: "The domain name managed by DigitalOcean." + type: "string" + required: true + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the domain) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +digitalocean: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/digitalocean-dns/config.yml b/infra-templates/digitalocean-dns/config.yml index 33b917f..315392e 100644 --- a/infra-templates/digitalocean-dns/config.yml +++ b/infra-templates/digitalocean-dns/config.yml @@ -1,7 +1,7 @@ name: DigitalOcean DNS description: | Rancher External DNS service powered by DigitalOcean -version: v0.6.2-rancher1 +version: v0.6.4.1 category: External DNS labels: io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/infra-templates/dnsimple/0/rancher-compose.yml b/infra-templates/dnsimple/0/rancher-compose.yml index 43f9cab..7a1ff09 100644 --- a/infra-templates/dnsimple/0/rancher-compose.yml +++ b/infra-templates/dnsimple/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.1.9-rancher1" description: "Rancher External DNS service powered by DNSimple. Requires Rancher version 0.44.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "DNSIMPLE_EMAIL" label: "DNSimple account email address" diff --git a/infra-templates/dnsimple/1/rancher-compose.yml b/infra-templates/dnsimple/1/rancher-compose.yml index 65fe19f..1a9473b 100644 --- a/infra-templates/dnsimple/1/rancher-compose.yml +++ b/infra-templates/dnsimple/1/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.2.1-rancher1" description: "Rancher External DNS service powered by DNSimple. Requires Rancher version 0.44.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "DNSIMPLE_EMAIL" label: "DNSimple account email address" diff --git a/infra-templates/dnsimple/2/rancher-compose.yml b/infra-templates/dnsimple/2/rancher-compose.yml index e2eb9ea..12a01d2 100644 --- a/infra-templates/dnsimple/2/rancher-compose.yml +++ b/infra-templates/dnsimple/2/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.6.0-rancher1" description: "Rancher External DNS service powered by DNSimple. Requires Rancher version v1.1.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.5.99 questions: - variable: "DNSIMPLE_EMAIL" label: "DNSimple Account Email Address" diff --git a/infra-templates/dnsimple/3/README.md b/infra-templates/dnsimple/3/README.md new file mode 100644 index 0000000..97b1559 --- /dev/null +++ b/infra-templates/dnsimple/3/README.md @@ -0,0 +1,36 @@ +## DNSimple DNS + +Rancher External DNS service powered by DNSimple DNS + +#### Changelog + +##### v0.6.0 + +* Reduces the overall rate of API requests to the DNS provider +* Adds support for custom DNS naming convention +* Stack, service and environment names used in service DNS names are now sanitized to conform with RFC 1123. Characters other than `a-z`, `A-Z`, `0-9` or `dash` are replaced by dashes. +* For internal use the service creates TXT records to track the FQDNs it manages. These TXT records are named `external-dns-.` and should not be deleted. + +#### Usage + +##### Upgrade Notes +While upgrading from a version lower than v0.6.0 the TTL configuration value should not be changed. You may change it once the upgrade has been completed. + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the **same** domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/dnsimple/3/docker-compose.yml b/infra-templates/dnsimple/3/docker-compose.yml new file mode 100644 index 0000000..95041b7 --- /dev/null +++ b/infra-templates/dnsimple/3/docker-compose.yml @@ -0,0 +1,14 @@ +dnsimple: + image: rancher/external-dns:v0.6.0 + command: -provider=dnsimple + expose: + - 1000 + environment: + DNSIMPLE_TOKEN: ${DNSIMPLE_TOKEN} + DNSIMPLE_EMAIL: ${DNSIMPLE_EMAIL} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/dnsimple/3/rancher-compose.yml b/infra-templates/dnsimple/3/rancher-compose.yml new file mode 100644 index 0000000..462cc64 --- /dev/null +++ b/infra-templates/dnsimple/3/rancher-compose.yml @@ -0,0 +1,46 @@ +# notemplating +.catalog: + name: "DNSimple DNS" + version: "v0.6.0-rancher2" + description: "Rancher External DNS service powered by DNSimple. Requires Rancher version v1.1.0" + minimum_rancher_version: v1.6.0-rc1 + questions: + - variable: "DNSIMPLE_EMAIL" + label: "DNSimple Account Email Address" + description: "Email address associated with your DNSimple account" + type: "string" + required: true + - variable: "DNSIMPLE_TOKEN" + label: "DNSimple API Token" + description: "API token for your DNSimple account" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Root Domain" + description: "The domain name managed by DNSimple." + type: "string" + required: true + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds" + type: "int" + default: 60 + required: false + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the root domain name) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +dnsimple: + health_check: + port: 1000 + interval: 15000 + unhealthy_threshold: 2 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/dnsimple/config.yml b/infra-templates/dnsimple/config.yml index 0f1b5e0..ddb531e 100644 --- a/infra-templates/dnsimple/config.yml +++ b/infra-templates/dnsimple/config.yml @@ -1,7 +1,7 @@ name: DNSimple DNS description: | Rancher External DNS service powered by DNSimple -version: v0.6.0-rancher1 +version: v0.6.0-rancher2 category: External DNS labels: io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/infra-templates/dnsupdate-rfc2136/0/rancher-compose.yml b/infra-templates/dnsupdate-rfc2136/0/rancher-compose.yml index f22e043..d9f8fec 100644 --- a/infra-templates/dnsupdate-rfc2136/0/rancher-compose.yml +++ b/infra-templates/dnsupdate-rfc2136/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.5.0-rancher1" description: "Rancher External DNS service powered by any RFC2136 compatible DNS" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "RFC2136_HOST" label: "Domain Name Server IP" diff --git a/infra-templates/dnsupdate-rfc2136/1/rancher-compose.yml b/infra-templates/dnsupdate-rfc2136/1/rancher-compose.yml index fb43d3e..c57a32f 100644 --- a/infra-templates/dnsupdate-rfc2136/1/rancher-compose.yml +++ b/infra-templates/dnsupdate-rfc2136/1/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.6.0-rancher1" description: "Rancher External DNS service powered by any RFC2136 compatible DNS server. Requires Rancher version v1.1.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.2.0-pre4-rc1 questions: - variable: "RFC2136_HOST" label: "DNS Server IP" diff --git a/infra-templates/dnsupdate-rfc2136/2/rancher-compose.yml b/infra-templates/dnsupdate-rfc2136/2/rancher-compose.yml index a6e60dc..3e782ca 100644 --- a/infra-templates/dnsupdate-rfc2136/2/rancher-compose.yml +++ b/infra-templates/dnsupdate-rfc2136/2/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v0.6.2-rancher1" description: "Rancher External DNS service powered by any RFC2136 compatible DNS server. Requires Rancher version v1.1.0" minimum_rancher_version: v1.2.0-pre4-rc1 + maximum_rancher_version: v1.5.99 questions: - variable: "RFC2136_HOST" label: "DNS Server IP" diff --git a/infra-templates/dnsupdate-rfc2136/3/README.md b/infra-templates/dnsupdate-rfc2136/3/README.md new file mode 100644 index 0000000..fdae2e7 --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/3/README.md @@ -0,0 +1,52 @@ +## DNS Update (RFC2136) + +Rancher External DNS service powered by any RFC2136 compatible DNS server + +#### Changelog + +##### v0.6.2 + +* Adds support for disabling/enforcing external DNS on the host and service level using labels +* Adds support for insecure DNS Updates +* Fixes an issue with lingering TCP keep-alive connections to the Rancher Metadata service + +#### Usage + +##### Upgrade Notes +While upgrading from a version lower than v0.6.0 the TTL configuration value should not be changed. You may change it once the upgrade has been completed. + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the same domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/dnsupdate-rfc2136/3/docker-compose.yml b/infra-templates/dnsupdate-rfc2136/3/docker-compose.yml new file mode 100644 index 0000000..b5d7215 --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/3/docker-compose.yml @@ -0,0 +1,17 @@ +rfc2136dns: + image: rancher/external-dns:v0.6.2 + command: -provider=rfc2136 + expose: + - 1000 + environment: + RFC2136_HOST: ${RFC2136_HOST} + RFC2136_PORT: ${RFC2136_PORT} + RFC2136_TSIG_KEYNAME: ${RFC2136_TSIG_KEYNAME} + RFC2136_TSIG_SECRET: ${RFC2136_TSIG_SECRET} + RFC2136_INSECURE: ${RFC2136_INSECURE} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/dnsupdate-rfc2136/3/rancher-compose.yml b/infra-templates/dnsupdate-rfc2136/3/rancher-compose.yml new file mode 100644 index 0000000..b3f2441 --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/3/rancher-compose.yml @@ -0,0 +1,63 @@ +# notemplating +.catalog: + name: "DNS Update (RFC2136)" + version: "v0.6.2-rancher2" + description: "Rancher External DNS service powered by any RFC2136 compatible DNS server. Requires Rancher version v1.1.0" + minimum_rancher_version: v1.6.0-rc1 + questions: + - variable: "RFC2136_HOST" + label: "DNS Server IP" + description: "Server IP or Hostname" + type: "string" + required: true + - variable: "RFC2136_PORT" + label: "DNS Server Port" + description: "Server port" + type: "string" + required: true + default: "53" + - variable: "RFC2136_INSECURE" + description: "Disables TSIG authentication for DNS Update requests" + label: "Insecure DNS Update" + required: true + default: false + type: "boolean" + - variable: "RFC2136_TSIG_KEYNAME" + label: "TSIG Key Name" + description: "Name of the TSIG key used for authenticating with the DNS server" + type: "string" + required: false + - variable: "RFC2136_TSIG_SECRET" + label: "TSIG Key" + description: "TSIG secret key used for authenticating with the DNS server (HMAC-MD5, base64 encoded)" + type: "string" + required: false + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds" + type: "int" + default: 60 + required: false + - variable: "ROOT_DOMAIN" + label: "Zone name" + description: "The name of an existing zone in which to create the records." + type: "string" + required: true + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the zone/domain name) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +rfc2136dns: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/dnsupdate-rfc2136/4/README.md b/infra-templates/dnsupdate-rfc2136/4/README.md new file mode 100644 index 0000000..9ad24a2 --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/4/README.md @@ -0,0 +1,60 @@ +## DNS Update (RFC2136) + +Rancher External DNS service powered by any RFC2136 compatible DNS server + +#### Changelog + +##### v0.6.2 + +* Adds support for disabling/enforcing external DNS on the host and service level using labels +* Adds support for insecure DNS Updates +* Fixes an issue with lingering TCP keep-alive connections to the Rancher Metadata service + +#### Usage + +##### Upgrade Notes +While upgrading from a version lower than v0.6.0 the TTL configuration value should not be changed. You may change it once the upgrade has been completed. + +##### Limitation when running the service on multiple Rancher servers + +When running multiple instances of the External DNS service configured to use the same domain name, then only one of them can run in the "Default" environment of a Rancher server instance. + +##### Supported host labels + +`io.rancher.host.external_dns_ip` +Override the IP address used in DNS records for containers running on the host. Defaults to the IP address the host is registered with in Rancher. + +`io.rancher.host.external_dns` +Accepts 'true' (default) or 'false' +When this is set to 'false' no DNS records will ever be created for containers running on this host. + +##### Supported service labels + +`io.rancher.service.external_dns` +Accepts 'always', 'never' or 'auto' (default) +- `always`: Always create DNS records for this service +- `never`: Never create DNS records for this service +- `auto`: Create DNS records for this service if it exposes ports on the host + + +`io.rancher.service.external_dns_name_template` +Accepts valid DNS name template + +By default DNS entries are named based on default template defined on dnsupdate service. +You can customize it per service by assigning `io.rancher.service.external_dns_name_template` label to each service. +dnsupdate will use this template instead of default one when creating dns record for related service. + +##### Custom DNS name template + +By default DNS entries are named `...`. +You can specify a custom name template used to construct the subdomain part (left of the domain/zone name) of the DNS records. The following placeholders are supported: + +* `%{{service_name}}` +* `%{{stack_name}}` +* `%{{environment_name}}` + +**Example:** + +`%{{stack_name}}-%{{service_name}}.statictext` + +Make sure to only use characters in static text and separators that your provider allows in DNS names. diff --git a/infra-templates/dnsupdate-rfc2136/4/docker-compose.yml b/infra-templates/dnsupdate-rfc2136/4/docker-compose.yml new file mode 100644 index 0000000..f9f0bbf --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/4/docker-compose.yml @@ -0,0 +1,17 @@ +rfc2136dns: + image: rancher/external-dns:v0.7.2 + command: -provider=rfc2136 + expose: + - 1000 + environment: + RFC2136_HOST: ${RFC2136_HOST} + RFC2136_PORT: ${RFC2136_PORT} + RFC2136_TSIG_KEYNAME: ${RFC2136_TSIG_KEYNAME} + RFC2136_TSIG_SECRET: ${RFC2136_TSIG_SECRET} + RFC2136_INSECURE: ${RFC2136_INSECURE} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/dnsupdate-rfc2136/4/rancher-compose.yml b/infra-templates/dnsupdate-rfc2136/4/rancher-compose.yml new file mode 100644 index 0000000..a89377d --- /dev/null +++ b/infra-templates/dnsupdate-rfc2136/4/rancher-compose.yml @@ -0,0 +1,63 @@ +# notemplating +.catalog: + name: "DNS Update (RFC2136)" + version: "v0.7.2-rancher1" + description: "Rancher External DNS service powered by any RFC2136 compatible DNS server. Requires Rancher version v1.1.0" + minimum_rancher_version: v1.6.0-rc1 + questions: + - variable: "RFC2136_HOST" + label: "DNS Server IP" + description: "Server IP or Hostname" + type: "string" + required: true + - variable: "RFC2136_PORT" + label: "DNS Server Port" + description: "Server port" + type: "string" + required: true + default: "53" + - variable: "RFC2136_INSECURE" + description: "Disables TSIG authentication for DNS Update requests" + label: "Insecure DNS Update" + required: true + default: false + type: "boolean" + - variable: "RFC2136_TSIG_KEYNAME" + label: "TSIG Key Name" + description: "Name of the TSIG key used for authenticating with the DNS server" + type: "string" + required: false + - variable: "RFC2136_TSIG_SECRET" + label: "TSIG Key" + description: "TSIG secret key used for authenticating with the DNS server (HMAC-MD5, base64 encoded)" + type: "string" + required: false + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds" + type: "int" + default: 60 + required: false + - variable: "ROOT_DOMAIN" + label: "Zone name" + description: "The name of an existing zone in which to create the records." + type: "string" + required: true + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the zone/domain name) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +rfc2136dns: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/dnsupdate-rfc2136/config.yml b/infra-templates/dnsupdate-rfc2136/config.yml index 38b9a9d..0e33515 100644 --- a/infra-templates/dnsupdate-rfc2136/config.yml +++ b/infra-templates/dnsupdate-rfc2136/config.yml @@ -1,7 +1,7 @@ name: DNS Update (RFC2136) description: | Rancher External DNS service powered by any RFC2136 compatible DNS -version: v0.6.2-rancher1 +version: v0.7.2-rancher1 category: External DNS labels: io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/infra-templates/gandi-dns/0/docker-compose.yml b/infra-templates/gandi-dns/0/docker-compose.yml new file mode 100644 index 0000000..e0ce227 --- /dev/null +++ b/infra-templates/gandi-dns/0/docker-compose.yml @@ -0,0 +1,13 @@ +gandidns: + image: rancher/external-dns:v0.7.2 + command: -provider=gandi + expose: + - 1000 + environment: + GANDI_APIKEY: ${GANDI_APIKEY} + ROOT_DOMAIN: ${ROOT_DOMAIN} + NAME_TEMPLATE: ${NAME_TEMPLATE} + TTL: ${TTL} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" \ No newline at end of file diff --git a/infra-templates/gandi-dns/0/rancher-compose.yml b/infra-templates/gandi-dns/0/rancher-compose.yml new file mode 100644 index 0000000..0235be3 --- /dev/null +++ b/infra-templates/gandi-dns/0/rancher-compose.yml @@ -0,0 +1,43 @@ +# notemplating +.catalog: + name: "Gandi DNS" + version: "v0.1.0" + description: "Rancher External DNS service powered by Gandi. Requires Rancher version v1.1.0" + maintainer: "Frederic Leger " + minimum_rancher_version: v1.6.0-rc1 + #maximum_rancher_version: + questions: + - variable: "GANDI_APIKEY" + label: "Gandi API key" + description: "API key for your Gandi account" + type: "string" + required: true + - variable: "ROOT_DOMAIN" + label: "Root Domain" + description: "The domain name managed by Gandi." + type: "string" + required: true + - variable: "TTL" + label: "TTL" + description: "The resource record cache time to live (TTL), in seconds (minimum 300)" + type: "int" + default: 300 + required: false + - variable: "NAME_TEMPLATE" + label: "DNS Name Template" + description: | + Name template used to construct the subdomain part (left of the root domain name) of the DNS record names. + Supported placeholders: %{{service_name}}, %{{stack_name}}, %{{environment_name}}. + By default DNS entries will be named '...'. + type: "string" + default: "%{{service_name}}.%{{stack_name}}.%{{environment_name}}" + required: false + +gandidns: + health_check: + port: 1000 + interval: 15000 + unhealthy_threshold: 2 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/gandi-dns/catalogIcon-gandidns.jpg b/infra-templates/gandi-dns/catalogIcon-gandidns.jpg new file mode 100644 index 0000000..17d849f Binary files /dev/null and b/infra-templates/gandi-dns/catalogIcon-gandidns.jpg differ diff --git a/infra-templates/gandi-dns/config.yml b/infra-templates/gandi-dns/config.yml new file mode 100644 index 0000000..061b35b --- /dev/null +++ b/infra-templates/gandi-dns/config.yml @@ -0,0 +1,7 @@ +name: GANDI DNS +description: | + Rancher External DNS service powered by Gandi.net +version: v0.1.0 +category: External DNS +labels: + io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' \ No newline at end of file diff --git a/infra-templates/powerdns-external-dns/1/docker-compose.yml b/infra-templates/powerdns-external-dns/1/docker-compose.yml new file mode 100644 index 0000000..ec4e6c6 --- /dev/null +++ b/infra-templates/powerdns-external-dns/1/docker-compose.yml @@ -0,0 +1,14 @@ +powerdns: + image: rancher/external-dns:v0.7.1 + command: "-provider=powerdns" + expose: + - 1000 + environment: + POWERDNS_API_KEY: ${POWERDNS_API_KEY} + POWERDNS_URL: ${POWERDNS_URL} + ROOT_DOMAIN: ${ROOT_DOMAIN} + TTL: ${TTL} + labels: + io.rancher.container.pull_image: always + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/infra-templates/powerdns-external-dns/1/rancher-compose.yml b/infra-templates/powerdns-external-dns/1/rancher-compose.yml new file mode 100644 index 0000000..bbc1771 --- /dev/null +++ b/infra-templates/powerdns-external-dns/1/rancher-compose.yml @@ -0,0 +1,38 @@ +.catalog: + name: "PowerDNS External" + version: "v0.7.1" + description: Rancher External DNS service for PowerDNS. + minimum_rancher_version: v1.2.0-pre4-rc1 + uuid: powerdns-external-dns:v0.7.1 + questions: + - variable: POWERDNS_URL + label: PowerDNS URL + type: string + description: http[s] base url to PowerDNS + required: true + default: http://powerdns:8100 + - variable: POWERDNS_API_KEY + label: PowerDNS API Key + type: password + description: API Key for PowerDNS + required: true + - variable: TTL + label: TTL + description: "The resource record cache time to live (TTL), in seconds" + type: int + default: 299 + required: false + - variable: "ROOT_DOMAIN" + label: "Hosted zone name" + description: "Hosted zone name (zone has to be pre-created). DNS entries will be created for ..." + type: "string" + required: true + +powerdns: + health_check: + port: 1000 + interval: 30000 + unhealthy_threshold: 3 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/infra-templates/powerdns-external-dns/config.yml b/infra-templates/powerdns-external-dns/config.yml index bc3ae73..b7185c1 100644 --- a/infra-templates/powerdns-external-dns/config.yml +++ b/infra-templates/powerdns-external-dns/config.yml @@ -1,7 +1,7 @@ name: PowerDNS External description: | Rancher External DNS service for PowerDNS -version: v0.5.0-rancher1 +version: v0.7.1 category: External DNS labels: io.rancher.orchestration.supported: 'cattle,mesos,swarm,kubernetes' diff --git a/kubernetes-templates/MongoDB/0/mongo-controller.yaml b/kubernetes-templates/MongoDB/0/mongo-controller.yaml index f956a5e..ee6e38a 100644 --- a/kubernetes-templates/MongoDB/0/mongo-controller.yaml +++ b/kubernetes-templates/MongoDB/0/mongo-controller.yaml @@ -9,23 +9,42 @@ spec: template: spec: containers: + - image: husseingalal/mongo-k8s-config:v0.2.0 + name: mongo-config + volumeMounts: + - mountPath: /opt/rancher/bin + name: utility + stdin: true + tty: true - name: mongo-sec - image: husseingalal/mongo-k8s + image: mongo:3.4 ports: - containerPort: 27017 volumeMounts: - - name: mongo-ephermal-storage + - name: mongo-datadir mountPath: /data/db + - mountPath: /opt/rancher/bin + name: utility command: - - /run.sh + - /opt/rancher/bin/run.sh - mongod - "--replSet" - rs0 - "--smallfiles" - "--noprealloc" + env: + - name: PRIMARY + value: "false" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP volumes: - - name: mongo-ephermal-storage - emptyDir: {} + - name: mongo-datadir + hostPath: + path: ${mongo_volume} + - name: utility + emptyDir: {} metadata: labels: secondary: "true" diff --git a/kubernetes-templates/MongoDB/0/mongo-master.yaml b/kubernetes-templates/MongoDB/0/mongo-master.yaml index 8e99fe1..437d9cb 100644 --- a/kubernetes-templates/MongoDB/0/mongo-master.yaml +++ b/kubernetes-templates/MongoDB/0/mongo-master.yaml @@ -9,33 +9,49 @@ spec: - port: 27017 targetPort: 27017 selector: - name: mongo-master + name: mongo-primary --- apiVersion: v1 kind: Pod metadata: labels: - name: mongo-master - name: mongo-master + name: mongo-primary + name: mongo-primary spec: containers: - - name: mongo-master - image: "husseingalal/mongo-k8s" + - name: mongo-config + image: husseingalal/mongo-k8s-config:v0.2.0 + volumeMounts: + - mountPath: /opt/rancher/bin + name: utility + stdin: true + tty: true + - name: mongo-primary + image: mongo:3.4 env: - - name: PRIMARY - value: "true" + - name: PRIMARY + value: "true" + - name: POD_IP + valueFrom: + fieldRef: + fieldPath: status.podIP ports: - containerPort: 27017 command: - - /run.sh + - /opt/rancher/bin/run.sh - mongod - "--replSet" - rs0 - "--smallfiles" - "--noprealloc" volumeMounts: + - mountPath: /opt/rancher/bin + name: utility - mountPath: /data/db - name: mongo-primary-ephermal-storage + name: mongo-datadir volumes: - - name: mongo-primary-ephermal-storage - emptyDir: {} + - name: mongo-datadir + hostPath: + path: ${mongo_volume} + - name: utility + emptyDir: {} diff --git a/kubernetes-templates/MongoDB/0/rancher-compose.yml b/kubernetes-templates/MongoDB/0/rancher-compose.yml index cc33791..0e1e90f 100644 --- a/kubernetes-templates/MongoDB/0/rancher-compose.yml +++ b/kubernetes-templates/MongoDB/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: MongoDB version: 3.2-rancher1 description: MongoDB Replica Set + maximum_rancher_version: v1.3.99 questions: - variable: "sec_no" label: "Number of Secondary nodes" @@ -9,3 +10,8 @@ type: int default: 2 description: "should be even number" + - variable: "mongo_volume" + label: "hostpath volume for mongodb" + required: true + type: string + default: "/data/db" diff --git a/kubernetes-templates/Prometheus/0/rancher-compose.yml b/kubernetes-templates/Prometheus/0/rancher-compose.yml index ab749f6..beeb6af 100644 --- a/kubernetes-templates/Prometheus/0/rancher-compose.yml +++ b/kubernetes-templates/Prometheus/0/rancher-compose.yml @@ -4,6 +4,7 @@ description: "Prometheus Monitoring Solution" uuid: prometheus-1 minimum_rancher_version: v0.56.0 + maximum_rancher_version: v1.3.99 questions: - variable: "cattle_config_url" label: "Rancher Server URL" diff --git a/kubernetes-templates/cassandra/0/rancher-compose.yml b/kubernetes-templates/cassandra/0/rancher-compose.yml index 17df724..13463bb 100644 --- a/kubernetes-templates/cassandra/0/rancher-compose.yml +++ b/kubernetes-templates/cassandra/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: "K8s Example Cassandra" version: "1.0.0" description: "" + maximum_rancher_version: v1.3.99 questions: - variable: "NODE_COUNT" label: "Initial number of Cassandra nodes" diff --git a/kubernetes-templates/cloud9/0/rancher-compose.yml b/kubernetes-templates/cloud9/0/rancher-compose.yml index f8ddeaa..fae9d2c 100644 --- a/kubernetes-templates/cloud9/0/rancher-compose.yml +++ b/kubernetes-templates/cloud9/0/rancher-compose.yml @@ -1,9 +1,10 @@ .catalog: name: Cloud9 description: | - (Experimental) Cloud 9 SDK + (Experimental) Cloud 9 SDK version: 3.0-k8s1 minimum_rancher_version: v1.0.0 + maximum_rancher_version: v1.3.99 maintainer: "Raul Sanchez " uuid: cloud9-0 questions: diff --git a/kubernetes-templates/ghost/0/rancher-compose.yml b/kubernetes-templates/ghost/0/rancher-compose.yml index 59e429a..04c0654 100644 --- a/kubernetes-templates/ghost/0/rancher-compose.yml +++ b/kubernetes-templates/ghost/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: Ghost version: 0.7.8-rancher1 description: Open source publishing platform + maximum_rancher_version: v1.3.99 questions: - variable: "mysql_root_pass" label: "MySQL root password" diff --git a/kubernetes-templates/guestbook/0/rancher-compose.yml b/kubernetes-templates/guestbook/0/rancher-compose.yml index 8ed50bd..db5627c 100644 --- a/kubernetes-templates/guestbook/0/rancher-compose.yml +++ b/kubernetes-templates/guestbook/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: "K8s Guestbook" version: "1.0.0" description: "It's a guestbook, I guess" + maximum_rancher_version: v1.3.99 questions: - variable: "SERVICE_NAME" label: "Service Name" diff --git a/kubernetes-templates/heapster/0/rancher-compose.yml b/kubernetes-templates/heapster/0/rancher-compose.yml index 48e770b..040d493 100644 --- a/kubernetes-templates/heapster/0/rancher-compose.yml +++ b/kubernetes-templates/heapster/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: Heapster Grafana InfluxDB version: canary-rancher1 description: A cluster-wide aggregator of monitoring and event data. + maximum_rancher_version: v1.3.99 questions: - variable: "GRAFANA_PORT" label: "Node port for Grafana" diff --git a/kubernetes-templates/kafka/0/zk-rc.yml b/kubernetes-templates/kafka/0/kafka-rc.yml similarity index 100% rename from kubernetes-templates/kafka/0/zk-rc.yml rename to kubernetes-templates/kafka/0/kafka-rc.yml diff --git a/kubernetes-templates/kafka/0/zk-service.yml b/kubernetes-templates/kafka/0/kafka-service.yml similarity index 100% rename from kubernetes-templates/kafka/0/zk-service.yml rename to kubernetes-templates/kafka/0/kafka-service.yml diff --git a/kubernetes-templates/kafka/0/rancher-compose.yml b/kubernetes-templates/kafka/0/rancher-compose.yml index 06fa8eb..258ceb8 100644 --- a/kubernetes-templates/kafka/0/rancher-compose.yml +++ b/kubernetes-templates/kafka/0/rancher-compose.yml @@ -4,6 +4,7 @@ description: | (Experimental) Apache Kafka cluster. minimum_rancher_version: v0.59.0 + maximum_rancher_version: v1.3.99 maintainer: "Raul Sanchez " uuid: kafka-0 questions: diff --git a/kubernetes-templates/kafka/1/README.md b/kubernetes-templates/kafka/1/README.md new file mode 100644 index 0000000..1bab12c --- /dev/null +++ b/kubernetes-templates/kafka/1/README.md @@ -0,0 +1,33 @@ +# Apache Kafka (Experimental) + +### Info: + + This template creates, scale in and scale out a multinodes kafka broker cluster on top of k8s. The configuration is generated with confd from k8s. + Cluster size are variable after deployment, and get reconfigured. + + +### Usage: + + Select Apache Kafka from catalog. + + Enter the number of nodes, mem and refresh interval for the kafka cluster. + + Change the following kafka default parameters, if you need: + +- kafka_name="kafka" # kafka k8s service and rc name. +- kafka_namespace="kafka" # kafka k8s namespace +- kafka_scale=3 # kafka scale to deploy. +- kafka_mem=512 # kafka broker memory. +- kafka_log_dir="/opt/kafka/logs" # Kafka log dir. +- kafka_log_retention="168" # kafka log retention. +- kafka_num_partitions="1" # Kafka partitions number +- kafka_delete_topics="false" # kafka delete topics +- kafka_pub_ip= < true | false > # Advertise public ip to zookeeper. +- zk_link="kafka-zk/zk" # zookeeper namespace/service to connect to. + + Click deploy. + + Kafka can now be accessed over the Rancher network. + + Note: When you scale the cluster, zero downtime is not guaranteed..yet.. + diff --git a/kubernetes-templates/kafka/1/kafka-rc.yml b/kubernetes-templates/kafka/1/kafka-rc.yml new file mode 100644 index 0000000..25d6139 --- /dev/null +++ b/kubernetes-templates/kafka/1/kafka-rc.yml @@ -0,0 +1,77 @@ +apiVersion: v1 +kind: ReplicationController +metadata: + name: "${kafka_name}" + namespace: "${kafka_namespace}" + labels: + name: "${kafka_name}" +spec: + replicas: ${kafka_scale} + selector: + name: "${kafka_name}" + template: + metadata: + labels: + name: "${kafka_name}" + spec: + containers: + - name: "broker-conf" + image: "rawmind/k8s-kafka:0.10.2.0-1" + volumeMounts: + - mountPath: "/opt/tools" + name: "broker-conf" + ports: + imagePullPolicy: "IfNotPresent" + - name: "broker-volume" + image: "rawmind/alpine-volume:0.0.2-1" + env: + - name: SERVICE_UID + value: "10003" + - name: SERVICE_GID + value: "10003" + - name: SERVICE_VOLUME + value: "${kafka_log_dir}" + - name: KEEP_ALIVE + value: "1" + volumeMounts: + - mountPath: "${kafka_log_dir}" + name: "broker-data" + ports: + imagePullPolicy: "IfNotPresent" + - name: "broker-service" + image: "rawmind/alpine-kafka:0.10.2.0-2" + env: + - name: JVMFLAGS + value: "-Xmx${kafka_mem}m -Xms${kafka_mem}m" + - name: CONFD_INTERVAL + value: "${kafka_interval}" + - name: KAFKA_ZK_SERVICE + value: "${zk_link}" + - name: KAFKA_DELETE_TOPICS + value: "${kafka_delete_topics}" + - name: KAFKA_LOG_DIRS + value: "${kafka_log_dir}" + - name: KAFKA_LOG_RETENTION_HOURS + value: "${kafka_log_retention}" + - name: KAFKA_NUM_PARTITIONS + value: "${kafka_num_partitions}" + - name: ADVERTISE_PUB_IP + value: "${kafka_pub_ip}" + - name: POD_NAMESPACE + value: "${kafka_namespace}" + volumeMounts: + - mountPath: "${kafka_log_dir}" + name: "broker-data" + - mountPath: "/opt/tools" + name: "broker-conf" + ports: + - containerPort: 9092 + name: "broker-client" + protocol: "TCP" + imagePullPolicy: "IfNotPresent" + restartPolicy: "Always" + volumes: + - name: "broker-data" + emptyDir: {} + - name: "broker-conf" + emptyDir: {} \ No newline at end of file diff --git a/kubernetes-templates/kafka/1/kafka-service.yml b/kubernetes-templates/kafka/1/kafka-service.yml new file mode 100644 index 0000000..0a6371a --- /dev/null +++ b/kubernetes-templates/kafka/1/kafka-service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: "${kafka_name}" + labels: + name: "${kafka_name}" +spec: + ports: + - port: 9092 + targetPort: 9092 + name: "broker-client" + protocol: "TCP" + selector: + name: "${kafka_name}" + clusterIP: "None" diff --git a/kubernetes-templates/kafka/1/rancher-compose.yml b/kubernetes-templates/kafka/1/rancher-compose.yml new file mode 100644 index 0000000..1dda912 --- /dev/null +++ b/kubernetes-templates/kafka/1/rancher-compose.yml @@ -0,0 +1,95 @@ +.catalog: + name: Kafka + version: 0.10.2.0-k8s + description: | + (Experimental) Apache Kafka cluster. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: kafka-0 + questions: + - variable: "kafka_name" + description: "Name of kafka rc and service." + label: "K8s rc name:" + required: true + default: "kafka" + type: "string" + - variable: "kafka_namespace" + description: "Name of kafka namespace." + label: "K8s namespace:" + required: true + default: "default" + type: "string" + - variable: "kafka_scale" + description: "Number of brokers nodes. Note: Recommended an odd number" + label: "Broker Nodes:" + required: true + default: 3 + type: "int" + - variable: "kafka_mem" + description: "Amount of memory to config brokers." + label: "Broker Memory (mb):" + required: true + default: 1024 + type: "string" + - variable: "kafka_log_dir" + description: "Broker volume to log data" + label: "Broker log volume:" + required: true + default: "/opt/kafka/logs" + type: "string" + - variable: "kafka_log_retention" + description: "Broker log retention in hours" + label: "Broker log retention (h):" + required: true + default: "168" + type: "int" + - variable: "kafka_num_partitions" + description: "Number of broker partitions" + label: "Broker partitions:" + required: true + default: "1" + type: "int" + - variable: "kafka_delete_topics" + label: "Kafka delete topics:" + description: | + Enable delete topics in kafka. + default: false + required: true + type: enum + options: + - false + - true + - variable: "kafka_interval" + description: "Interval to poll/apply configuration changes. 0 to disable" + label: "Broker Interval (s):" + required: true + default: 60 + type: "int" + - variable: "kafka_pub_ip" + description: "Advertise local and host public ip" + label: "Broker public ip:" + default: false + required: true + type: enum + options: + - false + - true + - variable: "zk_link" + description: | + Choose the Zookeeper service to use. + It's really recommended a dedicated zookeeper service just for Kafka. + label: "Zookeeper stack/service" + default: "default/zookeeper" + required: true + type: "service" +broker: + scale: ${kafka_scale} + retain_ip: true + health_check: + port: 9092 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + diff --git a/kubernetes-templates/kafka/2/README.md b/kubernetes-templates/kafka/2/README.md new file mode 100644 index 0000000..1bab12c --- /dev/null +++ b/kubernetes-templates/kafka/2/README.md @@ -0,0 +1,33 @@ +# Apache Kafka (Experimental) + +### Info: + + This template creates, scale in and scale out a multinodes kafka broker cluster on top of k8s. The configuration is generated with confd from k8s. + Cluster size are variable after deployment, and get reconfigured. + + +### Usage: + + Select Apache Kafka from catalog. + + Enter the number of nodes, mem and refresh interval for the kafka cluster. + + Change the following kafka default parameters, if you need: + +- kafka_name="kafka" # kafka k8s service and rc name. +- kafka_namespace="kafka" # kafka k8s namespace +- kafka_scale=3 # kafka scale to deploy. +- kafka_mem=512 # kafka broker memory. +- kafka_log_dir="/opt/kafka/logs" # Kafka log dir. +- kafka_log_retention="168" # kafka log retention. +- kafka_num_partitions="1" # Kafka partitions number +- kafka_delete_topics="false" # kafka delete topics +- kafka_pub_ip= < true | false > # Advertise public ip to zookeeper. +- zk_link="kafka-zk/zk" # zookeeper namespace/service to connect to. + + Click deploy. + + Kafka can now be accessed over the Rancher network. + + Note: When you scale the cluster, zero downtime is not guaranteed..yet.. + diff --git a/kubernetes-templates/kafka/2/kafka-rc.yml b/kubernetes-templates/kafka/2/kafka-rc.yml new file mode 100644 index 0000000..306fd1a --- /dev/null +++ b/kubernetes-templates/kafka/2/kafka-rc.yml @@ -0,0 +1,77 @@ +apiVersion: v1 +kind: ReplicationController +metadata: + name: "${kafka_name}" + namespace: "${kafka_namespace}" + labels: + name: "${kafka_name}" +spec: + replicas: ${kafka_scale} + selector: + name: "${kafka_name}" + template: + metadata: + labels: + name: "${kafka_name}" + spec: + containers: + - name: "broker-conf" + image: "rawmind/k8s-kafka:0.10.2.0-1" + volumeMounts: + - mountPath: "/opt/tools" + name: "broker-conf" + ports: + imagePullPolicy: "IfNotPresent" + - name: "broker-volume" + image: "rawmind/alpine-volume:0.0.2-1" + env: + - name: SERVICE_UID + value: "10003" + - name: SERVICE_GID + value: "10003" + - name: SERVICE_VOLUME + value: "${kafka_log_dir}" + - name: KEEP_ALIVE + value: "1" + volumeMounts: + - mountPath: "${kafka_log_dir}" + name: "broker-data" + ports: + imagePullPolicy: "IfNotPresent" + - name: "broker-service" + image: "rawmind/alpine-kafka:0.10.2.1" + env: + - name: JVMFLAGS + value: "-Xmx${kafka_mem}m -Xms${kafka_mem}m" + - name: CONFD_INTERVAL + value: "${kafka_interval}" + - name: KAFKA_ZK_SERVICE + value: "${zk_link}" + - name: KAFKA_DELETE_TOPICS + value: "${kafka_delete_topics}" + - name: KAFKA_LOG_DIRS + value: "${kafka_log_dir}" + - name: KAFKA_LOG_RETENTION_HOURS + value: "${kafka_log_retention}" + - name: KAFKA_NUM_PARTITIONS + value: "${kafka_num_partitions}" + - name: ADVERTISE_PUB_IP + value: "${kafka_pub_ip}" + - name: POD_NAMESPACE + value: "${kafka_namespace}" + volumeMounts: + - mountPath: "${kafka_log_dir}" + name: "broker-data" + - mountPath: "/opt/tools" + name: "broker-conf" + ports: + - containerPort: 9092 + name: "broker-client" + protocol: "TCP" + imagePullPolicy: "IfNotPresent" + restartPolicy: "Always" + volumes: + - name: "broker-data" + emptyDir: {} + - name: "broker-conf" + emptyDir: {} \ No newline at end of file diff --git a/kubernetes-templates/kafka/2/kafka-service.yml b/kubernetes-templates/kafka/2/kafka-service.yml new file mode 100644 index 0000000..0a6371a --- /dev/null +++ b/kubernetes-templates/kafka/2/kafka-service.yml @@ -0,0 +1,15 @@ +apiVersion: v1 +kind: Service +metadata: + name: "${kafka_name}" + labels: + name: "${kafka_name}" +spec: + ports: + - port: 9092 + targetPort: 9092 + name: "broker-client" + protocol: "TCP" + selector: + name: "${kafka_name}" + clusterIP: "None" diff --git a/kubernetes-templates/kafka/2/rancher-compose.yml b/kubernetes-templates/kafka/2/rancher-compose.yml new file mode 100644 index 0000000..46d835c --- /dev/null +++ b/kubernetes-templates/kafka/2/rancher-compose.yml @@ -0,0 +1,95 @@ +.catalog: + name: Kafka + version: 0.10.2.1-k8s + description: | + (Experimental) Apache Kafka cluster. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: kafka-0 + questions: + - variable: "kafka_name" + description: "Name of kafka rc and service." + label: "K8s rc name:" + required: true + default: "kafka" + type: "string" + - variable: "kafka_namespace" + description: "Name of kafka namespace." + label: "K8s namespace:" + required: true + default: "default" + type: "string" + - variable: "kafka_scale" + description: "Number of brokers nodes. Note: Recommended an odd number" + label: "Broker Nodes:" + required: true + default: 3 + type: "int" + - variable: "kafka_mem" + description: "Amount of memory to config brokers." + label: "Broker Memory (mb):" + required: true + default: 1024 + type: "string" + - variable: "kafka_log_dir" + description: "Broker volume to log data" + label: "Broker log volume:" + required: true + default: "/opt/kafka/logs" + type: "string" + - variable: "kafka_log_retention" + description: "Broker log retention in hours" + label: "Broker log retention (h):" + required: true + default: "168" + type: "int" + - variable: "kafka_num_partitions" + description: "Number of broker partitions" + label: "Broker partitions:" + required: true + default: "1" + type: "int" + - variable: "kafka_delete_topics" + label: "Kafka delete topics:" + description: | + Enable delete topics in kafka. + default: false + required: true + type: enum + options: + - false + - true + - variable: "kafka_interval" + description: "Interval to poll/apply configuration changes. 0 to disable" + label: "Broker Interval (s):" + required: true + default: 60 + type: "int" + - variable: "kafka_pub_ip" + description: "Advertise local and host public ip" + label: "Broker public ip:" + default: false + required: true + type: enum + options: + - false + - true + - variable: "zk_link" + description: | + Choose the Zookeeper service to use. + It's really recommended a dedicated zookeeper service just for Kafka. + label: "Zookeeper stack/service" + default: "default/zookeeper" + required: true + type: "service" +broker: + scale: ${kafka_scale} + retain_ip: true + health_check: + port: 9092 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + diff --git a/kubernetes-templates/kafka/config.yml b/kubernetes-templates/kafka/config.yml index 061b88b..adc60a9 100644 --- a/kubernetes-templates/kafka/config.yml +++ b/kubernetes-templates/kafka/config.yml @@ -1,7 +1,7 @@ name: Apache Kafka description: | (Experimental) Kafka cluster -version: 0.10.0.1-k8s +version: 0.10.2.1-k8s category: Clustering maintainer: "Raul Sanchez " minimum_rancher_version: v0.59.0 diff --git a/kubernetes-templates/minecraft/0/rancher-compose.yml b/kubernetes-templates/minecraft/0/rancher-compose.yml index bcbed8f..d285474 100644 --- a/kubernetes-templates/minecraft/0/rancher-compose.yml +++ b/kubernetes-templates/minecraft/0/rancher-compose.yml @@ -6,6 +6,7 @@ re-assembling of raw materials. It may be an elaborate parody of the Australian economy. maintainer: "Rancher" + maximum_rancher_version: v1.3.99 questions: - variable: REPLICAS default: 1 diff --git a/kubernetes-templates/rabbitmq/0/rancher-compose.yml b/kubernetes-templates/rabbitmq/0/rancher-compose.yml index 3cfc00e..1466228 100644 --- a/kubernetes-templates/rabbitmq/0/rancher-compose.yml +++ b/kubernetes-templates/rabbitmq/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: RabbitMQ version: 3.6.0-rancher1 description: A reliable, distributed messaging broker + maximum_rancher_version: v1.3.99 questions: - variable: REPLICAS default: 1 diff --git a/kubernetes-templates/redis/0/rancher-compose.yml b/kubernetes-templates/redis/0/rancher-compose.yml index 531b435..cc9fffc 100644 --- a/kubernetes-templates/redis/0/rancher-compose.yml +++ b/kubernetes-templates/redis/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: Redis version: 2.8.23-rancher1 description: A highly-available in-memory data structure store + maximum_rancher_version: v1.3.99 questions: - variable: "REDIS_REPLICAS" label: "Initial number of Redis nodes" diff --git a/kubernetes-templates/spark/0/rancher-compose.yml b/kubernetes-templates/spark/0/rancher-compose.yml index dc2a01a..7885398 100644 --- a/kubernetes-templates/spark/0/rancher-compose.yml +++ b/kubernetes-templates/spark/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: 0.1.0-rancher1 description: "Spark cluster" maintainer: "Rancher" + maximum_rancher_version: v1.3.99 questions: - variable: "SPARK_WORKER_REPLICAS" type: "string" diff --git a/kubernetes-templates/sysdig-cloud/0/rancher-compose.yml b/kubernetes-templates/sysdig-cloud/0/rancher-compose.yml index 0ba053c..7490797 100644 --- a/kubernetes-templates/sysdig-cloud/0/rancher-compose.yml +++ b/kubernetes-templates/sysdig-cloud/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: "Sysdig Cloud" version: "0.1" description: "Container-Native Application and Infrastructure Monitoring" + maximum_rancher_version: v1.3.99 questions: - variable: "SDC_ACCESS_KEY" label: "Sysdig Cloud access key" diff --git a/kubernetes-templates/traefik/0/rancher-compose.yml b/kubernetes-templates/traefik/0/rancher-compose.yml index 898ede7..f7e6bed 100644 --- a/kubernetes-templates/traefik/0/rancher-compose.yml +++ b/kubernetes-templates/traefik/0/rancher-compose.yml @@ -4,6 +4,7 @@ description: | Traefik load balancer. minimum_rancher_version: v0.59.0 + maximum_rancher_version: v1.3.99 maintainer: "German Ramos " uuid: traefik-0 questions: diff --git a/kubernetes-templates/weave-cloud/0/rancher-compose.yml b/kubernetes-templates/weave-cloud/0/rancher-compose.yml index abb620f..1b94efa 100644 --- a/kubernetes-templates/weave-cloud/0/rancher-compose.yml +++ b/kubernetes-templates/weave-cloud/0/rancher-compose.yml @@ -3,6 +3,7 @@ description: | Weave Cloud is a add-on to Kubernetes which provides Continuous Delivery, along with hosted Prometheus Monitoring and a visual dashboard for exploring & debugging microservices version: "latest" + maximum_rancher_version: v1.3.99 questions: - variable: "WEAVE_CLOUD_SERVICE_TOKEN" description: "Service token for your Weave Cloud instance, get one at https://cloud.weave.works" diff --git a/kubernetes-templates/wordpress/0/rancher-compose.yml b/kubernetes-templates/wordpress/0/rancher-compose.yml index 626029e..2052deb 100644 --- a/kubernetes-templates/wordpress/0/rancher-compose.yml +++ b/kubernetes-templates/wordpress/0/rancher-compose.yml @@ -2,6 +2,7 @@ name: "K8s Example Wordpress" version: "1.0.0" description: "" + maximum_rancher_version: v1.3.99 questions: - variable: "WP_PASSWORD" label: "Mysql database password" diff --git a/kubernetes-templates/zookeeper/0/rancher-compose.yml b/kubernetes-templates/zookeeper/0/rancher-compose.yml index ca20b63..56e4103 100644 --- a/kubernetes-templates/zookeeper/0/rancher-compose.yml +++ b/kubernetes-templates/zookeeper/0/rancher-compose.yml @@ -4,6 +4,7 @@ description: | (Experimental) Apache Zookeeper cluster. minimum_rancher_version: v0.59.0 + maximum_rancher_version: v1.3.99 maintainer: "Raul Sanchez " uuid: zk-0 questions: diff --git a/kubernetes-templates/zookeeper/1/rancher-compose.yml b/kubernetes-templates/zookeeper/1/rancher-compose.yml index 5917aca..e8b8d53 100644 --- a/kubernetes-templates/zookeeper/1/rancher-compose.yml +++ b/kubernetes-templates/zookeeper/1/rancher-compose.yml @@ -4,6 +4,7 @@ description: | (Experimental) Apache Zookeeper cluster. minimum_rancher_version: v0.59.0 + maximum_rancher_version: v1.3.99 maintainer: "Raul Sanchez " uuid: zk-0 questions: diff --git a/kubernetes-templates/zookeeper/1/zk-rc.yml b/kubernetes-templates/zookeeper/1/zk-rc.yml index 739d5a6..3bbaa4f 100644 --- a/kubernetes-templates/zookeeper/1/zk-rc.yml +++ b/kubernetes-templates/zookeeper/1/zk-rc.yml @@ -17,7 +17,7 @@ spec: spec: containers: - name: "zk-conf" - image: "rawmind/k8s-zk:3.4.8-10" + image: "rawmind/k8s-zk:3.4.9" volumeMounts: - mountPath: "/opt/tools" name: "zk-conf" @@ -40,7 +40,7 @@ spec: ports: imagePullPolicy: "IfNotPresent" - name: "zk-service" - image: "rawmind/alpine-zk:3.4.9" + image: "rawmind/alpine-zk:3.4.9-3" env: - name: JVMFLAGS value: "-Xmx${zk_mem}m -Xms${zk_mem}m" diff --git a/kubernetes-templates/zookeeper/1/zk-service.yml b/kubernetes-templates/zookeeper/1/zk-service.yml index 438bb3c..2ce431c 100644 --- a/kubernetes-templates/zookeeper/1/zk-service.yml +++ b/kubernetes-templates/zookeeper/1/zk-service.yml @@ -21,3 +21,4 @@ spec: protocol: "TCP" selector: name: "${zk_name}" + diff --git a/kubernetes-templates/zookeeper/config.yml b/kubernetes-templates/zookeeper/config.yml index a33c707..4aa9875 100644 --- a/kubernetes-templates/zookeeper/config.yml +++ b/kubernetes-templates/zookeeper/config.yml @@ -4,4 +4,4 @@ description: | version: 3.4.9-k8s1 category: Clustering maintainer: "Raul Sanchez " -projectURL: https://github.com/rawmind0/alpine-zk +projectURL: https://github.com/rawmind0/alpine-zk \ No newline at end of file diff --git a/machine-templates/cloudca/0/checksum b/machine-templates/cloudca/0/checksum new file mode 100644 index 0000000..c4025ab --- /dev/null +++ b/machine-templates/cloudca/0/checksum @@ -0,0 +1 @@ +bea9144384d543353b75ed0bea872fbe diff --git a/machine-templates/cloudca/0/rancher-compose.yml b/machine-templates/cloudca/0/rancher-compose.yml new file mode 100644 index 0000000..b6e9a2e --- /dev/null +++ b/machine-templates/cloudca/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: cloudca + version: "v1.0.1" diff --git a/machine-templates/cloudca/0/uiUrl b/machine-templates/cloudca/0/uiUrl new file mode 100644 index 0000000..884a3c2 --- /dev/null +++ b/machine-templates/cloudca/0/uiUrl @@ -0,0 +1 @@ +https://objects-east.cloud.ca/v1/5ef827605f884961b94881e928e7a250/rancher-ui-driver/v1.0.0/component.js diff --git a/machine-templates/cloudca/0/url b/machine-templates/cloudca/0/url new file mode 100644 index 0000000..6fecb2a --- /dev/null +++ b/machine-templates/cloudca/0/url @@ -0,0 +1 @@ +https://objects-east.cloud.ca/v1/5ef827605f884961b94881e928e7a250/docker-machine-driver-cloudca/v1.0.1/docker-machine-driver-cloudca_v1.0.1_linux-amd64.zip diff --git a/machine-templates/cloudca/1/checksum b/machine-templates/cloudca/1/checksum new file mode 100644 index 0000000..6005709 --- /dev/null +++ b/machine-templates/cloudca/1/checksum @@ -0,0 +1 @@ +100bf1dc97f5016602457ba397433561 diff --git a/machine-templates/cloudca/1/rancher-compose.yml b/machine-templates/cloudca/1/rancher-compose.yml new file mode 100644 index 0000000..405ebb3 --- /dev/null +++ b/machine-templates/cloudca/1/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: cloudca + version: "v1.0.2" diff --git a/machine-templates/cloudca/1/uiUrl b/machine-templates/cloudca/1/uiUrl new file mode 100644 index 0000000..a39e32f --- /dev/null +++ b/machine-templates/cloudca/1/uiUrl @@ -0,0 +1 @@ +https://objects-east.cloud.ca/v1/5ef827605f884961b94881e928e7a250/rancher-ui-driver/v1.0.2/component.js diff --git a/machine-templates/cloudca/1/url b/machine-templates/cloudca/1/url new file mode 100644 index 0000000..7d2343e --- /dev/null +++ b/machine-templates/cloudca/1/url @@ -0,0 +1 @@ +https://objects-east.cloud.ca/v1/5ef827605f884961b94881e928e7a250/docker-machine-driver-cloudca/v1.0.2/docker-machine-driver-cloudca_v1.0.2_linux-amd64.zip diff --git a/machine-templates/cloudca/catalogIcon-cloudca.svg b/machine-templates/cloudca/catalogIcon-cloudca.svg new file mode 100644 index 0000000..7c73c4b --- /dev/null +++ b/machine-templates/cloudca/catalogIcon-cloudca.svg @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + + + + + + + diff --git a/machine-templates/cloudca/config.yml b/machine-templates/cloudca/config.yml new file mode 100644 index 0000000..ab1cf0e --- /dev/null +++ b/machine-templates/cloudca/config.yml @@ -0,0 +1,2 @@ +name: cloudca +version: "v1.0.2" diff --git a/machine-templates/ecl/0/checksum b/machine-templates/ecl/0/checksum new file mode 100644 index 0000000..45a4f67 --- /dev/null +++ b/machine-templates/ecl/0/checksum @@ -0,0 +1 @@ +ff59f432259784194a296837069154b7 diff --git a/machine-templates/ecl/0/rancher-compose.yml b/machine-templates/ecl/0/rancher-compose.yml new file mode 100644 index 0000000..9ad663b --- /dev/null +++ b/machine-templates/ecl/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: ecl + version: "v1.0.0" diff --git a/machine-templates/ecl/0/uiUrl b/machine-templates/ecl/0/uiUrl new file mode 100644 index 0000000..130fc85 --- /dev/null +++ b/machine-templates/ecl/0/uiUrl @@ -0,0 +1 @@ +https://mittz.github.io/rancher/uidbinary/v1.0.0/component.js diff --git a/machine-templates/ecl/0/url b/machine-templates/ecl/0/url new file mode 100644 index 0000000..4b851a0 --- /dev/null +++ b/machine-templates/ecl/0/url @@ -0,0 +1 @@ +https://github.com/mittz/docker-machine-driver-ecl/releases/download/v1.0.0/docker-machine-driver-ecl-v1.0.0-linux-amd64.tar.gz diff --git a/machine-templates/ecl/catalogIcon-ecl.svg b/machine-templates/ecl/catalogIcon-ecl.svg new file mode 100644 index 0000000..4bd2cbf --- /dev/null +++ b/machine-templates/ecl/catalogIcon-ecl.svg @@ -0,0 +1,159 @@ + + + + diff --git a/machine-templates/ecl/config.yml b/machine-templates/ecl/config.yml new file mode 100644 index 0000000..330bbbd --- /dev/null +++ b/machine-templates/ecl/config.yml @@ -0,0 +1,2 @@ +name: ecl +version: "v1.0.0" diff --git a/machine-templates/interoutevdc/1/rancher-compose.yml b/machine-templates/interoutevdc/1/rancher-compose.yml new file mode 100644 index 0000000..259a888 --- /dev/null +++ b/machine-templates/interoutevdc/1/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: "interoutevdc" + version: "0.2.0" diff --git a/machine-templates/interoutevdc/1/uiUrl b/machine-templates/interoutevdc/1/uiUrl new file mode 100644 index 0000000..17f2e90 --- /dev/null +++ b/machine-templates/interoutevdc/1/uiUrl @@ -0,0 +1 @@ +https://myservices.interoute.com/rancher/component.js diff --git a/machine-templates/interoutevdc/1/url b/machine-templates/interoutevdc/1/url new file mode 100644 index 0000000..411e5ec --- /dev/null +++ b/machine-templates/interoutevdc/1/url @@ -0,0 +1 @@ +https://github.com/Interoute/docker-machine-driver-interoutevdc/releases/download/v1.1/docker-machine-driver-interoutevdc_linux-amd64.tar.gz diff --git a/machine-templates/interoutevdc/config.yml b/machine-templates/interoutevdc/config.yml index aa669ad..2024d4a 100644 --- a/machine-templates/interoutevdc/config.yml +++ b/machine-templates/interoutevdc/config.yml @@ -1,2 +1,2 @@ name: interoutevdc -version: "0.1.0" +version: "0.2.0" diff --git a/machine-templates/oneandone/0/rancher-compose.yml b/machine-templates/oneandone/0/rancher-compose.yml new file mode 100644 index 0000000..e195e5d --- /dev/null +++ b/machine-templates/oneandone/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: "oneandone" + version: "v1.1.1" \ No newline at end of file diff --git a/machine-templates/oneandone/0/uiUrl b/machine-templates/oneandone/0/uiUrl new file mode 100644 index 0000000..45fe835 --- /dev/null +++ b/machine-templates/oneandone/0/uiUrl @@ -0,0 +1 @@ +https://1and1.github.io/ui-driver-oneandone/1.0.0/component.js \ No newline at end of file diff --git a/machine-templates/oneandone/0/url b/machine-templates/oneandone/0/url new file mode 100644 index 0000000..bb05c67 --- /dev/null +++ b/machine-templates/oneandone/0/url @@ -0,0 +1 @@ +https://github.com/1and1/docker-machine-driver-oneandone/releases/download/v1.1.1/docker-machine-driver-oneandone-linux-amd64-v1.1.1.tar.gz \ No newline at end of file diff --git a/machine-templates/oneandone/catalogIcon-oneandone.png b/machine-templates/oneandone/catalogIcon-oneandone.png new file mode 100644 index 0000000..47c07ad Binary files /dev/null and b/machine-templates/oneandone/catalogIcon-oneandone.png differ diff --git a/machine-templates/oneandone/config.yml b/machine-templates/oneandone/config.yml new file mode 100644 index 0000000..393baeb --- /dev/null +++ b/machine-templates/oneandone/config.yml @@ -0,0 +1,2 @@ +name: oneandone +version: "v1.1.1" \ No newline at end of file diff --git a/machine-templates/p2pub/0/checksum b/machine-templates/p2pub/0/checksum new file mode 100644 index 0000000..23be59b --- /dev/null +++ b/machine-templates/p2pub/0/checksum @@ -0,0 +1 @@ +18a2399ee76db477053129a5928b51f8 diff --git a/machine-templates/p2pub/0/rancher-compose.yml b/machine-templates/p2pub/0/rancher-compose.yml new file mode 100644 index 0000000..2edb93d --- /dev/null +++ b/machine-templates/p2pub/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: p2pub + version: "v1.0.0" diff --git a/machine-templates/p2pub/0/uiUrl b/machine-templates/p2pub/0/uiUrl new file mode 100644 index 0000000..a2e7c5e --- /dev/null +++ b/machine-templates/p2pub/0/uiUrl @@ -0,0 +1 @@ +https://iij.github.io/ui-driver-p2pub/ui-driver/1.0.0/component.js diff --git a/machine-templates/p2pub/0/url b/machine-templates/p2pub/0/url new file mode 100644 index 0000000..9e25715 --- /dev/null +++ b/machine-templates/p2pub/0/url @@ -0,0 +1 @@ +https://github.com/iij/docker-machine-driver-p2pub/releases/download/1.0/docker-machine-driver-p2pub-linux-amd64.zip diff --git a/machine-templates/p2pub/catalogIcon-p2pub.svg b/machine-templates/p2pub/catalogIcon-p2pub.svg new file mode 100644 index 0000000..1b67b6e --- /dev/null +++ b/machine-templates/p2pub/catalogIcon-p2pub.svg @@ -0,0 +1,122 @@ + + + + diff --git a/machine-templates/p2pub/config.yml b/machine-templates/p2pub/config.yml new file mode 100644 index 0000000..12940c3 --- /dev/null +++ b/machine-templates/p2pub/config.yml @@ -0,0 +1,2 @@ +name: p2pub +version: "v1.0.0" diff --git a/machine-templates/profitbricks/0/rancher-compose.yml b/machine-templates/profitbricks/0/rancher-compose.yml new file mode 100644 index 0000000..2390058 --- /dev/null +++ b/machine-templates/profitbricks/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: "profitbricks" + version: "v1.2.3" \ No newline at end of file diff --git a/machine-templates/profitbricks/0/uiUrl b/machine-templates/profitbricks/0/uiUrl new file mode 100644 index 0000000..cb7d4fe --- /dev/null +++ b/machine-templates/profitbricks/0/uiUrl @@ -0,0 +1 @@ +https://profitbricks.github.io/ui-driver-profitbricks/docs/1.1.0/component.js \ No newline at end of file diff --git a/machine-templates/profitbricks/0/url b/machine-templates/profitbricks/0/url new file mode 100644 index 0000000..cdfad82 --- /dev/null +++ b/machine-templates/profitbricks/0/url @@ -0,0 +1 @@ +https://github.com/profitbricks/docker-machine-driver-profitbricks/releases/download/v1.2.3/docker-machine-driver-profitbricks-v1.2.3-linux-amd64.tar.gz \ No newline at end of file diff --git a/machine-templates/profitbricks/catalogIcon-profitbricks.png b/machine-templates/profitbricks/catalogIcon-profitbricks.png new file mode 100644 index 0000000..ebcac6a Binary files /dev/null and b/machine-templates/profitbricks/catalogIcon-profitbricks.png differ diff --git a/machine-templates/profitbricks/config.yml b/machine-templates/profitbricks/config.yml new file mode 100644 index 0000000..d841d79 --- /dev/null +++ b/machine-templates/profitbricks/config.yml @@ -0,0 +1,2 @@ +name: profitbricks +version: "v1.2.3" \ No newline at end of file diff --git a/machine-templates/qingcloud/0/checksum b/machine-templates/qingcloud/0/checksum new file mode 100644 index 0000000..56017a0 --- /dev/null +++ b/machine-templates/qingcloud/0/checksum @@ -0,0 +1 @@ +6891ca3791f23264ac3ca6576e856349 diff --git a/machine-templates/qingcloud/0/rancher-compose.yml b/machine-templates/qingcloud/0/rancher-compose.yml new file mode 100644 index 0000000..d11ff45 --- /dev/null +++ b/machine-templates/qingcloud/0/rancher-compose.yml @@ -0,0 +1,3 @@ +.catalog: + name: qingcloud + version: "v1.0.1" diff --git a/machine-templates/qingcloud/0/uiUrl b/machine-templates/qingcloud/0/uiUrl new file mode 100644 index 0000000..cbce490 --- /dev/null +++ b/machine-templates/qingcloud/0/uiUrl @@ -0,0 +1 @@ +http://machine-driver.oss-cn-shanghai.aliyuncs.com/qingcloud/ui/v1.0.1/component.js diff --git a/machine-templates/qingcloud/0/url b/machine-templates/qingcloud/0/url new file mode 100644 index 0000000..5bedbd5 --- /dev/null +++ b/machine-templates/qingcloud/0/url @@ -0,0 +1 @@ +http://machine-driver.oss-cn-shanghai.aliyuncs.com/qingcloud/driver/v1.0.1/docker-machine-driver-qingcloud-linux-amd64.tar.gz diff --git a/machine-templates/qingcloud/catalogIcon-qingcloud.png b/machine-templates/qingcloud/catalogIcon-qingcloud.png new file mode 100644 index 0000000..f6741b1 Binary files /dev/null and b/machine-templates/qingcloud/catalogIcon-qingcloud.png differ diff --git a/machine-templates/qingcloud/config.yml b/machine-templates/qingcloud/config.yml new file mode 100644 index 0000000..5b700af --- /dev/null +++ b/machine-templates/qingcloud/config.yml @@ -0,0 +1,2 @@ +name: qingcloud +version: "v1.0.1" diff --git a/swarm-templates/wordpress/config.yml b/swarm-templates/wordpress/config.yml index 5a68a92..c08d5e5 100644 --- a/swarm-templates/wordpress/config.yml +++ b/swarm-templates/wordpress/config.yml @@ -1,4 +1,4 @@ -name: Wordpress +name: WordPress description: | Blog tool, publishing platform and CMS version: 1.0.0-latest-rancher1 diff --git a/templates/MongoDB/2/docker-compose.yml b/templates/MongoDB/2/docker-compose.yml index 3f991d4..4819aa1 100644 --- a/templates/MongoDB/2/docker-compose.yml +++ b/templates/MongoDB/2/docker-compose.yml @@ -15,6 +15,8 @@ mongo-cluster: volumes_from: - mongo-datavolume - mongo-base + ports: + - 27017:27017/tcp mongo-base: restart: always net: none diff --git a/templates/MongoDB/3/README.md b/templates/MongoDB/3/README.md new file mode 100644 index 0000000..5d1109f --- /dev/null +++ b/templates/MongoDB/3/README.md @@ -0,0 +1,18 @@ +# MongoDB + + +### Info: + + This template creates MongoDB replica set on top of Rancher. Replica set size starts with 3 MongoDB instances, the replica set has the ability to scale up automatically when adding new instances. + + +### Usage: + + Select MongoDB from catalog. + + Enter the name of the replica set. + + Click deploy. + + MongoDB can now be accessed over the Rancher network. + diff --git a/templates/MongoDB/3/docker-compose.yml b/templates/MongoDB/3/docker-compose.yml new file mode 100644 index 0000000..98e7dd3 --- /dev/null +++ b/templates/MongoDB/3/docker-compose.yml @@ -0,0 +1,45 @@ +version: '2' +services: + mongo-cluster: + restart: always + environment: + MONGO_SERVICE_NAME: mongo-cluster + CATTLE_SCRIPT_DEBUG: ${debug} + entrypoint: /opt/rancher/bin/entrypoint.sh + command: + - --replSet + - "${replset_name}" + image: mongo:3.4 + labels: + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: mongo-base, mongo-datavolume + volumes_from: + - mongo-datavolume + - mongo-base + ports: + - 27017:27017/tcp + mongo-base: + restart: always + labels: + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + image: rancher/mongodb-conf:v0.1.1 + stdin_open: true + entrypoint: /bin/true + mongo-datavolume: + labels: + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + volumes: + - mongodata:/data/db + entrypoint: /bin/true + image: busybox +volumes: + mongodata: + driver: ${VOLUME_DRIVER} diff --git a/templates/MongoDB/3/rancher-compose.yml b/templates/MongoDB/3/rancher-compose.yml new file mode 100644 index 0000000..8c90ba7 --- /dev/null +++ b/templates/MongoDB/3/rancher-compose.yml @@ -0,0 +1,52 @@ +version: '2' +catalog: + name: "MongoDB" + version: "3.4-rancher1" + description: "MongoDB Replica Set" + uuid: mongodb-1 + minimum_rancher_version: v0.46.0 + questions: + - variable: replset_name + description: "Name of the MongoDB replicaSet" + label: "ReplicaSet Name" + type: "string" + required: true + default: "rs0" + - variable: host_label + label: "Host Label to MongoDB Tags" + description: | + Host label to use as MongoDB 'value' tag. + Example: 'database' + required: false + type: "string" + - variable: debug + description: "Enable Debug log for Mongo containers" + label: "Debug" + type: "string" + required: false + default: "" + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + - variable: mongo_scale + description: "How many containers the MongoDB will scale to?" + label: "mongo scale" + type: "int" + required: true + default: "3" +services: + mongo-cluster: + scale: ${mongo_scale} + retain_ip: true + metadata: + mongo: + yml: + replset.name: "${replset_name}" diff --git a/templates/MongoDB/config.yml b/templates/MongoDB/config.yml index 4ea53c1..31cda18 100644 --- a/templates/MongoDB/config.yml +++ b/templates/MongoDB/config.yml @@ -1,5 +1,5 @@ name: MongoDB description: | MongoDB Replica Set. -version: 3.2-rancher2 +version: "3.4-rancher1" category: Databases diff --git a/templates/Prometheus/5/README.md b/templates/Prometheus/5/README.md new file mode 100644 index 0000000..fadf442 --- /dev/null +++ b/templates/Prometheus/5/README.md @@ -0,0 +1,26 @@ +# Prometheus + +### Info: + +This template deploys a collection of monitoring services based upon the technologies listed below, once deployed you should have a monitoring platform capable of querying a wide variety of metrics that represent your environment, also included are somehandy pre-configured dashboards to get you started. + +In this catalog item, the following technologies are utilised to make this as useful as possible; + +* [Prometheus](https://github.com/prometheus/prometheus) - Used to scrape and store metrics from our data sources. +* [Prometheus Node Exporter](https://github.com/prometheus/node_exporter) - Gets host level metrics and exposes them to Prometheus. +* [cAdvisor](https://github.com/google/cadvisor) - Deploys and Exposes the cadvsior stats used by Rancher's agent container, to Prometheus. +* [Grafana](https://github.com/grafana/grafana/) - Used to visualise the data from Prometheus and InfluxDB. +* [Prometheus Rancher Exporter](https://github.com/infinityworksltd/prometheus-rancher-exporter/) - Allows Prometheus to access the Rancher API and return the status of any stack or service in the rancher environment associated with the API key used. + +The full compliment of metrics from the Rancher server itsself are now available for graphing directly in Prometheus, this is easily enabled with an environment variable. For those interested, I've documented the steps [here].(https://github.com/infinityworksltd/Guide_Rancher_Monitoring) + +All components in this stack are open source tools available in the community. All this template does is to bound them together in an easy to use package. I expect most people who find this useful will make use of this as a starting point and develop it further around their own needs. + +## Deployment: +1. Select Prometheus from the community catalog. +2. Enter the IP Address of your Rancher server (used for accessing Ranchers own metrics, optional) +3. Click deploy. + +## Usage +* Grafana will now be available on, running on port 3000. I've added a number of dashboards to help get you started. Authentication is with the default `admin/admin`. +* Prometheus will now be available, running on port 9090. Have a play around with some of the data. For more information on Prometheus, check out their [documentation](https://prometheus.io/docs/introduction/overview/). diff --git a/templates/Prometheus/5/docker-compose.yml b/templates/Prometheus/5/docker-compose.yml new file mode 100644 index 0000000..69d9481 --- /dev/null +++ b/templates/Prometheus/5/docker-compose.yml @@ -0,0 +1,72 @@ +cadvisor: + labels: + io.rancher.scheduler.global: 'true' + tty: true + image: google/cadvisor:latest + stdin_open: true + volumes: + - "/:/rootfs:ro" + - "/var/run:/var/run:rw" + - "/sys:/sys:ro" + - "/var/lib/docker/:/var/lib/docker:ro" + +node-exporter: + labels: + io.rancher.scheduler.global: 'true' + tty: true + image: prom/node-exporter:latest + stdin_open: true + +prom-conf: + tty: true + image: infinityworks/prom-conf:19 + volumes: + - /etc/prom-conf/ + net: none + +prometheus: + tty: true + image: prom/prometheus:v1.6.0 + command: -alertmanager.url=http://alertmanager:9093 -config.file=/etc/prom-conf/prometheus.yml -storage.local.path=/prometheus -web.console.libraries=/etc/prometheus/console_libraries -web.console.templates=/etc/prometheus/consoles + ports: + - 9090:9090 + labels: + io.rancher.sidekicks: prom-conf + volumes_from: + - prom-conf + volumes: + - prometheus-data:/prometheus + links: + - cadvisor:cadvisor + - node-exporter:node-exporter + - prometheus-rancher-exporter:prometheus-rancher-exporter + extra_hosts: + - "rancher-server:${RANCHER_SERVER}" + +graf-db: + tty: true + image: infinityworks/graf-db:11 + command: cat + volumes: + - /var/lib/grafana/ + net: none + +grafana: + tty: true + image: grafana/grafana:4.2.0 + ports: + - 3000:3000 + labels: + io.rancher.sidekicks: graf-db + volumes_from: + - graf-db + links: + - prometheus:prometheus + - prometheus-rancher-exporter:prometheus-rancher-exporter + +prometheus-rancher-exporter: + tty: true + labels: + io.rancher.container.create_agent: true + io.rancher.container.agent.role: environment + image: infinityworks/prometheus-rancher-exporter:v0.22.52 diff --git a/templates/Prometheus/5/rancher-compose.yml b/templates/Prometheus/5/rancher-compose.yml new file mode 100644 index 0000000..dd95c3d --- /dev/null +++ b/templates/Prometheus/5/rancher-compose.yml @@ -0,0 +1,43 @@ +.catalog: + name: "Prometheus" + version: "3.0.0" + description: "Prometheus Monitoring Solution" + uuid: prometheus-2 + minimum_rancher_version: v1.5.5 + questions: + - variable: "RANCHER_SERVER" + label: "Rancher Server" + description: "IP Address of the rancher server, no HTTP or slashes. This is only required for users that have enabled metrics to be exported by Rancher" + default: "0.0.0.0" + required: false + type: "string" + +prometheus: + scale: 1 + health_check: + port: 9090 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + +grafana: + scale: 1 + health_check: + port: 3000 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + +prometheus-rancher-exporter: + scale: 1 + health_check: + port: 9173 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 diff --git a/templates/Prometheus/config.yml b/templates/Prometheus/config.yml index cad549a..769e003 100644 --- a/templates/Prometheus/config.yml +++ b/templates/Prometheus/config.yml @@ -1,5 +1,5 @@ name: Prometheus description: | Prometheus and friends, auto-discovering monitoring solution for Rancher deployments. -version: 2.1.0 +version: 3.0.0 category: Monitoring diff --git a/templates/artifactory-oss/0/README.md b/templates/artifactory-oss/0/README.md new file mode 100644 index 0000000..c98776b --- /dev/null +++ b/templates/artifactory-oss/0/README.md @@ -0,0 +1,41 @@ +# Artifactory + +[Artifactory][artifactory] is a universal Binary Repository Manager for use by build tools (like Maven and Gradle), +dependency management tools (like Ivy and NuGet) and build servers (like Jenkins, Hudson, TeamCity and Bamboo). + +Repository managers serve two purposes: they act as highly configurable proxies between your organization and +external repositories and they also provide build servers with a deployment destination for your internally +generated artifacts. + +### Usage: + + - Select Artifactory from catalog. + - Select artifactory version. + - Select artifactory release, OSS or PRO. + - Set the params and select certificate. + + Click "Launch". + +### Notes: + +- To use the PRO version, you need to get a free trial. +- You need a certificate imported in rancher enviroment before deploy this package. +- If you use self signed certificates, you should implement [self-signed-certificates][using-self-signed-certificates] in your hosts. +- If you use http schema, you should implement [insecure-registry][insecure-registry] in your hosts. +- KNOWN LIMITATION: "SSL certificate" is required for http and https publish schema. + + +### More info: + +- [Resources][artifactory-resources] +- [Free-trial][artifactory-trial] +- [Self-signed-certificates][using-self-signed-certificates] +- [Insecure-registry][insecure-registry] + + +[artifactory]: https://www.jfrog.com/artifactory/ +[artifactory-resources]: https://www.jfrog.com/support-service/resources/ +[artifactory-trial]: https://www.jfrog.com/artifactory/free-trial/ +[using-self-signed-certificates]: https://docs.docker.com/registry/insecure/#using-self-signed-certificates +[insecure-registry]: https://docs.docker.com/registry/insecure/# Artifactory + \ No newline at end of file diff --git a/templates/artifactory-oss/0/docker-compose.yml.tpl b/templates/artifactory-oss/0/docker-compose.yml.tpl new file mode 100644 index 0000000..92260da --- /dev/null +++ b/templates/artifactory-oss/0/docker-compose.yml.tpl @@ -0,0 +1,59 @@ +version: '2' +services: + artifactory: + {{- if eq .Values.ARTIFACTORY_VERSION "OSS"}} + image: docker.bintray.io/jfrog/artifactory-oss:5.4.5 + {{- else}} + image: docker.bintray.io/jfrog/artifactory-pro:5.4.5 + {{- end}} + volumes: + - artifactory-data:/var/opt/jfrog/artifactory + environment: + - EXTRA_JAVA_OPTIONS=${EXTRA_JAVA_OPTIONS} + artifactory-rp: + image: rawmind/alpine-nginx:1.12.1-3 + external_links: + - artifactory:artifactory + environment: + NGINX_SERVER_NAME: artifactory + NGINX_SERVER_CONF: | + server { + + listen ${PUBLISH_PORT}; + server_name ~(?.+)\.${PUBLISH_NAME} ${PUBLISH_NAME}; + + set $$http_x_forwarded_proto ${PUBLISH_SCHEMA}; + + ## Application specific logs + ## access_log /var/log/nginx/oss.local-access.log timing; + ## error_log /var/log/nginx/oss.local-error.log; + + chunked_transfer_encoding on; + client_max_body_size 0; + + proxy_read_timeout 900; + proxy_pass_header Server; + proxy_cookie_path ~*^/.* /; + + location /v2 { + proxy_pass http://artifactory:8081/artifactory/api/docker/$$repo/v2/; + } + location / { + proxy_pass http://artifactory:8081/artifactory/; + } + proxy_set_header X-Artifactory-Override-Base-Url $$http_x_forwarded_proto://$$host:$$server_port; + proxy_set_header X-Forwarded-Port $$server_port; + proxy_set_header X-Forwarded-Proto $$http_x_forwarded_proto; + proxy_set_header Host $$http_host; + proxy_set_header X-Forwarded-For $$proxy_add_x_forwarded_for; + } + {{- if (.Values.PUBLISH_PORT)}} + artifactory-lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - ${PUBLISH_PORT}:${PUBLISH_PORT} + {{- end}} +volumes: + artifactory-data: + driver: ${VOLUME_DRIVER} + diff --git a/templates/artifactory-oss/0/rancher-compose.yml b/templates/artifactory-oss/0/rancher-compose.yml new file mode 100644 index 0000000..c8459aa --- /dev/null +++ b/templates/artifactory-oss/0/rancher-compose.yml @@ -0,0 +1,93 @@ +version: '2' +catalog: + name: "Artifactory" + version: "5.4.5" + description: "Artifactory is a universal Binary Repository Manager" + questions: + - variable: "ARTIFACTORY_VERSION" + label: "Version" + description: | + Select the Artifactory server version. OSS or PRO + required: true + default: "OSS" + type: enum + options: + - OSS + - PRO + - variable: "PUBLISH_SCHEMA" + description: "Publish schema" + label: "Publish schema:" + required: true + default: "https" + type: "enum" + options: + - http + - https + - variable: "PUBLISH_NAME" + label: "Publish name" + description: | + Set publish fqdn for Artifactory server. + required: true + type: "string" + default: "artifactory.local" + - variable: "PUBLISH_PORT" + label: "Publish port" + description: | + Set port if you want publish external port for Artifactory server. + required: true + type: "int" + default: 8081 + - variable: "SSL_CERT" + description: "Select SSL certificate." + label: "SSL certificate:" + required: true + default: "" + type: "certificate" + - variable: "EXTRA_JAVA_OPTIONS" + label: "Extra Java options" + description: | + type: "string" + default: "" + - variable: "VOLUME_DRIVER" + type: "string" + label: "Volume driver for Artifactory data" + description: | + Specifiy docker volume driver to use + default: "local" + required: true +services: + artifactory-lb: + scale: 1 + lb_config: + certs: [] + default_cert: ${SSL_CERT} + port_rules: + - protocol: ${PUBLISH_SCHEMA} + service: artifactory-rp + source_port: ${PUBLISH_PORT} + target_port: ${PUBLISH_PORT} + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + artifactory-rp: + scale: 1 + retain_ip: true + health_check: + port: ${PUBLISH_PORT} + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET / HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + artifactory: + scale: 1 + retain_ip: true + health_check: + port: 8081 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET / HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 diff --git a/templates/artifactory-oss/README.md b/templates/artifactory-oss/README.md new file mode 100644 index 0000000..bffd58a --- /dev/null +++ b/templates/artifactory-oss/README.md @@ -0,0 +1,9 @@ +# Artifactory + + +Artifactory is a universal Binary Repository Manager for use by build tools (like Maven and Gradle), +dependency management tools (like Ivy and NuGet) and build servers (like Jenkins, Hudson, TeamCity and Bamboo). + +Repository managers serve two purposes: they act as highly configurable proxies between your organization and +external repositories and they also provide build servers with a deployment destination for your internally +generated artifacts. \ No newline at end of file diff --git a/templates/artifactory-oss/catalogIcon-artifactory.svg b/templates/artifactory-oss/catalogIcon-artifactory.svg new file mode 100644 index 0000000..ab68b61 --- /dev/null +++ b/templates/artifactory-oss/catalogIcon-artifactory.svg @@ -0,0 +1,634 @@ + + + + + + diff --git a/templates/artifactory-oss/config.yml b/templates/artifactory-oss/config.yml new file mode 100644 index 0000000..53f9498 --- /dev/null +++ b/templates/artifactory-oss/config.yml @@ -0,0 +1,6 @@ +name: Artifactory +description: | + Artifactory is a universal Binary Repository Manager +version: 5.4.5 +category: Repository + diff --git a/templates/autospotting/0/README.md b/templates/autospotting/0/README.md new file mode 100644 index 0000000..1a25458 --- /dev/null +++ b/templates/autospotting/0/README.md @@ -0,0 +1,11 @@ +# Autospotting + +### Info +This service builds upon the open source autospotting at [https://github.com/cristim/autospotting](https://github.com/cristim/autospotting) + +This has been turned into a Rancher catalog entry with a couple of minor tweaks and the removal of the requirement to run it as a lambda function, it now runs as a docker container. + +Autospotting works by taking a tag that you specify and adding it to an AWS Auto-Scaling Group with a value of true. + +The container will then run and check for on-demand instances and replace them with cheap spot instances. This is a gradual process and will only replace one host in an ASG at a time. + diff --git a/templates/autospotting/0/docker-compose.yml b/templates/autospotting/0/docker-compose.yml new file mode 100644 index 0000000..19568f4 --- /dev/null +++ b/templates/autospotting/0/docker-compose.yml @@ -0,0 +1,13 @@ +aws-spot-instance-helper: + image: chrisurwin/autospotting:v0.1.0 + tty: true + labels: + io.rancher.container.pull_image: always + environment: + AWS_ACCESS_KEY_ID: "${AWS_ACCESS_KEY_ID}" + AWS_SECRET_ACCESS_KEY: "${AWS_SECRET_ACCESS_KEY}" + regions: "${regions}" + min_on_demand_number: "${min_on_demand_number}" + min_on_demand_percentage: "${min_on_demand_percentage}" + allowed_instance_types: "${allowed_instance_types}" + tag_name: "${tag_name}" \ No newline at end of file diff --git a/templates/autospotting/0/rancher-compose.yml b/templates/autospotting/0/rancher-compose.yml new file mode 100644 index 0000000..a9a45ea --- /dev/null +++ b/templates/autospotting/0/rancher-compose.yml @@ -0,0 +1,51 @@ +.catalog: + name: "Autospotting" + version: "v0.1.0" + description: "Autospotting" + minimum_rancher_version: v1.0.0 + questions: + - variable: "AWS_ACCESS_KEY_ID" + description: "AWS Access Key" + label: "AWS Access Key" + required: true + type: "string" + - variable: "AWS_SECRET_ACCESS_KEY" + description: "AWS Secret Key" + label: "Access Secret" + required: true + type: "string" + - variable: "regions" + description: "Regions where it should be activated (comma or whitespace separated list, also supports globs), by default it runs on all regions. Example: 'eu-*,us-east-1" + label: "AWS Regions" + required: false + type: "string" + - variable: "min_on_demand_number" + description: "On-demand capacity (as absolute number) ensured to be running in each of your groups" + label: "Minimum on demand number" + required: false + type: "string" + - variable: "min_on_demand_percentage" + description: "On-demand capacity (percentage of the total number of instances in the group) ensured to be running in each of your groups. Defaults to 0" + label: "Minimum on demand percentage" + required: false + type: "string" + - variable: "allowed_instance_types" + description: "If specified, the spot instances will have a specific instance type" + label: "Allowed instance types" + required: false + type: "string" + - variable: "tag_name" + description: "If specified you can tag instances with a specific tag to process, default is spot-enabled" + label: "Tag name" + required: false + type: "string" + +aws-spot-instance-helper: + health_check: + port: 9777 + interval: 2000 + unhealthy_threshold: 3 + strategy: recreate + response_timeout: 2000 + request_line: GET /ping HTTP/1.0 + healthy_threshold: 2 \ No newline at end of file diff --git a/templates/autospotting/catalogIcon-autospotting.svg b/templates/autospotting/catalogIcon-autospotting.svg new file mode 100644 index 0000000..b88cdbb --- /dev/null +++ b/templates/autospotting/catalogIcon-autospotting.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/autospotting/config.yml b/templates/autospotting/config.yml new file mode 100644 index 0000000..ed1ae21 --- /dev/null +++ b/templates/autospotting/config.yml @@ -0,0 +1,5 @@ +name: AutoSpotting +description: | + Replaces AWS On-Demand instances with cheaper Spot-Instances where possible +version: v0.1.0 +category: Infrastructure Services \ No newline at end of file diff --git a/templates/avi/0/README.md b/templates/avi/0/README.md new file mode 100644 index 0000000..907b75e --- /dev/null +++ b/templates/avi/0/README.md @@ -0,0 +1,32 @@ +Avi Vantage Platform Load Balancer Provider +======== + +## About Avi Vantage Platform +The [Avi Vantage Platform](https://avinetworks.com/software-load-balancer-for-any-cloud/) is built on software-defined architectural principles to create a centrally managed pool of distributed load balancers to deliver application services close to the applications. + +## About this provider +This provider load balances Rancher services using Avi Vantage Platform Load Balancer. It uses REST API to update the Avi controller which enables the Avi Service Engines to load balance the Rancher Services. + +## Usage + +1. Deploy the stack for this provider from Rancher Community Catalog. + While deploying, you need to give the username, password (optional, + read below), Avi Controller IP address, Avi Controller Port, the + Cloud name where Virtual Services and Pools are created. +2. Create Virtual Services using Avi Controller console. Make sure you + create VS in given cloud in Avi. Leave the Virtual Service pool as + empty. Configure any policies or rules for Virtual Service. +3. Create services in Rancher with public host port mapping and adding + label `io.rancher.service.external_lb.endpoint` with value as Virtual + Service name created in previous step. You can scale out/in the + service or stop the service and the changes will get reflected on Avi + Controller and Service Engine. + +### Using Rancher Secrets for Avi Password + +Optionally, you can use the Rancher Secrets to pass the Avi controller +password instead of using environment variable. +1. Run the Rancher Secrets service before deploying this provider stack. +2. Create a secret named "avi-creds". +3. While deploying the Avi provider stack, use the "avi-creds" secret + for Avi Provider service. diff --git a/templates/avi/0/docker-compose.yml b/templates/avi/0/docker-compose.yml new file mode 100644 index 0000000..83469d9 --- /dev/null +++ b/templates/avi/0/docker-compose.yml @@ -0,0 +1,16 @@ +avi: + image: rancher/external-lb:v0.3.2 + command: -provider=Avi + expose: + - 1000 + environment: + AVI_USER: ${AVI_USER} + AVI_PASSWORD: ${AVI_PASSWORD} + AVI_CONTROLLER_ADDR: ${AVI_CONTROLLER_ADDR} + AVI_CONTROLLER_PORT: ${AVI_CONTROLLER_PORT} + AVI_SSL_VERIFY: ${AVI_SSL_VERIFY} + AVI_CLOUD_NAME: ${AVI_CLOUD_NAME} + LB_TARGET_RANCHER_SUFFIX: ${LB_TARGET_RANCHER_SUFFIX} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-lb" diff --git a/templates/avi/0/rancher-compose.yml b/templates/avi/0/rancher-compose.yml new file mode 100644 index 0000000..1916234 --- /dev/null +++ b/templates/avi/0/rancher-compose.yml @@ -0,0 +1,52 @@ +.catalog: + name: Avi Vantange Platform Load Balancer + version: "v0.3.2-rancher1" + description: "External LB service powered by Avi Vantage Platform" + minimum_rancher_version: v1.1.0 + questions: + - variable: "AVI_USER" + label: "Avi account username" + description: "User name for your account on Avi Controller" + type: "string" + required: true + - variable: "AVI_PASSWORD" + label: "Avi user account password" + description: "Password for your account on Avi Controller" + type: "string" + required: false + - variable: "AVI_CONTROLLER_ADDR" + label: "Avi Controller IP Address" + description: "IP Address of the Avi Controller" + type: "string" + required: true + - variable: "AVI_CONTROLLER_PORT" + label: "Avi Controller Port (Optional)" + description: "Port on which Avi Controller is listening for API requests" + type: "string" + required: false + - variable: "AVI_CLOUD_NAME" + label: "Avi Cloud Name (Optional)" + description: "Name of Avi Cloud in which Virtual Services are created" + required: false + type: "string" + - variable: "AVI_SSL_VERIFY" + label: "Avi SSL Verify (Optional)" + description: "SSL certificate validation while connecting to Avi Controller" + required: false + type: "boolean" + default: false + - variable: "LB_TARGET_RANCHER_SUFFIX" + label: "Avi pool name suffix" + description: "Pool names in Avi created/updated by Rancher will have this suffix" + type: "string" + required: true + default: rancher.internal + +avi: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 2 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/templates/avi/catalogIcon-avi.png b/templates/avi/catalogIcon-avi.png new file mode 100644 index 0000000..69c3cde Binary files /dev/null and b/templates/avi/catalogIcon-avi.png differ diff --git a/templates/avi/config.yml b/templates/avi/config.yml new file mode 100644 index 0000000..562d7c0 --- /dev/null +++ b/templates/avi/config.yml @@ -0,0 +1,5 @@ +name: Avi Vantage Platform +description: | + External LB service powered by Avi Vantage Platform +version: v0.3.2-rancher1 +category: Load Balancing diff --git a/templates/aws-elbv1/1/README.md b/templates/aws-elbv1/1/README.md new file mode 100644 index 0000000..bc7a9c5 --- /dev/null +++ b/templates/aws-elbv1/1/README.md @@ -0,0 +1,15 @@ +AWS ELB Classic External LB Service +========== + +#### About ELB Classic Load Balancers +The [Classic Load Balancer](https://aws.amazon.com/elasticloadbalancing/classicloadbalancer/) option in AWS routes traffic based on application or network level information and is ideal for simple load balancing of traffic across multiple EC2 instances. + +#### About this service +Load balance Rancher services using Elastic Load Balancing. +This service keeps existing ELB Classic load balancers updated with the EC2 instances on which Rancher services that have one or more exposed ports and the label `io.rancher.service.external_lb.endpoint` are running on. + +#### Usage + +1. Deploy this stack +2. Using the AWS Console create a Classic ELB load balancer with one or more listeners and configure it according to your applications requirements. Configure the listener(s) with an instance protocol and port matching that of the Rancher service that you want to forward traffic to. +3. Create or update your service to expose host ports that match the configuration of the ELB listener(s). Add the service label `io.rancher.service.external_lb.endpoint` using as value the name of the ELB load balancer you created. diff --git a/templates/aws-elbv1/1/docker-compose.yml b/templates/aws-elbv1/1/docker-compose.yml new file mode 100644 index 0000000..6af3d03 --- /dev/null +++ b/templates/aws-elbv1/1/docker-compose.yml @@ -0,0 +1,14 @@ +elbv1: + image: rancher/external-lb:v0.3.0 + command: -provider=elbv1 + expose: + - 1000 + environment: + ELBV1_AWS_ACCESS_KEY: ${ELBV1_AWS_ACCESS_KEY} + ELBV1_AWS_SECRET_KEY: ${ELBV1_AWS_SECRET_KEY} + ELBV1_AWS_REGION: ${ELBV1_AWS_REGION} + ELBV1_AWS_VPCID: ${ELBV1_AWS_VPCID} + ELBV1_USE_PRIVATE_IP: ${ELBV1_USE_PRIVATE_IP} + labels: + io.rancher.container.create_agent: "true" + io.rancher.container.agent.role: "external-dns" diff --git a/templates/aws-elbv1/1/rancher-compose.yml b/templates/aws-elbv1/1/rancher-compose.yml new file mode 100644 index 0000000..a654e5b --- /dev/null +++ b/templates/aws-elbv1/1/rancher-compose.yml @@ -0,0 +1,41 @@ +.catalog: + name: ELB Classic Load Balancer + version: "v0.3.0-rancher1" + description: "External LB service powered by AWS Elastic Load Balancing" + minimum_rancher_version: v1.1.0 + questions: + - variable: "ELBV1_AWS_ACCESS_KEY" + label: "AWS Access Key ID" + description: "Access key ID for your AWS account" + type: "string" + required: false + - variable: "ELBV1_AWS_SECRET_KEY" + label: "AWS Secret Access Key" + description: "Secret access key for your AWS account" + type: "string" + required: false + - variable: "ELBV1_AWS_REGION" + label: "AWS Region (Optional)" + description: "The region for load balancers and EC2 instances in this Rancher environment. Defaults to the region of the instance the service will be running on." + type: "string" + required: false + - variable: "ELBV1_AWS_VPCID" + label: "AWS VPC ID (Optional)" + description: "The VPC for the load balancers and EC2 instances in this Rancher environment. Defaults to the VPC of the instance the service will be running on." + type: "string" + required: false + - variable: "ELBV1_USE_PRIVATE_IP" + label: "EC2 Private IP Lookup" + description: "If your EC2 instances are registered in Rancher with their private IP addresses, then this must be set to true." + required: true + type: "boolean" + default: false + +elbv1: + health_check: + port: 1000 + interval: 5000 + unhealthy_threshold: 2 + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/templates/aws-elbv1/config.yml b/templates/aws-elbv1/config.yml index f62d9e3..9aec5d1 100644 --- a/templates/aws-elbv1/config.yml +++ b/templates/aws-elbv1/config.yml @@ -1,5 +1,5 @@ name: ELB Classic Load Balancer description: | External LB service powered by AWS Elastic Load Balancing -version: v0.2.1-rancher1 +version: v0.3.0-rancher1 category: Load Balancing diff --git a/templates/bitbucket/0/docker-compose.yml b/templates/bitbucket/0/docker-compose.yml new file mode 100644 index 0000000..307ba36 --- /dev/null +++ b/templates/bitbucket/0/docker-compose.yml @@ -0,0 +1,24 @@ +version: '2' + +services: + + bitbucket: + image: atlassian/bitbucket-server:5.1 + volumes_from: + - bitbucket-data + ports: + - ${BITBUCKET_PORT}:7990 + labels: + io.rancher.sidekicks: bitbucket-data + io.rancher.container.hostname_override: container_name + + bitbucket-data: + image: atlassian/bitbucket-server:5.1 + entrypoint: + - /bin/true + volumes: + - /var/atlassian/application-data/bitbucket + labels: + io.rancher.container.start_once: 'true' + io.rancher.container.hostname_override: container_name + diff --git a/templates/bitbucket/0/rancher-compose.yml b/templates/bitbucket/0/rancher-compose.yml new file mode 100644 index 0000000..a72ea51 --- /dev/null +++ b/templates/bitbucket/0/rancher-compose.yml @@ -0,0 +1,24 @@ +version: '2' + +catalog: + + name: bitbucket + version: 0.0.1 + description: Git Server + questions: + - variable: BITBUCKET_PORT + label: Port + default: 80 + required: true + type: int + +services: + + bitbucket: + scale: 1 + start_on_create: true + + bitbucket-data: + scale: 1 + start_on_create: true + diff --git a/templates/bitbucket/README.md b/templates/bitbucket/README.md new file mode 100644 index 0000000..d9617f2 --- /dev/null +++ b/templates/bitbucket/README.md @@ -0,0 +1,4 @@ +# Bitbucket + +Read more in the official Bitbucket Docker [Documentation](https://bitbucket.org/atlassian/docker-atlassian-bitbucket-server). + diff --git a/templates/bitbucket/catalogIcon-bitbucket.svg b/templates/bitbucket/catalogIcon-bitbucket.svg new file mode 100644 index 0000000..77536e3 --- /dev/null +++ b/templates/bitbucket/catalogIcon-bitbucket.svg @@ -0,0 +1,104 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/bitbucket/config.yml b/templates/bitbucket/config.yml new file mode 100644 index 0000000..9799142 --- /dev/null +++ b/templates/bitbucket/config.yml @@ -0,0 +1,6 @@ +name: bitbucket +description: Git Server +version: 0.0.1 +category: Versioning +projectURL: https://github.com/ellerbrock/rancher-collection + diff --git a/templates/consul-registrator/1/docker-compose.yml b/templates/consul-registrator/1/docker-compose.yml index 1a281b4..8a43a9b 100644 --- a/templates/consul-registrator/1/docker-compose.yml +++ b/templates/consul-registrator/1/docker-compose.yml @@ -44,7 +44,7 @@ consul: - -client=0.0.0.0 environment: CONSUL_LOCAL_CONFIG: "{\"leave_on_terminate\": true, \"datacenter\": \"${consul_datacenter}\"}" - CONSUL_BIND_INTERFACE: eth0 + CONSUL_BIND_INTERFACE: ${consul_bind_interface} volumes_from: - consul-data log_opt: {} diff --git a/templates/consul-registrator/1/rancher-compose.yml b/templates/consul-registrator/1/rancher-compose.yml index 3caabff..fd38c67 100644 --- a/templates/consul-registrator/1/rancher-compose.yml +++ b/templates/consul-registrator/1/rancher-compose.yml @@ -13,3 +13,8 @@ type: "string" required: true default: "dc1" + - variable: consul_bind_interface + label: "Consul Bind Interface" + type: "string" + required: true + default: "eth0" diff --git a/templates/consul/1/README.md b/templates/consul/1/README.md new file mode 100644 index 0000000..f5d7c92 --- /dev/null +++ b/templates/consul/1/README.md @@ -0,0 +1,32 @@ +# Consul Cluster + + +### Info: + + This template creates 3 Consul nodes that uses RPC encryption with TLS and gossip encryption to secure connection between consul cluster nodes, configuration is generated with confd from Rancher metadata. + + TLS is used to verify the authenticity of the servers and the clients using the verify_incoming and verify_outgoing options. + + The variables used in this template include: + +- Certificates and keys for Consul nodes. +- CA certificate. +- 16-bytes, Base64 encoded gossip encryption key. +- Web UI option. +- ACL options. + + +The templates uses two Docker images one as the main image and the other one is the sidekick: + +- consul. +- [consul-config](https://github.com/galal-hussein/consul-config). + +### Usage: + + Select Consul from catalog. + + Enter the certificates and keys for consul nodes, ca certificates, and the encryption key. + + Click deploy. + + The consul nodes will be bound to the Rancher managed network IPs. diff --git a/templates/consul/1/docker-compose.yml.tpl b/templates/consul/1/docker-compose.yml.tpl new file mode 100644 index 0000000..5f86e0f --- /dev/null +++ b/templates/consul/1/docker-compose.yml.tpl @@ -0,0 +1,41 @@ +consul-base: + image: consul:0.8.1 + entrypoint: + - /opt/rancher/bin/start_consul.sh + net: "container:consul" + labels: + io.rancher.container.hostname_override: container_name + volumes_from: + - consul-data +consul-data: + image: alpine:latest + entrypoint: + - /bin/true + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + volumes: + - /var/consul + - /opt/rancher/bin + - /opt/rancher/ssl + - /opt/rancher/config + net: none +consul: + image: husseingalal/consul-config:0.1.2 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: consul-base,consul-data + volumes_from: + - consul-data +{{- if eq .Values.ui "true"}} +consul-lb: + ports: + - 8500:8500/tcp + expose: + - 8500:8500/tcp + tty: true + image: rancher/load-balancer-service + links: + - consul:consul-base + stdin_open: true +{{- end }} diff --git a/templates/consul/1/rancher-compose.yml b/templates/consul/1/rancher-compose.yml new file mode 100644 index 0000000..2f2d885 --- /dev/null +++ b/templates/consul/1/rancher-compose.yml @@ -0,0 +1,93 @@ +.catalog: + name: "Consul" + description: "Secure Consul cluster" + version: "0.8-rancher1" + upgrade_from: 0.0.0-rancher1 + uuid: consul-0 + questions: + - variable: ca_crt + label: "CA certificate" + type: "multiline" + required: true + - variable: consul1_key + label: "First consul key" + type: "multiline" + required: true + - variable: consul1_crt + label: "First consul certificate" + type: "multiline" + required: true + - variable: consul2_key + label: "Second consul key" + type: "multiline" + required: true + - variable: consul2_crt + label: "Second consul certificate" + type: "multiline" + required: true + - variable: consul3_key + label: "Third consul key" + type: "multiline" + required: true + - variable: consul3_crt + label: "Third consul certificate" + type: "multiline" + required: true + - variable: gossip_key + label: "Communication gossip key" + type: "multiline" + required: true + - variable: enable_acl + label: "ACL Access" + type: "boolean" + required: true + default: false + - variable: acl_default_policy + label: "ACL Default Policy" + type: "enum" + options: + - "allow" + - "deny" + default: "allow" + required: true + - variable: acl_down_policy + label: "ACL Down Policy" + type: "enum" + options: + - "allow" + - "deny" + default: "allow" + required: true + - variable: acl_master_token + label: "ACL Master Token" + type: "string" + default: "" + required: false + - variable: ui + label: "Enable UI" + type: "boolean" + default: false + required: true +consul: + scale: 3 + metadata: + ca.crt: | + ${ca_crt} + consul1.crt: | + ${consul1_crt} + consul1.key: | + ${consul1_key} + consul2.crt: | + ${consul2_crt} + consul2.key: | + ${consul2_key} + consul3.crt: | + ${consul3_crt} + consul3.key: | + ${consul3_key} + enc.key: "${gossip_key}" + acl.enabled: "${enable_acl}" + acl.default_policy: "${acl_default_policy}" + acl.down_policy: "${acl_down_policy}" + acl.master_token: "${acl_master_token}" + ui.enabled: ${ui} diff --git a/templates/consul/config.yml b/templates/consul/config.yml index 6955566..369848f 100644 --- a/templates/consul/config.yml +++ b/templates/consul/config.yml @@ -1,5 +1,5 @@ name: Consul Cluster description: | Consul cluster -version: 0.6-rancher1 +version: 0.8-rancher1 category: Clustering diff --git a/templates/datadog/5/docker-compose.yml b/templates/datadog/5/docker-compose.yml index 48b7a64..268dac2 100755 --- a/templates/datadog/5/docker-compose.yml +++ b/templates/datadog/5/docker-compose.yml @@ -8,7 +8,7 @@ datadog-init: io.rancher.container.start_once: 'true' io.rancher.container.pull_image: always datadog-agent: - image: datadog/docker-dd-agent:11.0.5110 + image: datadog/docker-dd-agent:11.0.5123 entrypoint: /opt/rancher/entrypoint-wrapper.py command: - supervisord diff --git a/templates/datadog/5/rancher-compose.yml b/templates/datadog/5/rancher-compose.yml index 9dc37b4..c76b77a 100755 --- a/templates/datadog/5/rancher-compose.yml +++ b/templates/datadog/5/rancher-compose.yml @@ -1,6 +1,6 @@ .catalog: name: "Datadog" - version: "1.1.0-11.0.5110" + version: "1.1.0-11.0.5123" description: "Real-time performance tracking and visualization of your container-based application deployment" minimum_rancher_version: v1.2.0 questions: diff --git a/templates/datadog/config.yml b/templates/datadog/config.yml index 79ac921..4e682a4 100755 --- a/templates/datadog/config.yml +++ b/templates/datadog/config.yml @@ -1,7 +1,7 @@ name: Datadog description: | Real-time performance tracking and visualization of your container-based application deployment -version: 1.1.0-11.0.5110 +version: 1.1.0-11.0.5123 category: Monitoring maintainer: "Jan Bruder " license: The MIT License diff --git a/templates/drone/1/rancher-compose.yml b/templates/drone/1/rancher-compose.yml index 6c6c692..bbf3641 100644 --- a/templates/drone/1/rancher-compose.yml +++ b/templates/drone/1/rancher-compose.yml @@ -18,7 +18,7 @@ type: "password" required: true label: "Remote Config" - description: "Must be the full connection string. see http://readme.drone.io/setup/overview/ for more info" + description: "Must be the full connection string. See http://readme.drone.io/admin/ for more info" - variable: "public_port" type: "int" required: true @@ -38,7 +38,7 @@ label: "Database Config" type: "password" required: true - description: "Must be full db string. The hostname for the DB will be 'database'. See http://readme.drone.io/setup/overview/ for more info" + description: "Must be full db string. The hostname for the DB will be 'database'. See http://docs.drone.io/databases.html for more info" - variable: "database_service" type: "service" label: "Database Service" diff --git a/templates/drone/2/README.md b/templates/drone/2/README.md new file mode 100644 index 0000000..9bddc3a --- /dev/null +++ b/templates/drone/2/README.md @@ -0,0 +1,19 @@ +# Drone + +### Info: + +This template creates an instance of Drone CI server 0.5 along with selectable number of agents to perform the builds. + +### Usage: + +Select the Drone template from the catalog. Provide the following information: + +1. Publish port +2. Agents scale +3. Drone secret +4. Run mode. debug | release +3. Remote driver and config. (Ie. GitHub) +4. Database driver and config. (Ie. sqlite) + + +See [Drone documentation](http://readme.drone.io/admin) for complete information. \ No newline at end of file diff --git a/templates/drone/2/docker-compose.yml.tpl b/templates/drone/2/docker-compose.yml.tpl new file mode 100644 index 0000000..c0c5612 --- /dev/null +++ b/templates/drone/2/docker-compose.yml.tpl @@ -0,0 +1,79 @@ +version: '2' +services: + agent: + image: drone/drone:0.5 + environment: + DRONE_SERVER: ws://drone:8000/ws/broker + DRONE_SECRET: ${drone_secret} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + links: + - server:drone + command: + - agent + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + server: + image: drone/drone:0.5 + environment: + GIN_MODE: ${gin_mode} + DRONE_SECRET: ${drone_secret} + DRONE_OPEN: ${drone_open} +{{- if (.Values.drone_admin)}} + DRONE_ADMIN: ${drone_admin} +{{- end}} +{{- if (.Values.drone_orgs)}} + DRONE_ORGS: ${drone_orgs} +{{- end}} +{{- if eq .Values.drone_driver "github"}} + DRONE_GITHUB: true + DRONE_GITHUB_CLIENT: ${drone_driver_client} + DRONE_GITHUB_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "bitbucket"}} + DRONE_BITBUCKET: true + DRONE_BITBUCKET_CLIENT: ${drone_driver_client} + DRONE_BITBUCKET_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "gitlab"}} + DRONE_GITLAB: true + DRONE_GITLAB_CLIENT: ${drone_driver_secret} + DRONE_GITLAB_SECRET: ${drone_driver_secret} + DRONE_GITLAB_URL: ${drone_driver_url} +{{- end}} +{{- if eq .Values.drone_driver "gogs"}} + DRONE_GOGS: true + DRONE_GOGS_URL: ${drone_driver_url} +{{- end}} +{{- if ne .Values.database_driver "sqlite"}} + DRONE_DATABASE_DRIVER: ${database_driver} + DRONE_DATABASE_DATASOURCE: ${database_source} +{{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if eq .Values.database_driver "sqlite"}} + io.rancher.sidekicks: server-volume + volumes_from: + - server-volume + server-volume: + image: rawmind/alpine-volume:0.0.2-1 + environment: + SERVICE_GID: '0' + SERVICE_UID: '0' + SERVICE_VOLUME: /var/lib/drone + network_mode: none + volumes: + - /var/lib/drone + labels: + io.rancher.container.start_once: 'true' + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- end}} + lb: + image: rancher/load-balancer-service + ports: + - ${host_port}:8000/tcp + links: + - server:server diff --git a/templates/drone/2/rancher-compose.yml b/templates/drone/2/rancher-compose.yml new file mode 100644 index 0000000..8a3e527 --- /dev/null +++ b/templates/drone/2/rancher-compose.yml @@ -0,0 +1,123 @@ +version: 2 +catalog: + name: Drone + version: 0.5-rancher1 + upgrade_from: 0.5-rancher1 + description: | + Drone CI Server ref http://readme.drone.io/admin/installation-guide/ + questions: + - variable: host_port + label: Drone server Host Port + description: | + Port that will be exposed on service creation + required: true + default: 8000 + type: int + - variable: agent_scale + label: Drone agent scale + description: Drone agent scale to deploy + required: true + default: 1 + type: int + - variable: drone_secret + label: Server and agents sercret. + description: Server and agents secret to be communicate. http://readme.drone.io/admin/user-registration/ + type: password + required: true + - variable: gin_mode + label: Run mode + description: "Drone run mode, GIN_MODE" + type: enum + default: "release" + options: + - "release" + - "debug" + required: true + - variable: drone_open + label: Open registration + description: | + Users self register. http://readme.drone.io/admin/user-registration/ + required: true + default: true + type: enum + options: + - true + - false + - variable: drone_admin + label: Drone Admin + description: List of admins for drone coma seperated. http://readme.drone.io/admin/user-admins/ + type: string + required: false + - variable: drone_orgs + label: Organizations + description: Comman seperated list of org that can access drone. http://readme.drone.io/admin/user-registration/ + type: string + required: false + - variable: "drone_driver" + type: "enum" + required: true + label: "Remote Driver" + default: "github" + description: "Remote Git and Auth scheme. ref http://readme.drone.io/admin" + options: + - github + - bitbucket + - gitlab + - gogs + - variable: drone_driver_client + label: Remote Driver client + description: "Client key from remote driver. Required for github, bitbucket and gitlab." + type: string + required: false + - variable: drone_driver_secret + label: Remote Driver secret + description: "Secret key from remote driver. Required for github, bitbucket and gitlab." + type: string + required: false + - variable: drone_driver_url + label: Remote Driver url + description: "Remote Driver server url. Required for gitlab and gogs, http://readme.drone.io/admin" + type: string + required: false + - variable: database_driver + label: Database Driver + description: "Database driver. If sqlite, additional volume would be mounted at /var/lib/drone." + type: enum + default: "sqlite" + options: + - "sqlite" + - "mysql" + - "postgres" + required: true + - variable: "database_source" + type: "string" + label: "Database source" + description: "Database datasource. Required if database driver is mysql or postgres, http://readme.drone.io/admin/database-engines/" + required: false +services: + agent: + scale: ${agent_scale} + start_on_create: true + server: + scale: 1 + start_on_create: true + health_check: + port: 8000 + interval: 2000 + unhealthy_threshold: 3 + strategy: recreate + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 + lb: + scale: 1 + start_on_create: true + load_balancer_config: + haproxy_config: {} + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate diff --git a/templates/drone/3/README.md b/templates/drone/3/README.md new file mode 100644 index 0000000..12fe3c0 --- /dev/null +++ b/templates/drone/3/README.md @@ -0,0 +1,19 @@ +# Drone + +### Info: + +This template creates an instance of Drone CI server 0.6 along with selectable number of agents to perform the builds. + +### Usage: + +Select the Drone template from the catalog. Provide the following information: + +1. Publish port +2. Agents scale +3. Drone secret +4. Run mode. debug | release +3. Remote driver and config. (Ie. GitHub) +4. Database driver and config. (Ie. sqlite) + + +See [Drone documentation](http://readme.drone.io/admin) for complete information. \ No newline at end of file diff --git a/templates/drone/3/docker-compose.yml.tpl b/templates/drone/3/docker-compose.yml.tpl new file mode 100644 index 0000000..0536ed9 --- /dev/null +++ b/templates/drone/3/docker-compose.yml.tpl @@ -0,0 +1,79 @@ +version: '2' +services: + agent: + image: drone/drone:0.7.1 + environment: + DRONE_SERVER: ws://drone:8000/ws/broker + DRONE_SECRET: ${drone_secret} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + links: + - server:drone + command: + - agent + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + server: + image: drone/drone:0.7.1 + environment: + GIN_MODE: ${gin_mode} + DRONE_SECRET: ${drone_secret} + DRONE_OPEN: ${drone_open} +{{- if (.Values.drone_admin)}} + DRONE_ADMIN: ${drone_admin} +{{- end}} +{{- if (.Values.drone_orgs)}} + DRONE_ORGS: ${drone_orgs} +{{- end}} +{{- if eq .Values.drone_driver "github"}} + DRONE_GITHUB: true + DRONE_GITHUB_CLIENT: ${drone_driver_client} + DRONE_GITHUB_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "bitbucket"}} + DRONE_BITBUCKET: true + DRONE_BITBUCKET_CLIENT: ${drone_driver_client} + DRONE_BITBUCKET_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "gitlab"}} + DRONE_GITLAB: true + DRONE_GITLAB_CLIENT: ${drone_driver_secret} + DRONE_GITLAB_SECRET: ${drone_driver_secret} + DRONE_GITLAB_URL: ${drone_driver_url} +{{- end}} +{{- if eq .Values.drone_driver "gogs"}} + DRONE_GOGS: true + DRONE_GOGS_URL: ${drone_driver_url} +{{- end}} +{{- if ne .Values.database_driver "sqlite"}} + DRONE_DATABASE_DRIVER: ${database_driver} + DRONE_DATABASE_DATASOURCE: ${database_source} +{{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if eq .Values.database_driver "sqlite"}} + io.rancher.sidekicks: server-volume + volumes_from: + - server-volume + server-volume: + image: rawmind/alpine-volume:0.0.2-1 + environment: + SERVICE_GID: '0' + SERVICE_UID: '0' + SERVICE_VOLUME: /var/lib/drone + network_mode: none + volumes: + - /var/lib/drone + labels: + io.rancher.container.start_once: 'true' + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- end}} + lb: + image: rancher/load-balancer-service + ports: + - ${host_port}:8000/tcp + links: + - server:server diff --git a/templates/drone/3/rancher-compose.yml b/templates/drone/3/rancher-compose.yml new file mode 100644 index 0000000..7a99c50 --- /dev/null +++ b/templates/drone/3/rancher-compose.yml @@ -0,0 +1,129 @@ +version: 2 +catalog: + name: Drone + version: 0.7.1-rancher1 + upgrade_from: 0.5-rancher1 + description: | + Drone CI Server ref http://readme.drone.io/admin/installation-guide/ + questions: + - variable: host_port + label: Drone server Host Port + description: | + Port that will be exposed on service creation + required: true + default: 8000 + type: int + - variable: agent_scale + label: Drone agent scale + description: Drone agent scale to deploy + required: true + default: 1 + type: int + - variable: drone_secret + label: Server and agents sercret. + description: Server and agents secret to be communicate. http://readme.drone.io/admin/user-registration/ + type: password + required: true + - variable: gin_mode + label: Run mode + description: "Drone run mode, GIN_MODE" + type: enum + default: "release" + options: + - "release" + - "debug" + required: true + - variable: drone_open + label: Open registration + description: | + Users self register. http://readme.drone.io/admin/user-registration/ + required: true + default: true + type: enum + options: + - true + - false + - variable: drone_admin + label: Drone Admin + description: List of admins for drone coma seperated. http://readme.drone.io/admin/user-admins/ + type: string + required: false + - variable: drone_orgs + label: Organizations + description: Comman seperated list of org that can access drone. http://readme.drone.io/admin/user-registration/ + type: string + required: false + - variable: "drone_driver" + type: "enum" + required: true + label: "Remote Driver" + default: "github" + description: "Remote Git and Auth scheme. ref http://readme.drone.io/admin" + options: + - github + - bitbucket + - gitlab + - gogs + - variable: drone_driver_client + label: Remote Driver client + description: "Client key from remote driver. Required for github, bitbucket and gitlab." + type: string + required: false + - variable: drone_driver_secret + label: Remote Driver secret + description: "Secret key from remote driver. Required for github, bitbucket and gitlab." + type: string + required: false + - variable: drone_driver_url + label: Remote Driver url + description: "Remote Driver server url. Required for gitlab and gogs, http://readme.drone.io/admin" + type: string + required: false + - variable: database_driver + label: Database Driver + description: "Database driver. If sqlite, additional volume would be mounted at /var/lib/drone." + type: enum + default: "sqlite" + options: + - "sqlite" + - "mysql" + - "postgres" + required: true + - variable: "database_source" + type: "string" + label: "Database source" + description: "Database datasource. Required if database driver is mysql or postgres, http://readme.drone.io/admin/database-engines/" + required: false +services: + agent: + scale: ${agent_scale} + start_on_create: true + server: + scale: 1 + start_on_create: true + health_check: + port: 8000 + interval: 2000 + unhealthy_threshold: 3 + strategy: recreate + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 + lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: server + source_port: ${host_port} + target_port: 8000 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate diff --git a/templates/drone/4/README.md b/templates/drone/4/README.md new file mode 100644 index 0000000..0349171 --- /dev/null +++ b/templates/drone/4/README.md @@ -0,0 +1,19 @@ +# Drone + +### Info: + +This template creates an instance of Drone CI server 0.8 along with selectable number of agents to perform the builds. + +### Usage: + +Select the Drone template from the catalog. Provide the following information: + +1. Publish port +2. Agents scale +3. Drone secret +4. Run mode. debug | release +3. Remote driver and config. (Ie. GitHub) +4. Database driver and config. (Ie. sqlite) + + +See [Drone documentation](http://readme.drone.io/admin) for complete information. diff --git a/templates/drone/4/docker-compose.yml.tpl b/templates/drone/4/docker-compose.yml.tpl new file mode 100644 index 0000000..eae9aad --- /dev/null +++ b/templates/drone/4/docker-compose.yml.tpl @@ -0,0 +1,116 @@ +version: '2' +services: + agent: + image: drone/agent:${drone_version} + environment: + DRONE_SERVER: ${drone_server} + DRONE_SECRET: ${drone_secret} +{{- if (.Values.http_proxy)}} + HTTP_PROXY: ${http_proxy} + http_proxy: ${http_proxy} +{{- end}} +{{- if (.Values.https_proxy)}} + HTTPS_PROXY: ${https_proxy} + https_proxy: ${https_proxy} +{{- end}} +{{- if (.Values.no_proxy)}} + NO_PROXY: ${no_proxy} + no_proxy: ${no_proxy} +{{- end}} + volumes: + - /var/run/docker.sock:/var/run/docker.sock + links: + - server:drone + command: + - agent + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + server: + image: drone/drone:${drone_version} + environment: + DRONE_HOST: ${drone_host} + GIN_MODE: ${gin_mode} +{{- if (.Values.drone_debug)}} + DRONE_DEBUG: '${drone_debug}' +{{- end}} + DRONE_SECRET: ${drone_secret} + DRONE_OPEN: ${drone_open} +{{- if (.Values.drone_admin)}} + DRONE_ADMIN: ${drone_admin} +{{- end}} +{{- if (.Values.drone_orgs)}} + DRONE_ORGS: ${drone_orgs} +{{- end}} +{{- if eq .Values.drone_driver "GitHub"}} + DRONE_GITHUB: true + DRONE_GITHUB_CLIENT: ${drone_driver_client} + DRONE_GITHUB_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "Bitbucket Cloud"}} + DRONE_BITBUCKET: true + DRONE_BITBUCKET_CLIENT: ${drone_driver_client} + DRONE_BITBUCKET_SECRET: ${drone_driver_secret} +{{- end}} +{{- if eq .Values.drone_driver "Bitbucket Server"}} + DRONE_STASH: true + DRONE_STASH_GIT_USERNAME: ${drone_driver_user} + DRONE_STASH_GIT_PASSWORD: ${drone_driver_password} + DRONE_STASH_CONSUMER_KEY: ${drone_driver_client} + DRONE_STASH_CONSUMER_RSA_STRING: ${drone_driver_secret} + DRONE_STASH_URL: ${drone_driver_url} +{{- end}} +{{- if eq .Values.drone_driver "GitLab"}} + DRONE_GITLAB: true + DRONE_GITLAB_CLIENT: ${drone_driver_secret} + DRONE_GITLAB_SECRET: ${drone_driver_secret} + DRONE_GITLAB_URL: ${drone_driver_url} +{{- end}} +{{- if eq .Values.drone_driver "Gogs"}} + DRONE_GOGS: true + DRONE_GOGS_URL: ${drone_driver_url} +{{- end}} +{{- if ne .Values.database_driver "sqlite"}} + DRONE_DATABASE_DRIVER: ${database_driver} + DRONE_DATABASE_DATASOURCE: ${database_source} +{{- end}} +{{- if (.Values.http_proxy)}} + HTTP_PROXY: ${http_proxy} + http_proxy: ${http_proxy} +{{- end}} +{{- if (.Values.https_proxy)}} + HTTPS_PROXY: ${https_proxy} + https_proxy: ${https_proxy} +{{- end}} +{{- if (.Values.no_proxy)}} + NO_PROXY: ${no_proxy} + no_proxy: ${no_proxy} +{{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if eq .Values.database_driver "sqlite"}} + io.rancher.sidekicks: server-volume + volumes_from: + - server-volume + server-volume: + image: rawmind/alpine-volume:0.0.2-1 + environment: + SERVICE_GID: '0' + SERVICE_UID: '0' + SERVICE_VOLUME: /var/lib/drone + network_mode: none + volumes: + - /var/lib/drone + labels: + io.rancher.container.start_once: 'true' + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- end}} + lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - ${host_port}:${host_port} + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label_soft: ${drone_lb_host_label} diff --git a/templates/drone/4/rancher-compose.yml b/templates/drone/4/rancher-compose.yml new file mode 100644 index 0000000..ee8bbec --- /dev/null +++ b/templates/drone/4/rancher-compose.yml @@ -0,0 +1,188 @@ +version: 2 +catalog: + name: Drone + version: 0.8.0-rc.1-rancher1 + upgrade_from: 0.5-rancher1 + description: | + Drone CI Server ref http://readme.drone.io/admin/installation-guide/ + questions: + - variable: drone_host + label: Drone Host URL + description: Intended URL Drone will be hosted on, e.g. http://drone.mycompany.com. + required: true + type: string + - variable: host_port + label: Drone Server Host Port + description: Public port that will be exposed on service creation. + required: true + default: 8000 + type: int + - variable: agent_scale + label: Drone Agent Scale + description: Drone agent scale to deploy + required: true + default: 1 + type: int + - variable: drone_secret + label: Server and Agents Secret + description: Server and agents secret to be communicate. http://readme.drone.io/admin/user-registration/ + type: password + required: true + - variable: gin_mode + label: Run mode + description: "Drone run mode, GIN_MODE" + type: enum + default: "release" + options: + - "release" + - "debug" + required: true + - variable: drone_open + label: Open Registration + description: | + Users self register. http://readme.drone.io/admin/user-registration/ + required: true + default: true + type: enum + options: + - true + - false + - variable: drone_admin + label: Drone Admin + description: List of admins for drone comma seperated. http://readme.drone.io/admin/user-admins/ + type: string + required: false + - variable: drone_orgs + label: Organizations + description: Comman seperated list of org that can access drone. http://readme.drone.io/admin/user-registration/ + type: string + required: false + - variable: "drone_driver" + type: "enum" + required: true + label: "Remote Driver" + default: "GitHub" + description: "Remote Git and Auth scheme. ref http://readme.drone.io/admin" + options: + - GitHub + - GitLab + - Gogs + - Bitbucket Cloud + - Bitbucket Server + - variable: drone_driver_client + label: Remote Driver Client + description: "Client key from remote driver. Required for GitHub, Bitbucket Cloud, Bitbucket Server and GitLab." + type: string + required: false + - variable: drone_driver_secret + label: Remote Driver Secret + description: "Secret key from remote driver. Required for GitHub, Bitbucket Cloud, Bitbucket Server and GitLab." + type: multiline + required: false + - variable: drone_driver_url + label: Remote Driver URL + description: "Remote Driver server url. Required for GitLab, Gogs and Bitbucket Server; see http://readme.drone.io/admin." + type: string + required: false + - variable: drone_driver_user + label: Remote Driver Username + description: "Remote Driver username. Required for BitBucket Server; see http://docs.drone.io/install-for-bitbucket-server/." + type: string + required: false + - variable: drone_driver_password + label: Remote Driver Password + description: "Remote Driver password. Required for BitBucket Server, http://docs.drone.io/install-for-bitbucket-server/." + type: password + required: false + - variable: drone_server + label: Drone Server + description: "Drone sever identifier. Used by the agent to connect to the server (does not require change)." + type: string + default: "drone:9000" + - variable: drone_version + label: Drone Version + description: "Drone version/Docker tag used for the Drone container images." + type: enum + default: "0.8.0-rc.1" + options: + - 0.8.0-rc.1 + - 0.8.0 + - '0.8' + - latest + - variable: database_driver + label: Database Driver + description: "Database driver. If sqlite, additional volume would be mounted at /var/lib/drone." + type: enum + default: "sqlite" + options: + - "sqlite" + - "mysql" + - "postgres" + required: true + - variable: "database_source" + type: "string" + label: "Database source" + description: "Database datasource. Required if database driver is mysql or postgres, http://readme.drone.io/admin/database-engines/" + required: false + - variable: "http_proxy" + type: string + label: HTTP Proxy + description: "Optional: HTTP forward proxy URL." + required: false + - variable: "https_proxy" + type: string + label: HTTPS Proxy + description: "Optional: HTTPS forward proxy URL." + required: false + - variable: "no_proxy" + type: string + label: No Proxy + description: "Optional: No proxy hosts (comma-separated hostnames/IPs)." + required: false + default: "drone" + - variable: "drone_debug" + label: Drone Debug + description: "Enable debug output with the Drone server." + type: enum + options: + - 'true' + - 'false' + default: 'false' + - variable: drone_lb_host_label + label: Drone LB Host Label + description: Host label (soft affinity) for scheduling of the load balancer service. + required: true + default: "drone_lb=true" + type: string +services: + agent: + scale: ${agent_scale} + start_on_create: true + server: + scale: 1 + start_on_create: true + health_check: + port: 8000 + interval: 2000 + unhealthy_threshold: 3 + strategy: recreate + request_line: GET / HTTP/1.0 + healthy_threshold: 2 + response_timeout: 2000 + lb: + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: server + source_port: ${host_port} + target_port: 8000 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate diff --git a/templates/drone/config.yml b/templates/drone/config.yml index 358b631..e501783 100644 --- a/templates/drone/config.yml +++ b/templates/drone/config.yml @@ -1,5 +1,5 @@ name: Drone description: | Drone CI Server -version: 0.4-rancher2 +version: 0.8.0-rc.1-rancher1 category: Continuous Integration diff --git a/templates/drupal/0/docker-compose.yml b/templates/drupal/0/docker-compose.yml new file mode 100644 index 0000000..4030f32 --- /dev/null +++ b/templates/drupal/0/docker-compose.yml @@ -0,0 +1,15 @@ +version: '2' +services: + web: + image: drupal + ports: + - ${public_port}:80 + depends_on: + - db + db: + image: mysql + environment: + MYSQL_DATABASE: ${database} + MYSQL_ROOT_PASSWORD: ${mysql_root_password} + MYSQL_USER: ${mysql_newusr} + MYSQL_PASSWORD: ${mysql_newusr_password} diff --git a/templates/drupal/0/rancher-compose.yml b/templates/drupal/0/rancher-compose.yml new file mode 100644 index 0000000..12adc41 --- /dev/null +++ b/templates/drupal/0/rancher-compose.yml @@ -0,0 +1,40 @@ +.catalog: + name: "Drupal" + version: "v0.1" + description: "Drupal is an open source CMS powering millions of websites and applications." + uuid: Drupal-0 + minimum_rancher_version: v0.51.0 + questions: + - variable: public_port + description: "public port to access the drupal site" + label: "Public Port" + required: true + default: "80" + type: "int" + + - variable: database + description: "database name" + label: "MYSQL_DATABASE" + required: true + type: "string" + + - variable: mysql_root_password + description: "password for root user" + label: "MYSQL_ROOT_PASSWORD" + required: true + type: "string" + + - variable: mysql_newusr + description: "new user name" + label: "MYSQL_USER" + required: false + type: "string" + + - variable: mysql_newusr_password + description: "new user password" + label: "MYSQL_USER_PASSWORD" + required: false + type: "string" + +drupal: + retain_ip: true diff --git a/templates/drupal/1/docker-compose.yml.tpl b/templates/drupal/1/docker-compose.yml.tpl new file mode 100644 index 0000000..39657db --- /dev/null +++ b/templates/drupal/1/docker-compose.yml.tpl @@ -0,0 +1,59 @@ +version: '2' +services: + drupal: + image: drupal:8.3.5-apache + labels: + io.rancher.container.hostname_override: container_name + links: + - db:db + volumes: + - drupal-modules:/var/www/html/modules + - drupal-profiles:/var/www/html/profiles + - drupal-themes:/var/www/html/themes + - drupal-sites:/var/www/html/sites + restart: always + + drupal-lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - ${PUBLIC_PORT}:${PUBLIC_PORT} + + db: + labels: + io.rancher.container.hostname_override: container_name + {{- if eq .Values.DB_TYPE "postgres"}} + image: postgres:9.6.3-alpine + environment: + POSTGRES_USER: ${DB_USER} + POSTGRES_PASSWORD: ${DB_PASS} + POSTGRES_DB: ${DB_NAME} + {{- end}} + {{- if eq .Values.DB_TYPE "mysql"}} + image: mysql:5.7.18 + environment: + MYSQL_DATABASE: ${DB_NAME} + MYSQL_ROOT_PASSWORD: ${DB_PASS} + MYSQL_USER: ${DB_USER} + MYSQL_PASSWORD: ${DB_PASS} + {{- end}} + volumes: + {{- if eq .Values.DB_TYPE "postgres"}} + - db-data:/var/lib/postgresql + {{- end}} + {{- if eq .Values.DB_TYPE "mysql"}} + - db-data:/var/lib/mysql + {{- end}} + restart: always + +volumes: + drupal-modules: + driver: local + drupal-profiles: + driver: local + drupal-themes: + driver: local + drupal-sites: + driver: local + db-data: + driver: local + diff --git a/templates/drupal/1/rancher-compose.yml b/templates/drupal/1/rancher-compose.yml new file mode 100644 index 0000000..8fb6f3e --- /dev/null +++ b/templates/drupal/1/rancher-compose.yml @@ -0,0 +1,76 @@ +version: '2' +catalog: + name: "Drupal" + version: "8.3.5-rancher1" + description: "Blog tool, publishing platform and CMS" + uuid: Drupal-0 + minimum_rancher_version: v0.51.0 + questions: + - variable: "PUBLIC_PORT" + description: "public port to access the drupal site" + label: "Public Port" + required: true + default: "15080" + type: "int" + + - variable: "DB_TYPE" + description: "public port to access the drupal site" + label: "DB type" + required: true + default: "postgres" + type: "enum" + options: + - "mysql" + - "postgres" + + - variable: "DB_NAME" + description: "Database Name to use for the server" + label: "DB Name" + required: true + default: "drupal" + type: "string" + + - variable: "DB_USER" + description: "Database User to use for the server" + label: "DB User" + required: true + default: "drupal" + type: "string" + + - variable: "DB_PASS" + description: "Database Password to use for the server" + label: "DB Password" + required: true + default: "" + type: "password" +services: + drupal: + retain_ip: true + scale: 1 + health_check: + healthy_threshold: 2 + response_timeout: 5000 + port: 80 + unhealthy_threshold: 3 + interval: 5000 + strategy: recreate + request_line: GET / # HTTP/1.0 + drupal-lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: drupal + source_port: ${PUBLIC_PORT} + target_port: 80 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + reinitializing_timeout: 60000 diff --git a/templates/drupal/catalogIcon-drupal.svg b/templates/drupal/catalogIcon-drupal.svg new file mode 100644 index 0000000..c362f21 --- /dev/null +++ b/templates/drupal/catalogIcon-drupal.svg @@ -0,0 +1,967 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/drupal/config.yml b/templates/drupal/config.yml new file mode 100644 index 0000000..0877efe --- /dev/null +++ b/templates/drupal/config.yml @@ -0,0 +1,5 @@ +name: Drupal +description: | + Drupal is an open source CMS powering millions of websites and applications. +version: "8.3.5-rancher1" +category: CMS diff --git a/templates/ecr/0/rancher-compose.yml b/templates/ecr/0/rancher-compose.yml index e53877b..ac82015 100644 --- a/templates/ecr/0/rancher-compose.yml +++ b/templates/ecr/0/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v1.0.0" description: "Updates credentials for ECR in Rancher" uuid: ecr-1 + maximum_rancher_version: "v1.4.99" questions: - variable: "aws_access_key_id" label: "AWS Access Key ID" diff --git a/templates/ecr/1/rancher-compose.yml b/templates/ecr/1/rancher-compose.yml index ca2f443..a9f950a 100644 --- a/templates/ecr/1/rancher-compose.yml +++ b/templates/ecr/1/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v1.0.1" description: "Updates credentials for ECR in Rancher" uuid: ecr-2 + maximum_rancher_version: "v1.4.99" questions: - variable: "aws_access_key_id" label: "AWS Access Key ID" diff --git a/templates/ecr/2/rancher-compose.yml b/templates/ecr/2/rancher-compose.yml index f750319..0aedfb0 100644 --- a/templates/ecr/2/rancher-compose.yml +++ b/templates/ecr/2/rancher-compose.yml @@ -3,6 +3,7 @@ version: "v1.1.0" description: "Updates credentials for ECR in Rancher" uuid: ecr-3 + maximum_rancher_version: "v1.4.99" questions: - variable: "aws_access_key_id" label: "AWS Access Key ID" diff --git a/templates/es-cluster/0/README.md b/templates/es-cluster/0/README.md new file mode 100644 index 0000000..c662188 --- /dev/null +++ b/templates/es-cluster/0/README.md @@ -0,0 +1,5 @@ +# Elasticsearch Cluster + +A scalable Elasticsearch cluster + +WARN: To avoid vm.max_map_count errors you could set "Update host sysctl" to true. Then param vm.max_map_count will be update to 262144 if it's less in your hosts. diff --git a/templates/es-cluster/0/docker-compose.yml.tpl b/templates/es-cluster/0/docker-compose.yml.tpl new file mode 100644 index 0000000..b917a34 --- /dev/null +++ b/templates/es-cluster/0/docker-compose.yml.tpl @@ -0,0 +1,131 @@ +version: '2' +services: + es-master: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.0 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "ES_JAVA_OPTS=-Xms${master_heap_size} -Xmx${master_heap_size}" + - "discovery.zen.ping.unicast.hosts=es-master" + - "discovery.zen.minimum_master_nodes=${minimum_master_nodes}" + - "node.master=true" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${master_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + + es-data: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.0 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${data_heap_size} -Xmx${data_heap_size}" + - "node.master=false" + - "node.data=true" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${data_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-client: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.0 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${client_heap_size} -Xmx${client_heap_size}" + - "node.master=false" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${client_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-storage: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-volume:0.0.2-1 + environment: + - SERVICE_UID=1000 + - SERVICE_GID=1000 + - SERVICE_VOLUME=/usr/share/elasticsearch/data + volumes: + - es-storage-volume:/usr/share/elasticsearch/data + + {{- if eq .Values.UPDATE_SYSCTL "true" }} + es-sysctl: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-sysctl:0.1 + privileged: true + environment: + - "SYSCTL_KEY=vm.max_map_count" + - "SYSCTL_VALUE=262144" + {{- end}} + +volumes: + es-storage-volume: + driver: local + per_container: true diff --git a/templates/es-cluster/0/rancher-compose.yml b/templates/es-cluster/0/rancher-compose.yml new file mode 100644 index 0000000..e5580a1 --- /dev/null +++ b/templates/es-cluster/0/rancher-compose.yml @@ -0,0 +1,97 @@ +.catalog: + name: Elasticsearch Cluster + version: 5.4.0-rancher1 + description: Scalable Elasticsearch Cluster + + questions: + - variable: "cluster_name" + type: "string" + required: true + label: "Cluster name" + description: "Name of the Elasticsearch Cluster" + default: "es-cluster" + + - variable: "UPDATE_SYSCTL" + label: "Update host sysctl:" + description: | + Set true to avoid vm.max_map_count errors. + WARN: If set true, host param vm.max_map_count will be update to 262144. + default: false + required: true + type: enum + options: + - false + - true + + - variable: "master_heap_size" + type: "string" + required: true + label: "Heap size (master nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "master_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (master nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (master nodes)" + default: 1073741824 + + - variable: "data_heap_size" + type: "string" + required: true + label: "Heap size (data nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "data_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (data nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (data nodes)" + default: 1073741824 + + - variable: "client_heap_size" + type: "string" + required: true + label: "Heap size (client nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "client_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (client nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (client nodes)" + default: 1073741824 + + - variable: "minimum_master_nodes" + type: "int" + required: true + label: "# of minimum Master Nodes" + description: "Set the number of required master nodes to reach quorum. Sets initial scale to this value as well" + default: 3 + + - variable: "initial_data_nodes" + type: "int" + required: true + label: "# of initial data nodes" + description: "Set the initial number of data nodes" + default: 2 + + - variable: "initial_client_nodes" + type: "int" + required: true + label: "# of initial client nodes" + description: "Set the initial number of client nodes" + default: 1 + + +es-master: + scale: ${minimum_master_nodes} + +es-data: + scale: ${initial_data_nodes} + +es-client: + scale: ${initial_client_nodes} diff --git a/templates/es-cluster/1/README.md b/templates/es-cluster/1/README.md new file mode 100644 index 0000000..c662188 --- /dev/null +++ b/templates/es-cluster/1/README.md @@ -0,0 +1,5 @@ +# Elasticsearch Cluster + +A scalable Elasticsearch cluster + +WARN: To avoid vm.max_map_count errors you could set "Update host sysctl" to true. Then param vm.max_map_count will be update to 262144 if it's less in your hosts. diff --git a/templates/es-cluster/1/docker-compose.yml.tpl b/templates/es-cluster/1/docker-compose.yml.tpl new file mode 100644 index 0000000..5aadb0a --- /dev/null +++ b/templates/es-cluster/1/docker-compose.yml.tpl @@ -0,0 +1,131 @@ +version: '2' +services: + es-master: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "ES_JAVA_OPTS=-Xms${master_heap_size} -Xmx${master_heap_size}" + - "discovery.zen.ping.unicast.hosts=es-master" + - "discovery.zen.minimum_master_nodes=${minimum_master_nodes}" + - "node.master=true" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${master_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + + es-data: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${data_heap_size} -Xmx${data_heap_size}" + - "node.master=false" + - "node.data=true" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${data_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-client: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${client_heap_size} -Xmx${client_heap_size}" + - "node.master=false" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${client_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-storage: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-volume:0.0.2-1 + environment: + - SERVICE_UID=1000 + - SERVICE_GID=1000 + - SERVICE_VOLUME=/usr/share/elasticsearch/data + volumes: + - es-storage-volume:/usr/share/elasticsearch/data + + {{- if eq .Values.UPDATE_SYSCTL "true" }} + es-sysctl: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-sysctl:0.1 + privileged: true + environment: + - "SYSCTL_KEY=vm.max_map_count" + - "SYSCTL_VALUE=262144" + {{- end}} + +volumes: + es-storage-volume: + driver: local + per_container: true diff --git a/templates/es-cluster/1/rancher-compose.yml b/templates/es-cluster/1/rancher-compose.yml new file mode 100644 index 0000000..632407f --- /dev/null +++ b/templates/es-cluster/1/rancher-compose.yml @@ -0,0 +1,97 @@ +.catalog: + name: Elasticsearch Cluster + version: 5.4.2-rancher1 + description: Scalable Elasticsearch Cluster + + questions: + - variable: "cluster_name" + type: "string" + required: true + label: "Cluster name" + description: "Name of the Elasticsearch Cluster" + default: "es-cluster" + + - variable: "UPDATE_SYSCTL" + label: "Update host sysctl:" + description: | + Set true to avoid vm.max_map_count errors. + WARN: If set true, host param vm.max_map_count will be update to 262144. + default: false + required: true + type: enum + options: + - false + - true + + - variable: "master_heap_size" + type: "string" + required: true + label: "Heap size (master nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "master_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (master nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (master nodes)" + default: 1073741824 + + - variable: "data_heap_size" + type: "string" + required: true + label: "Heap size (data nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "data_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (data nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (data nodes)" + default: 1073741824 + + - variable: "client_heap_size" + type: "string" + required: true + label: "Heap size (client nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "client_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (client nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (client nodes)" + default: 1073741824 + + - variable: "minimum_master_nodes" + type: "int" + required: true + label: "# of minimum Master Nodes" + description: "Set the number of required master nodes to reach quorum. Sets initial scale to this value as well" + default: 3 + + - variable: "initial_data_nodes" + type: "int" + required: true + label: "# of initial data nodes" + description: "Set the initial number of data nodes" + default: 2 + + - variable: "initial_client_nodes" + type: "int" + required: true + label: "# of initial client nodes" + description: "Set the initial number of client nodes" + default: 1 + + +es-master: + scale: ${minimum_master_nodes} + +es-data: + scale: ${initial_data_nodes} + +es-client: + scale: ${initial_client_nodes} diff --git a/templates/es-cluster/2/README.md b/templates/es-cluster/2/README.md new file mode 100644 index 0000000..c662188 --- /dev/null +++ b/templates/es-cluster/2/README.md @@ -0,0 +1,5 @@ +# Elasticsearch Cluster + +A scalable Elasticsearch cluster + +WARN: To avoid vm.max_map_count errors you could set "Update host sysctl" to true. Then param vm.max_map_count will be update to 262144 if it's less in your hosts. diff --git a/templates/es-cluster/2/docker-compose.yml.tpl b/templates/es-cluster/2/docker-compose.yml.tpl new file mode 100644 index 0000000..f4706fd --- /dev/null +++ b/templates/es-cluster/2/docker-compose.yml.tpl @@ -0,0 +1,131 @@ +version: '2' +services: + es-master: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "ES_JAVA_OPTS=-Xms${master_heap_size} -Xmx${master_heap_size}" + - "discovery.zen.ping.unicast.hosts=es-master" + - "discovery.zen.minimum_master_nodes=${minimum_master_nodes}" + - "node.master=true" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${master_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + + es-data: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${data_heap_size} -Xmx${data_heap_size}" + - "node.master=false" + - "node.data=true" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${data_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-client: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.4.2 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${client_heap_size} -Xmx${client_heap_size}" + - "node.master=false" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${client_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-storage: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-volume:0.0.2-1 + environment: + - SERVICE_UID=1000 + - SERVICE_GID=1000 + - SERVICE_VOLUME=/usr/share/elasticsearch/data + volumes: + - es-storage-volume:/usr/share/elasticsearch/data + + {{- if eq .Values.UPDATE_SYSCTL "true" }} + es-sysctl: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-sysctl:0.1 + privileged: true + environment: + - "SYSCTL_KEY=vm.max_map_count" + - "SYSCTL_VALUE=262144" + {{- end}} + +volumes: + es-storage-volume: + driver: ${VOLUME_DRIVER} + per_container: true diff --git a/templates/es-cluster/2/rancher-compose.yml b/templates/es-cluster/2/rancher-compose.yml new file mode 100644 index 0000000..aefd049 --- /dev/null +++ b/templates/es-cluster/2/rancher-compose.yml @@ -0,0 +1,111 @@ +version: '2' +catalog: + name: Elasticsearch Cluster + version: 5.4.2-rancher2 + description: Scalable Elasticsearch Cluster + + questions: + - variable: "cluster_name" + type: "string" + required: true + label: "Cluster name" + description: "Name of the Elasticsearch Cluster" + default: "es-cluster" + + - variable: "UPDATE_SYSCTL" + label: "Update host sysctl:" + description: | + Set true to avoid vm.max_map_count errors. + WARN: If set true, host param vm.max_map_count will be update to 262144. + default: false + required: true + type: enum + options: + - false + - true + + - variable: "master_heap_size" + type: "string" + required: true + label: "Heap size (master nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "master_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (master nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (master nodes)" + default: 1073741824 + + - variable: "data_heap_size" + type: "string" + required: true + label: "Heap size (data nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "data_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (data nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (data nodes)" + default: 1073741824 + + - variable: "client_heap_size" + type: "string" + required: true + label: "Heap size (client nodes)" + description: "Heap size to be allocated for Java (mater nodes)" + default: "512m" + + - variable: "client_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (client nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (client nodes)" + default: 1073741824 + + - variable: "minimum_master_nodes" + type: "int" + required: true + label: "# of minimum Master Nodes" + description: "Set the number of required master nodes to reach quorum. Sets initial scale to this value as well" + default: 3 + + - variable: "initial_data_nodes" + type: "int" + required: true + label: "# of initial data nodes" + description: "Set the initial number of data nodes" + default: 2 + + - variable: "initial_client_nodes" + type: "int" + required: true + label: "# of initial client nodes" + description: "Set the initial number of client nodes" + default: 1 + + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + +services: + + es-master: + scale: ${minimum_master_nodes} + + es-data: + scale: ${initial_data_nodes} + + es-client: + scale: ${initial_client_nodes} diff --git a/templates/es-cluster/3/README.md b/templates/es-cluster/3/README.md new file mode 100644 index 0000000..c662188 --- /dev/null +++ b/templates/es-cluster/3/README.md @@ -0,0 +1,5 @@ +# Elasticsearch Cluster + +A scalable Elasticsearch cluster + +WARN: To avoid vm.max_map_count errors you could set "Update host sysctl" to true. Then param vm.max_map_count will be update to 262144 if it's less in your hosts. diff --git a/templates/es-cluster/3/docker-compose.yml.tpl b/templates/es-cluster/3/docker-compose.yml.tpl new file mode 100644 index 0000000..9139827 --- /dev/null +++ b/templates/es-cluster/3/docker-compose.yml.tpl @@ -0,0 +1,131 @@ +version: '2' +services: + es-master: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.5.1 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "ES_JAVA_OPTS=-Xms${master_heap_size} -Xmx${master_heap_size}" + - "discovery.zen.ping.unicast.hosts=es-master" + - "discovery.zen.minimum_master_nodes=${minimum_master_nodes}" + - "node.master=true" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${master_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + + es-data: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.5.1 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${data_heap_size} -Xmx${data_heap_size}" + - "node.master=false" + - "node.data=true" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${data_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-client: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: es-storage + {{- if eq .Values.UPDATE_SYSCTL "true" -}} + ,es-sysctl + {{- end}} + image: docker.elastic.co/elasticsearch/elasticsearch:5.5.1 + environment: + - "cluster.name=${cluster_name}" + - "node.name=$${HOSTNAME}" + - "bootstrap.memory_lock=true" + - "xpack.security.enabled=false" + - "discovery.zen.ping.unicast.hosts=es-master" + - "ES_JAVA_OPTS=-Xms${client_heap_size} -Xmx${client_heap_size}" + - "node.master=false" + - "node.data=false" + ulimits: + memlock: + soft: -1 + hard: -1 + nofile: + soft: 65536 + hard: 65536 + mem_limit: ${client_mem_limit} + mem_swappiness: 0 + cap_add: + - IPC_LOCK + volumes_from: + - es-storage + depends_on: + - es-master + + es-storage: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-volume:0.0.2-1 + environment: + - SERVICE_UID=1000 + - SERVICE_GID=1000 + - SERVICE_VOLUME=/usr/share/elasticsearch/data + volumes: + - es-storage-volume:/usr/share/elasticsearch/data + + {{- if eq .Values.UPDATE_SYSCTL "true" }} + es-sysctl: + labels: + io.rancher.container.start_once: true + network_mode: none + image: rawmind/alpine-sysctl:0.1 + privileged: true + environment: + - "SYSCTL_KEY=vm.max_map_count" + - "SYSCTL_VALUE=262144" + {{- end}} + +volumes: + es-storage-volume: + driver: ${VOLUME_DRIVER} + per_container: true diff --git a/templates/es-cluster/3/rancher-compose.yml b/templates/es-cluster/3/rancher-compose.yml new file mode 100644 index 0000000..b39638b --- /dev/null +++ b/templates/es-cluster/3/rancher-compose.yml @@ -0,0 +1,111 @@ +version: '2' +catalog: + name: Elasticsearch Cluster + version: 5.5.1-rancher1 + description: Scalable Elasticsearch Cluster + + questions: + - variable: "cluster_name" + type: "string" + required: true + label: "Cluster name" + description: "Name of the Elasticsearch Cluster" + default: "es-cluster" + + - variable: "UPDATE_SYSCTL" + label: "Update host sysctl:" + description: | + Set true to avoid vm.max_map_count errors. + WARN: If set true, host param vm.max_map_count will be update to 262144. + default: false + required: true + type: enum + options: + - false + - true + + - variable: "master_heap_size" + type: "string" + required: true + label: "Heap size (master nodes)" + description: "Heap size to be allocated for Java (master nodes)" + default: "512m" + + - variable: "master_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (master nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (master nodes)" + default: 1073741824 + + - variable: "data_heap_size" + type: "string" + required: true + label: "Heap size (data nodes)" + description: "Heap size to be allocated for Java (data nodes)" + default: "512m" + + - variable: "data_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (data nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (data nodes)" + default: 1073741824 + + - variable: "client_heap_size" + type: "string" + required: true + label: "Heap size (client nodes)" + description: "Heap size to be allocated for Java (client nodes)" + default: "512m" + + - variable: "client_mem_limit" + type: "int" + required: true + label: "Memory limit in byte (client nodes)" + description: "Memory limit in Byte per elasticsearch container. AT LEAST double the heap size! (client nodes)" + default: 1073741824 + + - variable: "minimum_master_nodes" + type: "int" + required: true + label: "# of minimum Master Nodes" + description: "Set the number of required master nodes to reach quorum. Sets initial scale to this value as well" + default: 3 + + - variable: "initial_data_nodes" + type: "int" + required: true + label: "# of initial data nodes" + description: "Set the initial number of data nodes" + default: 2 + + - variable: "initial_client_nodes" + type: "int" + required: true + label: "# of initial client nodes" + description: "Set the initial number of client nodes" + default: 1 + + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + +services: + + es-master: + scale: ${minimum_master_nodes} + + es-data: + scale: ${initial_data_nodes} + + es-client: + scale: ${initial_client_nodes} diff --git a/templates/es-cluster/catalogIcon-elasticsearch.svg b/templates/es-cluster/catalogIcon-elasticsearch.svg new file mode 100644 index 0000000..76ee3cf --- /dev/null +++ b/templates/es-cluster/catalogIcon-elasticsearch.svg @@ -0,0 +1,67 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/es-cluster/config.yml b/templates/es-cluster/config.yml new file mode 100644 index 0000000..bb8b8c6 --- /dev/null +++ b/templates/es-cluster/config.yml @@ -0,0 +1,5 @@ +name: Elasticsearch Cluster 5.5.1 +description: | + Elasticsearch, you know for search! +version: 5.5.1-rancher1 +category: ELK diff --git a/templates/gitlab-multi-runner/0/docker-compose.yml b/templates/gitlab-multi-runner/0/docker-compose.yml new file mode 100644 index 0000000..c331348 --- /dev/null +++ b/templates/gitlab-multi-runner/0/docker-compose.yml @@ -0,0 +1,46 @@ +version: '2' + +services: + + gitlab-runner-config: + image: gitlab/gitlab-runner:alpine-v9.3.0 + stdin_open: true + volumes: + - /etc/gitlab-runner/ + tty: true + command: + - register + - -n + - --url + - ${GITLAB_URL} + - --registration-token + - ${GITLAB_TOKEN} + - --tag-list + - ${GITLAB_TAGS} + - --executor + - docker + - --description + - Rancher Docker Runner + - --docker-image + - docker:latest + - --docker-volumes + - /var/run/docker.sock:/var/run/docker.sock + - --docker-privileged + labels: + io.rancher.container.pull_image: always + io.rancher.container.start_once: 'true' + + gitlab-runner: + image: gitlab/gitlab-runner:alpine-v9.3.0 + stdin_open: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + tty: true + volumes_from: + - gitlab-runner-config + command: + - run + labels: + io.rancher.sidekicks: gitlab-runner-config + io.rancher.container.pull_image: always + io.rancher.scheduler.global: 'true' diff --git a/templates/gitlab-multi-runner/0/rancher-compose.yml b/templates/gitlab-multi-runner/0/rancher-compose.yml new file mode 100644 index 0000000..ab5c198 --- /dev/null +++ b/templates/gitlab-multi-runner/0/rancher-compose.yml @@ -0,0 +1,37 @@ +version: '2' + +catalog: + name: "gitlab-multi-runner" + version: "9.3.0" + description: "a Gitlab pipelines multi-runner, that will spawn privates runners in your infra." + minimum_rancher_version: v1.5.0 + # maximum_rancher_version: + # upgrade_from: # The previous versions that this template can be upgraded from + questions: + - variable: "GITLAB_URL" + label: "Gitlab Url" + description: "Url to your Gitlab CI endpoint" + type: "string" + default: "https://gitlab.com/ci" + required: true + + - variable: "GITLAB_TOKEN" + label: "Gitlab Token" + description: "Token provided in you project settings" + type: "string" + default: "xxxxxxxxxxxxxxxxxxxx" + required: true + + - variable: "GITLAB_TAGS" + label: "Gitlab Tags" + description: "Tags to apply" + type: "string" + default: "dev" + required: false + +services: + gitlab-runner-config: + scale: 1 + start_on_create: true + gitlab-runner: + start_on_create: true diff --git a/templates/gitlab-multi-runner/1/docker-compose.yml.tpl b/templates/gitlab-multi-runner/1/docker-compose.yml.tpl new file mode 100644 index 0000000..a765ee8 --- /dev/null +++ b/templates/gitlab-multi-runner/1/docker-compose.yml.tpl @@ -0,0 +1,47 @@ +version: '2' + +services: + + gitlab-runner-config: + image: gitlab/gitlab-runner:alpine-v9.4.1 + stdin_open: true + volumes: + - /etc/gitlab-runner/ + tty: true + command: + - register + - -n + - --url + - ${GITLAB_URL} + - --registration-token + - ${GITLAB_TOKEN} + - --tag-list + - ${GITLAB_TAGS} + - --executor + - docker + - --description + - Rancher Docker Runner + - --docker-image + - docker:latest + - --docker-volumes + - /var/run/docker.sock:/var/run/docker.sock + - --docker-privileged + labels: + io.rancher.container.start_once: 'true' + + gitlab-runner: + image: gitlab/gitlab-runner:alpine-v9.4.1 + stdin_open: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + tty: true + volumes_from: + - gitlab-runner-config + command: + - run + labels: + io.rancher.sidekicks: gitlab-runner-config + io.rancher.scheduler.global: 'true' + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} diff --git a/templates/gitlab-multi-runner/1/rancher-compose.yml b/templates/gitlab-multi-runner/1/rancher-compose.yml new file mode 100644 index 0000000..4c737e4 --- /dev/null +++ b/templates/gitlab-multi-runner/1/rancher-compose.yml @@ -0,0 +1,45 @@ +version: '2' + +catalog: + name: "gitlab-multi-runner" + version: "9.4.1" + description: "a Gitlab pipelines multi-runner, that will spawn privates runners in your infra." + minimum_rancher_version: v1.5.0 + # maximum_rancher_version: + # upgrade_from: # The previous versions that this template can be upgraded from + questions: + - variable: "GITLAB_URL" + label: "Gitlab Url" + description: "Url to your Gitlab CI endpoint" + type: "string" + default: "https://gitlab.com/ci" + required: true + + - variable: "GITLAB_TOKEN" + label: "Gitlab Token" + description: "Token provided in you project settings" + type: "string" + default: "xxxxxxxxxxxxxxxxxxxx" + required: true + + - variable: "GITLAB_TAGS" + label: "Gitlab Tags" + description: "Tags to apply" + type: "string" + default: "dev" + required: false + + - variable: "host_label" + label: "Host with Label to deploy gitlab-runner on" + description: | + Host label to use as gitlab-runner 'value' tag. + Example: 'gitlab-runner=true' + type: "string" + default: "" + required: false + +services: + gitlab-runner-config: + start_on_create: true + gitlab-runner: + start_on_create: true diff --git a/templates/gitlab-multi-runner/2/docker-compose.yml.tpl b/templates/gitlab-multi-runner/2/docker-compose.yml.tpl new file mode 100644 index 0000000..1923721 --- /dev/null +++ b/templates/gitlab-multi-runner/2/docker-compose.yml.tpl @@ -0,0 +1,47 @@ +version: '2' + +services: + + gitlab-runner-config: + image: gitlab/gitlab-runner:alpine-v9.4.2 + stdin_open: true + volumes: + - /etc/gitlab-runner/ + tty: true + command: + - register + - -n + - --url + - ${GITLAB_URL} + - --registration-token + - ${GITLAB_TOKEN} + - --tag-list + - ${GITLAB_TAGS} + - --executor + - docker + - --description + - Rancher Docker Runner + - --docker-image + - docker:latest + - --docker-volumes + - /var/run/docker.sock:/var/run/docker.sock + - --docker-privileged + labels: + io.rancher.container.start_once: 'true' + + gitlab-runner: + image: gitlab/gitlab-runner:alpine-v9.4.2 + stdin_open: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + tty: true + volumes_from: + - gitlab-runner-config + command: + - run + labels: + io.rancher.sidekicks: gitlab-runner-config + io.rancher.scheduler.global: 'true' + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} diff --git a/templates/gitlab-multi-runner/2/rancher-compose.yml b/templates/gitlab-multi-runner/2/rancher-compose.yml new file mode 100644 index 0000000..559c763 --- /dev/null +++ b/templates/gitlab-multi-runner/2/rancher-compose.yml @@ -0,0 +1,45 @@ +version: '2' + +catalog: + name: "gitlab-multi-runner" + version: "9.4.2" + description: "a Gitlab pipelines multi-runner, that will spawn privates runners in your infra." + minimum_rancher_version: v1.5.0 + # maximum_rancher_version: + # upgrade_from: # The previous versions that this template can be upgraded from + questions: + - variable: "GITLAB_URL" + label: "Gitlab Url" + description: "Url to your Gitlab CI endpoint" + type: "string" + default: "https://gitlab.com/ci" + required: true + + - variable: "GITLAB_TOKEN" + label: "Gitlab Token" + description: "Token provided in you project settings" + type: "string" + default: "xxxxxxxxxxxxxxxxxxxx" + required: true + + - variable: "GITLAB_TAGS" + label: "Gitlab Tags" + description: "Tags to apply" + type: "string" + default: "dev" + required: false + + - variable: "host_label" + label: "Host with Label to deploy gitlab-runner on" + description: | + Host label to use as gitlab-runner 'value' tag. + Example: 'gitlab-runner=true' + type: "string" + default: "" + required: false + +services: + gitlab-runner-config: + start_on_create: true + gitlab-runner: + start_on_create: true diff --git a/templates/gitlab-multi-runner/catalogIcon-gitlab-multi-runner.png b/templates/gitlab-multi-runner/catalogIcon-gitlab-multi-runner.png new file mode 100644 index 0000000..a629de7 Binary files /dev/null and b/templates/gitlab-multi-runner/catalogIcon-gitlab-multi-runner.png differ diff --git a/templates/gitlab-multi-runner/config.yml b/templates/gitlab-multi-runner/config.yml new file mode 100644 index 0000000..4686092 --- /dev/null +++ b/templates/gitlab-multi-runner/config.yml @@ -0,0 +1,5 @@ +name: gitlab-multi-runner +description: | + a Gitlab pipelines multi-runner, that will spawn privates runners in your infra. +version: 9.4.2 +category: Continuous Integration diff --git a/templates/gitlab/0/docker-compose.yml b/templates/gitlab/0/docker-compose.yml index 25e7e81..9422535 100644 --- a/templates/gitlab/0/docker-compose.yml +++ b/templates/gitlab/0/docker-compose.yml @@ -1,27 +1,26 @@ -gitlab-server: - ports: - - ${ssh_port}:22/tcp - - ${http_port}:80/tcp - - ${https_port}:443/tcp - labels: - io.rancher.sidekicks: gitlab-data - hostname: ${gitlab_hostname} - image: gitlab/gitlab-ce:latest - volumes_from: - - gitlab-data - environment: - GITLAB_OMNIBUS_CONFIG: | - external_url '${gitlab_omnipus_prefix}${gitlab_hostname}' - -gitlab-data: - labels: - io.rancher.container.start_once: 'true' - entrypoint: - - /bin/true - hostname: gitdata - image: gitlab/gitlab-ce:latest - volumes: - - /etc/gitlab - - /var/log/gitlab - - /var/opt/gitlab +version: '2' +volumes: + gitlab-app-data: + driver: ${volumedriver} + gitlab-log-data: + driver: ${volumedriver} + gitlab-conf-files: + driver: ${volumedriver} +services: + gitlab-server: + ports: + - ${ssh_port}:22/tcp + - ${http_port}:80/tcp + - ${https_port}:443/tcp + labels: + io.rancher.container.hostname_override: container_name + image: gitlab/gitlab-ce:9.3.3-ce.0 + volumes: + - gitlab-app-data:/var/opt/gitlab + - gitlab-log-data:/var/log/gitlab + - gitlab-conf-files:/etc/gitlab + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url '${gitlab_omnipus_prefix}${gitlab_hostname}' + registry_external_url '${gitlab_omnipus_prefix}${registry_gitlab_hostname}' diff --git a/templates/gitlab/0/rancher-compose.yml b/templates/gitlab/0/rancher-compose.yml index 9147ff9..b382043 100644 --- a/templates/gitlab/0/rancher-compose.yml +++ b/templates/gitlab/0/rancher-compose.yml @@ -1,6 +1,6 @@ .catalog: name: Gitlab Community - version: latest + version: 9.3.3-ce.0 description: | Gitlab CE is a free GitHub alternative minimum_rancher_version: v0.56.0 @@ -13,34 +13,49 @@ required: true default: "git.example.com" type: "string" + - variable: "registry_gitlab_hostname" + description: "Registry Gitlab hostname (without uri scheme http:// or https://)" + label: "Registry hostname:" + required: true + default: "registry.example.com" + type: "string" - variable: "gitlab_omnipus_prefix" label: "Gitlab external_url prefix:" description: | This is needed for the docker-compose file to set the correct external_url - default: 'https://' + default: 'http://' required: true - type: "string" + type: "enum" options: - - 'https://' - 'http://' + - 'https://' - variable: "http_port" description: "HTTP port to expose on host. Will be used to bind TCP" label: "HTTP port:" required: true default: 80 - type: "string" + type: "int" - variable: "https_port" description: "HTTPS port to expose on host. Will be used to bind TCP" label: "HTTPS port:" required: true default: 443 - type: "string" + type: "int" - variable: "ssh_port" description: "SSH port to expose on host. Will be used to bind TCP" label: "SSH port:" required: true default: 22 - type: "string" + type: "int" + - variable: "volumedriver" + description: "Choose the Volume Driver being used.(Option: local or rancher-nfs)" + label: "Volume Driver:" + required: true + default: local + type: "enum" + options: + - local + - rancher-nfs gitlab-server: scale: 1 @@ -52,8 +67,3 @@ gitlab-server: strategy: recreate response_timeout: 2000 healthy_threshold: 2 - -gitlab-data: - scale: 1 - retain_ip: true - diff --git a/templates/gitlab/1/README.md b/templates/gitlab/1/README.md new file mode 100644 index 0000000..ca11a7c --- /dev/null +++ b/templates/gitlab/1/README.md @@ -0,0 +1,9 @@ +# GitLab CE + +GitLab CE is a free alternative to GitHub + +Stack based on official GitLab version: latest + +https://hub.docker.com/r/gitlab/gitlab-ce/ + + diff --git a/templates/gitlab/1/docker-compose.yml b/templates/gitlab/1/docker-compose.yml new file mode 100644 index 0000000..d1d4bb9 --- /dev/null +++ b/templates/gitlab/1/docker-compose.yml @@ -0,0 +1,26 @@ +version: '2' +volumes: + gitlab-app-data: + driver: ${volumedriver} + gitlab-log-data: + driver: ${volumedriver} + gitlab-conf-files: + driver: ${volumedriver} + +services: + gitlab-server: + ports: + - ${ssh_port}:22/tcp + - ${http_port}:80/tcp + - ${https_port}:443/tcp + labels: + io.rancher.container.hostname_override: container_name + image: gitlab/gitlab-ce:9.4.2-ce.0 + volumes: + - gitlab-app-data:/var/opt/gitlab + - gitlab-log-data:/var/log/gitlab + - gitlab-conf-files:/etc/gitlab + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url '${gitlab_omnipus_prefix}${gitlab_hostname}' + registry_external_url '${gitlab_omnipus_prefix}${registry_gitlab_hostname}' diff --git a/templates/gitlab/1/rancher-compose.yml b/templates/gitlab/1/rancher-compose.yml new file mode 100644 index 0000000..083028c --- /dev/null +++ b/templates/gitlab/1/rancher-compose.yml @@ -0,0 +1,69 @@ +.catalog: + name: Gitlab Community + version: 9.4.2-ce.0 + description: | + Gitlab CE is a free GitHub alternative + minimum_rancher_version: v0.56.0 + maintainer: "Alexis Ducastel " + uuid: gitlab-0 + questions: + - variable: "gitlab_hostname" + description: "Gitlab hostname (without uri scheme http:// or https://)" + label: "Hostname:" + required: true + default: "git.example.com" + type: "string" + - variable: "registry_gitlab_hostname" + description: "Registry Gitlab hostname (without uri scheme http:// or https://)" + label: "Registry hostname:" + required: true + default: "registry.example.com" + type: "string" + - variable: "gitlab_omnipus_prefix" + label: "Gitlab external_url prefix:" + description: | + This is needed for the docker-compose file to set the correct external_url + default: 'http://' + required: true + type: "enum" + options: + - 'http://' + - 'https://' + - variable: "http_port" + description: "HTTP port to expose on host. Will be used to bind TCP" + label: "HTTP port:" + required: true + default: 80 + type: "int" + - variable: "https_port" + description: "HTTPS port to expose on host. Will be used to bind TCP" + label: "HTTPS port:" + required: true + default: 443 + type: "int" + - variable: "ssh_port" + description: "SSH port to expose on host. Will be used to bind TCP" + label: "SSH port:" + required: true + default: 22 + type: "int" + - variable: "volumedriver" + description: "Choose the Volume Driver being used.(Option: local or rancher-nfs)" + label: "Volume Driver:" + required: true + default: local + type: "enum" + options: + - local + - rancher-nfs + +gitlab-server: + scale: 1 + retain_ip: true + health_check: + port: 80 + interval: 30000 + unhealthy_threshold: 3 + strategy: recreate + response_timeout: 2000 + healthy_threshold: 2 diff --git a/templates/gitlab/2/README.md b/templates/gitlab/2/README.md new file mode 100644 index 0000000..ca11a7c --- /dev/null +++ b/templates/gitlab/2/README.md @@ -0,0 +1,9 @@ +# GitLab CE + +GitLab CE is a free alternative to GitHub + +Stack based on official GitLab version: latest + +https://hub.docker.com/r/gitlab/gitlab-ce/ + + diff --git a/templates/gitlab/2/docker-compose.yml b/templates/gitlab/2/docker-compose.yml new file mode 100644 index 0000000..6209a57 --- /dev/null +++ b/templates/gitlab/2/docker-compose.yml @@ -0,0 +1,26 @@ +version: '2' +volumes: + gitlab-app-data: + driver: ${volumedriver} + gitlab-log-data: + driver: ${volumedriver} + gitlab-conf-files: + driver: ${volumedriver} + +services: + gitlab-server: + ports: + - ${ssh_port}:22/tcp + - ${http_port}:80/tcp + - ${https_port}:443/tcp + labels: + io.rancher.container.hostname_override: container_name + image: gitlab/gitlab-ce:9.4.5-ce.0 + volumes: + - gitlab-app-data:/var/opt/gitlab + - gitlab-log-data:/var/log/gitlab + - gitlab-conf-files:/etc/gitlab + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url '${gitlab_omnipus_prefix}${gitlab_hostname}' + registry_external_url '${gitlab_omnipus_prefix}${registry_gitlab_hostname}' diff --git a/templates/gitlab/2/rancher-compose.yml b/templates/gitlab/2/rancher-compose.yml new file mode 100644 index 0000000..2729a84 --- /dev/null +++ b/templates/gitlab/2/rancher-compose.yml @@ -0,0 +1,69 @@ +.catalog: + name: Gitlab Community + version: 9.4.5-ce.0 + description: | + Gitlab CE is a free GitHub alternative + minimum_rancher_version: v0.56.0 + maintainer: "Alexis Ducastel " + uuid: gitlab-0 + questions: + - variable: "gitlab_hostname" + description: "Gitlab hostname (without uri scheme http:// or https://)" + label: "Hostname:" + required: true + default: "git.example.com" + type: "string" + - variable: "registry_gitlab_hostname" + description: "Registry Gitlab hostname (without uri scheme http:// or https://)" + label: "Registry hostname:" + required: true + default: "registry.example.com" + type: "string" + - variable: "gitlab_omnipus_prefix" + label: "Gitlab external_url prefix:" + description: | + This is needed for the docker-compose file to set the correct external_url + default: 'http://' + required: true + type: "enum" + options: + - 'http://' + - 'https://' + - variable: "http_port" + description: "HTTP port to expose on host. Will be used to bind TCP" + label: "HTTP port:" + required: true + default: 80 + type: "int" + - variable: "https_port" + description: "HTTPS port to expose on host. Will be used to bind TCP" + label: "HTTPS port:" + required: true + default: 443 + type: "int" + - variable: "ssh_port" + description: "SSH port to expose on host. Will be used to bind TCP" + label: "SSH port:" + required: true + default: 22 + type: "int" + - variable: "volumedriver" + description: "Choose the Volume Driver being used.(Option: local or rancher-nfs)" + label: "Volume Driver:" + required: true + default: local + type: "enum" + options: + - local + - rancher-nfs + +gitlab-server: + scale: 1 + retain_ip: true + health_check: + port: 80 + interval: 30000 + unhealthy_threshold: 3 + strategy: recreate + response_timeout: 3000 + healthy_threshold: 2 diff --git a/templates/gitlab/3/README.md b/templates/gitlab/3/README.md new file mode 100644 index 0000000..ca11a7c --- /dev/null +++ b/templates/gitlab/3/README.md @@ -0,0 +1,9 @@ +# GitLab CE + +GitLab CE is a free alternative to GitHub + +Stack based on official GitLab version: latest + +https://hub.docker.com/r/gitlab/gitlab-ce/ + + diff --git a/templates/gitlab/3/docker-compose.yml b/templates/gitlab/3/docker-compose.yml new file mode 100644 index 0000000..eddf7aa --- /dev/null +++ b/templates/gitlab/3/docker-compose.yml @@ -0,0 +1,27 @@ +version: '2' +volumes: + gitlab-app-data: + driver: ${volumedriver} + gitlab-log-data: + driver: ${volumedriver} + gitlab-conf-files: + driver: ${volumedriver} + +services: + gitlab-server: + ports: + - ${ssh_port}:22/tcp + - ${http_port}:80/tcp + - ${https_port}:443/tcp + labels: + io.rancher.container.hostname_override: container_name + image: gitlab/gitlab-ce:9.5.1-ce.0 + volumes: + - gitlab-app-data:/var/opt/gitlab + - gitlab-log-data:/var/log/gitlab + - gitlab-conf-files:/etc/gitlab + environment: + GITLAB_OMNIBUS_CONFIG: | + external_url '${gitlab_omnipus_prefix}${gitlab_hostname}' + registry_external_url '${gitlab_omnipus_prefix}${registry_gitlab_hostname}' + gitlab_rails['gitlab_shell_ssh_port'] = ${ssh_port} diff --git a/templates/gitlab/3/rancher-compose.yml b/templates/gitlab/3/rancher-compose.yml new file mode 100644 index 0000000..408c282 --- /dev/null +++ b/templates/gitlab/3/rancher-compose.yml @@ -0,0 +1,69 @@ +.catalog: + name: Gitlab Community + version: 9.5.1-ce.0 + description: | + Gitlab CE is a free GitHub alternative + minimum_rancher_version: v0.56.0 + maintainer: "Alexis Ducastel " + uuid: gitlab-0 + questions: + - variable: "gitlab_hostname" + description: "Gitlab hostname (without uri scheme http:// or https://)" + label: "Hostname:" + required: true + default: "git.example.com" + type: "string" + - variable: "registry_gitlab_hostname" + description: "Registry Gitlab hostname (without uri scheme http:// or https://)" + label: "Registry hostname:" + required: true + default: "registry.example.com" + type: "string" + - variable: "gitlab_omnipus_prefix" + label: "Gitlab external_url prefix:" + description: | + This is needed for the docker-compose file to set the correct external_url + default: 'http://' + required: true + type: "enum" + options: + - 'http://' + - 'https://' + - variable: "http_port" + description: "HTTP port to expose on host. Will be used to bind TCP" + label: "HTTP port:" + required: true + default: 80 + type: "int" + - variable: "https_port" + description: "HTTPS port to expose on host. Will be used to bind TCP" + label: "HTTPS port:" + required: true + default: 443 + type: "int" + - variable: "ssh_port" + description: "SSH port to expose on host. Will be used to bind TCP" + label: "SSH port:" + required: true + default: 22 + type: "int" + - variable: "volumedriver" + description: "Choose the Volume Driver being used.(Option: local or rancher-nfs)" + label: "Volume Driver:" + required: true + default: local + type: "enum" + options: + - local + - rancher-nfs + +gitlab-server: + scale: 1 + retain_ip: true + health_check: + port: 80 + interval: 30000 + unhealthy_threshold: 3 + strategy: recreate + response_timeout: 3000 + healthy_threshold: 2 diff --git a/templates/gitlab/config.yml b/templates/gitlab/config.yml index 66e2221..b39ac46 100644 --- a/templates/gitlab/config.yml +++ b/templates/gitlab/config.yml @@ -1,5 +1,5 @@ name: Gitlab Community description: | Gitlab CE is a free GitHub alternative -version: latest +version: 9.5.1-ce.0 category: Versioning diff --git a/templates/gocd/0/README.md b/templates/gocd/0/README.md new file mode 100644 index 0000000..f78d15f --- /dev/null +++ b/templates/gocd/0/README.md @@ -0,0 +1,35 @@ +# GoCD.io + +### Info: + +This template creates one GoCD server and scale out the number of GoCD agent you need. + +The GoCD agent is link with docker engine container as sidekick, so the idea is to not create GoCD agent per language but use docker container to build and test your stuff. +You can use on GoCD agent: +- docker cli +- docker-compose cli +- rancher-compose cli +- make + + +### Usage: + +Select GoCD from catalog. + +Choose if you should deploy GoCD Server, or GoCD Agent or the two. +Enter the number of GoCD agent you need. +Choose the key to autoregister GoCD agent. + +Click deploy. + +GoCD server can now be accessed over the Rancher network on port `8153` (http://IP_CONTAINER:8153). To access from external Rancher network, you need to set load balancer or expose the port 8153. + + + +### Source, bugs and enhances + + If you found bugs or need enhance, you can open ticket on github: + - [GoCD official core project](https://github.com/gocd/gocd) + - [GoCD Server docker image](https://github.com/disaster37/alpine-gocd-server) + - [GoCD Agent docker image](https://github.com/disaster37/alpine-gocd-agent) + - [Rancher Cattle metadata docker image](https://github.com/disaster37/rancher-cattle-metadata) \ No newline at end of file diff --git a/templates/gocd/0/docker-compose.yml.tpl b/templates/gocd/0/docker-compose.yml.tpl new file mode 100644 index 0000000..54b7f54 --- /dev/null +++ b/templates/gocd/0/docker-compose.yml.tpl @@ -0,0 +1,125 @@ +version: '2' +services: + {{- if eq .Values.DEPLOY_SERVER "true"}} + gocd-server: + tty: true + image: webcenter/alpine-gocd-server:17.3.0-1 + volumes: + {{- if eq (printf "%.1s" .Values.VOLUME_DRIVER_SERVER) "/" }} + - ${VOLUME_DRIVER_SERVER}:/data + {{- else}} + - gocd-server-data:/data + {{- end}} + environment: + - GOCD_CONFIG_memory=${GOCD_SERVER_MEMORY} + - GOCD_CONFIG_agent-key=${GOCD_AGENT_KEY} + - GOCD_CONFIG_server-url=${GOCD_SERVER_URL} + - GOCD_USER_${GOCD_USER}=${GOCD_PASSWORD} + - CONFD_BACKEND=${CONFD_BACKEND} + - CONFD_NODES=${CONFD_NODES} + - CONFD_PREFIX_KEY=${CONFD_PREFIX} + {{- if eq .Values.GOCD_AGENT_PACKAGE "true"}} + - GOCD_PLUGIN_script-executor=https://github.com/gocd-contrib/script-executor-task/releases/download/0.3/script-executor-0.3.0.jar + - GOCD_PLUGIN_docker-task=https://github.com/manojlds/gocd-docker/releases/download/0.1.27/docker-task-assembly-0.1.27.jar + - GOCD_PLUGIN_slack=https://github.com/Vincit/gocd-slack-task/releases/download/v1.3.1/gocd-slack-task-1.3.1.jar + - GOCD_PLUGIN_docker-pipline=https://github.com/Haufe-Lexware/gocd-plugins/releases/download/v1.0.0-beta/gocd-docker-pipeline-plugin-1.0.0.jar + - GOCD_PLUGIN_email-notifier=https://github.com/gocd-contrib/email-notifier/releases/download/v0.1/email-notifier-0.1.jar + - GOCD_PLUGIN_github-notifier=https://github.com/gocd-contrib/gocd-build-status-notifier/releases/download/1.3/github-pr-status-1.3.jar + - GOCD_PLUGIN_github-scm=https://github.com/ashwanthkumar/gocd-build-github-pull-requests/releases/download/v1.3.3/github-pr-poller-1.3.3.jar + - GOCD_PLUGIN_maven-repository=https://github.com/1and1/go-maven-poller/releases/download/v1.1.4/go-maven-poller.jar + - GOCD_PLUGIN_maven-task=https://github.com/ruckc/gocd-maven-plugin/releases/download/0.1.1/gocd-maven-plugin-0.1.1.jar + - GOCD_PLUGIN_s3-fetch=https://github.com/indix/gocd-s3-artifacts/releases/download/v2.0.2/s3fetch-assembly-2.0.2.jar + - GOCD_PLUGIN_s3-publish=https://github.com/indix/gocd-s3-artifacts/releases/download/v2.0.2/s3publish-assembly-2.0.2.jar + - GOCD_PLUGIN_nessus-scan=https://github.com/Haufe-Lexware/gocd-plugins/releases/download/v1.0.0-beta/gocd-nessus-scan-plugin-1.0.0.jar + - GOCD_PLUGIN_sonar=https://github.com/Haufe-Lexware/gocd-plugins/releases/download/v1.0.0-beta/gocd-sonar-qualitygates-plugin-1.0.0.jar + - GOCD_PLUGIN_gitlab-auth=https://github.com/gocd-contrib/gocd-oauth-login/releases/download/v2.3/gitlab-oauth-login-2.3.jar + - GOCD_PLUGIN_google-auth=https://github.com/gocd-contrib/gocd-oauth-login/releases/download/v2.3/google-oauth-login-2.3.jar + - GOCD_PLUGIN_github-auth=https://github.com/gocd-contrib/gocd-oauth-login/releases/download/v2.3/github-oauth-login-2.3.jar + {{- end}} + {{- if and (ne .Values.DEPLOY_LB "true") (.Values.PUBLISH_PORT)}} + ports: + - ${PUBLISH_PORT}:8153 + {{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + {{- if eq .Values.DEPLOY_LB "true"}} + lb: + image: rancher/lb-service-haproxy:v0.6.2 + {{- if (.Values.PUBLISH_PORT)}} + ports: + - ${PUBLISH_PORT}:8153/tcp + {{- else}} + expose: + - 8153:8153/tcp + {{- end}} + links: + - gocd-server:gocd-server + labels: + io.rancher.container.agent.role: environmentAdmin + io.rancher.container.create_agent: 'true' + {{- end}} + {{- end}} + {{- if eq .Values.DEPLOY_AGENT "true"}} + gocd-agent: + tty: true + image: webcenter/alpine-gocd-agent:17.3.0-1 + volumes: + {{- if eq (printf "%.1s" .Values.VOLUME_DRIVER_AGENT) "/"}} + - ${VOLUME_DRIVER_AGENT}:/data + {{- else}} + - gocd-agent-data:/data + {{- end}} + - gocd-scheduler-setting:/opt/scheduler + environment: + - GOCD_CONFIG_memory=${GOCD_AGENT_MEMORY} + - GOCD_CONFIG_agent_key=${GOCD_AGENT_KEY} + - GOCD_CONFIG_agent_resource_docker=${GOCD_AGENT_RESOURCE} + - DOCKER_HOST=docker-engine:2375 + {{- if eq .Values.DEPLOY_SERVER "true"}} + links: + - gocd-server:gocd-server + {{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.agent.role: environment + io.rancher.container.create_agent: 'true' + io.rancher.sidekicks: rancher-cattle-metadata,docker-engine + rancher-cattle-metadata: + network_mode: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: "true" + image: webcenter/rancher-cattle-metadata:1.0.1 + volumes: + - gocd-scheduler-setting:/opt/scheduler + docker-engine: + privileged: true + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + image: index.docker.io/docker:1.13-dind + volumes: + {{- if eq (printf "%.1s" .Values.VOLUME_DRIVER_AGENT) "/"}} + - ${VOLUME_DRIVER_AGENT}:/data + {{- else}} + - gocd-agent-data:/data + {{- end}} + {{- end}} + + +volumes: + gocd-scheduler-setting: + driver: local + per_container: true + {{- if ne (printf "%.1s" .Values.VOLUME_DRIVER_AGENT) "/"}} + gocd-agent-data: + driver: ${VOLUME_DRIVER_AGENT} + per_container: true + {{- end}} + {{- if ne (printf "%.1s" .Values.VOLUME_DRIVER_SERVER) "/"}} + gocd-server-data: + driver: ${VOLUME_DRIVER_SERVER} + {{- end}} diff --git a/templates/gocd/0/rancher-compose.yml b/templates/gocd/0/rancher-compose.yml new file mode 100644 index 0000000..11e6bb6 --- /dev/null +++ b/templates/gocd/0/rancher-compose.yml @@ -0,0 +1,155 @@ +version: '2' +catalog: + name: GoCD + version: 17.3.0-rancher1 + minimum_rancher_version: v1.5.0 + questions: + - variable: "DEPLOY_SERVER" + description: "Deploy GoCD server" + label: "Deploy GoCD server" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "DEPLOY_AGENT" + description: "Deploy GoCD agent" + label: "Deploy GoCD agent" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "GOCD_AGENT_SCALE" + description: "Number of GoCD agent" + label: "GoCD Agents" + required: true + default: 1 + type: "string" + - variable: "GOCD_AGENT_KEY" + description: "Key to use for auto registration agent" + label: "Agent key" + required: true + type: "password" + - variable: "GOCD_SERVER_MEMORY" + description: "Max memory allowed to GoCD server" + label: "Max memory for server" + type: "string" + required: true + default: "1024m" + - variable: "GOCD_AGENT_MEMORY" + description: "Max memory allowed to GoCD agent" + label: "Max memory for agent" + type: "string" + required: true + default: "2048m" + - variable: "GOCD_AGENT_RESOURCE" + description: "Resource name associated for agent" + label: "Resource name" + type: "string" + required: true + default: "docker" + - variable: "GOCD_USER" + description: "Login to connect on GoCD" + label: "Login" + type: "string" + required: true + default: "admin" + - variable: "GOCD_PASSWORD" + description: "Password to connect on GoCD" + label: "Password" + type: "password" + required: true + - variable: "GOCD_AGENT_PACKAGE" + description: "Install GoCD extra plugins" + label: "Install extra plugins" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "VOLUME_DRIVER_SERVER" + description: "Docker driver to store volume or base path for GoCD server" + label: "Volume drver / Path for server" + type: "string" + required: true + default: "local" + - variable: "VOLUME_DRIVER_AGENT" + description: "Docker driver to store volume or base path for GoCD agent" + label: "Volume drver / Path for agent" + type: "string" + required: true + default: "local" + - variable: "DEPLOY_LB" + description: "Deploy Loadbalancer" + label: "Deploy Loadbalancer" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "PUBLISH_PORT" + description: "Set port if you want publish external port for GoCD server or Loadbalancer" + label: "Publish port" + required: false + type: "string" + default: "8153" + - variable: "GOCD_SERVER_URL" + description: "The server URL use by agent to auto register. Don't touch if you deploy server and agent" + label: "Server URL" + required: true + type: "string" + default: "https://gocd-server:8154/go" + - variable: "CONFD_BACKEND" + description: "The confd backend to grab config" + label: "Confd backend" + required: true + default: "env" + type: "string" + - variable: "CONFD_NODES" + description: "The confd nodes" + label: "Confd nodes" + required: false + type: "string" + - variable: "CONFD_PREFIX" + description: "The confd prefix" + label: "Confd prefix" + required: true + default: "/gocd" + type: "string" + +services: + gocd-agent: + scale: ${GOCD_AGENT_SCALE} + retain_ip: true + gocd-server: + scale: 1 + retain_ip: false + health_check: + port: 8153 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: gocd-server + source_port: 8153 + target_port: 8153 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + interval: 2000 \ No newline at end of file diff --git a/templates/gocd/catalogIcon-gocd.png b/templates/gocd/catalogIcon-gocd.png new file mode 100644 index 0000000..8983baa Binary files /dev/null and b/templates/gocd/catalogIcon-gocd.png differ diff --git a/templates/gocd/config.yml b/templates/gocd/config.yml new file mode 100644 index 0000000..8c59e5e --- /dev/null +++ b/templates/gocd/config.yml @@ -0,0 +1,8 @@ +name: GoCD +description: | + GoCD Stack (server and agents) +version: 17.3.0-rancher1 +category: Continuous Integration +maintainer: "Sebastien Langoureaux " +license: Apache License +projectURL: https://www.gocd.io/ diff --git a/templates/gogs/0/docker-compose.yml b/templates/gogs/0/docker-compose.yml deleted file mode 100644 index cc95838..0000000 --- a/templates/gogs/0/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -gogs: - image: gogs/gogs:latest - ports: - - ${http_port}:3000 - - ${ssh_port}:22 - links: - - mysql:db - -mysql: - image: mysql:latest - ports: - - ${public_port}:3306 - environment: - MYSQL_ROOT_PASSWORD: ${mysql_password} diff --git a/templates/gogs/0/docker-compose.yml.tpl b/templates/gogs/0/docker-compose.yml.tpl new file mode 100644 index 0000000..ecb7c97 --- /dev/null +++ b/templates/gogs/0/docker-compose.yml.tpl @@ -0,0 +1,35 @@ +version: '2' +services: + gogs: + image: gogs/gogs:0.11.19 + volumes: + - gogs-data:/data +{{- if ne .Values.db_link ""}} + external_links: + - ${db_link}:db +{{- else}} + links: + - db:db + db: + image: mysql:5.5 + environment: + MYSQL_ROOT_PASSWORD: ${mysql_password} + MYSQL_USER: ${mysql_user} + MYSQL_PASSWORD: ${mysql_password} + MYSQL_DATABASE: ${mysql_db} + volumes: + - gogs-db:/var/lib/mysql +{{- end}} + lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - ${http_port}:${http_port}/tcp + - ${ssh_port}:${ssh_port}/tcp +volumes: + gogs-data: + driver: ${volume_driver} +{{- if eq .Values.db_link ""}} + gogs-db: + driver: ${volume_driver} +{{- end}} + diff --git a/templates/gogs/0/rancher-compose.yml b/templates/gogs/0/rancher-compose.yml index b9cf7c4..697a011 100644 --- a/templates/gogs/0/rancher-compose.yml +++ b/templates/gogs/0/rancher-compose.yml @@ -1,33 +1,94 @@ -.catalog: +version: '2' +catalog: name: "Gogs" - version: "v0.8.43" + version: "v0.11.19" description: "A painless self-hosted Git service" uuid: gogs-0 minimum_rancher_version: v0.51.0 questions: - - variable: public_port - description: "public port to access the mysql server" - label: "Public Port" - required: true - default: "3306" - type: "int" - variable: http_port description: "http port to access gogs webui" label: "Http Port" required: true - default: "10080" + default: "8080" type: "int" - variable: ssh_port description: "ssh port to access gogs cli" label: "SSH Port" required: true - default: "222" + default: "2222" type: "int" + - variable: "volume_driver" + description: "Volume driver to associate with this service" + label: "Volume Driver" + required: true + default: "local" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + - variable: "db_link" + description: | + DB external service link cluster. + label: "External db service" + default: "" + required: false + type: "service" + - variable: mysql_db + description: "mysql db" + label: "Mysql db" + required: true + default: "gogs" + type: "string" + - variable: mysql_user + description: "mysql user" + label: "Mysql User" + required: true + default: "gogs" + type: "string" - variable: mysql_password description: "mysql root password" label: "Mysql Password" required: true - default: "" + default: "default_pass" type: "password" - -gogs: +services: + gogs: + scale: 1 + retain_ip: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 3000 + unhealthy_threshold: 3 + initializing_timeout: 300000 + interval: 2000 + strategy: recreate + request_line: GET "/" "HTTP/1.0" + reinitializing_timeout: 120000 + lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: gogs + source_port: ${http_port} + target_port: 3000 + - priority: 2 + protocol: tcp + service: gogs + source_port: ${ssh_port} + target_port: 22 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + reinitializing_timeout: 60000 diff --git a/templates/gogs/config.yml b/templates/gogs/config.yml index be2e008..c675211 100644 --- a/templates/gogs/config.yml +++ b/templates/gogs/config.yml @@ -1,5 +1,5 @@ name: Gogs description: | A painless self-hosted Git service -version: v0.8.43 +version: v0.11.19 category: Git diff --git a/templates/influxdb/0/README.md b/templates/influxdb/0/README.md new file mode 100644 index 0000000..ef7aab2 --- /dev/null +++ b/templates/influxdb/0/README.md @@ -0,0 +1,20 @@ +# Influxdb + +### Info: + + This template deploys a Influxdb. + + +### Usage: + + Select influxdb from catalog. + + Change the following cloud9 default parameters, if you need: + +- Expose influxdb=true # Exposed influxdb service +- Influxdb port=8086 # Influxdb exposed port + + Click deploy. + + Influxdb can now be accessed over the Rancher network and over exposed port. + diff --git a/templates/influxdb/0/docker-compose.yml.tpl b/templates/influxdb/0/docker-compose.yml.tpl new file mode 100644 index 0000000..63628c5 --- /dev/null +++ b/templates/influxdb/0/docker-compose.yml.tpl @@ -0,0 +1,36 @@ +version: '2' +services: +{{- if eq .Values.EXPOSE_SERVICE "true"}} + lb: + image: rancher/lb-service-haproxy:v0.6.2 + ports: + - ${influxdb_port}:8086/tcp + labels: + io.rancher.container.agent.role: environmentAdmin + io.rancher.container.create_agent: 'true' +{{- end}} + influxdb: + image: influxdb:1.2.2-alpine + stdin_open: true + tty: true + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: influxdb-volume + volumes_from: + - influxdb-volume + influxdb-volume: + network_mode: "none" + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=0 + - SERVICE_GID=0 + - SERVICE_VOLUME=/var/lib/influxdb + volumes: + - /var/lib/influxdb + volume_driver: local + image: rawmind/alpine-volume:0.0.2-1 + diff --git a/templates/influxdb/0/rancher-compose.yml b/templates/influxdb/0/rancher-compose.yml new file mode 100644 index 0000000..f0f0f16 --- /dev/null +++ b/templates/influxdb/0/rancher-compose.yml @@ -0,0 +1,55 @@ +.catalog: + name: Influxdb + description: | + Influxdb + version: 1.2.2-rancher1 + minimum_rancher_version: v1.0.0 + maintainer: "Raul Sanchez " + uuid: influxdb-0 + questions: + - variable: "EXPOSE_SERVICE" + description: "Expose Influxdb" + label: "Expose influxdb:" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "influxdb_port" + description: | + Port to expose. + label: "Influxdb port:" + default: "8086" + required: true + type: "int" +version: '2' +services: + lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - hostname: '' + priority: 1 + protocol: http + service: influxdb + source_port: ${influxdb_port} + target_port: 8086 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + influxdb: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 8086 + unhealthy_threshold: 3 + interval: 2000 + diff --git a/templates/influxdb/catalogIcon-influxdb.svg b/templates/influxdb/catalogIcon-influxdb.svg new file mode 100644 index 0000000..a44cb48 --- /dev/null +++ b/templates/influxdb/catalogIcon-influxdb.svg @@ -0,0 +1,81 @@ + + + + + + diff --git a/templates/influxdb/config.yml b/templates/influxdb/config.yml new file mode 100644 index 0000000..c437592 --- /dev/null +++ b/templates/influxdb/config.yml @@ -0,0 +1,7 @@ +name: Influxdb +description: | + Influxdb +version: 1.2.2-rancher1 +category: Databases +maintainer: "Raul Sanchez " +license: diff --git a/templates/iron-functions/0/docker-compose.yml b/templates/iron-functions/0/docker-compose.yml new file mode 100644 index 0000000..d2fe381 --- /dev/null +++ b/templates/iron-functions/0/docker-compose.yml @@ -0,0 +1,75 @@ +version: '2' +services: + functions-ui: + image: iron/functions-ui:latest + environment: + API_URL: http://api:8080 + stdin_open: true + tty: true + links: + - functions-worker:api + labels: + io.rancher.container.pull_image: always + api-lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - 8080:8080/tcp + - 4000:4000/tcp + labels: + io.rancher.container.agent.role: environmentAdmin + io.rancher.container.create_agent: 'true' + setup-dbuser: + image: wjimenez5271/postgres_client:v2 + environment: + PGPASSWORD: ironfunctions + PGUSER: postgres + PGHOST: postgres + PGQUERY: GRANT ALL PRIVILEGES ON DATABASE funcs TO postgres; + SLEEP_BEFORE_EXEC: '5' + stdin_open: true + tty: true + labels: + io.rancher.container.pull_image: always + io.rancher.container.start_once: 'true' + functions-worker: + image: iron/functions:0.2.59 + environment: + MQ_URL: redis://redis:6379/ + DB_URL: postgres://postgres:ironfunctions@postgres/funcs?sslmode=disable + stdin_open: true + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /opt/ironfunc/:/app/data + tty: true + links: + - postgres:postgres + - redis:redis + labels: + io.rancher.container.pull_image: always + setup-db: + image: wjimenez5271/postgres_client:v2 + environment: + PGPASSWORD: ironfunctions + PGUSER: postgres + PGHOST: postgres + PGQUERY: CREATE DATABASE funcs; + stdin_open: true + tty: true + labels: + io.rancher.container.pull_image: always + io.rancher.container.start_once: 'true' + postgres: + image: postgres:9.6.3 + environment: + POSTGRES_PASSWORD: ironfunctions + stdin_open: true + tty: true + labels: + io.rancher.container.pull_image: always + io.rancher.sidekicks: setup-db,setup-dbuser + redis: + image: redis:4.0.1 + stdin_open: true + tty: true + labels: + io.rancher.container.pull_image: always diff --git a/templates/iron-functions/0/rancher-compose.yml b/templates/iron-functions/0/rancher-compose.yml new file mode 100644 index 0000000..dc0b72b --- /dev/null +++ b/templates/iron-functions/0/rancher-compose.yml @@ -0,0 +1,52 @@ +.catalog: + name: "IronFunctions" + version: "v0.0.2" + description: "Serverless platform using Docker" + uuid: ironfunc-0 + minimum_rancher_version: v1.5.0 + + +version: '2' +services: + functions-ui: + scale: 1 + start_on_create: true + api-lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: tcp + service: functions-worker + source_port: 8080 + target_port: 8080 + - path: '' + priority: 2 + protocol: tcp + service: functions-ui + source_port: 4000 + target_port: 4000 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate + setup-dbuser: + scale: 1 + start_on_create: true + functions-worker: + scale: 1 + start_on_create: true + setup-db: + scale: 1 + start_on_create: true + postgres: + scale: 1 + start_on_create: true + redis: + scale: 1 + start_on_create: true diff --git a/templates/iron-functions/catalogIcon-iron-functions.svg b/templates/iron-functions/catalogIcon-iron-functions.svg new file mode 100644 index 0000000..3c6de8e --- /dev/null +++ b/templates/iron-functions/catalogIcon-iron-functions.svg @@ -0,0 +1,109 @@ + + + + + + image/svg+xml + + + + + + + + ironfunction + + + + + + + + + + + + + + + + + + + + diff --git a/templates/iron-functions/config.yml b/templates/iron-functions/config.yml new file mode 100644 index 0000000..ce3c9f5 --- /dev/null +++ b/templates/iron-functions/config.yml @@ -0,0 +1,9 @@ +name: IronFunctions +description: | + Serverless platform using Docker (https://github.com/iron-io/functions) +version: v0.0.2 +category: Platform +maintainer: "William Jimenez " +minimum_rancher_version: v1.5.0 +license: Apache License 2.0 +projectURL: https://github.com/wjimenez5271/rancher-iron-functions diff --git a/templates/janitor/3/docker-compose.yml b/templates/janitor/3/docker-compose.yml index 3109a9a..431ade2 100644 --- a/templates/janitor/3/docker-compose.yml +++ b/templates/janitor/3/docker-compose.yml @@ -6,8 +6,8 @@ cleanup: KEEP_IMAGES: "${KEEP}" KEEP_CONTAINERS: "${KEEPC}" KEEP_CONTAINERS_NAMED: "${KEEPCN}" - LOOP: "true" - DEBUG: "0" + LOOP: "${LOOP}" + DEBUG: "${DEBUG}" labels: io.rancher.scheduler.global: "true" io.rancher.scheduler.affinity:host_label_ne: "${EXCLUDE_LABEL}" diff --git a/templates/janitor/3/rancher-compose.yml b/templates/janitor/3/rancher-compose.yml index 19ca95b..c10ddb6 100644 --- a/templates/janitor/3/rancher-compose.yml +++ b/templates/janitor/3/rancher-compose.yml @@ -34,3 +34,21 @@ default: "**None**" required: false type: "string" + - variable: "DEBUG" + label: "Enable more debugging output on pattern matches" + description: "Read https://github.com/meltwater/docker-cleanup#environment-variables" + required: true + default: 0 + type: "enum" + options: + - 0 + - 1 + - variable: "LOOP" + label: "Ability to do non-looped cleanups, run it once and exit. Defaults to yes to run it forever in loops." + description: "Read https://github.com/meltwater/docker-cleanup#environment-variables" + required: true + default: true + type: "enum" + options: + - false + - true diff --git a/templates/janitor/4/docker-compose.yml b/templates/janitor/4/docker-compose.yml new file mode 100644 index 0000000..431ade2 --- /dev/null +++ b/templates/janitor/4/docker-compose.yml @@ -0,0 +1,20 @@ +cleanup: + image: meltwater/docker-cleanup:1.8.0 + environment: + CLEAN_PERIOD: ${FREQUENCY} + DELAY_TIME: "900" + KEEP_IMAGES: "${KEEP}" + KEEP_CONTAINERS: "${KEEPC}" + KEEP_CONTAINERS_NAMED: "${KEEPCN}" + LOOP: "${LOOP}" + DEBUG: "${DEBUG}" + labels: + io.rancher.scheduler.global: "true" + io.rancher.scheduler.affinity:host_label_ne: "${EXCLUDE_LABEL}" + net: none + privileged: true + tty: false + stdin_open: false + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - /var/lib/docker:/var/lib/docker diff --git a/templates/janitor/4/rancher-compose.yml b/templates/janitor/4/rancher-compose.yml new file mode 100644 index 0000000..8db4a8a --- /dev/null +++ b/templates/janitor/4/rancher-compose.yml @@ -0,0 +1,54 @@ +.catalog: + name: "Janitor" + version: "v1.7.1" + description: "Docker cleanup" + uuid: janitor-3 + questions: + - variable: "FREQUENCY" + label: "Frequency" + description: "Run the cleanup on a cycle of this many seconds" + default: 3600 + required: true + type: "int" + - variable: "EXCLUDE_LABEL" + label: "Exclude label" + description: "Specify a Rancher host label here that will be used to determine on which hosts the Janitor container should not deploy." + default: janitor.exclude=true + required: true + type: "string" + - variable: "KEEP" + label: "Keep images" + description: "A comma separated list of images that should never be removed. These are left-anchored Bash Shell Wildcard patterns." + default: "rancher/" + required: false + type: "string" + - variable: "KEEPC" + label: "Keep containers" + description: "A comma separated list of images that should never have stopped containers removed. These are left-anchored Bash Shell Wildcard patterns." + default: "*:*" + required: false + type: "string" + - variable: "KEEPCN" + label: "Keep named containers" + description: "A comma separated list of names of exited or dead container that should never be removed. These are left-anchored Bash Shell Wildcard patterns." + default: "*-datavolume" + required: false + type: "string" + - variable: "DEBUG" + label: "Enable more debugging output on pattern matches" + description: "Read https://github.com/meltwater/docker-cleanup#environment-variables" + required: true + default: 0 + type: "enum" + options: + - 0 + - 1 + - variable: "LOOP" + label: "Ability to do non-looped cleanups, run it once and exit. Defaults to yes to run it forever in loops." + description: "Read https://github.com/meltwater/docker-cleanup#environment-variables" + required: true + default: true + type: "enum" + options: + - false + - true diff --git a/templates/janitor/config.yml b/templates/janitor/config.yml index 082b015..b128907 100644 --- a/templates/janitor/config.yml +++ b/templates/janitor/config.yml @@ -1,7 +1,7 @@ name: Janitor description: | Automatic cleanup of unused images on hosts, in order to save disk space. -version: v1.7 +version: v1.7.1 category: Monitoring maintainer: Steve Shipway diff --git a/templates/jenkins-ci/2/docker-compose.yml b/templates/jenkins-ci/2/docker-compose.yml index 33f5de9..edb56fb 100644 --- a/templates/jenkins-ci/2/docker-compose.yml +++ b/templates/jenkins-ci/2/docker-compose.yml @@ -1,5 +1,5 @@ jenkins-primary: - image: "jenkins:2.19.4" + image: "jenkins:2.32.2" ports: - "${PORT}:8080" labels: diff --git a/templates/jenkins-ci/2/rancher-compose.yml b/templates/jenkins-ci/2/rancher-compose.yml index df16cf0..b0feb48 100644 --- a/templates/jenkins-ci/2/rancher-compose.yml +++ b/templates/jenkins-ci/2/rancher-compose.yml @@ -1,6 +1,6 @@ .catalog: name: Jenkins - version: 2.19.4-rancher1 + version: 2.32.2-rancher1 description: | Jenkins CI management server. questions: diff --git a/templates/jenkins-ci/3/docker-compose.yml b/templates/jenkins-ci/3/docker-compose.yml new file mode 100644 index 0000000..0f694e9 --- /dev/null +++ b/templates/jenkins-ci/3/docker-compose.yml @@ -0,0 +1,20 @@ +jenkins-primary: + image: "jenkins:2.60.1" + ports: + - "${PORT}:8080" + labels: + io.rancher.sidekicks: jenkins-plugins,jenkins-datavolume + io.rancher.container.hostname_override: container_name + volumes_from: + - jenkins-plugins + - jenkins-datavolume + entrypoint: /usr/share/jenkins/rancher/jenkins.sh +jenkins-plugins: + image: rancher/jenkins-plugins:v0.1.1 +jenkins-datavolume: + image: "busybox" + volumes: + - ${volume_work}:/var/jenkins_home + labels: + io.rancher.container.start_once: true + entrypoint: ["chown", "-R", "1000:1000", "/var/jenkins_home"] diff --git a/templates/jenkins-ci/3/rancher-compose.yml b/templates/jenkins-ci/3/rancher-compose.yml new file mode 100644 index 0000000..ae6b848 --- /dev/null +++ b/templates/jenkins-ci/3/rancher-compose.yml @@ -0,0 +1,42 @@ +.catalog: + name: Jenkins + version: 2.60.1-rancher1 + description: | + Jenkins CI management server. + questions: + - variable: "PORT" + type: "int" + label: "Port Number" + description: "Which port should Jenkins listen on?" + default: 8080 + required: true + - variable: "volume_work" + description: "Work volume to save jenkins data" + label: "Work volume:" + required: true + default: "/var/lib/docker/jenkins-ci" + type: "string" + - variable: "plugins" + type: "multiline" + label: "List of Plugins" + description: | + List of plugins in the format [:] + one entry per line. + default: | + credentials + git + git-client + github + github-api + github-oauth + greenballs + junit + plain-credentials + scm-api + ssh-credentials + ssh-slaves + swarm +jenkins-primary: + metadata: + plugins: | + ${plugins} diff --git a/templates/jenkins-ci/config.yml b/templates/jenkins-ci/config.yml index d840a03..42c8ad3 100644 --- a/templates/jenkins-ci/config.yml +++ b/templates/jenkins-ci/config.yml @@ -1,5 +1,5 @@ name: Jenkins description: | Jenkins CI server (LTS) -version: 2.19.4-rancher1 +version: 2.60.1-rancher1 category: Continuous Integration diff --git a/templates/kafka/2/README.md b/templates/kafka/2/README.md new file mode 100644 index 0000000..df396ad --- /dev/null +++ b/templates/kafka/2/README.md @@ -0,0 +1,30 @@ +# Apache Kafka (Experimental) + +### Info: + + This template creates, scale in and scale out a multinodes kafka broker cluster on top of Rancher. The configuration is generated with confd from Rancher metadata. + Cluster size are variable after deployment, and get reconfigured after refresh interval. + + +### Usage: + + Select Apache Kafka from catalog. + + Enter the number of nodes, mem and refresh interval for the kafka cluster. + + Change the following kafka default parameters, if you need: + +- kafka_scale=3 # kafka scale to deploy. +- kafka_mem=512 # kafka broker memory. +- kafka_log_dir="/opt/kafka/logs" # Kafka log dir. +- kafka_log_retention="168" # kafka log retention. +- kafka_num_partitions="1" # Kafka partitions number +- kafka_delete_topics="false" # kafka delete topics +- kafka_pub_ip= < true | false > # Advertise public ip to zookeeper. +- zk_link="kafka-zk/zk" # zookeeper stack/service to connect to. + + Click deploy. + + Kafka can now be accessed over the Rancher network. + + Note: When you scale the cluster, zero downtime is not guaranteed..yet.. diff --git a/templates/kafka/2/docker-compose.yml b/templates/kafka/2/docker-compose.yml new file mode 100644 index 0000000..373ffc0 --- /dev/null +++ b/templates/kafka/2/docker-compose.yml @@ -0,0 +1,44 @@ +broker: + tty: true + image: rawmind/alpine-kafka:0.10.2.1 + volumes_from: + - broker-volume + - broker-conf + environment: + - JVMFLAGS=-Xmx${kafka_mem}m -Xms${kafka_mem}m + - CONFD_INTERVAL=${kafka_interval} + - ZK_SERVICE=${zk_link} + - KAFKA_DELETE_TOPICS=${kafka_delete_topics} + - KAFKA_LOG_DIRS=${kafka_log_dir} + - KAFKA_LOG_RETENTION_HOURS=${kafka_log_retention} + - KAFKA_NUM_PARTITIONS=${kafka_num_partitions} + - ADVERTISE_PUB_IP=${kafka_pub_ip} + external_links: + - ${zk_link}:zk + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: broker-volume, broker-conf +broker-conf: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + image: rawmind/rancher-kafka:0.10.2.0 + volumes: + - /opt/tools +broker-volume: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10003 + - SERVICE_GID=10003 + - SERVICE_VOLUME=${kafka_log_dir} + volumes: + - ${kafka_log_dir} + volume_driver: local + image: rawmind/alpine-volume:0.0.2-1 diff --git a/templates/kafka/2/rancher-compose.yml b/templates/kafka/2/rancher-compose.yml new file mode 100644 index 0000000..9c02325 --- /dev/null +++ b/templates/kafka/2/rancher-compose.yml @@ -0,0 +1,80 @@ +.catalog: + name: Kafka + version: 0.10.2.1-rancher1 + description: | + (Experimental) Apache Kafka cluster. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: kafka-0 + questions: + - variable: "kafka_scale" + description: "Number of brokers nodes. Note: Recommended an odd number" + label: "Broker Nodes:" + required: true + default: 3 + type: "int" + - variable: "kafka_mem" + description: "Amount of memory to config brokers." + label: "Broker Memory (mb):" + required: true + default: 1024 + type: "string" + - variable: "kafka_log_dir" + description: "Broker volume to log data" + label: "Broker log volume:" + required: true + default: "/opt/kafka/logs" + type: "string" + - variable: "kafka_log_retention" + description: "Broker log retention in hours" + label: "Broker log retention (h):" + required: true + default: "168" + type: "int" + - variable: "kafka_num_partitions" + description: "Number of broker partitions" + label: "Broker partitions:" + required: true + default: "1" + type: "int" + - variable: "kafka_delete_topics" + label: "Kafka delete topics:" + description: | + Enable delete topics in kafka. + default: false + required: true + type: enum + options: + - false + - true + - variable: "kafka_interval" + description: "Interval to poll/apply configuration changes. 0 to disable" + label: "Broker Interval (s):" + required: true + default: 60 + type: "int" + - variable: "kafka_pub_ip" + description: "Advertise local and host public ip" + label: "Broker public ip:" + required: false + default: false + type: "boolean" + - variable: "zk_link" + description: | + Choose the Zookeeper service to use. + It's really recommended a dedicated zookeeper service just for Kafka. + label: "Zookeeper stack/service" + default: "kafka-zk/zk" + required: true + type: "service" +broker: + scale: ${kafka_scale} + retain_ip: true + health_check: + port: 9092 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + diff --git a/templates/kafka/3/README.md b/templates/kafka/3/README.md new file mode 100644 index 0000000..43dac9e --- /dev/null +++ b/templates/kafka/3/README.md @@ -0,0 +1,32 @@ +# Apache Kafka (Experimental) + +### Info: + + This template creates, scale in and scale out a multinodes kafka broker cluster on top of Rancher. The configuration is generated with confd from Rancher metadata. + Cluster size are variable after deployment, and get reconfigured after refresh interval. + + +### Usage: + + Select Apache Kafka from catalog. + + Enter the number of nodes, mem and refresh interval for the kafka cluster. + + Change the following kafka default parameters, if you need: + +- kafka_scale=3 # kafka scale to deploy. +- kafka_mem=512 # kafka broker memory. +- kafka_log_dir="/opt/kafka/logs" # Kafka log dir. +- kafka_log_retention="168" # kafka log retention. +- kafka_num_partitions="1" # Kafka partitions number +- kafka_delete_topics="false" # kafka delete topics +- kafka_auto_create_topics="true" # kafka auto create topics +- kafka_replication_factor=1 # Kafka replication factor +- kafka_pub_ip= < true | false > # Advertise public ip to zookeeper. +- zk_link="kafka-zk/zk" # zookeeper stack/service to connect to. + + Click deploy. + + Kafka can now be accessed over the Rancher network. + + Note: When you scale the cluster, zero downtime is not guaranteed..yet.. diff --git a/templates/kafka/3/docker-compose.yml b/templates/kafka/3/docker-compose.yml new file mode 100644 index 0000000..8e4d841 --- /dev/null +++ b/templates/kafka/3/docker-compose.yml @@ -0,0 +1,46 @@ +broker: + tty: true + image: rawmind/alpine-kafka:0.11.0.0-1 + volumes_from: + - broker-volume + - broker-conf + environment: + - JVMFLAGS=-Xmx${kafka_mem}m -Xms${kafka_mem}m + - CONFD_INTERVAL=${kafka_interval} + - ZK_SERVICE=${zk_link} + - KAFKA_DELETE_TOPICS=${kafka_delete_topics} + - KAFKA_LOG_DIRS=${kafka_log_dir} + - KAFKA_LOG_RETENTION_HOURS=${kafka_log_retention} + - KAFKA_NUM_PARTITIONS=${kafka_num_partitions} + - ADVERTISE_PUB_IP=${kafka_pub_ip} + - KAFKA_AUTO_CREATE_TOPICS=${kafka_auto_create_topics} + - KAFKA_REPLICATION_FACTOR=${kafka_replication_factor} + external_links: + - ${zk_link}:zk + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: broker-volume, broker-conf +broker-conf: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + image: rawmind/rancher-kafka:0.11.0.0-1 + volumes: + - /opt/tools +broker-volume: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10003 + - SERVICE_GID=10003 + - SERVICE_VOLUME=${kafka_log_dir} + volumes: + - ${kafka_log_dir} + volume_driver: local + image: rawmind/alpine-volume:0.0.2-1 diff --git a/templates/kafka/3/rancher-compose.yml b/templates/kafka/3/rancher-compose.yml new file mode 100644 index 0000000..69c89bf --- /dev/null +++ b/templates/kafka/3/rancher-compose.yml @@ -0,0 +1,96 @@ +.catalog: + name: Kafka + version: 0.11.0.0-rancher1 + description: | + (Experimental) Apache Kafka cluster. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: kafka-0 + questions: + - variable: "kafka_scale" + description: "Number of brokers nodes. Note: Recommended an odd number" + label: "Broker Nodes:" + required: true + default: 3 + type: "int" + - variable: "kafka_mem" + description: "Amount of memory to config brokers." + label: "Broker Memory (mb):" + required: true + default: 1024 + type: "string" + - variable: "kafka_log_dir" + description: "Broker volume to log data" + label: "Broker log volume:" + required: true + default: "/opt/kafka/logs" + type: "string" + - variable: "kafka_log_retention" + description: "Broker log retention in hours" + label: "Broker log retention (h):" + required: true + default: "168" + type: "int" + - variable: "kafka_num_partitions" + description: "Number of broker partitions" + label: "Broker partitions:" + required: true + default: "1" + type: "int" + - variable: "kafka_delete_topics" + label: "Delete topics:" + description: | + Enable delete topics in kafka. + default: false + required: true + type: enum + options: + - false + - true + - variable: "kafka_auto_create_topics" + label: "Auto create topics:" + description: | + Enable auto create topics in kafka. + default: true + required: true + type: enum + options: + - false + - true + - variable: "kafka_replication_factor" + description: "Topics replication factor" + label: "Replication factor:" + required: true + default: 1 + type: "int" + - variable: "kafka_interval" + description: "Interval to poll/apply configuration changes. 0 to disable" + label: "Broker Interval (s):" + required: true + default: 60 + type: "int" + - variable: "kafka_pub_ip" + description: "Advertise local and host public ip" + label: "Broker public ip:" + required: false + default: false + type: "boolean" + - variable: "zk_link" + description: | + Choose the Zookeeper service to use. + It's really recommended a dedicated zookeeper service just for Kafka. + label: "Zookeeper stack/service" + default: "kafka-zk/zk" + required: true + type: "service" +broker: + scale: ${kafka_scale} + retain_ip: true + health_check: + port: 9092 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + diff --git a/templates/kafka/config.yml b/templates/kafka/config.yml index 1bee24d..af07587 100644 --- a/templates/kafka/config.yml +++ b/templates/kafka/config.yml @@ -1,7 +1,7 @@ name: Apache Kafka description: | (Experimental) Kafka cluster -version: 0.10.0.1-rancher1 +version: 0.11.0.0-rancher1 category: Clustering maintainer: "Raul Sanchez " minimum_rancher_version: v0.59.0 diff --git a/templates/keepalived/0/README.md b/templates/keepalived/0/README.md new file mode 100755 index 0000000..0c5e43b --- /dev/null +++ b/templates/keepalived/0/README.md @@ -0,0 +1,50 @@ +# Keepalived + +This catalog recipe enables unicast VRRP based failover for one or more floating IP Addresses. It's intended deployment is for use on a pair edge or ingress nodes where forward-facing load-balancers or other like services will be scheduled. + + +### Form Fields +* **Update Host Sysctl** - If `true` automatically sets the needed sysctl setting on the host. +* **Host Label Name** - Host label key name used to schedule keepalived master and backup instances. +* **Master Label** - The value of the keepalived host Label to signify the master instance. +* **Backup Label** - The value of the keepalived host Label to signify the backup instance. +* **Interface Name** - The host interface that keepalived will monitor and use for VRRP traffic. +* **Virtual Router ID** - A unique number from 0 to 255 that should identify the VRRP group. +* **Master IP** - The IP on the master host that the keepalived daemon should bind to. +* **Backup IP** - The IP on the backup host that the keepalived daemon should bind to. +* **Virtual IP** - Virtual IP to be created. Must be in ip notation: `/ dev ` + +### Requirements + +The host must have the sysctl setting `net.ipv4.ip_nonlocal_bind=1` configured. + +### Usage + +This service is intended to be deployed to edge nodes with a `master` and `backup` deployed respectively. One or more Virtual IPs may then be bound to hosts. These hosts should have an additional label used for load-balancer scheduling e.g. `ingress=true` + +#### Adding an HA Load Balancer Service + +**Ensure your edge hosts have an additional host label before proceeding** + +1. From the Stack menu add a new `Load Balancer`. +2. Set `Scale` to be `Always run one instance of this container on every host`. +3. Add an appropriate `Name` and `Description`. +4. In the `Port Rules` section, click `Show host IP address options.` This enables the Host IP Field. +5. Update the `Port Rules` with the `Host IP` field set to your `Virtual IP` as defined in the keepalived config. Configure the rest of the fields as needed for your application. +6. Click on the `Scheduling` tab and click on `Add Scheduling Rule`. +7. Create a rule where "The host `must` have a `host label` of `` = ``. +8. Click Create. + +#### Adding additional Virtual IPs to the keepalived Service + +1. From the Stack menu expand the `keepalived` service. +2. Select upgrade on the `keepalived-backup` service. +3. Add a new Environment Variable called `KEEPALIVED_VIRTUAL_IPADDRESS_`. Where `` should be a unique value from 0-999. e.g. `KEEPALIVED_VIRTUAL_IPADDRESS_2`. +4. Set the value to be a **QUOTED STRING** with an additional virtual IP following the standard ip format of `/ dev `. e.g. `10.255.33.102/24 dev eth0`. +5. Press `Upgrade`. +6. Repeat the same steps for the `keepalived-master` service. + + +### Troubleshooting + +For further help see the main [arc-ts/keepalived git repo](https://github.com/arc-ts/keepalived) \ No newline at end of file diff --git a/templates/keepalived/0/docker-compose.yml.tpl b/templates/keepalived/0/docker-compose.yml.tpl new file mode 100755 index 0000000..0d6cec3 --- /dev/null +++ b/templates/keepalived/0/docker-compose.yml.tpl @@ -0,0 +1,56 @@ +version: '2' +services: + keepalived-master: + restart: always + image: arcts/keepalived:1.1.0 + network_mode: host + cap_add: + - NET_ADMIN + environment: + KEEPALIVED_AUTOCONF: true + KEEPALIVED_STATE: MASTER + KEEPALIVED_INTERFACE: ${interface} + KEEPALIVED_VIRTUAL_ROUTER_ID: ${router_id} + KEEPALIVED_UNICAST_SRC_IP: ${master_ip} + KEEPALIVED_UNICAST_PEER_0: ${backup_ip} + KEEPALIVED_TRACK_INTERFACE_1: ${interface} + KEEPALIVED_VIRTUAL_IPADDRESS_1: "\"${virtual_ip}\"" + labels: + io.rancher.scheduler.affinity:host_label: ${host_label}=${master_label} + {{- if eq .Values.update_sysctl "true" }} + io.rancher.sidekicks: keepalived-sysctl + {{- end}} + + keepalived-backup: + restart: always + image: arcts/keepalived:1.1.0 + network_mode: host + cap_add: + - NET_ADMIN + environment: + KEEPALIVED_AUTOCONF: true + KEEPALIVED_STATE: BACKUP + KEEPALIVED_INTERFACE: ${interface} + KEEPALIVED_VIRTUAL_ROUTER_ID: ${router_id} + KEEPALIVED_UNICAST_SRC_IP: ${backup_ip} + KEEPALIVED_UNICAST_PEER_0: ${master_ip} + KEEPALIVED_TRACK_INTERFACE_1: ${interface} + KEEPALIVED_VIRTUAL_IPADDRESS_1: "\"${virtual_ip}\"" + labels: + io.rancher.scheduler.affinity:host_label: ${host_label}=${backup_label} + {{- if eq .Values.update_sysctl "true" }} + io.rancher.sidekicks: keepalived-sysctl + {{- end}} + +{{- if eq .Values.update_sysctl "true" }} + keepalived-sysctl: + image: rawmind/alpine-sysctl:0.1-1 + network_mode: none + privileged: true + environment: + SYSCTL_KEY: net.ipv4.ip_nonlocal_bind + SYSCTL_VALUE: 1 + labels: + io.rancher.container.start_once: true +{{- end}} + diff --git a/templates/keepalived/0/rancher-compose.yml b/templates/keepalived/0/rancher-compose.yml new file mode 100755 index 0000000..00df4a4 --- /dev/null +++ b/templates/keepalived/0/rancher-compose.yml @@ -0,0 +1,63 @@ +.catalog: + name: "keepalived" + version: v1.0.1 + description: "Keepalived VRRP based HA service." + minimum_rancher_version: v0.46.0 + uuid: keepalived-1 + questions: + - variable: "update_sysctl" + description: | + Set true to update sysctl. + WARN: If set to true, sysctl key net.ipv4.ip_nonlocal_bind will be set to 1. + label: "Update Host Sysctl:" + type: "enum" + default: "false" + options: + - "true" + - "false" + required: true + - variable: "host_label" + description: "Host label key name used to schedule keepalived master and backup instances." + label: "Host Label Name:" + type: "string" + default: "vrrp_role" + required: true + - variable: "master_label" + description: "The value of the keepalived host Label to signify the master instance." + label: "Master Label:" + type: "string" + default: "master" + required: true + - variable: "backup_label" + description: "The value of the keepalived host Label to signify the backup instance." + label: "Backup Label:" + type: "string" + default: "backup" + required: true + - variable: "interface" + description: "The name of the host interface." + label: "Interface Name:" + type: "string" + default: "eth0" + required: true + - variable: "router_id" + description: "The virtual Router ID to assign to the VRRP Pair." + label: "Virtual Router ID:" + type: "int" + default: "2" + required: true + - variable: "master_ip" + description: "Host IP of master node" + label: "Master IP:" + type: "string" + required: true + - variable: "backup_ip" + description: "Host IP of backup node" + label: "Backup IP:" + type: "string" + required: true + - variable: "virtual_ip" + description: "Virtual IP to be created. MUST be in ip notation: / dev " + label: "Virtual IP:" + type: "string" + required: true diff --git a/templates/keepalived/catalogIcon-keepalived.svg b/templates/keepalived/catalogIcon-keepalived.svg new file mode 100644 index 0000000..7b82b7a --- /dev/null +++ b/templates/keepalived/catalogIcon-keepalived.svg @@ -0,0 +1,293 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + image/svg+xml + + + + + + + + + + ka + + + + diff --git a/templates/keepalived/config.yml b/templates/keepalived/config.yml new file mode 100755 index 0000000..b0e0aaf --- /dev/null +++ b/templates/keepalived/config.yml @@ -0,0 +1,5 @@ +name: keepalived +description: | + Keepalived enables services to be deployed in HA with VRRP based failover across multiple hosts. +version: v1.0.1 +category: Networking diff --git a/templates/kibana/3/docker-compose.yml b/templates/kibana/3/docker-compose.yml new file mode 100644 index 0000000..066e42e --- /dev/null +++ b/templates/kibana/3/docker-compose.yml @@ -0,0 +1,33 @@ +kibana-vip: + ports: + - "${public_port}:80" + restart: always + tty: true + image: rancher/load-balancer-service + links: + - nginx-proxy:kibana5 + stdin_open: true +nginx-proxy-conf: + image: rancher/nginx-conf:v0.2.0 + command: "-backend=rancher --prefix=/2015-07-25" + labels: + io.rancher.container.hostname_override: container_name +nginx-proxy: + image: rancher/nginx:v1.9.4-3 + volumes_from: + - nginx-proxy-conf + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: nginx-proxy-conf,kibana5 + external_links: + - ${elasticsearch_source}:elasticsearch +kibana5: + restart: always + tty: true + image: kibana:5.3.0 + net: "container:nginx-proxy" + stdin_open: true + environment: + ELASTICSEARCH_URL: "http://elasticsearch:9200" + labels: + io.rancher.container.hostname_override: container_name diff --git a/templates/kibana/3/rancher-compose.yml b/templates/kibana/3/rancher-compose.yml new file mode 100644 index 0000000..66479a4 --- /dev/null +++ b/templates/kibana/3/rancher-compose.yml @@ -0,0 +1,24 @@ +.catalog: + name: "Kibana" + version: "5.3.0-rancher1" + description: "Kibana: Explore & Visualize Your Data" + questions: + - variable: "elasticsearch_source" + description: "Link to elasticsearch service or stack/service" + label: "Elasticsearch source" + type: "service" + required: true + default: "es/elasticsearch-clients" + - variable: "public_port" + label: "Public Port" + description: "Unique public port for Kibana" + type: "int" + default: 80 + required: true + +nginx-proxy: + metadata: + nginx: + conf: + servername: "kibana" + upstream_port: 5601 diff --git a/templates/letsencrypt/4/README.md b/templates/letsencrypt/4/README.md new file mode 100644 index 0000000..0ce3020 --- /dev/null +++ b/templates/letsencrypt/4/README.md @@ -0,0 +1,101 @@ +# Let's Encrypt Certificate Manager + +### About +The Let's Encrypt Certificate Manager obtains a free (SAN) SSL Certificate from the [Let's Encrypt CA](https://letsencrypt.org/) and adds it to Rancher's certificate store. Once the certificate is created it is scheduled for automatic renewal 20-days before expiration. Rancher load balancer services are automatically updated to use the renewed certificate. + +### Changelog v0.5.0 + +- Added support for Aurora DNS, Azure DNS and NS1 +- Added support for stopping container after creating/renewing certificate +- Added configuration option to specify DNS resolvers to use (fixes an issue with private zones on AWS) +- Added configuration option to specify renewal grace period +- Added support for Rancher servers using self-signed certs +- Logs now contain ACME library messages + +### Usage + 1. Accept the terms of service. + 2. Select the API version to use. The Sandbox API should be used for testing purposes. + 3. Fill in your email address. + 4. Enter the name used for storing the certificate in Rancher and volumes. Any existing certificate by that name will be updated. + 5. Enter one or more domain names. The first domain will be used as the Common Name property of the certificate. + 6. Fill in the required credentials for the chosen provider. Note provider specific usage notes below. + +If you want the certificate to be automatically renewed, leave the service running. Otherwise you may remove the service once the certificate has appeared in Rancher's certificate store. + +### Store data in a persistent volume + +If you specify a name under "Volume Name" then account data, certificate and private key are stored in a (host scoped) Docker volume with the specified name. +To store the data in a stack scoped volume that can be shared with services running on other hosts, you should provide the name of an already active persistent storage service under "Persistent Storage Driver". See the [Storage Service documentation](https://docs.rancher.com/rancher/v1.3/en/rancher-services/storage-service/). + +#### Example + +1. Configure the service with a volume named "letsencrypt". +2. Mount the volume to `/etc/letsencrypt` in another service. + +This service can then access the certificate and key in the following locations: + +- `/etc/letsencrypt/production/certs//fullchain.pem` +- `/etc/letsencrypt/production/certs//privkey.pem` + +where `` is the name of the certificate sanitized to consist of only the following characters: `[a-zA-Z0-9-_.]`. + +### Provider specific usage + +#### AWS Route 53 + +Note: If you have both a private and public zone for the domain, make sure you configure the service to use public DNS resolvers (the default ones are fine). + +The following IAM policy describes the minimum permissions required when using AWS Route 53 for domain authorization. +Replace `` with the ID of the hosted zone that encloses the domain(s) for which you are going to obtain certificates. You may use a wildcard (*) in place of the ID to make this policy work with all of the hosted zones associated with an AWS account. + +```json +{ + "Version": "2012-10-17", + "Statement": [ + { + "Effect": "Allow", + "Action": [ + "route53:GetChange", + "route53:ListHostedZonesByName" + ], + "Resource": [ + "*" + ] + }, + { + "Effect": "Allow", + "Action": [ + "route53:ChangeResourceRecordSets" + ], + "Resource": [ + "arn:aws:route53:::hostedzone/" + ] + } + ] +} +``` + +#### OVH + +First create your credentials on https://eu.api.ovh.com/createToken/ by filling out the form like this: + +- `Account ID`: Your OVH account ID +- `Password`: Your password +- `Script name`: letsencrypt +- `Script description`: Letsencrypt for Rancher +- `Validity`: Unlimited +- `Rights`: + - GET /domain/zone/* + - POST /domain/zone/* + - DELETE /domain/zone/* + +Then deploy this service using the generated key, application secret and consumer key. + +#### HTTP + +If you prefer not to use a DNS-based challenge or your provider is not supported, you can use the HTTP challenge. +Simply choose `HTTP` from the list of providers. +Then make sure that HTTP requests to `domain.com/.well-known/acme-challenge` are forwarded to port 80 of the `rancher-letsencrypt` service, e.g. by configuring a Rancher load balancer accordingly. Make sure the reverse proxy passes the original `host` header to the backend. + +### Suggestions & bug reports +Please submit suggestions or any issues you find to the [rancher-letsencrypt](https://github.com/janeczku/rancher-letsencrypt) GitHub repo. \ No newline at end of file diff --git a/templates/letsencrypt/4/docker-compose.yml.tpl b/templates/letsencrypt/4/docker-compose.yml.tpl new file mode 100644 index 0000000..cc81f63 --- /dev/null +++ b/templates/letsencrypt/4/docker-compose.yml.tpl @@ -0,0 +1,57 @@ +version: '2' +services: + letsencrypt: + image: janeczku/rancher-letsencrypt:v0.5.0 + environment: + EULA: ${EULA} + API_VERSION: ${API_VERSION} + CERT_NAME: ${CERT_NAME} + EMAIL: ${EMAIL} + DOMAINS: ${DOMAINS} + DNS_RESOLVERS: ${DNS_RESOLVERS} + PUBLIC_KEY_TYPE: ${PUBLIC_KEY_TYPE} + RENEWAL_TIME: ${RENEWAL_TIME} + RENEWAL_PERIOD_DAYS: ${RENEWAL_PERIOD_DAYS} + PROVIDER: ${PROVIDER} + CLOUDFLARE_EMAIL: ${CLOUDFLARE_EMAIL} + CLOUDFLARE_KEY: ${CLOUDFLARE_KEY} + DO_ACCESS_TOKEN: ${DO_ACCESS_TOKEN} + AWS_ACCESS_KEY: ${AWS_ACCESS_KEY} + AWS_SECRET_KEY: ${AWS_SECRET_KEY} + DNSIMPLE_EMAIL: ${DNSIMPLE_EMAIL} + DNSIMPLE_KEY: ${DNSIMPLE_KEY} + DYN_CUSTOMER_NAME: ${DYN_CUSTOMER_NAME} + DYN_USER_NAME: ${DYN_USER_NAME} + DYN_PASSWORD: ${DYN_PASSWORD} + VULTR_API_KEY: ${VULTR_API_KEY} + OVH_APPLICATION_KEY: ${OVH_APPLICATION_KEY} + OVH_APPLICATION_SECRET: ${OVH_APPLICATION_SECRET} + OVH_CONSUMER_KEY: ${OVH_CONSUMER_KEY} + GANDI_API_KEY: ${GANDI_API_KEY} + AZURE_CLIENT_ID: ${AZURE_CLIENT_ID} + AZURE_CLIENT_SECRET: ${AZURE_CLIENT_SECRET} + AZURE_SUBSCRIPTION_ID: ${AZURE_SUBSCRIPTION_ID} + AZURE_TENANT_ID: ${AZURE_TENANT_ID} + AZURE_RESOURCE_GROUP: ${AZURE_RESOURCE_GROUP} + volumes: + - /var/lib/rancher:/var/lib/rancher + {{- if .Values.VOLUME_NAME}} + - {{.Values.VOLUME_NAME}}:/etc/letsencrypt + {{- end }} + labels: + io.rancher.container.create_agent: 'true' + io.rancher.container.agent.role: 'environment' + {{- if eq .Values.RUN_ONCE "true" }} + io.rancher.container.start_once: "true" + {{- end }} +{{- if .Values.VOLUME_NAME}} +volumes: + {{.Values.VOLUME_NAME}}: + {{- if .Values.STORAGE_DRIVER}} + driver: {{.Values.STORAGE_DRIVER}} + {{- if .Values.STORAGE_DRIVER_OPT}} + driver_opts: + {{.Values.STORAGE_DRIVER_OPT}} + {{- end }} + {{- end }} +{{- end }} diff --git a/templates/letsencrypt/4/rancher-compose.yml b/templates/letsencrypt/4/rancher-compose.yml new file mode 100644 index 0000000..3a14a35 --- /dev/null +++ b/templates/letsencrypt/4/rancher-compose.yml @@ -0,0 +1,226 @@ +.catalog: + name: Let's Encrypt + version: 0.5.0 + description: Trusted SSL certificates at zero cost + minimum_rancher_version: v1.5.0 + questions: + - variable: EULA + label: I Agree to the Let's Encrypt TOS + description: | + Read https://letsencrypt.org/documents/LE-SA-v1.0.1-July-27-2015.pdf + required: true + type: enum + options: + - "Yes" + - "No" + - variable: API_VERSION + label: Let's Encrypt API Version + description: | + Select the Let's Encrypt API endpoint used for issuing the certificate. + Use `Sandbox` for testing your configuration. + required: true + type: enum + default: Production + options: + - Production + - Sandbox + - variable: EMAIL + label: Your Email Address + description: | + Enter the email address to use for creating the Let's Encrypt account. + required: true + type: string + - variable: CERT_NAME + label: Certificate Name + description: | + Name for storing the certificate in the Rancher API and in volumes. + Any existing certificate by that name will be updated. + required: true + type: string + - variable: DOMAINS + label: Domain Names + description: | + Comma delimited list of the certificate domains starting with the Common Name. + E.g: `example.com, dev.example.com`. + required: true + type: string + - variable: PUBLIC_KEY_TYPE + label: Public Key Algorithm + description: | + Select one of the available key types. + required: true + type: enum + default: RSA-2048 + options: + - RSA-2048 + - RSA-4096 + - RSA-8192 + - ECDSA-256 + - ECDSA-384 + - variable: RENEWAL_TIME + label: Renewal Time of Day (00-23) + description: | + Set the time of day (UTC in hours) at which certificate renewals should be run. + default: 12 + required: true + type: int + - variable: RENEWAL_PERIOD_DAYS + label: Renewal Grace Period + description: | + Number of days before expiration the certificate should be renewed / become eligible for renewal. + default: 20 + required: true + type: int + - variable: RUN_ONCE + label: Run Once + description: | + Stop the service after creating or renewing the certificate instead of continously running and managing renewal. + required: true + type: boolean + default: false + - variable: DNS_RESOLVERS + label: DNS Resolvers + description: | + Comma delimited list of DNS resolvers used to check propagation of ACME TXT record. + If empty the DNS resolvers configured in your hosts /etc/resolv.conf are used. + required: false + default: "8.8.8.8:53,8.8.4.4:53" + type: string + - variable: VOLUME_NAME + label: Volume Name (Optional) + description: | + To store the account data, certificates and private keys in a volume, enter the volume name that should be used. + By default this will be a (host scoped) named Docker volume. See "Persistent Storage Driver" for other options. + required: false + type: string + - variable: STORAGE_DRIVER + label: Volume Storage Driver (Optional) + description: | + To use a stack scoped volume backed by a persistent storage service, enter the name + of an existing storage driver (see `Infrastructure -> Storage`). This also requires "Volume Name" to be set. + required: false + type: string + - variable: STORAGE_DRIVER_OPT + label: Storage Driver Option (Optional) + description: | + Specify a single "driver_opts" key/value pair in the format "optionName: optionValue". + E.g. for the `rancher-ebs` driver you should specify the required 'size' option like this: "size: 1". + required: false + type: string + - variable: PROVIDER + label: Domain Validation Method + description: Select a DNS provider to use for domain validation. Use 'HTTP' if your domain is hosted elsewhere. + required: true + type: enum + options: + - CloudFlare + - DigitalOcean + - DNSimple + - Dyn + - Gandi + - Ovh + - Route53 + - Vultr + - HTTP + - Azure + - NS1 + - variable: AWS_ACCESS_KEY + label: AWS Route53 Access Key Id + description: Enter the Access Key Id for your AWS account. + type: string + required: false + - variable: AWS_SECRET_KEY + label: AWS Route53 Secret Access Key + description: Enter the Secret Access Key for your AWS account. + type: password + required: false + - variable: AZURE_CLIENT_ID + label: Azure Client ID + description: Enter the Client Id for your Azure account. + type: string + required: false + - variable: AZURE_CLIENT_SECRET + label: Azure Client Secret + description: Enter the Access Key Id for your Azure account. + type: password + required: false + - variable: AZURE_SUBSCRIPTION_ID + label: Azure Subscription Id + description: Enter the Azure Subscription Id for your Azure account. + type: string + required: false + - variable: AZURE_TENANT_ID + label: Azure Tenant Id + description: Enter the Azure Tenant Id for your Azure account. + type: string + required: false + - variable: AZURE_RESOURCE_GROUP + label: Azure Resource Group + description: Enter the Azure Resource Group for your Azure account. + type: string + required: false + - variable: CLOUDFLARE_EMAIL + label: CloudFlare Email Address + description: Enter the email address associated with your CloudFlare account. + type: string + required: false + - variable: CLOUDFLARE_KEY + label: CloudFlare API Key + description: Enter the Global API Key for your CloudFlare account. + type: password + required: false + - variable: DO_ACCESS_TOKEN + label: DigitalOcean API Access Token + description: Enter the Personal Access Token for your DigitalOcean account. + type: password + required: false + - variable: DNSIMPLE_EMAIL + label: DNSimple Email Address + description: Enter the email address associated with your DNSimple account. + type: string + required: false + - variable: DNSIMPLE_KEY + label: DNSimple API Key + description: Enter your DNSimple API key. + type: password + required: false + - variable: DYN_CUSTOMER_NAME + label: Dyn Customer Name + description: Enter your Dyn customer name. + type: string + required: false + - variable: DYN_USER_NAME + label: Dyn User Name + description: Enter your Dyn user name. + type: string + required: false + - variable: DYN_PASSWORD + label: Dyn Password + description: Enter your Dyn password. + type: password + required: false + - variable: GANDI_API_KEY + label: Gandi API Key + description: Enter the API key for your Gandi account. + type: password + required: false + - variable: OVH_APPLICATION_KEY + label: OVH Application Key + description: Enter your OVH application key. + type: string + required: false + - variable: OVH_APPLICATION_SECRET + label: OVH Application Secret + description: Enter your OVH application secret. + type: password + required: false + - variable: OVH_CONSUMER_KEY + label: OVH Consumer Key + description: Enter your OVH consumer key. + type: password + required: false + - variable: VULTR_API_KEY + label: Vultr API Key + description: Enter the API key for your Vultr account. + type: password + required: false diff --git a/templates/letsencrypt/config.yml b/templates/letsencrypt/config.yml index a763cd4..c0c3f9a 100644 --- a/templates/letsencrypt/config.yml +++ b/templates/letsencrypt/config.yml @@ -1,7 +1,7 @@ name: Let's Encrypt description: | Trusted SSL certificates at zero cost -version: 0.4.0 +version: 0.5.0 category: Security maintainer: Jan Bruder license: The MIT License diff --git a/templates/logentries/0/docker-compose.yml b/templates/logentries/0/docker-compose.yml new file mode 100644 index 0000000..2cea085 --- /dev/null +++ b/templates/logentries/0/docker-compose.yml @@ -0,0 +1,11 @@ +version: '2' +services: + docker-logentries: + image: logentries/docker-logentries:0.2.1 + command: ${logentries_command} + restart: always + volumes: + - /var/run/docker.sock:/var/run/docker.sock + labels: + io.rancher.scheduler.global: "true" + io.rancher.container.hostname_override: container_name diff --git a/templates/logentries/0/rancher-compose.yml b/templates/logentries/0/rancher-compose.yml new file mode 100644 index 0000000..c52ed0c --- /dev/null +++ b/templates/logentries/0/rancher-compose.yml @@ -0,0 +1,16 @@ +version: '2' +catalog: + name: logentries + version: 0.2.1 + description: "logentries: The Fastest Way to Analyze Your Log Data" + questions: + - variable: logentries_command + label: Command + type: "string" + required: true + default: "-t -j" + description: | + The command used to configure the logentries container. +services: + docker-logentries: + start_on_create: true diff --git a/templates/logentries/README.md b/templates/logentries/README.md new file mode 100644 index 0000000..30bcc3c --- /dev/null +++ b/templates/logentries/README.md @@ -0,0 +1,3 @@ +# logentries + +This template deploys a [logentries](https://logentries.com/) stack running the official [docker-logentries](https://github.com/rapid7/docker-logentries) image. diff --git a/templates/logentries/catalogIcon-logentries.svg b/templates/logentries/catalogIcon-logentries.svg new file mode 100644 index 0000000..66a5327 --- /dev/null +++ b/templates/logentries/catalogIcon-logentries.svg @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/logentries/config.yml b/templates/logentries/config.yml new file mode 100644 index 0000000..689950b --- /dev/null +++ b/templates/logentries/config.yml @@ -0,0 +1,7 @@ +name: Logentries +description: | + Forward all your Docker logs to logentries, like a breeze. +version: "0.2.1" +category: Logging +maintainer: "Nick Haynes " +license: The MIT License diff --git a/templates/logmatic/0/docker-compose.yml b/templates/logmatic/0/docker-compose.yml index a950fc0..ed6c6f1 100755 --- a/templates/logmatic/0/docker-compose.yml +++ b/templates/logmatic/0/docker-compose.yml @@ -1,6 +1,6 @@ logmatic-agent: image: logmatic/logmatic-docker - entrypoint: /usr/src/app/index.js + entrypoint: python /app/main.py command: ${logmatic_key} ${opts_args} restart: always volumes: diff --git a/templates/meanshop/0/docker-compose.yml b/templates/meanshop/0/docker-compose.yml new file mode 100644 index 0000000..eaa28c7 --- /dev/null +++ b/templates/meanshop/0/docker-compose.yml @@ -0,0 +1,39 @@ +version: '2' +services: + meanshop-nginx: + image: ohmydocker/meanshop:nginx + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.pull_image: always + ports: + - ${PORT}:80 + meanshop-node: + image: ohmydocker/meanshop:alpine + labels: + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.container.pull_image: always + environment: + MEANGO_DEBUG: ${debug} + PORT: 9000 + MONGODB_DB_URL: "mongodb://meango/meanshop" + meango: + restart: always + environment: + MONGO_SERVICE_NAME: meango + CATTLE_SCRIPT_DEBUG: ${debug} + tty: true + image: mongo:3.2 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: meango-datavolume + io.rancher.container.pull_image: always + volumes_from: + - meango-datavolume + meango-datavolume: + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + volumes: + - /data/db + entrypoint: /bin/true + image: busybox diff --git a/templates/meanshop/0/rancher-compose.yml b/templates/meanshop/0/rancher-compose.yml new file mode 100644 index 0000000..c2b7463 --- /dev/null +++ b/templates/meanshop/0/rancher-compose.yml @@ -0,0 +1,41 @@ +.catalog: + name: "meanshop" + version: "0.4.9" + description: "Ecommerce powered by Meanshop" + uuid: meanshop-0 + minimum_rancher_version: v0.51.0 + questions: + - variable: "MEANSHOP_HOST" + description: "Hostname to use for the MEANSHOP server" + label: "MEANSHOP Hostname" + required: true + default: "meanshop" + type: "string" + - variable: "MEANSHOP_DOMAIN" + description: "Domain to use for the MEANSHOP server" + label: "MEANSHOP Domain" + required: true + default: "example.com" + type: "string" + - variable: "PORT" + description: "Port to use for the MEANSHOP server" + label: "MEANSHOP Port" + required: true + default: "8080" + type: "int" + +meanshop-nginx: + scale: 1 + retain_ip: true + +meanshop-node: + scale: 1 + retain_ip: true + +meango: + scale: 1 + retain_ip: true + metadata: + mongo: + yml: + replset.name: "${replset_name}" diff --git a/templates/meanshop/README.md b/templates/meanshop/README.md new file mode 100644 index 0000000..7891a46 --- /dev/null +++ b/templates/meanshop/README.md @@ -0,0 +1,13 @@ +#[MeanShop](http://meanshop.com/) + +Is a project by [Adrian Mejia](http://adrianmejia.com/) +which he describes as an: +"E-commerce Application built with the MEAN stack". +Visit it's [github page here.](https://github.com/amejiarosario/meanshop/) +Where Adrian maintains a set of links where you can purchase his book. + +This is a rancher template that should enable you to quickly test it on +your rancher setup. + +There are experimental versions of this template in this catalog [here](https://github.com/ohmydocker/ohmydocker-catalog) which implement +other setups. Issues, PRs, etc are welcome there. diff --git a/templates/meanshop/catalogIcon-meanshop.png b/templates/meanshop/catalogIcon-meanshop.png new file mode 100644 index 0000000..df19cd4 Binary files /dev/null and b/templates/meanshop/catalogIcon-meanshop.png differ diff --git a/templates/meanshop/config.yml b/templates/meanshop/config.yml new file mode 100644 index 0000000..8e4d48b --- /dev/null +++ b/templates/meanshop/config.yml @@ -0,0 +1,5 @@ +name: Meanshop +description: | + Ecommerce powered by Meanshop +version: 0.4.9 +category: Repository diff --git a/templates/minio/0/README.md b/templates/minio/0/README.md new file mode 100644 index 0000000..e8de9af --- /dev/null +++ b/templates/minio/0/README.md @@ -0,0 +1,49 @@ +# Minio.io + +### Info: + +This template creates, scale in and scale out a multinodes minio cluster on top of Rancher. The configuration is generated with confd from Rancher metadata. +Cluster size is static after deployement. It's mean that you should redeploy the stack if you should change the size of your cluster (minio.io limitation). + + +### Usage: + +Select Minio Cloud Storage from catalog. + +Enter the number of nodes for your minio cluster and set the key and secret to connect in minio. + +Click deploy. + +Minio can now be accessed over the Rancher network on port `9000` (http://IP_CONTAINER:9000). To access from external Rancher network, you need to set load balancer or expose the port 9000. + +### Disks / nodes + +You can set many disks per nodes (max of 4). If you use local disk (no extra Docker driver), you need to mount them on the same `base path` and indicate this name on `Volume Driver / Path` section. +Moreover, you need to use the same disk name with a number as suffix (from 0 to 4) and report this on `Disk base name` section. + +For example, if you should to use 4 disks per nodes: +- Number of disks per node: 4 +- Volume driver / Path: /data/minio +- Disk base name: disk + +And you have to mount the following partition: +- /data/minio/disk0 +- /data/minio/disk1 +- /data/minio/disk2 +- /data/minio/disk3 +- + +To more info about nodes and disks, you can read the [official documentation](https://github.com/minio/minio/tree/master/docs/distributed) + + + +### Advance info +1. This template create first the container called `rancher-cattle-metadata`. It embedded confd, with some scripts to get many settings from Cattle scheduler and expose them through the volume. +2. Then, the template create `minio` container. It will launch the scripts provided from `rancher-cattle-metadata` container with `volumes_from`. it will create /opt/scheduler/conf/scheduler.cfg file with some usefull infos about container, service, stack and host. Next, it will source `/opt/scheduler/conf/scheduler.cfg` and launch confd scripts to configure minio. + +### Source, bugs and enhances + + If you found bugs or need enhance, you can open ticket on github: + - [Minio official core project](https://github.com/minio/minio) + - [Minio docker image](https://github.com/disaster37/alpine-minio) + - [Rancher Cattle metadata docker image](https://github.com/disaster37/rancher-cattle-metadata) diff --git a/templates/minio/0/docker-compose.yml.tpl b/templates/minio/0/docker-compose.yml.tpl new file mode 100644 index 0000000..7bce3f8 --- /dev/null +++ b/templates/minio/0/docker-compose.yml.tpl @@ -0,0 +1,70 @@ +version: '2' +services: + minio-server: + tty: true + image: webcenter/alpine-minio:2017-03-16_4 + volumes: + - minio-scheduler-setting:/opt/scheduler + {{- if eq (printf "%.1s" .Values.VOLUME_DRIVER) "/" }} + {{- range $idx, $e := atoi .Values.MINIO_DISKS | until }} + - ${VOLUME_DRIVER}/${DISK_BASE_NAME}{{$idx}}:/data/disk{{$idx}} + {{- end}} + {{- else}} + {{- range $idx, $e := atoi .Values.MINIO_DISKS | until }} + - minio-data-{{$idx}}:/data/disk{{$idx}} + {{- end}} + {{- end}} + environment: + - MINIO_CONFIG_minio.access.key=${MINIO_ACCESS_KEY} + - MINIO_CONFIG_minio.secret.key=${MINIO_SECRET_KEY} + - CONFD_BACKEND=${CONFD_BACKEND} + - CONFD_NODES=${CONFD_NODES} + - CONFD_PREFIX_KEY=${CONFD_PREFIX} + {{- range $idx, $e := atoi .Values.MINIO_DISKS | until }} + - MINIO_DISKS_{{$idx}}=disk{{$idx}} + {{- end}} + {{- if (ne .Values.DEPLOY_LB "true") and .Values.PUBLISH_PORT}} + ports: + - ${PUBLISH_PORT}:9000 + {{- end}} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: rancher-cattle-metadata + rancher-cattle-metadata: + network_mode: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: "true" + image: webcenter/rancher-cattle-metadata:1.0.1 + volumes: + - minio-scheduler-setting:/opt/scheduler + {{- if eq .Values.DEPLOY_LB "true"}} + lb: + image: rancher/lb-service-haproxy:v0.6.2 + {{- if .Values.PUBLISH_PORT}} + ports: + - ${PUBLISH_PORT}:9000/tcp + {{- else}} + expose: + - 9000:9000/tcp + {{- end}} + links: + - minio-server:minio-server + labels: + io.rancher.container.agent.role: environmentAdmin + io.rancher.container.create_agent: 'true' + {{- end}} + +volumes: + minio-scheduler-setting: + driver: local + per_container: true + {{- if ne (printf "%.1s" .Values.VOLUME_DRIVER) "/" }} + {{- range $idx, $e := atoi .Values.MINIO_DISKS | until }} + minio-data-{{$idx}}: + per_container: true + driver: ${VOLUME_DRIVER} + {{- end}} + {{- end}} \ No newline at end of file diff --git a/templates/minio/0/rancher-compose.yml b/templates/minio/0/rancher-compose.yml new file mode 100644 index 0000000..8363018 --- /dev/null +++ b/templates/minio/0/rancher-compose.yml @@ -0,0 +1,113 @@ +version: '2' +catalog: + name: Minio + version: 2017-03-16-rancher1 + questions: + - variable: "MINIO_SCALE" + description: "Number of minio nodes." + label: "Minio Nodes" + required: true + default: 1 + type: enum + options: + - 1 + - 4 + - 6 + - 8 + - 10 + - 12 + - 14 + - 16 + - variable: "MINIO_DISKS" + description: "Number of disks per node" + label: "Disks Per Node" + required: true + type: enum + default: 1 + options: + - 1 + - 2 + - 4 + - variable: "DISK_BASE_NAME" + description: "The base name for each disk" + label: "Disk base name" + type: "string" + required: true + default: "disk" + - variable: "VOLUME_DRIVER" + description: "Docker driver to store volume or base path for each disks" + label: "Volume drver / Path" + type: "string" + required: true + default: "local" + - variable: "MINIO_ACCESS_KEY" + description: "The key to connect on minio" + label: "Minio key" + required: true + type: "string" + - variable: "MINIO_SECRET_KEY" + description: "The secret key to connect on minio" + label: "Minio secret key" + required: true + type: "password" + - variable: "DEPLOY_LB" + description: "Deploy Loadbalancer" + label: "Deploy Loadbalancer" + required: true + type: enum + default: "true" + options: + - "true" + - "false" + - variable: "PUBLISH_PORT" + description: "Set port if you want publish external port for minio or Loadbalancer" + label: "Publish port" + required: false + type: "string" + default: "9000" + - variable: "CONFD_BACKEND" + description: "The confd backend to grab config" + label: "Confd backend" + required: true + default: "env" + type: "string" + - variable: "CONFD_NODES" + description: "The confd nodes" + label: "Confd nodes" + required: false + type: "string" + - variable: "CONFD_PREFIX" + description: "The confd prefix" + label: "Confd prefix" + required: true + default: "/minio" + type: "string" + +services: + minio-server: + scale: ${MINIO_SCALE} + retain_ip: true + health_check: + port: 9000 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 + lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - priority: 1 + protocol: http + service: minio-server + source_port: 9000 + target_port: 9000 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + interval: 2000 \ No newline at end of file diff --git a/templates/minio/catalogIcon-minio.svg b/templates/minio/catalogIcon-minio.svg new file mode 100644 index 0000000..d3e61c4 --- /dev/null +++ b/templates/minio/catalogIcon-minio.svg @@ -0,0 +1,3531 @@ + + + + + + + + + + +]> + + + + + + + + + + + + + + + + + + + + + + + eJzsvXmPHcl1L/gJ8jvc+cOA9GCWMjIictEMBrirRwNrgVreYDw0KDbV4jObbLDZ8tN8+jm/s0VE +3rxVxWbJbstVwaUqK29kZCxn+Z3tb/6P33zxYv/V+9+/fhHv+l33N39z/PD65cf3H36+46u7X7x9 ++/13Hz/g0k9++9NdGO96umn/i/lLvfEfX3/47s37dz/nX/EvL/j0Tw6v3/7pzVc/3f3kp3Tpd28+ +vn1NF3/55t2b91++ff/1+y+/evnh37785f4Xv7r77k9f/9QeTD2dXn6kW0P/s5B+FsZd+HmOu9/8 +Eje8fPenl9999+b/w6/HOEe6dnj//buv3rz7+vD+f+Mz8+7FFIZd7tPuxYyx/D9vfvv6u/VNd+Pc +T7gz3C3DsNDt8S6GmT9z10/TSB88vX/1/Tev3338zYf3r15/993x/dv3H777+e7455fvdr98+TX9 +5uXuX16/ffv+33eHty9f/VtHc5K/vLx5+5pe/5uXH3dhwGTsfxGGLw/fv3n71a++/+b3r2lixnnA +5fgld/kP31Ff1C2+x+Xpy198Q1e+eP3xIw2YHoiX+O3fHeph0MW7vu+XfuBvAl5GvonL7if/+tvX +X7/hFaO5/J8/1Wd9eP/tNzTh1OGQ7sZ+Xuj1l3GX5+kuLinvktz3u9fffPuW5p9nKvbjXd69iAv+ +q3/Qe+ld+T5+9kKrRF0OuxEvjqHJXWUeX//pzet///nuV+/fvZbJ2n/4+IUsZkp9L//Kb377/dvX +H/7h3ZuPGC8uLTJbv3z/1eu3dL9//vL2JU8St1D+lRt+9/LD168/0gZ4//b7j7xHZ3sCrcbfv/zz +ayxpkAf8+tvX7373/h95jC9i6u/iNO0G2ixxop3R343jOO3CPAy7EPNC3/GThrTs4uwDCOVfeQ56 +RZ/2sImW8ze0wL/+8ObrN+9+3vOcycL/3Yc3X5V1D331B73fzdXfxf7K2GkaPn58/U7fhXbc8ZfV +DurvfvkFPfb87qvj+2+wFt/h4NAueUe7is6i/M6/59/Qx7//Vl6Bf/6Slu03H968Q5/dr/g385e/ +efs9/ervPrz//ttfvPvD++4nQjL+8fUrogu0sl/tfv37/0U/EBHgXb373YeXr6gD+tnvuXv55tuf +3tsdvdyH1zv5JX2Sf7T/H/706fUf6DyWj8vV87s/vX77/tuqW7/y8t1Xu396+eHbh7v+zduX715+ +2PF17/nv3/yJfvOSZqr0Xa49olPaJt/S5PBH+JbVA+65ofrVIx708uMfiXS9fvfVd963/NgOXK49 +3N8Xr7AHP+wOH77/7o+7371//9a7bX/lvetlvor7fxzP+A1/4N2v38kEXT9Jb1g/iajRj+4pdPft +J9Avf8y9H1++ffvm6w8vv/3jm1dbD9j4vT9JfvcpG+vP3/z+/ds3331T9lN15TcvP3x88+rt6y/+ +/N3H1988enF356/eEJG7cYzvveeLf3/58dUf//7N7z+8/PDm9b2nDwvwhzfvvqK9/8X3bz6+LhP0 +/ptvIfjsvvjjy29f82t8/OOF7/zCO8xfEumvifuLF/dQ/aHfHd5Vv/+7Dy+/ekMMhSS7y0tIWLsv +/u3PP+3qH8Ajd4evun/tiHP1YegzfZNIVJmGrke7C3lYUqBvcp9nEo76u2mcx2Hq0u5vvjx8qD65 +s08Kv9VP7uyTO/vkDjeQcAPm2aMTYn9ffl4nh+9+yCiCdPA5Y/AuaASHky+Zzfz2Yvz6w8t3X7/+ +WxVQaUFWF6i7LIvyf3X9XLWlaeXavGrXd9m1fUd//m/q93A6nA+XY38Mx+EYj+k4HqfjfFyO++Ph +eDqej5dTfwqn4RRP+TSeptN8Wk770+F0PJ1Ol3N/DufhHKmlcz6P56k7z9zvSb6O2g7a9tQWanPT +Jm3lO2sj/6XW0R/02z/0FR5oqy/qkPs976u2bLR5o00bbZTWnWW840QSaR7TGMdhDGOfL/mcT/mY +D3mflzznKY8555RjDqQPXdI5ndIxHdI+LWlOUxpTTinFNKSQ+njp4pn67e+GIdJutMNH8zJqm7TV +36PZ+l//1O4Y/p+HPk/zPO/nI63QhfbMsMQlL+MyLfOyXw60iuflsg/7YZ/3437eL/v9/kjrez70 +h3AYDumQD+NhPiyH/eFAZ4J3ReI2eisrL23hHSLt4M12UdlTZ2qnx22IT/riLi+9tPOlavXXqWnH +qh2qprtJ5vJMb3ecDzSfC83qNI9zntMc52GGYnihnXOajtNhWqZ5ItV2ylOaiPJMgVbyQvvpNB7H +w7gfF6I4E3dJ+wGttxYv2s7eTt6O3g7a9t4WNOpyvZfa3bPeVePV99Iyt+b7rvpxXH/P70KjONAo +z/FCbzTQfs+072c6AQc6C+d0obsHOiGJzspEZ2ZPp+dE5CbQmYp0ukaalIWm50gTdaEpGzqau0yz +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 +w9t9HeYf0rof9rHnDn/EHdbpzkq0/HbKte2Ea6uEmxYU3Zb/shRn6zj5cZUXss4KWWmU3T0q5RpC +uC4HttfE/5brnHRMA4/qgmB1ObCwUQjsVmEB7ru7KgNWSoE9pqhAW1YglsJg29UFNoqE3VMo7GKF +wW61x4trVT2C7hEVxT6p4thTCOP/vTq003viqC2c23gJdGJPfFonzmkWNCki6vKNnGYu8HE88kGc ++AAOXLLtTAeOD5scssiV2y6KyAnqKnCruROUHLdt+MDK16fbzm97Bb1cg2wGrBq0KuCqhhFcB3qc +m0CPfRvowep2rmI9SrRH6DTg41IFfZxEgNZYwb2GfywaAmJhIFNSxZyNTBYSkjoOUrBWTOTFXlcy +xVyaVuUTiKfSOi9V17btTAz7e5oSmC4u97b5U1u3cXH6nNZ93sd//B0WXLHXFrh98kUOa7nLOfbs +FDPPMUyapd+raFhOzEHSnnGcw3iNRX5uP4fvusCxM+MuRARP0N2et3/jN3b/3ZjpF2O4Q+zeLqa7 +kdT15nPbd7Sfn6jXPNCoUJhjmTY+v77DPz9Nq3Ry68ufB2HGTQwzNnmJLcV4E8a1lWW8hHAZ9d0K +3xJLo5rxF0Y+R6Z2kgVMcin0mhxBkontuaSkpJySRFWS1UryXHGGs5LM5Yd/SXzz2ZXFk0U9Xltq +P8cMzJXDHlvH4BFpMQEBSZxdqYB88ApdVgU5KIBTspaUvCUHLfhxcvCGq2FJ8tWxaflmu/0V69Za +LSZUzEgS5ZQXwPOI1Bq5hEy0Mz1KtkY63BWIT5ufDttEG6iqPvMUvbGtIud+mpJWFKH9KGaFjMo1 +TRWgdYrLq1Iln9vRpxzvf/rjm4+v/3Z3ePvy1b/RuW5+bArfmA/CfXke70szXpf/qBKNX6cZb7M6 +tmU/rop+eM0PkntKyY9SWK8+JNulPm4ek86jo9YF9aarNLLnDf+2tYfbofMqpqWM3rqU3nUxvaty +egVq7RSQ9JJ6D5fVW8erl7ToqYpFXzSW2VxE6hCFdLW2h65a3JKevU4kf7QsQ48r7tL5Mhvwfdgo +7XJd3GWLLPKqd49wbyxFciWNZrv6tX/jJNabup7iqdoCW+Xo1+UUrwoqdr4N1hthvRVmhQD2j1/L +Nthk7erTnNKuOqb1SpaiL7fK9ExbKwnzRX1kl+rI9uyPuF2m57Thqdqs5f2raeu5clddRTtqvGPX +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 + + + /ML4IBJK9Xx+X/UNRr+u1USp+6WjaqYu2uknErEj/tBvRVu8HjRuFuLUunvTPa2H90jlvecloYSh +Px9WKflMY+BmOO6wBbt/1tGsdHn4Ts+exk7aLk0tohQY5eVTsqQlNX8mNM229Z9pt+Nw0bl+yxD9 +4bh+a49mu+S4tfYEdo979Ye073NIsUrlYYmvjEeeh8Wg6J8Ug2f+Rh9jeWE5DPPic7hOPzJGdd6L +HPd5v/r7Md7XfI/y/vd3LZ7R650Mj+N79h/rF//qx99995/vmelv/vZnv/7117/6xVd/8w9f/d3X +v/z6Z7/++ufMUtOs1Hupv+fz2Dneq4umxfFD//rn3/z6u1999Vf/+Ovv/tdf/uzjN7/4+6/+jX3y +9sW/+pt7Nnsf+7e/+vo333z926/+7rvf/oMd6t0Z5/d+/L/75p5Q/83X3/z9f/LL/sTPi0O/++VX +3/ziq//xV9/94vce+5Ov/+Ovf/DB/8M333714btffvP1P3z1P3/9Tz/wN3747j/Hb7yQyd+33/0b +/8M3P//1f/p9V8LN/te/+u63dtwf8GT+vZ/xfVfN8Pj1Nzz2r/7dP/3y699zNP/zs//zvuj7rvzT +Vz/57uNwX5bvvR5u499+/auP90rXj3+Mwr/+0X/zV39Tv/rrX/zcT7a/f/z133/zC7f891/8i7/9 +7ttf/uzn3/3jr/7bHw3/rQzdeiE4SdRMARbc+0tl64ssWi//Sv//f/vtj0w/INbT2/RP+vN/uv/z +/7qNv/1iXb74t1/87//H8sXP7ZS/i63X+JkuGPL4pi9+Mlrzin4yfsKnrdMn/OIHv+R+l3/8s4// +N09cg+r2e+a3nd/739mP/l/kKlRCHbscDLmHbMVu9xcP4fZxN7kPW+X/vmC/GLv2+39uN9dkWikQ +Yx0CqkuK4Vs3amINY9Om8h6tNPzv5ZJBDSb0j5+h8HmZ/0yBm4iFclt3C056ve9qJRcEa1QcoROp +iFEdA7E4YUKwkCLHoinbjlFwlXSHn7cKsYLJMuuIl8LMlcUKHe7JnSy6LNG8QZb53jKtWnylIQ3Q +5hLPG6rRuVpgW6vSStfKGrwR2gy0uvDBpyPjVRrDMqtugANoFoh3CBoRCJfjwf5Z65SauY4rvK/D +9jQG12LLe293xF3jYqVAZQFESvKKBWrJhWI4dw/kbcp6EmzcvftUVpqnsLqqiGPBsKgPxFbCap/l +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 +MLHUUKmJyCw1Xc/My4OmxkqTigGHqU0hs9SmGCi1Bt+iJXNWvXd4D3j/FqWz3f6tHYYVaARJzZQn +DRqcM9UgqeE6yGgcgJxGcsb7pSZJrW1eXDtJamZYbY1+ZPO09KaOLXPU5LZDP0Vg1NQWqAkiQ9Rk +RAMRKBhqtxciBxlNJpk0MWSAGsNogqpxo7Zj4dOmkPFpUwx82h4OeUFPGw5eKPA0tTR1dyeDYinn +svtY6LRX6PhHxqX//0hO+x2f4Pj2r/7dr3+bL6wL/ebvfvmnf/fTP/7qp3/65Z/95p/+3j/E10P8 +r/7spz//m+8c/T//6m9++uV/99Ov/sNf/+5PHIf+5m9/+fW5/9u/+82v/+Cxv/jpr377//jg/+ZX +/1F341c//f0v/4ef/i87+g9+vZ//5m/W17NH+fd+x//1V3/527+2E8bvurb+35//H18H89v84jd/ +sT5P237n5fXx//Snv/uLn37923X8x8/4b3/2X/zrf7f/8t/++i/9ZP370L9/+Se/+fWffj2sv/16 +Xv/oj0z+Nz/9h697l/7Dz/7kb/Vfbvsv/+bv/uHv/zqu81/+yU//9M3/8bWO/a9+tn3711//9+// +6Wf/8DMV4ZV6u+3bf//1P/7PL+mfvo1v/+O3/+1/3779pY7+s5/90dc2Uy0FAkRdml412P7HKmun +LfvaX0hW6Ok7Spz6i+9f8Rc/+zUf7H/6mQK75GJkT3PIOUR1rbcGTEW0vgaejcqU1vkfX2uaZ/2P +f//nuvyhbdYhr8OwQeADy8DDUC0h/6LKFNmW89/KOvWvPv6D9yF9/imXP/6UOqA1VX5e/XfI8yIf +f/Syju6Pv+nq5590puHntb8vz2t8/EWt0sczPv9kyB9/83J7+M+Lf19eF/mrn/0vP4t35B84qFum +4etc7fZ2/85L5twz7txpWbzfKcdFfvH9a/u33h3y8/FHl1yurp3vff8eufzR97Xrt/6v/+FnqpLS +BS5rIFnX5VPI8EHL7M8/N+X6HZWU/c5Xn3K9iGNwPu+fDBJxsBGwTlYFJmtBvXORw/xfTB5W3oG8 +KbLg4t38WILgJuLd9H+z96bLkRzHlvAT4B3wR2bS2ADKiMjYLn+R0JVM85UWEyWNZDNjNBANihhh +4aDRpHSf/otz3D0yK6uaKDSb3SiwTCY24MiMjMXDw5fjHiQKfFKodN83apZK3rKEhA== + + + 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 +LWvXoCK+ueMv/U5j4dWtRYPPq+2Fg/aHT8DnUE/ufuOO5qAv70iIebF09PSukmKB4vEkXXp6krxR +qN4Yrly/lu15EsvRHUgp+/Xyl2Lx5ssvnVt7D7b3F2++avpdMcdm273cnpomiX37xuvsAfXtyW7d +MppRdvpoR+3fm1uN9vHTNVInsstr6WXAROPR1uNf3PD5i+7alhJ0935d+Rj13jf2thp7U9MrN/qP +T+pysf52ZWe9O1tRl7Rncn/6UDHU8pd8uPDkRX1rbRHHsJwbn/ztmcXBXHlSX99YeH+z86HYUzv+ +8praF0+9YXF0Z0FRzNo1paC8e978eOtgoTqouPvlSG3y/qXFL/d22u4P2KuTerF9vD8fP3hxQ8PU +Fit9bOvXL3PNmX45W/lTvL22KlwXVr5iyk/mlrpH0Z6il8M32d2bT18v3jou4/Gl6XbYF9UyL571 +r53aiJrc3N3d/jLe5M1cIyrfXG0ut7PD+lajFS91i8tFJG586SzefPqsSxvmcZgxKqL7iTs7r96q +Q9N4XN/YWvwyThuXh8udO4+Hizeb063sXvbq/vKT5Rf3rHaYafmS3+7svG2s7mysLw== + + + pS/FaGzjP1y+pIRH9Kw58/DeWvngXXOklWC9ifOK0B5ltx79Wt9r7F9+n+Y3j+eXlTrUuea6Iq0P +ne21+yC6t7dnf53+COq+vbK98OY41Lx5ZsXWlV83mx8vX9lU67v+buXD59EO+SDH8Xl/tLK9dG1m +avrm4+vJ2/rW1pVLAbHcW7XdrmkvlSaLNWbC5td3pxDIg8vN5fp7pSIurr5SfKxxY0tanyHPtjys +r2zV83Jjv0w/LR2pRS5FpzaBIGjBVJqd693YsurZnURZSfcOF2/fPX6pZGW3F12Z0EV76fDq6OFS ++vqX5w/uvEuvXmilWs0LepmZf4dRDlefKPNjpe+fu2yxD2n4EL5OtVyZXFYmwpvSdXEzLi49ac6+ +Xh/VH72Od71B7zx6stvYPSpv+HcWamYziss/Pdx3/JeZcP/TgfROqr29YIZ7/Un/c2OvfNhtbF/r +TJdrnwa3m/Vu7xdyh1boRe0+rvJuPlleeNd49Oj2Aqtq4tnmXHMl3ptp3qxv/GI29OWM4vxbC9md +Zv3uUjZ9LBurre70GP/prs8q3LzfAC+dbzxa/WVZccvwAN2+cbL+urkYjT6qPe9tNy9duxErE/Y5 +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 + + + diff --git a/templates/minio/config.yml b/templates/minio/config.yml new file mode 100644 index 0000000..c720457 --- /dev/null +++ b/templates/minio/config.yml @@ -0,0 +1,8 @@ +name: Minio Cloud Storage +description: | + Store photos, videos, VMs, containers, log files, or any blob of data as objects. +version: 2017-03-16-rancher1 +category: Storage +maintainer: "Sebastien Langoureaux " +license: Apache License +projectURL: https://minio.io/ diff --git a/templates/mysql/0/README.md b/templates/mysql/0/README.md new file mode 100644 index 0000000..11e8931 --- /dev/null +++ b/templates/mysql/0/README.md @@ -0,0 +1,18 @@ +# MySQL + +## What is MySQL? + +MySQL is the world's most popular open source database. With its proven performance, reliability and ease-of-use, MySQL has become the leading database choice for web-based applications, covering the entire range from personal projects and websites, via e-commerce and information services, all the way to high profile web properties including Facebook, Twitter, YouTube, Yahoo! and many more. + +For more information and related downloads for MySQL Server and other MySQL products, please visit [www.mysql.com](http://www.mysql.com). + +## Services + +Includes the following services: +- Load Balancer +- MySQL Server +- MySQL Data (sidekick to the server) + +## Usage + +The minimum configuration option(s) required to launch the stack is the MySQL Public LB Port and MySQL Root Password. See the description of each option for more information. diff --git a/templates/mysql/0/docker-compose.yml.tpl b/templates/mysql/0/docker-compose.yml.tpl new file mode 100644 index 0000000..b014999 --- /dev/null +++ b/templates/mysql/0/docker-compose.yml.tpl @@ -0,0 +1,40 @@ +version: '2' +services: + mysql-lb: + image: rancher/lb-service-haproxy:v0.6.4 + ports: + - ${mysql_lb_port}:${mysql_lb_port} + mysql-data: + image: busybox + labels: + io.rancher.container.start_once: true + volumes: + - /var/lib/mysql + mysql: + image: ${mysql_image} + environment: +{{- if eq .Values.mysql_allow_empty_password "yes"}} + MYSQL_ALLOW_EMPTY_PASSWORD: ${mysql_allow_empty_password} +{{- end}} +{{- if (.Values.mysql_database)}} + MYSQL_DATABASE: ${mysql_database} +{{- end}} +{{- if eq .Values.mysql_onetime_password "yes"}} + MYSQL_ONETIME_PASSWORD: ${mysql_onetime_password} +{{- end}} +{{- if (.Values.mysql_password)}} + MYSQL_PASSWORD: ${mysql_password} +{{- end}} +{{- if eq .Values.mysql_random_root_password "yes"}} + MYSQL_RANDOM_ROOT_PASSWORD: ${mysql_random_root_password} +{{- end}} + MYSQL_ROOT_PASSWORD: ${mysql_root_password} +{{- if (.Values.mysql_user)}} + MYSQL_USER: ${mysql_user} +{{- end}} + tty: true + stdin_open: true + labels: + io.rancher.sidekicks: mysql-data + volumes_from: + - mysql-data diff --git a/templates/mysql/0/rancher-compose.yml b/templates/mysql/0/rancher-compose.yml new file mode 100644 index 0000000..f41e4c1 --- /dev/null +++ b/templates/mysql/0/rancher-compose.yml @@ -0,0 +1,124 @@ +.catalog: + name: "mysql" + version: "v0.0.1" + description: "A recommended stack for the MySQL RDBMS." + uuid: mysql-0 + minimum_rancher_version: v1.0.0 + questions: + - variable: mysql_lb_port + description: "Public port for access to MySQL through the load balancer" + label: "MySQL Public LB Port" + required: true + default: 3306 + type: "int" + - variable: mysql_root_password + description: "The password that will be set for the MySQL root superuser account." + label: "MySQL Root Password" + required: true + type: password + - variable: mysql_image + description: "The docker image to use for the MySQL server." + label: "MySQL Docker Image" + type: "enum" + options: + - "mysql:latest" + - "mysql:8.0.1" + - "mysql:8.0" + - "mysql:8" + - "mysql:5.7.18" + - "mysql:5.7" + - "mysql:5" + - "mysql:5.6.36" + - "mysql:5.6" + - "mysql:5.5.56" + - "mysql:5.5" + - "mariadb:latest" + - "mariadb:10.3.0" + - "mariadb:10.3" + - "mariadb:10.2.6" + - "mariadb:10.2" + - "mariadb:10.1.24" + - "mariadb:10.1" + - "mariadb:10" + - "mariadb:10.0.31" + - "mariadb:10.0" + - "mariadb:5.5.56" + - "mariadb:5.5" + - "mariadb:5" + default: "mysql:latest" + required: true + - variable: mysql_database + description: "Optional, allows you to specify the name of a database to be created on image startup." + label: "MySQL Database" + required: false + type: "string" + - variable: mysql_user + description: "Creates an additional MySQL (super)user. MySQL Password must also be set." + label: "MySQL User" + required: false + type: "string" + - variable: mysql_password + description: "A password for the additional MySQL (super)user. MySQL User must also be set." + label: "MySQL Password" + required: false + type: password + - variable: mysql_allow_empty_password + description: "Set to 'yes' to allow the container to be started with a blank password for the root user." + label: MySQL Allow Empty Password + type: "enum" + options: + - "yes" + - "no" + default: "no" + required: false + - variable: mysql_random_root_password + description: "Set to 'yes' to generate a random initial password for the root user (using pwgen)." + label: MySQL Random Root Password + type: "enum" + options: + - "yes" + - "no" + default: "no" + required: false + - variable: mysql_onetime_password + description: "Set to 'yes' and the root user's password will be set as expired once init is complete." + label: MySQL One-time Password + type: "enum" + options: + - "yes" + - "no" + default: "no" + required: false + +version: '2' +services: + mysql-lb: + scale: 1 + start_on_create: true + lb_config: + certs: [] + port_rules: + - protocol: tcp + service: mysql + source_port: ${mysql_lb_port} + target_port: 3306 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 42 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate + mysql: + scale: 1 + start_on_create: true + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 3306 + unhealthy_threshold: 3 + interval: 2000 + strategy: recreate + mysql-data: + scale: 1 + start_on_create: true diff --git a/templates/mysql/README.md b/templates/mysql/README.md new file mode 100644 index 0000000..bc36af5 --- /dev/null +++ b/templates/mysql/README.md @@ -0,0 +1,3 @@ +## What is inside the MySQL Stack? +* MySQL database server + sidekick with volume data +* Load Balancer diff --git a/templates/mysql/catalogIcon-mysql.svg b/templates/mysql/catalogIcon-mysql.svg new file mode 100644 index 0000000..6d1d5c8 --- /dev/null +++ b/templates/mysql/catalogIcon-mysql.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/mysql/config.yml b/templates/mysql/config.yml new file mode 100644 index 0000000..fef7918 --- /dev/null +++ b/templates/mysql/config.yml @@ -0,0 +1,5 @@ +name: MySQL +description: | + MySQL — an open-source relational database management system (RDBMS) +version: v0.0.1 +category: Databases diff --git a/templates/neuvector/0/README.md b/templates/neuvector/0/README.md index cbbba90..b001029 100644 --- a/templates/neuvector/0/README.md +++ b/templates/neuvector/0/README.md @@ -2,9 +2,9 @@ ### Info: -NeuVector provides continuous network security for application containers. +NeuVector provides continuous network security for application containers. Deploy the NeuVector containers to get network visibility, application layer segmentation, Docker Bench auditing, and run-time vulnerability scanning. -Deploy the NeuVector containers to protect running containers from violations, threats, and vulnerabilities. NeuVector also detects host and container privilege escalations / break outs. +NeuVector also detects host and container privilege escalations / break outs and application threats such as DDoS and DNS attacks. NeuVector can be deployed on greenfield or brownfield (already running) application environments. diff --git a/templates/neuvector/0/docker-compose.yml b/templates/neuvector/0/docker-compose.yml index a84cf29..bee18e6 100644 --- a/templates/neuvector/0/docker-compose.yml +++ b/templates/neuvector/0/docker-compose.yml @@ -1,5 +1,5 @@ allinone: - image: neuvector/allinone:0.9 + image: neuvector/allinone:rancher1.2 container_name: neuvector.allinone restart: always privileged: true @@ -9,6 +9,7 @@ allinone: ports: - 8443:8443 volumes: + - /var/neuvector:/var/neuvector - /var/run/docker.sock:/var/run/docker.sock - /proc:/host/proc:ro - /sys/fs/cgroup:/host/cgroup:ro @@ -17,7 +18,7 @@ allinone: io.rancher.scheduler.affinity:host_label: ${NV_ALLINONE_LABEL} io.rancher.container.hostname_override: container_name enforcer: - image: neuvector/enforcer:0.9 + image: neuvector/enforcer:rancher1.2 container_name: neuvector.enforcer restart: always privileged: true @@ -25,6 +26,7 @@ enforcer: - affinity:com.myself.name!=neuvector - CLUSTER_JOIN_ADDR=allinone volumes: + - /var/neuvector:/var/neuvector - /var/run/docker.sock:/var/run/docker.sock - /proc:/host/proc:ro - /sys/fs/cgroup/:/host/cgroup/:ro diff --git a/templates/neuvector/0/rancher-compose.yml b/templates/neuvector/0/rancher-compose.yml index df7deae..336660d 100644 --- a/templates/neuvector/0/rancher-compose.yml +++ b/templates/neuvector/0/rancher-compose.yml @@ -1,6 +1,6 @@ .catalog: name: "NeuVector" - version: "v0.9" + version: "rancher1.2" description: "Container Security Solution" questions: - variable: "NV_ALLINONE_LABEL" diff --git a/templates/neuvector/config.yml b/templates/neuvector/config.yml index 244920b..a3bcc64 100644 --- a/templates/neuvector/config.yml +++ b/templates/neuvector/config.yml @@ -1,6 +1,6 @@ name: NeuVector description: | - Container Application Security -version: v0.9 + Container Security Solution +version: rancher1.2 category: Security maintainer: neuvector support diff --git a/templates/nextcloud/0/docker-compose.yml b/templates/nextcloud/0/docker-compose.yml new file mode 100644 index 0000000..2dfb5ac --- /dev/null +++ b/templates/nextcloud/0/docker-compose.yml @@ -0,0 +1,48 @@ +version: '2' + +services: + + nextcloud: + image: nextcloud:12-apache + volumes_from: + - nextcloud-data + ports: + - ${NEXTCLOUD_PORT}:80 + depends_on: + - mariadb + labels: + io.rancher.sidekicks: nextcloud-data + io.rancher.container.hostname_override: container_name + + nextcloud-data: + image: nextcloud:12-apache + entrypoint: + - /bin/true + volumes: + - /var/www/html + labels: + io.rancher.container.start_once: 'true' + io.rancher.container.hostname_override: container_name + + mariadb: + image: mariadb:10 + environment: + MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASS} + MYSQL_DATABASE: ${MYSQL_DATABASE} + MYSQL_USER: ${MYSQL_USER} + MYSQL_PASSWORD: ${MYSQL_PASS} + labels: + io.rancher.sidekicks: mariadb-data + io.rancher.container.hostname_override: container_name + + mariadb-data: + image: mariadb:10 + entrypoint: + - /bin/true + volumes: + - /var/lib/mysql + tty: true + labels: + io.rancher.container.start_once: 'true' + io.rancher.container.hostname_override: container_name + diff --git a/templates/nextcloud/0/rancher-compose.yml b/templates/nextcloud/0/rancher-compose.yml new file mode 100644 index 0000000..804707c --- /dev/null +++ b/templates/nextcloud/0/rancher-compose.yml @@ -0,0 +1,50 @@ +version: '2' + +catalog: + + name: nextcloud + version: 0.0.1 + description: Nextcloud - Enterprise File Sync and Share + questions: + - variable: NEXTCLOUD_PORT + label: Port + default: 80 + required: true + type: int + - variable: MYSQL_ROOT_PASS + label: MySQL root password + required: true + type: password + - variable: MYSQL_DATABASE + default: nextcloud + label: MySQL Database + required: true + type: string + - variable: MYSQL_USER + default: nextcloud + label: MySQL User + required: true + type: string + - variable: MYSQL_PASS + label: MySQL Pass + required: true + type: password + +services: + + nextcloud: + scale: 1 + start_on_create: true + + nextcloud-data: + scale: 1 + start_on_create: true + + mariadb: + scale: 1 + start_on_create: true + + mariadb-data: + scale: 1 + start_on_create: true + diff --git a/templates/nextcloud/README.md b/templates/nextcloud/README.md new file mode 100644 index 0000000..6581bd8 --- /dev/null +++ b/templates/nextcloud/README.md @@ -0,0 +1,22 @@ +# NextCloud + +Enterprise File Sync and Share + +## Configuration + +When you start Nextcloud for the first time you will see the [Installation Wizard](https://docs.nextcloud.com/server/12/admin_manual/installation/installation_wizard.html). + +1.) Point your Web browser to your Nextcloud Installation and enter your [Username / Password](https://docs.nextcloud.com/server/12/admin_manual/installation/installation_wizard.html#quick-start). + +2.) We persist the [Data Directory Location](https://docs.nextcloud.com/server/12/admin_manual/installation/installation_wizard.html#data-directory-location) from `/var/www/html/data` to a Sidekick Container. *(If you don't change the location there is nothing else to do. In case you want to use another directory you have to update the volumes entry for the `nextcloud-data` service in `docker-compose.yml`.)* + +3.) The last step is to update the [Database Settings](https://docs.nextcloud.com/server/12/admin_manual/installation/installation_wizard.html#database-choice) and switch from SQLite to MariaDB for better performance. + +- Database: `YOUR-DATABASE` (default: `nextcloud`) +- MySQL Username: `YOUR-USER` (default: `nextcloud`) +- MySQL Password: `YOUR-PASSWORD` +- MySQL Hostname: `mariadb` (**Important:** Use `mariadb` instead of `localhost`) + +Read more in the official [Nextcloud Documentation](https://docs.nextcloud.com/). + + diff --git a/templates/nextcloud/catalogIcon-nextcloud.svg b/templates/nextcloud/catalogIcon-nextcloud.svg new file mode 100644 index 0000000..628c953 --- /dev/null +++ b/templates/nextcloud/catalogIcon-nextcloud.svg @@ -0,0 +1,103 @@ + + + +image/svg+xml \ No newline at end of file diff --git a/templates/nextcloud/config.yml b/templates/nextcloud/config.yml new file mode 100644 index 0000000..28f63b8 --- /dev/null +++ b/templates/nextcloud/config.yml @@ -0,0 +1,6 @@ +name: nextcloud +description: Enterprise File Sync and Share +version: 0.0.1 +category: File Synchronisation +projectURL: https://github.com/ellerbrock/rancher-collection + diff --git a/templates/nuxeo/0/rancher-compose.yml b/templates/nuxeo/0/rancher-compose.yml index 34b9a61..9b86fb7 100644 --- a/templates/nuxeo/0/rancher-compose.yml +++ b/templates/nuxeo/0/rancher-compose.yml @@ -2,7 +2,7 @@ name: "Nuxeo Platform" version: 8.1-rancher1 description: | - Enterprise Content Management + Enterprise Content Management Platform for Business Applications uuid: nuxeo-1 questions: @@ -16,14 +16,14 @@ type: "string" label: "List of Nuxeo packages" description: | - List of Nuxeo packages + List of Nuxeo packages default: nuxeo-web-mobile nuxeo-drive nuxeo-diff nuxeo-spreadsheet nuxeo-dam nuxeo-template-rendering nuxeo-template-rendering-samples nuxeo-showcase-content - variable: url description: "The URL that this nuxeo instance should serve" label: "Nuxeo URL" type: "string" required: true - default: "http://localhost:8080/" + default: "http://localhost:8080/" - variable: volumedriver type: "string" label: "Volume driver" @@ -40,14 +40,14 @@ nuxeo: interval: 5000 unhealthy_threshold: 5 # For TCP, request_line needs to be '' - # TCP Example: + # TCP Example: # request_line: '' - request_line: GET /nuxeo/login.jsp + request_line: GET /nuxeo/login.jsp healthy_threshold: 2 # Response timeout is measured in milliseconds response_timeout: 2000 -elasticsearch: +elasticsearch-masters: metadata: elasticsearch: yml: @@ -67,4 +67,4 @@ lb: interval: 2000 unhealthy_threshold: 3 healthy_threshold: 2 - response_timeout: 2000 \ No newline at end of file + response_timeout: 2000 diff --git a/templates/openproject/0/docker-compose.yml b/templates/openproject/0/docker-compose.yml new file mode 100644 index 0000000..77b78c2 --- /dev/null +++ b/templates/openproject/0/docker-compose.yml @@ -0,0 +1,26 @@ +version: '2' + +services: + + openproject: + image: openproject/community:7 + volumes_from: + - openproject-data + ports: + - ${OPENPROJECT_PORT}:80 + labels: + io.rancher.sidekicks: openproject-data + io.rancher.container.hostname_override: container_name + + openproject-data: + image: openproject/community:7 + entrypoint: + - /bin/true + volumes: + - /var/lib/postgresql/9.4/main + - /var/log/supervisor + - /var/db/openproject + labels: + io.rancher.container.start_once: 'true' + io.rancher.container.hostname_override: container_name + diff --git a/templates/openproject/0/rancher-compose.yml b/templates/openproject/0/rancher-compose.yml new file mode 100644 index 0000000..aa6fa23 --- /dev/null +++ b/templates/openproject/0/rancher-compose.yml @@ -0,0 +1,24 @@ +version: '2' + +catalog: + + name: openproject + version: 0.0.1 + description: Project planning and scheduling + questions: + - variable: OPENPROJECT_PORT + label: Port + default: 80 + required: true + type: int + +services: + + openproject: + scale: 1 + start_on_create: true + + openproject-data: + scale: 1 + start_on_create: true + diff --git a/templates/openproject/README.md b/templates/openproject/README.md new file mode 100644 index 0000000..9a608e7 --- /dev/null +++ b/templates/openproject/README.md @@ -0,0 +1,6 @@ +# OpenProject + +Login via Username: `admin` and Password `admin`. + +Read more in the official OpenProject [Documentation](https://www.openproject.org/help/). + diff --git a/templates/openproject/catalogIcon-openproject.png b/templates/openproject/catalogIcon-openproject.png new file mode 100644 index 0000000..680ea77 Binary files /dev/null and b/templates/openproject/catalogIcon-openproject.png differ diff --git a/templates/openproject/config.yml b/templates/openproject/config.yml new file mode 100644 index 0000000..baa3695 --- /dev/null +++ b/templates/openproject/config.yml @@ -0,0 +1,6 @@ +name: openproject +description: Project planning and scheduling +version: 0.0.1 +category: Agile +projectURL: https://github.com/ellerbrock/rancher-collection + diff --git a/templates/postgres/0/docker-compose.yml b/templates/postgres/0/docker-compose.yml index 24e8dfa..89ff0da 100644 --- a/templates/postgres/0/docker-compose.yml +++ b/templates/postgres/0/docker-compose.yml @@ -1,11 +1,9 @@ version: '2' services: postgres-lb: - image: rancher/load-balancer-service - links: - - postgres + image: rancher/lb-service-haproxy ports: - - ${lb_port}:5432 + - ${lb_port} postgres-data: image: busybox diff --git a/templates/postgres/1/docker-compose.yml.tpl b/templates/postgres/1/docker-compose.yml.tpl new file mode 100644 index 0000000..70084d2 --- /dev/null +++ b/templates/postgres/1/docker-compose.yml.tpl @@ -0,0 +1,41 @@ +version: '2' +services: + postgres-lb: + image: rancher/lb-service-haproxy + ports: + - ${lb_port} + {{- if ne .Values.host_label ""}} + labels: + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + + postgres-data: + image: busybox + labels: + io.rancher.container.start_once: true + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + volumes: + - pgdata:/var/lib/postgresql/data/pgdata + + postgres: + image: postgres:${POSTGRES_TAG} + environment: + PGDATA: /var/lib/postgresql/data/pgdata + POSTGRES_DB: ${postgres_db} + POSTGRES_USER: ${postgres_user} + POSTGRES_PASSWORD: ${postgres_password} + tty: true + stdin_open: true + labels: + io.rancher.sidekicks: postgres-data + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + volumes_from: + - postgres-data +volumes: + pgdata: + driver: ${VOLUME_DRIVER} + per_container: true diff --git a/templates/postgres/1/rancher-compose.yml b/templates/postgres/1/rancher-compose.yml new file mode 100644 index 0000000..b636956 --- /dev/null +++ b/templates/postgres/1/rancher-compose.yml @@ -0,0 +1,98 @@ +version: '2' +catalog: + name: "Postgres" + version: "v0.0.2" + description: "PostgreSQL" + uuid: postgres-0 + minimum_rancher_version: v0.9.0 + questions: + - variable: lb_port + description: "Port to access PostgreSQL from external services" + label: "Postgres LB Port" + required: true + default: 5432 + type: "int" + - variable: postgres_db + description: "Postgres Database" + label: "Postgres Database" + required: true + default: "postgres_sb" + type: "string" + - variable: postgres_user + description: "Postgres User" + label: "Postgres User" + required: true + default: "postgres_user" + type: "string" + - variable: postgres_password + description: "Postgres Password" + label: "Postgres Password" + required: true + default: "postgres_password" + type: "string" + - variable: "POSTGRES_TAG" + description: "The postgres tag to associate with this server" + label: "Postgres tag" + required: true + default: "9.6-alpine" + type: enum + options: # List of options if using type of `enum` + - latest + - 10-alpine + - 10 + - 9-alpine + - 9 + - 9.6-alpine + - 9.6 + - 9.5-alpine + - 9.5 + - 9.4-alpine + - 9.4 + - 9.3-alpine + - 9.3 + - 9.2-alpine + - 9.2 + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + - variable: host_label + label: "Host with Label to put postgres on" + description: | + Host label to use as postgres 'value' tag. + Example: 'postgres=true' + required: false + default: "" + type: "string" + +services: + postgres-lb: + scale: 1 + lb_config: + certs: [] + port_rules: + - protocol: tcp + service: postgres + source_port: ${lb_port} + target_port: 5432 + health_check: + port: 42 + interval: 2000 + unhealthy_threshold: 3 + healthy_threshold: 2 + response_timeout: 2000 + postgres: + scale: 1 + health_check: + port: 5432 + interval: 2000 + unhealthy_threshold: 3 + healthy_threshold: 2 + response_timeout: 2000 diff --git a/templates/postgres/config.yml b/templates/postgres/config.yml index 22d6fc8..5d3e681 100644 --- a/templates/postgres/config.yml +++ b/templates/postgres/config.yml @@ -1,5 +1,5 @@ name: PostgreSQL description: | PostgreSQL — an object-relational database (ORDBMS) -version: v0.0.1 -category: Database +version: v0.0.2 +category: Databases diff --git a/templates/project-harbor/0/README.md b/templates/project-harbor/0/README.md new file mode 100644 index 0000000..05fd42f --- /dev/null +++ b/templates/project-harbor/0/README.md @@ -0,0 +1,14 @@ +##Harbor 0.5.0 deployment: single-host (revision 0) + +This version deploys `Harbor` 0.5.0 on a single host of a Cattle cluster. + +The host is identified, by default, by the `harbor-host=true` label (can be changed at deployment time to point to another key). + +Note that: +- the `IP/Hostname/FQDN` parameter needs to be set to the exact same name you will use to access the registry (e.g. IP or FQDN of the host) +- the host needs to have port `80` and port `443` free for use (the Harbor proxy container will bind to those ports) +- this catalog entry only supports `http` (`https` access is not supported) +- because only `http` is supported, the Docker Host pulling/pushing from/to Harbor needs to have the `--insecure-registry` flag properly configured +- if you want to re-provision Harbor on the same Docker host and you want to use different inputs (e.g. a different password) you need to remove the `/data` directory on the host. If you fail to do so the new Harbor instance will use the same parameters entered in the previous deployment (saved in the `/data` directory) + +![](singlehost.png) diff --git a/templates/project-harbor/0/docker-compose.yml b/templates/project-harbor/0/docker-compose.yml new file mode 100644 index 0000000..91ba36c --- /dev/null +++ b/templates/project-harbor/0/docker-compose.yml @@ -0,0 +1,168 @@ +version: '2' +services: + harbor-setupwrapper: + image: mreferre/harbor-setupwrapper:0.5.0 + container_name: harbor-setupwrapper + environment: + - HARBORHOSTNAME=${harborhostname} + - HARBOR_ADMIN_PASSWORD=${harbor_admin_password} + volumes: + - /etc/registry + - /etc/ui + - /etc/jobservice + - /etc/nginx + - /configdb + - /configui + - /configjobservice + command: ["/harbor/harbor-setupwrapper.sh"] + network_mode: "none" + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: 'true' + io.rancher.sidekicks: registry, ui, jobservice, mysql, proxy + log: + image: vmware/harbor-log:0.5.0 + container_name: harbor-log + restart: always + volumes: + - /var/log/harbor:/var/log/docker/ + ports: + - 1514:514 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + registry: + image: library/registry:2.5.0 + container_name: registry + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/registry:/storage + volumes_from: + - harbor-setupwrapper + environment: + - GODEBUG=netdns=cgo + command: + ["serve", "/etc/registry/config.yml"] + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "registry" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + mysql: + image: vmware/harbor-db:0.5.0 + container_name: harbor-db + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/database:/var/lib/mysql + volumes_from: + - harbor-setupwrapper + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "mysql" + entrypoint: + - /bin/sh + - -c + command: + - /configdb/entrypointdb.sh + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + ui: + image: vmware/harbor-ui:0.5.0 + container_name: harbor-ui + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data:/harbor_storage + volumes_from: + - harbor-setupwrapper + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "ui" + entrypoint: + - /bin/sh + - -c + command: + - /configui/entrypointui.sh + external_links: + - registry + - mysql + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + jobservice: + image: vmware/harbor-jobservice:0.5.0 + container_name: harbor-jobservice + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/job_logs:/var/log/jobs + volumes_from: + - harbor-setupwrapper + depends_on: + - log + #external_links: + # - registry + # - ui + # - mysql + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "jobservice" + entrypoint: + - /bin/sh + - -c + command: + - /configjobservice/entrypointjobservice.sh + #external_links: + # - registry + # - ui + # - mysql + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + proxy: + image: nginx:1.11.5 + container_name: nginx + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes_from: + - harbor-setupwrapper + ports: + - 80:80 + - 443:443 + depends_on: + - log + #external_links: + # - registry + # - ui + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "proxy" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} diff --git a/templates/project-harbor/0/rancher-compose.yml b/templates/project-harbor/0/rancher-compose.yml new file mode 100644 index 0000000..5d970d1 --- /dev/null +++ b/templates/project-harbor/0/rancher-compose.yml @@ -0,0 +1,48 @@ +version: '2' +.catalog: + name: Harbor + version: 0.5.0-rev0-singlehost + description: | + Enterprise Class Container Registry by VMware + minimum_rancher_version: v0.59.0 + uuid: harbor-0 + questions: + - variable: "harborhostname" + description: "Harbor IP, HOSTNAME or FQDN as used to acces it from the Docker CLI" + label: "IP/Hostname/FQDN:" + required: true + default: myregistry + type: "string" + - variable: "harbor_admin_password" + label: "Harbor password:" + description: | + Harbor admin password + default: Vmware123! + required: true + type: "string" + - variable: "harborhostlabel" + label: "Harbor will be deployed on the host with this label (default: harbor-host=true)" + description: | + Harbor host label + default: harbor-host=true + required: true + type: "string" +services: + registry: + scale: 1 + start_on_create: false + proxy: + scale: 1 + start_on_create: false + jobservice: + scale: 1 + start_on_create: false + ui: + scale: 1 + start_on_create: false + mysql: + scale: 1 + start_on_create: false + harbor-setupwrapper: + scale: 1 + start_on_create: true diff --git a/templates/project-harbor/0/singlehost.png b/templates/project-harbor/0/singlehost.png new file mode 100644 index 0000000..d743fa8 Binary files /dev/null and b/templates/project-harbor/0/singlehost.png differ diff --git a/templates/project-harbor/1/README.md b/templates/project-harbor/1/README.md new file mode 100644 index 0000000..10f1cee --- /dev/null +++ b/templates/project-harbor/1/README.md @@ -0,0 +1,18 @@ +##Harbor 0.5.0 deployment: distributed (revision 0) + +This version deploys `Harbor` 0.5.0 on a Cattle cluster. + +All hosts have to have the `harbor-log=true` label (the log container needs to be deployed on all of them). + +Also, `Traefik` needs to be enabled on one of the host and a proper DNS configuration needs to be in place. + +Last but not least a storage service for named volumes needs to be available (this catalog entry has been tested with `rancher-nfs` which needs to be activated separately and prior to launch the distributed Harbor deployment). + +Note that: +- the `IP/Hostname/FQDN` can be arbitrary set but the `(Traefik) domain` parameter needs to be a domain name that resolves to the host where `Traefik` is running +- this catalog entry only supports `http` (`https` access is not supported) +- because only `http` is supported, the Docker Host pulling/pushing from/to Harbor needs to have the `--insecure-registry` flag properly configured +- while the Rancher UI may show that stack upgrades are available, upgrades are not supported at this point +- sometimes the proxy front-end fails to configure properly (due to a race condition) and it shows the "welcome to NGINX" page. If it happens, try to re-deploy the restart the `proxy` container + +![](distributed.png) diff --git a/templates/project-harbor/1/distributed.png b/templates/project-harbor/1/distributed.png new file mode 100644 index 0000000..48ff707 Binary files /dev/null and b/templates/project-harbor/1/distributed.png differ diff --git a/templates/project-harbor/1/docker-compose.yml b/templates/project-harbor/1/docker-compose.yml new file mode 100644 index 0000000..51de591 --- /dev/null +++ b/templates/project-harbor/1/docker-compose.yml @@ -0,0 +1,210 @@ +version: '2' +volumes: #most volumes mappings require optimization (now all volumes map all containers) + etcjobservice: + #external: true + driver: ${volumedriver} + etcnginx: + #external: true + driver: ${volumedriver} + etcregistry: + #external: true + driver: ${volumedriver} + etcui: + #external: true + driver: ${volumedriver} + configjobservice: + #external: true + driver: ${volumedriver} + configdb: + #external: true + driver: ${volumedriver} + configui: + #external: true + driver: ${volumedriver} + data: #according to the eng team this is not even needed (but leaving it in for consistency) + #external: true + driver: ${volumedriver} + data-registry: + #external: true + driver: ${volumedriver} + data-database: + #external: true + driver: ${volumedriver} + data-job_logs: + #external: true + driver: ${volumedriver} +services: + harbor-setupwrapper: + image: mreferre/harbor-setupwrapper:0.5.0 + container_name: harbor-setupwrapper + environment: + - HARBORHOSTNAME=${harborhostname}.${traefikdomain} + - HARBOR_ADMIN_PASSWORD=${harbor_admin_password} + volumes: + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + command: ["/harbor/harbor-setupwrapper.sh"] + network_mode: "none" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: 'true' + log: + image: vmware/harbor-log:0.5.0 + container_name: harbor-log + restart: always + volumes: + - /var/log/harbor/:/var/log/docker/ + ports: + - 1514:514 + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: harbor-log=true + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + registry: + image: library/registry:2.5.0 + container_name: registry + restart: always + volumes: + - data-registry:/storage + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + environment: + - GODEBUG=netdns=cgo + command: + ["serve", "/etc/registry/config.yml"] + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "registry" + labels: + io.rancher.container.hostname_override: container_name + mysql: + image: vmware/harbor-db:0.5.0 + container_name: harbor-db + restart: always + volumes: + - data-database:/var/lib/mysql + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "mysql" + entrypoint: + - /bin/sh + - -c + command: + - /configdb/entrypointdb.sh + labels: + io.rancher.container.hostname_override: container_name + ui: + image: vmware/harbor-ui:0.5.0 + container_name: harbor-ui + restart: always + volumes: + - data:/harbor_storage #according to the eng team this is not even needed (but leaving it in for consistency) + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "ui" + entrypoint: + - /bin/sh + - -c + command: + - /configui/entrypointui.sh + labels: + io.rancher.container.hostname_override: container_name + jobservice: + image: vmware/harbor-jobservice:0.5.0 + container_name: harbor-jobservice + restart: always + volumes: + - data-job_logs:/var/log/jobs + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "jobservice" + entrypoint: + - /bin/sh + - -c + command: + - /configjobservice/entrypointjobservice.sh + labels: + io.rancher.container.hostname_override: container_name + proxy: + image: nginx:1.11.5 + container_name: nginx + restart: always + volumes: + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + depends_on: + - log + - harbor-setupwrapper + external_links: #these entries seem to be required for the proxy service to start correctly + - registry + - ui + - mysql + - jobservice + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "proxy" + labels: + io.rancher.container.hostname_override: container_name + traefik.alias: ${harborhostname} + traefik.port: 80 + traefik.domain: ${traefikdomain} + traefik.enable: stack diff --git a/templates/project-harbor/1/rancher-compose.yml b/templates/project-harbor/1/rancher-compose.yml new file mode 100644 index 0000000..8eeb432 --- /dev/null +++ b/templates/project-harbor/1/rancher-compose.yml @@ -0,0 +1,56 @@ +version: '2' +.catalog: + name: Harbor + version: 0.5.0-rev0-distributed + description: | + Enterprise Class Container Registry by VMware + minimum_rancher_version: v0.59.0 + uuid: harbor-0 + questions: + - variable: "harborhostname" + description: "Harbor IP, HOSTNAME or FQDN as used to acces it from the Docker CLI" + label: "IP/Hostname/FQDN:" + required: true + default: myregistry + type: "string" + - variable: "harbor_admin_password" + label: "Harbor password:" + description: | + Harbor admin password + default: Vmware123! + required: true + type: "string" + - variable: "traefikdomain" + description: "Harbor domain name (if you are using Traefik you should call out the domain here and the harbor host name should just represent the hostname)" + label: "(Traefik) domain:" + required: true + default: mycompany.com + type: "string" + - variable: "volumedriver" + description: "Volume Driver being used (default: rancher-nfs)" + label: "Volume Driver:" + required: true + default: rancher-nfs + type: "string" +services: + registry: + scale: 1 + proxy: + scale: 1 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 80 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + request_line: + jobservice: + scale: 1 + ui: + scale: 1 + mysql: + scale: 1 + harbor-setupwrapper: + scale: 1 diff --git a/templates/project-harbor/2/README.md b/templates/project-harbor/2/README.md new file mode 100644 index 0000000..4cf3e71 --- /dev/null +++ b/templates/project-harbor/2/README.md @@ -0,0 +1,15 @@ +##Harbor 1.1.1 deployment: single-host (revision 0) + +This version deploys `Harbor` 1.1.1 on a single host of a Cattle cluster. + +The host is identified, by default, by the `harbor-host=true` label (can be changed at deployment time to point to another key). + +Note that: +- the `IP/Hostname/FQDN` parameter needs to be set to the exact same name you will use to access the registry (e.g. IP or FQDN of the host) +- the host needs to have port `80` and port `443` free for use (the Harbor proxy container will bind to those ports) +- this catalog entry only supports `http` (`https` access is not supported) +- because only `http` is supported, the Docker Host pulling/pushing from/to Harbor needs to have the `--insecure-registry` flag properly configured +- if you want to re-provision Harbor on the same Docker host and you want to use different inputs (e.g. a different password) you need to remove the `/data` directory on the host. If you fail to do so the new Harbor instance will use the same parameters entered in the previous deployment (saved in the `/data` directory) +- While the Rancher UI may show that stack upgrades are available, upgrades are not supported at this point + +![](singlehost.png) diff --git a/templates/project-harbor/2/docker-compose.yml b/templates/project-harbor/2/docker-compose.yml new file mode 100644 index 0000000..119f776 --- /dev/null +++ b/templates/project-harbor/2/docker-compose.yml @@ -0,0 +1,207 @@ +version: '2' +services: + harbor-setupwrapper: + image: mreferre/harbor-setupwrapper:1.1.1-1 + container_name: harbor-setupwrapper + environment: + - HARBORHOSTNAME=${harborhostname} + - HARBOR_ADMIN_PASSWORD=${harbor_admin_password} + volumes: + - /data:/data + - /etc/registry + - /etc/ui + - /etc/jobservice + - /etc/nginx + - /configdb + - /configui + - /configjobservice + - /configadminserver + command: ["/harbor/harbor-setupwrapper.sh"] + network_mode: "none" + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: 'true' + io.rancher.sidekicks: registry, ui, jobservice, mysql, proxy, adminserver + log: + image: vmware/harbor-log:v1.1.1 + container_name: harbor-log + restart: always + volumes: + - /var/log/harbor:/var/log/docker/:z + ports: + - 1514:514 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + registry: + image: vmware/registry:photon-2.6.0 + container_name: registry + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/registry:/storage:z + volumes_from: + - harbor-setupwrapper + environment: + - GODEBUG=netdns=cgo + command: + ["serve", "/etc/registry/config.yml"] + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "registry" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + mysql: + image: vmware/harbor-db:v1.1.1 + container_name: harbor-db + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/database:/var/lib/mysql:z + volumes_from: + - harbor-setupwrapper + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "mysql" + entrypoint: + - /bin/sh + - -c + command: + - /configdb/entrypointdb.sh + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + adminserver: + image: vmware/harbor-adminserver:v1.1.1 + container_name: harbor-adminserver + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/config/:/etc/adminserver/config/:z +# - /data/secretkey:/etc/adminserver/key:z +# - /data/:/data/:z + volumes_from: + - harbor-setupwrapper + depends_on: + - log + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "adminserver" + entrypoint: + - /bin/sh + - -c + command: + - /configadminserver/entrypointadminserver.sh + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + ui: + image: vmware/harbor-ui:v1.1.1 + container_name: harbor-ui + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes +# - /data/secretkey:/etc/ui/key:z + - /data/ca_download/:/etc/ui/ca/:z + volumes_from: + - harbor-setupwrapper + depends_on: + - log + - adminserver + - registry + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "ui" + entrypoint: + - /bin/sh + - -c + command: + - /configui/entrypointui.sh + external_links: + - registry + - mysql + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + jobservice: + image: vmware/harbor-jobservice:v1.1.1 + container_name: harbor-jobservice + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes: #original directory mapping has been moved to named volumes + - /data/job_logs:/var/log/jobs:z +# - /data/secretkey:/etc/jobservice/key:z + volumes_from: + - harbor-setupwrapper + depends_on: + - log + - ui + - adminserver + #external_links: + # - registry + # - ui + # - mysql + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "jobservice" + entrypoint: + - /bin/sh + - -c + command: + - /configjobservice/entrypointjobservice.sh + #external_links: + # - registry + # - ui + # - mysql + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + proxy: + image: vmware/nginx:1.11.5-patched + container_name: nginx + restart: always + dns_search: #https://forums.rancher.com/t/cant-resolve-simple-container-names-within-sidekick-structure/3876 + - harbor-setupwrapper + volumes_from: + - harbor-setupwrapper + ports: + - 80:80 + - 443:443 + - 4443:4443 + depends_on: + - mysql + - registry + - ui + - log + #external_links: + # - registry + # - ui + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "proxy" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} diff --git a/templates/project-harbor/2/rancher-compose.yml b/templates/project-harbor/2/rancher-compose.yml new file mode 100644 index 0000000..b92e9b1 --- /dev/null +++ b/templates/project-harbor/2/rancher-compose.yml @@ -0,0 +1,51 @@ +version: '2' +.catalog: + name: Harbor + version: 1.1.1-rev0-singlehost + description: | + Enterprise Class Container Registry [by VMware] + minimum_rancher_version: v0.59.0 + uuid: harbor-2 + questions: + - variable: "harborhostname" + description: "Harbor IP, HOSTNAME or FQDN as used to acces it from the Docker CLI" + label: "IP/Hostname/FQDN:" + required: true + default: myregistry + type: "string" + - variable: "harbor_admin_password" + label: "Harbor password:" + description: | + Harbor admin password + default: Vmware123! + required: true + type: "string" + - variable: "harborhostlabel" + label: "Harbor will be deployed on the host with this label (default: harbor-host=true)" + description: | + Harbor host label + default: harbor-host=true + required: true + type: "string" +services: + registry: + scale: 1 + start_on_create: false + adminserver: + scale: 1 + start_on_create: false + proxy: + scale: 1 + start_on_create: false + jobservice: + scale: 1 + start_on_create: false + ui: + scale: 1 + start_on_create: false + mysql: + scale: 1 + start_on_create: false + harbor-setupwrapper: + scale: 1 + start_on_create: true diff --git a/templates/project-harbor/2/singlehost.png b/templates/project-harbor/2/singlehost.png new file mode 100644 index 0000000..d743fa8 Binary files /dev/null and b/templates/project-harbor/2/singlehost.png differ diff --git a/templates/project-harbor/3/README.md b/templates/project-harbor/3/README.md new file mode 100644 index 0000000..6a1a80a --- /dev/null +++ b/templates/project-harbor/3/README.md @@ -0,0 +1,18 @@ +##Harbor 1.1.1 deployment: distributed (revision 0) + +This version deploys `Harbor` 1.1.1 on a Cattle cluster. + +All hosts have to have the `harbor-log=true` label (the log container needs to be deployed on all of them). + +Also, `Traefik` needs to be enabled on one of the host and a proper DNS configuration needs to be in place. + +Last but not least a storage service for named volumes needs to be available (this catalog entry has been tested with `rancher-nfs` which needs to be activated separately and prior to launch the distributed Harbor deployment). + +Note that: +- the `IP/Hostname/FQDN` can be arbitrary set but the `(Traefik) domain` parameter needs to be a domain name that resolves to the host where `Traefik` is running +- this catalog entry only supports `http` (`https` access is not supported) +- because only `http` is supported, the Docker Host pulling/pushing from/to Harbor needs to have the `--insecure-registry` flag properly configured +- while the Rancher UI may show that stack upgrades are available, upgrades are not supported at this point +- sometimes the proxy front-end fails to configure properly (due to a race condition) and it shows the "welcome to NGINX" page. If it happens, try to re-deploy the restart the `proxy` container + +![](distributed.png) diff --git a/templates/project-harbor/3/distributed.png b/templates/project-harbor/3/distributed.png new file mode 100644 index 0000000..48ff707 Binary files /dev/null and b/templates/project-harbor/3/distributed.png differ diff --git a/templates/project-harbor/3/docker-compose.yml b/templates/project-harbor/3/docker-compose.yml new file mode 100644 index 0000000..d8e681b --- /dev/null +++ b/templates/project-harbor/3/docker-compose.yml @@ -0,0 +1,290 @@ +version: '2' +volumes: #most volumes mappings require optimization (now all volumes map all containers) + etcjobservice: + #external: true + driver: ${volumedriver} + etcnginx: + #external: true + driver: ${volumedriver} + etcregistry: + #external: true + driver: ${volumedriver} + etcui: + #external: true + driver: ${volumedriver} + configjobservice: + #external: true + driver: ${volumedriver} + configdb: + #external: true + driver: ${volumedriver} + configui: + #external: true + driver: ${volumedriver} + configadminserver: + #external: true + driver: ${volumedriver} + data: #according to the eng team this is not even needed (but leaving it in for consistency) + #external: true + driver: ${volumedriver} + data-registry: + #external: true + driver: ${volumedriver} + data-database: + #external: true + driver: ${volumedriver} + data-job_logs: + #external: true + driver: ${volumedriver} + data-ca_download: + #external: true + driver: ${volumedriver} + data-config: + #external: true + driver: ${volumedriver} +services: + harbor-setupwrapper: + image: mreferre/harbor-setupwrapper:1.1.1-1 + container_name: harbor-setupwrapper + environment: + - HARBORHOSTNAME=${harborhostname}.${traefikdomain} + - HARBOR_ADMIN_PASSWORD=${harbor_admin_password} + volumes: + - data:/data + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + command: ["/harbor/harbor-setupwrapper.sh"] + network_mode: "none" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: 'true' + log: + image: vmware/harbor-log:v1.1.1 + container_name: harbor-log + restart: always + volumes: + - /var/log/harbor/:/var/log/docker/:z + ports: + - 1514:514 + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: harbor-log=true + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + registry: + image: vmware/registry:photon-2.6.0 + container_name: registry + restart: always + volumes: + - data-registry:/storage + - data:/data + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + environment: + - GODEBUG=netdns=cgo + command: + ["serve", "/etc/registry/config.yml"] + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "registry" + labels: + io.rancher.container.hostname_override: container_name + mysql: + image: vmware/harbor-db:v1.1.1 + container_name: harbor-db + restart: always + volumes: + - data-database:/var/lib/mysql + - data:/data:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "mysql" + entrypoint: + - /bin/sh + - -c + command: + - /configdb/entrypointdb.sh + labels: + io.rancher.container.hostname_override: container_name + adminserver: + image: vmware/harbor-adminserver:v1.1.1 + container_name: harbor-adminserver + restart: always + volumes: +# - /data/secretkey:/etc/adminserver/key + - data-database:/var/lib/mysql + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "adminserver" + entrypoint: + - /bin/sh + - -c + command: + - /configadminserver/entrypointadminserver.sh + labels: + io.rancher.container.hostname_override: container_name + ui: + image: vmware/harbor-ui:v1.1.1 + container_name: harbor-ui + restart: always + volumes: +# - /data/secretkey:/etc/ui/key:z +# - data:/harbor_storage #according to the eng team this is not even needed (but leaving it in for consistency) + - data:/data/:z + - data-database:/var/lib/mysql + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + - adminserver + - registry + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "ui" + entrypoint: + - /bin/sh + - -c + command: + - /configui/entrypointui.sh + labels: + io.rancher.container.hostname_override: container_name + jobservice: + image: vmware/harbor-jobservice:v1.1.1 + container_name: harbor-jobservice + restart: always + volumes: +# - /data/secretkey:/etc/jobservice/key:z + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + - ui + - adminserver + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "jobservice" + entrypoint: + - /bin/sh + - -c + command: + - /configjobservice/entrypointjobservice.sh + labels: + io.rancher.container.hostname_override: container_name + proxy: + image: vmware/nginx:1.11.5-patched + container_name: nginx + restart: always + volumes: + - data-database:/var/lib/mysql + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - mysql + - registry + - ui + - log + - harbor-setupwrapper + external_links: #these entries seem to be required for the proxy service to start correctly + - registry + - ui + - mysql + - jobservice + - adminserver + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "proxy" + labels: + io.rancher.container.hostname_override: container_name + traefik.alias: ${harborhostname} + traefik.port: 80 + traefik.domain: ${traefikdomain} + traefik.enable: stack diff --git a/templates/project-harbor/3/rancher-compose.yml b/templates/project-harbor/3/rancher-compose.yml new file mode 100644 index 0000000..1226102 --- /dev/null +++ b/templates/project-harbor/3/rancher-compose.yml @@ -0,0 +1,58 @@ +version: '2' +.catalog: + name: Harbor + version: 1.1.1-rev0-distributed + description: | + Enterprise Class Container Registry [by VMware] + minimum_rancher_version: v0.59.0 + uuid: harbor-3 + questions: + - variable: "harborhostname" + description: "Harbor IP, HOSTNAME or FQDN as used to acces it from the Docker CLI" + label: "IP/Hostname/FQDN:" + required: true + default: myregistry + type: "string" + - variable: "harbor_admin_password" + label: "Harbor password:" + description: | + Harbor admin password + default: Vmware123! + required: true + type: "string" + - variable: "traefikdomain" + description: "Harbor domain name (if you are using Traefik you should call out the domain here and the harbor host name should just represent the hostname)" + label: "(Traefik) domain:" + required: true + default: mycompany.com + type: "string" + - variable: "volumedriver" + description: "Volume Driver being used (default: rancher-nfs)" + label: "Volume Driver:" + required: true + default: rancher-nfs + type: "string" +services: + registry: + scale: 1 + adminserver: + scale: 1 + proxy: + scale: 1 + health_check: + healthy_threshold: 2 + response_timeout: 2000 + port: 80 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + request_line: + jobservice: + scale: 1 + ui: + scale: 1 + mysql: + scale: 1 + harbor-setupwrapper: + scale: 1 diff --git a/templates/project-harbor/4/README.md b/templates/project-harbor/4/README.md new file mode 100644 index 0000000..dd4c5c3 --- /dev/null +++ b/templates/project-harbor/4/README.md @@ -0,0 +1,44 @@ +### Harbor 1.1.1 deployment (revision 1) ### + +This catalog item version deploys `Harbor` 1.1.1 on a Cattle cluster and leverages [Harbor setup wrapper](https://hub.docker.com/r/mreferre/harbor-setupwrapper/tags/) version 1.1.1-1. + +This catalog item version supports both a basic (i.e. standalone) as well as advanced (i.e. distributed) deployment model for Harbor. + +The basic model has less pre-requisites but it's less powerful. The advanced model has more pre-requisites but it's more powerful. + +#### Governing the deployment model #### + +You govern the deployment model being used by setting the `harbor-host` label: +- if you set the label on one host, you opt in for the basic model. +- if you set the label on two or more hosts, you opt in for the advanced model. + +#### Storage pre-requisites #### + +If you opt in for the basic model there is no storage prerequisite and you can use the `local` volume driver. All volumes will be created locally and transparently on the host with the `harbor-host` label. + +If you opt in for the advanced model you have to configure a volume driver that supports sharing among containers (this catalog entry has been tested with `rancher-nfs` which needs to be activated separately and prior to launch the advanced deployment model). + +You can use a volume driver that supports sharing among containers when deploying with the basic model but it is not required. + +#### Network pre-requisites #### + +The network pre-requisites as described in this section apply to both the basic and advanced deployment models. + +> **Note:** the Harbor name you choose at deployment time must be the exact same end-point (IP, FQDN, etc) that you are going to use with your Docker client to `login` into Harbor, `pull` and `push` images from and to Harbor. This has ramification on how you configure access to the Harbor service. + +In this implementation, access to Harbor is fullfilled by a Rancher load balancer that forwards the host port 80 to port 80 of the Harbor proxy container. The Rancher load balancer is deployed on all hosts that have the `harbor-lb-host` label. + +The simplest way to configure the deployment is to set the `harbor-lb-host` label on a single host and use the IP address (or FQDN) of that host in the Harbor `IP/Hostname/FQDN` field. This IP (or FQDN) is what you will use to consume Harbor. + +A more sophisticated way to configure the deployment is to set the `harbor-lb-host` label on multiple hosts and have an external component (e.g. DNS with RR, or external LB) that can send requests to multiple hosts. In this case the Harbor `IP/Hostname/FQDN` field will need to be filled with the FQDN as provided by the DNS or by the external LB (virtual IP). This DNS name (or virtual IP) is what you will use to consume Harbor. + +In general, the only real prerequisite is that the `IP/Hostname/FQDN` field at deployment time maps exactly what the user will be using as an endpoint when interacting with the Harbor service. You should have a certain degree of flexibility to configure your deployment as long as you fullfill this requirement. + +#### Additional considerations and known issues #### + +- this catalog entry only supports `http` (`https` access is not supported) +- because only `http` is supported, the Docker Host pulling/pushing from/to Harbor needs to have the `--insecure-registry` flag properly configured +- the host(s) with the `harbor-lb-host` label need to have port `80` free for use (different port forwarding configurations hasn't been tested) +- while the Rancher UI may show that stack upgrades are available, upgrades are not supported at this point +- sometimes the proxy front-end fails to configure properly (due to a race condition) and it shows the "welcome to NGINX" page. If it happens, try to re-deploy the restart the `proxy` container +- every Harbor deployment will create a certain number of volumes. Note that these volumes may not always be properly deleted on the NFS share or on the local Docker host due to bug and/or limitations in the driver(s). It is suggested to keep an eye on volumes sprawl. \ No newline at end of file diff --git a/templates/project-harbor/4/docker-compose.yml b/templates/project-harbor/4/docker-compose.yml new file mode 100644 index 0000000..1e3667b --- /dev/null +++ b/templates/project-harbor/4/docker-compose.yml @@ -0,0 +1,299 @@ +version: '2' +volumes: #most volumes mappings require optimization (now all volumes map all containers) + etcjobservice: + #external: true + driver: ${volumedriver} + etcnginx: + #external: true + driver: ${volumedriver} + etcregistry: + #external: true + driver: ${volumedriver} + etcui: + #external: true + driver: ${volumedriver} + configjobservice: + #external: true + driver: ${volumedriver} + configdb: + #external: true + driver: ${volumedriver} + configui: + #external: true + driver: ${volumedriver} + configadminserver: + #external: true + driver: ${volumedriver} + data: #according to the eng team this is not even needed (but leaving it in for consistency) + #external: true + driver: ${volumedriver} + data-registry: + #external: true + driver: ${volumedriver} + data-database: + #external: true + driver: ${volumedriver} + data-job_logs: + #external: true + driver: ${volumedriver} + data-ca_download: + #external: true + driver: ${volumedriver} + data-config: + #external: true + driver: ${volumedriver} +services: + harbor-setupwrapper: + image: mreferre/harbor-setupwrapper:1.1.1-1 + container_name: harbor-setupwrapper + environment: + - HARBORHOSTNAME=${harborhostname}.${traefikdomain} + - HARBOR_ADMIN_PASSWORD=${harbor_admin_password} + volumes: + - data:/data + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + command: ["/harbor/harbor-setupwrapper.sh"] + network_mode: "none" + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: 'true' + log: + image: vmware/harbor-log:v1.1.1 + container_name: harbor-log + restart: always + volumes: + - /var/log/harbor/:/var/log/docker/:z + ports: + - 1514:514 + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + registry: + image: vmware/registry:photon-2.6.0 + container_name: registry + restart: always + volumes: + - data-registry:/storage + - data:/data + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + environment: + - GODEBUG=netdns=cgo + command: + ["serve", "/etc/registry/config.yml"] + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "registry" + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + mysql: + image: vmware/harbor-db:v1.1.1 + container_name: harbor-db + restart: always + volumes: + - data-database:/var/lib/mysql + - data:/data:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "mysql" + entrypoint: + - /bin/sh + - -c + command: + - /configdb/entrypointdb.sh + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + adminserver: + image: vmware/harbor-adminserver:v1.1.1 + container_name: harbor-adminserver + restart: always + volumes: +# - /data/secretkey:/etc/adminserver/key + - data-database:/var/lib/mysql + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "adminserver" + entrypoint: + - /bin/sh + - -c + command: + - /configadminserver/entrypointadminserver.sh + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + ui: + image: vmware/harbor-ui:v1.1.1 + container_name: harbor-ui + restart: always + volumes: + - data:/data/:z + - data-database:/var/lib/mysql + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + - adminserver + - registry + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "ui" + entrypoint: + - /bin/sh + - -c + command: + - /configui/entrypointui.sh + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + jobservice: + image: vmware/harbor-jobservice:v1.1.1 + container_name: harbor-jobservice + restart: always + volumes: +# - /data/secretkey:/etc/jobservice/key:z + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - log + - harbor-setupwrapper + - ui + - adminserver + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "jobservice" + entrypoint: + - /bin/sh + - -c + command: + - /configjobservice/entrypointjobservice.sh + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + proxy: + image: vmware/nginx:1.11.5-patched + container_name: nginx + restart: always + volumes: + - data-database:/var/lib/mysql + - data:/data/:z + - data-job_logs:/var/log/jobs + - data-ca_download:/etc/ui/ca/ + - data-config:/etc/adminserver/config/ + - etcui:/etc/ui + - etcjobservice:/etc/jobservice + - etcregistry:/etc/registry + - etcnginx:/etc/nginx + - configdb:/configdb + - configui:/configui + - configjobservice:/configjobservice + - configadminserver:/configadminserver + depends_on: + - mysql + - registry + - ui + - log + - harbor-setupwrapper + external_links: #these entries seem to be required for the proxy service to start correctly + - registry + - ui + - mysql + - jobservice + - adminserver + logging: + driver: "syslog" + options: + syslog-address: "tcp://127.0.0.1:1514" + tag: "proxy" + labels: + io.rancher.scheduler.affinity:host_label: ${harborhostlabel} + io.rancher.container.hostname_override: container_name + harbor-lb: + image: rancher/lb-service-haproxy + ports: + - 80 + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${harborlbhostlabel} + io.rancher.container.hostname_override: container_name diff --git a/templates/project-harbor/4/rancher-compose.yml b/templates/project-harbor/4/rancher-compose.yml new file mode 100644 index 0000000..afcd473 --- /dev/null +++ b/templates/project-harbor/4/rancher-compose.yml @@ -0,0 +1,75 @@ +version: '2' +.catalog: + name: Harbor + version: 1.1.1-1-rev1 + description: | + Enterprise Class Container Registry [by VMware] + minimum_rancher_version: v0.59.0 + uuid: harbor-4 + questions: + - variable: "harborhostname" + description: "Harbor IP, HOSTNAME or FQDN as used to acces it from the Docker CLI" + label: "IP/Hostname/FQDN:" + required: true + default: myregistry + type: "string" + - variable: "harbor_admin_password" + label: "Harbor password:" + description: | + Harbor admin password + default: Vmware123! + required: true + type: "string" + - variable: "harborhostlabel" + label: "Harbor will be deployed on the host(s) with this label (default: harbor-host=true)" + description: | + The various Harbor containers will be deployed on host(s) with this label + Set the label on one host if you want Harbor to be deployed on a single host (rancher-nfs volume driver is required for multiple hosts) + default: harbor-host=true + required: true + type: "string" + - variable: "harborlbhostlabel" + label: "Rancher load balancer will be deployed on the host(s) with this label (default: harbor-lb-host=true)" + description: | + The Rancher load balancer will be deployed on host(s) with this label + Make sure you understand the pre-requisite as outlined in the README document above + default: harbor-lb-host=true + required: true + type: "string" + - variable: "volumedriver" + description: "Volume Driver being used. Set rancher-nfs if you run in distributed mode" + label: "Volume Driver:" + required: true + default: local + type: "enum" + options: + - local + - rancher-nfs +services: + registry: + scale: 1 + adminserver: + scale: 1 + proxy: + scale: 1 + harbor-lb: + scale: 1 + lb_config: + port_rules: + - source_port: 80 + target_port: 80 + service: proxy + health_check: + port: 42 + interval: 2000 + unhealthy_threshold: 3 + healthy_threshold: 2 + response_timeout: 2000 + jobservice: + scale: 1 + ui: + scale: 1 + mysql: + scale: 1 + harbor-setupwrapper: + scale: 1 diff --git a/templates/project-harbor/catalogIcon-vmwareharbor.svg b/templates/project-harbor/catalogIcon-vmwareharbor.svg new file mode 100644 index 0000000..805eede --- /dev/null +++ b/templates/project-harbor/catalogIcon-vmwareharbor.svg @@ -0,0 +1,270 @@ + +image/svg+xml \ No newline at end of file diff --git a/templates/project-harbor/config.yml b/templates/project-harbor/config.yml new file mode 100644 index 0000000..33859d4 --- /dev/null +++ b/templates/project-harbor/config.yml @@ -0,0 +1,7 @@ +name: Project Harbor +description: | + (Experimental) Enterprise Class Container Registry [by VMware] +version: 1.1.1-1-rev1 +category: Private Container Registry +projectURL: https://github.com/vmware/harbor +license: Apache License 2.0 diff --git a/templates/quasardb-community/config.yml b/templates/quasardb-community/config.yml index 88c4098..4eceffa 100644 --- a/templates/quasardb-community/config.yml +++ b/templates/quasardb-community/config.yml @@ -2,7 +2,7 @@ name: QuasarDB Community description: | QuasarDB is a distributed key-value store with peer-to-peer replication, transactions, atomic operations, no-limit tagging and real-time search. version: 2.0.0-rc8 -category: Database +category: Databases maintainer: Alexis Ducastel projectURL: https://www.quasardb.net diff --git a/templates/rabbitmq-3/2/README.md b/templates/rabbitmq-3/2/README.md new file mode 100644 index 0000000..5716bb4 --- /dev/null +++ b/templates/rabbitmq-3/2/README.md @@ -0,0 +1,12 @@ +RabbitMQ 3.6 with easy Rancher clustering +=== +Provides RabbitMQ image that can scale to a cluster. + +The following environment variables are passed to confd in order to set up RabbitMQ's configuration file: + +* Partition handling: RabbitMQ's cluster handling setting: default set to autoheal +* Erlang cookie: cookie to allow nodes communication: default set to defaultcookiepleasechange +* Net ticktime: adjusts the frequency of both tick messages and detection of failures: default set to 60 +* Confd args: additional confd args along with default --backend rancher --prefix /2015-07-25: default set to --interval 5 + +*Note*: You can pass an alternate `confd` configuration via the `ALTERNATE_CONF` environment variable. diff --git a/templates/rabbitmq-3/2/docker-compose.yml.tpl b/templates/rabbitmq-3/2/docker-compose.yml.tpl new file mode 100755 index 0000000..048adc1 --- /dev/null +++ b/templates/rabbitmq-3/2/docker-compose.yml.tpl @@ -0,0 +1,54 @@ +version: '2' +services: + rabbitmq: + image: webhostingcoopteam/rabbitmq-conf:0.2.1 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: rabbitmq-base,rabbitmq-datavolume + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + volumes_from: + - rabbitmq-datavolume + environment: + - RABBITMQ_NET_TICKTIME=${net_ticktime} + - RABBITMQ_CLUSTER_PARTITION_HANDLING=${cluster_partition_handling} + - CONFD_ARGS=${confd_args} + rabbitmq-datavolume: + network_mode: "none" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + io.rancher.container.start_once: true + volumes: + - rabbitconf:/etc/rabbitmq + - rancherbin:/opt/rancher/bin + entrypoint: /bin/true + image: rabbitmq:3.6-management-alpine + rabbitmq-base: + network_mode: "container:rabbitmq" + labels: + io.rancher.container.hostname_override: container_name + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + {{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} + {{- end}} + image: rabbitmq:3.6-management-alpine + restart: always + volumes_from: + - rabbitmq-datavolume + entrypoint: + - /opt/rancher/bin/run.sh + environment: + - RABBITMQ_ERLANG_COOKIE=${erlang_cookie} +volumes: + rancherbin: + driver: ${VOLUME_DRIVER} + per_container: true + rabbitconf: + driver: ${VOLUME_DRIVER} + per_container: true diff --git a/templates/rabbitmq-3/2/rancher-compose.yml b/templates/rabbitmq-3/2/rancher-compose.yml new file mode 100755 index 0000000..a5f0112 --- /dev/null +++ b/templates/rabbitmq-3/2/rancher-compose.yml @@ -0,0 +1,82 @@ +version: '2' +catalog: + name: "Rabbit MQ" + version: "0.2.1" + decription: A reliable, distributed messaging broker + questions: + - variable: "erlang_cookie" + description: "Erlang cookie required for auth" + label: "Erlang cookie:" + required: true + default: "defaultcookie" + type: "string" + - variable: "cluster_partition_handling" + label: "Partition Handling:" + description: "Cluster partition handling mode" + required: true + type: "enum" + default: autoheal + options: + - autoheal + - ignore + - pause_minority + - variable: "net_ticktime" + description: "Rabbitmq net ticktime setting" + label: "Net ticktime:" + required: false + type: "int" + default: 60 + - variable: "confd_args" + description: "Confd additional args" + label: "Confd args" + required: false + type: "string" + default: --interval 5 + - variable: RABBITMQ_TAG + default: "rabbitmq:3.6.10-management-alpine" + label: "rabbitMQ_version" + required: true + type: enum + options: # List of options if using type of `enum` + - "rabbitmq:3.6.10-management-alpine" + - "rabbitmq:3.6.10-management" + - "rabbitmq:3.6.9-management-alpine" + - "rabbitmq:3.6.9-management" + - "rabbitmq:3.6.8-management-alpine" + - "rabbitmq:3.6.8-management" + - "rabbitmq:3.6-management-alpine" + - "rabbitmq:3.6-management" + - "rabbitmq:management" + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + - variable: host_label + label: "Host with Label to put rabbitmq on" + description: | + Host label to use as rabbitmq 'value' tag. + Example: 'rabbitmq=true' + required: false + default: "" + type: "string" + - variable: "initial_data_nodes" + type: "int" + required: true + label: "# of initial data nodes" + description: "Set the initial number of data nodes" + default: 1 + +services: + rabbitmq: + scale: ${initial_data_nodes} + metadata: + rabbitmq: + config: + node.name: "$${HOSTNAME}" diff --git a/templates/rabbitmq-3/config.yml b/templates/rabbitmq-3/config.yml index 7554719..80d25f7 100755 --- a/templates/rabbitmq-3/config.yml +++ b/templates/rabbitmq-3/config.yml @@ -1,5 +1,5 @@ name: RabbitMQ 3.6 description: | - Robust messaging for applications -version: 0.2.0 + Robust messaging for applications +version: "0.2.1" category: Message queues diff --git a/templates/rabbitmq-examples/0/README.md b/templates/rabbitmq-examples/0/README.md new file mode 100644 index 0000000..a797d5a --- /dev/null +++ b/templates/rabbitmq-examples/0/README.md @@ -0,0 +1,11 @@ +# RabbitMQ Examples + +I needed to test a rabbitMQ with some basics so I forked the official tutorials and added a Dockerfile +[here](https://github.com/joshuacox/rabbitmq-tutorials/tree/jsdockerfile/javascript-nodejs) + +[dockerhub here](https://hub.docker.com/r/joshuacox/rabbitmq-tutorials/) + +In that fork, there is a `Makefile` that can run through the proof of +concept. `make` will start a rabbitmq container, then start all the +listeners as deamons, and the emitters to run once. The emitters are +ephemeral and will go away once their message is sent or they error out. diff --git a/templates/rabbitmq-examples/0/docker-compose.yml.tpl b/templates/rabbitmq-examples/0/docker-compose.yml.tpl new file mode 100644 index 0000000..d177fd3 --- /dev/null +++ b/templates/rabbitmq-examples/0/docker-compose.yml.tpl @@ -0,0 +1,253 @@ +version: '2' +services: +{{- if eq .Values.rabbitmq_link ""}} + rabbit: + hostname: rabbit + image: rabbitmq:3 +{{- end}} + + receive: + command: receive +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: send +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + send: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: send +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + + worker: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: newtask +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + command: worker +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + newtask: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: new_task +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + + rpcserver: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: rpcclient +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + command: rpc_server +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + rpcclient: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: rpc_client 4 +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + + receivelogs: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: emitlog +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + command: receive_logs +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + emitlog: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: emit_log +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + + receivelogsdirect: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: emitlogdirect +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + command: receive_logs_direct info +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + emitlogdirect: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: emit_log_direct +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + + receivelogstopic: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: emitlogtopic +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + command: receive_logs_topic anonymous.info +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} + emitlogtopic: + image: joshuacox/rabbitmq-tutorials + labels: + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + command: emit_log_topic +{{- if ne .Values.rabbitmq_link ""}} + external_links: + - ${rabbitmq_link}:rabbit + environment: + - AMQ_HOST=rabbit.rancher.internal +{{- else}} + links: + - rabbit + environment: + - AMQ_HOST=rabbit +{{- end}} diff --git a/templates/rabbitmq-examples/0/rancher-compose.yml b/templates/rabbitmq-examples/0/rancher-compose.yml new file mode 100644 index 0000000..8d73300 --- /dev/null +++ b/templates/rabbitmq-examples/0/rancher-compose.yml @@ -0,0 +1,32 @@ +version: '2' +catalog: + name: RabbitMQ_Examples + version: 3.6-rancher1 + description: | + tutorial storage examples + questions: + - variable: rabbitmq_link + description: "rabbitmq service link" + label: "rabbitmq stack/service" + default: "" + required: false + type: "service" + - variable: "host_label" + description: "Host label where to run this service." + label: "Host label:" + required: false + default: "" + type: "string" +services: + receive: + scale: 1 + receivelogs: + scale: 1 + receivelogsdirect: + scale: 1 + receivelogstopic: + scale: 1 + rpcserver: + scale: 1 + worker: + scale: 1 diff --git a/templates/rabbitmq-examples/catalogIcon-rabbitmq.png b/templates/rabbitmq-examples/catalogIcon-rabbitmq.png new file mode 100755 index 0000000..f458f7f Binary files /dev/null and b/templates/rabbitmq-examples/catalogIcon-rabbitmq.png differ diff --git a/templates/rabbitmq-examples/config.yml b/templates/rabbitmq-examples/config.yml new file mode 100755 index 0000000..a90ef55 --- /dev/null +++ b/templates/rabbitmq-examples/config.yml @@ -0,0 +1,7 @@ +name: RabbitMQ 3.6 Tutorial Examples +description: | + Robust messaging for applications Examples +version: 3.6-rancher1 +category: Message queues +maintainer: "Josh Cox " +minimum_rancher_version: v0.59.0 diff --git a/templates/rancher-backup/0/docker-compose.yml b/templates/rancher-backup/0/docker-compose.yml deleted file mode 100644 index b22a784..0000000 --- a/templates/rancher-backup/0/docker-compose.yml +++ /dev/null @@ -1,45 +0,0 @@ -backup: - environment: - CRON_SCHEDULE: ${CRON_SCHEDULE} - BACKEND: ${BACKEND} - TARGET_PATH: ${TARGET_PATH} - BK_FULL_FREQ: ${BK_FULL_FREQ} - BK_KEEP_FULL: ${BK_KEEP_FULL} - BK_KEEP_FULL_CHAIN: ${BK_KEEP_FULL_CHAIN} - VOLUME_SIZE: ${VOLUME_SIZE} - DEBUG: false - DISABLE_DUMP : ${DISABLE_DUMP} - DISABLE_DUMP_RANCHER: ${DISABLE_DUMP_RANCHER} - FTP_PASSWORD: ${FTP_PASSWORD} - AWS_ACCESS_KEY_ID: ${AWS_ACCESS_KEY_ID} - AWS_SECRET_ACCESS_KEY: ${AWS_SECRET_ACCESS_KEY} - AZURE_ACCOUNT_NAME: ${AZURE_ACCOUNT_NAME} - AZURE_ACCOUNT_KEY: ${AZURE_ACCOUNT_KEY} - CLOUDFILES_USERNAME: ${CLOUDFILES_USERNAME} - CLOUDFILES_APIKEY: ${CLOUDFILES_APIKEY} - DPBX_ACCESS_TOKEN: ${DPBX_ACCESS_TOKEN} - GS_ACCESS_KEY_ID: ${GS_ACCESS_KEY_ID} - GS_SECRET_ACCESS_KEY: ${GS_SECRET_ACCESS_KEY} - GOOGLE_DRIVE_ACCOUNT_KEY: ${GOOGLE_DRIVE_ACCOUNT_KEY} - SWIFT_USERNAME: ${SWIFT_USERNAME} - SWIFT_PASSWORD: ${SWIFT_PASSWORD} - SWIFT_AUTHURL: ${SWIFT_AUTHURL} - labels: - io.rancher.sidekicks: backup-data - io.rancher.container.create_agent: true - io.rancher.container.agent.role: environment - tty: true - image: webcenter/rancher-backup:1.0.2 - stdin_open: false - privileged: true - volumes_from: - - backup-data - -backup-data: - labels: - io.rancher.container.start_once: 'true' - image: alpine - volumes: - - /backup - net: none - command: /bin/true diff --git a/templates/rancher-backup/0/docker-compose.yml.tpl b/templates/rancher-backup/0/docker-compose.yml.tpl new file mode 100644 index 0000000..155e64c --- /dev/null +++ b/templates/rancher-backup/0/docker-compose.yml.tpl @@ -0,0 +1,71 @@ +version: '2' +services: + backup: + environment: + - BACKUP_CRON_schedule=${CRON_SCHEDULE} + - BACKUP_DUPLICITY_url=${BACKEND} + - BACKUP_DUPLICITY_target-path=${TARGET_PATH} + - BACKUP_DUPLICITY_source-path=/backup + - BACKUP_DUPLICITY_full-if-older-than=${BK_FULL_FREQ} + - BACKUP_DUPLICITY_remove-all-but-n-full=${BK_KEEP_FULL} + - BACKUP_DUPLICITY_remove-all-inc-of-but-n-full=${BK_KEEP_FULL_CHAIN} + - BACKUP_DUPLICITY_volsize=${VOLUME_SIZE} + - BACKUP_DUPLICITY_options=${DUPLICITY_OPTIONS} + - DEBUG=false + - BACKUP_MODULE_database=${ENABLE_DUMP_SERVICE} + - BACKUP_MODULE_stack=${ENABLE_DUMP_STACK} + - BACKUP_MODULE_rancher-db=${ENABLE_DUMP_RANCHER_DATABASE} + - BACKUP_RANCHER_db_host=${RANCHER_DATABASE_HOST} + - BACKUP_RANCHER_db_port=${RANCHER_DATABASE_PORT} + - BACKUP_RANCHER_db_user=${RANCHER_DATABASE_USER} + - BACKUP_RANCHER_db_password=${RANCHER_DATABASE_PASSWORD} + - BACKUP_RANCHER_db_name=${RANCHER_DATABASE_NAME} + - DOCKER_HOST=docker-engine:2375 + - FTP_PASSWORD=${FTP_PASSWORD} + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY} + - AZURE_ACCOUNT_NAME=${AZURE_ACCOUNT_NAME} + - AZURE_ACCOUNT_KEY=${AZURE_ACCOUNT_KEY} + - CLOUDFILES_USERNAME=${CLOUDFILES_USERNAME} + - CLOUDFILES_APIKEY=${CLOUDFILES_APIKEY} + - DPBX_ACCESS_TOKEN=${DPBX_ACCESS_TOKEN} + - GS_ACCESS_KEY_ID=${GS_ACCESS_KEY_ID} + - GS_SECRET_ACCESS_KEY=${GS_SECRET_ACCESS_KEY} + - GOOGLE_DRIVE_ACCOUNT_KEY=${GOOGLE_DRIVE_ACCOUNT_KEY} + - SWIFT_USERNAME=${SWIFT_USERNAME} + - SWIFT_PASSWORD=${SWIFT_PASSWORD} + - SWIFT_AUTHURL=${SWIFT_AUTHURL} + - CONFD_BACKEND=${CONFD_BACKEND} + - CONFD_NODES=${CONFD_NODES} + - CONFD_PREFIX_KEY=${CONFD_PREFIX} + labels: + io.rancher.sidekicks: docker-engine + io.rancher.container.create_agent: true + io.rancher.container.agent.role: environment + tty: true + image: webcenter/rancher-backup:2.0.0-2 + stdin_open: false + volumes: + {{- if (contains .Values.VOLUME_DRIVER "/")}} + - ${VOLUME_DRIVER}:/data + {{- else}} + - backup-data:/data + {{- end}} + docker-engine: + privileged: true + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + image: index.docker.io/docker:1.13-dind + volumes: + {{- if (contains .Values.VOLUME_DRIVER "/")}} + - ${VOLUME_DRIVER}:/data + {{- else}} + - backup-data:/backup + {{- end}} + +{{- if not (contains .Values.VOLUME_DRIVER "/")}} +volumes: + backup-data: + driver: local +{{- end}} diff --git a/templates/rancher-backup/0/rancher-compose.yml b/templates/rancher-backup/0/rancher-compose.yml index 67998e9..8a1feb4 100644 --- a/templates/rancher-backup/0/rancher-compose.yml +++ b/templates/rancher-backup/0/rancher-compose.yml @@ -1,124 +1,190 @@ -.catalog: +version: '2' +catalog: name: "Rancher Backup" - version: "1.0.2" + version: "2.0.0" description: "It's a general purpose to solve backup matter on Rancher" - uuid: rancher-backup-1.0.2 - minimum_rancher_version: v0.56.0 + minimum_rancher_version: v1.5.0 questions: - - variable: CRON_SCHEDULE + - variable: "CRON_SCHEDULE" description: "The schedule with the Go cron syntaxe (per default, each day)" label: "Schedule" type: "string" required: true default: "0 0 0 * * *" - - variable: BACKEND + - variable: "BACKEND" description: "The duplicity backend for remote backup" label: "Backend" type: "string" required: true - - variable: TARGET_PATH - description: "The path on target backup (default, /backup)" + - variable: "TARGET_PATH" + description: "The path on target backup" label: "Target path on backend" type: "string" required: true - default: "/backup" - - variable: BK_FULL_FREQ + default: "/" + - variable: "BK_FULL_FREQ" description: "The backup full frequency (per defaut, each 7 days)" label: "Backup full frequency" type: "string" required: true default: "7D" - - variable: BK_KEEP_FULL + - variable: "BK_KEEP_FULL" description: "How many keep full backup (per default, keep 3s)" label: "Backup full retention" type: "string" required: true default: "5" - - variable: BK_KEEP_FULL_CHAIN + - variable: "BK_KEEP_FULL_CHAIN" description: "How many keep incremental backup chain (per default, keep 1)" label: "Backup incremental retention" type: "string" required: true default: "1" - - variable: VOLUME_SIZE - description: "The volume size in MB (per default, 25)" + - variable: "VOLUME_SIZE" + description: "The volume size in MB" label: "Volume size" type: "string" required: true - default: "25" - - variable: DISABLE_DUMP + default: "200" + - variable: "DUPLICITY_OPTIONS" + description: "Pass options when invoke Duplicity command backup" + label: "Duplicity options" + type: "string" + required: false + - variable: "ENABLE_DUMP_SERVICE" description: "If disabled, it's doesn't perform dump before save data" - label: "Disable dump" + label: "Enable dump service" type: "string" required: true - default: "false" + default: "true" type: "enum" options: - "false" - "true" - - variable: DISABLE_DUMP_RANCHER + - variable: "ENABLE_DUMP_STACK" description: "If disabled, it's doesn't perform the backup of stack definition" - label: "Disable Rancher dump" + label: "Enable Rancher dump stack" type: "string" required: true - default: "false" + default: "true" type: "enum" options: - "false" - "true" - - variable: FTP_PASSWORD + - variable: "ENABLE_DUMP_RANCHER_DATABASE" + description: "If disabled, it's doesn't perform the dump of Rancher database" + label: "Enable Rancher database dump" + type: "string" + required: true + default: "true" + type: "enum" + options: + - "false" + - "true" + - variable: "VOLUME_DRIVER" + description: "Docker driver to store volume of local dump" + label: "Volume drver / Path" + type: "string" + required: true + default: "local" + - variable: "RANCHER_DATABASE_HOST" + description: "The rancher database host" + label: "Rancher DB host" + type: "string" + required: false + - variable: "RANCHER_DATABASE_PORT" + description: "The rancher database port" + label: "Rancher DB port" + type: "string" + required: false + default: "3306" + - variable: "RANCHER_DATABASE_NAME" + description: "The rancher database name" + label: "Rancher DB name" + type: "string" + required: false + default: "rancher" + - variable: "RANCHER_DATABASE_USER" + description: "The rancher database user" + label: "Rancher DB user" + type: "string" + required: false + default: "rancher" + - variable: "RANCHER_DATABASE_PASSWORD" + description: "The rancher database password" + label: "Rancher DB password" + type: "password" + required: false + - variable: "CONFD_BACKEND" + description: "The confd backend to grab config" + label: "Confd backend" + required: true + default: "env" + type: "string" + - variable: "CONFD_NODES" + description: "The confd nodes" + label: "Confd nodes" + required: false + type: "string" + - variable: "CONFD_PREFIX" + description: "The confd prefix" + label: "Confd prefix" + required: true + default: "/backup" + type: "string" + - variable: "FTP_PASSWORD" label: "FTP password" type: "password" required: false - - variable: AWS_ACCESS_KEY_ID + - variable: "AWS_ACCESS_KEY_ID" label: "AWS access key" type: "string" required: false - - variable: AWS_SECRET_ACCESS_KEY + - variable: "AWS_SECRET_ACCESS_KEY" label: "AWS secret key" type: "password" required: false - - variable: AZURE_ACCOUNT_NAME + - variable: "AZURE_ACCOUNT_NAME" label: "Azure account name" type: "string" required: false - - variable: AZURE_ACCOUNT_KEY + - variable: "AZURE_ACCOUNT_KEY" label: "Azure account key" type: "password" required: false - - variable: CLOUDFILES_USERNAME + - variable: "CLOUDFILES_USERNAME" label: "CloudFiles username" type: "string" required: false - - variable: CLOUDFILES_APIKEY + - variable: "CLOUDFILES_APIKEY" label: "Cloudfiles API key" type: "password" required: false - - variable: DPBX_ACCESS_TOKEN + - variable: "DPBX_ACCESS_TOKEN" label: "Dropbox access token" type: "password" required: false - - variable: GS_ACCESS_KEY_ID + - variable: "GS_ACCESS_KEY_ID" label: "Google Storage key" type: "string" required: false - - variable: GS_SECRET_ACCESS_KEY + - variable: "GS_SECRET_ACCESS_KEY" label: "Google Storage secret" type: "password" required: false - - variable: GOOGLE_DRIVE_ACCOUNT_KEY + - variable: "GOOGLE_DRIVE_ACCOUNT_KEY" label: "Google Drive account key" type: "password" required: false - - variable: SWIFT_USERNAME + - variable: "SWIFT_USERNAME" label: "Swift username" type: "string" required: false - - variable: SWIFT_PASSWORD + - variable: "SWIFT_PASSWORD" label: "Swift password" type: "password" required: false - - variable: SWIFT_AUTHURL + - variable: "SWIFT_AUTHURL" label: "Swift auth URL" type: "string" required: false @@ -127,5 +193,3 @@ backup: scale: 1 -backup-data: - scale: 1 diff --git a/templates/rancher-backup/config.yml b/templates/rancher-backup/config.yml index 8c5aa70..eb47b19 100644 --- a/templates/rancher-backup/config.yml +++ b/templates/rancher-backup/config.yml @@ -1,5 +1,7 @@ name: Rancher Backup description: | It's a general purpose to solve backup matter on Rancher. -version: 1.0.2 +version: 2.0.0 category: Backup +maintainer: "Sebastien Langoureaux " +license: MIT License diff --git a/templates/reactioncommerce/0/README.md b/templates/reactioncommerce/0/README.md new file mode 100644 index 0000000..dd9a400 --- /dev/null +++ b/templates/reactioncommerce/0/README.md @@ -0,0 +1,22 @@ +### Docs + +The Reaction Commerce official docs are +[here](https://docs.reactioncommerce.com/) + +This template implements the same method as found +[here](https://docs.reactioncommerce.com/reaction-docs/master/deploying-reaction-using-docker) + +### MongoDB + +You'll need a mongodb stack running, choose it in the external link +question below + +### Traefik + +For external access you'll need to setup [traefik](https://github.com/rancher/community-catalog/tree/master/templates/traefik), all the appropriate +labels will be set when you set the hostname and domain below + +### Support + +There are experimental versions of this template in this catalog [here](https://github.com/ohmydocker/ohmydocker-catalog) which implement +other setups. Issues, PRs, etc are welcome there. diff --git a/templates/reactioncommerce/0/docker-compose.yml.tpl b/templates/reactioncommerce/0/docker-compose.yml.tpl new file mode 100644 index 0000000..4ca7e1f --- /dev/null +++ b/templates/reactioncommerce/0/docker-compose.yml.tpl @@ -0,0 +1,40 @@ +version: '2' +services: + reaction: + image: reactioncommerce/reaction:v1.4.0 + restart: always + labels: + io.rancher.scheduler.affinity:host_label: ${host_label} + traefik.enable: true + traefik.alias: ${REACTION_HOST} + traefik.domain: ${REACTION_DOMAIN} + traefik.acme: true + traefik.port: 3000 + environment: + MONGO_URL: "mongodb://mongo/${MONGO_DB}" + ROOT_URL: "http://${REACTION_HOST}.${REACTION_DOMAIN}" + REACTION_EMAIL: ${REACTION_EMAIL} + REACTION_USER: ${REACTION_USER} + REACTION_AUTH: ${REACTION_AUTH} +{{- if ne .Values.mongo_link ""}} + external_links: + - ${mongo_link}:mongo + tty: true +{{- else}} + mongo: + command: mongod --storageEngine=wiredTiger + restart: always + environment: + MONGO_SERVICE_NAME: mongo + CATTLE_SCRIPT_DEBUG: ${debug} + tty: true + image: mongo:3.4 + labels: + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.container.hostname_override: container_name + volumes: + - mongodata:/data/db +volumes: + mongodata: + driver: ${VOLUME_DRIVER} +{{- end}} diff --git a/templates/reactioncommerce/0/rancher-compose.yml b/templates/reactioncommerce/0/rancher-compose.yml new file mode 100644 index 0000000..e295a7a --- /dev/null +++ b/templates/reactioncommerce/0/rancher-compose.yml @@ -0,0 +1,70 @@ +version: '2' +catalog: + name: "reactiondemo" + version: 1.4.0-rancher1 + description: "E-commerce powered by reaction" + uuid: reaction-0 + minimum_rancher_version: v0.51.0 + questions: + - variable: "REACTION_HOST" + description: "Hostname to use for the reaction server" + label: "reaction Hostname" + required: true + default: "reaction" + type: "string" + - variable: "REACTION_DOMAIN" + description: "Domain to use for the reaction server" + label: "reaction Domain" + required: true + default: "local" + type: "string" + - variable: host_label + label: "Host Label to reaction Tags" + description: | + Host label to use as reaction 'value' tag. + Example: 'reaction=true' + required: false + default: "private=true" + type: "string" + - variable: REACTION_EMAIL + label: "reaction Email" + required: true + default: "test@local" + type: "string" + - variable: REACTION_USER + label: "reaction User" + required: true + default: "" + type: "string" + - variable: REACTION_AUTH + label: "reaction Auth" + required: true + default: "" + type: "password" + - variable: "mongo_link" + description: | + MongoDB external service link + cluster. + label: "External stack/service" + default: "" + required: false + type: "service" + - variable: "MONGO_DB" + default: "reaction" + description: "The mongodb name to associate with this server." + label: "mongo_db" + required: true + type: "string" + +services: + reaction: + scale: 1 + retain_ip: true + health_check: + healthy_threshold: 2 + response_timeout: 5000 + port: 3000 + unhealthy_threshold: 3 + interval: 5000 + strategy: recreate + request_line: GET / # HTTP/1.0 diff --git a/templates/reactioncommerce/README.md b/templates/reactioncommerce/README.md new file mode 100644 index 0000000..675e427 --- /dev/null +++ b/templates/reactioncommerce/README.md @@ -0,0 +1 @@ +#[ReactionCommerce](http://reactioncommerce.com/) diff --git a/templates/reactioncommerce/catalogIcon-reactioncommerce.png b/templates/reactioncommerce/catalogIcon-reactioncommerce.png new file mode 100644 index 0000000..bd5e651 Binary files /dev/null and b/templates/reactioncommerce/catalogIcon-reactioncommerce.png differ diff --git a/templates/reactioncommerce/config.yml b/templates/reactioncommerce/config.yml new file mode 100644 index 0000000..7719f54 --- /dev/null +++ b/templates/reactioncommerce/config.yml @@ -0,0 +1,5 @@ +name: Reaction Commerce +description: | + E-commerce powered by Reaction +version: 1.4.0-rancher1 +category: Repository diff --git a/templates/redmine/0/docker-compose.yml b/templates/redmine/0/docker-compose.yml new file mode 100644 index 0000000..1389433 --- /dev/null +++ b/templates/redmine/0/docker-compose.yml @@ -0,0 +1,45 @@ +version: '2' +services: + redmine: + image: sameersbn/redmine:3.3.2-1 + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.pull_image: always + traefik.enable: true + traefik.alias: ${REDMINE_HOST} + traefik.domain: ${REDMINE_DOMAIN} + traefik.acme: true + traefik.port: 80 + environment: + - PORT=80 + - TZ=${TZ} + - DB_PASS=${DB_PASS} + - DB_ADAPTER=mysql2 + - DB_HOST=db + - DB_USER=redmine + - DB_NAME=redmine_production + - REDMINE_SECRET_TOKEN=${REDMINE_SECRET_TOKEN} + - SMTP_ENABLED=false + - IMAP_ENABLED=false + volumes: + - redminedata:/home/redmine/data + - redminelog:/var/log/redmine + db: + restart: always + image: mariadb:10.2 + volumes: + - redminedbdata:/var/lib/mysql + labels: + io.rancher.container.pull_image: always + environment: + - MYSQL_USER=redmine + - MYSQL_PASSWORD=${DB_PASS} + - MYSQL_ROOT_PASSWORD=${DB_PASS} + - MYSQL_DATABASE=redmine_production +volumes: + redminedata: + driver: ${VOLUME_DRIVER} + redminelog: + driver: ${VOLUME_DRIVER} + redminedbdata: + driver: ${VOLUME_DRIVER} diff --git a/templates/redmine/0/rancher-compose.yml b/templates/redmine/0/rancher-compose.yml new file mode 100644 index 0000000..d8effe1 --- /dev/null +++ b/templates/redmine/0/rancher-compose.yml @@ -0,0 +1,61 @@ +version: '2' +catalog: + name: Redmine + version: 0.1.2 + description: | + Redmine + questions: + - variable: "REDMINE_HOST" + description: "Hostname to use for the Redmine" + label: "Thalhalla Store Hostname" + required: true + default: "redmine" + type: "string" + - variable: "REDMINE_DOMAIN" + description: "Domain to use for the Redmine server" + label: "REDMINE Domain" + required: true + default: "" + type: "string" + - variable: "TZ" + description: "Timezone to use for the server" + label: "Timezone" + required: true + default: "America/Chicago" + type: "string" + - variable: "DB_PASS" + description: "Database Password to use for the server" + label: "DB Password" + required: true + default: "" + type: "password" + - variable: "REDMINE_SECRET_TOKEN" + description: "REDMINE_SECRET_TOKEN" + label: "REDMINE_SECRET_TOKEN" + required: true + default: "" + type: "password" + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "rancher-nfs" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs + +services: + redmine: + scale: 1 + retain_ip: true + health_check: + healthy_threshold: 2 + response_timeout: 5000 + port: 80 + unhealthy_threshold: 3 + interval: 5000 + strategy: recreate + request_line: GET / # HTTP/1.0 diff --git a/templates/redmine/README.md b/templates/redmine/README.md new file mode 100644 index 0000000..7f7aaae --- /dev/null +++ b/templates/redmine/README.md @@ -0,0 +1,11 @@ +[Redmine](https://www.redmine.org/) + +Redmine is a flexible project management web application. Written using +the Ruby on Rails framework, it is cross-platform and cross-database. + +This rancher template should get you a redmine container up and running +to test. To see other implementations, including postgres, and using convoy for persistent data see +the catalog [here](https://github.com/webhostingcoopteam/whc-catalog) + +For external access you'll need to setup [traefik](https://github.com/rancher/community-catalog/tree/master/templates/traefik), all the appropriate +labels will be set when you set the hostname and domain below diff --git a/templates/redmine/catalogIcon-redmine.png b/templates/redmine/catalogIcon-redmine.png new file mode 100644 index 0000000..e962805 Binary files /dev/null and b/templates/redmine/catalogIcon-redmine.png differ diff --git a/templates/redmine/config.yml b/templates/redmine/config.yml new file mode 100644 index 0000000..453bbcd --- /dev/null +++ b/templates/redmine/config.yml @@ -0,0 +1,5 @@ +name: Redmine +description: | + Redmine Project Manager +version: 0.1.2 +category: Project Management diff --git a/templates/rethinkdb/0/README.md b/templates/rethinkdb/0/README.md new file mode 100644 index 0000000..ddc7f05 --- /dev/null +++ b/templates/rethinkdb/0/README.md @@ -0,0 +1,17 @@ +# RethinkDB Cluster +RethinkDB is the first open-source, scalable JSON database built from the ground up for the realtime web. It inverts the traditional database architecture by exposing an exciting new access model – instead of polling for changes, the developer can tell RethinkDB to continuously push updated query results to applications in realtime. RethinkDB’s realtime push architecture dramatically reduces the time and effort necessary to build scalable realtime apps. + + +**This Template creates 2 services:** +- **rethinkdb:** This is the scalable database service. +- **rethinkdb-proxy:** This is the proxy service, the query-router and admin panel. (queries are sent to this service) + + +### Repository +https://github.com/xkodiak/rancher-rethinkdb + +### Variables +- **Proxy Web Port:** admin panel port (default: 8080) +- **Proxy Query Port:** query port (default: 28015) +- **Volume Driver:** local, rancher-nfs, ... (default: local) + diff --git a/templates/rethinkdb/0/docker-compose.yml b/templates/rethinkdb/0/docker-compose.yml new file mode 100644 index 0000000..6b69a23 --- /dev/null +++ b/templates/rethinkdb/0/docker-compose.yml @@ -0,0 +1,23 @@ +version: '2' +volumes: + rethinkdb-data: + driver: '${rethinkdb_volume_driver}' + per_container: true +services: + rethinkdb: + image: xkodiak/rancher-rethinkdb:2.3.5 + volumes: + - rethinkdb-data:/data + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + rethinkdb-proxy: + image: xkodiak/rancher-rethinkdb:2.3.5 + entrypoint: /proxy.sh + links: + - rethinkdb:db + ports: + - ${rethinkdb_proxy_webport}:8080/tcp + - ${rethinkdb_proxy_queryport}:28015/tcp + depends_on: + - rethinkdb diff --git a/templates/rethinkdb/0/rancher-compose.yml b/templates/rethinkdb/0/rancher-compose.yml new file mode 100644 index 0000000..d2524bf --- /dev/null +++ b/templates/rethinkdb/0/rancher-compose.yml @@ -0,0 +1,34 @@ +.catalog: + name: "RethinkDB" + version: "2.3.5" + description: "(Experimental) NoSQL-Database" + uuid: rethinkdb-0 + questions: + - variable: "rethinkdb_proxy_webport" + description: "" + label: "Proxy Web Port (Admin Panel):" + required: true + type: "int" + default: 8080 + - variable: "rethinkdb_proxy_queryport" + description: "" + label: "Proxy Query Port:" + required: true + type: "int" + default: 28015 + - variable: "rethinkdb_volume_driver" + description: "" + label: "Volume Driver:" + required: true + type: "string" + default: "local" + + +version: '2' +services: + rethinkdb: + scale: 1 + start_on_create: true + rethinkdb-proxy: + scale: 1 + start_on_create: true diff --git a/templates/rethinkdb/catalogIcon-rethinkdb.svg b/templates/rethinkdb/catalogIcon-rethinkdb.svg new file mode 100644 index 0000000..30c8eea --- /dev/null +++ b/templates/rethinkdb/catalogIcon-rethinkdb.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/rethinkdb/config.yml b/templates/rethinkdb/config.yml new file mode 100644 index 0000000..fe967df --- /dev/null +++ b/templates/rethinkdb/config.yml @@ -0,0 +1,5 @@ +name: RethinkDB Cluster +description: | + RethinkDB is the open-source, scalable database that makes building realtime apps dramatically easier. +version: 2.3.5 +category: Databases diff --git a/templates/sematext/0/docker-compose.yml b/templates/sematext/0/docker-compose.yml index c4c2d80..83be754 100755 --- a/templates/sematext/0/docker-compose.yml +++ b/templates/sematext/0/docker-compose.yml @@ -8,8 +8,8 @@ sematext-agent: - HTTP_PROXY=${http_proxy} - MATCH_BY_IMAGE=${match_by_image} - MATCH_BY_NAME=${match_by_name} - - SKIP_BY_IMAGE=${match_by_image} - - SKIP_BY_NAME=${match_by_name} + - SKIP_BY_IMAGE=${skip_by_image} + - SKIP_BY_NAME=${skip_by_name} - LOGAGENT_PATTERNS=${logagent_patterns} - KUBERNETES=${kubernetes} restart: always diff --git a/templates/sentry/0/docker-compose.yml b/templates/sentry/0/docker-compose.yml index a4cdb80..2088569 100644 --- a/templates/sentry/0/docker-compose.yml +++ b/templates/sentry/0/docker-compose.yml @@ -56,7 +56,7 @@ sentry: command: - /bin/bash - -c - - sentry upgrade --noinput && sentry createuser --email ${sentry_inital_user_email} --password ${sentry_inital_user_password} --superuser && /entrypoint.sh run web || /entrypoint.sh run web + - sentry upgrade --noinput && sentry createuser --email ${sentry_initial_user_email} --password ${sentry_initial_user_password} --superuser && /entrypoint.sh run web || /entrypoint.sh run web log_opt: {} image: sentry:8.5.0 links: diff --git a/templates/sentry/0/rancher-compose.yml b/templates/sentry/0/rancher-compose.yml index befa967..b9ed333 100644 --- a/templates/sentry/0/rancher-compose.yml +++ b/templates/sentry/0/rancher-compose.yml @@ -16,17 +16,17 @@ label: "Sentry public port" description: "Port that Sentry will listen on. Alternatively you could point a load balancer to the port 9000 of this container" - - variable: "sentry_inital_user_email" + - variable: "sentry_initial_user_email" type: "string" required: true - label: "SENTRY_INITAL_USER_EMAIL" + label: "SENTRY_INITIAL_USER_EMAIL" description: "The initial superuser email" - - variable: "sentry_inital_user_password" + - variable: "sentry_initial_user_password" type: "password" required: true - label: "SENTRY_INITAL_USER_PASSWORD" - description: "The initial superuser password. Please use a simple intial password and change it afterwards in the Sentry interface" + label: "SENTRY_INITIAL_USER_PASSWORD" + description: "The initial superuser password. Please use a simple initial password and change it afterwards in the Sentry interface" - variable: "sentry_server_email" type: "string" @@ -52,12 +52,6 @@ label: "SENTRY_EMAIL_PASSWORD" description: "The password for the email account. see https://hub.docker.com/_/sentry/ for more info" - - variable: "sentry_email_password" - type: "string" - required: false - label: "SENTRY_EMAIL_PASSWORD" - description: "The password for the email account. see https://hub.docker.com/_/sentry/ for more info" - - variable: "sentry_email_port" type: "int" required: false diff --git a/templates/sentry/1/README.md b/templates/sentry/1/README.md new file mode 100644 index 0000000..c35b928 --- /dev/null +++ b/templates/sentry/1/README.md @@ -0,0 +1,20 @@ +# Sentry + + +### Info: + This templates creates a complete [sentry](https://github.com/getsentry/sentry) setup including postgres and redis servers. + + Images are the offical images from: + * Sentry: [https://hub.docker.com/_/sentry/](https://hub.docker.com/_/sentry/) + * Postgres: [https://hub.docker.com/_/postgres/](https://hub.docker.com/_/postgres/) + * Redis: [https://hub.docker.com/_/redis/](https://hub.docker.com/_/redis/) + +### Usage: + + * Select Sentry from catalog. + + * Required: Enter a sentry secret + + * Optional: Email configuration + + * Click deploy. diff --git a/templates/sentry/1/docker-compose.yml b/templates/sentry/1/docker-compose.yml new file mode 100644 index 0000000..f86f5f6 --- /dev/null +++ b/templates/sentry/1/docker-compose.yml @@ -0,0 +1,114 @@ +sentry-postgres: + environment: + POSTGRES_DB: ${sentry_db_name} + POSTGRES_USER: ${sentry_db_user} + POSTGRES_PASSWORD: ${sentry_db_pass} + PGDATA: /data/postgres/data + log_driver: '' + labels: + io.rancher.sidekicks: sentry-postgres-datavolume + io.rancher.container.hostname_override: container_name + volumes_from: + - sentry-postgres-datavolume + tty: true + log_opt: {} + image: postgres:9.6-alpine + stdin_open: true +sentry-postgres-datavolume: + image: alpine + stdin_open: true + net: none + entrypoint: + - /bin/true + volumes: + - /data/postgres/data + tty: true + labels: + io.rancher.container.start_once: 'true' +sentry-cron: + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + command: + - run + - cron + log_opt: {} + image: sentry:8.17.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true +sentry-redis: + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + log_opt: {} + image: redis:3.2-alpine + stdin_open: true +sentry: + ports: + - ${sentry_public_port}:9000/tcp + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + command: + - /bin/bash + - -c + - sentry upgrade --noinput && sentry createuser --email ${sentry_initial_user_email} --password ${sentry_initial_user_password} --superuser && /entrypoint.sh run web || /entrypoint.sh run web + log_opt: {} + image: sentry:8.17.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true +sentry-worker: + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.container.hostname_override: container_name + tty: true + command: + - run + - worker + log_opt: {} + image: sentry:8.17.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true diff --git a/templates/sentry/1/rancher-compose.yml b/templates/sentry/1/rancher-compose.yml new file mode 100644 index 0000000..54ffc6e --- /dev/null +++ b/templates/sentry/1/rancher-compose.yml @@ -0,0 +1,129 @@ +version: '2' +catalog: + name: Sentry + version: 8.17.0 + description: Sentry is a realtime event logging and aggregation platform + + questions: + - variable: "sentry_secret_key" + type: "password" + required: true + label: "SENTRY_SECRET_KEY" + description: "A secret key used for cryptographic functions within Sentry. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_public_port" + type: "int" + required: true + label: "Sentry public port" + default: 9000 + description: "Port that Sentry will listen on. Alternatively you could point a load balancer to the port 9000 of this container" + + - variable: "sentry_db_name" + type: "string" + required: true + label: "Sentry db name" + default: "sentry" + description: "Sentry db name." + + - variable: "sentry_db_user" + type: "string" + required: true + label: "Sentry db user" + default: "sentry" + description: "Sentry db user." + + - variable: "sentry_db_pass" + type: "string" + required: true + label: "Sentry db pass" + default: "sentry" + description: "Sentry db pass." + + - variable: "sentry_initial_user_email" + type: "string" + required: true + label: "SENTRY_INITIAL_USER_EMAIL" + description: "The initial superuser email" + + - variable: "sentry_initial_user_password" + type: "password" + required: true + label: "SENTRY_INITIAL_USER_PASSWORD" + description: "The initial superuser password. Please use a simple initial password and change it afterwards in the Sentry interface" + + - variable: "sentry_server_email" + type: "string" + required: false + label: "SENTRY_SERVER_EMAIL" + description: "The email address used for 'From:'. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_host" + type: "string" + required: false + label: "SENTRY_EMAIL_HOST" + description: "The smtp server address. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_user" + type: "string" + required: false + label: "SENTRY_EMAIL_USER" + description: "The username for the email account. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_password" + type: "password" + required: false + label: "SENTRY_EMAIL_PASSWORD" + description: "The password for the email account. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_port" + type: "int" + required: false + label: "SENTRY_EMAIL_PORT" + description: "Port of the smtp server. see https://hub.docker.com/_/sentry/ for more info" + +services: + sentry-cron: + scale: 1 + start_on_create: true + sentry-postgres-datavolume: + scale: 1 + start_on_create: true + sentry-worker: + start_on_create: true + sentry-redis: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 6379 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + reinitializing_timeout: 60000 + sentry-postgres: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 5432 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + reinitializing_timeout: 60000 + sentry: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 9000 + unhealthy_threshold: 3 + initializing_timeout: 600000 + interval: 2000 + strategy: recreate + request_line: GET "/auth/login/sentry" "HTTP/1.0" + reinitializing_timeout: 60000 diff --git a/templates/sentry/2/README.md b/templates/sentry/2/README.md new file mode 100644 index 0000000..c35b928 --- /dev/null +++ b/templates/sentry/2/README.md @@ -0,0 +1,20 @@ +# Sentry + + +### Info: + This templates creates a complete [sentry](https://github.com/getsentry/sentry) setup including postgres and redis servers. + + Images are the offical images from: + * Sentry: [https://hub.docker.com/_/sentry/](https://hub.docker.com/_/sentry/) + * Postgres: [https://hub.docker.com/_/postgres/](https://hub.docker.com/_/postgres/) + * Redis: [https://hub.docker.com/_/redis/](https://hub.docker.com/_/redis/) + +### Usage: + + * Select Sentry from catalog. + + * Required: Enter a sentry secret + + * Optional: Email configuration + + * Click deploy. diff --git a/templates/sentry/2/docker-compose.yml b/templates/sentry/2/docker-compose.yml new file mode 100644 index 0000000..02fd700 --- /dev/null +++ b/templates/sentry/2/docker-compose.yml @@ -0,0 +1,114 @@ +sentry-postgres: + environment: + POSTGRES_DB: ${sentry_db_name} + POSTGRES_USER: ${sentry_db_user} + POSTGRES_PASSWORD: ${sentry_db_pass} + PGDATA: /data/postgres/data + log_driver: '' + labels: + io.rancher.sidekicks: sentry-postgres-datavolume + io.rancher.container.hostname_override: container_name + volumes_from: + - sentry-postgres-datavolume + tty: true + log_opt: {} + image: postgres:9.6-alpine + stdin_open: true +sentry-postgres-datavolume: + image: alpine + stdin_open: true + net: none + entrypoint: + - /bin/true + volumes: + - /data/postgres/data + tty: true + labels: + io.rancher.container.start_once: 'true' +sentry-cron: + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + command: + - run + - cron + log_opt: {} + image: sentry:8.18.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true +sentry-redis: + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + log_opt: {} + image: redis:3.2-alpine + stdin_open: true +sentry: + ports: + - ${sentry_public_port}:9000/tcp + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.container.hostname_override: container_name + tty: true + command: + - /bin/bash + - -c + - sentry upgrade --noinput && sentry createuser --email ${sentry_initial_user_email} --password ${sentry_initial_user_password} --superuser && /entrypoint.sh run web || /entrypoint.sh run web + log_opt: {} + image: sentry:8.18.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true +sentry-worker: + environment: + SENTRY_EMAIL_HOST: ${sentry_email_host} + SENTRY_EMAIL_PASSWORD: ${sentry_email_password} + SENTRY_EMAIL_PORT: '${sentry_email_port}' + SENTRY_EMAIL_USER: ${sentry_email_user} + SENTRY_SECRET_KEY: ${sentry_secret_key} + SENTRY_SERVER_EMAIL: ${sentry_server_email} + SENTRY_POSTGRES_HOST: postgres + SENTRY_DB_NAME: ${sentry_db_name} + SENTRY_DB_USER: ${sentry_db_user} + SENTRY_DB_PASSWORD: ${sentry_db_pass} + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.container.hostname_override: container_name + tty: true + command: + - run + - worker + log_opt: {} + image: sentry:8.18.0 + links: + - sentry-postgres:postgres + - sentry-redis:redis + stdin_open: true diff --git a/templates/sentry/2/rancher-compose.yml b/templates/sentry/2/rancher-compose.yml new file mode 100644 index 0000000..9631c30 --- /dev/null +++ b/templates/sentry/2/rancher-compose.yml @@ -0,0 +1,129 @@ +version: '2' +catalog: + name: Sentry + version: 8.18.0 + description: Sentry is a realtime event logging and aggregation platform + + questions: + - variable: "sentry_secret_key" + type: "password" + required: true + label: "SENTRY_SECRET_KEY" + description: "A secret key used for cryptographic functions within Sentry. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_public_port" + type: "int" + required: true + label: "Sentry public port" + default: 9000 + description: "Port that Sentry will listen on. Alternatively you could point a load balancer to the port 9000 of this container" + + - variable: "sentry_db_name" + type: "string" + required: true + label: "Sentry db name" + default: "sentry" + description: "Sentry db name." + + - variable: "sentry_db_user" + type: "string" + required: true + label: "Sentry db user" + default: "sentry" + description: "Sentry db user." + + - variable: "sentry_db_pass" + type: "string" + required: true + label: "Sentry db pass" + default: "sentry" + description: "Sentry db pass." + + - variable: "sentry_initial_user_email" + type: "string" + required: true + label: "SENTRY_INITIAL_USER_EMAIL" + description: "The initial superuser email" + + - variable: "sentry_initial_user_password" + type: "password" + required: true + label: "SENTRY_INITIAL_USER_PASSWORD" + description: "The initial superuser password. Please use a simple initial password and change it afterwards in the Sentry interface" + + - variable: "sentry_server_email" + type: "string" + required: false + label: "SENTRY_SERVER_EMAIL" + description: "The email address used for 'From:'. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_host" + type: "string" + required: false + label: "SENTRY_EMAIL_HOST" + description: "The smtp server address. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_user" + type: "string" + required: false + label: "SENTRY_EMAIL_USER" + description: "The username for the email account. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_password" + type: "password" + required: false + label: "SENTRY_EMAIL_PASSWORD" + description: "The password for the email account. see https://hub.docker.com/_/sentry/ for more info" + + - variable: "sentry_email_port" + type: "int" + required: false + label: "SENTRY_EMAIL_PORT" + description: "Port of the smtp server. see https://hub.docker.com/_/sentry/ for more info" + +services: + sentry-cron: + scale: 1 + start_on_create: true + sentry-postgres-datavolume: + scale: 1 + start_on_create: true + sentry-worker: + start_on_create: true + sentry-redis: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 6379 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + reinitializing_timeout: 60000 + sentry-postgres: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 5432 + unhealthy_threshold: 3 + initializing_timeout: 60000 + interval: 2000 + strategy: recreate + reinitializing_timeout: 60000 + sentry: + scale: 1 + start_on_create: true + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 9000 + unhealthy_threshold: 3 + initializing_timeout: 600000 + interval: 2000 + strategy: recreate + request_line: GET "/auth/login/sentry" "HTTP/1.0" + reinitializing_timeout: 60000 diff --git a/templates/sentry/config.yml b/templates/sentry/config.yml index 4b8a9f2..76276bb 100644 --- a/templates/sentry/config.yml +++ b/templates/sentry/config.yml @@ -1,4 +1,4 @@ name: Sentry -version: 8.5.0 +version: 8.18.0 description: Sentry is a realtime event logging and aggregation platform category: Error Tracking diff --git a/templates/sonarqube/README.md b/templates/sonarqube/0/README.md similarity index 100% rename from templates/sonarqube/README.md rename to templates/sonarqube/0/README.md diff --git a/templates/sonarqube/0/docker-compose.yml b/templates/sonarqube/0/docker-compose.yml index fa6b751..74e98a3 100644 --- a/templates/sonarqube/0/docker-compose.yml +++ b/templates/sonarqube/0/docker-compose.yml @@ -7,7 +7,7 @@ sonarqube-data: - /opt/sonarqube/extensions/plugins sonarqube: - image: sonarqube + image: sonarqube:5.6.6 ports: - ${http_port}:9000 links: diff --git a/templates/sonarqube/1/README.md b/templates/sonarqube/1/README.md new file mode 100644 index 0000000..b95a44c --- /dev/null +++ b/templates/sonarqube/1/README.md @@ -0,0 +1,19 @@ +## What is inside SonarQube Stack? +* [SonarQube Server](http://www.sonarqube.org/) + Sidekick for storing plugins +* Postgres Database + Sidekick for storing data + +## Info +* In default SonarQube package will install alpine docker version and will create "sonar" postgres database, user and password. +* SonarQube service is exposed by a loadbalancer. +* Optional, you could install non alpine version. Use it if your software needs glibc. +* Optional, you could use an external postgres database link. +* Once SonarQube will start, make sure you setup correct information in setup page. +* For easy upgrades there are sidekicks for postgres data with dedicated storage. + +## Installing Plugins Manually +* Go to [Plugin Library](http://docs.sonarqube.org/display/PLUG/Plugin+Library) and find your favourite plugins +* Execute `docker exec -it [sonarqube-data bash]`, go to /opt/sonarqube/extensions/plugins and put your plugins here +* Restart SonarQube container. + +## First Start +* Use admin/admin to login to the SonarQube interface. \ No newline at end of file diff --git a/templates/sonarqube/1/docker-compose.yml.tpl b/templates/sonarqube/1/docker-compose.yml.tpl new file mode 100644 index 0000000..8fcb41b --- /dev/null +++ b/templates/sonarqube/1/docker-compose.yml.tpl @@ -0,0 +1,67 @@ +version: '2' +services: + sonarqube-lb: + image: rancher/lb-service-haproxy:v0.7.6 + ports: + - ${http_port}:${http_port} + sonarqube-storage: + network_mode: none + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=0 + - SERVICE_GID=0 + - SERVICE_VOLUME=/opt/sonarqube/extensions/plugins + volumes: + - sonarqube-plugin:/opt/sonarqube/extensions/plugins + image: rawmind/alpine-volume:0.0.2-1 + sonarqube: + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: sonarqube-storage + image: sonarqube:${docker_version} + environment: + SONARQUBE_WEB_JVM_OPTS: ${jvm_opts} + SONARQUBE_JDBC_USERNAME: ${postgres_user} + SONARQUBE_JDBC_PASSWORD: ${postgres_password} + SONARQUBE_JDBC_URL: jdbc:postgresql://db:${postgres_port}/${postgres_db} + volumes_from: + - sonarqube-storage +{{- if ne .Values.postgres_link ""}} + external_links: + - ${postgres_link}:db +{{- else}} + links: + - db:db + db: + labels: + io.rancher.container.hostname_override: container_name + io.rancher.sidekicks: db-storage + image: postgres:9.6.3-alpine + environment: + POSTGRES_USER: ${postgres_user} + POSTGRES_PASSWORD: ${postgres_password} + POSTGRES_DB: ${postgres_db} + volumes_from: + - db-storage + db-storage: + network_mode: none + labels: + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=0 + - SERVICE_GID=0 + - SERVICE_VOLUME=/var/lib/postgresql + volumes: + - db-data:/var/lib/postgresql + image: rawmind/alpine-volume:0.0.2-1 +{{- end}} +volumes: + sonarqube-plugin: + driver: local +{{- if eq .Values.postgres_link ""}} + db-data: + driver: local +{{- end}} diff --git a/templates/sonarqube/1/rancher-compose.yml b/templates/sonarqube/1/rancher-compose.yml new file mode 100644 index 0000000..bb90a51 --- /dev/null +++ b/templates/sonarqube/1/rancher-compose.yml @@ -0,0 +1,84 @@ +version: '2' +catalog: + name: "SonarQube" + version: "v6.5" + description: "SonarQube" + uuid: sonarqube-0 + minimum_rancher_version: v0.51.0 + questions: + - variable: docker_version + description: "SonarQube docker version" + label: "SonarQube docker version" + required: true + default: "6.5-alpine" + type: "enum" + options: + - 6.5-alpine + - 6.5 + - variable: http_port + description: "SonarQube http port" + label: "SonarQube http Port" + required: true + default: "9000" + type: "int" + - variable: jvm_opts + description: "SonarQube web jvm options" + label: "SonarQube web jvm options" + required: false + default: "" + type: "string" + - variable: postgres_port + description: "Postgres Port" + label: "Postgres Port" + required: true + default: "5432" + type: "int" + - variable: postgres_db + description: "Postgres Database Name" + label: "Postgres Database" + required: true + default: "sonar" + type: "string" + - variable: postgres_user + description: "Postgres User" + label: "Postgres User" + required: true + default: "sonar" + type: "string" + - variable: postgres_password + description: "Postgres Password" + label: "Postgres Password" + required: true + default: "sonar" + type: "password" + - variable: "postgres_link" + description: | + Optional external postgres service to use. + label: "Postgres stack/service" + default: "" + required: false + type: "service" +services: + sonarqube-lb: + scale: 1 + lb_config: + port_rules: + - protocol: http + service: sonarqube + source_port: ${http_port} + target_port: 9000 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + sonarqube: + scale: 1 + retain_ip: true + health_check: + port: 9000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET / HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 diff --git a/templates/sonarqube/config.yml b/templates/sonarqube/config.yml index ccd4ad5..13373da 100644 --- a/templates/sonarqube/config.yml +++ b/templates/sonarqube/config.yml @@ -1,5 +1,5 @@ name: SonarQube description: | SonarQube - an open source quality management platform. -version: v0.0.1 +version: v6.5 category: Test Automation diff --git a/templates/thingsboard/0/README.md b/templates/thingsboard/0/README.md new file mode 100644 index 0000000..f56f8f8 --- /dev/null +++ b/templates/thingsboard/0/README.md @@ -0,0 +1,11 @@ +## What is inside Thingsboard Stack? +* Thingsboard application +* PostgresSQL or Cassandra + +## External Requirments +* Zookeeper service(available in community catalog) + +## Info +* Thingsboard is an open-source IoT platform that enables rapid development, management and scaling of IoT projects. See [Thingsboard Architecture](https://thingsboard.io/docs/reference/architecture/) for more details. +* You can choose from two storage backends: postgres, cassandra +* You will need a Zookeeper service up and running before running this catalog diff --git a/templates/thingsboard/0/docker-compose.yml.tpl b/templates/thingsboard/0/docker-compose.yml.tpl new file mode 100644 index 0000000..54dbb92 --- /dev/null +++ b/templates/thingsboard/0/docker-compose.yml.tpl @@ -0,0 +1,49 @@ +version: '2' +services: + tb: + image: "thingsboard/application:1.2.4" + ports: + - "${http_public_port}:8080" + - "${mqtt_public_port}:1883" + - "${coap_public_port}:5683/udp" + environment: + - MQTT_BIND_ADDRESS=0.0.0.0 + - MQTT_BIND_PORT=1883 + - COAP_BIND_ADDRESS=0.0.0.0 + - COAP_BIND_PORT=5683 + - ZOOKEEPER_URL=zk:2181 + - DATABASE_TYPE=${database_type} + {{- if eq .Values.database_type "cassandra" }} + - CASSANDRA_URL=db:9042 + - CASSANDRA_HOST=db + - CASSANDRA_PORT=9042 + {{- else }} + - POSTGRES_HOST=db + - POSTGRES_PORT=5432 + {{- end }} + - ADD_SCHEMA_AND_SYSTEM_DATA=${add_schema_and_system_data} + - ADD_DEMO_DATA=${add_demo_data} + volumes: + - hsqldb_data_dir:/usr/share/thingsboard/data/sql + links: + - db:db + external_links: + - ${zookeeper_service}:zk + entrypoint: /run-application.sh + db: + {{- if eq .Values.database_type "cassandra" }} + image: "cassandra:3" + volumes: + - db_data_dir:/var/lib/cassandra + {{- else }} + image: "postgres:9.6" + environment: + - POSTGRES_DB=${postgres_db} + volumes: + - db_data_dir:/var/lib/postgresql/data + {{- end }} +volumes: + hsqldb_data_dir: + driver: ${volume_driver} + db_data_dir: + driver: ${volume_driver} \ No newline at end of file diff --git a/templates/thingsboard/0/rancher-compose.yml b/templates/thingsboard/0/rancher-compose.yml new file mode 100644 index 0000000..635b196 --- /dev/null +++ b/templates/thingsboard/0/rancher-compose.yml @@ -0,0 +1,80 @@ +version: '2' +catalog: + name: "Thingsboard" + version: "v0.1" + description: "An open source IoT platform" + uuid: Thingsboard-1 + questions: + - variable: http_public_port + description: "Thingsboard dashboard published port" + label: "Http public port" + required: true + default: "8080" + type: int + - variable: mqtt_public_port + description: "MQTT published port" + label: "MQTT public port" + required: true + default: "1883" + type: int + - variable: coap_public_port + description: "COAP published port" + label: "COAP public port" + required: true + default: "5683" + type: int + - variable: database_type + description: "Choose database type to use: sql or cassandra" + label: "Database type" + required: true + default: "sql" + type: enum + options: + - sql + - cassandra + - variable: add_schema_and_system_data + description: "Whether to init scheme and system data" + label: "Add schema and system data" + required: true + default: true + type: boolean + - variable: add_demo_data + description: "Whether to insert demo data" + label: "Add demo data" + required: true + default: true + type: boolean + - variable: zookeeper_service + description: "Zookeeper service stack" + label: "Zookeeper service" + required: true + default: "zookeeper/zk" + type: "service" + - variable: postgres_db + description: "Database name in postgresql" + label: "Dbname" + required: true + default: "thingsboard" + type: string + - variable: volume_driver + description: "Volume driver to use with this service" + label: "Volume driver" + required: true + default: "local" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs +services: + tb: + scale: 1 + retain_ip: true + health_check: + port: 8080 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET / HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 diff --git a/templates/thingsboard/catalogIcon-thingsboard.png b/templates/thingsboard/catalogIcon-thingsboard.png new file mode 100644 index 0000000..0f3b57b Binary files /dev/null and b/templates/thingsboard/catalogIcon-thingsboard.png differ diff --git a/templates/thingsboard/config.yml b/templates/thingsboard/config.yml new file mode 100644 index 0000000..9ae3d8f --- /dev/null +++ b/templates/thingsboard/config.yml @@ -0,0 +1,5 @@ +name: Thingsboard +description: | + An open source IoT platform +version: v0.1 +category: IoT \ No newline at end of file diff --git a/templates/traefik/10/README.md b/templates/traefik/10/README.md new file mode 100644 index 0000000..11bae29 --- /dev/null +++ b/templates/traefik/10/README.md @@ -0,0 +1,79 @@ +# Traefik active load balancer (Experimental) + +### Info: + + This template deploys traefik active load balancers on top of Rancher. The configuration is generated and updated with confd from Rancher metadata. + It would be deployed in hosts with label traefik_lb=true. + +### Config: + +- host_label = "traefik_lb=true" # Host label where to run traefik service. +- http_port = 8080 # Port exposed to get access to the published services. +- https_port = 8443 # Port exposed to get secured access to the published services. +- admin_port = 8000 # Port exposed to get admin access to the traefik service. +- https_enable = + - false: Enable http enpoints and disable https ones. + - true: Enable http and https endpoints. + - only: Enable https endpoints and redirect http to https. +- acme_enable = false # Enable/Disable acme traefik support. +- acme_email = "test@traefik.io" # acme user email +- acme_ondemand = true # acme ondemand parameter. +- acme_onhostrule = true # acme onHostRule parameter. +- ssl_key # Paste your ssl key. *Required if you enable https +- ssl_crt # Paste your ssl crt. *Required if you enable https +- insecure_skip = false # Enable InsecureSkipVerify param. +- refresh_interval = 10s # Interval to refresh traefik rules.toml from rancher-metadata. + +NOTE: If you enable acme support, additional sidekick will be created for acme persistance. + +### Service configuration labels: + +Traefik labels has to be added in your services, in order to get included in traefik dynamic config. + +- traefik.enable = + - true: the service will be published as *service_name.stack_name.traefik_domain* + - stack: the service will be published as *stack_name.traefik_domain*. WARNING: You could have collisions inside services within your stack + - false: the service will not be published +- traefik.priority = # Override for frontend priority. 5 by default +- traefik.protocol = < http | https > # Override the default http protocol +- traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend +- traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFULL +- traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". traefik.domain must be defined but is not appended here. +- traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," +- traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," +- traefik.port = < port > # Port to expose throught traefik +- traefik.acme = < true | false > # Enable/disable ACME traefik feature +- traefik.path = < path > # Path rule. Multiple values separated by "," +- traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," +- traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," +- traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," + +Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends + +WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. + +### Usage: + + Select Traefik from catalog. + + Set the params. + + Click deploy. + + Services will be accessed throught hosts ip's whith $host_label: + + - http://${service_name}.${stack_name}.${traefik.domain}:${http_port} + - https://${service_name}.${stack_name}.${traefik.domain}:${https_port} + + or + + - http://${stack_name}.${traefik.domain}:${http_port} + - https://${stack_name}.${traefik.domain}:${https_port} + + If you set traefik.alias you service could also be acceses through + + - http://${traefik.alias}.${traefik.domain}:${http_port} + - https://${traefik.alias}.${traefik.domain}:${https_port} + +Note: To access the services, you need to create A or CNAMES dns entries for every one. + diff --git a/templates/traefik/10/docker-compose.yml.tpl b/templates/traefik/10/docker-compose.yml.tpl new file mode 100644 index 0000000..7aec314 --- /dev/null +++ b/templates/traefik/10/docker-compose.yml.tpl @@ -0,0 +1,67 @@ +version: '2' +services: + traefik: + ports: + - ${admin_port}:8000/tcp + - ${http_port}:${http_port}/tcp + - ${https_port}:${https_port}/tcp + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: traefik-conf + {{- if eq .Values.acme_enable "true" -}} + ,traefik-acme + {{- end}} + io.rancher.container.hostname_override: container_name + image: rawmind/alpine-traefik:1.3.6 + environment: + - CONF_INTERVAL=${refresh_interval} + - TRAEFIK_HTTP_PORT=${http_port} + - TRAEFIK_HTTPS_PORT=${https_port} + - TRAEFIK_HTTPS_ENABLE=${https_enable} + {{- if eq .Values.acme_enable "true"}} + - TRAEFIK_ACME_ENABLE=${acme_enable} + - TRAEFIK_ACME_EMAIL=${acme_email} + - TRAEFIK_ACME_ONDEMAND=${acme_ondemand} + - TRAEFIK_ACME_ONHOSTRULE=${acme_onhostrule} + {{- end}} + - TRAEFIK_INSECURE_SKIP=${insecure_skip} + volumes_from: + - traefik-conf + {{- if eq .Values.acme_enable "true"}} + - traefik-acme + {{- end}} + traefik-conf: + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.start_once: 'true' + image: rawmind/rancher-traefik:1.3.6 + network_mode: none + volumes: + - tools-volume:/opt/tools + {{- if eq .Values.acme_enable "true"}} + traefik-acme: + network_mode: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10001 + - SERVICE_GID=10001 + - SERVICE_VOLUME=/opt/traefik/acme + volumes: + - ${VOLUME_NAME}:/opt/traefik/acme + image: rawmind/alpine-volume:0.0.2-1 + {{- end}} +volumes: + tools-volume: + driver: local + per_container: true + {{- if eq .Values.acme_enable "true"}} + ${VOLUME_NAME}: + driver: ${VOLUME_DRIVER} + {{- end}} diff --git a/templates/traefik/10/rancher-compose.yml b/templates/traefik/10/rancher-compose.yml new file mode 100644 index 0000000..207e24b --- /dev/null +++ b/templates/traefik/10/rancher-compose.yml @@ -0,0 +1,126 @@ +version: '2' +catalog: + name: traefik + version: v1.3.6-rancher1 + description: | + (Experimental) Traefik load balancer. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: traefik-0 + questions: + - variable: "host_label" + description: "Host label where to run traefik service." + label: "Host label:" + required: true + default: "traefik_lb=true" + type: "string" + - variable: "http_port" + description: "Traefik http public port to listen." + label: "Http port:" + required: true + default: 8080 + type: "int" + - variable: "https_port" + description: "Traefik https public port to listen." + label: "Https port:" + required: true + default: 8443 + type: "int" + - variable: "admin_port" + description: "Traefik admin public port to listen." + label: "Admin port:" + required: true + default: 8000 + type: "int" + - variable: "https_enable" + label: "Enable HTTPS:" + description: | + Enable https working mode. If you activate, you need to fill SSL key and SSL crt in order to work. + default: false + required: true + type: enum + options: + - false + - true + - only + - variable: "acme_enable" + description: "Enable acme support on traefik." + label: "Enable ACME:" + required: true + default: false + type: "boolean" + - variable: "acme_email" + description: "ACME user email." + label: "ACME email:" + required: true + default: "test@traefik.io" + type: "string" + - variable: "acme_ondemand" + description: "Enable acme ondemand." + label: "ACME ondemand:" + required: true + default: true + type: "boolean" + - variable: "acme_onhostrule" + description: "Enable acme onHostRule." + label: "ACME onHostRule:" + required: true + default: true + type: "boolean" + - variable: "ssl_key" + description: "SSL key to secure the service. *Required if you enable https" + label: "SSL key" + type: "multiline" + required: false + default: "" + - variable: "ssl_crt" + description: "SSL cert to secure the service. *Required if you enable https" + label: "SSL crt" + type: "multiline" + required: false + default: "" + - variable: "insecure_skip" + description: "Enable InsecureSkipVerify param." + label: "InsecureSkipVerify:" + required: true + default: false + type: "boolean" + - variable: "refresh_interval" + description: "Interval to poll/apply configuration changes." + label: "Refresh Interval (s):" + required: true + default: 10 + type: "int" + - variable: "VOLUME_NAME" + description: "The volume name shared to store ACME certs" + label: "ACME Volume Name" + required: true + default: "TRAEFIK" + type: "string" + - variable: "VOLUME_DRIVER" + description: "The volume driver shared to store ACME certs" + label: "ACME Volume Driver" + required: true + default: "rancher-nfs" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs +services: + traefik: + retain_ip: true + health_check: + port: 8000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET /dashboard/# HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + metadata: + traefik: + ssl_key: | + ${ssl_key} + ssl_crt: | + ${ssl_crt} diff --git a/templates/traefik/6/README.md b/templates/traefik/6/README.md new file mode 100644 index 0000000..11bae29 --- /dev/null +++ b/templates/traefik/6/README.md @@ -0,0 +1,79 @@ +# Traefik active load balancer (Experimental) + +### Info: + + This template deploys traefik active load balancers on top of Rancher. The configuration is generated and updated with confd from Rancher metadata. + It would be deployed in hosts with label traefik_lb=true. + +### Config: + +- host_label = "traefik_lb=true" # Host label where to run traefik service. +- http_port = 8080 # Port exposed to get access to the published services. +- https_port = 8443 # Port exposed to get secured access to the published services. +- admin_port = 8000 # Port exposed to get admin access to the traefik service. +- https_enable = + - false: Enable http enpoints and disable https ones. + - true: Enable http and https endpoints. + - only: Enable https endpoints and redirect http to https. +- acme_enable = false # Enable/Disable acme traefik support. +- acme_email = "test@traefik.io" # acme user email +- acme_ondemand = true # acme ondemand parameter. +- acme_onhostrule = true # acme onHostRule parameter. +- ssl_key # Paste your ssl key. *Required if you enable https +- ssl_crt # Paste your ssl crt. *Required if you enable https +- insecure_skip = false # Enable InsecureSkipVerify param. +- refresh_interval = 10s # Interval to refresh traefik rules.toml from rancher-metadata. + +NOTE: If you enable acme support, additional sidekick will be created for acme persistance. + +### Service configuration labels: + +Traefik labels has to be added in your services, in order to get included in traefik dynamic config. + +- traefik.enable = + - true: the service will be published as *service_name.stack_name.traefik_domain* + - stack: the service will be published as *stack_name.traefik_domain*. WARNING: You could have collisions inside services within your stack + - false: the service will not be published +- traefik.priority = # Override for frontend priority. 5 by default +- traefik.protocol = < http | https > # Override the default http protocol +- traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend +- traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFULL +- traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". traefik.domain must be defined but is not appended here. +- traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," +- traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," +- traefik.port = < port > # Port to expose throught traefik +- traefik.acme = < true | false > # Enable/disable ACME traefik feature +- traefik.path = < path > # Path rule. Multiple values separated by "," +- traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," +- traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," +- traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," + +Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends + +WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. + +### Usage: + + Select Traefik from catalog. + + Set the params. + + Click deploy. + + Services will be accessed throught hosts ip's whith $host_label: + + - http://${service_name}.${stack_name}.${traefik.domain}:${http_port} + - https://${service_name}.${stack_name}.${traefik.domain}:${https_port} + + or + + - http://${stack_name}.${traefik.domain}:${http_port} + - https://${stack_name}.${traefik.domain}:${https_port} + + If you set traefik.alias you service could also be acceses through + + - http://${traefik.alias}.${traefik.domain}:${http_port} + - https://${traefik.alias}.${traefik.domain}:${https_port} + +Note: To access the services, you need to create A or CNAMES dns entries for every one. + diff --git a/templates/traefik/6/docker-compose.yml.tpl b/templates/traefik/6/docker-compose.yml.tpl new file mode 100644 index 0000000..bf72727 --- /dev/null +++ b/templates/traefik/6/docker-compose.yml.tpl @@ -0,0 +1,64 @@ +traefik: + ports: + - ${admin_port}:8000/tcp + - ${http_port}:${http_port}/tcp + - ${https_port}:${https_port}/tcp + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: traefik-conf + {{- if eq .Values.acme_enable "true" -}} + ,traefik-acme + {{- end}} + io.rancher.container.hostname_override: container_name + tty: true + log_opt: {} + image: rawmind/alpine-traefik:1.2.3-1 + environment: + - CONF_INTERVAL=${refresh_interval} + - TRAEFIK_HTTP_PORT=${http_port} + - TRAEFIK_HTTPS_PORT=${https_port} + - TRAEFIK_HTTPS_ENABLE=${https_enable} +{{- if eq .Values.acme_enable "true"}} + - TRAEFIK_ACME_ENABLE=${acme_enable} + - TRAEFIK_ACME_EMAIL=${acme_email} + - TRAEFIK_ACME_ONDEMAND=${acme_ondemand} + - TRAEFIK_ACME_ONHOSTRULE=${acme_onhostrule} +{{- end}} + - TRAEFIK_INSECURE_SKIP=${insecure_skip} + volumes_from: + - traefik-conf +{{- if eq .Values.acme_enable "true"}} + - traefik-acme +{{- end}} +traefik-conf: + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.start_once: 'true' + tty: true + log_opt: {} + image: rawmind/rancher-traefik:0.3.4-19 + net: none + volumes: + - /opt/tools +{{- if eq .Values.acme_enable "true"}} +traefik-acme: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10001 + - SERVICE_GID=10001 + - SERVICE_VOLUME=/opt/traefik/acme + volumes: + - /opt/traefik/acme + volume_driver: ${VOLUME_DRIVER} + image: rawmind/alpine-volume:0.0.2-1 +{{- end}} \ No newline at end of file diff --git a/templates/traefik/6/rancher-compose.yml b/templates/traefik/6/rancher-compose.yml new file mode 100644 index 0000000..a9b23a2 --- /dev/null +++ b/templates/traefik/6/rancher-compose.yml @@ -0,0 +1,107 @@ +.catalog: + name: traefik + version: v1.2.3-1-rancher1 + description: | + (Experimental) Traefik load balancer. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: traefik-0 + questions: + - variable: "host_label" + description: "Host label where to run traefik service." + label: "Host label:" + required: true + default: "traefik_lb=true" + type: "string" + - variable: "http_port" + description: "Traefik http public port to listen." + label: "Http port:" + required: true + default: 8080 + type: "int" + - variable: "https_port" + description: "Traefik https public port to listen." + label: "Https port:" + required: true + default: 8443 + type: "int" + - variable: "admin_port" + description: "Traefik admin public port to listen." + label: "Admin port:" + required: true + default: 8000 + type: "int" + - variable: "https_enable" + label: "Enable HTTPS:" + description: | + Enable https working mode. If you activate, you need to fill SSL key and SSL crt in order to work. + default: false + required: true + type: enum + options: + - false + - true + - only + - variable: "acme_enable" + description: "Enable acme support on traefik." + label: "Enable ACME:" + required: true + default: false + type: "boolean" + - variable: "acme_email" + description: "ACME user email." + label: "ACME email:" + required: true + default: "test@traefik.io" + type: "string" + - variable: "acme_ondemand" + description: "Enable acme ondemand." + label: "ACME ondemand:" + required: true + default: true + type: "boolean" + - variable: "acme_onhostrule" + description: "Enable acme onHostRule." + label: "ACME onHostRule:" + required: true + default: true + type: "boolean" + - variable: "ssl_key" + description: "SSL key to secure the service. *Required if you enable https" + label: "SSL key" + type: "multiline" + required: false + default: "" + - variable: "ssl_crt" + description: "SSL cert to secure the service. *Required if you enable https" + label: "SSL crt" + type: "multiline" + required: false + default: "" + - variable: "insecure_skip" + description: "Enable InsecureSkipVerify param." + label: "InsecureSkipVerify:" + required: true + default: false + type: "boolean" + - variable: "refresh_interval" + description: "Interval to poll/apply configuration changes." + label: "Refresh Interval (s):" + required: true + default: 10 + type: "int" +traefik: + retain_ip: true + health_check: + port: 8000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET /dashboard/# HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + metadata: + traefik: + ssl_key: | + ${ssl_key} + ssl_crt: | + ${ssl_crt} diff --git a/templates/traefik/7/README.md b/templates/traefik/7/README.md new file mode 100644 index 0000000..11bae29 --- /dev/null +++ b/templates/traefik/7/README.md @@ -0,0 +1,79 @@ +# Traefik active load balancer (Experimental) + +### Info: + + This template deploys traefik active load balancers on top of Rancher. The configuration is generated and updated with confd from Rancher metadata. + It would be deployed in hosts with label traefik_lb=true. + +### Config: + +- host_label = "traefik_lb=true" # Host label where to run traefik service. +- http_port = 8080 # Port exposed to get access to the published services. +- https_port = 8443 # Port exposed to get secured access to the published services. +- admin_port = 8000 # Port exposed to get admin access to the traefik service. +- https_enable = + - false: Enable http enpoints and disable https ones. + - true: Enable http and https endpoints. + - only: Enable https endpoints and redirect http to https. +- acme_enable = false # Enable/Disable acme traefik support. +- acme_email = "test@traefik.io" # acme user email +- acme_ondemand = true # acme ondemand parameter. +- acme_onhostrule = true # acme onHostRule parameter. +- ssl_key # Paste your ssl key. *Required if you enable https +- ssl_crt # Paste your ssl crt. *Required if you enable https +- insecure_skip = false # Enable InsecureSkipVerify param. +- refresh_interval = 10s # Interval to refresh traefik rules.toml from rancher-metadata. + +NOTE: If you enable acme support, additional sidekick will be created for acme persistance. + +### Service configuration labels: + +Traefik labels has to be added in your services, in order to get included in traefik dynamic config. + +- traefik.enable = + - true: the service will be published as *service_name.stack_name.traefik_domain* + - stack: the service will be published as *stack_name.traefik_domain*. WARNING: You could have collisions inside services within your stack + - false: the service will not be published +- traefik.priority = # Override for frontend priority. 5 by default +- traefik.protocol = < http | https > # Override the default http protocol +- traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend +- traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFULL +- traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". traefik.domain must be defined but is not appended here. +- traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," +- traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," +- traefik.port = < port > # Port to expose throught traefik +- traefik.acme = < true | false > # Enable/disable ACME traefik feature +- traefik.path = < path > # Path rule. Multiple values separated by "," +- traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," +- traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," +- traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," + +Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends + +WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. + +### Usage: + + Select Traefik from catalog. + + Set the params. + + Click deploy. + + Services will be accessed throught hosts ip's whith $host_label: + + - http://${service_name}.${stack_name}.${traefik.domain}:${http_port} + - https://${service_name}.${stack_name}.${traefik.domain}:${https_port} + + or + + - http://${stack_name}.${traefik.domain}:${http_port} + - https://${stack_name}.${traefik.domain}:${https_port} + + If you set traefik.alias you service could also be acceses through + + - http://${traefik.alias}.${traefik.domain}:${http_port} + - https://${traefik.alias}.${traefik.domain}:${https_port} + +Note: To access the services, you need to create A or CNAMES dns entries for every one. + diff --git a/templates/traefik/7/docker-compose.yml.tpl b/templates/traefik/7/docker-compose.yml.tpl new file mode 100644 index 0000000..ea94dcc --- /dev/null +++ b/templates/traefik/7/docker-compose.yml.tpl @@ -0,0 +1,64 @@ +traefik: + ports: + - ${admin_port}:8000/tcp + - ${http_port}:${http_port}/tcp + - ${https_port}:${https_port}/tcp + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: traefik-conf + {{- if eq .Values.acme_enable "true" -}} + ,traefik-acme + {{- end}} + io.rancher.container.hostname_override: container_name + tty: true + log_opt: {} + image: rawmind/alpine-traefik:1.3.3 + environment: + - CONF_INTERVAL=${refresh_interval} + - TRAEFIK_HTTP_PORT=${http_port} + - TRAEFIK_HTTPS_PORT=${https_port} + - TRAEFIK_HTTPS_ENABLE=${https_enable} +{{- if eq .Values.acme_enable "true"}} + - TRAEFIK_ACME_ENABLE=${acme_enable} + - TRAEFIK_ACME_EMAIL=${acme_email} + - TRAEFIK_ACME_ONDEMAND=${acme_ondemand} + - TRAEFIK_ACME_ONHOSTRULE=${acme_onhostrule} +{{- end}} + - TRAEFIK_INSECURE_SKIP=${insecure_skip} + volumes_from: + - traefik-conf +{{- if eq .Values.acme_enable "true"}} + - traefik-acme +{{- end}} +traefik-conf: + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.start_once: 'true' + tty: true + log_opt: {} + image: rawmind/rancher-traefik:1.3.3-1 + net: none + volumes: + - /opt/tools +{{- if eq .Values.acme_enable "true"}} +traefik-acme: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10001 + - SERVICE_GID=10001 + - SERVICE_VOLUME=/opt/traefik/acme + volumes: + - /opt/traefik/acme + volume_driver: ${VOLUME_DRIVER} + image: rawmind/alpine-volume:0.0.2-1 +{{- end}} \ No newline at end of file diff --git a/templates/traefik/7/rancher-compose.yml b/templates/traefik/7/rancher-compose.yml new file mode 100644 index 0000000..332bff3 --- /dev/null +++ b/templates/traefik/7/rancher-compose.yml @@ -0,0 +1,107 @@ +.catalog: + name: traefik + version: v1.3.3-rancher1 + description: | + (Experimental) Traefik load balancer. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: traefik-0 + questions: + - variable: "host_label" + description: "Host label where to run traefik service." + label: "Host label:" + required: true + default: "traefik_lb=true" + type: "string" + - variable: "http_port" + description: "Traefik http public port to listen." + label: "Http port:" + required: true + default: 8080 + type: "int" + - variable: "https_port" + description: "Traefik https public port to listen." + label: "Https port:" + required: true + default: 8443 + type: "int" + - variable: "admin_port" + description: "Traefik admin public port to listen." + label: "Admin port:" + required: true + default: 8000 + type: "int" + - variable: "https_enable" + label: "Enable HTTPS:" + description: | + Enable https working mode. If you activate, you need to fill SSL key and SSL crt in order to work. + default: false + required: true + type: enum + options: + - false + - true + - only + - variable: "acme_enable" + description: "Enable acme support on traefik." + label: "Enable ACME:" + required: true + default: false + type: "boolean" + - variable: "acme_email" + description: "ACME user email." + label: "ACME email:" + required: true + default: "test@traefik.io" + type: "string" + - variable: "acme_ondemand" + description: "Enable acme ondemand." + label: "ACME ondemand:" + required: true + default: true + type: "boolean" + - variable: "acme_onhostrule" + description: "Enable acme onHostRule." + label: "ACME onHostRule:" + required: true + default: true + type: "boolean" + - variable: "ssl_key" + description: "SSL key to secure the service. *Required if you enable https" + label: "SSL key" + type: "multiline" + required: false + default: "" + - variable: "ssl_crt" + description: "SSL cert to secure the service. *Required if you enable https" + label: "SSL crt" + type: "multiline" + required: false + default: "" + - variable: "insecure_skip" + description: "Enable InsecureSkipVerify param." + label: "InsecureSkipVerify:" + required: true + default: false + type: "boolean" + - variable: "refresh_interval" + description: "Interval to poll/apply configuration changes." + label: "Refresh Interval (s):" + required: true + default: 10 + type: "int" +traefik: + retain_ip: true + health_check: + port: 8000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET /dashboard/# HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + metadata: + traefik: + ssl_key: | + ${ssl_key} + ssl_crt: | + ${ssl_crt} diff --git a/templates/traefik/8/README.md b/templates/traefik/8/README.md new file mode 100644 index 0000000..11bae29 --- /dev/null +++ b/templates/traefik/8/README.md @@ -0,0 +1,79 @@ +# Traefik active load balancer (Experimental) + +### Info: + + This template deploys traefik active load balancers on top of Rancher. The configuration is generated and updated with confd from Rancher metadata. + It would be deployed in hosts with label traefik_lb=true. + +### Config: + +- host_label = "traefik_lb=true" # Host label where to run traefik service. +- http_port = 8080 # Port exposed to get access to the published services. +- https_port = 8443 # Port exposed to get secured access to the published services. +- admin_port = 8000 # Port exposed to get admin access to the traefik service. +- https_enable = + - false: Enable http enpoints and disable https ones. + - true: Enable http and https endpoints. + - only: Enable https endpoints and redirect http to https. +- acme_enable = false # Enable/Disable acme traefik support. +- acme_email = "test@traefik.io" # acme user email +- acme_ondemand = true # acme ondemand parameter. +- acme_onhostrule = true # acme onHostRule parameter. +- ssl_key # Paste your ssl key. *Required if you enable https +- ssl_crt # Paste your ssl crt. *Required if you enable https +- insecure_skip = false # Enable InsecureSkipVerify param. +- refresh_interval = 10s # Interval to refresh traefik rules.toml from rancher-metadata. + +NOTE: If you enable acme support, additional sidekick will be created for acme persistance. + +### Service configuration labels: + +Traefik labels has to be added in your services, in order to get included in traefik dynamic config. + +- traefik.enable = + - true: the service will be published as *service_name.stack_name.traefik_domain* + - stack: the service will be published as *stack_name.traefik_domain*. WARNING: You could have collisions inside services within your stack + - false: the service will not be published +- traefik.priority = # Override for frontend priority. 5 by default +- traefik.protocol = < http | https > # Override the default http protocol +- traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend +- traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFULL +- traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". traefik.domain must be defined but is not appended here. +- traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," +- traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," +- traefik.port = < port > # Port to expose throught traefik +- traefik.acme = < true | false > # Enable/disable ACME traefik feature +- traefik.path = < path > # Path rule. Multiple values separated by "," +- traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," +- traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," +- traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," + +Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends + +WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. + +### Usage: + + Select Traefik from catalog. + + Set the params. + + Click deploy. + + Services will be accessed throught hosts ip's whith $host_label: + + - http://${service_name}.${stack_name}.${traefik.domain}:${http_port} + - https://${service_name}.${stack_name}.${traefik.domain}:${https_port} + + or + + - http://${stack_name}.${traefik.domain}:${http_port} + - https://${stack_name}.${traefik.domain}:${https_port} + + If you set traefik.alias you service could also be acceses through + + - http://${traefik.alias}.${traefik.domain}:${http_port} + - https://${traefik.alias}.${traefik.domain}:${https_port} + +Note: To access the services, you need to create A or CNAMES dns entries for every one. + diff --git a/templates/traefik/8/docker-compose.yml.tpl b/templates/traefik/8/docker-compose.yml.tpl new file mode 100644 index 0000000..8126149 --- /dev/null +++ b/templates/traefik/8/docker-compose.yml.tpl @@ -0,0 +1,64 @@ +traefik: + ports: + - ${admin_port}:8000/tcp + - ${http_port}:${http_port}/tcp + - ${https_port}:${https_port}/tcp + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: traefik-conf + {{- if eq .Values.acme_enable "true" -}} + ,traefik-acme + {{- end}} + io.rancher.container.hostname_override: container_name + tty: true + log_opt: {} + image: rawmind/alpine-traefik:1.3.3 + environment: + - CONF_INTERVAL=${refresh_interval} + - TRAEFIK_HTTP_PORT=${http_port} + - TRAEFIK_HTTPS_PORT=${https_port} + - TRAEFIK_HTTPS_ENABLE=${https_enable} +{{- if eq .Values.acme_enable "true"}} + - TRAEFIK_ACME_ENABLE=${acme_enable} + - TRAEFIK_ACME_EMAIL=${acme_email} + - TRAEFIK_ACME_ONDEMAND=${acme_ondemand} + - TRAEFIK_ACME_ONHOSTRULE=${acme_onhostrule} +{{- end}} + - TRAEFIK_INSECURE_SKIP=${insecure_skip} + volumes_from: + - traefik-conf +{{- if eq .Values.acme_enable "true"}} + - traefik-acme +{{- end}} +traefik-conf: + log_driver: '' + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.start_once: 'true' + tty: true + log_opt: {} + image: rawmind/rancher-traefik:1.3.3-1 + net: none + volumes: + - /opt/tools +{{- if eq .Values.acme_enable "true"}} +traefik-acme: + net: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10001 + - SERVICE_GID=10001 + - SERVICE_VOLUME=/opt/traefik/acme + volumes: + - ${VOLUME_NAME}:/opt/traefik/acme + volume_driver: ${VOLUME_DRIVER} + image: rawmind/alpine-volume:0.0.2-1 +{{- end}} diff --git a/templates/traefik/8/rancher-compose.yml b/templates/traefik/8/rancher-compose.yml new file mode 100644 index 0000000..49af3aa --- /dev/null +++ b/templates/traefik/8/rancher-compose.yml @@ -0,0 +1,123 @@ +.catalog: + name: traefik + version: v1.3.3-rancher2 + description: | + (Experimental) Traefik load balancer. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: traefik-0 + questions: + - variable: "host_label" + description: "Host label where to run traefik service." + label: "Host label:" + required: true + default: "traefik_lb=true" + type: "string" + - variable: "http_port" + description: "Traefik http public port to listen." + label: "Http port:" + required: true + default: 8080 + type: "int" + - variable: "https_port" + description: "Traefik https public port to listen." + label: "Https port:" + required: true + default: 8443 + type: "int" + - variable: "admin_port" + description: "Traefik admin public port to listen." + label: "Admin port:" + required: true + default: 8000 + type: "int" + - variable: "https_enable" + label: "Enable HTTPS:" + description: | + Enable https working mode. If you activate, you need to fill SSL key and SSL crt in order to work. + default: false + required: true + type: enum + options: + - false + - true + - only + - variable: "acme_enable" + description: "Enable acme support on traefik." + label: "Enable ACME:" + required: true + default: false + type: "boolean" + - variable: "acme_email" + description: "ACME user email." + label: "ACME email:" + required: true + default: "test@traefik.io" + type: "string" + - variable: "acme_ondemand" + description: "Enable acme ondemand." + label: "ACME ondemand:" + required: true + default: true + type: "boolean" + - variable: "acme_onhostrule" + description: "Enable acme onHostRule." + label: "ACME onHostRule:" + required: true + default: true + type: "boolean" + - variable: "ssl_key" + description: "SSL key to secure the service. *Required if you enable https" + label: "SSL key" + type: "multiline" + required: false + default: "" + - variable: "ssl_crt" + description: "SSL cert to secure the service. *Required if you enable https" + label: "SSL crt" + type: "multiline" + required: false + default: "" + - variable: "insecure_skip" + description: "Enable InsecureSkipVerify param." + label: "InsecureSkipVerify:" + required: true + default: false + type: "boolean" + - variable: "refresh_interval" + description: "Interval to poll/apply configuration changes." + label: "Refresh Interval (s):" + required: true + default: 10 + type: "int" + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "rancher-nfs" + type: enum + options: # List of options if using type of `enum` + - rancher-nfs + - rancher-efs + - rancher-ebs + - variable: "VOLUME_NAME" + description: "The VOLUME name to associate with this server" + label: "VOLUME Name" + required: true + default: "TRAEFIK" + type: "string" +traefik: + retain_ip: true + health_check: + port: 8000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET /dashboard/# HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + metadata: + traefik: + ssl_key: | + ${ssl_key} + ssl_crt: | + ${ssl_crt} diff --git a/templates/traefik/9/README.md b/templates/traefik/9/README.md new file mode 100644 index 0000000..11bae29 --- /dev/null +++ b/templates/traefik/9/README.md @@ -0,0 +1,79 @@ +# Traefik active load balancer (Experimental) + +### Info: + + This template deploys traefik active load balancers on top of Rancher. The configuration is generated and updated with confd from Rancher metadata. + It would be deployed in hosts with label traefik_lb=true. + +### Config: + +- host_label = "traefik_lb=true" # Host label where to run traefik service. +- http_port = 8080 # Port exposed to get access to the published services. +- https_port = 8443 # Port exposed to get secured access to the published services. +- admin_port = 8000 # Port exposed to get admin access to the traefik service. +- https_enable = + - false: Enable http enpoints and disable https ones. + - true: Enable http and https endpoints. + - only: Enable https endpoints and redirect http to https. +- acme_enable = false # Enable/Disable acme traefik support. +- acme_email = "test@traefik.io" # acme user email +- acme_ondemand = true # acme ondemand parameter. +- acme_onhostrule = true # acme onHostRule parameter. +- ssl_key # Paste your ssl key. *Required if you enable https +- ssl_crt # Paste your ssl crt. *Required if you enable https +- insecure_skip = false # Enable InsecureSkipVerify param. +- refresh_interval = 10s # Interval to refresh traefik rules.toml from rancher-metadata. + +NOTE: If you enable acme support, additional sidekick will be created for acme persistance. + +### Service configuration labels: + +Traefik labels has to be added in your services, in order to get included in traefik dynamic config. + +- traefik.enable = + - true: the service will be published as *service_name.stack_name.traefik_domain* + - stack: the service will be published as *stack_name.traefik_domain*. WARNING: You could have collisions inside services within your stack + - false: the service will not be published +- traefik.priority = # Override for frontend priority. 5 by default +- traefik.protocol = < http | https > # Override the default http protocol +- traefik.sticky = < true | false > # Enable/disable sticky sessions to the backend +- traefik.alias = < alias > # Alternate names to route rule. Multiple values separated by ",". traefik.domain is appended. WARNING: You could have collisions BE CAREFULL +- traefik.alias.fqdn = < alias fqdn > # Alternate names to route rule. Multiple values separated by ",". traefik.domain must be defined but is not appended here. +- traefik.domain = < domain.name > # Domain names to route rules. Multiple domains separated by "," +- traefik.domain.regexp = < domain.regexp > # Domain name regexp rule. Multiple domains separated by "," +- traefik.port = < port > # Port to expose throught traefik +- traefik.acme = < true | false > # Enable/disable ACME traefik feature +- traefik.path = < path > # Path rule. Multiple values separated by "," +- traefik.path.strip = < path > # Path strip rule. Multiple values separated by "," +- traefik.path.prefix = < path > # Path prefix rule. Multiple values separated by "," +- traefik.path.prefix.strip = < path > # Path prefix strip rule. Multiple values separated by "," + +Details for configuring the traefik rules can be found at: https://docs.traefik.io/basics/#frontends + +WARNING: Only services with healthy state are added to traefik, so health checks are mandatory. + +### Usage: + + Select Traefik from catalog. + + Set the params. + + Click deploy. + + Services will be accessed throught hosts ip's whith $host_label: + + - http://${service_name}.${stack_name}.${traefik.domain}:${http_port} + - https://${service_name}.${stack_name}.${traefik.domain}:${https_port} + + or + + - http://${stack_name}.${traefik.domain}:${http_port} + - https://${stack_name}.${traefik.domain}:${https_port} + + If you set traefik.alias you service could also be acceses through + + - http://${traefik.alias}.${traefik.domain}:${http_port} + - https://${traefik.alias}.${traefik.domain}:${https_port} + +Note: To access the services, you need to create A or CNAMES dns entries for every one. + diff --git a/templates/traefik/9/docker-compose.yml.tpl b/templates/traefik/9/docker-compose.yml.tpl new file mode 100644 index 0000000..ff4871d --- /dev/null +++ b/templates/traefik/9/docker-compose.yml.tpl @@ -0,0 +1,67 @@ +version: '2' +services: + traefik: + ports: + - ${admin_port}:8000/tcp + - ${http_port}:${http_port}/tcp + - ${https_port}:${https_port}/tcp + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.sidekicks: traefik-conf + {{- if eq .Values.acme_enable "true" -}} + ,traefik-acme + {{- end}} + io.rancher.container.hostname_override: container_name + image: rawmind/alpine-traefik:1.3.5 + environment: + - CONF_INTERVAL=${refresh_interval} + - TRAEFIK_HTTP_PORT=${http_port} + - TRAEFIK_HTTPS_PORT=${https_port} + - TRAEFIK_HTTPS_ENABLE=${https_enable} + {{- if eq .Values.acme_enable "true"}} + - TRAEFIK_ACME_ENABLE=${acme_enable} + - TRAEFIK_ACME_EMAIL=${acme_email} + - TRAEFIK_ACME_ONDEMAND=${acme_ondemand} + - TRAEFIK_ACME_ONHOSTRULE=${acme_onhostrule} + {{- end}} + - TRAEFIK_INSECURE_SKIP=${insecure_skip} + volumes_from: + - traefik-conf + {{- if eq .Values.acme_enable "true"}} + - traefik-acme + {{- end}} + traefik-conf: + labels: + io.rancher.scheduler.global: 'true' + io.rancher.scheduler.affinity:host_label: ${host_label} + io.rancher.scheduler.affinity:container_label_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.start_once: 'true' + image: rawmind/rancher-traefik:1.3.3-1 + network_mode: none + volumes: + - tools-volume:/opt/tools + {{- if eq .Values.acme_enable "true"}} + traefik-acme: + network_mode: none + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10001 + - SERVICE_GID=10001 + - SERVICE_VOLUME=/opt/traefik/acme + volumes: + - ${VOLUME_NAME}:/opt/traefik/acme + image: rawmind/alpine-volume:0.0.2-1 + {{- end}} +volumes: + tools-volume: + driver: local + per_container: true + {{- if eq .Values.acme_enable "true"}} + ${VOLUME_NAME}: + driver: ${VOLUME_DRIVER} + {{- end}} diff --git a/templates/traefik/9/rancher-compose.yml b/templates/traefik/9/rancher-compose.yml new file mode 100644 index 0000000..bf7df9d --- /dev/null +++ b/templates/traefik/9/rancher-compose.yml @@ -0,0 +1,126 @@ +version: '2' +catalog: + name: traefik + version: v1.3.5-rancher1 + description: | + (Experimental) Traefik load balancer. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: traefik-0 + questions: + - variable: "host_label" + description: "Host label where to run traefik service." + label: "Host label:" + required: true + default: "traefik_lb=true" + type: "string" + - variable: "http_port" + description: "Traefik http public port to listen." + label: "Http port:" + required: true + default: 8080 + type: "int" + - variable: "https_port" + description: "Traefik https public port to listen." + label: "Https port:" + required: true + default: 8443 + type: "int" + - variable: "admin_port" + description: "Traefik admin public port to listen." + label: "Admin port:" + required: true + default: 8000 + type: "int" + - variable: "https_enable" + label: "Enable HTTPS:" + description: | + Enable https working mode. If you activate, you need to fill SSL key and SSL crt in order to work. + default: false + required: true + type: enum + options: + - false + - true + - only + - variable: "acme_enable" + description: "Enable acme support on traefik." + label: "Enable ACME:" + required: true + default: false + type: "boolean" + - variable: "acme_email" + description: "ACME user email." + label: "ACME email:" + required: true + default: "test@traefik.io" + type: "string" + - variable: "acme_ondemand" + description: "Enable acme ondemand." + label: "ACME ondemand:" + required: true + default: true + type: "boolean" + - variable: "acme_onhostrule" + description: "Enable acme onHostRule." + label: "ACME onHostRule:" + required: true + default: true + type: "boolean" + - variable: "ssl_key" + description: "SSL key to secure the service. *Required if you enable https" + label: "SSL key" + type: "multiline" + required: false + default: "" + - variable: "ssl_crt" + description: "SSL cert to secure the service. *Required if you enable https" + label: "SSL crt" + type: "multiline" + required: false + default: "" + - variable: "insecure_skip" + description: "Enable InsecureSkipVerify param." + label: "InsecureSkipVerify:" + required: true + default: false + type: "boolean" + - variable: "refresh_interval" + description: "Interval to poll/apply configuration changes." + label: "Refresh Interval (s):" + required: true + default: 10 + type: "int" + - variable: "VOLUME_NAME" + description: "The volume name shared to store ACME certs" + label: "ACME Volume Name" + required: true + default: "TRAEFIK" + type: "string" + - variable: "VOLUME_DRIVER" + description: "The volume driver shared to store ACME certs" + label: "ACME Volume Driver" + required: true + default: "rancher-nfs" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs +services: + traefik: + retain_ip: true + health_check: + port: 8000 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET /dashboard/# HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 + metadata: + traefik: + ssl_key: | + ${ssl_key} + ssl_crt: | + ${ssl_crt} diff --git a/templates/traefik/config.yml b/templates/traefik/config.yml index 8930f64..4f54076 100644 --- a/templates/traefik/config.yml +++ b/templates/traefik/config.yml @@ -1,9 +1,9 @@ name: Traefik description: | (Experimental) Traefik active load balancer -version: v1.1.2-rancher1 +version: v1.3.6-rancher1 category: Load Balancing maintainer: "Raul Sanchez " minimum_rancher_version: v0.59.0 -license: +license: projectURL: https://github.com/rawmind0/alpine-traefik diff --git a/templates/wordpress/1/docker-compose.yml b/templates/wordpress/1/docker-compose.yml new file mode 100644 index 0000000..9021b8d --- /dev/null +++ b/templates/wordpress/1/docker-compose.yml @@ -0,0 +1,32 @@ +version: '2' +services: + mariadb: + image: 'bitnami/mariadb:10.1' + volumes: + - 'mariadb_data:/bitnami' + environment: + - MARIADB_ROOT_PASSWORD=${mariadb_root_password} + - MARIADB_USER=${mariadb_user} + - MARIADB_PASSWORD=${mariadb_user_password} + - MARIADB_DATABASE=${mariadb_database_name} + wordpress: + image: 'bitnami/wordpress:4' + volumes: + - 'wordpress_data:/bitnami' + depends_on: + - mariadb + environment: + - WORDPRESS_DATABASE_NAME=${mariadb_database_name} + - WORDPRESS_DATABASE_USER=${mariadb_user} + - WORDPRESS_DATABASE_PASSWORD=${mariadb_user_password} + - WORDPRESS_USERNAME=${wordpress_username} + - WORDPRESS_PASSWORD=${wordpress_password} + wordpress-lb: + image: rancher/lb-service-haproxy:v0.7.5 + ports: + - ${public_port}:${public_port} +volumes: + mariadb_data: + driver: ${volume_driver} + wordpress_data: + driver: ${volume_driver} \ No newline at end of file diff --git a/templates/wordpress/1/rancher-compose.yml b/templates/wordpress/1/rancher-compose.yml new file mode 100644 index 0000000..a23a105 --- /dev/null +++ b/templates/wordpress/1/rancher-compose.yml @@ -0,0 +1,86 @@ +version: '2' +catalog: + name: "Wordpress" + version: "v0.2-bitnami" + description: "Blog tool, publishing platform and CMS based on bitnami images" + uuid: Wordpress-1 + minimum_rancher_version: v0.51.0 + questions: + - variable: public_port + description: "public port to access the wordpress site" + label: "Public Port" + required: true + default: "80" + type: "int" + - variable: mariadb_root_password + description: "MariaDB root password, set on first run" + label: "MariaDB Root Password" + required: true + default: "mariadb_my_root" + type: "string" + - variable: mariadb_user + description: "MariaDB database user, created on first run" + label: "MariaDB Database User" + required: true + default: "wordpress_user" + type: "string" + - variable: mariadb_user_password + description: "MariaDB database user password, set on first run" + label: "MariaDB Database User Password" + required: true + default: "wordpress_password" + type: "string" + - variable: mariadb_database_name + description: "Wordpress database name" + label: "Wordpress database name" + required: true + default: "bitnami_wordpress" + type: "string" + - variable: wordpress_username + description: "WordPress application username" + label: "WordPress application username" + required: true + default: "admin" + type: "string" + - variable: wordpress_password + description: "WordPress application password" + label: "WordPress application password" + required: true + default: "bitnami" + type: "string" + - variable: volume_driver + description: "Volume driver to use with this service" + label: "Volume driver" + required: true + default: "local" + type: enum + options: + - local + - rancher-nfs + - rancher-efs + - rancher-ebs +services: + wordpress-lb: + scale: 1 + lb_config: + certs: [] + port_rules: + - protocol: http + service: wordpress + source_port: ${public_port} + target_port: 80 + health_check: + response_timeout: 2000 + healthy_threshold: 2 + port: 42 + unhealthy_threshold: 3 + wordpress: + scale: 1 + retain_ip: true + health_check: + port: 80 + interval: 5000 + unhealthy_threshold: 3 + request_line: 'GET / HTTP/1.0' + healthy_threshold: 2 + response_timeout: 5000 \ No newline at end of file diff --git a/templates/wordpress/README.md b/templates/wordpress/README.md new file mode 100644 index 0000000..4de1c01 --- /dev/null +++ b/templates/wordpress/README.md @@ -0,0 +1,12 @@ +## What is inside WordPress Stack? +* MariaDB Database +* WordPress (php/apache) +* Rancher Load Balancer (haproxy) + +## Info +* To persist website and database data, two volumes are created: mariadb_data, wordpress_data. +* You can choose from one of existing rancher volume types depending on your own environment. + +## Compatibility Notes + +* Version v0.2-bitnami has some known [issue](https://github.com/bitnami/bitnami-docker-testlink/issues/17#issuecomment-261783035) with Docker overlay and overlay2 storage driver. Please try to switch to aufs or devicemapper. diff --git a/templates/wordpress/config.yml b/templates/wordpress/config.yml index 5f43d8b..eb08385 100644 --- a/templates/wordpress/config.yml +++ b/templates/wordpress/config.yml @@ -1,5 +1,5 @@ name: Wordpress description: | Blog tool, publishing platform and CMS -version: v0.1-educaas1 +version: v0.2-bitnami category: Blogging diff --git a/templates/zammad/0/docker-compose.yml b/templates/zammad/0/docker-compose.yml index 4e03fd9..92f7356 100644 --- a/templates/zammad/0/docker-compose.yml +++ b/templates/zammad/0/docker-compose.yml @@ -3,7 +3,7 @@ version: '2' services: elasticsearch: - image: zammad/zammad-docker-compose:elasticsearch + image: zammad/zammad-docker-compose:zammad-elasticsearch labels: io.rancher.container.pull_image: always restart: always @@ -11,7 +11,7 @@ services: nginx: depends_on: - zammad - image: zammad/zammad-docker-compose:nginx + image: zammad/zammad-docker-compose:zammad-nginx labels: io.rancher.container.pull_image: always links: @@ -24,7 +24,7 @@ services: - data-zammad:/home/zammad postgresql: - image: zammad/zammad-docker-compose:postgresql + image: zammad/zammad-docker-compose:zammad-postgresql labels: io.rancher.container.pull_image: always restart: always diff --git a/templates/zammad/0/rancher-compose.yml b/templates/zammad/0/rancher-compose.yml index 01a021c..8ff8ee5 100644 --- a/templates/zammad/0/rancher-compose.yml +++ b/templates/zammad/0/rancher-compose.yml @@ -23,7 +23,7 @@ zammad-scheduler: start_on_create: true zammad-railsserver: scale: 1 - tart_on_create: true + start_on_create: true zammad-websocket: scale: 1 start_on_create: true diff --git a/templates/zammad/README.md b/templates/zammad/README.md index 8da00a2..6b2cf52 100644 --- a/templates/zammad/README.md +++ b/templates/zammad/README.md @@ -41,7 +41,7 @@ https://docs.zammad.org/en/latest/api-intro.html https://zammad.org/participate -Thanks! ❤️ ❤️ ❤️ +Thanks! Your Zammad Team diff --git a/templates/zookeeper/2/docker-compose.yml b/templates/zookeeper/2/docker-compose.yml index 67c4da6..795cb29 100644 --- a/templates/zookeeper/2/docker-compose.yml +++ b/templates/zookeeper/2/docker-compose.yml @@ -1,6 +1,6 @@ zk: tty: true - image: rawmind/alpine-zk:3.4.9 + image: rawmind/alpine-zk:3.4.9-3 volumes_from: - zk-volume - zk-conf @@ -21,7 +21,7 @@ zk-conf: io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} io.rancher.container.hostname_override: container_name io.rancher.container.start_once: true - image: rawmind/rancher-zk:3.4.8-5 + image: rawmind/rancher-zk:3.4.9 volumes: - /opt/tools zk-volume: diff --git a/templates/zookeeper/3/README.md b/templates/zookeeper/3/README.md new file mode 100644 index 0000000..ee2b770 --- /dev/null +++ b/templates/zookeeper/3/README.md @@ -0,0 +1,27 @@ +# Apache Zookeeper (Experimental) + +### Info: + + This template creates, scale in and scale out a multinodes zk (zookeeper) cluster on top of Rancher. The configuration is generated with confd from Rancher metadata. + Cluster size are variable after deployment, and get reconfigured if refresh interval > 0. + + +### Usage: + + Select Apache Zookeeper from catalog. + + Enter the number of nodes, mem and refresh interval for the zk cluster. (set refresh data to 0 to disable dinamic config) + + Change the following zookeeper default parameters, if you need: + +- ZK_DATA_DIR="/opt/zk/data" +- ZK_INIT_LIMIT="10" +- ZK_MAX_CLIENT_CXNS="500" +- ZK_SYNC_LIMIT="5" +- ZK_TICK_TIME="2000" + + Click deploy. + + Zookeeper can now be accessed over the Rancher network. + + Note: When you scale the cluster, zero downtime is expected... diff --git a/templates/zookeeper/3/docker-compose.yml.tpl b/templates/zookeeper/3/docker-compose.yml.tpl new file mode 100644 index 0000000..a6c73dc --- /dev/null +++ b/templates/zookeeper/3/docker-compose.yml.tpl @@ -0,0 +1,55 @@ +version: '2' +services: + zk: + tty: true + image: rawmind/alpine-zk:3.4.9-3 + volumes_from: + - zk-volume + - zk-conf + environment: + - JVMFLAGS=-Xmx${zk_mem}m -Xms${zk_mem}m + - ZK_DATA_DIR=${zk_data_dir} + - ZK_INIT_LIMIT=${zk_init_limit} + - ZK_MAX_CLIENT_CXNS=${zk_max_client_cxns} + - ZK_SYNC_LIMIT=${zk_sync_limit} + - ZK_TICK_TIME=${zk_tick_time} + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.sidekicks: zk-volume, zk-conf + zk-conf: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + image: rawmind/rancher-zk:3.4.9 + volumes: + - zkconfig:/opt/tools + zk-volume: + labels: + io.rancher.scheduler.affinity:container_label_soft_ne: io.rancher.stack_service.name=$${stack_name}/$${service_name} + io.rancher.container.hostname_override: container_name +{{- if ne .Values.host_label ""}} + io.rancher.scheduler.affinity:host_label: ${host_label} +{{- end}} + io.rancher.container.start_once: true + environment: + - SERVICE_UID=10002 + - SERVICE_GID=10002 + - SERVICE_VOLUME=${zk_data_dir} + volumes: + - zkdata:${zk_data_dir} + image: rawmind/alpine-volume:0.0.2-1 +volumes: + zkconfig: + driver: ${VOLUME_DRIVER} + per_container: true + zkdata: + driver: ${VOLUME_DRIVER} + per_container: true diff --git a/templates/zookeeper/3/rancher-compose.yml b/templates/zookeeper/3/rancher-compose.yml new file mode 100644 index 0000000..15751d9 --- /dev/null +++ b/templates/zookeeper/3/rancher-compose.yml @@ -0,0 +1,88 @@ +version: '2' +catalog: + name: Zookeeper + version: 3.4.9-rancher2 + description: | + (Experimental) Apache Zookeeper cluster. + minimum_rancher_version: v0.59.0 + maintainer: "Raul Sanchez " + uuid: zk-0 + questions: + - variable: "zk_scale" + description: "Number of zk nodes. Note: Recommended an odd number" + label: "Zk Nodes:" + required: true + default: 3 + type: "int" + - variable: "zk_mem" + description: "Amount of memory to config zk." + label: "Zk Memory (mb):" + required: true + default: 512 + type: "int" + - variable: "zk_init_limit" + description: "Time to allow followers to connect and sync with leader" + label: "Zk init limit (ticks):" + required: true + default: 10 + type: "int" + - variable: "zk_data_dir" + description: "Directory where zookeeper store data" + label: "Zk data dir:" + required: true + default: "/opt/zk/data" + type: "string" + - variable: "zk_max_client_cxns" + description: "Max client concurrent connections" + label: "Zk max client cxns:" + required: true + default: 500 + type: "int" + - variable: "zk_sync_limit" + description: "Time to allow followers to sync with leader" + label: "Zk sync limit (ticks):" + required: true + default: 5 + type: "int" + - variable: "zk_tick_time" + description: "Tick time length" + label: "Zk tick time (ms):" + required: true + default: 2000 + type: "int" + - variable: "zk_interval" + description: "Interval to poll/apply configuration changes. 0 to disable, reconfiguration will be done when you restart zk nodes" + label: "Zk Interval (s):" + required: true + default: 60 + type: "int" + - variable: host_label + label: "Host with Label to put zookeeper on" + description: | + Host label to use as zookeeper 'value' tag. + Example: 'zookeeper=true' + required: false + default: "" + type: "string" + - variable: "VOLUME_DRIVER" + description: "The VOLUME driver to associate with this server" + label: "VOLUME Driver" + required: true + default: "local" + type: enum + options: # List of options if using type of `enum` + - local + - rancher-nfs + - rancher-efs + - rancher-ebs +services: + zk: + scale: ${zk_scale} + retain_ip: true + health_check: + port: 2181 + interval: 5000 + unhealthy_threshold: 3 + request_line: '' + healthy_threshold: 2 + response_timeout: 5000 diff --git a/templates/zookeeper/config.yml b/templates/zookeeper/config.yml index 84ea903..d6b7d77 100644 --- a/templates/zookeeper/config.yml +++ b/templates/zookeeper/config.yml @@ -1,7 +1,7 @@ name: Apache Zookeeper description: | (Experimental) Zookeeper cluster -version: 3.4.9-rancher1 +version: 3.4.9-rancher2 category: Clustering maintainer: "Raul Sanchez " projectURL: https://github.com/rawmind0/alpine-zk