提交 8c2d3605 编写于 作者: O openeuler-ci-bot 提交者: Gitee

!192 support tag image

Merge pull request !192 from wangfengtu/support_tag
......@@ -88,6 +88,9 @@ service ImageService {
// health check service
rpc HealthCheck(HealthCheckRequest) returns (HealthCheckResponse) {}
// Add a tag to the image
rpc TagImage(TagImageRequest) returns (TagImageResponse) {}
}
message HealthCheckRequest {}
......@@ -583,3 +586,13 @@ message ImageFsInfoResponse {
string errmsg = 2;
uint32 cc = 3;
}
message TagImageRequest {
ImageSpec srcName = 1;
ImageSpec destName = 2;
}
message TagImageResponse {
string errmsg = 1;
uint32 cc = 2;
}
......@@ -70,6 +70,9 @@ service ImagesService {
// Logout from a Docker registry
rpc Logout(LogoutRequest) returns (LogoutResponse);
// Add a tag to the image
rpc Tag(TagImageRequest) returns (TagImageResponse);
}
message Image {
......@@ -126,6 +129,16 @@ message DeleteImageResponse {
string errmsg = 3;
}
message TagImageRequest {
string src_name = 1;
string dest_name = 2;
}
message TagImageResponse {
uint32 cc = 1;
string errmsg = 2;
}
message LoadImageRequest {
string file = 1;
string type = 2;
......
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: wangfengtu
* Create: 2020-04-15
* Description: provide image tag functions
******************************************************************************/
#include "tag.h"
#include <stdio.h>
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include "utils.h"
#include "arguments.h"
#include "isula_connect.h"
#include "log.h"
const char g_cmd_tag_desc[] = "Create a tag TARGET_IMAGE that refers to SOURCE_IMAGE";
const char g_cmd_tag_usage[] = "tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]";
struct client_arguments g_cmd_tag_args = {};
/*
* Add a tag to the image
*/
static int client_tag(const struct client_arguments *args)
{
isula_connect_ops *ops = NULL;
struct isula_tag_request request = { 0 };
struct isula_tag_response *response = NULL;
client_connect_config_t config = { 0 };
int ret = 0;
response = util_common_calloc_s(sizeof(struct isula_tag_response));
if (response == NULL) {
ERROR("Out of memory");
return -1;
}
request.src_name = args->image_name;
request.dest_name = args->tag;
ops = get_connect_client_ops();
if (ops == NULL || !ops->image.tag) {
ERROR("Unimplemented ops");
ret = -1;
goto out;
}
config = get_connect_config(args);
ret = ops->image.tag(&request, response, &config);
if (ret) {
client_print_error(response->cc, response->server_errono, response->errmsg);
if (response->server_errono) {
ret = ESERVERERROR;
}
goto out;
}
out:
isula_tag_response_free(response);
return ret;
}
int cmd_tag_main(int argc, const char **argv)
{
struct log_config lconf = { 0 };
int exit_code = 1;
command_t cmd;
struct command_option options[] = {
LOG_OPTIONS(lconf),
COMMON_OPTIONS(g_cmd_tag_args),
};
set_default_command_log_config(argv[0], &lconf);
if (client_arguments_init(&g_cmd_tag_args)) {
COMMAND_ERROR("client arguments init failed");
exit(ECOMMON);
}
g_cmd_tag_args.progname = argv[0];
command_init(&cmd, options, sizeof(options) / sizeof(options[0]), argc, (const char **)argv, g_cmd_tag_desc,
g_cmd_tag_usage);
if (command_parse_args(&cmd, &g_cmd_tag_args.argc, &g_cmd_tag_args.argv)) {
exit(exit_code);
}
if (log_init(&lconf)) {
COMMAND_ERROR("RMI: log init failed");
exit(exit_code);
}
if (g_cmd_tag_args.argc != 2) {
COMMAND_ERROR("\"tag\" requires exactly 2 arguments.");
exit(exit_code);
}
g_cmd_tag_args.image_name = g_cmd_tag_args.argv[0];
g_cmd_tag_args.tag = g_cmd_tag_args.argv[1];
if (!util_valid_image_name(g_cmd_tag_args.image_name)) {
COMMAND_ERROR("%s is not a valid image name", g_cmd_tag_args.image_name);
exit(exit_code);
}
if (!util_valid_tag(g_cmd_tag_args.tag)) {
COMMAND_ERROR("%s is not a valid tag", g_cmd_tag_args.tag);
exit(exit_code);
}
int ret = client_tag(&g_cmd_tag_args);
if (ret != 0) {
COMMAND_ERROR("Tag image \"%s\" to \"%s\" failed", g_cmd_tag_args.image_name, g_cmd_tag_args.tag);
exit(exit_code);
}
exit(EXIT_SUCCESS);
}
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: wangfengtu
* Create: 2020-04-15
* Description: provide image tag definition
******************************************************************************/
#ifndef __CMD_TAG_IMAGE_H
#define __CMD_TAG_IMAGE_H
#include "arguments.h"
#ifdef __cplusplus
extern "C" {
#endif
extern const char g_cmd_tag_desc[];
extern const char g_cmd_tag_usage[];
extern struct client_arguments g_cmd_tag_args;
int cmd_tag_main(int argc, const char **argv);
#ifdef __cplusplus
}
#endif
#endif /* __CMD_TAG_IMAGE_H */
......@@ -28,6 +28,7 @@
#include "run.h"
#include "images.h"
#include "rmi.h"
#include "tag.h"
#include "wait.h"
#include "restart.h"
#include "pause.h"
......@@ -190,6 +191,10 @@ struct command g_commands[] = {
// `logout` sub-command
"logout", cmd_logout_main, g_cmd_logout_desc, NULL, &g_cmd_logout_args
},
{
// `tag` sub-command
"tag", cmd_tag_main, g_cmd_tag_desc, NULL, &g_cmd_tag_args
},
#endif
{ NULL, NULL, NULL, NULL, NULL } // End of the list
};
......
......@@ -167,6 +167,62 @@ public:
}
};
class ImageTag : public ClientBase<ImagesService, ImagesService::Stub, isula_tag_request, TagImageRequest,
isula_tag_response, TagImageResponse> {
public:
explicit ImageTag(void *args)
: ClientBase(args)
{
}
~ImageTag() = default;
int request_to_grpc(const isula_tag_request *request, TagImageRequest *grequest) override
{
if (request == nullptr) {
return -1;
}
if (request->src_name != nullptr) {
grequest->set_src_name(request->src_name);
}
if (request->dest_name != nullptr) {
grequest->set_dest_name(request->dest_name);
}
return 0;
}
int response_from_grpc(TagImageResponse *gresponse, isula_tag_response *response) override
{
response->server_errono = (uint32_t)gresponse->cc();
if (!gresponse->errmsg().empty()) {
response->errmsg = util_strdup_s(gresponse->errmsg().c_str());
}
return 0;
}
int check_parameter(const TagImageRequest &req) override
{
if (req.src_name().empty()) {
ERROR("Missing source image name in the request");
return -1;
}
if (req.dest_name().empty()) {
ERROR("Missing destition image name in the request");
return -1;
}
return 0;
}
Status grpc_call(ClientContext *context, const TagImageRequest &req, TagImageResponse *reply) override
{
return stub_->Tag(context, req, reply);
}
};
class ImagesLoad : public ClientBase<ImagesService, ImagesService::Stub, isula_load_request, LoadImageRequest,
isula_load_response, LoadImageResponse> {
public:
......@@ -468,6 +524,7 @@ int grpc_images_client_ops_init(isula_connect_ops *ops)
ops->image.inspect = container_func<isula_inspect_request, isula_inspect_response, ImageInspect>;
ops->image.login = container_func<isula_login_request, isula_login_response, Login>;
ops->image.logout = container_func<isula_logout_request, isula_logout_response, Logout>;
ops->image.tag = container_func<isula_tag_request, isula_tag_response, ImageTag>;
return 0;
}
......@@ -677,6 +677,62 @@ public:
}
};
class ISulaTag : public ClientBase<isula::ImageService, isula::ImageService::Stub, isula_tag_request,
isula::TagImageRequest, isula_tag_response, isula::TagImageResponse> {
public:
explicit ISulaTag(void *args) : ClientBase(args)
{
}
~ISulaTag() = default;
int request_to_grpc(const isula_tag_request *req, isula::TagImageRequest *grequest) override
{
if (req == nullptr) {
return -1;
}
if (req->src_name == nullptr || req->src_name->image == nullptr ||
req->dest_name == nullptr || req->dest_name->image == nullptr) {
return -1;
}
isula::ImageSpec *src_image = new (std::nothrow) isula::ImageSpec;
isula::ImageSpec *dest_image = new (std::nothrow) isula::ImageSpec;
if (src_image == nullptr || dest_image == nullptr) {
ERROR("Out of memory");
return -1;
}
src_image->set_image(req->src_name->image);
dest_image->set_image(req->dest_name->image);
grequest->set_allocated_srcname(src_image);
grequest->set_allocated_destname(dest_image);
return 0;
}
int response_from_grpc(isula::TagImageResponse *gresp, isula_tag_response *resp) override
{
if (!gresp->errmsg().empty()) {
resp->errmsg = util_strdup_s(gresp->errmsg().c_str());
}
resp->server_errono = gresp->cc();
return 0;
}
int check_parameter(const isula::TagImageRequest &req) override
{
if (req.has_srcname() && !req.srcname().image().empty() &&
req.has_destname() && !req.destname().image().empty()) {
return 0;
}
ERROR("Image name is required.");
return -1;
}
Status grpc_call(ClientContext *context, const isula::TagImageRequest &req,
isula::TagImageResponse *reply) override
{
return stub_->TagImage(context, req, reply);
}
};
class ISulaLoad : public ClientBase<isula::ImageService, isula::ImageService::Stub, isula_load_request,
isula::LoadImageRequest, isula_load_response, isula::LoadImageResponose> {
public:
......@@ -1141,6 +1197,7 @@ int grpc_isula_image_client_ops_init(isula_image_ops *ops)
ops->pull = container_func<isula_pull_request, isula_pull_response, ISulaImagePull>;
ops->rmi = container_func<isula_rmi_request, isula_rmi_response, ISulaRmi>;
ops->tag = container_func<isula_tag_request, isula_tag_response, ISulaTag>;
ops->load = container_func<isula_load_request, isula_load_response, ISulaLoad>;
ops->login = container_func<isula_login_request, isula_login_response, ISulaLogin>;
ops->logout = container_func<isula_logout_request, isula_logout_response, ISulaLogout>;
......
......@@ -119,6 +119,8 @@ typedef struct {
struct isula_login_response *response, void *arg);
int(*logout)(const struct isula_logout_request *request,
struct isula_logout_response *response, void *arg);
int(*tag)(const struct isula_tag_request *request,
struct isula_tag_response *response, void *arg);
} image_ops;
typedef struct {
......
......@@ -302,6 +302,28 @@ void free_isula_rmi_response(struct isula_rmi_response *ptr)
free(ptr);
}
void free_isula_tag_request(struct isula_tag_request *ptr)
{
if (ptr == NULL) {
return;
}
free_image_spec(ptr->src_name);
ptr->src_name = NULL;
free_image_spec(ptr->dest_name);
ptr->dest_name = NULL;
free(ptr);
}
void free_isula_tag_response(struct isula_tag_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
void free_isula_load_request(struct isula_load_request *ptr)
{
if (ptr == NULL) {
......
......@@ -160,6 +160,17 @@ struct isula_rmi_response {
uint32_t server_errono;
};
struct isula_tag_request {
struct image_spec *src_name;
struct image_spec *dest_name;
};
struct isula_tag_response {
char *errmsg;
uint32_t cc;
uint32_t server_errono;
};
struct isula_load_request {
char *file;
char *tag;
......@@ -299,6 +310,7 @@ typedef struct {
int (*prepare)(const struct isula_prepare_request *req, struct isula_prepare_response *resp, void *arg);
int (*remove)(const struct isula_remove_request *req, struct isula_remove_response *resp, void *arg);
int (*tag)(const struct isula_tag_request *req, struct isula_tag_response *resp, void *arg);
int (*mount)(const struct isula_mount_request *req, struct isula_mount_response *resp, void *arg);
int (*umount)(const struct isula_umount_request *req, struct isula_umount_response *resp, void *arg);
int (*containers_list)(const struct isula_containers_list_request *req, struct isula_containers_list_response *resp,
......@@ -336,6 +348,8 @@ void free_isula_prepare_request(struct isula_prepare_request *req);
void free_isula_prepare_response(struct isula_prepare_response *resp);
void free_isula_remove_request(struct isula_remove_request *req);
void free_isula_remove_response(struct isula_remove_response *resp);
void free_isula_tag_request(struct isula_tag_request *req);
void free_isula_tag_response(struct isula_tag_response *resp);
void free_isula_mount_request(struct isula_mount_request *req);
void free_isula_mount_response(struct isula_mount_response *resp);
void free_isula_umount_request(struct isula_umount_request *req);
......
......@@ -151,6 +151,27 @@ int ImagesServiceImpl::image_remove_request_from_grpc(const DeleteImageRequest *
return 0;
}
int ImagesServiceImpl::image_tag_request_from_grpc(const TagImageRequest *grequest,
image_tag_image_request **request)
{
image_tag_image_request *tmpreq = (image_tag_image_request *)util_common_calloc_s(
sizeof(image_tag_image_request));
if (tmpreq == nullptr) {
ERROR("Out of memory");
return -1;
}
if (!grequest->src_name().empty()) {
tmpreq->src_name = util_strdup_s(grequest->src_name().c_str());
}
if (!grequest->dest_name().empty()) {
tmpreq->dest_name = util_strdup_s(grequest->dest_name().c_str());
}
*request = tmpreq;
return 0;
}
int ImagesServiceImpl::image_load_request_from_grpc(
const LoadImageRequest *grequest, image_load_image_request **request)
{
......@@ -279,6 +300,39 @@ Status ImagesServiceImpl::Delete(ServerContext *context, const DeleteImageReques
return Status::OK;
}
Status ImagesServiceImpl::Tag(ServerContext *context, const TagImageRequest *request, TagImageResponse *reply)
{
auto status = GrpcServerTlsAuth::auth(context, "image_tag");
if (!status.ok()) {
return status;
}
service_callback_t *cb = get_service_callback();
if (cb == nullptr || cb->image.tag == nullptr) {
return Status(StatusCode::UNIMPLEMENTED, "Unimplemented callback");
}
image_tag_image_request *image_req = nullptr;
int tret = image_tag_request_from_grpc(request, &image_req);
if (tret != 0) {
ERROR("Failed to transform grpc request");
reply->set_cc(ISULAD_ERR_INPUT);
return Status::OK;
}
image_tag_image_response *image_res = nullptr;
int ret = cb->image.tag(image_req, &image_res);
tret = response_to_grpc(image_res, reply);
free_image_tag_image_request(image_req);
free_image_tag_image_response(image_res);
if (tret != 0) {
reply->set_errmsg(util_strdup_s(errno_to_error_message(ISULAD_ERR_INTERNAL)));
reply->set_cc(ISULAD_ERR_INPUT);
ERROR("Failed to translate response to grpc, operation is %s", ret ? "failed" : "success");
}
return Status::OK;
}
Status ImagesServiceImpl::Load(ServerContext *context, const LoadImageRequest *request, LoadImageResponse *reply)
{
auto status = GrpcServerTlsAuth::auth(context, "image_load");
......
......@@ -47,6 +47,8 @@ public:
Status Delete(ServerContext *context, const DeleteImageRequest *request, DeleteImageResponse *reply) override;
Status Tag(ServerContext *context, const TagImageRequest *request, TagImageResponse *reply) override;
Status Load(ServerContext *context, const LoadImageRequest *request, LoadImageResponse *reply) override;
Status Inspect(ServerContext *context, const InspectImageRequest *request, InspectImageResponse *reply) override;
......@@ -77,6 +79,8 @@ private:
int image_remove_request_from_grpc(const DeleteImageRequest *grequest, image_delete_image_request **request);
int image_tag_request_from_grpc(const TagImageRequest *grequest, image_tag_image_request **request);
int image_load_request_from_grpc(const LoadImageRequest *grequest, image_load_image_request **request);
int inspect_request_from_grpc(const InspectImageRequest *grequest, image_inspect_request **request);
......
......@@ -408,6 +408,34 @@ bool util_valid_digest(const char *digest)
return util_reg_match(patten, digest) == 0;
}
bool util_valid_tag(const char *tag)
{
char *patten = "^[a-f0-9]{64}$";
if (tag == NULL) {
ERROR("invalid NULL param");
return false;
}
if (strlen(tag) >= strlen(SHA256_PREFIX) && !strncasecmp(tag, SHA256_PREFIX, strlen(SHA256_PREFIX))) {
ERROR("tag must not prefixed with \"sha256:\"");
return false;
}
// cannot specify 64-byte hexadecimal strings
if (util_reg_match(patten, tag) == 0) {
ERROR("cannot specify 64-byte hexadecimal strings");
return false;
}
if (!util_valid_image_name(tag)) {
ERROR("Not a valid image name");
return false;
}
return true;
}
bool util_valid_file(const char *path, uint32_t fmod)
{
struct stat s;
......
......@@ -56,6 +56,8 @@ bool util_valid_file(const char *path, uint32_t fmod);
bool util_valid_digest(const char *digest);
bool util_valid_tag(const char *tag);
bool util_valid_digest_file(const char *path, const char *digest);
bool util_valid_key_type(const char *key);
......
......@@ -71,6 +71,7 @@ static const struct bim_ops g_embedded_ops = {
.logout = NULL,
.health_check = NULL,
.tag_image = NULL,
};
#endif
......@@ -106,6 +107,7 @@ static const struct bim_ops g_isula_ops = {
.logout = isula_logout,
.health_check = isula_health_check,
.tag_image = isula_tag,
};
#endif
......@@ -140,6 +142,7 @@ static const struct bim_ops g_ext_ops = {
.logout = ext_logout,
.health_check = NULL,
.tag_image = NULL,
};
static const struct bim_type g_bims[] = {
......@@ -1426,6 +1429,68 @@ pack_response:
return ret;
}
int im_tag_image(const im_tag_request *request, im_tag_response **response)
{
int ret = -1;
char *src_name = NULL;
char *dest_name = NULL;
const struct bim_type *bim_type = NULL;
struct bim *bim = NULL;
if (request == NULL || response == NULL) {
ERROR("Invalid input arguments");
return -1;
}
*response = util_common_calloc_s(sizeof(im_remove_response));
if (*response == NULL) {
ERROR("Out of memory");
return -1;
}
if (request->src_name.image == NULL || request->dest_name.image == NULL) {
ERROR("remove image requires source image ref and dest image ref");
isulad_set_error_message("remove image requires source image ref and dest image ref");
goto pack_response;
}
src_name = util_strdup_s(request->src_name.image);
dest_name = util_strdup_s(request->dest_name.image);
bim_type = bim_query(src_name);
if (bim_type == NULL) {
ERROR("No such image:%s", src_name);
isulad_set_error_message("No such image:%s", src_name);
goto pack_response;
}
bim = bim_get(bim_type->image_type, src_name, NULL, NULL);
if (bim == NULL) {
ERROR("Failed to init bim for image %s", src_name);
goto pack_response;
}
if (bim->ops->tag_image == NULL) {
ERROR("Unimplements tag image in %s", bim->type);
goto pack_response;
}
ret = bim->ops->tag_image(request);
if (ret != 0) {
ERROR("Failed to tag image %s to %s", src_name, dest_name);
ret = -1;
goto pack_response;
}
pack_response:
if (g_isulad_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_isulad_errmsg);
}
free(src_name);
free(dest_name);
bim_put(bim);
return ret;
}
void free_im_remove_request(im_remove_request *ptr)
{
if (ptr == NULL) {
......@@ -1449,6 +1514,30 @@ void free_im_remove_response(im_remove_response *ptr)
free(ptr);
}
void free_im_tag_request(im_tag_request *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->src_name.image);
ptr->src_name.image = NULL;
free(ptr->dest_name.image);
ptr->dest_name.image = NULL;
free(ptr);
}
void free_im_tag_response(im_tag_response *ptr)
{
if (ptr == NULL) {
return;
}
free(ptr->errmsg);
ptr->errmsg = NULL;
free(ptr);
}
static int do_im_inspect_image(struct bim *bim, char **inspected_json)
{
int ret = 0;
......
......@@ -103,6 +103,15 @@ typedef struct {
char *errmsg;
} im_remove_response;
typedef struct {
image_spec src_name;
image_spec dest_name;
} im_tag_request;
typedef struct {
char *errmsg;
} im_tag_response;
typedef struct {
// Spec of the image.
image_spec image;
......@@ -260,6 +269,8 @@ struct bim_ops {
/* health check */
int (*health_check)(void);
/* Add a tag to the image */
int (*tag_image)(const im_tag_request *request);
};
struct bim {
......@@ -318,6 +329,12 @@ void free_im_remove_request(im_remove_request *ptr);
void free_im_remove_response(im_remove_response *ptr);
int im_tag_image(const im_tag_request *request, im_tag_response **response);
void free_im_tag_request(im_tag_request *ptr);
void free_im_tag_response(im_tag_response *ptr);
int im_inspect_image(const im_inspect_request *request, im_inspect_response **response);
void free_im_inspect_request(im_inspect_request *ptr);
......
......@@ -26,6 +26,7 @@
#include "isula_rootfs_mount.h"
#include "isula_rootfs_umount.h"
#include "isula_image_rmi.h"
#include "isula_image_tag.h"
#include "isula_container_fs_usage.h"
#include "isula_image_fs_info.h"
#include "isula_storage_status.h"
......@@ -264,6 +265,62 @@ out:
return ret;
}
int isula_tag(const im_tag_request *request)
{
int ret = -1;
char *src_name = NULL;
char *dest_name = NULL;
oci_image_t *image_info = NULL;
char *errmsg = NULL;
if (request == NULL || request->src_name.image == NULL || request->dest_name.image == NULL) {
ERROR("Invalid input arguments");
return -1;
}
src_name = oci_resolve_image_name(request->src_name.image);
if (src_name == NULL) {
ret = -1;
ERROR("Failed to resolve source image name");
goto out;
}
dest_name = oci_normalize_image_name(request->dest_name.image);
if (src_name == NULL) {
ret = -1;
ERROR("Failed to resolve source image name");
goto out;
}
image_info = oci_images_store_get(src_name);
if (image_info == NULL) {
INFO("No such image exist %s", src_name);
ret = -1;
goto out;
}
oci_image_lock(image_info);
ret = isula_image_tag(src_name, dest_name, &errmsg);
if (ret != 0) {
isulad_set_error_message("Failed to tag image with error: %s", errmsg);
ERROR("Failed to tag image '%s' to '%s' with error: %s", src_name, dest_name, errmsg);
goto out;
}
ret = register_new_oci_image_into_memory(dest_name);
if (ret != 0) {
ERROR("Register image %s into store failed", dest_name);
goto out;
}
out:
oci_image_unlock(image_info);
oci_image_unref(image_info);
free(src_name);
free(dest_name);
free(errmsg);
return ret;
}
int isula_container_filesystem_usage(const im_container_fs_usage_request *request, imagetool_fs_info **fs_usage)
{
int ret = 0;
......
......@@ -28,6 +28,7 @@ void isula_exit(void);
int isula_pull_rf(const im_pull_request *request, im_pull_response **response);
int isula_rmi(const im_remove_request *request);
int isula_tag(const im_tag_request *request);
int isula_get_filesystem_info(im_fs_info_response **response);
int isual_load_image(const im_load_request *request);
......
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: wangfengtu
* Create: 2020-04-15
* Description: isula image tag operator implement
*******************************************************************************/
#include "isula_image_tag.h"
#include "isula_image_connect.h"
#include "isula_helper.h"
#include "connect.h"
#include "utils.h"
#include "log.h"
static int generate_isula_tag_request(const char *src_name, const char *dest_name, struct isula_tag_request **ireq)
{
struct isula_tag_request *tmp_req = NULL;
int ret = 0;
if (src_name == NULL || dest_name == NULL || ireq == NULL) {
ERROR("Required image name");
return -1;
}
tmp_req = (struct isula_tag_request *)util_common_calloc_s(sizeof(struct isula_tag_request));
if (tmp_req == NULL) {
ERROR("Out of memory");
return -1;
}
tmp_req->src_name = (struct image_spec *)util_common_calloc_s(sizeof(struct image_spec));
if (tmp_req->src_name == NULL) {
ERROR("Out of memory");
ret = -1;
goto out;
}
tmp_req->dest_name = (struct image_spec *)util_common_calloc_s(sizeof(struct image_spec));
if (tmp_req->dest_name == NULL) {
ERROR("Out of memory");
ret = -1;
goto out;
}
tmp_req->src_name->image = util_strdup_s(src_name);
tmp_req->dest_name->image = util_strdup_s(dest_name);
out:
*ireq = tmp_req;
return ret;
}
int isula_image_tag(const char *src_name, const char *dest_name, char **errmsg)
{
int ret = -1;
struct isula_tag_request *ireq = NULL;
struct isula_tag_response *iresp = NULL;
client_connect_config_t conf = { 0 };
isula_image_ops *im_ops = NULL;
im_ops = get_isula_image_ops();
if (im_ops == NULL) {
ERROR("Don't init isula server grpc client");
return -1;
}
if (im_ops->tag == NULL) {
ERROR("Umimplement tag operator");
return -1;
}
ret = generate_isula_tag_request(src_name, dest_name, &ireq);
if (ret != 0) {
goto out;
}
iresp = (struct isula_tag_response *)util_common_calloc_s(sizeof(struct isula_tag_response));
if (iresp == NULL) {
ERROR("Out of memory");
goto out;
}
ret = get_isula_image_connect_config(&conf);
if (ret != 0) {
goto out;
}
INFO("Send remove image GRPC request");
ret = im_ops->tag(ireq, iresp, &conf);
if (ret != 0) {
ERROR("Tag image %s to %s failed: %s", src_name, dest_name, iresp->errmsg);
}
*errmsg = iresp->errmsg;
iresp->errmsg = NULL;
out:
free_isula_tag_request(ireq);
free_isula_tag_response(iresp);
free_client_connect_config_value(&conf);
return ret;
}
/******************************************************************************
* Copyright (c) Huawei Technologies Co., Ltd. 2020. All rights reserved.
* iSulad licensed under the Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
* http://license.coscl.org.cn/MulanPSL2
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, EITHER EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, MERCHANTABILITY OR FIT FOR A PARTICULAR
* PURPOSE.
* See the Mulan PSL v2 for more details.
* Author: wangfengtu
* Create: 2020-04-15
* Description: isula image tag operator implement
*******************************************************************************/
#ifndef __IMAGE_ISULA_IMAGE_TAG_H
#define __IMAGE_ISULA_IMAGE_TAG_H
#include <stdbool.h>
#ifdef __cplusplus
extern "C" {
#endif
int isula_image_tag(const char *src_name, const char *dest_name, char **errmsg);
#ifdef __cplusplus
}
#endif
#endif
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"src_name": {
"type": "string"
},
"dest_name": {
"type": "string"
}
}
}
{
"$schema": "http://json-schema.org/draft-04/schema#",
"type": "object",
"properties": {
"cc": {
"type": "uint32"
},
"errmsg": {
"type": "string"
}
}
}
......@@ -1181,6 +1181,36 @@ void isula_rmi_response_free(struct isula_rmi_response *response)
return;
}
/* isula tag request free */
void isula_tag_request_free(struct isula_tag_request *request)
{
if (request == NULL) {
return;
}
free(request->src_name);
request->src_name = NULL;
free(request->dest_name);
request->dest_name = NULL;
free(request);
return;
}
/* isula tag response free */
void isula_tag_response_free(struct isula_tag_response *response)
{
if (response == NULL) {
return;
}
free(response->errmsg);
response->errmsg = NULL;
free(response);
return;
}
/* isula pull response free */
void isula_pull_request_free(struct isula_pull_request *request)
{
......
......@@ -605,6 +605,17 @@ struct isula_pull_request {
char *image_name;
};
struct isula_tag_request {
char *src_name;
char *dest_name;
};
struct isula_tag_response {
uint32_t cc;
uint32_t server_errono;
char *errmsg;
};
struct isula_pull_response {
char *image_ref;
uint32_t cc;
......@@ -808,6 +819,10 @@ void isula_rmi_request_free(struct isula_rmi_request *request);
void isula_rmi_response_free(struct isula_rmi_response *response);
void isula_tag_request_free(struct isula_tag_request *request);
void isula_tag_response_free(struct isula_tag_response *response);
void isula_load_request_free(struct isula_load_request *request);
void isula_load_response_free(struct isula_load_response *response);
......
......@@ -60,6 +60,8 @@
#include "host_info_response.h"
#include "image_delete_image_request.h"
#include "image_delete_image_response.h"
#include "image_tag_image_request.h"
#include "image_tag_image_response.h"
#include "image_load_image_request.h"
#include "image_load_image_response.h"
#include "image_inspect_request.h"
......@@ -157,6 +159,8 @@ typedef struct {
int(*login)(const image_login_request *request, image_login_response **response);
int(*logout)(const image_logout_request *request, image_logout_response **response);
int(*tag)(const image_tag_image_request *request, image_tag_image_response **response);
} service_image_callback_t;
typedef struct {
......
......@@ -384,6 +384,111 @@ out:
return (ret < 0) ? ECOMMON : ret;
}
/* tag image */
static int tag_image(const char *src_name, const char *dest_name)
{
int ret = 0;
im_tag_request *im_request = NULL;
im_tag_response *im_response = NULL;
if (src_name == NULL || dest_name == NULL) {
ERROR("invalid NULL param");
return EINVALIDARGS;
}
im_request = util_common_calloc_s(sizeof(im_tag_request));
if (im_request == NULL) {
ERROR("Out of memory");
ret = -1;
goto out;
}
im_request->src_name.image = util_strdup_s(src_name);
im_request->dest_name.image = util_strdup_s(dest_name);
ret = im_tag_image(im_request, &im_response);
if (ret != 0) {
if (im_response != NULL && im_response->errmsg != NULL) {
ERROR("Tag image %s to %s failed:%s", src_name, dest_name, im_response->errmsg);
isulad_try_set_error_message("Tag image %s to %s failed:%s", src_name, dest_name, im_response->errmsg);
} else {
ERROR("Tag image %s to %s failed", src_name, dest_name);
isulad_try_set_error_message("Tag image %s to %s failed");
}
ret = -1;
goto out;
}
out:
free_im_tag_request(im_request);
free_im_tag_response(im_response);
return ret;
}
/* image tag cb */
static int image_tag_cb(const image_tag_image_request *request,
image_tag_image_response **response)
{
int ret = -1;
char *src_name = NULL;
char *dest_name = NULL;
uint32_t cc = ISULAD_SUCCESS;
DAEMON_CLEAR_ERRMSG();
if (request == NULL || request->src_name == NULL || response == NULL ||
request->dest_name == NULL) {
ERROR("Invalid input arguments");
return EINVALIDARGS;
}
src_name = request->src_name;
dest_name = request->dest_name;
*response = util_common_calloc_s(sizeof(image_delete_image_response));
if (*response == NULL) {
ERROR("Out of memory");
cc = ISULAD_ERR_MEMOUT;
goto out;
}
if (!util_valid_image_name(src_name)) {
ERROR("Invalid image name %s", src_name);
cc = ISULAD_ERR_INPUT;
isulad_try_set_error_message("Invalid image name:%s", src_name);
goto out;
}
if (!util_valid_image_name(dest_name)) {
ERROR("Invalid image name %s", dest_name);
cc = ISULAD_ERR_INPUT;
isulad_try_set_error_message("Invalid image name:%s", dest_name);
goto out;
}
EVENT("Image Event: {Object: %s, Type: Tagging}", src_name);
ret = tag_image(src_name, dest_name);
if (ret != 0) {
cc = ISULAD_ERR_EXEC;
goto out;
}
EVENT("Image Event: {Object: %s, Type: Tagged}", src_name);
out:
if (*response != NULL) {
(*response)->cc = cc;
if (g_isulad_errmsg != NULL) {
(*response)->errmsg = util_strdup_s(g_isulad_errmsg);
DAEMON_CLEAR_ERRMSG();
}
}
return (ret < 0) ? ECOMMON : ret;
}
static bool valid_repo_tags(char * const * const repo_tags, size_t repo_index)
{
if (repo_tags != NULL && repo_tags[repo_index] != NULL) {
......@@ -890,5 +995,6 @@ void image_callback_init(service_image_callback_t *cb)
cb->inspect = image_inspect_cb;
cb->login = login_cb;
cb->logout = logout_cb;
cb->tag = image_tag_cb;
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册