Skip to content

Commit c0e4748

Browse files
author
Douglas Curtis
authored
Merge pull request #2610 from project-koku/rc-2021.01.22
Rc 2021.01.22
2 parents e64a9c5 + 01d01a0 commit c0e4748

File tree

67 files changed

+3510
-1459
lines changed

Some content is hidden

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

67 files changed

+3510
-1459
lines changed

.github/workflows/unittests.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,7 @@ jobs:
5454
path: |
5555
~/.cache/pipenv
5656
~/.local/share/virtualenvs
57-
key: os-${{ runner.os }}-env-${{ matrix.python-version }}-${{ hashFiles('**/Pipfile.lock') }}-${{ github.ref }}
57+
key: ${{ runner.os }}-env-${{ matrix.python-version }}-${{ hashFiles('**/Pipfile.lock') }}-${{ github.ref }}
5858

5959
- name: Install dependencies
6060
if: steps.cache-dependencies.outputs.cache-hit != 'true'

docs/source/specs/openapi.json

+114-6
Original file line numberDiff line numberDiff line change
@@ -396,7 +396,7 @@
396396
}]
397397
}
398398
},
399-
"/forecasts/aws/costs": {
399+
"/forecasts/aws/costs/": {
400400
"summary": "AWS Cost Forecasts",
401401
"get": {
402402
"tags":["Forecasts"],
@@ -441,7 +441,7 @@
441441
}]
442442
}
443443
},
444-
"/forecasts/azure/costs": {
444+
"/forecasts/azure/costs/": {
445445
"summary": "Azure Cost Forecasts",
446446
"get": {
447447
"tags":["Forecasts"],
@@ -486,7 +486,52 @@
486486
}]
487487
}
488488
},
489-
"/forecasts/openshift/costs": {
489+
"/forecasts/gcp/costs/": {
490+
"summary": "GCP Cost Forecasts",
491+
"get": {
492+
"tags":["Forecasts"],
493+
"parameters": [{
494+
"$ref": "#/components/parameters/QueryFilter",
495+
"name":"QueryFilter"
496+
}],
497+
"responses": {
498+
"200": {
499+
"description": "An object describing the cost forecast.",
500+
"content": {
501+
"application/json": {
502+
"schema": {
503+
"$ref": "#/components/schemas/Forecast"
504+
}
505+
}
506+
}
507+
},
508+
"400": {
509+
"description": "Request Error",
510+
"content": {
511+
"application/json": {
512+
"schema": {
513+
"$ref": "#/components/schemas/Error"
514+
}
515+
}
516+
}
517+
},
518+
"500": {
519+
"description": "Unexpected Error",
520+
"content": {
521+
"application/json": {
522+
"schema": {
523+
"$ref": "#/components/schemas/Error"
524+
}
525+
}
526+
}
527+
}
528+
},
529+
"security": [{
530+
"basic_auth": []
531+
}]
532+
}
533+
},
534+
"/forecasts/openshift/costs/": {
490535
"summary": "OpenShift Cost Forecasts",
491536
"get": {
492537
"tags":["Forecasts"],
@@ -531,7 +576,7 @@
531576
}]
532577
}
533578
},
534-
"/forecasts/openshift/infrastructures/aws/costs": {
579+
"/forecasts/openshift/infrastructures/aws/costs/": {
535580
"summary": "OpenShift on AWS Cost Forecasts",
536581
"get": {
537582
"tags":["Forecasts"],
@@ -576,7 +621,7 @@
576621
}]
577622
}
578623
},
579-
"/forecasts/openshift/infrastructures/all/costs": {
624+
"/forecasts/openshift/infrastructures/all/costs/": {
580625
"summary": "OpenShift on Cloud Cost Forecasts",
581626
"get": {
582627
"tags":["Forecasts"],
@@ -621,7 +666,7 @@
621666
}]
622667
}
623668
},
624-
"/forecasts/openshift/infrastructures/azure/costs": {
669+
"/forecasts/openshift/infrastructures/azure/costs/": {
625670
"summary": "OpenShift on Azure Cost Forecasts",
626671
"get": {
627672
"tags":["Forecasts"],
@@ -2406,6 +2451,31 @@
24062451
}
24072452
}
24082453
},
2454+
"/user-access/": {
2455+
"get": {
2456+
"tags": [
2457+
"UserAccess"
2458+
],
2459+
"summary": "Returns user permission status.",
2460+
"operationId": "listUserAccess",
2461+
"parameters": [{
2462+
"$ref": "#/components/parameters/QueryType"
2463+
}
2464+
],
2465+
"responses": {
2466+
"200": {
2467+
"description": "| - 200 response",
2468+
"content": {
2469+
"application/json": {
2470+
"schema": {
2471+
"$ref": "#/components/schemas/UserAccessListPagination"
2472+
}
2473+
}
2474+
}
2475+
}
2476+
}
2477+
}
2478+
},
24092479
"/sources/": {
24102480
"get": {
24112481
"tags": [
@@ -3822,6 +3892,14 @@
38223892
"type": "boolean"
38233893
}
38243894
},
3895+
"QueryType": {
3896+
"name": "type",
3897+
"in": "query",
3898+
"description": "String to identify user access permission type (i.e. AWS, cost_model).",
3899+
"schema": {
3900+
"type": "string"
3901+
}
3902+
},
38253903
"QueryValue": {
38263904
"in": "query",
38273905
"name": "value",
@@ -4476,6 +4554,26 @@
44764554
}
44774555
]
44784556
},
4557+
"UserAccessListPagination": {
4558+
"allOf": [{
4559+
"$ref": "#/components/schemas/ListPagination"
4560+
},
4561+
{
4562+
"type": "object",
4563+
"required": [
4564+
"data"
4565+
],
4566+
"properties": {
4567+
"data": {
4568+
"type": "array",
4569+
"items": {
4570+
"$ref": "#/components/schemas/UserAccessTypeOut"
4571+
}
4572+
}
4573+
}
4574+
}
4575+
]
4576+
},
44794577
"ResourceTypeListPagination": {
44804578
"allOf": [{
44814579
"$ref": "#/components/schemas/ListPagination"
@@ -4523,6 +4621,16 @@
45234621
}
45244622
}
45254623
},
4624+
"UserAccessTypeOut": {
4625+
"properties": {
4626+
"type": {
4627+
"type": "string"
4628+
},
4629+
"access": {
4630+
"type": "boolean"
4631+
}
4632+
}
4633+
},
45264634
"ResourceTypeListOut": {
45274635
"properties": {
45284636
"value": {

koku/api/common/permissions/__init__.py

+3
Original file line numberDiff line numberDiff line change
@@ -16,17 +16,20 @@
1616
#
1717
from api.common.permissions.aws_access import AwsAccessPermission
1818
from api.common.permissions.azure_access import AzureAccessPermission
19+
from api.common.permissions.gcp_access import GcpAccessPermission
1920
from api.common.permissions.openshift_access import OpenShiftAccessPermission
2021
from api.provider.models import Provider
2122

2223
RESOURCE_TYPES = [
2324
AwsAccessPermission.resource_type,
2425
AzureAccessPermission.resource_type,
2526
OpenShiftAccessPermission.resource_type,
27+
GcpAccessPermission.resource_type,
2628
]
2729

2830
RESOURCE_TYPE_MAP = {
2931
AwsAccessPermission.resource_type: [Provider.PROVIDER_AWS, Provider.PROVIDER_AWS_LOCAL],
3032
AzureAccessPermission.resource_type: [Provider.PROVIDER_AZURE, Provider.PROVIDER_AZURE_LOCAL],
3133
OpenShiftAccessPermission.resource_type: [Provider.PROVIDER_OCP],
34+
GcpAccessPermission.resource_type: [Provider.PROVIDER_GCP, Provider.PROVIDER_GCP_LOCAL],
3235
}

koku/api/forecast/serializers.py

+4
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ class AWSCostForecastParamSerializer(ForecastParamSerializer):
5050
"""AWS Cost Forecast Serializer."""
5151

5252

53+
class GCPCostForecastParamSerializer(ForecastParamSerializer):
54+
"""GCP Cost Forecast Serializer."""
55+
56+
5357
class AzureCostForecastParamSerializer(ForecastParamSerializer):
5458
"""Azure Cost Forecast Serializer."""
5559

koku/api/forecast/views.py

+13
Original file line numberDiff line numberDiff line change
@@ -27,22 +27,26 @@
2727
from api.common.pagination import ForecastListPaginator
2828
from api.common.permissions import AwsAccessPermission
2929
from api.common.permissions import AzureAccessPermission
30+
from api.common.permissions import GcpAccessPermission
3031
from api.common.permissions import OpenShiftAccessPermission
3132
from api.common.permissions.openshift_all_access import OpenshiftAllAccessPermission
3233
from api.forecast.serializers import AWSCostForecastParamSerializer
3334
from api.forecast.serializers import AzureCostForecastParamSerializer
35+
from api.forecast.serializers import GCPCostForecastParamSerializer
3436
from api.forecast.serializers import OCPAllCostForecastParamSerializer
3537
from api.forecast.serializers import OCPAWSCostForecastParamSerializer
3638
from api.forecast.serializers import OCPAzureCostForecastParamSerializer
3739
from api.forecast.serializers import OCPCostForecastParamSerializer
3840
from api.query_params import QueryParameters
3941
from forecast import AWSForecast
4042
from forecast import AzureForecast
43+
from forecast import GCPForecast
4144
from forecast import OCPAllForecast
4245
from forecast import OCPAWSForecast
4346
from forecast import OCPAzureForecast
4447
from forecast import OCPForecast
4548
from reporting.models import AzureTagsSummary
49+
from reporting.models import GCPTagsSummary
4650
from reporting.models import OCPAWSTagsSummary
4751
from reporting.models import OCPAzureTagsSummary
4852
from reporting.models import OCPStorageVolumeLabelSummary
@@ -128,3 +132,12 @@ class OCPAllCostForecastView(ForecastView):
128132
query_handler = OCPAllForecast
129133
serializer = OCPAllCostForecastParamSerializer
130134
tag_handler = [OCPAWSTagsSummary, OCPAzureTagsSummary]
135+
136+
137+
class GCPForecastCostView(ForecastView):
138+
"""GCP Cost Forecast View."""
139+
140+
permission_classes = (GcpAccessPermission,)
141+
query_handler = GCPForecast
142+
serializer = GCPCostForecastParamSerializer
143+
tag_handler = [GCPTagsSummary]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Generated by Django 3.1.3 on 2021-01-15 15:32
2+
from django.db import migrations
3+
4+
5+
class Migration(migrations.Migration):
6+
7+
dependencies = [("api", "0033_sources_name_text")]
8+
9+
operations = [migrations.RemoveField(model_name="sources", name="endpoint_id")]

koku/api/organizations/queries.py

-3
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
from api.query_filter import QueryFilter
2929
from api.query_filter import QueryFilterCollection
3030
from api.query_handler import QueryHandler
31-
from api.utils import DateHelper
3231

3332

3433
LOG = logging.getLogger(__name__)
@@ -71,8 +70,6 @@ class OrgQueryHandler(QueryHandler):
7170
SUPPORTED_FILTERS = []
7271
FILTER_MAP = {}
7372

74-
dh = DateHelper()
75-
7673
def __init__(self, parameters):
7774
"""Establish org query handler.
7875

koku/api/provider/models.py

-3
Original file line numberDiff line numberDiff line change
@@ -190,9 +190,6 @@ class Meta:
190190
# Kafka message offset for Platform-Sources kafka stream
191191
offset = models.IntegerField(null=False)
192192

193-
# Endpoint ID. Identifier to connect source to authentication.
194-
endpoint_id = models.IntegerField(null=True)
195-
196193
# Koku Specific data.
197194
# Customer Account ID
198195
account_id = models.TextField(null=True)

koku/api/query_handler.py

+25-9
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
import logging
2020

2121
from dateutil import relativedelta
22+
from django.core.exceptions import FieldDoesNotExist
2223
from django.db.models.functions import TruncDay
2324
from django.db.models.functions import TruncMonth
2425

@@ -59,6 +60,7 @@ def __init__(self, parameters):
5960
6061
"""
6162
LOG.debug(f"Query Params: {parameters}")
63+
self.dh = DateHelper()
6264
parameters = self.filter_to_order_by(parameters)
6365
self.tenant = parameters.tenant
6466
self.access = parameters.access
@@ -215,25 +217,24 @@ def _get_timeframe(self):
215217
time_scope_units = self.get_time_scope_units()
216218
start = None
217219
end = None
218-
dh = DateHelper()
219220
if time_scope_units == "month":
220221
if time_scope_value == -1:
221222
# get current month
222-
start = dh.this_month_start
223-
end = dh.today
223+
start = self.dh.this_month_start
224+
end = self.dh.today
224225
else:
225226
# get previous month
226-
start = dh.last_month_start
227-
end = dh.last_month_end
227+
start = self.dh.last_month_start
228+
end = self.dh.last_month_end
228229
else:
229230
if time_scope_value == -10:
230231
# get last 10 days
231-
start = dh.n_days_ago(dh.this_hour, 9)
232-
end = dh.this_hour
232+
start = self.dh.n_days_ago(self.dh.this_hour, 9)
233+
end = self.dh.this_hour
233234
else:
234235
# get last 30 days
235-
start = dh.n_days_ago(dh.this_hour, 29)
236-
end = dh.this_hour
236+
start = self.dh.n_days_ago(self.dh.this_hour, 29)
237+
end = self.dh.this_hour
237238

238239
self.start_datetime = start
239240
self.end_datetime = end
@@ -344,5 +345,20 @@ def set_access_filters(self, access, filt, filters):
344345
filters.add(q_filter)
345346
else:
346347
filt["operation"] = "in"
348+
try:
349+
check_field_type = None
350+
if hasattr(self, "query_table"):
351+
# Reports APIs
352+
check_field_type = self.query_table._meta.get_field(filt.get("field", "")).get_internal_type()
353+
elif hasattr(self, "data_sources"):
354+
# Tags APIs
355+
check_field_type = (
356+
self.data_sources[0].get("db_table")._meta.get_field(filt.get("field", "")).get_internal_type()
357+
)
358+
if check_field_type == "ArrayField":
359+
filt["operation"] = "contains"
360+
except FieldDoesNotExist:
361+
pass
362+
347363
q_filter = QueryFilter(parameter=access, **filt)
348364
filters.add(q_filter)

koku/api/report/all/openshift/query_handler.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
from api.models import Provider
2121
from api.report.all.openshift.provider_map import OCPAllProviderMap
2222
from api.report.aws.openshift.query_handler import OCPInfrastructureReportQueryHandlerBase
23-
from api.report.queries import is_grouped_or_filtered_by_project
23+
from api.report.queries import is_grouped_by_project
2424

2525
LOG = logging.getLogger(__name__)
2626

@@ -61,7 +61,7 @@ def __init__(self, parameters):
6161
"""
6262
self._mapper = OCPAllProviderMap(provider=self.provider, report_type=parameters.report_type)
6363
# Update which field is used to calculate cost by group by param.
64-
if is_grouped_or_filtered_by_project(parameters):
64+
if is_grouped_by_project(parameters):
6565
self._report_type = parameters.report_type + "_by_project"
6666
self._mapper = OCPAllProviderMap(provider=self.provider, report_type=self._report_type)
6767

0 commit comments

Comments
 (0)