11//! Hub FVM API Client
22
3- use std:: env:: var;
4-
53use anyhow:: { Error , Result } ;
64use serde:: { Deserialize , Serialize } ;
75use url:: Url ;
86
97use crate :: fvm:: { Channel , PackageSet , PackageSetRecord } ;
108
11- const INFINYON_CI_CONTEXT : & str = "INFINYON_CI_CONTEXT" ;
12- const CONTEXT_QUERY_PARAM : & str = "ctx" ;
13-
149#[ derive( Debug , Deserialize , Serialize ) ]
1510pub struct ApiError {
1611 pub status : u16 ,
@@ -33,25 +28,30 @@ impl Client {
3328 /// Fetches a [`PackageSet`] from the Hub with the specific [`Channel`]
3429 pub async fn fetch_package_set ( & self , channel : & Channel , arch : & str ) -> Result < PackageSet > {
3530 use crate :: htclient:: ResponseExt ;
31+ use std:: collections:: HashMap ;
3632
37- let url = self . make_fetch_package_set_url ( channel, arch ) ?;
33+ let url = self . make_fetch_package_set_url ( channel) ?;
3834 let res = crate :: htclient:: get ( url)
3935 . await
4036 . map_err ( |err| Error :: msg ( err. to_string ( ) ) ) ?;
4137 let res_status = res. status ( ) ;
4238
4339 if res_status. is_success ( ) {
44- let pkgset_record = res. json :: < PackageSetRecord > ( ) . map_err ( |err| {
45- tracing:: debug!( ?err, "Failed to parse PackageSet from Hub " ) ;
46- Error :: msg ( "Failed to parse server's response " )
40+ let manifest = res. json :: < HashMap < String , PackageSetRecord > > ( ) . map_err ( |err| {
41+ tracing:: debug!( ?err, "Failed to parse manifest from GitHub releases " ) ;
42+ Error :: msg ( "Failed to parse manifest file " )
4743 } ) ?;
4844
45+ let pkgset_record = manifest
46+ . get ( arch)
47+ . ok_or_else ( || Error :: msg ( format ! ( "Architecture '{}' not found in manifest" , arch) ) ) ?;
48+
4949 tracing:: info!( ?pkgset_record, "Found PackageSet" ) ;
50- return Ok ( pkgset_record. into ( ) ) ;
50+ return Ok ( pkgset_record. clone ( ) . into ( ) ) ;
5151 }
5252
5353 let error = res. json :: < ApiError > ( ) . map_err ( |err| {
54- tracing:: debug!( ?err, "Failed to parse API Error from Hub " ) ;
54+ tracing:: debug!( ?err, "Failed to parse API Error" ) ;
5555 Error :: msg ( format ! ( "Server responded with status code {res_status}" ) )
5656 } ) ?;
5757
@@ -60,23 +60,23 @@ impl Client {
6060 Err ( anyhow:: anyhow!( error. message) )
6161 }
6262
63- /// Builds the URL to the Hub API for fetching a [`PackageSet`] using the
64- /// [`Client`]'s `api_url`.
65- fn make_fetch_package_set_url ( & self , channel : & Channel , arch : & str ) -> Result < Url > {
66- let mut url = Url :: parse ( & format ! (
67- "{}hub/v1/fvm/pkgset/{channel}" ,
63+ /// Builds the URL to fetch a [`PackageSet`] manifest from GitHub releases
64+ /// using the [`Client`]'s `api_url`.
65+ ///
66+ /// For example: https://github.com/fluvio-community/fluvio/releases/download/v0.18.1/manifest.json
67+ fn make_fetch_package_set_url ( & self , channel : & Channel ) -> Result < Url > {
68+ let version = match channel {
69+ Channel :: Stable => "stable" ,
70+ Channel :: Latest => "latest" ,
71+ Channel :: Tag ( v) => & format ! ( "v{}" , v) ,
72+ Channel :: Other ( s) => s. as_str ( ) ,
73+ } ;
74+
75+ let url = Url :: parse ( & format ! (
76+ "{}/releases/download/{}/manifest.json" ,
6877 self . api_url,
69- channel = channel ,
78+ version
7079 ) ) ?;
71- let mut params = url:: form_urlencoded:: Serializer :: new ( String :: new ( ) ) ;
72-
73- params. append_pair ( "arch" , arch) ;
74-
75- if let Ok ( ctx) = var ( INFINYON_CI_CONTEXT ) {
76- params. append_pair ( CONTEXT_QUERY_PARAM , ctx. as_str ( ) ) ;
77- }
78-
79- url. set_query ( Some ( params. finish ( ) . as_str ( ) ) ) ;
8080
8181 Ok ( url)
8282 }
@@ -85,77 +85,61 @@ impl Client {
8585#[ cfg( test) ]
8686mod tests {
8787 use std:: str:: FromStr ;
88- use std:: env:: { set_var, remove_var} ;
8988
9089 use url:: Url ;
9190 use semver:: Version ;
9291
93- use crate :: fvm:: api:: client:: INFINYON_CI_CONTEXT ;
94-
9592 use super :: { Client , Channel } ;
9693
9794 #[ test]
9895 fn creates_a_default_client ( ) {
99- let client = Client :: new ( "https://hub.infinyon.cloud " ) . unwrap ( ) ;
96+ let client = Client :: new ( "https://github.com/fluvio-community/fluvio " ) . unwrap ( ) ;
10097
10198 assert_eq ! (
10299 client. api_url,
103- Url :: parse( "https://hub.infinyon.cloud " ) . unwrap( )
100+ Url :: parse( "https://github.com/fluvio-community/fluvio " ) . unwrap( )
104101 ) ;
105102 }
106103
107104 #[ test]
108105 fn builds_urls_for_fetching_pkgsets ( ) {
109106 // Scenario: Using Stable Channel
110107
111- let client = Client :: new ( "https://hub.infinyon.cloud " ) . unwrap ( ) ;
108+ let client = Client :: new ( "https://github.com/fluvio-community/fluvio " ) . unwrap ( ) ;
112109 let url = client
113- . make_fetch_package_set_url ( & Channel :: Stable , "arm-unknown-linux-gnueabihf" )
110+ . make_fetch_package_set_url ( & Channel :: Stable )
114111 . unwrap ( ) ;
115112
116113 assert_eq ! (
117114 url. as_str( ) ,
118- "https://hub.infinyon.cloud/hub/v1/fvm/pkgset /stable?arch=arm-unknown-linux-gnueabihf " ,
115+ "https://github.com/fluvio-community/fluvio/releases/download /stable/manifest.json " ,
119116 "failed on Scenario Using Stable Channel"
120117 ) ;
121118
122- // Scenario: Using Tag
119+ // Scenario: Using Latest Channel
123120
124- let client = Client :: new ( "https://hub.infinyon.cloud " ) . unwrap ( ) ;
121+ let client = Client :: new ( "https://github.com/fluvio-community/fluvio " ) . unwrap ( ) ;
125122 let url = client
126- . make_fetch_package_set_url (
127- & Channel :: Tag ( Version :: from_str ( "0.10.14-dev+123345abc" ) . unwrap ( ) ) ,
128- "arm-unknown-linux-gnueabihf" ,
129- )
123+ . make_fetch_package_set_url ( & Channel :: Latest )
130124 . unwrap ( ) ;
131125
132126 assert_eq ! (
133127 url. as_str( ) ,
134- "https://hub.infinyon.cloud/hub/v1/fvm/pkgset/0.10.14-dev+123345abc?arch=arm-unknown-linux-gnueabihf " ,
135- "failed on Scenario Using Tag "
128+ "https://github.com/fluvio-community/fluvio/releases/download/latest/manifest.json " ,
129+ "failed on Scenario Using Latest Channel "
136130 ) ;
137131
138- // Scenario: Using Context
139-
140- unsafe {
141- set_var ( INFINYON_CI_CONTEXT , "unit_testing" ) ;
142- }
132+ // Scenario: Using Tag
143133
144- let client = Client :: new ( "https://hub.infinyon.cloud " ) . unwrap ( ) ;
134+ let client = Client :: new ( "https://github.com/fluvio-community/fluvio " ) . unwrap ( ) ;
145135 let url = client
146- . make_fetch_package_set_url (
147- & Channel :: Tag ( Version :: from_str ( "0.10.14-dev+123345abc" ) . unwrap ( ) ) ,
148- "arm-unknown-linux-gnueabihf" ,
149- )
136+ . make_fetch_package_set_url ( & Channel :: Tag ( Version :: from_str ( "0.10.14" ) . unwrap ( ) ) )
150137 . unwrap ( ) ;
151138
152139 assert_eq ! (
153140 url. as_str( ) ,
154- "https://hub.infinyon.cloud/hub/v1/fvm/pkgset/0 .10.14-dev+123345abc?arch=arm-unknown-linux-gnueabihf&ctx=unit_testing " ,
155- "failed on Scenario Using Context "
141+ "https://github.com/fluvio-community/fluvio/releases/download/v0 .10.14/manifest.json " ,
142+ "failed on Scenario Using Tag "
156143 ) ;
157- unsafe {
158- remove_var ( INFINYON_CI_CONTEXT ) ;
159- }
160144 }
161145}
0 commit comments