Skip to content

Commit

Permalink
Merge #742
Browse files Browse the repository at this point in the history
742: launch/find: Allow using and searching for unsupported cloud images r=Saviq a=townsend2010

This uses an `--allow-unsupported` option for `launch` and `find`.

Fixes #736

Co-authored-by: Chris Townsend <[email protected]>
  • Loading branch information
2 people authored and Saviq committed Apr 24, 2019
1 parent 3b27daf commit 263ceb7
Show file tree
Hide file tree
Showing 16 changed files with 99 additions and 36 deletions.
3 changes: 3 additions & 0 deletions completions/bash/multipass
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ _multipass_complete()
"recover"|"start"|"stop"|"suspend"|"restart")
opts="${opts} --all"
;;
"find")
opts="${opts} --show-unsupported"
;;
esac

if [[ ${prev} == -* ]]; then
Expand Down
5 changes: 2 additions & 3 deletions include/multipass/query.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -13,8 +13,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alberto Aguirre <[email protected]>
*
*/

#ifndef MULTIPASS_QUERY_H
Expand All @@ -39,6 +37,7 @@ class Query
bool persistent;
std::string remote_name;
Type query_type;
bool allow_unsupported{false};
};
}
#endif // MULTIPASS_QUERY_H
4 changes: 2 additions & 2 deletions include/multipass/vm_image_host.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -38,7 +38,7 @@ class VMImageHost
virtual optional<VMImageInfo> info_for(const Query& query) = 0;
virtual std::vector<VMImageInfo> all_info_for(const Query& query) = 0;
virtual VMImageInfo info_for_full_hash(const std::string& full_hash) = 0;
virtual std::vector<VMImageInfo> all_images_for(const std::string& remote_name) = 0;
virtual std::vector<VMImageInfo> all_images_for(const std::string& remote_name, const bool allow_unsupported) = 0;
virtual void for_each_entry_do(const Action& action) = 0;
virtual std::vector<std::string> supported_remotes() = 0;

Expand Down
9 changes: 8 additions & 1 deletion src/client/cmd/find.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -131,6 +131,8 @@ mp::ParseCode cmd::Find::parse_args(mp::ArgParser* parser)
"then search ‘daily‘. <string> can be a partial image hash or an "
"Ubuntu release version, codename or alias.",
"[<remote:>][<string>]");
QCommandLineOption unsupportedOption("show-unsupported", "Show unsupported cloud images as well");
parser->addOptions({unsupportedOption});

auto status = parser->commandParse(this);

Expand Down Expand Up @@ -165,5 +167,10 @@ mp::ParseCode cmd::Find::parse_args(mp::ArgParser* parser)
}
}

if (parser->isSet(unsupportedOption))
{
request.set_allow_unsupported(true);
}

return status;
}
3 changes: 2 additions & 1 deletion src/daemon/custom_image_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -199,7 +199,8 @@ mp::VMImageInfo mp::CustomVMImageHost::info_for_full_hash_impl(const std::string
return {};
}

std::vector<mp::VMImageInfo> mp::CustomVMImageHost::all_images_for(const std::string& remote_name)
std::vector<mp::VMImageInfo> mp::CustomVMImageHost::all_images_for(const std::string& remote_name,
const bool allow_unsupported)
{
std::vector<mp::VMImageInfo> images;
auto custom_manifest = manifest_from(remote_name);
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/custom_image_host.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2018 Canonical, Ltd.
* Copyright (C) 2018-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -46,7 +46,7 @@ class CustomVMImageHost final : public CommonVMImageHost

optional<VMImageInfo> info_for(const Query& query) override;
std::vector<VMImageInfo> all_info_for(const Query& query) override;
std::vector<VMImageInfo> all_images_for(const std::string& remote_name) override;
std::vector<VMImageInfo> all_images_for(const std::string& remote_name, const bool allow_unsupported) override;
std::vector<std::string> supported_remotes() override;

protected:
Expand Down
18 changes: 9 additions & 9 deletions src/daemon/daemon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,7 +88,7 @@ mp::Query query_from(const mp::LaunchRequest* request, const std::string& name)
else if (QString::fromStdString(image).startsWith("http"))
query_type = mp::Query::Type::HttpDownload;

return {name, image, false, request->remote_name(), query_type};
return {name, image, false, request->remote_name(), query_type, true};
}

