github.com/alibaba/sealer@v0.8.6-0.20220430115802-37a2bdaa8173/pkg/image/default_image_metadata.go (about)

     1  // Copyright © 2021 Alibaba Group Holding Ltd.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License");
     4  // you may not use this file except in compliance with the License.
     5  // You may obtain a copy of the License at
     6  //
     7  //     http://www.apache.org/licenses/LICENSE-2.0
     8  //
     9  // Unless required by applicable law or agreed to in writing, software
    10  // distributed under the License is distributed on an "AS IS" BASIS,
    11  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    12  // See the License for the specific language governing permissions and
    13  // limitations under the License.
    14  
    15  package image
    16  
    17  import (
    18  	"context"
    19  	"encoding/json"
    20  	"fmt"
    21  
    22  	"github.com/distribution/distribution/v3"
    23  	"github.com/distribution/distribution/v3/manifest/schema2"
    24  
    25  	"github.com/alibaba/sealer/pkg/image/distributionutil"
    26  	"github.com/alibaba/sealer/pkg/image/reference"
    27  	"github.com/alibaba/sealer/pkg/image/store"
    28  	v1 "github.com/alibaba/sealer/types/api/v1"
    29  )
    30  
    31  //DefaultImageMetadataService provide service for image metadata operations
    32  type DefaultImageMetadataService struct {
    33  	imageStore store.ImageStore
    34  }
    35  
    36  // Tag is used to give a name for imageName
    37  func (d DefaultImageMetadataService) Tag(imageName, tarImageName string) error {
    38  	tarNamed, err := reference.ParseToNamed(tarImageName)
    39  	if err != nil {
    40  		return err
    41  	}
    42  
    43  	manifestList, err := d.imageStore.GetImageManifestList(imageName)
    44  	if err != nil {
    45  		return err
    46  	}
    47  
    48  	for _, m := range manifestList {
    49  		image, err := d.imageStore.GetByID(m.ID)
    50  		if err != nil {
    51  			return err
    52  		}
    53  
    54  		image.Name = tarNamed.CompleteName()
    55  		err = setClusterFile(tarNamed.CompleteName(), image)
    56  		if err != nil {
    57  			return err
    58  		}
    59  
    60  		imageID, err := GenerateImageID(*image)
    61  		if err != nil {
    62  			return err
    63  		}
    64  		image.Spec.ID = imageID
    65  		err = d.imageStore.Save(*image)
    66  		if err != nil {
    67  			return err
    68  		}
    69  	}
    70  	return nil
    71  }
    72  
    73  //List will list all cloud image locally
    74  func (d DefaultImageMetadataService) List() (store.ImageMetadataMap, error) {
    75  	return d.imageStore.GetImageMetadataMap()
    76  }
    77  
    78  // GetImage will return the v1.Image locally
    79  func (d DefaultImageMetadataService) GetImage(imageName string, platform *v1.Platform) (*v1.Image, error) {
    80  	image, err := d.imageStore.GetByName(imageName, platform)
    81  	if err != nil {
    82  		return nil, err
    83  	}
    84  	return image, nil
    85  }
    86  
    87  // GetRemoteImage will return the v1.Image from remote registry
    88  func (d DefaultImageMetadataService) GetRemoteImage(imageName string, platform *v1.Platform) (v1.Image, error) {
    89  	var (
    90  		image v1.Image
    91  		err   error
    92  		named reference.Named
    93  		ctx   = context.Background()
    94  	)
    95  
    96  	named, err = reference.ParseToNamed(imageName)
    97  	if err != nil {
    98  		return image, err
    99  	}
   100  
   101  	repo, err := distributionutil.NewV2Repository(named, "pull")
   102  	if err != nil {
   103  		return v1.Image{}, err
   104  	}
   105  
   106  	ms, err := repo.Manifests(ctx)
   107  	if err != nil {
   108  		return v1.Image{}, err
   109  	}
   110  
   111  	manifest, err := ms.Get(ctx, "", distribution.WithTagOption{Tag: named.Tag()})
   112  	if err != nil {
   113  		return v1.Image{}, err
   114  	}
   115  
   116  	// just transform it to schema2.DeserializedManifest
   117  	// because we only upload this kind manifest.
   118  	scheme2Manifest, ok := manifest.(*schema2.DeserializedManifest)
   119  	if !ok {
   120  		return v1.Image{}, fmt.Errorf("failed to parse manifest %s to DeserializedManifest", named.RepoTag())
   121  	}
   122  
   123  	bs := repo.Blobs(ctx)
   124  	configJSONReader, err := bs.Open(ctx, scheme2Manifest.Config.Digest)
   125  	if err != nil {
   126  		return v1.Image{}, err
   127  	}
   128  	defer configJSONReader.Close()
   129  
   130  	decoder := json.NewDecoder(configJSONReader)
   131  	return image, decoder.Decode(&image)
   132  }
   133  
   134  func (d DefaultImageMetadataService) DeleteImage(imageName string, platform *v1.Platform) error {
   135  	return d.imageStore.DeleteByName(imageName, platform)
   136  }