Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add V2 scope to /api/clusters endpoint #1492

Merged
merged 8 commits into from
Jun 7, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 8 additions & 8 deletions assets/js/lib/network/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -68,36 +68,36 @@ function handleResponseStatus(response) {
return response;
}

export const post = function post(url, data) {
export const post = function post(url, data, config = null) {
return networkClient
.post(url, data)
.post(url, data, config)
.then(handleResponseStatus)
.catch((error) => {
handleError(error);
});
};

export const del = function del(url) {
export const del = function del(url, config = null) {
return networkClient
.delete(url)
.delete(url, config)
.then(handleResponseStatus)
.catch((error) => {
handleError(error);
});
};

export const put = function put(url, data) {
export const put = function put(url, data, config = null) {
return networkClient
.put(url, data)
.put(url, data, config)
.then(handleResponseStatus)
.catch((error) => {
handleError(error);
});
};

export const get = function get(url) {
export const get = function get(url, config = null) {
return networkClient
.get(url)
.get(url, config)
.then(handleResponseStatus)
.catch((error) => {
handleError(error);
Expand Down
16 changes: 16 additions & 0 deletions assets/js/lib/network/network.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,22 @@ describe('networkClient', () => {
clearCredentialsFromStore();
});

it('should use default baseURL', async () => {
axiosMock.onGet('/api/v1/test').reply(200, { ok: 'ok' });

const response = await networkClient.get('/test');

expect(response.data).toEqual({ ok: 'ok' });
});

it('should apply the specific config in each request', async () => {
axiosMock.onGet('/base/test').reply(200, { ok: 'ok' });

const response = await networkClient.get('/test', { baseURL: '/base' });

expect(response.data).toEqual({ ok: 'ok' });
});

it('should attach the access token from the store when a request is made', async () => {
storeAccessToken('test-access');

Expand Down
4 changes: 3 additions & 1 deletion assets/js/state/sagas/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,9 @@ function* initialDataFetch() {
yield put(stopHostsLoading());

yield put(startClustersLoading());
const { data: clusters } = yield call(get, '/clusters');
const { data: clusters } = yield call(get, '/clusters', {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess for now this is enough.
However at a certain point I'd find it of great help having something like yield call(getV2, '/clusters');
Feel free to keep it as you did for now.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fair enough. I wanted to keep the current changes minimalist.
This wouldn't require many changes, simply to add 4 new functions (get, post, del, put) with that naming.
Let's keep it on the radar

baseURL: '/api/v2',
});
yield put(setClusters(clusters));
yield put(stopClustersLoading());

Expand Down
2 changes: 1 addition & 1 deletion lib/trento/application/projectors/cluster_projector.ex
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ defmodule Trento.ClusterProjector do
repo: Trento.Repo,
name: "cluster_projector"

alias TrentoWeb.V1.ClusterView
alias TrentoWeb.V2.ClusterView

alias Trento.Domain.Events.{
ChecksSelected,
Expand Down
27 changes: 27 additions & 0 deletions lib/trento_web/controllers/v2/cluster_controller.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
defmodule TrentoWeb.V2.ClusterController do
use TrentoWeb, :controller
use OpenApiSpex.ControllerSpecs

alias Trento.Clusters

alias TrentoWeb.OpenApi.V2.Schema

plug OpenApiSpex.Plug.CastAndValidate, json_render_error_v2: true
action_fallback TrentoWeb.FallbackController

operation :list,
summary: "List Pacemaker Clusters",
tags: ["Target Infrastructure"],
description: "List all the discovered Pacemaker Clusters on the target infrastructure",
responses: [
ok:
{"A collection of the discovered Pacemaker Clusters", "application/json",
Schema.Cluster.PacemakerClustersCollection}
]

def list(conn, _) do
clusters = Clusters.get_all_clusters()

render(conn, "clusters.json", clusters: clusters)
end
end
22 changes: 9 additions & 13 deletions lib/trento_web/openapi/v1/schema/cluster.ex
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ defmodule TrentoWeb.OpenApi.V1.Schema.Cluster do
@moduledoc false

require OpenApiSpex
require Trento.Domain.Enums.ClusterType, as: ClusterType

alias OpenApiSpex.Schema

Expand Down Expand Up @@ -37,13 +36,12 @@ defmodule TrentoWeb.OpenApi.V1.Schema.Cluster do
site: %Schema{type: :string},
hana_status: %Schema{type: :string},
attributes: %Schema{
title: "ClusterNodeAttributes",
type: :array,
items: %Schema{type: :string}
type: :object,
arbulu89 marked this conversation as resolved.
Show resolved Hide resolved
description: "Node attributes",
additionalProperties: %Schema{type: :string}
},
virtual_ip: %Schema{type: :string},
resources: %Schema{
title: "ClustrNodeResources",
description: "A list of Cluster resources",
type: :array,
items: ClusterResource
Expand All @@ -57,7 +55,7 @@ defmodule TrentoWeb.OpenApi.V1.Schema.Cluster do

OpenApiSpex.schema(%{
title: "SbdDevice",
description: "Ad Sbd Device",
description: "SBD Device",
type: :object,
properties: %{
device: %Schema{type: :string},
Expand All @@ -83,30 +81,28 @@ defmodule TrentoWeb.OpenApi.V1.Schema.Cluster do
sr_health_state: %Schema{type: :string, description: "SR health state"},
fencing_type: %Schema{type: :string, description: "Fencing Type"},
stopped_resources: %Schema{
title: "ClusterResource",
description: "A list of the stopped resources on this HANA Cluster",
type: :array,
items: ClusterResource
},
nodes: %Schema{
title: "HanaClusterNodes",
type: :array,
items: HanaClusterNode
},
sbd_devices: %Schema{
title: "SbdDevice",
type: :array,
items: SbdDevice
}
}
},
required: [:nodes]
})
end

defmodule Details do
@moduledoc false

OpenApiSpex.schema(%{
title: "PacemakerClusterDetail",
title: "PacemakerClusterDetails",
description: "Details of the detected PacemakerCluster",
nullable: true,
oneOf: [
Expand Down Expand Up @@ -135,11 +131,11 @@ defmodule TrentoWeb.OpenApi.V1.Schema.Cluster do
type: %Schema{
type: :string,
description: "Detected type of the cluster",
enum: ClusterType.values()
enum: [:hana_scale_up, :hana_scale_out, :unknown]
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using hardcoded values as they cannot be changed without adding non backward compatible changes.
This schema won't be updated anymore

},
selected_checks: %Schema{
title: "SelectedChecks",
description: "A list ids of the checks selected for execution on this cluster",
description: "A list of check ids selected for an execution on this cluster",
type: :array,
items: %Schema{type: :string}
},
Expand Down
8 changes: 8 additions & 0 deletions lib/trento_web/openapi/v2/api_spec.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
defmodule TrentoWeb.OpenApi.V2.ApiSpec do
@moduledoc """
OpenApi specification entry point for V2 version
"""

use TrentoWeb.OpenApi.ApiSpec,
api_version: "v2"
end
176 changes: 176 additions & 0 deletions lib/trento_web/openapi/v2/schema/cluster.ex
Original file line number Diff line number Diff line change
@@ -0,0 +1,176 @@
defmodule TrentoWeb.OpenApi.V2.Schema.Cluster do
@moduledoc false

require OpenApiSpex
require Trento.Domain.Enums.ClusterType, as: ClusterType

alias OpenApiSpex.Schema

alias TrentoWeb.OpenApi.V1.Schema.{Cluster, Provider, ResourceHealth, Tags}

defmodule AscsErsClusterNode do
@moduledoc false

OpenApiSpex.schema(%{
title: "AscsErsClusterNode",
description: "ASCS/ERS Cluster Node",
type: :object,
properties: %{
attributes: %Schema{
type: :object,
arbulu89 marked this conversation as resolved.
Show resolved Hide resolved
description: "Node attributes",
additionalProperties: %Schema{type: :string}
},
filesystems: %Schema{
type: :array,
items: %Schema{type: :string},
description: "List of filesystems managed in this node"
},
name: %Schema{
type: :string,
description: "Node name"
},
resources: %Schema{
type: :array,
items: Cluster.ClusterResource,
description: "A list of Cluster resources"
},
roles: %Schema{
type: :array,
items: %Schema{type: :string, enum: ["ascs", "ers"]},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This mean that we can have at most two roles, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, one node can have from 0 to 2 roles for each SAP system.
The normal scenario is when one node is only ascs and the other ers, but during a failover, one nodes takes both roles and the other none.
PD: Creating a tech-debt ticket to put the enum values in an Enum object, so we don't need to spread them all around the code

description: "List of roles managed in this node"
},
virtual_ips: %Schema{
type: :array,
items: %Schema{type: :string},
description: "List of virtual IPs managed in this node"
}
}
})
end

defmodule AscsErsClusterSAPSystem do
@moduledoc false

OpenApiSpex.schema(%{
title: "AscsErsClusterSAPSystem",
description: "SAP system managed by a ASCS/ERS cluster",
type: :object,
properties: %{
distributed: %Schema{
type: :boolean,
description: "ASCS and ERS instances are distributed and running in different nodes"
},
filesystem_resource_based: %Schema{
type: :boolean,
description:
"ASCS and ERS filesystems are handled by the cluster with the Filesystem resource agent"
},
nodes: %Schema{
type: :array,
items: AscsErsClusterNode,
description: "List of ASCS/ERS nodes for this SAP system"
}
}
})
end

defmodule AscsErsClusterDetails do
@moduledoc false

OpenApiSpex.schema(%{
title: "AscsErsClusterDetails",
description: "Details of a ASCS/ERS Pacemaker Cluster",
type: :object,
properties: %{
fencing_type: %Schema{
type: :string,
description: "Fencing type"
},
sap_systems: %Schema{
type: :array,
items: AscsErsClusterSAPSystem,
description: "List of managed SAP systems in a single or multi SID cluster"
},
sbd_devices: %Schema{
type: :array,
items: Cluster.SbdDevice,
description: "List of SBD devices used in the cluster"
},
stopped_resources: %Schema{
type: :array,
items: Cluster.ClusterResource,
description: "List of the stopped resources on this HANA Cluster"
}
},
required: [:sap_systems]
})
end

defmodule Details do
@moduledoc false

OpenApiSpex.schema(%{
title: "PacemakerClusterDetails",
description: "Details of the detected PacemakerCluster",
nullable: true,
oneOf: [
AscsErsClusterDetails,
Cluster.HanaClusterDetails
]
})
end

defmodule PacemakerCluster do
@moduledoc false

OpenApiSpex.schema(%{
title: "PacemakerCluster",
description: "A discovered Pacemaker Cluster on the target infrastructure",
type: :object,
properties: %{
id: %Schema{type: :string, description: "Cluster ID", format: :uuid},
name: %Schema{type: :string, description: "Cluster name"},
sid: %Schema{type: :string, description: "SID"},
additional_sids: %Schema{
type: :array,
items: %Schema{type: :string},
description: "Additionally discovered SIDs, such as ASCS/ERS cluster SIDs"
},
provider: Provider.SupportedProviders,
type: %Schema{
type: :string,
description: "Detected type of the cluster",
enum: ClusterType.values()
},
selected_checks: %Schema{
title: "SelectedChecks",
description: "A list of check ids selected for an execution on this cluster",
type: :array,
items: %Schema{type: :string}
},
health: ResourceHealth,
resources_number: %Schema{type: :integer, description: "Resource number", nullable: true},
hosts_number: %Schema{type: :integer, description: "Hosts number", nullable: true},
cib_last_written: %Schema{
type: :string,
description: "CIB last written date",
nullable: true
},
details: Details,
tags: Tags
}
})
end

defmodule PacemakerClustersCollection do
@moduledoc false

OpenApiSpex.schema(%{
title: "PacemakerClustersCollection",
description: "A list of the discovered Pacemaker Clusters",
type: :array,
items: PacemakerCluster
})
end
end
Loading