Skip to content

Commit 0d6cadb

Browse files
committed
adding oci-stop-untagged-instance-python
1 parent b109f6d commit 0d6cadb

File tree

9 files changed

+215
-0
lines changed

9 files changed

+215
-0
lines changed

Diff for: samples/oci-stop-untagged-instance-python/README.md

+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
# Function for Stopping improperly tagged instance during provisioning
2+
3+
This is an example of a function to check if a compute instance is tagged correctly on provisioning. If not, stop the instance.
4+
5+
This function is trigged by the compute event -- **Instance - Launch End** which is generated by compute at the completion of instance provisioning whether it succeeds or fails.
6+
7+
This sample uses Oracle cloud infrastructure search to search for compute resources with the freeform tag with a tag key of **costcenter** and tag value of **1234**.
8+
9+
Uses the [OCI Python SDK](https://oracle-cloud-infrastructure-python-sdk.readthedocs.io/en/latest/index.html) to create a client that receive user information when called in the OCI or a valid config file exists.
10+
11+
As you make your way through this tutorial, look out for this icon ![user input icon](./images/userinput.png).
12+
Whenever you see it, it's time for you to perform an action.
13+
14+
15+
## Prerequisites
16+
Before you deploy this sample function, make sure you have run step A, B and C of the [Oracle Functions Quick Start Guide for Cloud Shell](https://www.oracle.com/webfolder/technetwork/tutorials/infographics/oci_functions_cloudshell_quickview/functions_quickview_top/functions_quickview/index.html)
17+
* A - Set up your tenancy
18+
* B - Create application
19+
* C - Set up your Cloud Shell dev environment
20+
21+
22+
## List Applications
23+
Assuming your have successfully completed the prerequisites, you should see your
24+
application in the list of applications.
25+
```
26+
fn ls apps
27+
```
28+
29+
30+
## Create or Update your Dynamic Group
31+
In order to use other OCI Services, your function must be part of a dynamic group. For information on how to create a dynamic group, refer to the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Tasks/managingdynamicgroups.htm#To).
32+
33+
When specifying the *Matching Rules*, we suggest matching all functions in a compartment with:
34+
```
35+
ALL {resource.type = 'fnfunc', resource.compartment.id = 'ocid1.compartment.oc1..aaaaaxxxxx'}
36+
```
37+
Please check the [Accessing Other Oracle Cloud Infrastructure Resources from Running Functions](https://docs.cloud.oracle.com/en-us/iaas/Content/Functions/Tasks/functionsaccessingociresources.htm) for other *Matching Rules* options.
38+
39+
40+
## Create or Update IAM Policies
41+
Create a new policy that allows the dynamic group to *use instance-family*.
42+
43+
![user input icon](./images/userinput.png)
44+
45+
Your policy should look something like this:
46+
```
47+
Allow dynamic-group <dynamic-group-name> to use instance-family in compartment <compartment-name>
48+
```
49+
For more information on how to create policies, check the [documentation](https://docs.cloud.oracle.com/iaas/Content/Identity/Concepts/policysyntax.htm).
50+
51+
52+
## Review and customize your function
53+
Review the following files in the current folder:
54+
* the code of the function, [func.py](./func.py)
55+
* its dependencies, [requirements.txt](./requirements.txt)
56+
* the function metadata, [func.yaml](./func.yaml)
57+
58+
59+
## Deploy the function
60+
In Cloud Shell, run the fn deploy command to build the function and its dependencies as a Docker image,
61+
push the image to OCIR, and deploy the function to Oracle Functions in your application.
62+
63+
![user input icon](./images/userinput.png)
64+
```
65+
fn -v deploy --app <your app name>
66+
```
67+
e.g.
68+
```
69+
fn -v deploy --app myapp
70+
```
71+
72+
73+
Test
74+
----
75+
### Create A Cloud Event
76+
To create a new cloud event rule, click on Application Integration -> Events Service in the sidebar menu:
77+
78+
![user input icon](./images/userinput.png)
79+
80+
![event service image](./images/event_service.png)
81+
82+
### Click on 'Create Rule' and populate the form:
83+
![user input icon](./images/userinput.png)
84+
85+
![event rule image](./images/event_rule.png)
86+
87+
In this case, the event is **Instance - Launch End** and the action to take is to call the function **stop-untagged-instance**
88+
89+
### Launch a Compute instance
90+
91+
![user input icon](./images/userinput.png)
92+
93+
Launch an instance with no tags
94+
95+
![launch instance start](./images/launch_instance_start.png)
96+
97+
In a few seconds you should see that the instance has stopped because it wasn't tagged.
98+
99+
![launch instance stop ](./images/launch_instance_stopped.png)
100+
101+

Diff for: samples/oci-stop-untagged-instance-python/func.py

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#
2+
# oci-stop-untagged-instance-python version 1.0.
3+
#
4+
# Copyright (c) 2020 Oracle, Inc.
5+
# Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl.
6+
#
7+
8+
import io
9+
import json
10+
from fdk import response
11+
12+
import oci
13+
14+
def handler(ctx, data: io.BytesIO=None):
15+
16+
resp=None
17+
18+
try:
19+
body = json.loads(data.getvalue())
20+
jsondata = body.get("data")
21+
22+
23+
print("event type : " + body["eventType"],flush=True)
24+
print("Instance Id : " + body["data"]["resourceId"],flush=True)
25+
print("Instance Name : " + body["data"]["resourceName"],flush=True)
26+
print("Availability Domain : " + body["data"]["availabilityDomain"],flush=True)
27+
28+
print(jsondata.get("resourceId"),flush=True)
29+
print(jsondata.get("resourceName"),flush=True)
30+
print(jsondata.get("availabilityDomain"),flush=True)
31+
32+
print(json.dumps(body, indent=4), flush=True)
33+
34+
instanceId = body["data"]["resourceId"]
35+
signer = oci.auth.signers.get_resource_principals_signer()
36+
37+
resp = do(signer,instanceId)
38+
39+
return response.Response(
40+
ctx, response_data=json.dumps(resp),
41+
headers={"Content-Type": "application/json"}
42+
)
43+
except ( Exception, ValueError) as e:
44+
print("Error " + str(e), flush=True)
45+
46+
def do(signer,instanceId):
47+
48+
print("Searching for untagged instance", flush=True)
49+
50+
results = ""
51+
message = ""
52+
resp = ""
53+
54+
try:
55+
search_client = oci.resource_search.ResourceSearchClient(config={}, signer=signer)
56+
print("Search client initialized",flush=True)
57+
58+
key="costcenter"
59+
value="1234"
60+
61+
structured_search = oci.resource_search.models.StructuredSearchDetails(
62+
query="query instance resources where ((freeformTags.key != '{}' && freeformTags.value != '{}') && (identifier='{}'))".format(key,value,instanceId),
63+
type='Structured',
64+
matching_context_type=oci.resource_search.models.SearchDetails.MATCHING_CONTEXT_TYPE_NONE)
65+
results = search_client.search_resources(structured_search)
66+
if len(results.data.items) == 1:
67+
message = "Instance " + instanceId + " was untagged "
68+
print(message, flush=True)
69+
resp = perform_action(signer,instanceId, 'STOP')
70+
else:
71+
message = "Instance " + instanceId + " properly tagged "
72+
print(message, flush=True)
73+
74+
except oci.exceptions.ServiceError as e:
75+
print('RQS Search failed with Service Error: {0}'.format(e),flush=True)
76+
raise
77+
except oci.exceptions.RequestException as e:
78+
print('RQS Search failed w/ a Request exception. {0}'.format(e),flush=True)
79+
raise
80+
81+
return resp
82+
83+
84+
def perform_action(signer,instanceId,action):
85+
86+
compute_client = oci.core.ComputeClient(config={}, signer=signer)
87+
print("Performing action", flush=True)
88+
try:
89+
if compute_client.get_instance(instanceId).data.lifecycle_state in ('RUNNING'):
90+
try:
91+
92+
resp = compute_client.instance_action(instanceId,action)
93+
print('response code: {0}'.format(resp.status),flush=True)
94+
except oci.exceptions.ServiceError as e:
95+
print('Action failed. {0}'.format(e),flush=True)
96+
raise
97+
else:
98+
print('The instance {0} was in the incorrect state to stop'.format(instanceId),flush=True)
99+
except oci.exceptions.ServiceError as e:
100+
print('Action failed. {0}'.format(e),flush=True)
101+
raise
102+
103+
print('Action ' + action + ' performed on instance: {}'.format(instanceId),flush=True)
104+
105+
return compute_client.get_instance(instanceId).data.lifecycle_state

Diff for: samples/oci-stop-untagged-instance-python/func.yaml

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
schema_version: 20180708
2+
name: oci-stop-untagged-instance-python
3+
version: 0.0.1
4+
runtime: python
5+
entrypoint: /python/bin/fdk /function/func.py handler
6+
memory: 256
56.7 KB
Loading
Loading
Loading
Loading
2.96 KB
Loading
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
fdk
2+
oci-cli
3+
oci

0 commit comments

Comments
 (0)