diff --git a/docker-compose-non-dev.yml b/docker-compose-non-dev.yml index cf36ae833dd2..8136b9ad6db8 100644 --- a/docker-compose-non-dev.yml +++ b/docker-compose-non-dev.yml @@ -16,46 +16,47 @@ # x-superset-image: &superset-image apachesuperset.docker.scarf.sh/apache/superset:${TAG:-latest-dev} x-superset-depends-on: &superset-depends-on - - db + # - db - redis x-superset-volumes: &superset-volumes # /app/pythonpath_docker will be appended to the PYTHONPATH in the final container - ./docker:/app/docker + - ./superset:/app/superset - superset_home:/app/superset_home version: "3.7" services: redis: image: redis:7 - container_name: superset_cache + container_name: sf_superset_cache restart: unless-stopped volumes: - redis:/data - db: - env_file: docker/.env-non-dev - image: postgres:15 - container_name: superset_db - restart: unless-stopped - volumes: - - db_home:/var/lib/postgresql/data - - ./docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d + # db: + # env_file: docker/.env-non-dev + # image: postgres:15 + # container_name: sf_superset_db + # restart: unless-stopped + # volumes: + # - db_home:/var/lib/postgresql/data + # - ./docker/docker-entrypoint-initdb.d:/docker-entrypoint-initdb.d superset: env_file: docker/.env-non-dev image: *superset-image - container_name: superset_app - command: ["/app/docker/docker-bootstrap.sh", "app-gunicorn"] + container_name: sf_superset_app + command: ["/app/docker/docker-bootstrap.sh", "app"] user: "root" restart: unless-stopped ports: - - 8088:8088 + - 80:8088 depends_on: *superset-depends-on volumes: *superset-volumes superset-init: image: *superset-image - container_name: superset_init + container_name: sf_superset_init command: ["/app/docker/docker-init.sh"] env_file: docker/.env-non-dev depends_on: *superset-depends-on @@ -66,7 +67,7 @@ services: superset-worker: image: *superset-image - container_name: superset_worker + container_name: sf_superset_worker command: ["/app/docker/docker-bootstrap.sh", "worker"] env_file: docker/.env-non-dev restart: unless-stopped @@ -82,7 +83,7 @@ services: superset-worker-beat: image: *superset-image - container_name: superset_worker_beat + container_name: sf_superset_worker_beat command: ["/app/docker/docker-bootstrap.sh", "beat"] env_file: docker/.env-non-dev restart: unless-stopped diff --git a/docker/.env-non-dev b/docker/.env-non-dev index a86ddbd193f0..9c2614ce64b4 100644 --- a/docker/.env-non-dev +++ b/docker/.env-non-dev @@ -17,10 +17,10 @@ COMPOSE_PROJECT_NAME=superset # database configurations (do not modify) -DATABASE_DB=superset -DATABASE_HOST=db -DATABASE_PASSWORD=superset -DATABASE_USER=superset +DATABASE_DB=superset_sourcefuse +DATABASE_HOST=host.docker.internal +DATABASE_PASSWORD=admin +DATABASE_USER=postgres DATABASE_PORT=5432 DATABASE_DIALECT=postgresql @@ -46,8 +46,10 @@ REDIS_HOST=redis REDIS_PORT=6379 SUPERSET_ENV=production -SUPERSET_LOAD_EXAMPLES=yes +#SUPERSET_LOAD_EXAMPLES=yes SUPERSET_SECRET_KEY=TEST_NON_DEV_SECRET CYPRESS_CONFIG=false SUPERSET_PORT=8088 MAPBOX_API_KEY='' + +FLASK_DEBUG=true \ No newline at end of file diff --git a/docker/pythonpath_dev/superset_config_local.example b/docker/pythonpath_dev/superset_config_local.example deleted file mode 100644 index dfa03bb778a8..000000000000 --- a/docker/pythonpath_dev/superset_config_local.example +++ /dev/null @@ -1,27 +0,0 @@ -# -# Licensed to the Apache Software Foundation (ASF) under one or more -# contributor license agreements. See the NOTICE file distributed with -# this work for additional information regarding copyright ownership. -# The ASF licenses this file to You under the Apache License, Version 2.0 -# (the "License"); you may not use this file except in compliance with -# the License. You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# - -# -# This is an example "local" configuration file. In order to set/override config -# options that ONLY apply to your local environment, simply copy/rename this file -# to docker/pythonpath/superset_config_docker.py -# It ends up being imported by docker/superset_config.py which is loaded by -# superset/config.py -# - -SQLALCHEMY_DATABASE_URI = "postgresql+psycopg2://pguser:pgpwd@some.host/superset" -SQLALCHEMY_ECHO = True diff --git a/docs/static/resources/openapi.json b/docs/static/resources/openapi.json index 13d5c8c21cea..66e73e22fed5 100644 --- a/docs/static/resources/openapi.json +++ b/docs/static/resources/openapi.json @@ -17878,6 +17878,32 @@ "tags": ["Current User"] } }, + "/api/v1/sf_restapi/": { + "get": { + "description": "Returns the user object corresponding to the agent making the request, or returns a 401 error if the user is unauthenticated.", + "responses": { + "200": { + "content": { + "application/json": { + "schema": { + "properties": { + "result": { + "$ref": "#/components/schemas/UserResponseSchema" + } + }, + "type": "object" + } + } + }, + "description": "The current user" + }, + "401": { + "$ref": "#/components/responses/401" + } + }, + "tags": ["Sourcefuse Rest API"] + } + }, "/api/v1/me/roles/": { "get": { "description": "Returns the user roles corresponding to the agent making the request, or returns a 401 error if the user is unauthenticated.", diff --git a/superset/config.py b/superset/config.py index bf1c42469920..4d8c8a0b0a5e 100644 --- a/superset/config.py +++ b/superset/config.py @@ -246,6 +246,7 @@ def _try_json_readsha(filepath: str, length: int) -> str | None: "superset.views.core.log", "superset.views.core.explore_json", "superset.charts.data.api.data", + "superset.sfrestapi.api.test_post", ] # Whether to run the web server in debug mode or not diff --git a/superset/initialization/__init__.py b/superset/initialization/__init__.py index c18cf8a059f7..dcbd4629ce96 100644 --- a/superset/initialization/__init__.py +++ b/superset/initialization/__init__.py @@ -155,6 +155,7 @@ def init_views(self) -> None: from superset.row_level_security.api import RLSRestApi from superset.security.api import SecurityRestApi from superset.sqllab.api import SqlLabRestApi + from superset.sfrestapi.api import SFRestAPI from superset.tags.api import TagRestApi from superset.views.alerts import AlertView, ReportView from superset.views.all_entities import TaggedObjectsModelView, TaggedObjectView @@ -229,6 +230,8 @@ def init_views(self) -> None: appbuilder.add_api(SavedQueryRestApi) appbuilder.add_api(TagRestApi) appbuilder.add_api(SqlLabRestApi) + appbuilder.add_api(SFRestAPI) + # # Setup regular views # diff --git a/superset/sfrestapi/__init__.py b/superset/sfrestapi/__init__.py new file mode 100644 index 000000000000..13a83393a912 --- /dev/null +++ b/superset/sfrestapi/__init__.py @@ -0,0 +1,16 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. diff --git a/superset/sfrestapi/api.py b/superset/sfrestapi/api.py new file mode 100644 index 000000000000..e7646fd25c2b --- /dev/null +++ b/superset/sfrestapi/api.py @@ -0,0 +1,120 @@ +import logging +import boto3 + + +import simplejson as json +from flask import Response, request +from flask_appbuilder.api import expose, protect, safe +from flask_appbuilder.security.decorators import permission_name + +from superset import app +from superset.constants import MODEL_API_RW_METHOD_PERMISSION_MAP + +from superset.extensions import event_logger + +from superset.utils import core as utils +from superset.views.base import json_success +from superset.views.base_api import BaseSupersetApi, statsd_metrics, requires_json +from superset.sfrestapi.schemas import SFRestAPIListBucketSchema + +# config = app.config +logger = logging.getLogger(__name__) + + +class SFRestAPI(BaseSupersetApi): + class_permission_name = "AdvancedDataType" + method_permission_name = MODEL_API_RW_METHOD_PERMISSION_MAP + + resource_name = "sfrestapi" + allow_browser_login = True + openapi_spec_tag = "SF Rest API" + openapi_spec_component_schemas = (SFRestAPIListBucketSchema,) + + @expose("/list-s3-buckets", methods=("GET",)) + @protect() + @safe + @statsd_metrics + @event_logger.log_this + def get(self) -> Response: + """List all Buckets in account + --- + get: + summary: Get the list of all buckets in account. + description: >- + List of All S3 Buckets as an array + responses: + 200: + description: Returns the list of all buckets in account. + content: + application/json: + schema: + $ref: '#/components/schemas/SFRestAPIListBucketSchema' + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + """ + + logger.info("============================================================") + s3 = boto3.client("s3") + response = s3.list_buckets() + buckets = [] + for bucket in response["Buckets"]: + buckets.append(bucket["Name"]) + return json_success( + json.dumps( + {"buckets": buckets}, + default=utils.json_iso_dttm_ser, + ignore_nan=True, + ), + 200, + ) + + @expose("/test-post", methods=("POST",)) + @statsd_metrics + @requires_json + @event_logger.log_this + @protect() + def test_post(self) -> Response: + """Estimate the SQL query execution cost. + --- + post: + summary: Estimate the SQL query execution cost + requestBody: + description: SQL query and params + required: true + content: + application/json: + schema: + $ref: '#/components/schemas/EstimateQueryCostSchema' + responses: + 200: + description: Query estimation result + content: + application/json: + schema: + type: object + properties: + result: + type: object + 400: + $ref: '#/components/responses/400' + 401: + $ref: '#/components/responses/401' + 403: + $ref: '#/components/responses/403' + 500: + $ref: '#/components/responses/500' + """ + return json_success( + json.dumps( + {"request": request.json}, + default=utils.json_iso_dttm_ser, + ignore_nan=True, + ), + 200, + ) diff --git a/superset/sfrestapi/schemas.py b/superset/sfrestapi/schemas.py new file mode 100644 index 000000000000..a936796f183a --- /dev/null +++ b/superset/sfrestapi/schemas.py @@ -0,0 +1,4 @@ +from marshmallow import fields, Schema + +class SFRestAPIListBucketSchema(Schema): + buckets = fields.List(fields.String()) \ No newline at end of file diff --git a/superset/static/logo.svg b/superset/static/logo.svg new file mode 100644 index 000000000000..89ef0b145372 --- /dev/null +++ b/superset/static/logo.svg @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + +