Skip to content

Commit 5b40e1a

Browse files
authored
Releasing version 2.2.5
Releasing version 2.2.5
2 parents dc61e22 + 4a5136d commit 5b40e1a

File tree

71 files changed

+1666
-213
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+1666
-213
lines changed

CHANGELOG.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.
44

55
The format is based on `Keep a Changelog <http://keepachangelog.com/>`_.
66

7+
====================
8+
2.2.5 - 2019-04-02
9+
====================
10+
11+
Added
12+
-----
13+
* Support for provider service key names on virtual circuits in the FastConnect service
14+
* Support for customer reference names on cross connects and cross connect groups in the FastConnect service
15+
* A sample showing how to use Streaming service from the SDK is available on `GitHub <https://github.com/oracle/oci-python-sdk/blob/master/examples/stream_example.py>`__.
16+
717
====================
818
2.2.4 - 2019-03-26
919
====================

docs/api/core.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,7 @@ Core Services
107107
oci.core.models.ExportImageViaObjectStorageTupleDetails
108108
oci.core.models.ExportImageViaObjectStorageUriDetails
109109
oci.core.models.FastConnectProviderService
110+
oci.core.models.FastConnectProviderServiceKey
110111
oci.core.models.GetPublicIpByIpAddressDetails
111112
oci.core.models.GetPublicIpByPrivateIpIdDetails
112113
oci.core.models.IPSecConnection
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
FastConnectProviderServiceKey
2+
=============================
3+
4+
.. currentmodule:: oci.core.models
5+
6+
.. autoclass:: FastConnectProviderServiceKey
7+
:show-inheritance:
8+
:special-members: __init__
9+
:members:
10+
:undoc-members:
11+
:inherited-members:

examples/stream_example.py

