1 // 2 // Copyright (C) 2019 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 #pragma once 17 18 #include <chrono> 19 #include <functional> 20 #include <memory> 21 #include <ostream> 22 #include <string> 23 #include <tuple> 24 #include <utility> 25 #include <variant> 26 #include <vector> 27 28 #include "common/libs/utils/result.h" 29 #include "host/libs/web/credential_source.h" 30 #include "host/libs/web/http_client/http_client.h" 31 32 namespace cuttlefish { 33 34 class Artifact { 35 public: 36 Artifact(const Json::Value&); Artifact(std::string name)37 Artifact(std::string name) : name_(std::move(name)) {} 38 Name()39 const std::string& Name() const { return name_; } Size()40 size_t Size() const { return size_; } LastModifiedTime()41 unsigned long LastModifiedTime() const { return last_modified_time_; } Md5()42 const std::string& Md5() const { return md5_; } ContentType()43 const std::string& ContentType() const { return content_type_; } Revision()44 const std::string& Revision() const { return revision_; } CreationTime()45 unsigned long CreationTime() const { return creation_time_; } Crc32()46 unsigned int Crc32() const { return crc32_; } 47 48 private: 49 std::string name_; 50 size_t size_; 51 unsigned long last_modified_time_; 52 std::string md5_; 53 std::string content_type_; 54 std::string revision_; 55 unsigned long creation_time_; 56 unsigned int crc32_; 57 }; 58 59 struct DeviceBuild { DeviceBuildDeviceBuild60 DeviceBuild(std::string id, std::string target) 61 : id(std::move(id)), target(std::move(target)) {} 62 63 std::string id; 64 std::string target; 65 std::string product; 66 }; 67 68 std::ostream& operator<<(std::ostream&, const DeviceBuild&); 69 70 struct DirectoryBuild { 71 // TODO(schuffelen): Support local builds other than "eng" 72 DirectoryBuild(std::vector<std::string> paths, std::string target); 73 74 std::vector<std::string> paths; 75 std::string target; 76 std::string id; 77 std::string product; 78 }; 79 80 std::ostream& operator<<(std::ostream&, const DirectoryBuild&); 81 82 using Build = std::variant<DeviceBuild, DirectoryBuild>; 83 84 std::ostream& operator<<(std::ostream&, const Build&); 85 86 class BuildApi { 87 public: 88 BuildApi(); 89 BuildApi(std::unique_ptr<HttpClient>, std::unique_ptr<CredentialSource>); 90 BuildApi(std::unique_ptr<HttpClient>, std::unique_ptr<HttpClient>, 91 std::unique_ptr<CredentialSource>, std::string api_key, 92 const std::chrono::seconds retry_period); 93 ~BuildApi() = default; 94 95 Result<std::string> LatestBuildId(const std::string& branch, 96 const std::string& target); 97 98 // download the artifact from the build and apply the callback 99 Result<void> ArtifactToCallback(const DeviceBuild& build, 100 const std::string& artifact, 101 HttpClient::DataCallback callback); 102 103 // determine the format of the build source argument and parse for the 104 // relevant build identifiers 105 Result<Build> ArgumentToBuild(const std::string& arg, 106 const std::string& default_build_target); 107 108 Result<std::string> DownloadFile(const Build& build, 109 const std::string& target_directory, 110 const std::string& artifact_name); 111 112 Result<std::string> DownloadFileWithBackup( 113 const Build& build, const std::string& target_directory, 114 const std::string& artifact_name, 115 const std::string& backup_artifact_name); 116 117 private: 118 Result<std::vector<std::string>> Headers(); 119 120 Result<std::string> BuildStatus(const DeviceBuild&); 121 122 Result<std::string> ProductName(const DeviceBuild&); 123 124 Result<std::vector<Artifact>> Artifacts( 125 const DeviceBuild& build, 126 const std::vector<std::string>& artifact_filenames); 127 128 Result<std::vector<Artifact>> Artifacts( 129 const DirectoryBuild& build, 130 const std::vector<std::string>& artifact_filenames); 131 Artifacts(const Build & build,const std::vector<std::string> & artifact_filenames)132 Result<std::vector<Artifact>> Artifacts( 133 const Build& build, const std::vector<std::string>& artifact_filenames) { 134 auto res = std::visit( 135 [this, &artifact_filenames](auto&& arg) { 136 return Artifacts(arg, artifact_filenames); 137 }, 138 build); 139 return CF_EXPECT(std::move(res)); 140 } 141 142 Result<void> ArtifactToFile(const DeviceBuild& build, 143 const std::string& artifact, 144 const std::string& path); 145 146 Result<void> ArtifactToFile(const DirectoryBuild& build, 147 const std::string& artifact, 148 const std::string& path); 149 ArtifactToFile(const Build & build,const std::string & artifact,const std::string & path)150 Result<void> ArtifactToFile(const Build& build, const std::string& artifact, 151 const std::string& path) { 152 auto res = std::visit( 153 [this, &artifact, &path](auto&& arg) { 154 return ArtifactToFile(arg, artifact, path); 155 }, 156 build); 157 CF_EXPECT(std::move(res)); 158 return {}; 159 } 160 161 Result<std::string> DownloadTargetFile(const Build& build, 162 const std::string& target_directory, 163 const std::string& artifact_name); 164 165 std::unique_ptr<HttpClient> http_client; 166 std::unique_ptr<HttpClient> inner_http_client; 167 std::unique_ptr<CredentialSource> credential_source; 168 std::string api_key_; 169 std::chrono::seconds retry_period_; 170 }; 171 172 std::string GetBuildZipName(const Build& build, const std::string& name); 173 174 } // namespace cuttlefish 175