oci-radar 1.0.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- oci_radar-1.0.0/LICENSE +21 -0
- oci_radar-1.0.0/PKG-INFO +50 -0
- oci_radar-1.0.0/README.md +34 -0
- oci_radar-1.0.0/oci_radar/__init__.py +0 -0
- oci_radar-1.0.0/oci_radar/cli.py +23 -0
- oci_radar-1.0.0/oci_radar/diagram.py +74 -0
- oci_radar-1.0.0/oci_radar/inventory.py +88 -0
- oci_radar-1.0.0/oci_radar/operations.py +40 -0
- oci_radar-1.0.0/oci_radar.egg-info/PKG-INFO +50 -0
- oci_radar-1.0.0/oci_radar.egg-info/SOURCES.txt +15 -0
- oci_radar-1.0.0/oci_radar.egg-info/dependency_links.txt +1 -0
- oci_radar-1.0.0/oci_radar.egg-info/entry_points.txt +2 -0
- oci_radar-1.0.0/oci_radar.egg-info/requires.txt +2 -0
- oci_radar-1.0.0/oci_radar.egg-info/top_level.txt +3 -0
- oci_radar-1.0.0/pyproject.toml +28 -0
- oci_radar-1.0.0/setup.cfg +4 -0
- oci_radar-1.0.0/tests/test_placeholder.py +1 -0
oci_radar-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Mor Michaeli
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
oci_radar-1.0.0/PKG-INFO
ADDED
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oci-radar
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI tool for OCI services inventory and diagramming
|
|
5
|
+
Author: Mor Michaeli
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: typer
|
|
14
|
+
Requires-Dist: pandas
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# OCI Radar
|
|
18
|
+
|
|
19
|
+
CLI tool for Oracle Cloud Infrastructure (OCI) services inventory and diagramming.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Full run (inventory + diagram)
|
|
31
|
+
oci-radar run
|
|
32
|
+
|
|
33
|
+
# Inventory only
|
|
34
|
+
oci-radar inventory
|
|
35
|
+
|
|
36
|
+
# Diagram only (requires inventory CSV)
|
|
37
|
+
oci-radar diagram
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Prerequisites
|
|
41
|
+
|
|
42
|
+
- [OCI CLI](https://docs.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm) installed and configured (`oci setup config`)
|
|
43
|
+
- Set `OCI_COMPARTMENT_ID` env var, or the tool will resolve the root tenancy compartment automatically
|
|
44
|
+
|
|
45
|
+
## Outputs
|
|
46
|
+
|
|
47
|
+
| File | Description |
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `oci_inventory.csv` | All resources across the tenancy |
|
|
50
|
+
| `oci_diagram.drawio` | draw.io diagram grouped by service type |
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# OCI Radar
|
|
2
|
+
|
|
3
|
+
CLI tool for Oracle Cloud Infrastructure (OCI) services inventory and diagramming.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install -e .
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# Full run (inventory + diagram)
|
|
15
|
+
oci-radar run
|
|
16
|
+
|
|
17
|
+
# Inventory only
|
|
18
|
+
oci-radar inventory
|
|
19
|
+
|
|
20
|
+
# Diagram only (requires inventory CSV)
|
|
21
|
+
oci-radar diagram
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
## Prerequisites
|
|
25
|
+
|
|
26
|
+
- [OCI CLI](https://docs.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm) installed and configured (`oci setup config`)
|
|
27
|
+
- Set `OCI_COMPARTMENT_ID` env var, or the tool will resolve the root tenancy compartment automatically
|
|
28
|
+
|
|
29
|
+
## Outputs
|
|
30
|
+
|
|
31
|
+
| File | Description |
|
|
32
|
+
|------|-------------|
|
|
33
|
+
| `oci_inventory.csv` | All resources across the tenancy |
|
|
34
|
+
| `oci_diagram.drawio` | draw.io diagram grouped by service type |
|
|
File without changes
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import typer
|
|
2
|
+
|
|
3
|
+
from . import inventory as inv_mod, diagram as dia_mod, operations as ops_mod
|
|
4
|
+
|
|
5
|
+
app = typer.Typer()
|
|
6
|
+
|
|
7
|
+
@app.command()
|
|
8
|
+
def inventory():
|
|
9
|
+
"""Inventory OCI services"""
|
|
10
|
+
inv_mod.run_inventory()
|
|
11
|
+
|
|
12
|
+
@app.command()
|
|
13
|
+
def diagram():
|
|
14
|
+
"""Generate diagram of OCI services"""
|
|
15
|
+
dia_mod.generate_diagram()
|
|
16
|
+
|
|
17
|
+
@app.command()
|
|
18
|
+
def run():
|
|
19
|
+
"""Run operations on OCI services"""
|
|
20
|
+
ops_mod.run_operations()
|
|
21
|
+
|
|
22
|
+
def main():
|
|
23
|
+
app()
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import pandas as pd
|
|
2
|
+
|
|
3
|
+
def generate_diagram():
|
|
4
|
+
"""Generate draw.io diagram from OCI inventory"""
|
|
5
|
+
try:
|
|
6
|
+
try:
|
|
7
|
+
df = pd.read_csv('oci_inventory.csv')
|
|
8
|
+
except FileNotFoundError:
|
|
9
|
+
print("Inventory not found. Running inventory first...")
|
|
10
|
+
from . import inventory
|
|
11
|
+
inventory.run_inventory()
|
|
12
|
+
df = pd.read_csv('oci_inventory.csv')
|
|
13
|
+
|
|
14
|
+
service_counts = df['ServiceType'].value_counts().to_dict()
|
|
15
|
+
|
|
16
|
+
xml = generate_drawio_xml(service_counts)
|
|
17
|
+
|
|
18
|
+
with open('oci_diagram.drawio', 'w') as f:
|
|
19
|
+
f.write(xml)
|
|
20
|
+
|
|
21
|
+
print("Diagram saved to oci_diagram.drawio")
|
|
22
|
+
return True
|
|
23
|
+
|
|
24
|
+
except Exception as e:
|
|
25
|
+
print(f"Error generating diagram: {e}")
|
|
26
|
+
return False
|
|
27
|
+
|
|
28
|
+
def generate_drawio_xml(service_counts):
|
|
29
|
+
"""Generate draw.io XML with OCI services"""
|
|
30
|
+
xml = '''<?xml version="1.0" encoding="UTF-8"?>
|
|
31
|
+
<mxfile host="app.diagrams.net" modified="2026-05-26T00:00:00.000Z" agent="oci-radar" version="15.8.7" type="device">
|
|
32
|
+
<diagram id="diagram1" name="OCI Services">
|
|
33
|
+
<mxGraphModel dx="1200" dy="800" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1100" pageHeight="850" math="0" shadow="0">
|
|
34
|
+
<root>
|
|
35
|
+
<mxCell id="0"/>
|
|
36
|
+
<mxCell id="1" parent="0"/>
|
|
37
|
+
<mxCell id="title" value="OCI Services Inventory" style="text;html=1;fontSize=18;fontStyle=1;verticalAlign=middle;" vertex="1" parent="1">
|
|
38
|
+
<mxGeometry x="400" y="20" width="300" height="40" as="geometry"/>
|
|
39
|
+
</mxCell>
|
|
40
|
+
'''
|
|
41
|
+
|
|
42
|
+
y = 100
|
|
43
|
+
colors = {
|
|
44
|
+
'Compute Instances': '#FF6B6B',
|
|
45
|
+
'DB Systems': '#4ECDC4',
|
|
46
|
+
'Autonomous DB': '#45B7D1',
|
|
47
|
+
'Functions': '#96CEB4',
|
|
48
|
+
'OKE': '#FFEAA7',
|
|
49
|
+
'Object Storage': '#DDA0DD',
|
|
50
|
+
'Container Instances': '#F8B88B',
|
|
51
|
+
'Streaming': '#B4A7D6',
|
|
52
|
+
'Data Science': '#A8E6CF',
|
|
53
|
+
'Load Balancers': '#FFD3A5',
|
|
54
|
+
'VCN': '#C3E6CB',
|
|
55
|
+
'API Gateway': '#FFC0CB',
|
|
56
|
+
'Vault Secrets': '#E2C9F5',
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
for service_type, count in sorted(service_counts.items()):
|
|
60
|
+
color = colors.get(service_type, '#CCCCCC')
|
|
61
|
+
safe_id = service_type.replace(' ', '_').replace('/', '_')
|
|
62
|
+
|
|
63
|
+
xml += f''' <mxCell id="service_{safe_id}" value="{service_type}
({count} resources)" style="rounded=1;whiteSpace=wrap;html=1;fillColor={color};fontSize=12;fontStyle=1;" vertex="1" parent="1">
|
|
64
|
+
<mxGeometry x="50" y="{y}" width="200" height="60" as="geometry"/>
|
|
65
|
+
</mxCell>
|
|
66
|
+
'''
|
|
67
|
+
y += 80
|
|
68
|
+
|
|
69
|
+
xml += ''' </root>
|
|
70
|
+
</mxGraphModel>
|
|
71
|
+
</diagram>
|
|
72
|
+
</mxfile>'''
|
|
73
|
+
|
|
74
|
+
return xml
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import subprocess
|
|
3
|
+
import os
|
|
4
|
+
import pandas as pd
|
|
5
|
+
|
|
6
|
+
def run_inventory():
|
|
7
|
+
"""Run inventory using OCI CLI"""
|
|
8
|
+
try:
|
|
9
|
+
compartment_id = os.getenv('OCI_COMPARTMENT_ID')
|
|
10
|
+
if not compartment_id:
|
|
11
|
+
result = subprocess.run(
|
|
12
|
+
['oci', 'iam', 'compartment', 'list', '--include-root', '--all',
|
|
13
|
+
'--query', 'data[?contains(id,`tenancy`)].id | [0]', '--raw-output'],
|
|
14
|
+
capture_output=True,
|
|
15
|
+
text=True,
|
|
16
|
+
check=True
|
|
17
|
+
)
|
|
18
|
+
compartment_id = result.stdout.strip()
|
|
19
|
+
|
|
20
|
+
if not compartment_id:
|
|
21
|
+
print("Error: Could not determine compartment ID. Set OCI_COMPARTMENT_ID or run 'oci setup config'")
|
|
22
|
+
return
|
|
23
|
+
|
|
24
|
+
print(f"Using compartment: {compartment_id}")
|
|
25
|
+
|
|
26
|
+
result = subprocess.run(
|
|
27
|
+
[
|
|
28
|
+
'oci', 'search', 'resource', 'structured-search',
|
|
29
|
+
'--query-text', 'query all resources',
|
|
30
|
+
'--limit', '1000',
|
|
31
|
+
'--query', 'data.items[*].{name:displayName,type:resourceType,compartmentId:compartmentId,state:lifecycleState,region:identifier}',
|
|
32
|
+
'--output', 'json',
|
|
33
|
+
],
|
|
34
|
+
capture_output=True,
|
|
35
|
+
text=True,
|
|
36
|
+
check=True
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
raw = json.loads(result.stdout)
|
|
40
|
+
items = raw if isinstance(raw, list) else raw.get('data', raw)
|
|
41
|
+
|
|
42
|
+
resources = []
|
|
43
|
+
for item in items:
|
|
44
|
+
res_type = item.get('type', '')
|
|
45
|
+
resources.append({
|
|
46
|
+
'Name': item.get('name', ''),
|
|
47
|
+
'Type': res_type,
|
|
48
|
+
'ServiceType': normalize_service_type(res_type),
|
|
49
|
+
'CompartmentId': item.get('compartmentId', ''),
|
|
50
|
+
'State': item.get('state', ''),
|
|
51
|
+
'Region': item.get('region', ''),
|
|
52
|
+
})
|
|
53
|
+
|
|
54
|
+
df = pd.DataFrame(resources)
|
|
55
|
+
df.to_csv('oci_inventory.csv', index=False)
|
|
56
|
+
print(f"Inventory saved to oci_inventory.csv ({len(resources)} resources)")
|
|
57
|
+
|
|
58
|
+
except subprocess.CalledProcessError as e:
|
|
59
|
+
print(f"Error running OCI CLI: {e.stderr}")
|
|
60
|
+
return
|
|
61
|
+
except FileNotFoundError:
|
|
62
|
+
print("Error: OCI CLI not found. Please install it: https://docs.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm")
|
|
63
|
+
return
|
|
64
|
+
|
|
65
|
+
def normalize_service_type(resource_type):
|
|
66
|
+
"""Map OCI resource types to friendly service names"""
|
|
67
|
+
mappings = {
|
|
68
|
+
'Instance': 'Compute Instances',
|
|
69
|
+
'DbSystem': 'DB Systems',
|
|
70
|
+
'AutonomousDatabase': 'Autonomous DB',
|
|
71
|
+
'FunctionsApplication': 'Functions',
|
|
72
|
+
'Cluster': 'OKE',
|
|
73
|
+
'Bucket': 'Object Storage',
|
|
74
|
+
'ContainerInstance': 'Container Instances',
|
|
75
|
+
'Stream': 'Streaming',
|
|
76
|
+
'DataScienceProject': 'Data Science',
|
|
77
|
+
'LoadBalancer': 'Load Balancers',
|
|
78
|
+
'Vcn': 'VCN',
|
|
79
|
+
'Subnet': 'Subnets',
|
|
80
|
+
'SecurityList': 'Security Lists',
|
|
81
|
+
'InternetGateway': 'Internet Gateways',
|
|
82
|
+
'NatGateway': 'NAT Gateways',
|
|
83
|
+
'ServiceGateway': 'Service Gateways',
|
|
84
|
+
'ApiGateway': 'API Gateway',
|
|
85
|
+
'VaultSecret': 'Vault Secrets',
|
|
86
|
+
'Key': 'Keys',
|
|
87
|
+
}
|
|
88
|
+
return mappings.get(resource_type, resource_type)
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import subprocess
|
|
2
|
+
from . import inventory, diagram
|
|
3
|
+
|
|
4
|
+
def run_operations():
|
|
5
|
+
"""Run full operations: inventory and diagram using OCI CLI"""
|
|
6
|
+
print("=== OCI Radar ===\n")
|
|
7
|
+
|
|
8
|
+
try:
|
|
9
|
+
result = subprocess.run(['oci', '--version'], capture_output=True, text=True)
|
|
10
|
+
if result.returncode != 0:
|
|
11
|
+
raise FileNotFoundError()
|
|
12
|
+
print("✓ OCI CLI found\n")
|
|
13
|
+
except FileNotFoundError:
|
|
14
|
+
print("✗ Error: OCI CLI not found")
|
|
15
|
+
print(" Install: https://docs.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm")
|
|
16
|
+
return False
|
|
17
|
+
|
|
18
|
+
try:
|
|
19
|
+
subprocess.run(
|
|
20
|
+
['oci', 'iam', 'compartment', 'list', '--include-root', '--limit', '1'],
|
|
21
|
+
capture_output=True,
|
|
22
|
+
text=True,
|
|
23
|
+
check=True
|
|
24
|
+
)
|
|
25
|
+
print("✓ OCI authentication valid\n")
|
|
26
|
+
except subprocess.CalledProcessError:
|
|
27
|
+
print("✗ Error: Not authenticated to OCI")
|
|
28
|
+
print(" Run: oci setup config")
|
|
29
|
+
return False
|
|
30
|
+
|
|
31
|
+
print("--- Running Inventory ---")
|
|
32
|
+
inventory.run_inventory()
|
|
33
|
+
print()
|
|
34
|
+
|
|
35
|
+
print("--- Generating Diagram ---")
|
|
36
|
+
diagram.generate_diagram()
|
|
37
|
+
print()
|
|
38
|
+
|
|
39
|
+
print("✓ Operations completed successfully")
|
|
40
|
+
return True
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: oci-radar
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: CLI tool for OCI services inventory and diagramming
|
|
5
|
+
Author: Mor Michaeli
|
|
6
|
+
License-Expression: MIT
|
|
7
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
8
|
+
Classifier: Programming Language :: Python :: 3
|
|
9
|
+
Classifier: Operating System :: OS Independent
|
|
10
|
+
Requires-Python: >=3.8
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Requires-Dist: typer
|
|
14
|
+
Requires-Dist: pandas
|
|
15
|
+
Dynamic: license-file
|
|
16
|
+
|
|
17
|
+
# OCI Radar
|
|
18
|
+
|
|
19
|
+
CLI tool for Oracle Cloud Infrastructure (OCI) services inventory and diagramming.
|
|
20
|
+
|
|
21
|
+
## Installation
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
pip install -e .
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```bash
|
|
30
|
+
# Full run (inventory + diagram)
|
|
31
|
+
oci-radar run
|
|
32
|
+
|
|
33
|
+
# Inventory only
|
|
34
|
+
oci-radar inventory
|
|
35
|
+
|
|
36
|
+
# Diagram only (requires inventory CSV)
|
|
37
|
+
oci-radar diagram
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Prerequisites
|
|
41
|
+
|
|
42
|
+
- [OCI CLI](https://docs.oracle.com/iaas/Content/API/SDKDocs/cliinstall.htm) installed and configured (`oci setup config`)
|
|
43
|
+
- Set `OCI_COMPARTMENT_ID` env var, or the tool will resolve the root tenancy compartment automatically
|
|
44
|
+
|
|
45
|
+
## Outputs
|
|
46
|
+
|
|
47
|
+
| File | Description |
|
|
48
|
+
|------|-------------|
|
|
49
|
+
| `oci_inventory.csv` | All resources across the tenancy |
|
|
50
|
+
| `oci_diagram.drawio` | draw.io diagram grouped by service type |
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
LICENSE
|
|
2
|
+
README.md
|
|
3
|
+
pyproject.toml
|
|
4
|
+
oci_radar/__init__.py
|
|
5
|
+
oci_radar/cli.py
|
|
6
|
+
oci_radar/diagram.py
|
|
7
|
+
oci_radar/inventory.py
|
|
8
|
+
oci_radar/operations.py
|
|
9
|
+
oci_radar.egg-info/PKG-INFO
|
|
10
|
+
oci_radar.egg-info/SOURCES.txt
|
|
11
|
+
oci_radar.egg-info/dependency_links.txt
|
|
12
|
+
oci_radar.egg-info/entry_points.txt
|
|
13
|
+
oci_radar.egg-info/requires.txt
|
|
14
|
+
oci_radar.egg-info/top_level.txt
|
|
15
|
+
tests/test_placeholder.py
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "oci-radar"
|
|
7
|
+
version = "1.0.0"
|
|
8
|
+
description = "CLI tool for OCI services inventory and diagramming"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.8"
|
|
11
|
+
authors = [{name = "Mor Michaeli"}]
|
|
12
|
+
license = "MIT"
|
|
13
|
+
license-files = ["LICENSE"]
|
|
14
|
+
classifiers = [
|
|
15
|
+
"Development Status :: 5 - Production/Stable",
|
|
16
|
+
"Programming Language :: Python :: 3",
|
|
17
|
+
"Operating System :: OS Independent",
|
|
18
|
+
]
|
|
19
|
+
dependencies = [
|
|
20
|
+
"typer",
|
|
21
|
+
"pandas",
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
[project.scripts]
|
|
25
|
+
oci-radar = "oci_radar.cli:main"
|
|
26
|
+
|
|
27
|
+
[tool.setuptools.packages.find]
|
|
28
|
+
where = ["."]
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
# Placeholder for tests
|