Lines changed: 161 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,161 @@
1+
import oci
2+
import sys
3+
import base64
4+
import time
5+
6+
# ==========================================================
7+
# This file provides an example of basic streaming usage
8+
# * - List streams
9+
# * - Get a Stream
10+
# * - Create a Stream
11+
# * - Delete a Stream
12+
# * - Publish to a Stream
13+
# * - Consume from a stream partition using cursor
14+
# * - Consume from a stream using a group cursor
15+
# Documentation : https://docs.cloud.oracle.com/iaas/Content/Streaming/Concepts/streamingoverview.htm
16+
17+
# Usage : python stream_example.py <compartment id>
18+
19+
STREAM_NAME = "SdkExampleStream"
20+
PARTITIONS = 1
21+
22+
23+
def publish_example_messages(client, stream_id):
24+
# Build up a PutMessagesDetails and publish some messages to the stream
25+
message_list = []
26+
for i in range(100):
27+
key = "key" + str(i)
28+
value = "value" + str(i)
29+
encoded_key = base64.b64encode(key)
30+
encoded_value = base64.b64encode(value)
31+
message_list.append(oci.streaming.models.PutMessagesDetailsEntry(key=encoded_key, value=encoded_value))
32+
33+
print ("Publishing {} messages to the stream {} ".format(len(message_list), stream_id))
34+
messages = oci.streaming.models.PutMessagesDetails(messages=message_list)
35+
put_message_result = client.put_messages(stream_id, messages)
36+
37+
# The put_message_result can contain some useful metadata for handling failures
38+
for entry in put_message_result.data.entries:
39+
if entry.error:
40+
print ("Error ({}) : {}".format(entry.error, entry.error_message))
41+
else:
42+
print ("Published message to partition {} , offset {}".format(entry.partition, entry.offset))
43+
44+
45+
def get_or_create_stream(client, compartment_id, stream_name, partition, sac_composite):
46+
47+
list_streams = client.list_streams(compartment_id, name=stream_name,
48+
lifecycle_state=oci.streaming.models.StreamSummary.LIFECYCLE_STATE_ACTIVE)
49+
if list_streams.data:
50+
# If we find an active stream with the correct name, we'll use it.
51+
print ("An active stream {} has been found".format(stream_name))
52+
sid = list_streams.data[0].id
53+
return get_stream(sac_composite.client, sid)
54+
55+
print (" No Active stream {} has been found; Creating it now. ".format(stream_name))
56+
print (" Creating stream {} with {} partitions.".format(stream_name, partition))
57+
58+
# Create stream_details object that need to be passed while creating stream.
59+
stream_details = oci.streaming.models.CreateStreamDetails(name=stream_name, partitions=partition,
60+
compartment_id=compartment, retention_in_hours=24)
61+
62+
# Since stream creation is asynchronous; we need to wait for the stream to become active.
63+
response = sac_composite.create_stream_and_wait_for_state(
64+
stream_details, wait_for_states=[oci.streaming.models.StreamSummary.LIFECYCLE_STATE_ACTIVE])
65+
return response
66+
67+
68+
def get_stream(admin_client, stream_id):
69+
return admin_client.get_stream(stream_id)
70+
71+
72+
def delete_stream(client, stream_id):
73+
print (" Deleting Stream {}".format(stream_id))
74+
# Stream deletion is an asynchronous operation, give it some time to complete.
75+
client.delete_stream_and_wait_for_state(stream_id, oci.streaming.models.StreamSummary.LIFECYCLE_STATE_DELETED)
76+
77+
78+
def get_cursor_by_partition(client, stream_id, partition):
79+
print("Creating a cursor for partition {}".format(partition))
80+
cursor_details = oci.streaming.models.CreateCursorDetails(
81+
partition=partition,
82+
type=oci.streaming.models.CreateCursorDetails.TYPE_TRIM_HORIZON)
83+
response = client.create_cursor(stream_id, cursor_details)
84+
cursor = response.data.value
85+
return cursor
86+
87+
88+
def simple_message_loop(client, stream_id, initial_cursor):
89+
cursor = initial_cursor
90+
while True:
91+
get_response = client.get_messages(stream_id, cursor, limit=10)
92+
# No messages to process. return.
93+
if not get_response.data:
94+
return
95+
96+
# Process the messages
97+
print(" Read {} messages".format(len(get_response.data)))
98+
for message in get_response.data:
99+
print("{}: {}".format(base64.b64decode(message.key), base64.b64decode(message.value)))
100+
101+
# get_messages is a throttled method; clients should retrieve sufficiently large message
102+
# batches, as to avoid too many http requests.
103+
time.sleep(1)
104+
# use the next-cursor for iteration
105+
cursor = get_response.headers["opc-next-cursor"]
106+
107+
108+
def get_cursor_by_group(sc, sid, group_name, instance_name):
109+
print(" Creating a cursor for group {}, instance {}".format(group_name, instance_name))
110+
cursor_details = oci.streaming.models.CreateGroupCursorDetails(group_name=group_name, instance_name=instance_name,
111+
type=oci.streaming.models.
112+
CreateGroupCursorDetails.TYPE_TRIM_HORIZON,
113+
commit_on_get=True)
114+
response = sc.create_group_cursor(sid, cursor_details)
115+
return response.data.value
116+
117+
118+
# Load the default configuration
119+
config = oci.config.from_file()
120+
121+
# Create a StreamAdminClientCompositeOperations for composite operations.
122+
stream_admin_client = oci.streaming.StreamAdminClient(config)
123+
stream_admin_client_composite = oci.streaming.StreamAdminClientCompositeOperations(stream_admin_client)
124+
125+
if len(sys.argv) != 2:
126+
raise RuntimeError('This example expects an ocid for the compartment in which streams should be created.')
127+
128+
compartment = sys.argv[1]
129+
130+
# We will reuse a stream if its already created.
131+
# This will utilize list_streams() to determine if a stream exists and return it, or create a new one.
132+
stream = get_or_create_stream(stream_admin_client, compartment, STREAM_NAME,
133+
PARTITIONS, stream_admin_client_composite).data
134+
135+
print (" Created Stream {} with id : {}".format(stream.name, stream.id))
136+
137+
# Streams are assigned a specific endpoint url based on where they are provisioned.
138+
# Create a stream client using the provided message endpoint.
139+
stream_client = oci.streaming.StreamClient(config, service_endpoint=stream.messages_endpoint)
140+
s_id = stream.id
141+
142+
# Publish some messages to the stream
143+
publish_example_messages(stream_client, s_id)
144+
145+
# Use a cursor for getting messages; each get_messages call will return a next-cursor for iteration.
146+
# There are a couple kinds of cursors.
147+
# A cursor can be created at a given partition/offset.
148+
# This gives explicit offset management control to the consumer.
149+
150+
print("Starting a simple message loop with a partition cursor")
151+
partition_cursor = get_cursor_by_partition(stream_client, s_id, partition="0")
152+
simple_message_loop(stream_client, s_id, partition_cursor)
153+
154+
# A cursor can be created as part of a consumer group.
155+
# Committed offsets are managed for the group, and partitions
156+
# are dynamically balanced amongst consumers in the group.
157+
group_cursor = get_cursor_by_group(stream_client, s_id, "example-group", "example-instance-1")
158+
simple_message_loop(stream_client, s_id, group_cursor)
159+
160+
# Cleanup; remember to delete streams which are not in use.
161+
delete_stream(stream_admin_client_composite, s_id)

