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

refactor(web): replace NetworkClient with queries #1519

Merged
merged 50 commits into from
Aug 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
89a779c
Getting rid of network client
teclator Jul 29, 2024
7d7041e
fix(web): network types improvements
dgdavid Aug 3, 2024
dd2f88a
fix(web): network queries code formatting
dgdavid Aug 5, 2024
1f97471
fix(web): network utils improvements
dgdavid Aug 5, 2024
ced72d2
fix(web): NetworkPage improvements
dgdavid Aug 5, 2024
6dfd01b
fix(web) improve WifiNetworksListPage
dgdavid Aug 5, 2024
1c49e5d
Filter null values from networks
teclator Aug 5, 2024
9c03398
Fix undefined data case.
teclator Aug 5, 2024
935cd93
feature(web): add method to slugify strings
dgdavid Aug 7, 2024
12aa549
fix(web): add clear information about not found WiFi networks
dgdavid Aug 7, 2024
274e7a8
Some small fixes
teclator Aug 7, 2024
35249de
Continue adopting Typescript in network
teclator Aug 7, 2024
509a647
Killing network client
teclator Aug 7, 2024
7ddf4a1
fix(web): improve how select wifi networks
dgdavid Aug 7, 2024
574ddab
fix(web): drop leftover .filter
dgdavid Aug 7, 2024
320a372
chore(web): start testing WifiNetworksListPage components
dgdavid Aug 7, 2024
d681c48
fix(web): improve network types a bit
dgdavid Aug 8, 2024
4e506f3
fix(web): reactivate WifiConnectionForm tests
dgdavid Aug 8, 2024
1b2ec19
fix(web): WifiConnectionForm improvements
dgdavid Aug 8, 2024
bc49841
Remove network client
teclator Aug 8, 2024
afead73
chore(web): drop no longer needed network component
dgdavid Aug 8, 2024
09dbfc8
chore(web): drop orphan network client test
dgdavid Aug 8, 2024
60b2728
Select the configured network (like a hidden one)
teclator Aug 8, 2024
a3d0c4d
chore(web): reactivate network/ConnectionsTable tests
dgdavid Aug 8, 2024
6b5a0c5
chore(web): add more testing for network components
dgdavid Aug 8, 2024
f4a4445
chore(web): add tests for IpAddressInput network component
dgdavid Aug 8, 2024
217b934
fix(web): use right props for IpAddressInput
dgdavid Aug 9, 2024
078c7f1
chore(web): add tests for IpPrefixInput network component
dgdavid Aug 9, 2024
f404bc9
fix(web) network types adjustments
dgdavid Aug 9, 2024
d833469
chore(web) add missing test
dgdavid Aug 9, 2024
539c23c
Kill the network model completely
teclator Aug 9, 2024
4889a91
Merge branch 'master' into network_query_continue
dgdavid Aug 9, 2024
b28be07
Change some network http methods
teclator Aug 9, 2024
56df1f2
chore(web): make post and patch payloads optional
dgdavid Aug 10, 2024
7b74a34
chore(web): add more network types
dgdavid Aug 10, 2024
a56665c
chore(web): use `axios` for network too
dgdavid Aug 10, 2024
019156b
Defined as classes AccessPoint, Device and Connection
teclator Aug 12, 2024
2b6fcd5
Some leftover fixes
teclator Aug 12, 2024
32930e0
chore(web): migrate network components to TypeScript
dgdavid Aug 12, 2024
96d2b9b
refactor(web): stop exporting everything from network
dgdavid Aug 12, 2024
fb4ebb9
Small fixes
teclator Aug 13, 2024
d090cde
fix(web): mark param as optional
dgdavid Aug 13, 2024
29f4a73
fix(web): improve code readability
dgdavid Aug 13, 2024
0352995
fix(web): drop leftover console.log
dgdavid Aug 13, 2024
fab8a0a
fix(web): use ternary operator instead of checking a value twice
dgdavid Aug 13, 2024
f52a5ad
fix(web): typo
dgdavid Aug 13, 2024
d588c38
fix(web): adapt types and remove no longer needed ts-expect-error
dgdavid Aug 13, 2024
02220c0
Merge branch 'master' into network_query_continue
dgdavid Aug 13, 2024
27e17bb
Merge branch 'master' into network_query_continue
dgdavid Aug 14, 2024
80d11dd
Added test to securityFromFlags
teclator Aug 16, 2024
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
1 change: 1 addition & 0 deletions rust/agama-lib/src/network/settings.rs
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,7 @@ pub struct NetworkDevice {
}