auto make_cloud_init_vendor_config(const mp::SSHKeyProvider& key_provider, const std::string& time_zone,
Expand Down Expand Up @@ -757,8 +757,8 @@ try // clang-format on
throw std::runtime_error(fmt::format(
"{} is not a supported remote. Please use `multipass find` for list of supported images.", remote));

auto images_info =
it->second->all_info_for({"", request->search_string(), false, remote, Query::Type::Alias});
auto images_info = it->second->all_info_for(
{"", request->search_string(), false, remote, Query::Type::Alias, request->allow_unsupported()});

if (!images_info.empty())
{
Expand All @@ -769,8 +769,8 @@ try // clang-format on
{
for (const auto& image_host : config->image_hosts)
{
auto images_info =
image_host->all_info_for({"", request->search_string(), false, remote, Query::Type::Alias});
auto images_info = image_host->all_info_for(
{"", request->search_string(), false, remote, Query::Type::Alias, request->allow_unsupported()});

if (!images_info.empty())
{
Expand Down Expand Up @@ -822,7 +822,7 @@ try // clang-format on
if (it == remote_image_host_map.end())
throw std::runtime_error(fmt::format("Remote \"{}\" is unknown.", remote));

auto vm_images_info = it->second->all_images_for(remote);
auto vm_images_info = it->second->all_images_for(remote, request->allow_unsupported());
for (const auto& info : vm_images_info)
{
if (!info.aliases.empty())
Expand Down Expand Up @@ -850,12 +850,12 @@ try // clang-format on
{
std::unordered_set<std::string> image_found;
const auto default_remote{"release"};
auto action = [&response, &image_found, default_remote](const std::string& remote,
const mp::VMImageInfo& info) {
auto action = [&response, &image_found, default_remote, request](const std::string& remote,
const mp::VMImageInfo& info) {
if (!mp::platform::is_remote_supported(remote))
return;

if (info.supported)
if (info.supported || request->allow_unsupported())
{
if (image_found.find(info.release_title.toStdString()) == image_found.end())
{
Expand Down
15 changes: 7 additions & 8 deletions src/daemon/ubuntu_image_host.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand All @@ -13,8 +13,6 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Authored by: Alberto Aguirre <[email protected]>
*
*/

#include "ubuntu_image_host.h"
Expand Down Expand Up @@ -108,7 +106,7 @@ mp::optional<mp::VMImageInfo> mp::UbuntuVMImageHost::info_for(const Query& query

if (info)
{
if (!info->supported)
if (!info->supported && !query.allow_unsupported)
throw std::runtime_error(fmt::format("The {} release is no longer supported.", query.release));

return with_location_fully_resolved(QString::fromStdString(remote_url_from(remote_name)), *info);
Expand All @@ -132,7 +130,7 @@ std::vector<mp::VMImageInfo> mp::UbuntuVMImageHost::all_info_for(const Query& qu

if (info)
{
if (!info->supported)
if (!info->supported && !query.allow_unsupported)
throw std::runtime_error(fmt::format("The {} release is no longer supported.", query.release));

images.push_back(*info);
Expand All @@ -143,7 +141,7 @@ std::vector<mp::VMImageInfo> mp::UbuntuVMImageHost::all_info_for(const Query& qu

for (const auto& entry : manifest->products)
{
if (entry.id.startsWith(key) && entry.supported &&
if (entry.id.startsWith(key) && (entry.supported || query.allow_unsupported) &&
found_hashes.find(entry.id.toStdString()) == found_hashes.end())
{
images.push_back(
Expand Down Expand Up @@ -177,14 +175,15 @@ mp::VMImageInfo mp::UbuntuVMImageHost::info_for_full_hash_impl(const std::string
return mp::VMImageInfo{{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, -1};
}

std::vector<mp::VMImageInfo> mp::UbuntuVMImageHost::all_images_for(const std::string& remote_name)
std::vector<mp::VMImageInfo> mp::UbuntuVMImageHost::all_images_for(const std::string& remote_name,
const bool allow_unsupported)
{
std::vector<mp::VMImageInfo> images;
auto manifest = manifest_from(remote_name);

for (const auto& entry : manifest->products)
{
if (entry.supported)
if (entry.supported || allow_unsupported)
{
images.push_back(with_location_fully_resolved(QString::fromStdString(remote_url_from(remote_name)), entry));
}
Expand Down
4 changes: 2 additions & 2 deletions src/daemon/ubuntu_image_host.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -40,7 +40,7 @@ class UbuntuVMImageHost final : public CommonVMImageHost

optional<VMImageInfo> info_for(const Query& query) override;
std::vector<VMImageInfo> all_info_for(const Query& query) override;
std::vector<VMImageInfo> all_images_for(const std::string& remote_name) override;
std::vector<VMImageInfo> all_images_for(const std::string& remote_name, const bool allow_unsupported) override;
std::vector<std::string> supported_remotes() override;

protected:
Expand Down
1 change: 1 addition & 0 deletions src/rpc/multipass.proto
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ message FindRequest {
string search_string = 1;
string remote_name = 2;
int32 verbosity_level = 3;
bool allow_unsupported = 4;
}

message FindReply {
Expand Down
5 changes: 3 additions & 2 deletions tests/stub_image_host.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -41,7 +41,8 @@ struct StubVMImageHost final : public multipass::VMImageHost
return {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, -1};
};

std::vector<multipass::VMImageInfo> all_images_for(const std::string& remote_name) override
std::vector<multipass::VMImageInfo> all_images_for(const std::string& remote_name,
const bool allow_unsupported) override
{
return {};
};
Expand Down
7 changes: 7 additions & 0 deletions tests/test_cli_client.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,13 @@ TEST_F(Client, delete_cmd_accepts_purge_option)
EXPECT_THAT(send_command({"delete", "-p", "bar"}), Eq(mp::ReturnCode::Ok));
}

// find cli tests
TEST_F(Client, find_cmd_unsupported_option_ok)
{
EXPECT_CALL(mock_daemon, find(_, _, _));
EXPECT_THAT(send_command({"find", "--show-unsupported"}), Eq(mp::ReturnCode::Ok));
}

TEST_F(Client, help_returns_ok_return_code)
{
EXPECT_THAT(send_command({"--help"}), Eq(mp::ReturnCode::Ok));
Expand Down
2 changes: 1 addition & 1 deletion tests/test_custom_image_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ TEST_F(CustomImageHost, all_images_for_snapcraft_returns_two_matches)
{
mp::CustomVMImageHost host{&url_downloader, default_ttl, test_path};

auto images = host.all_images_for("snapcraft");
auto images = host.all_images_for("snapcraft", false);

const size_t expected_matches{2};
EXPECT_THAT(images.size(), Eq(expected_matches));
Expand Down
34 changes: 34 additions & 0 deletions tests/test_data/releases/multiple_versions_manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -105,6 +105,40 @@
"pubname": "ubuntu-zesty-17.04-amd64-server-20170619.1"
}
}
},
"com.ubuntu.cloud:server:17.10:amd64": {
"aliases": "17.10,a,artful",
"arch": "amd64",
"os": "ubuntu",
"release": "artful",
"release_codename": "Artful Aardvark",
"release_title": "17.10",
"support_eol": "2018-07-19",
"supported": false,
"version": "17.10",
"versions": {
"20171017": {
"items": {
"disk1.img": {
"ftype": "disk1.img",
"md5": "2d011144148d71d2745d0c5be6e785ab",
"path": "server/releases/artful/release-20171017/ubuntu-17.10-server-cloudimg-amd64.img",
"sha256": "520224efaaf49b15a976b49c7ce7f2bd2e5b161470d684b37a838933595c0520",
"size": 317849600
},
"lxd.tar.xz": {
"combined_squashfs_sha256": "d6b33e50f42d129cdd0d3ef0b267d79012e382380deb30f6e22b5f9910a1e8ec",
"ftype": "lxd.tar.xz",
"md5": "15241f00869ffebbeff53bc020b562c7",
"path": "server/releases/artful/release-20171017/ubuntu-17.10-server-cloudimg-amd64-lxd.tar.xz",
"sha256": "d421060416078ea4ec3a25953dd66b87efc937ef5edb16e64f9cb7ba9b8fad0a",
"size": 776
}
},
"label": "release",
"pubname": "ubuntu-artful-17.10-amd64-server-20171017"
}
}
}
},
"updated": "Thu, 18 May 2017 09:18:01 +0000"
Expand Down
4 changes: 2 additions & 2 deletions tests/test_image_vault.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (C) 2017-2018 Canonical, Ltd.
* Copyright (C) 2017-2019 Canonical, Ltd.
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
Expand Down Expand Up @@ -72,7 +72,7 @@ struct ImageHost : public mp::VMImageHost
return {{}, {}, {}, {}, {}, {}, {}, {}, {}, {}, -1};
}

std::vector<mp::VMImageInfo> all_images_for(const std::string& remote_name) override
std::vector<mp::VMImageInfo> all_images_for(const std::string& remote_name, const bool allow_unsupported) override
{
return {};
}
Expand Down
17 changes: 14 additions & 3 deletions tests/test_ubuntu_image_host.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -86,13 +86,14 @@ TEST_F(UbuntuImageHost, iterates_over_all_entries)
auto action = [&ids](const std::string& remote, const mp::VMImageInfo& info) { ids.insert(info.id.toStdString()); };
host.for_each_entry_do(action);

const size_t expected_entries{4};
const size_t expected_entries{5};
EXPECT_THAT(ids.size(), Eq(expected_entries));

EXPECT_THAT(ids.count("1797c5c82016c1e65f4008fcf89deae3a044ef76087a9ec5b907c6d64a3609ac"), Eq(1u));
EXPECT_THAT(ids.count("8842e7a8adb01c7a30cc702b01a5330a1951b12042816e87efd24b61c5e2239f"), Eq(1u));
EXPECT_THAT(ids.count("1507bd2b3288ef4bacd3e699fe71b827b7ccf321ec4487e168a30d7089d3c8e4"), Eq(1u));
EXPECT_THAT(ids.count("ab115b83e7a8bebf3d3a02bf55ad0cb75a0ed515fcbc65fb0c9abe76c752921c"), Eq(1u));
EXPECT_THAT(ids.count("520224efaaf49b15a976b49c7ce7f2bd2e5b161470d684b37a838933595c0520"), Eq(1u));
}

TEST_F(UbuntuImageHost, can_query_by_hash)
Expand Down Expand Up @@ -184,17 +185,27 @@ TEST_F(UbuntuImageHost, all_images_for_release_returns_four_matches)
{
mp::UbuntuVMImageHost host{all_remote_specs, &url_downloader, default_ttl};

auto images = host.all_images_for(release_remote_spec.first);
auto images = host.all_images_for(release_remote_spec.first, false);

const size_t expected_matches{4};
EXPECT_THAT(images.size(), Eq(expected_matches));
}

TEST_F(UbuntuImageHost, all_images_for_release_unsupported_returns_five_matches)
{
mp::UbuntuVMImageHost host{all_remote_specs, &url_downloader, default_ttl};

auto images = host.all_images_for(release_remote_spec.first, true);

const size_t expected_matches{5};
EXPECT_THAT(images.size(), Eq(expected_matches));
}

TEST_F(UbuntuImageHost, all_images_for_daily_returns_two_matches)
{
mp::UbuntuVMImageHost host{all_remote_specs, &url_downloader, default_ttl};

auto images = host.all_images_for(daily_remote_spec.first);
auto images = host.all_images_for(daily_remote_spec.first, false);

const size_t expected_matches{2};
EXPECT_THAT(images.size(), Eq(expected_matches));
Expand Down

0 comments on commit 263ceb7

Please sign in to comment.