Skip to content

Commit

Permalink
Merge pull request #1689 from habitat-sh/psajja/enhance-bldr-info
Browse files Browse the repository at this point in the history
Enhance builder info
  • Loading branch information
sajjaphani authored Jan 12, 2022
2 parents bb4bb6a + b2f8fa7 commit 1d97217
Show file tree
Hide file tree
Showing 8 changed files with 124 additions and 27 deletions.
55 changes: 32 additions & 23 deletions components/builder-api/src/server/resources/pkgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,8 @@

use crate::{bldr_core::{error::Error::RpcError,
metrics::CounterMetric},
db::models::{channel::Channel,
db::models::{channel::{Channel,
ChannelWithPromotion},
origin::*,
package::{BuilderPackageIdent,
BuilderPackageTarget,
Expand Down Expand Up @@ -228,15 +229,15 @@ fn get_packages_for_origin_package_version(req: HttpRequest,
}

#[allow(clippy::needless_pass_by_value)]
fn get_latest_package_for_origin_package(req: HttpRequest,
path: Path<(String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
async fn get_latest_package_for_origin_package(req: HttpRequest,
path: Path<(String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
let (origin, pkg) = path.into_inner();

let ident = PackageIdent::new(origin, pkg, None, None);

match do_get_package(&req, &qtarget, &ident) {
match do_get_package(&req, &qtarget, &ident).await {
Ok(json_body) => {
HttpResponse::Ok().append_header((http::header::CONTENT_TYPE,
headers::APPLICATION_JSON))
Expand All @@ -252,15 +253,15 @@ fn get_latest_package_for_origin_package(req: HttpRequest,
}

#[allow(clippy::needless_pass_by_value)]
fn get_latest_package_for_origin_package_version(req: HttpRequest,
path: Path<(String, String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
async fn get_latest_package_for_origin_package_version(req: HttpRequest,
path: Path<(String, String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
let (origin, pkg, version) = path.into_inner();

let ident = PackageIdent::new(origin, pkg, Some(version), None);

match do_get_package(&req, &qtarget, &ident) {
match do_get_package(&req, &qtarget, &ident).await {
Ok(json_body) => {
HttpResponse::Ok().append_header((http::header::CONTENT_TYPE,
headers::APPLICATION_JSON))
Expand All @@ -276,15 +277,15 @@ fn get_latest_package_for_origin_package_version(req: HttpRequest,
}

#[allow(clippy::needless_pass_by_value)]
fn get_package(req: HttpRequest,
path: Path<(String, String, String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
async fn get_package(req: HttpRequest,
path: Path<(String, String, String, String)>,
qtarget: Query<Target>)
-> HttpResponse {
let (origin, pkg, version, release) = path.into_inner();

let ident = PackageIdent::new(origin, pkg, Some(version), Some(release));

match do_get_package(&req, &qtarget, &ident) {
match do_get_package(&req, &qtarget, &ident).await {
Ok(json_body) => {
HttpResponse::Ok().append_header((http::header::CONTENT_TYPE,
headers::APPLICATION_JSON))
Expand Down Expand Up @@ -693,9 +694,8 @@ fn get_package_channels(req: HttpRequest,
&*conn)
{
Ok(channels) => {
let list: Vec<String> = channels.iter()
.map(|channel| channel.name.to_string())
.collect();
let list: Vec<ChannelWithPromotion> =
channels.into_iter().map(|channel| channel.into()).collect();
HttpResponse::Ok().append_header((http::header::CACHE_CONTROL, headers::NO_CACHE))
.json(list)
}
Expand Down Expand Up @@ -1308,10 +1308,10 @@ async fn do_upload_package_async(req: HttpRequest,
}
}

fn do_get_package(req: &HttpRequest,
qtarget: &Query<Target>,
ident: &PackageIdent)
-> Result<String> {
async fn do_get_package(req: &HttpRequest,
qtarget: &Query<Target>,
ident: &PackageIdent)
-> Result<String> {
let opt_session_id = match authorize_session(req, None, None) {
Ok(session) => Some(session.get_id()),
Err(_) => None,
Expand Down Expand Up @@ -1428,6 +1428,15 @@ fn do_get_package(req: &HttpRequest,

pkg_json["channels"] = json!(channels);
pkg_json["is_a_service"] = json!(pkg.is_a_service());
let size = match req_state(req).packages.size_of(ident, target).await {
Ok(size) => size,
Err(err) => {
debug!("Could not get size for {:?}, {:?}", ident, err);
0
}
};

pkg_json["size"] = json!(size);

let json_body = serde_json::to_string(&pkg_json).unwrap();

Expand Down
2 changes: 2 additions & 0 deletions components/builder-api/src/server/services/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ pub enum Counter {
SingleUploadRequests,
MultipartUploadRequests,
DownloadRequests,
SizeRequests,
UploadFailures,
AtomicChannelRequests,
MemcacheMemberRoleHit,
Expand All @@ -54,6 +55,7 @@ impl metrics::Metric for Counter {
Counter::SingleUploadRequests => "upload-single".into(),
Counter::MultipartUploadRequests => "upload-multi".into(),
Counter::DownloadRequests => "download-packages".into(),
Counter::SizeRequests => "size-packages".into(),
Counter::UploadFailures => "upload-failures".into(),
Counter::AtomicChannelRequests => "channel-to-channel".into(),
Counter::MemcacheMemberRoleHit => "memcache-session.hit".into(),
Expand Down
23 changes: 22 additions & 1 deletion components/builder-api/src/server/services/s3.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ use rusoto_s3::{CompleteMultipartUploadRequest,
UploadPartRequest,
S3};

use rusoto_core::HttpClient;
use rusoto_core::{HttpClient,
RusotoError};

use super::metrics::Counter;
use crate::{bldr_core::metrics::CounterMetric,
Expand Down Expand Up @@ -211,6 +212,26 @@ impl S3Handler {
}
}

pub async fn size_of(&self, ident: &PackageIdent, target: PackageTarget) -> Result<i64> {
Counter::SizeRequests.increment();
let mut request = HeadObjectRequest::default();
let key = s3_key(ident, target)?;
request.bucket = self.bucket.to_owned();
request.key = key;

let payload = self.client.head_object(request).await;
match payload {
Ok(response) =>
response.content_length.ok_or_else(|| Error::HeadObject(RusotoError::ParseError(String::from("Content length parse error"))))
,
Err(e) => {
warn!("Failed to retrieve object metadata from S3, ident={}: {:?}",
ident, e);
Err(Error::HeadObject(e))
}
}
}

async fn single_upload<P: Into<PathBuf>>(&self,
key: &str,
hart: File,
Expand Down
15 changes: 15 additions & 0 deletions components/builder-db/src/models/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,13 @@ pub struct Channel {
pub origin: String,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct ChannelWithPromotion {
pub name: String,
pub created_at: Option<NaiveDateTime>,
pub promoted_at: Option<NaiveDateTime>,
}

#[derive(Insertable)]
#[table_name = "origin_channels"]
pub struct CreateChannel<'a> {
Expand Down Expand Up @@ -488,6 +495,14 @@ impl From<AuditPackage> for AuditPackageEvent {
}
}

impl From<Channel> for ChannelWithPromotion {
fn from(value: Channel) -> ChannelWithPromotion {
ChannelWithPromotion { name: value.name.clone(),
created_at: value.created_at,
promoted_at: value.updated_at, }
}
}

#[derive(Debug, Serialize, Deserialize, Insertable)]
#[table_name = "audit_package"]
pub struct PackageChannelAudit<'a> {
Expand Down
14 changes: 14 additions & 0 deletions test/builder-api/src/channels.js
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,20 @@ describe('Channels API', function () {
});
});

it('Check the package channels after package promotion', function (done) {
request.get(`/depot/pkgs/neurosis/testapp/0.1.3/20171205003213/channels`)
.type('application/json')
.accept('application/json')
.set('Authorization', global.boboBearer)
.expect(200)
.end(function (err, res) {
expect(res.body.length).to.equal(2);
expect(res.body[0].name).to.equal('unstable');
expect(res.body[1].name).to.equal('foo');
done(err);
});
});

it('tests builder events after putting a specified package into the specified channel', function (done) {
const url = appendDateRange('/depot/events');
request.get(url)
Expand Down
1 change: 0 additions & 1 deletion test/builder-api/src/jobs.js
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,6 @@ describe("Jobs API", function () {
.set("Authorization", global.boboBearer)
.expect(200)
.end(function (err, res) {
console.log(res.body);
expect(res.body.range_start).to.equal(0);
expect(res.body.range_end).to.equal(0);
expect(res.body.total_count).to.equal(1);
Expand Down
40 changes: 39 additions & 1 deletion test/builder-api/src/packages.js
Original file line number Diff line number Diff line change
Expand Up @@ -950,7 +950,7 @@ describe('Working with packages', function () {
.expect(200)
.end(function (err, res) {
expect(res.body.length).to.equal(1);
expect(res.body[0]).to.equal('unstable');
expect(res.body[0].name).to.equal('unstable');
done(err);
});
});
Expand Down Expand Up @@ -993,6 +993,18 @@ describe('Working with packages', function () {
});
});

// TODO supposed to be 404, but receiving an ampty array
it('unauthenticated users cannot view private package channels', function (done) {
request.get(`/depot/pkgs/neurosis/testapp/0.1.3/${release2}/channels`)
.type('application/json')
.accept('application/json')
.expect(200)
.end(function (err, res) {
expect(res.body.length).to.equal(0);
done(err);
});
});

it('does not let members of other origins view private packages', function (done) {
request.get(`/depot/pkgs/neurosis/testapp/0.1.3/${release2}`)
.type('application/json')
Expand Down Expand Up @@ -1033,6 +1045,32 @@ describe('Working with packages', function () {
done(err);
});
});

// TODO supposed to be 404, but receiving an ampty array
it('does not let members of the other origin to view private package channels', function (done) {
request.get(`/depot/pkgs/neurosis/testapp/0.1.3/${release2}/channels`)
.type('application/json')
.accept('application/json')
.set('Authorization', global.mystiqueBearer)
.expect(200)
.end(function (err, res) {
expect(res.body.length).to.equal(0);
done(err);
});
});

it('allows owners of the origin to view private package channels', function (done) {
request.get(`/depot/pkgs/neurosis/testapp/0.1.3/${release2}/channels`)
.type('application/json')
.accept('application/json')
.set('Authorization', global.boboBearer)
.expect(200)
.end(function (err, res) {
expect(res.body.length).to.equal(1);
expect(res.body[0].name).to.equal('unstable');
done(err);
});
});
});

describe('Behavior of non-standard version packages', function () {
Expand Down
1 change: 0 additions & 1 deletion test/builder-api/src/projects.js
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,6 @@ describe('Projects API', function () {
.send(dependentProjectCreatePayload)
.expect(201)
.end(function (err, res) {
console.log(res.body);
dependentProjectExpectations(res);
done(err);
});
Expand Down

0 comments on commit 1d97217

Please sign in to comment.