Skip to content

Commit

Permalink
Releasing version 2.2.5
Browse files Browse the repository at this point in the history
Releasing version 2.2.5
  • Loading branch information
dshelbyo authored Apr 2, 2019
2 parents dc61e22 + 4a5136d commit 5b40e1a
Show file tree
Hide file tree
Showing 71 changed files with 1,666 additions and 213 deletions.
10 changes: 10 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ All notable changes to this project will be documented in this file.

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

====================
2.2.5 - 2019-04-02
====================

Added
-----
* Support for provider service key names on virtual circuits in the FastConnect service
* Support for customer reference names on cross connects and cross connect groups in the FastConnect service
* 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>`__.

====================
2.2.4 - 2019-03-26
====================
Expand Down
1 change: 1 addition & 0 deletions docs/api/core.rst
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,7 @@ Core Services
oci.core.models.ExportImageViaObjectStorageTupleDetails
oci.core.models.ExportImageViaObjectStorageUriDetails
oci.core.models.FastConnectProviderService
oci.core.models.FastConnectProviderServiceKey
oci.core.models.GetPublicIpByIpAddressDetails
oci.core.models.GetPublicIpByPrivateIpIdDetails
oci.core.models.IPSecConnection
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
FastConnectProviderServiceKey
=============================

.. currentmodule:: oci.core.models

.. autoclass:: FastConnectProviderServiceKey
:show-inheritance:
:special-members: __init__
:members:
:undoc-members:
:inherited-members:
161 changes: 161 additions & 0 deletions examples/stream_example.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
import oci
import sys
import base64
import time

# ==========================================================
# This file provides an example of basic streaming usage
# * - List streams
# * - Get a Stream
# * - Create a Stream
# * - Delete a Stream
# * - Publish to a Stream
# * - Consume from a stream partition using cursor
# * - Consume from a stream using a group cursor
# Documentation : https://docs.cloud.oracle.com/iaas/Content/Streaming/Concepts/streamingoverview.htm

# Usage : python stream_example.py <compartment id>

STREAM_NAME = "SdkExampleStream"
PARTITIONS = 1


def publish_example_messages(client, stream_id):
# Build up a PutMessagesDetails and publish some messages to the stream
message_list = []
for i in range(100):
key = "key" + str(i)
value = "value" + str(i)
encoded_key = base64.b64encode(key)
encoded_value = base64.b64encode(value)
message_list.append(oci.streaming.models.PutMessagesDetailsEntry(key=encoded_key, value=encoded_value))

print ("Publishing {} messages to the stream {} ".format(len(message_list), stream_id))
messages = oci.streaming.models.PutMessagesDetails(messages=message_list)
put_message_result = client.put_messages(stream_id, messages)

# The put_message_result can contain some useful metadata for handling failures
for entry in put_message_result.data.entries:
if entry.error:
print ("Error ({}) : {}".format(entry.error, entry.error_message))
else:
print ("Published message to partition {} , offset {}".format(entry.partition, entry.offset))


def get_or_create_stream(client, compartment_id, stream_name, partition, sac_composite):

list_streams = client.list_streams(compartment_id, name=stream_name,
lifecycle_state=oci.streaming.models.StreamSummary.LIFECYCLE_STATE_ACTIVE)
if list_streams.data:
# If we find an active stream with the correct name, we'll use it.
print ("An active stream {} has been found".format(stream_name))
sid = list_streams.data[0].id
return get_stream(sac_composite.client, sid)

print (" No Active stream {} has been found; Creating it now. ".format(stream_name))
print (" Creating stream {} with {} partitions.".format(stream_name, partition))

# Create stream_details object that need to be passed while creating stream.
stream_details = oci.streaming.models.CreateStreamDetails(name=stream_name, partitions=partition,
compartment_id=compartment, retention_in_hours=24)

# Since stream creation is asynchronous; we need to wait for the stream to become active.
response = sac_composite.create_stream_and_wait_for_state(
stream_details, wait_for_states=[oci.streaming.models.StreamSummary.LIFECYCLE_STATE_ACTIVE])
return response


def get_stream(admin_client, stream_id):
return admin_client.get_stream(stream_id)


def delete_stream(client, stream_id):
print (" Deleting Stream {}".format(stream_id))
# Stream deletion is an asynchronous operation, give it some time to complete.
client.delete_stream_and_wait_for_state(stream_id, oci.streaming.models.StreamSummary.LIFECYCLE_STATE_DELETED)


def get_cursor_by_partition(client, stream_id, partition):
print("Creating a cursor for partition {}".format(partition))
cursor_details = oci.streaming.models.CreateCursorDetails(
partition=partition,
type=oci.streaming.models.CreateCursorDetails.TYPE_TRIM_HORIZON)
response = client.create_cursor(stream_id, cursor_details)
cursor = response.data.value
return cursor


def simple_message_loop(client, stream_id, initial_cursor):
cursor = initial_cursor
while True:
get_response = client.get_messages(stream_id, cursor, limit=10)
# No messages to process. return.
if not get_response.data:
return

# Process the messages
print(" Read {} messages".format(len(get_response.data)))
for message in get_response.data:
print("{}: {}".format(base64.b64decode(message.key), base64.b64decode(message.value)))

# get_messages is a throttled method; clients should retrieve sufficiently large message
# batches, as to avoid too many http requests.
time.sleep(1)
# use the next-cursor for iteration
cursor = get_response.headers["opc-next-cursor"]


def get_cursor_by_group(sc, sid, group_name, instance_name):
print(" Creating a cursor for group {}, instance {}".format(group_name, instance_name))
cursor_details = oci.streaming.models.CreateGroupCursorDetails(group_name=group_name, instance_name=instance_name,
type=oci.streaming.models.
CreateGroupCursorDetails.TYPE_TRIM_HORIZON,
commit_on_get=True)
response = sc.create_group_cursor(sid, cursor_details)
return response.data.value


# Load the default configuration
config = oci.config.from_file()

# Create a StreamAdminClientCompositeOperations for composite operations.
stream_admin_client = oci.streaming.StreamAdminClient(config)
stream_admin_client_composite = oci.streaming.StreamAdminClientCompositeOperations(stream_admin_client)

if len(sys.argv) != 2:
raise RuntimeError('This example expects an ocid for the compartment in which streams should be created.')

compartment = sys.argv[1]

# We will reuse a stream if its already created.
# This will utilize list_streams() to determine if a stream exists and return it, or create a new one.
stream = get_or_create_stream(stream_admin_client, compartment, STREAM_NAME,
PARTITIONS, stream_admin_client_composite).data

print (" Created Stream {} with id : {}".format(stream.name, stream.id))

# Streams are assigned a specific endpoint url based on where they are provisioned.
# Create a stream client using the provided message endpoint.
stream_client = oci.streaming.StreamClient(config, service_endpoint=stream.messages_endpoint)
s_id = stream.id

# Publish some messages to the stream
publish_example_messages(stream_client, s_id)

# Use a cursor for getting messages; each get_messages call will return a next-cursor for iteration.
# There are a couple kinds of cursors.
# A cursor can be created at a given partition/offset.
# This gives explicit offset management control to the consumer.

print("Starting a simple message loop with a partition cursor")
partition_cursor = get_cursor_by_partition(stream_client, s_id, partition="0")
simple_message_loop(stream_client, s_id, partition_cursor)

# A cursor can be created as part of a consumer group.
# Committed offsets are managed for the group, and partitions
# are dynamically balanced amongst consumers in the group.
group_cursor = get_cursor_by_group(stream_client, s_id, "example-group", "example-instance-1")
simple_message_loop(stream_client, s_id, group_cursor)

# Cleanup; remember to delete streams which are not in use.
delete_stream(stream_admin_client_composite, s_id)
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

import oci # noqa: F401
import oci # noqa: F401
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401


class AnnouncementClientCompositeOperations(object):
Expand Down
3 changes: 2 additions & 1 deletion src/oci/audit/audit_client_composite_operations.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

import oci # noqa: F401
import oci # noqa: F401
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401


class AuditClientCompositeOperations(object):
Expand Down
5 changes: 1 addition & 4 deletions src/oci/auth/federation_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,7 @@ def _get_security_token_from_auth_service(self):
fingerprint = crypto.load_certificate(crypto.FILETYPE_PEM, self.leaf_certificate_retriever.get_certificate_raw()).digest('sha1').decode('utf-8')
signer = AuthTokenRequestSigner(self.tenancy_id, fingerprint, self.leaf_certificate_retriever)

if self.cert_bundle_verify:
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, verify=self.cert_bundle_verify, timeout=(10, 60))
else:
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, timeout=(10, 60))
response = self.requests_session.post(self.federation_endpoint, json=request_payload, auth=signer, verify=self.cert_bundle_verify, timeout=(10, 60))

parsed_response = None
try:
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

import oci # noqa: F401
import oci # noqa: F401
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401


class AutoScalingClientCompositeOperations(object):
Expand Down
13 changes: 11 additions & 2 deletions src/oci/budget/budget_client_composite_operations.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

import oci # noqa: F401
import oci # noqa: F401
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401


class BudgetClientCompositeOperations(object):
Expand Down Expand Up @@ -119,7 +120,15 @@ def delete_budget_and_wait_for_state(self, budget_id, wait_for_states=[], operat
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
"""
initial_get_result = self.client.get_budget(budget_id)
operation_result = self.client.delete_budget(budget_id, **operation_kwargs)
operation_result = None
try:
operation_result = self.client.delete_budget(budget_id, **operation_kwargs)
except oci.exceptions.ServiceError as e:
if e.status == 404:
return WAIT_RESOURCE_NOT_FOUND
else:
raise e

if not wait_for_states:
return operation_result

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
# coding: utf-8
# Copyright (c) 2016, 2019, Oracle and/or its affiliates. All rights reserved.

import oci # noqa: F401
import oci # noqa: F401
from oci.util import WAIT_RESOURCE_NOT_FOUND # noqa: F401


class ContainerEngineClientCompositeOperations(object):
Expand Down Expand Up @@ -115,7 +116,15 @@ def delete_cluster_and_wait_for_state(self, cluster_id, wait_for_states=[], oper
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``
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
"""
operation_result = self.client.delete_cluster(cluster_id, **operation_kwargs)
operation_result = None
try:
operation_result = self.client.delete_cluster(cluster_id, **operation_kwargs)
except oci.exceptions.ServiceError as e:
if e.status == 404:
return WAIT_RESOURCE_NOT_FOUND
else:
raise e

if not wait_for_states:
return operation_result

Expand Down Expand Up @@ -153,7 +162,15 @@ def delete_node_pool_and_wait_for_state(self, node_pool_id, wait_for_states=[],
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``
as dictionary keys to modify how long the waiter function will wait between retries and the maximum amount of time it will wait
"""
operation_result = self.client.delete_node_pool(node_pool_id, **operation_kwargs)
operation_result = None
try:
operation_result = self.client.delete_node_pool(node_pool_id, **operation_kwargs)
except oci.exceptions.ServiceError as e:
if e.status == 404:
return WAIT_RESOURCE_NOT_FOUND
else:
raise e

if not wait_for_states:
return operation_result

Expand Down
Loading

0 comments on commit 5b40e1a

Please sign in to comment.