Job management using OCI Instance Run command

This site is based on machine translation. The original is https://qiita.com/tktk2712/items/f18e4370d6a1586ac940 (Japanese)

# Overview
Run command function issue commands to Oracle Cloud Infrastructure (OCI) instances.
[Running Commands on an Instance](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/runningcommands.htm)
This time, run command run a script on Windows and Linux instances.

# What’s benefit?
Run command allows you to run commands and jobs without loging in  to the instance. By combining a job management tool and Run command instead of a task scheduler or Cron, you can manage jobs , so you can expect to improve operational quality, 
for example:
- Run jobs without logging in by an operator
- unified management in combination with job management tools
- Change and distribution to multiple instances

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/d3084f3d-36ba-e410-06b2-138fece93ac0.png">

# Composition
Scripts and outputs are forwarded via Object storage.

<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/5ecd915d-7542-52f1-230f-78b11fa94b3f.png">

(1) Create a command from the job management tool created in OCI
(2) The cloud agent of the target instance in OCI receives the command
(3) The agent downloads the script stored in Object storage
(4) Execute the script on the agent
(5) The agent uploads script execution results (Output) to Object Storage
(6) If necessary, download and check the output from the job management tool, etc.

# Creation
## Obtain data
Obtain the following information
- Compartment OCID
Enter the compartment name in the search window of the OCI console, the compartment will be displayed and click on it.
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/03a79a09-6192-0a64-bbed-8caa06597e05.png">

The compartment contents will be displayed, then copy the OCID
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/b534eeb4-ccb4-a653-ef48-e32d916a4813.png">

- Object Storage namespace and bucket name
Select the target bucket from Storage >> Bucket Name from the OCI navigation menu, note the namespace, and copy the bucket OCID.

<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/be04393e-7243-d8db-8539-631447fa0b2d.png">

- instance OCID
Obtain information about the instance that run command.
Select the target instance from Compute >> Instances from the OCI navigation menu and copy the OCID
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/95dff0ef-da3c-753f-c96e-42808174444d.png">

## Instance-side Run command environment preparation
- From the OCI navigation menu, select the target instance from Compute >> Instances, select the Oracle Cloud Agent tab and confirm that the Compute Instance Run Command plugin is running
<img width="500" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/59384f95-a61d-7a2a-f5fd-a9d01dbc9edb.png">