#[derive(Clone, Debug, Default, Serialize, Deserialize, utoipa::ToSchema)]
#[serde(rename_all = "camelCase")]
pub struct NetworkConnection {
pub id: String,
#[serde(skip_serializing_if = "Option::is_none")]
Expand Down
14 changes: 7 additions & 7 deletions rust/agama-server/src/network/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ use axum::{
extract::{Path, State},
http::StatusCode,
response::{IntoResponse, Response},
routing::{delete, get, put},
routing::{delete, get, patch, post},
Json, Router,
};

Expand Down Expand Up @@ -101,10 +101,10 @@ pub async fn network_service<T: Adapter + Send + Sync + 'static>(
.put(update_connection)
.get(connection),
)
.route("/connections/:id/connect", get(connect))
.route("/connections/:id/disconnect", get(disconnect))
.route("/connections/:id/connect", patch(connect))
Copy link
Contributor

Choose a reason for hiding this comment

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

see below reasoning, but I think that post is better here then patch.

Copy link
Contributor

Choose a reason for hiding this comment

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

See #1519 (comment)

If you don't mind, we can postpone this discussion until @teclator and @imobachgs are back. As far as I know, this was a change agreed by them. So we can merge as it is and change our mind later if needed.

.route("/connections/:id/disconnect", patch(disconnect))
.route("/devices", get(devices))
.route("/system/apply", put(apply))
.route("/system/apply", post(apply))
Copy link
Contributor

Choose a reason for hiding this comment

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

what is rationale for this change? for me the main difference between post and put is idempotency. So when I call apply twice will it do two actions and only the first apply do something?

Copy link
Contributor

@dgdavid dgdavid Aug 13, 2024

Choose a reason for hiding this comment

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

If I correctly understood what @imobachgs told me last week, the rationale here is that we're using POST for these kind of actions, like it's the case of probing.

Copy link
Contributor

Choose a reason for hiding this comment

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

we are getting maybe too theoretical, but probe is not idempotent for me as next probe can find something else. But I think that apply is idempotent as it should not create/do something different.

.route("/wifi", get(wifi_networks))
.with_state(state))
}
Expand Down Expand Up @@ -293,7 +293,7 @@ async fn update_connection(
}

