In a previous post, I walked through how to create an Autonomous Database on the Oracle Cloud using the OCI-CLI. In this post you’ll learn how to create a compute instance.
You can use these commands in your Oracle Cloud Shell from your Cloud Dashboard where the OCI-CLI is already setup and ready to go.
If you’d rather use your own environment you can follow these instructions to install and configure the OCI-CLI.
Environment Variables
There are some pieces of information you’ll need in order to create the compute instance. Of course you can look this information up manually, but it’s more fun to automate as much as possible.
Preset Values
Create environment variables for the following:
The name of the Compartment you want to create your new Compute instance in.
The name for your new Compute instance.
The shape you want to use.
VM.Standard.E2.1.Micro is used for an Always-Fee Compute instance.
The absolute path for your user’s home directory.
Shell
1
2
3
4
export COMPARTMENT_NAME='Test'
export COMPUTE_NAME='TestCompute'
export COMPUTE_SHAPE='VM.Standard.E2.1.Micro'
export USER_HOME=$(eval echo~)
The following commands will create the given object and use the returned OCID to create an environment variable to be used in the other steps.
For example:
Shell
1
export NEW_OCID=$(the OCI commandyou would run tocreate the objectandreturnthe OCID)
Compartment OCID
The previous post demonstrates how to use the
--query parameter to get the OCID for the Compartment.
Shell
1
export COMPARTMENT_ID=$(oci iam compartment list--query"data[?name=='${COMPARTMENT_NAME}'].id | [0]"--raw-output)
Availability Domain
You’ll need to define which Availability Domain you want to use. The above Compute Shape is typically available in your third sub-domain, ‘xxxx:US-ASHBURN-AD-3’.
The following
--query parameter for the list command will search for the name of a sub-domain ending in ‘-3’, if one is not found it will chose the first sub-domain in the array.
Shell
1
export AVAILABILITY_DOMAIN=$(oci iam availability-domain list--query"(data[?ends_with(name, '-3')] | [0].name) || data[0].name"--raw-output)
Create a Virtual Cloud Network
Your Compute instance will need a VCN in order to connect to the outside world. If you have already created a compute instance in this compartment you can re-use the existing VCN and subnet or follow these instructions to create a new one.
In order to connect to your compute instance you’ll need an RSA key pair.
If you don’t already have a key pair, use the following command to generate two new files, your “key pair”.
id_rsa is your private key, do not share this.
id_rsa.pub is your public key that you will share. The below command will create these files in the .ssh directory inside your home directory. You can change the directory or name if you wish.
Now that you have created a network and a key pair you can
Create the Compute Instance
If you created your key pair with a different name or in a different location than
${USER_HOME}/.ssh/id_rsa.pub , you will need to modify the
--ssh-authorized-keys-filevalue below when you launch your new instance.
In this post I’ll cover how to create an Oracle Autonomous Cloud Database download the Wallet credentials and connect to the database all from the command line using the OCI-CLI.
After that I’ll include an example of a shell script that I use to setup my Demo environment.
I like to keep all of my work compartmentalized so that I don’t run into conflicts between my (and potentially other people’s) projects. This means I’ll need to get the OCID of the compartment I want to work in.
Rather than use the Web Console you can run this command to get a list of your available compartments.
Shell
1
oci iam compartment list
Assuming that you already know which compartment you want to work with you can use the
--query parameter to retrieve the ID of that compartment.
The above command returns an array called data that I will use to query an object.
Shell
1
--query"data[]"
I’d like to retrieve only the object with a name of ‘Demo’.
Now that I have the full object, I can get the id value.
1
--query"data[?name=='Demo'].id"
Shell
1
2
3
[
"ocid1.compartment.oc1..aaaaaaaa7a6biglongguid"
]
The list command will return all objects that match the query criteria in an array. Even when there is only a single object it will be returned in an array.
Next, I pipe out the first (and only) value from the array.
Shell
1
--query"data[?name=='Demo'].id | [0]"
Shell
1
"ocid1.compartment.oc1..aaaaaaaa7a6biglongguid"
Using the
--raw-output parameter, I can get the raw value without the double quotes.
Shell
1
oci iam compartment list--query"data[?name=='Demo'].id | [0]"--raw-output
Shell
1
ocid1.compartment.oc1..aaaaaaaa7a6biglongguid
I can use this command to set an environment variable.
Shell
1
export COMPARTMENT_ID=$(oci iam compartment list--query"data[?name=='Demo'].id | [0]"--raw-output)
If the compartment doesn’t exist you can use OCI to create one. For this command you will need the OCID of an existing compartment. This will be the parent compartment.
If you want to use an existing compartment as a parent, you can use the above command to get the OCID. Or, if you want to add the new compartment to the ROOT compartment, you can use the Tenancy OCID.
You can get the Tenancy OCID from:
Your OCI Config file
cat~/.oci/config.
The OCID of an existing compartments parent.
This time I’m using the
?contains() function to check compartment-id for the string ‘.tenancy.’. Notice that the compartment-id must be double quoted because it contains a ‘-‘ and those double quotes are escaped.
\"compartment-id\"oci iam compartment list--query"data[?contains(\"compartment-id\",'.tenancy.')].\"compartment-id\" | [0]"--raw-output
Once you have the parent compartment OCID the command to create a new compartment is:
I can check to see if the database already exists by using a query similar to the one I used for compartments.
1
export DB_ID=$(oci db autonomous-database list-c$COMPARTMENT_ID--query"data[?\"db-name\"=='demo'].id | [0]"--raw-output)
If the demo database doesn’t exist I can create a new Always-Free Autonomous Cloud Database with the OCI-CLI.
The data-storage-size-in-tbs is set to 1TB which is larger than the free tier supports. Setting
--is-free-tier True will cause the system to automatically scale it to the correct size.
The default value for ‘is-free-tier’ is False, if you do not include this parameter you will create a standard Autonomous Cloud Database. You should check the Cost Estimator to ensure that you’re OK with the cost.
Setting
--db-workload"OLTP" will create an Autonomous Transaction Processing database, using “DW” will create a Data Warehouse.
Make sure you use a strong
--admin-password , this will be the admin password for the new database.
Shell
1
2
3
4
5
6
7
8
9
oci db autonomous-database create\
--compartment-id$COMPARTMENT_ID\
--cpu-core-count1\
--data-storage-size-in-tbs1\
--db-name"$DB_NAME"\
--display-name"$DB_DISPLAY_NAME"\
--db-workload"OLTP"\
--admin-password"T3stertester"\
--is-free-tier True
This command will return a JSON object with the properties of the new database.
I’ll add the query and raw-output parameters to extract the ID and assign it to an environment variable.
Shell
1
2
3
4
5
6
7
8
9
10
export DB_ID=$(oci db autonomous-database create\
--compartment-id$COMPARTMENT_ID\
--cpu-core-count1\
--data-storage-size-in-tbs1\
--db-name"$DB_NAME"\
--display-name"$DB_DISPLAY_NAME"\
--db-workload"OLTP"\
--admin-password"T3stertester"\
--is-free-tier True\
--query"data.id"--raw-output)
In order to connect to my new database I will need to
Download the Wallet
Wait for your database to be in an AVAILABLE state before attempting to download the wallet.
This command will download your wallet credentials in a .zip file, just like you’d get from the web console.
The $DB_ID variable was set above for the demo database. The –file parameter accepts the location and file name where you want to download the .zip file. The new file will have the password set by –password.
Shell
1
oci db autonomous-database generate-wallet--autonomous-database-id$DB_ID--password Pw4ZipFile--file/home/bcarter/wallets/Wallet_demo.zip
I’ll start SQLcl without making a connection (/nolog).
Set cloudconfig to the location of the wallet credentials.
Connect with the admin password and one of the service names contained in the tnsnames.ora file included in the wallet zip file.
The predefined service names will be in the form of
<name of the database>_<performance level> . You can find more information here.
# If the Database does not exist ask to create it.
if[[-z"${DB_ID}"]];then
echo"No ${DB_NAME} Database found."
whiletrue;do
read-p"Do you wish to create the ${DB_NAME} Database? "yn
case$ynin
[Yy]*)create_db;break;;
[Nn]*)exit;;
*)echo"Please answer y or n.";;
esac
done
fi
# Download the wallet
download_wallet
# Create an SQL script to test the connection
echo"setcloudconfig${WALLET_ZIP}
connectadmin/${DB_PW}@${DB_NAME}_TP
select'Yes! I connected to my Always Free ATP database!'did_it_work from dual;
exit;">testConnection.sql
# Test the connection
sql/nolog@testConnection.sql
# Delete the test script
rmtestConnection.sql
Notice that in the create database method I added a new parameter to the OCI call
--wait-for-state AVAILABLE. Since I won’t be able to download the wallet until the database is available, I use this parameter to pause at the create step until the new Database is fully up and running.
When I run the script I get
Shell
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@OraBlaineOS:OCI-CLI$./setup.sh
Query returned empty result,no output toshow.
No demo Database found.
Doyou wish tocreate the demo Database?y
Action completed.Waiting untilthe resource has entered state:('AVAILABLE',)
I love working with cloud resources. I don’t have to bog down my laptop and I don’t have to maintain all of the back-end stuff. I don’t mean to make it sound as if I think the “back-end stuff” is easy. It’s actually, I understand just enough of that “stuff” to make it go (most of the time) so it’s nice to have experts in the cloud taking care of it for me.
Some of you may be thinking “but cloud resources are expensive.” That’s true sometimes, but it depends on who’s cloud you’re using. If you’ve been following me you should already know how much I like Oracle’s Always Free Services and you should know that I love to automate anything I can. If you’d like to follow along but you don’t have an Oracle Cloud account, click that link, create an Always Free account then come back.
Oracle’s cloud CLI is a small application you can use to control your Oracle Cloud resources. It gives you the same core functionality as you’d get using the Web Console, and some extra commands. It allows you to control your cloud account from your local console application so you can easily automate the control of your resources.
Pre-requisits
Python 3.5+
The CLI is built with Python so make sure you have Python version 3.5 or higher installed.
RSA Key Pair
You will need an RSA key attached to your cloud user in order to remotely access your account. This must be an RSA key pair in PEM format (minimum 2048 bits).
The easiest way to generate this key par is with openssl. The following commands work in Linux/Mac environments. For Windows you can use your favorite tool or execute the commands in GitBash, WSL or some other Linux shell environment.
The first command creates a PRIVATE KEY called ‘myPrivateKey.pem’ (name yours whatever you’d like). This is the key you will use to access remote systems. DO NOT share this key, whoever has this key can connect to those systems as you. Think of it as your admin password.
The second command uses your private key to create a PUBLIC KEY called ‘myPublicKey.pem’ (name yours whatever you’d like). This is the key you will share with remote systems. Those systems will add your PUBLIC KEY to their authorized keys list, allowing you to access their system using your private key.
Store these keys in a secure location. On Linux, the default location is usually in the ~/.ssh directory. But, if you’re creating separate keys for your projects, you can store them wherever you’d like. Just remember the location for later.
Cloud Account
You need to have access to an Oracle Cloud account with a user that is authorized to preform the tasks you intend to automate. A good way to tell if your user has the correct permissions is to log onto your account through the Web Console and create an Always Free database then terminate it.
While you’re logged into the Web Console collect some information.
Tenancy
In the menu, under Administration, click Tenancy Details.
Locate the OCID and click Copy.
Save this value for later.
User
In the menu under Identity click Users.
Select your user.
Near the bottom click ‘API Keys’ under the resource menu.
Click the ‘Add Public Key’ button.
Choose the PUBLIC key file you generated earlier.
Click the ‘Add’ button.
Your key should now show up in the ‘API Keys’ list.
Copy the fingerprint of your key and save it for later.
Near the top of the user page, locate the OCID and click Copy. Save this value for later.
Quickstart Install
You can download an execute a script that will ask you typical installation configuration questions, after which it will install and configure the OCI-CLI.
The following is current as of the publish date for this post, but you may want to review the instructions in case things change.
You can add other connection profiles manually by following this format or you can use the same command to add a new profile. If you re-run the command, it will ask you for a name to use for the new profile which will be added to the config file.
Now that your OCI-CLI is installed and configured, you should familiarize yourself with the OCI-CLI documentation to learn about the many, many commands you can use to automate the control of your Oracle Cloud resources.
You can use these same commands from any system with the OCI-CLI installed, including Oracle Cloud Compute instances.
Make sure there’s only one / between your URL and cc. For example: buttona1=https://asdr34edyjtyi4j-codecard.adb.us-ashburn-1.oraclecloudapps.com/ords/cc/functions/master
When all of that is done, go to the Development section of the Service Console for your ATP instance and click “SQL Developer Web”. Sign in as admin with the admin password you created in step 2.
Database Setup
As Admin, create the CODE_CARD schema.
Execute the following code in the worksheet. Use a good password and remember it for later.
This will create the new CODE_CARD schema and REST enable the schema so you can use it with ORDS. Notice the p_url_mapping_pattern is set to ‘cc’, this will be part of the REST URI in the following sections.
oraclecloudapps.com/ords/cc/
As code_card, create the database objects
Switch to the code_card schema by changing the URL In your browser. Replace ‘admin’ with ‘cc’. ...oraclecloudapps.com/ords/admin/_sdw/?nav=worksheet to
...oraclecloudapps.com/ords/cc/_sdw/?nav=worksheet
Log into SQL Developer Web as code_card using your new password.
In a worksheet, use the following to create the tables.
You will need two rest endpoints. One to POST the setting for each button press and one your CodeCard will use to GET those settings.
There are multiple ways you can create an ORDS API, this post will walk through how to create the API using PL/SQL. I will explain the settings that are most important for the CodeCard interface. For the other settings, you can find the full documentation here.
This step was completed above
When you created the new schema above, you also REST enabled the new schema with this PL/SQL.
Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
BEGIN
ords_admin.enable_schema(
p_enabled=>TRUE,
p_schema=>'CODE_CARD',
p_url_mapping_type=>'BASE_PATH',
p_url_mapping_pattern=>'cc',
p_auto_rest_auth=>NULL
);
commit;
END;
This command was included in the above step so that you could log into SQL Developer WEB as code_card.
The following will explain the individual PL/SQL procedures used to create the REST API.
If you want to skip the explanation, you can jump straight to the complete code included below.
Define a module
A module is a collection of related REST services. Think of a module as a package that contains REST endpoints.
Create a module called ‘functions’.
Oracle PL/SQL
1
2
3
4
5
6
ORDS.DEFINE_MODULE(
p_module_name=>'functions',
p_base_path=>'/functions/',
p_items_per_page=>25,
p_status=>'PUBLISHED',
p_comments=>NULL);
The base path is set to ‘/functions/’, this will be part of the REST URI.
tmp_function := ''Button '' || UPPER(:buttonlabel) || '' short press'';
elsif :buttonfunction = ''2'' then
tmp_function := ''Button '' || UPPER(:buttonlabel) ||'' long press'';
else
tmp_function := ''No button pressed'';
end if;
APEX_JSON.open_object;
APEX_JSON.write(''template'', ''template1'');
APEX_JSON.write(''title'', ''Uh oh!'');
APEX_JSON.write(''subtitle'', tmp_function);
APEX_JSON.write(''bodytext'', ''You have not configured your Code Card'');
APEX_JSON.write(''icon'', ''fail'');
APEX_JSON.close_object;
end;');
Using a source type of ‘json/collection’ would allow you to use a simple SQL query and ORDS would handle all of the JSON formatting for us. This would be easier.
However, we want to be able to return a functioning screen layout to the CodeCard even if there’s an error. Using a source type of ‘plsql/block’ lets you create and return a custom APEX_JSON object even if there’s an error.
Parameters for the bind variables
The PL/SQL code uses 3 bind variables that are mapped to incoming request header values.
The bind variables are mapped to the header values by defining parameters. These parameters will all be assigned to the ‘functions’ module, ‘master’ template and ‘GET’ handler. They will be passed ‘IN’ through the ‘HEADER’ as a ‘STRING’ type. The value of the incoming header defined in ‘p_name’ will be mapped to value of the PL/SQL bind variable defined in ‘p_bind_variable_name’.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'GET',
p_name=>'X-CODECARD-BUTTON-FUNCTION',
p_bind_variable_name=>'buttonfunction',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'GET',
p_name=>'X-CODECARD-BUTTON-LABEL',
p_bind_variable_name=>'buttonlabel',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'GET',
p_name=>'X-CODECARD-ID',
p_bind_variable_name=>'badgeid',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
X-CODECARD-ID is the id assigned to your CodeCard.
X-CODECARD-BUTTON-LABEL will either be the A or B button.
X-CODECARD-BUTTON-FUNCTION will be 1 for a short press or 2 for a long press.
Handle POST requests
The CodeCard sends a POST request to the REST API to store the settings assigned to a specific button and press function.
where BADGEID = upper(:badgeId) and BUTTONLABEL = :buttonlabel and BUTTONFUNCTION = :buttonfunction
returning id into tmpId;
commit;
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''reacordId'', tmpId);
APEX_JSON.close_object;
end;');
This PL/SQL block will either create a new record or update an existing record for the incoming CodeCard id, button label and button function.
Parameters for the bind variables
The parameters for the POST handler are the same as for the GET handler.
Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-BUTTON-FUNCTION',
p_bind_variable_name=>'buttonFunction',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-BUTTON-LABEL',
p_bind_variable_name=>'buttonLabel',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-ID',
p_bind_variable_name=>'badgeId',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
Register template (Optional)
The register template is used by the CodeCard designer to map your name to your CodeCard id, if you choose to enter it. Another post will detail how to install the CodeCard designer in an always free Oracle compute instance. If you plan on implementing the designer, include this handler template and handler. Even if you do not plan on implementing the designer, it won’t hurt anything to include these objects.
Oracle PL/SQL
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
ORDS.DEFINE_TEMPLATE(
p_module_name=>'functions',
p_pattern=>'register',
p_priority=>0,
p_etag_type=>'HASH',
p_etag_query=>NULL,
p_comments=>NULL);
ORDS.DEFINE_HANDLER(
p_module_name=>'functions',
p_pattern=>'register',
p_method=>'POST',
p_source_type=>'plsql/block',
p_mimes_allowed=>'application/json',
p_comments=>NULL,
p_source=>
'declare
tmpBadgeId varchar2(100);
begin
insert into CODECARD (
BADGEID, NAME, CREATED
)
values (
UPPER(:badgeId), INITCAP(:name), systimestamp
);
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''status'', ''registered'');
APEX_JSON.close_object;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
UPDATE CODECARD set NAME = INITCAP(:name) where BADGEID = upper(:badgeId);
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''status'', ''logged'');
APEX_JSON.close_object;
end;');
If you are piecing all of the above sections together you will need to execute a ‘COMMIT’ to save the changes to your database. Or, you can use the following.
Full ORDS PL/SQL code
In a worksheet use the following code to create the Oracle REST Data Services API.
where BADGEID = upper(:badgeId) and BUTTONLABEL = :buttonlabel and BUTTONFUNCTION = :buttonfunction
returning id into tmpId;
commit;
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''reacordId'', tmpId);
APEX_JSON.close_object;
end;');
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-BUTTON-FUNCTION',
p_bind_variable_name=>'buttonFunction',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-BUTTON-LABEL',
p_bind_variable_name=>'buttonLabel',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_PARAMETER(
p_module_name=>'functions',
p_pattern=>'master',
p_method=>'POST',
p_name=>'X-CODECARD-ID',
p_bind_variable_name=>'badgeId',
p_source_type=>'HEADER',
p_param_type=>'STRING',
p_access_method=>'IN',
p_comments=>NULL);
ORDS.DEFINE_TEMPLATE(
p_module_name=>'functions',
p_pattern=>'register',
p_priority=>0,
p_etag_type=>'HASH',
p_etag_query=>NULL,
p_comments=>NULL);
ORDS.DEFINE_HANDLER(
p_module_name=>'functions',
p_pattern=>'register',
p_method=>'POST',
p_source_type=>'plsql/block',
p_mimes_allowed=>'application/json',
p_comments=>NULL,
p_source=>
'declare
tmpBadgeId varchar2(100);
begin
insert into CODECARD (
BADGEID, NAME, CREATED
)
values (
UPPER(:badgeId), INITCAP(:name), systimestamp
);
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''status'', ''registered'');
APEX_JSON.close_object;
EXCEPTION
WHEN DUP_VAL_ON_INDEX THEN
UPDATE CODECARD set NAME = INITCAP(:name) where BADGEID = upper(:badgeId);
APEX_JSON.open_object;
APEX_JSON.write(''badgeId'', upper(:badgeId));
APEX_JSON.write(''status'', ''logged'');
APEX_JSON.close_object;
end;');
COMMIT;
END;
Setup a button press
One final piece of information you’ll need is your CodeCard’s id.
Turn your CodeCard on.
Press and release the A and B buttons at the same time. Your CodeCard will display a barcode with a 12 character id string under it.
Save that ID string.
Testing
POST
If you are using a tool such as Postman to test your API you will need to create a POST request with the following pieces.
URI: {{URL from the prerequisite section}}/cc/functions/master
For example:
https://asdr34edyjtyi4j-codecard.adb.us-ashburn-1.oraclecloudapps.com/ords/cc/functions/master
Headers
X-CODECARD-ID: Us the ID string from above
X-CODECARD-BUTTON-LABEL: either ‘a’ or ‘b’
X-CODECARD-BUTTON-FUNCTION: use ‘1’ for a short press or ‘2’ for a long press
Content-Type: application/json
Body: use a JSON object like this
JavaScript
1
2
3
4
5
6
7
8
9
{
"template":"template5",
"title":"I DID IT!!!",
"subtitle":"My CodeCard",
"bodytext":"is running on my Oracle Always Free ATP database!",
"icon":"opensource",
"backgroundColor":"white",
"barcode":"Oracle Code"
}
If you’d prefer to use a CURL command (replace the {{ }} sections with your values):
"bodytext": "is running on my Oracle Always Free ATP database!",
"icon": "opensource",
"backgroundColor": "white",
"barcode": "Oracle Code"
}'
With either method, you should receive a response with a status of 200 and a JSON object in the body like this
JavaScript
1
2
3
4
{
"badgeId":"YourBadgeId"
,"reacordId":2
}
Test GET
Assuming you completed the prerequisite section, you should be able to short or long press the A or B button on your CodeCard and your new template settings will be displayed on your screen.
You can also test the GET handler by sending a GET request to the same URI used above. Use the same values for the headers, you do not need a body.
X-CODECARD-ID: Use the ID string from above
X-CODECARD-BUTTON-LABEL: either ‘a’ or ‘b’
X-CODECARD-BUTTON-FUNCTION: use ‘1’ for a short press or ‘2’ for a long press
If you’d rather use CURL (replace the {{ }} sections with your values):
You’ve signed up for the Oracle Cloud Free Tier at https://www.oracle.com/cloud/free/ and now you want to create an Always Free Autonomous Database.
Create a new Database
These instructions should work for both (ATP) Autonomous Transaction Processing and (ADW) Autonomous Data Warehouse Databases.
After you log into your Oracle Cloud Dashboard.
Click on the “Create an ATP database” box. (Or the “Create an ADW database” box if you want a data warehouse)
Choose the compartment you want to use.
Fill in the “Display Name” field. This name will be displayed in the GUI lists and drop down selection boxes in your Oracle Cloud dashboard. You can change this later.
Fill in the “Database Name” field. This name will be used as the permanent ID for this database. It will show up in places such as the auto-generated TNSNAMES.ORA file that you’ll download in another step. You can not change this later, so choose wisely.
In the “Choose a workload type” section, make sure the correct workload type is selected..
Since we want to create an Always Free Database, leave “Shared Infrastructure” selected in the “Choose a deployment type” section.
Make sure the “Always Free” selector is turned on. This will lock in the options for an Always Free instance. (20 GB of storage and 1 OCPU)
Scroll down to the “Create administrator credentials” section and enter a Strong password for your Admin account.
You will use the Admin account to connect to your Autonomous Database instead of SYS or System.
Under the “Choose a license type” section make sure “License Included” is selected.
Click the “Create Autonomous Database” button.
Your new ATP instance will be provisioned. The orange box will turn green once it has been provisioned and is available to use.
While you’re waiting, check that you see the Always Free tag next to your database name. If you do not see the tag, you may want to check to see what license you created the instance under and make sure you are OK with those options or terminate the instance and create a new one with the Always Free options selected.
Once the orange box turns green and your database is available, you will want to connect to it.
The Oracle Autonomous Cloud Databases are setup with a little extra security. In order to connect you will need to use a wallet credentials file.
Download the Oracle Credentials file
There are a couple different ways to get the wallet file through the Cloud Dashboard.
From the Details page
Click on the “DB Connection” button.
On this form you will find a list of the auto-generated TNSNAMES entries and connection strings that you can use to connect to your database. There is a link to the documentation explaining the difference between the entries. For typical transactions I like to use the one ending in _TP.
Click the “Download Wallet” button.
Create a password that will be used to access the .zip file.
Click the “Download” button.
Remember the location where you save your wallet file, you will need it when we test the connection.
Save the .zip file to a secure location. This file is used to access your database so keep it secure.
From the Service Console
You can get to the Service Console for your Database instance either from the Details page
or from the menu for the instance in the Autonomous Transaction Processing Database list.
Once your in the service Console
Click on “Administration”.
Click on “Download Client Credentials (Wallet)”.
Create a password that will be used to access the .zip file.
Click the “Download” button.
Important Wallet Security Information
All wallets downloaded with either method will create a copy of the *SAME WALLET* even if you use different passwords for the .zip file.
You can rotate the wallet from your database instance details page. Read the docs.
Click the “DB Connection” button.
Press the “Rotate Wallet” button and follow the instructions.
Connect to the Database
SQLcl is a great tool for making a quick and easy connection to the new database.
Start SQLcl in ‘nolog’ mode
1
2
3
4
SQL>sql/nolog
SQLcl:Release18.3Production on Fri Jan0317:57:562020
Copyright(c)1982,2020,Oracle.All rights reserved.
Set the location of your .zip file in the cloudconfig variable.
In this post I’ll cover how to make a connection from a Node.js application in a Docker container to your Oracle Database in three different scenarios.
The container will run, execute the query and stop. You should see something similar to this output.
1
2
{metaData:[{name:'CURRENT_TIMESTAMP'}],
rows:[[2019-08-27T16:42:16.122Z]]}
Since both containers are using the same Docker network, you do not need to open the port when you run the Oracle XE container. This is useful if you’d like to keep your database private inside the Docker environment.
After you create an Oracle ATP Cloud Database you’ll need to download the credentials file and extract it into a secure location.
For this database, you will be using an entry in the tnsnames.ora file to make the database connection. Change the NODE_ORACLEDB_CONNECTIONSTRING environment variable to use the tnsnames entry:
1
export NODE_ORACLEDB_CONNECTIONSTRING=projects_tp
Before you run the container, you need to modify the sqlnet.ora file found in the credentials directory. Change the wallet location to the value that will be mapped inside the Docker container.
When you run the new container for the node app you will map a volume from the directory where you extracted your credentials file to the internal container directory. Mapping a volume makes sure that there is not a copy of the credential files inside the Docker container.
1
-v/my/host/machine/credentials/directory:/wallet
Finally, when you run the new container, you will add an additional environment variable defining where the tns admin information is located.
The container will run, execute the query and stop. You should see something similar to this output.
1
2
{metaData:[{name:'CURRENT_TIMESTAMP'}],
rows:[[2019-08-27T18:21:26.298Z]]}
I used the same docker image for all of the examples
You may have noticed that you only built the Docker image once at the beginning of the post. The application in the Docker image uses environment variables to connect to the database. This allows you to run the same application in one or more containers and each container can connect to different Oracle Databases without having to rebuild the image.
Whenever I give a presentation, write a blog post or make a video I like to run all of my examples and demos locally and on an Oracle Cloud instance. I keep a Virtual Box machine or Docker Container ready on my laptop, just in case I can’t get to the internet, but for speed and dependability, you just can’t beat a cloud instance.
I like to have some automation scripts handy to create and destroy my environments and depending on what I’m doing that can sometimes take a while.
So when Oracle’s Autonomous Transaction Processing Database was released I was excited by how fast I could spin up a new instance. It takes a few minutes instead of around an hour for other options. Oracle wanted to make sure ATP was solid, so they initially launched with a limited feature set and new features have been making their way into Oracle’s Autonomous Transaction Processing Database almost every month.
I was scheduled to give my ‘Creating REST APIs Is Fast, Easy, and Secure with Oracle REST Data Services‘ talk on Wednesday and I like to live dangerously, so I decide (Tuesday afternoon) to convert my demos over to ORDS on ATP. I figured worst case, if I couldn’t figure it out I’d just use my Docker container.
It’s going to be hard… right?
I already had a couple of ATP instances that I use for stuff and things. Since I wanted to do a live demo, I decided to spin up a new instance just in case I expose anything that could be used to get in. It took under 5 minutes to fully create and start up a brand new ATP database. After that, I downloaded my Client Credentials (Wallet) and connected with SQL Developer. There are lots of examples for this part so I’ll move on to the new stuff.
New User
I try to do as little as possible as the Admin user so I created a rest_demo user with a couple of tables and a view.
Then I used the SQL Developer ‘Auto REST’ feature to REST enable the schema and a table. (PL/SQL exported below in case you want to try it.)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
DECLARE
PRAGMA AUTONOMOUS_TRANSACTION;
BEGIN
ORDS.ENABLE_SCHEMA(p_enabled=>TRUE,
p_schema=>'REST_DEMO',
p_url_mapping_type=>'BASE_PATH',
p_url_mapping_pattern=>'api',
p_auto_rest_auth=>FALSE);
commit;
ORDS.ENABLE_OBJECT(p_enabled=>TRUE,
p_schema=>'REST_DEMO',
p_object=>'COOL_DATA_T',
p_object_type=>'TABLE',
p_object_alias=>'cool_data',
p_auto_rest_auth=>FALSE);
commit;
END;
Get the URI
Now I just needed the URI to test my new service. Here are the steps:
Log into your Oracle Cloud Dashboard.
From the menu, select ‘Autonomous Transaction Processing’.
From the instance menu, select ‘Service Console’.
Or, Click on your Instance Name then Click the ‘Service Console’ button.
Click ‘Development’.
In the Rest Data Services box, click the “Copy URL” button.
Test it
For a simple fast test, I just used an internet browser with the following URI:
https://someIdstuff-blaineords.adb.my-region-1.oraclecloudapps.com/ords/api/cool_data
Well, that was easy.
To be honest I expected this to be a lot harder and that I’d have problems. I ran through all of the demos for my presentation and they just worked, first try.
The thing I spent the most time on was re-checking everything. Since it was so easy, I thought I had connected to one of my pre-existing cloud databases.
Go try it!
As always, don’t take my word for it, go try it yourself.
Here are some links to help get you going:
If you don’t have access to an Oracle Cloud account, you can get a trial account here.
You must be logged in to post a comment.