aws-cost-calculator-cli 1.5.1__tar.gz → 1.5.3__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.
Potentially problematic release.
This version of aws-cost-calculator-cli might be problematic. Click here for more details.
- {aws_cost_calculator_cli-1.5.1/aws_cost_calculator_cli.egg-info → aws_cost_calculator_cli-1.5.3}/PKG-INFO +1 -1
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3/aws_cost_calculator_cli.egg-info}/PKG-INFO +1 -1
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/cli.py +73 -30
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/executor.py +22 -11
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/setup.py +1 -1
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/COST_CALCULATION_METHODOLOGY.md +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/LICENSE +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/MANIFEST.in +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/README.md +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/aws_cost_calculator_cli.egg-info/SOURCES.txt +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/aws_cost_calculator_cli.egg-info/dependency_links.txt +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/aws_cost_calculator_cli.egg-info/entry_points.txt +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/aws_cost_calculator_cli.egg-info/requires.txt +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/aws_cost_calculator_cli.egg-info/top_level.txt +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/__init__.py +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/api_client.py +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/drill.py +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/monthly.py +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/trends.py +0 -0
- {aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-cost-calculator-cli
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.3
|
|
4
4
|
Summary: AWS Cost Calculator CLI - Calculate daily and annual AWS costs across multiple accounts
|
|
5
5
|
Home-page: https://github.com/yourusername/cost-calculator
|
|
6
6
|
Author: Cost Optimization Team
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aws-cost-calculator-cli
|
|
3
|
-
Version: 1.5.
|
|
3
|
+
Version: 1.5.3
|
|
4
4
|
Summary: AWS Cost Calculator CLI - Calculate daily and annual AWS costs across multiple accounts
|
|
5
5
|
Home-page: https://github.com/yourusername/cost-calculator
|
|
6
6
|
Author: Cost Optimization Team
|
|
@@ -20,48 +20,91 @@ from cost_calculator.executor import execute_trends, execute_monthly, execute_dr
|
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
def load_profile(profile_name):
|
|
23
|
-
"""Load profile configuration from
|
|
23
|
+
"""Load profile configuration from local file or DynamoDB API"""
|
|
24
|
+
import os
|
|
25
|
+
import requests
|
|
26
|
+
|
|
24
27
|
config_dir = Path.home() / '.config' / 'cost-calculator'
|
|
25
28
|
config_file = config_dir / 'profiles.json'
|
|
26
29
|
creds_file = config_dir / 'credentials.json'
|
|
27
30
|
|
|
28
|
-
|
|
31
|
+
# Try local file first
|
|
32
|
+
if config_file.exists():
|
|
33
|
+
with open(config_file) as f:
|
|
34
|
+
profiles = json.load(f)
|
|
35
|
+
|
|
36
|
+
if profile_name in profiles:
|
|
37
|
+
profile = profiles[profile_name]
|
|
38
|
+
|
|
39
|
+
# Load credentials if using static credentials (not SSO)
|
|
40
|
+
if 'aws_profile' not in profile:
|
|
41
|
+
if not creds_file.exists():
|
|
42
|
+
# Try environment variables
|
|
43
|
+
if os.environ.get('AWS_ACCESS_KEY_ID'):
|
|
44
|
+
profile['credentials'] = {
|
|
45
|
+
'aws_access_key_id': os.environ['AWS_ACCESS_KEY_ID'],
|
|
46
|
+
'aws_secret_access_key': os.environ['AWS_SECRET_ACCESS_KEY'],
|
|
47
|
+
'aws_session_token': os.environ.get('AWS_SESSION_TOKEN')
|
|
48
|
+
}
|
|
49
|
+
return profile
|
|
50
|
+
|
|
51
|
+
raise click.ClickException(
|
|
52
|
+
f"No credentials found for profile '{profile_name}'.\n"
|
|
53
|
+
f"Run: cc configure --profile {profile_name}"
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
with open(creds_file) as f:
|
|
57
|
+
creds = json.load(f)
|
|
58
|
+
|
|
59
|
+
if profile_name not in creds:
|
|
60
|
+
raise click.ClickException(
|
|
61
|
+
f"No credentials found for profile '{profile_name}'.\n"
|
|
62
|
+
f"Run: cc configure --profile {profile_name}"
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
profile['credentials'] = creds[profile_name]
|
|
66
|
+
|
|
67
|
+
return profile
|
|
68
|
+
|
|
69
|
+
# Profile not found locally - try DynamoDB API
|
|
70
|
+
api_secret = os.environ.get('COST_API_SECRET')
|
|
71
|
+
if not api_secret:
|
|
29
72
|
raise click.ClickException(
|
|
30
|
-
f"Profile
|
|
73
|
+
f"Profile '{profile_name}' not found locally and COST_API_SECRET not set.\n"
|
|
31
74
|
f"Run: cc init --profile {profile_name}"
|
|
32
75
|
)
|
|
33
76
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
f"Available profiles: {', '.join(profiles.keys())}"
|
|
77
|
+
try:
|
|
78
|
+
response = requests.post(
|
|
79
|
+
'https://64g7jq7sjygec2zmll5lsghrpi0txrzo.lambda-url.us-east-1.on.aws/',
|
|
80
|
+
headers={'X-API-Secret': api_secret, 'Content-Type': 'application/json'},
|
|
81
|
+
json={'operation': 'get', 'profile_name': profile_name},
|
|
82
|
+
timeout=10
|
|
41
83
|
)
|
|
42
|
-
|
|
43
|
-
profile = profiles[profile_name]
|
|
44
|
-
|
|
45
|
-
# Load credentials if using static credentials (not SSO)
|
|
46
|
-
if 'aws_profile' not in profile:
|
|
47
|
-
if not creds_file.exists():
|
|
48
|
-
raise click.ClickException(
|
|
49
|
-
f"No credentials found for profile '{profile_name}'.\n"
|
|
50
|
-
f"Run: cc configure --profile {profile_name}"
|
|
51
|
-
)
|
|
52
|
-
|
|
53
|
-
with open(creds_file) as f:
|
|
54
|
-
creds = json.load(f)
|
|
55
84
|
|
|
56
|
-
if
|
|
85
|
+
if response.status_code == 200:
|
|
86
|
+
profile_data = response.json()
|
|
87
|
+
profile = {'accounts': profile_data['accounts']}
|
|
88
|
+
|
|
89
|
+
# Use environment credentials
|
|
90
|
+
if os.environ.get('AWS_ACCESS_KEY_ID'):
|
|
91
|
+
profile['credentials'] = {
|
|
92
|
+
'aws_access_key_id': os.environ['AWS_ACCESS_KEY_ID'],
|
|
93
|
+
'aws_secret_access_key': os.environ['AWS_SECRET_ACCESS_KEY'],
|
|
94
|
+
'aws_session_token': os.environ.get('AWS_SESSION_TOKEN')
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
return profile
|
|
98
|
+
else:
|
|
57
99
|
raise click.ClickException(
|
|
58
|
-
f"
|
|
59
|
-
f"Run: cc
|
|
100
|
+
f"Profile '{profile_name}' not found in DynamoDB.\n"
|
|
101
|
+
f"Run: cc profile create --name {profile_name} --accounts \"...\""
|
|
60
102
|
)
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
103
|
+
except requests.exceptions.RequestException as e:
|
|
104
|
+
raise click.ClickException(
|
|
105
|
+
f"Failed to fetch profile from API: {e}\n"
|
|
106
|
+
f"Run: cc init --profile {profile_name}"
|
|
107
|
+
)
|
|
65
108
|
|
|
66
109
|
|
|
67
110
|
def calculate_costs(profile_config, accounts, start_date, offset, window):
|
|
@@ -11,22 +11,33 @@ def get_credentials_dict(config):
|
|
|
11
11
|
Extract credentials from config in format needed for API.
|
|
12
12
|
|
|
13
13
|
Returns:
|
|
14
|
-
dict with access_key, secret_key, session_token
|
|
14
|
+
dict with access_key, secret_key, session_token, or None if profile is 'dummy'
|
|
15
15
|
"""
|
|
16
16
|
if 'aws_profile' in config:
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
frozen_creds = credentials.get_frozen_credentials()
|
|
17
|
+
# Skip credential loading for dummy profile (API-only mode)
|
|
18
|
+
if config['aws_profile'] == 'dummy':
|
|
19
|
+
return None
|
|
21
20
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
'
|
|
25
|
-
|
|
26
|
-
|
|
21
|
+
# Get temporary credentials from SSO session
|
|
22
|
+
try:
|
|
23
|
+
session = boto3.Session(profile_name=config['aws_profile'])
|
|
24
|
+
credentials = session.get_credentials()
|
|
25
|
+
frozen_creds = credentials.get_frozen_credentials()
|
|
26
|
+
|
|
27
|
+
return {
|
|
28
|
+
'access_key': frozen_creds.access_key,
|
|
29
|
+
'secret_key': frozen_creds.secret_key,
|
|
30
|
+
'session_token': frozen_creds.token
|
|
31
|
+
}
|
|
32
|
+
except Exception:
|
|
33
|
+
# If profile not found, return None (API will handle)
|
|
34
|
+
return None
|
|
27
35
|
else:
|
|
28
36
|
# Use static credentials
|
|
29
|
-
creds = config
|
|
37
|
+
creds = config.get('credentials', {})
|
|
38
|
+
if not creds:
|
|
39
|
+
return None
|
|
40
|
+
|
|
30
41
|
result = {
|
|
31
42
|
'access_key': creds['aws_access_key_id'],
|
|
32
43
|
'secret_key': creds['aws_secret_access_key']
|
{aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/COST_CALCULATION_METHODOLOGY.md
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{aws_cost_calculator_cli-1.5.1 → aws_cost_calculator_cli-1.5.3}/cost_calculator/api_client.py
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|