#[utoipa::path(
get,
patch,
path = "/connections/:id/connect",
context_path = "/api/network",
responses(
Expand Down Expand Up @@ -325,7 +325,7 @@ async fn connect(
}

#[utoipa::path(
get,
patch,
path = "/connections/:id/disconnect",
context_path = "/api/network",
responses(
Expand Down Expand Up @@ -357,7 +357,7 @@ async fn disconnect(
}

#[utoipa::path(
put,
post,
path = "/system/apply",
context_path = "/api/network",
responses(
Expand Down
36 changes: 0 additions & 36 deletions rust/data.json

This file was deleted.

4 changes: 2 additions & 2 deletions web/src/api/http.ts
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ const get = (url: string) => http.get(url).then(({ data }) => data);
* @param url - endpoint URL
* @param data - Request payload
*/
const patch = (url: string, data: object) => http.patch(url, data);
const patch = (url: string, data?: object) => http.patch(url, data);

/**
* Performs a PUT request with the given URL and data
Expand All @@ -55,7 +55,7 @@ const put = (url: string, data: object) => http.put(url, data);
* @param url - endpoint URL
* @param data - request payload
*/
const post = (url: string, data: object) => http.post(url, data);
const post = (url: string, data?: object) => http.post(url, data);
Copy link
Contributor

Choose a reason for hiding this comment

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

hmm, for both changes, does it make sense to have patch and post that does not provide data? It looks like bug for me.

Copy link
Contributor

Choose a reason for hiding this comment

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

after seeing below usage I would say that post change makes sense...but still for patch I kind of expect instructions how to modify source and below usage is at least confusing for me.

Copy link
Contributor

Choose a reason for hiding this comment

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

Which verbs use for which actions / request will be for sure a topic for discussions. I personally have to revisit all the spec for refreshing my mind about HTTP verbs and the best usage of them. But as per RFC, https://www.rfc-editor.org/rfc/rfc5789, patch does not require a payload. It's optional.

As you pasted in another comment, A PATCH request is considered a set of instructions on how to modify a resource. In the network case, we're using PATCH for request a connect or disconnect instructions (aka actions) which tells the server how to modify the resource: connection or disconnecting it.


/**
* Performs a DELETE request on the given URL
Expand Down
98 changes: 98 additions & 0 deletions web/src/api/network.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,98 @@
/*
* Copyright (c) [2024] SUSE LLC
*
* All Rights Reserved.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of version 2 of the GNU General Public License as published
* by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
* more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, contact SUSE LLC.
*
* To contact SUSE LLC about this file by physical or electronic mail, you may
* find current contact information at www.suse.com.
*/

import { del, get, patch, post, put } from "~/api/http";
import { APIAccessPoint, APIConnection, APIDevice, NetworkGeneralState } from "~/types/network";

/**
* Returns the network configuration
*/
const fetchState = (): Promise<NetworkGeneralState> => get("/api/network/state");

/**
* Returns a list of known devices
*/
const fetchDevices = (): Promise<APIDevice[]> => get("/api/network/devices");

/**
* Returns data for given connection name
*/
const fetchConnection = (name: string): Promise<APIConnection> =>
get(`/api/network/connections/${name}`);

/**
* Returns the list of known connections
*/
const fetchConnections = (): Promise<APIConnection[]> => get("/api/network/connections");

/**
* Returns the list of known access points
*/
const fetchAccessPoints = (): Promise<APIAccessPoint[]> => get("/api/network/wifi");

/**
* Adds a new connection
*
* @param connection - connection to be added
*/
const addConnection = (connection: APIConnection) => post("/api/network/connections", connection);

/**
* Updates given connection
*
* @param connection - connection to be added
*/
const updateConnection = (connection: APIConnection) =>
put(`/api/network/connections/${connection.id}`, connection);

/**
* Deletes the connection matching given name
*/
const deleteConnection = (name: string) => del(`/api/network/connections/${name}`);

/**
* Apply network changes
*/
const applyChanges = () => post("/api/network/system/apply");

/**
* Performs the connect action for connection matching given name
*/
const connect = (name: string) => patch(`/api/network/connections/${name}/connect`);
Copy link
Contributor

Choose a reason for hiding this comment

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

to be honest, I do not get here why it is patch..for patch it should contain patch structure that changes connection object. https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/PATCH mentions that A PATCH request is considered a set of instructions on how to modify a resource. Contrast this with PUT which is a complete representation of a resource. So here I expect that for connect and disconnect it is more like action like apply that uses POST above.

Copy link
Contributor

Choose a reason for hiding this comment

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

As commented at #1519 (comment), you can think in these actions as the instructions you're requesting for modifying the connection state.

As I said in linked comment, I still having pending to refresh the HTTP verbs/requests. But I tend to think in POST as a request for creating something or appending more data to a resource (although for the latest I'd use a PUT). Also, I expect that servers returns the resource representation or at least where to retrieve it. None of these are the case for connect and disconnect actions for which we are just requiring a change in the connection state, a request side-effect.


/**
* Performs the disconnect action for connection matching given name
*/
const disconnect = (name: string) => patch(`/api/network/connections/${name}/disconnect`);

export {
fetchState,
fetchDevices,
fetchConnection,
fetchConnections,
fetchAccessPoints,
applyChanges,
addConnection,
updateConnection,
deleteConnection,
connect,
disconnect,
};
4 changes: 0 additions & 4 deletions web/src/client/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -24,14 +24,12 @@
import { L10nClient } from "./l10n";
import { ManagerClient } from "./manager";
import { StorageClient } from "./storage";
import { NetworkClient } from "./network";
import { HTTPClient, WSClient } from "./http";

/**
* @typedef {object} InstallerClient
* @property {L10nClient} l10n - localization client.
* @property {ManagerClient} manager - manager client.
* @property {NetworkClient} network - network client.
* @property {StorageClient} storage - storage client.
* @property {() => WSClient} ws - Agama WebSocket client.
* @property {() => boolean} isConnected - determines whether the client is connected
Expand All @@ -53,7 +51,6 @@ const createClient = (url) => {
const l10n = new L10nClient(client);
// TODO: unify with the manager client
const manager = new ManagerClient(client);
const network = new NetworkClient(client);
const storage = new StorageClient(client);

const isConnected = () => client.ws().isConnected() || false;
Expand All @@ -62,7 +59,6 @@ const createClient = (url) => {
return {
l10n,
manager,
network,
storage,
isConnected,
isRecoverable,
Expand Down
120 changes: 0 additions & 120 deletions web/src/client/network.test.js

This file was deleted.

Loading
Loading