Skip to content

Commit

Permalink
add ci build, fix clippy and cargo fmt
Browse files Browse the repository at this point in the history
  • Loading branch information
andrusha committed Jul 25, 2023
1 parent 3eb4377 commit 62299d3
Show file tree
Hide file tree
Showing 10 changed files with 143 additions and 64 deletions.
71 changes: 71 additions & 0 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
name: CI

on:
push:

env:
CARGO_TERM_COLOR: always

jobs:

check:
name: Check
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Run cargo check
uses: actions-rs/cargo@v1
with:
command: check

test:
name: Test
strategy:
matrix:
platform: [ubuntu-latest, macos-latest, windows-latest]
runs-on: ${{ matrix.platform }}
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true

- name: Run cargo test
uses: actions-rs/cargo@v1
with:
command: test

lints:
name: Lints
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions-rs/toolchain@v1
with:
profile: minimal
toolchain: stable
override: true
components: rustfmt, clippy

- name: cargo fmt
uses: actions-rs/cargo@v1
with:
command: fmt
args: --all -- --check

- name: cargo clippy
uses: actions-rs/cargo@v1
with:
command: clippy
args: -- -D warnings
10 changes: 8 additions & 2 deletions jwt/examples/json_api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,10 @@ fn main() -> Result<()> {

println!("{}", &args.sql);

let url = format!("https://{}.snowflakecomputing.com/api/v2/statements", &args.account_identifier);
let url = format!(
"https://{}.snowflakecomputing.com/api/v2/statements",
&args.account_identifier
);
let auth = format!("Bearer {}", &jwt);
let resp = ureq::post(&url)
.set("X-Snowflake-Authorization-Token-Type", "KEYPAIR_JWT")
Expand All @@ -69,7 +72,10 @@ fn main() -> Result<()> {
}
Err(ureq::Error::Status(code, r)) => {
let rstr = r.into_string().context("consuming response")?;
println!("failed to execute statement, server replied with {}, {}", code, rstr);
println!(
"failed to execute statement, server replied with {}, {}",
code, rstr
);
}
Err(ureq::Error::Transport(tr)) => {
println!("transport error: {:?}", tr);
Expand Down
25 changes: 11 additions & 14 deletions jwt/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use base64::Engine;
use jsonwebtoken::{Algorithm, encode, EncodingKey, Header};
use openssl;
use jsonwebtoken::{encode, Algorithm, EncodingKey, Header};
use openssl::rsa::Rsa;
use serde::{Deserialize, Serialize};
use sha2::{Digest, Sha256};
use thiserror::Error;
Expand Down Expand Up @@ -56,17 +56,17 @@ mod jwt_numeric_date {

/// Serializes an OffsetDateTime to a Unix timestamp (milliseconds since 1970/1/1T00:00:00T)
pub fn serialize<S>(date: &OffsetDateTime, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
where
S: Serializer,
{
let timestamp = date.unix_timestamp();
serializer.serialize_i64(timestamp)
}

/// Attempts to deserialize an i64 and use as a Unix timestamp
pub fn deserialize<'de, D>(deserializer: D) -> Result<OffsetDateTime, D::Error>
where
D: Deserializer<'de>,
where
D: Deserializer<'de>,
{
OffsetDateTime::from_unix_timestamp(i64::deserialize(deserializer)?)
.map_err(|_| serde::de::Error::custom("invalid Unix timestamp value"))
Expand All @@ -77,7 +77,7 @@ fn pubkey_fingerprint(pubkey: &[u8]) -> String {
let mut hasher = Sha256::new();
hasher.update(pubkey);

base64::engine::general_purpose::STANDARD.encode(&hasher.finalize())
base64::engine::general_purpose::STANDARD.encode(hasher.finalize())
}

pub fn generate_jwt_token<T: AsRef<[u8]>>(
Expand All @@ -87,20 +87,17 @@ pub fn generate_jwt_token<T: AsRef<[u8]>>(
) -> Result<String, JwtError> {
// Reading a private key:
// rsa-2048.p8 -> public key -> der bytes -> hash
let privk = openssl::rsa::Rsa::private_key_from_pem(private_key_pem.as_ref())?;
let privk = Rsa::private_key_from_pem(private_key_pem.as_ref())?;
let pubk = privk.public_key_to_der()?;

let iss = format!(
"{}.SHA256:{}",
full_identifier,
pubkey_fingerprint(&pubk)
);
let iss = format!("{}.SHA256:{}", full_identifier, pubkey_fingerprint(&pubk));

let iat = OffsetDateTime::now_utc();
let exp = iat + Duration::days(1);

let claims = Claims::new(iss, full_identifier.to_owned(), iat, exp);
let ek = EncodingKey::from_rsa_der(&privk.private_key_to_der()?);

encode(&Header::new(Algorithm::RS256), &claims, &ek).map_err(|e| JwtEncodingError(e.to_string())).into()
encode(&Header::new(Algorithm::RS256), &claims, &ek)
.map_err(|e| JwtEncodingError(e.to_string()))
}
24 changes: 11 additions & 13 deletions snowflake-api/examples/filetransfer.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,8 @@
use anyhow::Result;
use arrow::util::pretty::pretty_format_batches;
use clap::Parser;
use std::fs;
use snowflake_api::{QueryResult, SnowflakeApi};
use std::fs;

extern crate snowflake_api;

Expand Down Expand Up @@ -63,18 +63,16 @@ async fn main() -> Result<()> {
Some(&args.role),
&pem,
)?
},
(None, Some(pwd)) => {
SnowflakeApi::with_password_auth(
&args.account_identifier,
&args.warehouse,
Some(&args.database),
Some(&args.schema),
&args.username,
Some(&args.role),
pwd,
)?
},
}
(None, Some(pwd)) => SnowflakeApi::with_password_auth(
&args.account_identifier,
&args.warehouse,
Some(&args.database),
Some(&args.schema),
&args.username,
Some(&args.role),
pwd,
)?,
_ => {
panic!("Either private key path or password must be set")
}
Expand Down
25 changes: 11 additions & 14 deletions snowflake-api/examples/run_sql.rs
Original file line number Diff line number Diff line change
@@ -1,13 +1,12 @@
extern crate snowflake_api;

use std::fs;
use anyhow::Result;
use arrow::util::pretty::pretty_format_batches;
use clap::Parser;
use std::fs;

use snowflake_api::{QueryResult, SnowflakeApi};


#[derive(clap::ValueEnum, Clone, Debug)]
enum Output {
Arrow,
Expand Down Expand Up @@ -77,18 +76,16 @@ async fn main() -> Result<()> {
Some(&args.role),
&pem,
)?
},
(None, Some(pwd)) => {
SnowflakeApi::with_password_auth(
&args.account_identifier,
&args.warehouse,
Some(&args.database),
Some(&args.schema),
&args.username,
Some(&args.role),
pwd,
)?
},
}
(None, Some(pwd)) => SnowflakeApi::with_password_auth(
&args.account_identifier,
&args.warehouse,
Some(&args.database),
Some(&args.schema),
&args.username,
Some(&args.role),
pwd,
)?,
_ => {
panic!("Either private key path or password must be set")
}
Expand Down
12 changes: 6 additions & 6 deletions snowflake-api/src/connection.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,18 @@ use url::Url;
use uuid::Uuid;

#[derive(Error, Debug)]
pub enum RequestError {
pub enum ConnectionError {
#[error(transparent)]
RequestError(#[from] reqwest::Error),

#[error(transparent)]
UrlParseError(#[from] url::ParseError),
UrlParsing(#[from] url::ParseError),

#[error(transparent)]
DeserializationError(#[from] serde_json::Error),
Deserialization(#[from] serde_json::Error),

#[error(transparent)]
InvalidHeaderError(#[from] header::InvalidHeaderValue),
InvalidHeader(#[from] header::InvalidHeaderValue),
}

struct QueryContext {
Expand Down Expand Up @@ -56,7 +56,7 @@ pub struct Connection {
}

impl Connection {
pub fn new() -> Result<Self, RequestError> {
pub fn new() -> Result<Self, ConnectionError> {
// use builder to fail safely, unlike client new
let client = ClientBuilder::new()
.user_agent("Rust/0.0.1")
Expand All @@ -77,7 +77,7 @@ impl Connection {
extra_get_params: &[(&str, &str)],
auth: Option<&str>,
body: impl serde::Serialize,
) -> Result<R, RequestError> {
) -> Result<R, ConnectionError> {
let context = query_type.query_context();

// todo: increment subsequent request ids (on retry?)
Expand Down
13 changes: 6 additions & 7 deletions snowflake-api/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,25 +12,24 @@ use object_store::ObjectStore;
use regex::Regex;
use thiserror::Error;

use crate::connection::{Connection, RequestError};
use session::{AuthError, Session};
use crate::connection::{Connection, ConnectionError};
use put_response::{PutResponse, S3PutResponse};
use query_response::QueryResponse;
use session::{AuthError, Session};

use crate::connection::QueryType;

mod auth_response;
mod connection;
mod error_response;
mod put_response;
mod query_response;
mod session;
mod auth_response;


#[derive(Error, Debug)]
pub enum SnowflakeApiError {
#[error(transparent)]
RequestError(#[from] RequestError),
RequestError(#[from] ConnectionError),

#[error(transparent)]
AuthError(#[from] AuthError),
Expand Down Expand Up @@ -173,7 +172,7 @@ impl SnowflakeApi {
let info = r.data.stage_info;
let (bucket_name, bucket_path) = info
.location
.split_once("/")
.split_once('/')
.ok_or(SnowflakeApiError::InvalidBucketPath(info.location.clone()))?;

let s3 = AmazonS3Builder::new()
Expand Down Expand Up @@ -234,7 +233,7 @@ impl SnowflakeApi {
if resp.data.returned == 0 {
log::info!("Got response with 0 rows");

return Ok(QueryResult::Empty);
Ok(QueryResult::Empty)
} else if let Some(json) = resp.data.rowset {
log::info!("Got JSON response");

Expand Down
2 changes: 2 additions & 0 deletions snowflake-api/src/put_response.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::error_response::ErrorResponse;
use serde::Deserialize;

// Mostly getting big S3PutResponse, no point in boxing it
#[allow(clippy::large_enum_variant)]
#[derive(Deserialize, Debug)]
#[serde(untagged)]
pub enum PutResponse {
Expand Down
2 changes: 2 additions & 0 deletions snowflake-api/src/query_response.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use crate::error_response::ErrorResponse;
use serde::Deserialize;

// Mostly getting big QueryResponseInt, no need to box it
#[allow(clippy::large_enum_variant)]
#[derive(Deserialize, Debug)]
#[serde(untagged)]
pub enum QueryResponse {
Expand Down
Loading

0 comments on commit 62299d3

Please sign in to comment.