- When runn command with Administrator Privileges, execute the following step.
[Running Commands with Administrator Privileges](https://docs.oracle.com/ja-jp/iaas/Content/Compute/Tasks/runningcommands.htm#administrator-privileges)
    -Grant administrator privileges to user OCARUN
    -Recommend restart the instance after granting

## Script preparation
Prepare the script to be executed on the instance.
The script we will execute this time is to start nginx and confirm its startup.
<font color="Red">Create line breaks in the script using CR+LF on Windows and LF on Linux.</font>

- Script creation
Windows
```source_nginxstart_win.txt
echo %date%
echo %time%

cd c:\nginx-1.24.0
start nginx

ping 127.0.0.1
curl -s -o nul -w "%%{http_code}" http://127.0.0.1
exit /b
```

Linux
```source_nginxstart_linux.txt
date

sudo systemctl start nginx

ping -c 4 127.0.0.1
curl -s -o /dev/nul -w "%{http_code}" http://127.0.0.1
exit 0
```


- Upload to Object Storage
From the OCI navigation menu, select the target bucket from Storage >> Bucket name and upload.
<img width="600" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/9b423ece-08cb-d6f0-3805-651f03e69dca.png">

## OCI policy
Add a policy to enable Run command execution from Job management tools, etc.

- Create dynamic groups containing instances of Job management tools, etc.
[Managing Dynamic Groups](https://docs.oracle.com/en-us/iaas/Content/Identity/Tasks/managingdynamicgroups.htm#three)

- Grant Object Storage read/write permissions to dynamic groups
[Creating a Policy](https://docs.oracle.com/en-us/iaas/Content/Identity/policymgmt/managingpolicies_topic-To_create_a_policy.htm)
```
Allow dynamic-group "dynamic groups" to manage objects in compartment "compartment name"
```
- Grant Run command execution permission to dynamic group
[Create policy](https://docs.oracle.com/en-us/iaas/Content/Identity/policymgmt/managingpolicies_topic-To_create_a_policy.htm)
```
Allow dynamic-group "dynamic groups" to use instance-agent-command-execution-family in compartment "compartment name"
```

Ref:[Run command policy creation](https://docs.oracle.com/en-us/iaas/Content/Compute/Tasks/instances.htm#permissions)

## Preparation of job management tools, etc.
Create JSON that specifies the Script location, Output location, and instance.
Windows
```runcommand_nginxstart_win.json
{
 "compartmentId": "ocid1.compartment.oc1..*****",
 "content": {
  "output":
    {
      "bucketName": "bucket name",
      "namespaceName": "namespace",
      "objectName": "runcommand/output_nginxstart_win.log",
      "outputType": "OBJECT_STORAGE_TUPLE"
    },
  "source":
    {
      "bucketName": "bucket name",
      "namespaceName": "namespace",
      "objectName": "runcommand/source_nginxstart_win.txt",
      "sourceType": "OBJECT_STORAGE_TUPLE"
    },
 },
 "displayName": "nginxstart_win",
 "target": {
  "instanceId": "ocid1.instance.oc1.ap-tokyo-1.*****"
 },
 "timeoutInSeconds": "300"
}
```

Linux
```runcommand_nginxstart_linux.json
{
 "compartmentId": "ocid1.compartment.oc1..*****",
 "content": {
  "output":
    {
      "bucketName": "bucket name",
      "namespaceName": "namespace",
      "objectName": "runcommand/output_nginxstart_linux.log",
      "outputType": "OBJECT_STORAGE_TUPLE"
    },
  "source":
    {
      "bucketName": "bucket name",
      "namespaceName": "namespace",
      "objectName": "runcommand/source_nginxstart_linux.txt",
      "sourceType": "OBJECT_STORAGE_TUPLE"
    },
 },
 "displayName": "nginxstart_linux",
 "target": {
  "instanceId": "ocid1.instance.oc1.ap-tokyo-1.*****"
 },
 "timeoutInSeconds": "300"
}
```

<details><summary>Ref:JSON file</summary><div>
The JSON template can be obtained using the following command.

```
[user@linux]$ oci instance-agent command create --generate-full-command-json-input
{
  "compartmentId": "string",
  "content": {
    "output": [
      "This parameter should actually be a JSON object rather than an array - pick one of the following object variants to use",
      {
        "bucketName": "string",
        "namespaceName": "string",
        "objectName": "string",
        "outputType": "OBJECT_STORAGE_TUPLE"
      },
      {
        "outputType": "OBJECT_STORAGE_URI",
        "outputUri": "string"
      },
      {
        "outputType": "TEXT"
      }
    ],
    "source": [
      "This parameter should actually be a JSON object rather than an array - pick one of the following object variants to use",
      {
        "bucketName": "string",
        "namespaceName": "string",
        "objectName": "string",
        "sourceType": "OBJECT_STORAGE_TUPLE"
      },
      {
        "sourceType": "OBJECT_STORAGE_URI",
        "sourceUri": "string"
      },
      {
        "sourceType": "TEXT",
        "text": "string",
        "textSha256": "string"
      }
    ]
  },
  "displayName": "string",
  "target": {
    "instanceId": "string"
  },
  "timeoutInSeconds": "string"
}
```
</div></details>


# Execution
Execute from an instance of the Job management tool, etc.
Windows
```
[user@linux]$ oci instance-agent command create --auth instance_principal --endpoint https://iaas.ap-tokyo-1.oraclecloud.com --from-json file:///path/to/runcommand_nginxstart_win.json
```
Linux
```
[user@linux]$ oci instance-agent command create --auth instance_principal --endpoint https://iaas.ap-tokyo-1.oraclecloud.com --from-json file:///path/to/runcommand_nginxstart_linux.json
```
You can check the status of the executed command by selecting the target instance from the OCI console navigation menu >> Instances and selecting the execution command from the resource menu at the bottom left.
When creating a command
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/053750d5-df20-d513-973d-8af3aef09113.png">
When the command is successful
<img width="400" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2730992/2c5d0535-ff22-3936-3cfe-0d7515638fce.png">

Output can be downloaded and checked from Object storage.
Windows
```
[user@linux]$ oci os object get --auth instance_principal --endpoint https://objectstorage.ap-tokyo-1.oraclecloud.com --namespace 【ネームスペース】 --bucket-name 【バケット名】 --name runcommand/output_nginxstart_win.log --file output_nginxstart_win.log
Downloading object  [####################################]  100%
```

```runcommand_output_nginxstart_win.log
C:\Windows\system32>echo Mon 04/08/2024 
Mon 04/08/2024

C:\Windows\system32>echo 16:06:48.03 
16:06:48.03

C:\Windows\system32>cd c:\nginx-1.24.0 

c:\nginx-1.24.0>start nginx 

c:\nginx-1.24.0>ping 127.0.0.1 

Pinging 127.0.0.1 with 32 bytes of data:
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128
Reply from 127.0.0.1: bytes=32 time<1ms TTL=128

Ping statistics for 127.0.0.1:
    Packets: Sent = 4, Received = 4, Lost = 0 (0% loss),
Approximate round trip times in milli-seconds:
    Minimum = 0ms, Maximum = 0ms, Average = 0ms

c:\nginx-1.24.0>curl -s -o nul -w "%{http_code}" http://127.0.0.1 
200
c:\nginx-1.24.0>exit /b 
```
Linux
```
[user@linux]$ oci os object get --auth instance_principal --endpoint https://objectstorage.ap-tokyo-1.oraclecloud.com --namespace 【ネームスペース】 --bucket-name 【バケット名】 --name runcommand/output_nginxstart_linux.log --file output_nginxstart_linux.log
Downloading object  [####################################]  100%
```

```runcommand_output_nginxstart_linux.log
Mon Apr  8 15:59:19 JST 2024
PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.
64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.046 ms
64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.051 ms
64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.047 ms
64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.048 ms

--- 127.0.0.1 ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3054ms
rtt min/avg/max/mdev = 0.046/0.048/0.051/0.002 ms
200
```
It's able to start and confirm the startup of nginx on Windows and Linux.
Registering these OCI CLI commands in the job management tool, you can incorporate them into operations.