src/oci/announcements_service/announcement_client_composite_operations.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# coding: utf-8
22
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
33

4-
import oci # noqa: F401
4+
import oci # noqa: F401
5+
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401
56

67

78
class AnnouncementClientCompositeOperations(object):

src/oci/audit/audit_client_composite_operations.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# coding: utf-8
22
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
33

4-
import oci # noqa: F401
4+
import oci # noqa: F401
5+
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401
56

67

78
class AuditClientCompositeOperations(object):

src/oci/auth/federation_client.py

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -143,10 +143,7 @@ def _get_security_token_from_auth_service(self):
143143
fingerprint = crypto.load_certificate(crypto.FILETYPE_PEM, self.leaf_certificate_retriever.get_certificate_raw()).digest('sha1').decode('utf-8')
144144
signer = AuthTokenRequestSigner(self.tenancy_id, fingerprint, self.leaf_certificate_retriever)
145145

146-
if self.cert_bundle_verify:
147-
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, verify=self.cert_bundle_verify, timeout=(10, 60))
148-
else:
149-
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, timeout=(10, 60))
146+
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, verify=self.cert_bundle_verify, timeout=(10, 60))
150147

151148
parsed_response = None
152149
try:

src/oci/autoscaling/auto_scaling_client_composite_operations.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# coding: utf-8
22
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
33

4-
import oci # noqa: F401
4+
import oci # noqa: F401
5+
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401
56

67

78
class AutoScalingClientCompositeOperations(object):

src/oci/budget/budget_client_composite_operations.py

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# coding: utf-8
22
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
33

4-
import oci # noqa: F401
4+
import oci # noqa: F401
5+
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401
56

67

78
class BudgetClientCompositeOperations(object):
@@ -119,7 +120,15 @@ def delete_budget_and_wait_for_state(self, budget_id, wait_for_states=[], operat
119120
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
120121
"""
121122
initial_get_result = self.client.get_budget(budget_id)
122-
operation_result = self.client.delete_budget(budget_id, **operation_kwargs)
123+
operation_result = None
124+
try:
125+
operation_result = self.client.delete_budget(budget_id, **operation_kwargs)
126+
except oci.exceptions.ServiceError as e:
127+
if e.status == 404:
128+
return WAIT_RESOURCE_NOT_FOUND
129+
else:
130+
raise e
131+
123132
if not wait_for_states:
124133
return operation_result
125134

src/oci/container_engine/container_engine_client_composite_operations.py

Lines changed: 20 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# coding: utf-8
22
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.
33

4-
import oci # noqa: F401
4+
import oci # noqa: F401
5+
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401
56

67

78
class ContainerEngineClientCompositeOperations(object):
@@ -115,7 +116,15 @@ def delete_cluster_and_wait_for_state(self, cluster_id, wait_for_states=[], oper
115116
A dictionary of keyword arguments to pass to the :py:func:`oci.wait_until` function. For example, you could pass ``max_interval_seconds`` or ``max_interval_seconds``
116117
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
117118
"""
118-
operation_result = self.client.delete_cluster(cluster_id, **operation_kwargs)
119+
operation_result = None
120+
try:
121+
operation_result = self.client.delete_cluster(cluster_id, **operation_kwargs)
122+
except oci.exceptions.ServiceError as e:
123+
if e.status == 404:
124+
return WAIT_RESOURCE_NOT_FOUND
125+
else:
126+
raise e
127+
119128
if not wait_for_states:
120129
return operation_result
121130

@@ -153,7 +162,15 @@ def delete_node_pool_and_wait_for_state(self, node_pool_id, wait_for_states=[],
153162
A dictionary of keyword arguments to pass to the :py:func:`oci.wait_until` function. For example, you could pass ``max_interval_seconds`` or ``max_interval_seconds``
154163
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
155164
"""
156-
operation_result = self.client.delete_node_pool(node_pool_id, **operation_kwargs)
165+
operation_result = None
166+
try:
167+
operation_result = self.client.delete_node_pool(node_pool_id, **operation_kwargs)
168+
except oci.exceptions.ServiceError as e:
169+
if e.status == 404:
170+
return WAIT_RESOURCE_NOT_FOUND
171+
else:
172+
raise e
173+
157174
if not wait_for_states:
158175
return operation_result
159176

0 commit comments

Comments
 (0)