Эх сурвалжийг харах

[api] Introduce API versioning for public APIs (#3352)

- Set the existing API version as v1
Harsh Gupta 2 жил өмнө
parent
commit
4d303a0550

+ 1 - 1
desktop/core/src/desktop/api_public_tests.py

@@ -77,7 +77,7 @@ class TestEditorApi():
     self.user_not_me = User.objects.get(username="not_api_user")
 
   def test_urls_exist(self):
-    assert_equal(reverse('api:editor_execute', args=['hive']), '/api/editor/execute/hive')
+    assert_equal(reverse('api:editor_execute', args=['hive']), '/api/v1/editor/execute/hive')
 
   def test_editor_execute(self):
     with patch('desktop.api_public.notebook_api.execute') as execute:

+ 0 - 0
desktop/core/src/desktop/api_public_urls.py → desktop/core/src/desktop/api_public_urls_v1.py


+ 1 - 1
desktop/core/src/desktop/js/api/apiHelper.js

@@ -1429,7 +1429,7 @@ class ApiHelper {
 
   async getHistory(options) {
     return new Promise((resolve, reject) => {
-      $.get('/api/editor/get_history', {
+      $.get('/api/v1/editor/get_history', {
         doc_type: options.type,
         limit: options.limit || 50,
         page: options.page || 1,

+ 1 - 1
desktop/core/src/desktop/js/api/auth.ts

@@ -16,7 +16,7 @@
 
 import { post } from 'api/utils';
 
-const JWT_URL = 'api/token/auth/';
+const JWT_URL = 'api/v1/token/auth/';
 
 export const login = async (username: string, email: string, password: string): Promise<void> => {
   if (email !== '') {

+ 9 - 9
desktop/core/src/desktop/js/api/urls.js

@@ -14,14 +14,14 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-export const AUTOCOMPLETE_API_PREFIX = '/api/editor/autocomplete/';
-export const BANNERS_API = '/api/banners/';
+export const AUTOCOMPLETE_API_PREFIX = '/api/v1/editor/autocomplete/';
+export const BANNERS_API = '/api/v1/banners/';
 export const SAMPLE_API_PREFIX = '/notebook/api/sample/';
-export const EXECUTE_API_PREFIX = '/api/editor/execute/'; // Dups with api.ts
+export const EXECUTE_API_PREFIX = '/api/v1/editor/execute/'; // Dups with api.ts
 export const DOCUMENTS_API = '/desktop/api2/doc/';
 export const DOCUMENTS_SEARCH_API = '/desktop/api2/docs/';
 export const GET_HUE_CONFIG_API = '/desktop/api2/get_hue_config';
-export const FETCH_CONFIG_API = '/api/get_config/';
+export const FETCH_CONFIG_API = '/api/v1/get_config/';
 export const HDFS_API_PREFIX = '/filebrowser/view=' + encodeURIComponent('/');
 export const OFS_API_PREFIX = '/filebrowser/view=' + encodeURIComponent('ofs://');
 export const ADLS_API_PREFIX = '/filebrowser/view=' + encodeURIComponent('adl:/');
@@ -42,16 +42,16 @@ export const SEND_SLACK_MESSAGE = '/desktop/slack/api/message/send';
 export const TOPO_URL = '/desktop/topo/';
 
 export const SEARCH_API = '/desktop/api/search/entities';
-export const INTERACTIVE_SEARCH_API = '/api/metadata/search/entities_interactive';
+export const INTERACTIVE_SEARCH_API = '/api/v1/metadata/search/entities_interactive';
 
-export const CREATE_SESSION_API = '/api/editor/create_session'; // Note: dup by api.ts
-export const CLOSE_SESSION_API = '/api/editor/close_session'; // Note: dup by api.ts
+export const CREATE_SESSION_API = '/api/v1/editor/create_session'; // Note: dup by api.ts
+export const CLOSE_SESSION_API = '/api/v1/editor/close_session'; // Note: dup by api.ts
 export const FETCH_RESULT_SIZE_API = '/notebook/api/fetch_result_size';
 export const FETCH_RESULT_DATA_API = '/notebook/api/fetch_result_data';
-export const GET_LOGS_API = '/api/editor/get_logs';
+export const GET_LOGS_API = '/api/v1/editor/get_logs';
 export const CANCEL_STATEMENT_API = '/notebook/api/cancel_statement';
 export const CLOSE_STATEMENT_API = '/notebook/api/close_statement';
-export const CHECK_STATUS_API = '/api/editor/check_status';
+export const CHECK_STATUS_API = '/api/v1/editor/check_status';
 
 export const HBASE_API_PREFIX = '/hbase/api/';
 export const SAVE_TO_FILE_API = '/filebrowser/save';

+ 1 - 1
desktop/core/src/desktop/js/apps/editor/api.ts

@@ -19,7 +19,7 @@ import { ExecutionStatus } from './execution/sqlExecutable';
 import { CancellablePromise } from 'api/cancellablePromise';
 import { get } from 'api/utils';
 
-const HISTORY_API_URL = '/api/editor/get_history';
+const HISTORY_API_URL = '/api/v1/editor/get_history';
 
 export const formatSql = async (options: {
   statements: string;

+ 9 - 9
desktop/core/src/desktop/js/apps/editor/execution/api.ts

@@ -156,15 +156,15 @@ export interface AuthRequest {
   message?: string;
 }
 
-const CANCEL_STATEMENT_API = '/api/editor/cancel_statement';
-const CHECK_STATUS_API = '/api/editor/check_status';
-const CLOSE_SESSION_API = '/api/editor/close_session';
-const CLOSE_STATEMENT_API = '/api/editor/close_statement';
-const CREATE_SESSION_API = '/api/editor/create_session';
-const EXECUTE_API_PREFIX = '/api/editor/execute/';
-const FETCH_RESULT_DATA_API = '/api/editor/fetch_result_data';
-const FETCH_RESULT_SIZE_API = '/api/editor/fetch_result_size';
-const GET_LOGS_API = '/api/editor/get_logs';
+const CANCEL_STATEMENT_API = '/api/v1/editor/cancel_statement';
+const CHECK_STATUS_API = '/api/v1/editor/check_status';
+const CLOSE_SESSION_API = '/api/v1/editor/close_session';
+const CLOSE_STATEMENT_API = '/api/v1/editor/close_statement';
+const CREATE_SESSION_API = '/api/v1/editor/create_session';
+const EXECUTE_API_PREFIX = '/api/v1/editor/execute/';
+const FETCH_RESULT_DATA_API = '/api/v1/editor/fetch_result_data';
+const FETCH_RESULT_SIZE_API = '/api/v1/editor/fetch_result_size';
+const GET_LOGS_API = '/api/v1/editor/get_logs';
 
 export const createSession = async (options: {
   type: string;

+ 1 - 1
desktop/core/src/desktop/js/apps/notebook/notebook.js

@@ -632,7 +632,7 @@ class Notebook {
       self.loadingHistory(true);
 
       $.get(
-        '/api/editor/get_history',
+        '/api/v1/editor/get_history',
         {
           doc_type: self.selectedSnippet(),
           limit: QUERIES_PER_PAGE,

+ 10 - 10
desktop/core/src/desktop/js/catalog/analyzer/ApiSqlAnalyzer.ts

@@ -61,16 +61,16 @@ const genericSqlAnalyzerMultiTableFetch = <T extends TimestampedData>(
   });
 };
 
-const COMPATIBILITY_URL = '/api/optimizer/query_compatibility';
-const PREDICT_URL = '/api/optimizer/predict';
-const RISK_URL = '/api/optimizer/query_risk/';
-const SIMILARITY_URL = '/api/optimizer/similar_queries';
-const TOP_AGGS_URL = '/api/optimizer/top_aggs';
-const TOP_COLUMNS_URL = '/api/optimizer/top_columns';
-const TOP_FILTERS_URL = '/api/optimizer/top_filters';
-const TOP_JOINS_URL = '/api/optimizer/top_joins';
-const TOP_TABLES_URL = '/api/optimizer/top_tables';
-const TABLE_DETAILS_URL = '/api/optimizer/table_details';
+const COMPATIBILITY_URL = '/api/v1/optimizer/query_compatibility';
+const PREDICT_URL = '/api/v1/optimizer/predict';
+const RISK_URL = '/api/v1/optimizer/query_risk/';
+const SIMILARITY_URL = '/api/v1/optimizer/similar_queries';
+const TOP_AGGS_URL = '/api/v1/optimizer/top_aggs';
+const TOP_COLUMNS_URL = '/api/v1/optimizer/top_columns';
+const TOP_FILTERS_URL = '/api/v1/optimizer/top_filters';
+const TOP_JOINS_URL = '/api/v1/optimizer/top_joins';
+const TOP_TABLES_URL = '/api/v1/optimizer/top_tables';
+const TABLE_DETAILS_URL = '/api/v1/optimizer/table_details';
 
 export default class ApiSqlAnalyzer implements SqlAnalyzer {
   connector: Connector;

+ 9 - 9
desktop/core/src/desktop/js/catalog/api.ts

@@ -61,17 +61,17 @@ interface SampleFetchOptions extends SharedFetchOptions {
 }
 
 const ADD_TAGS_URL = '/metadata/api/catalog/add_tags';
-const AUTOCOMPLETE_URL_PREFIX = '/api/editor/autocomplete/';
-const CANCEL_STATEMENT_URL = '/api/editor/cancel_statement';
-const CHECK_STATUS_URL = '/api/editor/check_status';
-const CLOSE_STATEMENT_URL = '/api/editor/close_statement';
+const AUTOCOMPLETE_URL_PREFIX = '/api/v1/editor/autocomplete/';
+const CANCEL_STATEMENT_URL = '/api/v1/editor/cancel_statement';
+const CHECK_STATUS_URL = '/api/v1/editor/check_status';
+const CLOSE_STATEMENT_URL = '/api/v1/editor/close_statement';
 const DELETE_TAGS_URL = '/metadata/api/catalog/delete_tags';
-const DESCRIBE_URL = '/api/editor/describe/';
-const FETCH_RESULT_DATA_URL = '/api/editor/fetch_result_data';
+const DESCRIBE_URL = '/api/v1/editor/describe/';
+const FETCH_RESULT_DATA_URL = '/api/v1/editor/fetch_result_data';
 const FIND_ENTITY_URL = '/metadata/api/catalog/find_entity';
 const LIST_TAGS_URL = '/metadata/api/catalog/list_tags';
 const METASTORE_TABLE_URL_PREFIX = '/metastore/table/';
-const SAMPLE_URL_PREFIX = '/api/editor/sample/';
+const SAMPLE_URL_PREFIX = '/api/v1/editor/sample/';
 const SEARCH_URL = '/desktop/api/search/entities';
 const UPDATE_PROPERTIES_URL = '/metadata/api/catalog/update_properties';
 
@@ -106,7 +106,7 @@ const performAnalyze = ({
     });
     try {
       const analyzeResponse = await post<DefaultApiResponse & { watch_url?: string }>(
-        `/api/${
+        `/api/v1/${
           entry.getConnector().id === 'hive' ? 'beeswax' : entry.getConnector().id
         }/analyze/${getEntryUrlPath(entry)}`,
         undefined,
@@ -204,7 +204,7 @@ export const fetchNamespaces = (
   connector: Connector,
   silenceErrors?: boolean
 ): CancellablePromise<Record<string, Namespace[]> & { dynamicClusters?: boolean }> =>
-  get(`/api/get_namespaces/${connector.id}`, undefined, { silenceErrors });
+  get(`/api/v1/get_namespaces/${connector.id}`, undefined, { silenceErrors });
 
 export const fetchNavigatorMetadata = ({
   entry,

+ 1 - 1
desktop/core/src/desktop/js/reactComponents/FileChooser/api.test.ts

@@ -31,7 +31,7 @@ describe('tests the filesystems api', () => {
 
     const filesystems = await fetchFileSystems();
 
-    expect(getSpy).toHaveBeenCalledWith('/api/storage/filesystems');
+    expect(getSpy).toHaveBeenCalledWith('/api/v1/storage/filesystems');
     expect(filesystems).toEqual(mockData);
   });
 

+ 2 - 2
desktop/core/src/desktop/js/reactComponents/FileChooser/api.ts

@@ -18,8 +18,8 @@ import { get } from '../../api/utils';
 import { CancellablePromise } from '../../api/cancellablePromise';
 import { PathAndFileData } from './types';
 
-const FILESYSTEMS_API_URL = '/api/storage/filesystems';
-const VIEWFILES_API_URl = '/api/storage/view=';
+const FILESYSTEMS_API_URL = '/api/v1/storage/filesystems';
+const VIEWFILES_API_URl = '/api/v1/storage/view=';
 export interface ApiFileSystem {
   file_system: string;
   user_home_directory: string;

+ 1 - 1
desktop/core/src/desktop/middleware.py

@@ -313,7 +313,7 @@ class LoginAndPermissionMiddleware(MiddlewareMixin):
     if request.path in ['/oidc/authenticate/', '/oidc/callback/', '/oidc/logout/', '/hue/oidc_failed/']:
       return None
 
-    if AUTH.AUTO_LOGIN_ENABLED.get() and request.path.startswith('/api/token/auth'):
+    if AUTH.AUTO_LOGIN_ENABLED.get() and request.path.startswith('/api/v1/token/auth'):
       pass # allow /api/token/auth can create user or make it active
     elif request.path.startswith('/api/'):
       return None

+ 5 - 5
desktop/core/src/desktop/urls.py

@@ -47,7 +47,7 @@ from desktop import appmanager
 from desktop import views as desktop_views
 from desktop import api as desktop_api
 from desktop import api2 as desktop_api2
-from desktop import api_public_urls
+from desktop import api_public_urls_v1
 from desktop.auth import views as desktop_auth_views
 from desktop.conf import METRICS, USE_NEW_EDITOR, ANALYTICS, has_connectors, ENABLE_PROMETHEUS, SLACK
 from desktop.configuration import api as desktop_configuration_api
@@ -206,11 +206,11 @@ dynamic_patterns += [
 ]
 
 dynamic_patterns += [
-  re_path('^api/token/auth/?$', TokenObtainPairView.as_view(), name='token_obtain'),
-  re_path('^api/token/verify/?$', TokenVerifyView.as_view(), name='token_verify'),
-  re_path('^api/token/refresh/?$', TokenRefreshView.as_view(), name='token_refresh'),
+  re_path('^api/v1/token/auth/?$', TokenObtainPairView.as_view(), name='token_obtain'),
+  re_path('^api/v1/token/verify/?$', TokenVerifyView.as_view(), name='token_verify'),
+  re_path('^api/v1/token/refresh/?$', TokenRefreshView.as_view(), name='token_refresh'),
 
-  re_path(r'^api/', include(('desktop.api_public_urls', 'api'), 'api')),
+  re_path(r'^api/v1/', include(('desktop.api_public_urls_v1', 'api'), 'api')),
 ]
 
 dynamic_patterns += [