Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[ui] example job with actions #19153

Merged
merged 4 commits into from
Dec 4, 2023
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions ui/app/utils/default-job-templates.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import helloWorld from './default_jobs/hello-world';
import parameterized from './default_jobs/parameterized';
import serviceDiscovery from './default_jobs/service-discovery';
import variables from './default_jobs/variables';
import actions from './default_jobs/actions';

export default [
{
Expand All @@ -22,6 +23,20 @@ export default [
},
],
},
{
id: 'nomad/job-templates/default/actions',
keyValues: [
{
key: 'template',
value: actions,
},
{
key: 'description',
value:
'Nomad Actions let job authors describe commands that can be run in one click from the UI or one command from the CLI. This example job shows how to use them to simulate development on a Redis instance.',
},
],
},
{
id: 'nomad/job-templates/default/parameterized-job',
keyValues: [
Expand Down
131 changes: 131 additions & 0 deletions ui/app/utils/default_jobs/actions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
/**
* Copyright (c) HashiCorp, Inc.
* SPDX-License-Identifier: BUSL-1.1
*/

export default `job "redis-actions" {
datacenters = ["*"]

group "cache" {
count = 1
philrenaud marked this conversation as resolved.
Show resolved Hide resolved
network {
port "db" {}
}

task "redis" {
driver = "docker"

config {
image = "redis:3.2"
ports = ["db"]
command = "/bin/sh"
args = ["-c", "redis-server --port \${NOMAD_PORT_db} & /local/db_log.sh"]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like above, we can probably use port mapping to keep this a bit cleaner and avoid the extra args, but if you want to use dynamic ports something like this would be a bit easier to understand?

job "example" {
  group "cache" {
    network {
      port "db" {}
    }

    task "redis" {
      driver = "docker"

      config {
        image   = "redis:7"
        ports   = ["db"]
        args    = ["/etc/redis/redis.conf"]
        volumes = ["local/conf:/etc/redis"]
      }

      template {
        data        = <<EOF
port {{env "NOMAD_PORT_db"}}
EOF
        destination = "local/conf/redis.conf"
      }
    }
  }
}

Then the redis-cli -p \${NOMAD_PORT_db} DBSIZE command in db_log.sh could be another action?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realize it's not practical or desired for a real-world redis server on Nomad, but it seemed cool to illustrate db size output live when you make edits via action.

In the (pending) actions tutorial (PR), I hoped this would be something easily demonstrable to a user.

}

resources {
cpu = 500
memory = 256
}
philrenaud marked this conversation as resolved.
Show resolved Hide resolved

service {
name = "redis-service"
port = "db"
provider = "nomad"
philrenaud marked this conversation as resolved.
Show resolved Hide resolved

check {
name = "alive"
type = "tcp"
port = "db"
interval = "10s"
timeout = "2s"
}
}

template {
data = <<EOF
#!/bin/sh
while true; do
echo "$(date): Current DB Size: $(redis-cli -p \${NOMAD_PORT_db} DBSIZE)"
sleep 3
done
EOF
destination = "local/db_log.sh"
perms = "0755"
}

# Adds a random key/value to the Redis database
action "add-random-key" {
command = "/bin/sh"
args = ["-c", "key=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13); value=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13); redis-cli -p \${NOMAD_PORT_db} SET $key $value; echo Key $key added with value $value"]
}

# Adds a random key/value with a "temp_" prefix to the Redis database
action "add-random-temporary-key" {
command = "/bin/sh"
args = ["-c", "key=temp_$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13); value=$(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 13); redis-cli -p \${NOMAD_PORT_db} SET $key $value; echo Key $key added with value $value"]
}

# Lists all keys currently stored in the Redis database.
action "list-keys" {
command = "/bin/sh"
args = ["-c", "redis-cli -p \${NOMAD_PORT_db} KEYS '*'"]
}

# Retrieves various stats about the Redis server
action "get-redis-stats" {
command = "/bin/sh"
args = ["-c", "redis-cli -p \${NOMAD_PORT_db} INFO"]
}

# Performs a latency check of the Redis server.
# This action is a non-terminating action, meaning it will run indefinitely until it is stopped.
# Pass an escape sequence (Ctrl-C) to stop the action.
action "health-check" {
command = "/bin/sh"
args = ["-c", "redis-cli -p \${NOMAD_PORT_db} --latency"]
}

# Deletes all keys with a 'temp_' prefix
action "flush-temp-keys" {
command = "/bin/sh"
args = ["-c", <<EOF
keys_to_delete=$(redis-cli -p \${NOMAD_PORT_db} --scan --pattern 'temp_*')
if [ -n "$keys_to_delete" ]; then
# Count the number of keys to delete
deleted_count=$(echo "$keys_to_delete" | wc -l)
# Execute the delete command
echo "$keys_to_delete" | xargs redis-cli -p \${NOMAD_PORT_db} DEL
else
deleted_count=0
fi
remaining_keys=$(redis-cli -p \${NOMAD_PORT_db} DBSIZE)
echo "$deleted_count temporary keys removed; $remaining_keys keys remaining in database"
EOF
]
}


# Toggles saving to disk (RDB persistence). When enabled, allocation logs will indicate a save every 60 seconds.
action "toggle-save-to-disk" {
command = "/bin/sh"
args = ["-c", <<EOF
current_config=$(redis-cli -p \${NOMAD_PORT_db} CONFIG GET save | awk 'NR==2');
if [ -z "$current_config" ]; then
# Enable saving to disk (example: save after 60 seconds if at least 1 key changed)
redis-cli -p \${NOMAD_PORT_db} CONFIG SET save "60 1";
echo "Saving to disk enabled: 60 seconds interval if at least 1 key changed";
else
# Disable saving to disk
redis-cli -p \${NOMAD_PORT_db} CONFIG SET save "";
echo "Saving to disk disabled";
fi;
EOF
]
}


}
}

}
philrenaud marked this conversation as resolved.
Show resolved Hide resolved
`;
18 changes: 14 additions & 4 deletions ui/tests/acceptance/job-run-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ const newJobName = 'new-job';
const newJobTaskGroupName = 'redis';
const newJobNamespace = 'default';

const NUMBER_OF_DEFAULT_TEMPLATES = 5;

let managementToken, clientToken;

const jsonJob = (overrides) => {
Expand Down Expand Up @@ -245,7 +247,10 @@ module('Acceptance | job run', function (hooks) {
// Assert
assert
.dom('[data-test-template-card]')
.exists({ count: 4 }, 'A list of default job templates is rendered.');
.exists(
{ count: NUMBER_OF_DEFAULT_TEMPLATES },
'A list of default job templates is rendered.'
);

await click('[data-test-create-new-button]');
assert.equal(currentRouteName(), 'jobs.run.templates.new');
Expand Down Expand Up @@ -331,7 +336,10 @@ module('Acceptance | job run', function (hooks) {
// Assert
assert
.dom('[data-test-template-card]')
.exists({ count: 4 }, 'A list of default job templates is rendered.');
.exists(
{ count: NUMBER_OF_DEFAULT_TEMPLATES },
'A list of default job templates is rendered.'
);

await click('[data-test-create-new-button]');
assert.equal(currentRouteName(), 'jobs.run.templates.new');
Expand Down Expand Up @@ -380,7 +388,10 @@ module('Acceptance | job run', function (hooks) {
// Assert
assert
.dom('[data-test-template-card]')
.exists({ count: 4 }, 'A list of default job templates is rendered.');
.exists(
{ count: NUMBER_OF_DEFAULT_TEMPLATES },
'A list of default job templates is rendered.'
);

await click('[data-test-create-new-button]');
assert.equal(currentRouteName(), 'jobs.run.templates.new');
Expand Down Expand Up @@ -576,7 +587,6 @@ module('Acceptance | job run', function (hooks) {

test('default templates', async function (assert) {
assert.expect(4);
const NUMBER_OF_DEFAULT_TEMPLATES = 4;

await visit('/jobs/run/templates');

Expand Down
Loading