Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions CHANGELOG.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,36 @@ All notable changes to this project will be documented in this file.

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

3.89.3 - 2026-07-21
-------------------
Added
~~~~~
* Analytics service

* Support for Analytics Instance Resource Groups for Oracle Analytics Cloud (OAC)

* ``oci analytics analytics-instance create-resource-group``
* ``oci analytics analytics-instance delete-resource-group``
* ``oci analytics analytics-instance get-resource-group``
* ``oci analytics analytics-instance list-resource-groups``
* ``oci analytics analytics-instance update-resource-group``

* Networking service

* Support for new optional parameter for multiple FastConnect enhancements

* ``oci network cross-connect create --interface-down-timer-value-in-milliseconds --is-interface-hold-timer-enabled --is-qos-enabled``
* ``oci network cross-connect update --interface-down-timer-value-in-milliseconds --is-interface-hold-timer-enabled``
* ``oci network cross-connect-group create --interface-down-timer-value-in-milliseconds --is-interface-hold-timer-enabled --is-qos-enabled --minimum-links``
* ``oci network cross-connect-group update --interface-down-timer-value-in-milliseconds --is-interface-hold-timer-enabled --minimum-links``
* ``oci network virtual-circuit create --traffic-mode``
* ``oci network virtual-circuit update --traffic-mode``

* Support for getting and updating a Letter of Authority for a cross-connect

* ``oci network letter-of-authority update-cross-connect``
* ``oci network letter-of-authority get-cross-connect``

3.89.2 - 2026-07-14
-------------------
Added
Expand Down
2 changes: 1 addition & 1 deletion requirements.txt
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ Jinja2>=3.1.5,<4.0.0; python_version >= '3.7'
jmespath>=0.10.0,<=1.0.1
ndg-httpsclient==0.4.2
mock==2.0.0
oci==2.182.0
oci==2.182.1
packaging>=22.0,<25.0; python_version > '3.8'
packaging==20.2; python_version <= '3.8'
pluggy==0.13.0; python_version < '3.9'
Expand Down
480 changes: 387 additions & 93 deletions services/analytics/src/oci_cli_analytics/generated/analytics_cli.py

Large diffs are not rendered by default.

5 changes: 5 additions & 0 deletions services/analytics/tests/util/generated/command_to_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,15 +6,19 @@
"analytics.change_analytics_instance_network_endpoint": "oci.analytics.AnalyticsClient.change_analytics_instance_network_endpoint",
"analytics.create_analytics_instance": "oci.analytics.AnalyticsClient.create_analytics_instance",
"analytics.create_private_access_channel": "oci.analytics.AnalyticsClient.create_private_access_channel",
"analytics.create_resource_group": "oci.analytics.AnalyticsClient.create_resource_group",
"analytics.create_vanity_url": "oci.analytics.AnalyticsClient.create_vanity_url",
"analytics.delete_analytics_instance": "oci.analytics.AnalyticsClient.delete_analytics_instance",
"analytics.delete_private_access_channel": "oci.analytics.AnalyticsClient.delete_private_access_channel",
"analytics.delete_resource_group": "oci.analytics.AnalyticsClient.delete_resource_group",
"analytics.delete_vanity_url": "oci.analytics.AnalyticsClient.delete_vanity_url",
"analytics.delete_work_request": "oci.analytics.AnalyticsClient.delete_work_request",
"analytics.get_analytics_instance": "oci.analytics.AnalyticsClient.get_analytics_instance",
"analytics.get_private_access_channel": "oci.analytics.AnalyticsClient.get_private_access_channel",
"analytics.get_resource_group": "oci.analytics.AnalyticsClient.get_resource_group",
"analytics.get_work_request": "oci.analytics.AnalyticsClient.get_work_request",
"analytics.list_analytics_instances": "oci.analytics.AnalyticsClient.list_analytics_instances",
"analytics.list_resource_groups": "oci.analytics.AnalyticsClient.list_resource_groups",
"analytics.list_work_request_errors": "oci.analytics.AnalyticsClient.list_work_request_errors",
"analytics.list_work_request_logs": "oci.analytics.AnalyticsClient.list_work_request_logs",
"analytics.list_work_requests": "oci.analytics.AnalyticsClient.list_work_requests",
Expand All @@ -25,5 +29,6 @@
"analytics.stop_analytics_instance": "oci.analytics.AnalyticsClient.stop_analytics_instance",
"analytics.update_analytics_instance": "oci.analytics.AnalyticsClient.update_analytics_instance",
"analytics.update_private_access_channel": "oci.analytics.AnalyticsClient.update_private_access_channel",
"analytics.update_resource_group": "oci.analytics.AnalyticsClient.update_resource_group",
"analytics.update_vanity_url": "oci.analytics.AnalyticsClient.update_vanity_url",
}

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@

virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.ip_sec_connection_device_config_group.name)
virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.ip_sec_connection_device_status_group.name)
virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.letter_of_authority_group.name)
# to expose GET/UPDATE operations on LOA through oci-cli
# virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.letter_of_authority_group.name)
virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.virtual_circuit_bandwidth_shape_group.name)
virtualnetwork_cli.virtual_network_root_group.commands.pop(virtualnetwork_cli.peer_region_for_remote_peering_group.name)

