Skip to content

Commit

Permalink
Merge branch 'main' into patch-3
Browse files Browse the repository at this point in the history
  • Loading branch information
chadwcarlson authored Dec 9, 2024
2 parents 7d76805 + eb8656b commit e5f560c
Show file tree
Hide file tree
Showing 231 changed files with 12,727 additions and 9,410 deletions.
4 changes: 4 additions & 0 deletions .github/actions/redirection-verification/action.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ inputs:
environment-url:
description: 'Pull Request Environment URL'
required: true
number_retries:
description: 'The number of attempts we should make to contact the target environment URL. 1 second delay between attempt.'
required: false
default: '100'

####
#outputs:
Expand Down
130 changes: 82 additions & 48 deletions .github/actions/redirection-verification/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,55 +35,89 @@ function linkify(path,url) {
* @type {string}
*/
axios.defaults.baseURL = core.getInput('environment-url')
//axios.defaults.baseURL = 'https://httpstat.us/random/200,500-504,500-504,500-504'
const retries = Number(core.getInput('number_retries'))
//const retries = Number('100')
function sleep(ms) {
return new Promise((resolve) => {
setTimeout(resolve, ms);
});
}

try {
/**
* @todo Can we get the full workspace path to this file?
* @type {*}
*/
const yamlData = yaml.load(fs.readFileSync('./.platform/routes.yaml', 'utf8'));
/**
* @todo the key (docs.upsun.com) here should be a variable that is set somewhere else
* @type {Record<string, string[]> | _.LodashAt | ((request: string) => (string[] | null)) | string[]}
*/
const anchors = yamlData['https://docs.upsun.com/'].redirects.paths

const RedirectKeys = Object.keys(anchors).filter((path)=>{
const verifyTargetResponse = async(count = 0) => {
try {
const axiosResponse = await axios.get('/');
core.notice('Target URL finally responded with a 200. Proceeding.')
return axiosResponse;
} catch (error) {
if (error || error.status != 200) {
core.info(`At attempt ${count}, target url responded with status ${error.status}, retrying...`)
if (count++ < retries) {
await sleep(1000);
return verifyTargetResponse(count);
} else {
core.setFailed(`Max number of retries (${retries}) reached. Aborting.`)
};
} else {
core.setFailed(`Action failed with error ${error}`)
};
};
};

const verify = async () => {
let targetReady = await verifyTargetResponse();
core.info('Target URL ready. Beginning verification.')
try {
/**
* @todo the piece we're using to identify our contracts (/anchors/) should be a variable
* @todo Can we get the full workspace path to this file?
* @type {*}
*/
return path.startsWith('/anchors/')
})

const validateRedirects = RedirectKeys.map(async (path, index, array) => {
//console.log(`I'm going to test ${path} to see if it goes to ${anchors[path].to}`)

try {
const response = await axios.head(path);
//core.info(`Response for our check of ${path} is ${response.status}`)
return response
} catch (reqerr) {
//core.warning(`issue encountered with path ${path}!!! Returned status is ${reqerr.status}`)
let row = [{data: linkify(path, axios.defaults.baseURL)},{data: linkify( anchors[path].to, axios.defaults.baseURL) }]
tableData.push(row)
}
});


Promise.all(validateRedirects).then(() => {
if(tableData.length > 1) {

core.error('There was an error with one or more redirects.')

core.summary.addTable(tableData)

core.summary.write()
core.setFailed('There was an error with one or more contracted redirects.')
} else {
core.notice('All contracted redirections are valid.')
}
});

} catch (error) {
core.setFailed(`Action failed with error ${error}`)
const yamlData = yaml.load(fs.readFileSync('./.platform/routes.yaml', 'utf8'));
/**
* @todo the key (docs.upsun.com) here should be a variable that is set somewhere else
* @type {Record<string, string[]> | _.LodashAt | ((request: string) => (string[] | null)) | string[]}
*/
const anchors = yamlData['https://docs.upsun.com/'].redirects.paths

const RedirectKeys = Object.keys(anchors).filter((path)=>{
/**
* @todo the piece we're using to identify our contracts (/anchors/) should be a variable
*/
return path.startsWith('/anchors/')
})

const validateRedirects = RedirectKeys.map(async (path, index, array) => {
//console.log(`I'm going to test ${path} to see if it goes to ${anchors[path].to}`)

try {
const response = await axios.head(path);
core.debug(`Response for our check of ${path} is ${response.status}`)
return response
} catch (reqerr) {
//core.warning(`issue encountered with path ${path}!!! Returned status is ${reqerr.status}`)
let row = [{data: linkify(path, axios.defaults.baseURL)},{data: linkify( anchors[path].to, axios.defaults.baseURL) }]
tableData.push(row)
}
});


Promise.all(validateRedirects).then(() => {
if(tableData.length > 1) {

core.error('There was an error with one or more redirects.')

core.summary.addTable(tableData)

core.summary.write()
core.setFailed('There was an error with one or more contracted redirects.')
} else {
core.notice('All contracted redirections are valid.')
}
});

} catch (error) {
core.setFailed(`Action failed with error ${error}`)
}
}

verify();
146 changes: 108 additions & 38 deletions sites/platform/src/add-services/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,25 +30,25 @@ Configure your service in the following pattern:
```yaml {configFile="services"}
# The name of the service container. Must be unique within a project.
SERVICE_NAME:
type: {{<variable "SERVICE_TYPE" >}}:{{<variable "VERSION" >}}
# Other options...
type: <SERVICE_TYPE>:<VERSION>
# Other options...
```

An example service configuration for two databases might look like this:

```yaml {configFile="services"}
# The name of the service container. Must be unique within a project.
mariadb:
type: mariadb:{{% latest "mariadb" %}}
disk: 2048
type: mariadb:{{% latest "mariadb" %}}
disk: 2048
# The name of the service container. Must be unique within a project.
postgresql:
type: postgresql:{{% latest "postgresql" %}}
disk: 1024
type: postgresql:{{% latest "postgresql" %}}
disk: 1024
```
This YAML file is a dictionary defining all of the services you want to use.
The top-level key is a custom service name ({{<variable "SERVICE_NAME" >}}; in the example, `mariadb` and `postgresql`), which you use to identify the service in step 2.
The top-level key is a custom service name (``<SERVICE_NAME>``: in the example, `mariadb` and `postgresql`), which you use to identify the service in step 2.

You can give it any name you want with lowercase alphanumeric characters, hyphens, and underscores.

Expand Down Expand Up @@ -101,17 +101,25 @@ This is done in your [app configuration for relationships](/create-apps/app-refe

The relationship follows this pattern:

{{< codetabs >}}

+++
title=Using default endpoints
+++

```yaml {configFile="app"}
name: myapp
# Other options...
# Relationships enable an app container's access to a service.
# The example below shows simplified configuration leveraging a default service (identified from the relationship name) and a default endpoint.
# See the Application reference for all options for defining relationships and endpoints.
relationships:
{{<variable "SERVICE_NAME" >}}:
<SERVICE_NAME>:
```

You can define `<SERVICE_NAME>` as you like, so long as it's unique between all defined services
You can define `<SERVICE_NAME>` as you like, so long as it's unique between all defined services
and matches in both the application and services configuration.

The example above leverages [default endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships.
Expand All @@ -121,24 +129,87 @@ That is, it uses default endpoints behind-the-scenes, providing a [relationship]
Depending on your needs, instead of default endpoint configuration,
you can use [explicit endpoint configuration](/create-apps/app-reference/single-runtime-image#relationships).

<--->

+++
title=Using explicit endpoints
+++

```yaml {configFile="app"}
# Relationships enable access from this app to a given service.
# The example below shows configuration with an explicitly set service name and endpoint.
# See the Application reference for all options for defining relationships and endpoints.
# Note that legacy definition of the relationship is still supported.
# More information: https://docs.platform.sh/create-apps/app-reference/single-runtime-image.html#relationships
relationships:
<RELATIONSHIP_NAME>:
service: <SERVICE_NAME>
endpoint: <ENDPOINT_NAME>
```

You can define ``<SERVICE_NAME>`` and ``<RELATIONSHIP_NAME>`` as you like, so long as it's unique between all defined services and relationships
and matches in both the application and services configuration. `<ENDPOINT_NAME>` is the endpoint your app will use to connect to the service (refer to the service reference to know which value to use).

The example above leverages [explicit endpoint](/create-apps/app-reference/single-runtime-image#relationships) configuration for relationships.

Depending on your needs, instead of explicit endpoint configuration,
you can use [default endpoint configuration](/create-apps/app-reference/single-runtime-image#relationships).

With the above definition, the application container now has access to the service via the relationship `<RELATIONSHIP_NAME>` and its corresponding [`PLATFORM_RELATIONSHIPS` environment variable](/development/variables/use-variables.md#use-provided-variables).

{{< /codetabs >}}

An example relationship to connect to the databases given in the [example in step 1](#1-configure-the-service):

{{< codetabs >}}

+++
title=Using default endpoints
+++

```yaml {configFile="app"}
name: myapp
# Other options...
# Relationships enable an app container's access to a service.
relationships:
mariadb:
postgresql:
mariadb:
postgresql:
```

<--->

+++
title=Using explicit endpoints
+++

```yaml {configFile="app"}
name: myapp
# Other options...
# Relationships enable access from this app to a given service.
# The example below shows configuration with explicitly set service names and endpoints.
# See the Application reference for all options for defining relationships and endpoints.
# Note that legacy definition of the relationship is still supported.
# More information: https://docs.platform.sh/create-apps/app-reference/single-runtime-image.html#relationships
relationships:
mariadb:
service: mariadb
endpoint: mysql
postgresql:
service: postgresql
endpoint: mysql
```

{{< /codetabs >}}

```yaml {configFile="services"}
mariadb:
type: mariadb:{{% latest "mariadb" %}}
disk: 2048
type: mariadb:{{% latest "mariadb" %}}
disk: 2048
postgresql:
type: postgresql:{{% latest "postgresql" %}}
disk: 1024
type: postgresql:{{% latest "postgresql" %}}
disk: 1024
```

As with the service name, you can give the relationship any name you want
Expand Down Expand Up @@ -200,7 +271,6 @@ Connecting to a service using an SSH tunnel is a two-step process.

### 1. Obtain service credentials


To get the credentials for a given service, run the following command:

```bash
Expand All @@ -211,25 +281,25 @@ You get output like the following:

```yaml
mariadb:
-
username: user
scheme: mysql
service: mariadb
fragment: null
ip: 198.51.100.37
hostname: abcdefghijklm1234567890123.mariadb.service._.eu.{{< vendor/urlraw "hostname" >}}
public: false
cluster: abcdefgh1234567-main-abcd123
host: mariadb.internal
rel: mysql
query:
is_master: true
path: main
password: ''
type: 'mariadb:10.6'
port: 3306
host_mapped: false
url: 'mysql://user:@mariadb.internal:3306/main'
-
username: user
scheme: mysql
service: mariadb
fragment: null
ip: 198.51.100.37
hostname: abcdefghijklm1234567890123.mariadb.service._.eu.{{< vendor/urlraw "hostname" >}}
public: false
cluster: abcdefgh1234567-main-abcd123
host: mariadb.internal
rel: mysql
query:
is_master: true
path: main
password: ''
type: 'mariadb:10.6'
port: 3306
host_mapped: false
url: 'mysql://user:@mariadb.internal:3306/main'
```

With this example, you can connect to the `mariadb` relationship
Expand Down Expand Up @@ -257,10 +327,10 @@ With the example above, you connect to a URL like the following:

## Upgrading services

{{% vendor/name %}} provides a large number of [managed service versions](#available-services).
{{% vendor/name %}} provides a large number of [managed service versions](#available-services).
As new versions are made available, you will inevitably upgrade infrastructure to a more recent (or latest version).

When you do so, we would recommend:

1. **Use preview environments**. Leverage preview (non-production environments) to perform the upgrade, then merge the upgrade into production (promotion). This will give you an opportunity to test inherited production data in a safe, isolated environment first.
1. **Upgrade progressively**. For one reason or another, you may be more than a single version behind the upgrade you are trying to perform. To avoid data loss issues caused by large differences in versions, [upgrade one version at a time](https://www.rabbitmq.com/upgrade.html#rabbitmq-version-upgradability).
1. **Use preview environments**. Leverage preview (non-production environments) to perform the upgrade, then merge the upgrade into production (promotion). This will give you an opportunity to test inherited production data in a safe, isolated environment first.
1. **Upgrade progressively**. For one reason or another, you may be more than a single version behind the upgrade you are trying to perform. To avoid data loss issues caused by large differences in versions, [upgrade one version at a time](https://www.rabbitmq.com/upgrade.html#rabbitmq-version-upgradability).
Loading

0 comments on commit e5f560c

Please sign in to comment.