Expand Down
1 change: 1 addition & 0 deletions services/core/tests/util/generated/command_to_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -239,6 +239,7 @@
"virtual_network.update_cpe": "oci.core.VirtualNetworkClient.update_cpe",
"virtual_network.update_cross_connect": "oci.core.VirtualNetworkClient.update_cross_connect",
"virtual_network.update_cross_connect_group": "oci.core.VirtualNetworkClient.update_cross_connect_group",
"virtual_network.update_cross_connect_letter_of_authority": "oci.core.VirtualNetworkClient.update_cross_connect_letter_of_authority",
"virtual_network.update_dhcp_options": "oci.core.VirtualNetworkClient.update_dhcp_options",
"virtual_network.update_drg": "oci.core.VirtualNetworkClient.update_drg",
"virtual_network.update_drg_attachment": "oci.core.VirtualNetworkClient.update_drg_attachment",
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ def open_relative(*path):
readme = f.read()

requires = [
'oci==2.182.0',
'oci==2.182.1',
'arrow>=1.0.0,<2.0.0',
'certifi>=2025.1.31,<2026.0.0',
'click<=8.1.2',
Expand Down
12 changes: 11 additions & 1 deletion src/oci_cli/cli_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -730,7 +730,17 @@ def render_response(response, ctx):
last_event_time = time.time()
try:
for event in response.data.events():
render(json.loads(event.data), response.headers, ctx)
event_data = event.data.strip()
if not event_data:
# event.data is not expected to be None, however, if the data is only whitespace characters, then,
# event.data.strip() can be None. For such cases we simply skip printing/rendering it.
continue
try:
render(json.loads(event_data), response.headers, ctx)
except json.decoder.JSONDecodeError:
# If text/event-stream is set, it doesn't guarantee the payload in event.data is JSON, it could be
# arbitrary text.
print(pretty_print_format(event_data))
elapsed_time = time.time() - last_event_time
if elapsed_time > event_read_timeout:
raise TimeoutError
Expand Down
2 changes: 1 addition & 1 deletion src/oci_cli/version.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
# Copyright (c) 2016, 2026, Oracle and/or its affiliates. All rights reserved.
# This software is dual-licensed to you under the Universal Permissive License (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl or Apache License 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose either license.

__version__ = '3.89.2'
__version__ = '3.89.3'
59 changes: 59 additions & 0 deletions tests/unit/test_cli_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,19 @@ def build_config(ctx):
return Mock.expected_result


class MockSseEvent(object):
def __init__(self, data):
self.data = data


class MockSseStream(object):
def __init__(self, events):
self._events = events

def events(self):
return iter(self._events)


class TestCliUtil(unittest.TestCase):

@staticmethod
Expand All @@ -52,6 +65,14 @@ def _build_paginated_response(data, has_next_page=False, next_page=None):
response.next_page = next_page
return response

@staticmethod
def _build_sse_response(event_payloads):
response = Obj()
response.status = 200
response.headers = {'content-type': 'text/event-stream'}
response.data = MockSseStream([MockSseEvent(payload) for payload in event_payloads])
return response

def test_iam_coalesce_provided_and_default_value(self):
ctx = Obj()
ctx.obj = Obj()
Expand Down Expand Up @@ -226,3 +247,41 @@ def test_list_call_get_all_results_multiple_keys_stream_output_does_not_swallow_
ctx=ctx,
stream_output=True
)

def test_render_response_outputs_non_json_sse_event_without_crashing(self):
ctx = self._build_ctx()
ctx.obj['output'] = 'json'
ctx.obj['raw_output'] = None
response = self._build_sse_response([
'{"index": 0, "message": {"role": "ASSISTANT"}}',
'{"usage": {"completionTokens": 8, "promptTokens": 4, "totalTokens": 12}}',
'[DONE]'
])

with mock.patch('oci_cli.cli_util.render') as mock_render:
with mock.patch('oci_cli.cli_util.print') as mock_print:
cli_util.render_response(response, ctx)

self.assertEqual(2, mock_render.call_count)
self.assertEqual(1, mock_print.call_count)
mock_print.assert_called_once_with('"[DONE]"')

def test_render_response_skips_empty_or_whitespace_only_sse_events(self):
ctx = self._build_ctx()
ctx.obj['output'] = 'json'
ctx.obj['raw_output'] = None
response = self._build_sse_response([
'{"index": 0, "message": {"role": "ASSISTANT"}}',
'{"usage": {"completionTokens": 8, "promptTokens": 4, "totalTokens": 12}}',
' ',
'\n\t\t',
' [DONE] \t'
])

with mock.patch('oci_cli.cli_util.render') as mock_render:
with mock.patch('oci_cli.cli_util.print') as mock_print:
cli_util.render_response(response, ctx)

self.assertEqual(2, mock_render.call_count)
self.assertEqual(1, mock_print.call_count)
mock_print.assert_called_once_with('"[DONE]"')