github.com/sacloud/iaas-api-go@v1.12.0/helper/query/public_archive_info.go (about)

     1  // Copyright 2016-2022 The sacloud/iaas-api-go Authors
     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 query
    16  
    17  import (
    18  	"context"
    19  	"errors"
    20  	"strings"
    21  
    22  	"github.com/sacloud/iaas-api-go"
    23  	"github.com/sacloud/iaas-api-go/types"
    24  )
    25  
    26  var (
    27  	// allowDiskEditTags ディスクの編集可否判定に用いるタグ
    28  	allowDiskEditTags = []string{
    29  		"os-unix",
    30  		"os-linux",
    31  	}
    32  
    33  	// bundleInfoWindowsHostClass ディスクの編集可否判定に用いる、BundleInfoでのWindows判定文字列
    34  	bundleInfoWindowsHostClass = "ms_windows"
    35  )
    36  
    37  func isSophosUTM(archive *iaas.Archive) bool {
    38  	// SophosUTMであれば編集不可
    39  	if archive.BundleInfo != nil && strings.Contains(strings.ToLower(archive.BundleInfo.ServiceClass), "sophosutm") {
    40  		return true
    41  	}
    42  	return false
    43  }
    44  
    45  // CanEditDisk ディスクの修正が可能か判定
    46  func CanEditDisk(ctx context.Context, zone string, reader *ArchiveSourceReader, id types.ID) (bool, error) {
    47  	archive, err := getPublicArchiveFromAncestors(ctx, zone, reader, id)
    48  	if err != nil {
    49  		return false, err
    50  	}
    51  	return archive != nil, nil
    52  }
    53  
    54  // GetPublicArchiveIDFromAncestors ソースアーカイブ/ディスクを辿りパブリックアーカイブのIDを検索
    55  func GetPublicArchiveIDFromAncestors(ctx context.Context, zone string, reader *ArchiveSourceReader, id types.ID) (types.ID, error) {
    56  	archive, err := getPublicArchiveFromAncestors(ctx, zone, reader, id)
    57  	if err != nil {
    58  		return 0, err
    59  	}
    60  	if archive == nil {
    61  		return 0, nil
    62  	}
    63  	return archive.ID, nil
    64  }
    65  
    66  func getPublicArchiveFromAncestors(ctx context.Context, zone string, reader *ArchiveSourceReader, id types.ID) (*iaas.Archive, error) {
    67  	disk, err := reader.DiskReader.Read(ctx, zone, id)
    68  	if err != nil {
    69  		if !iaas.IsNotFoundError(err) {
    70  			return nil, err
    71  		}
    72  	}
    73  	if disk != nil {
    74  		// 無限ループ予防
    75  		if disk.ID == disk.SourceDiskID || disk.ID == disk.SourceArchiveID {
    76  			return nil, errors.New("invalid state: disk has invalid ID or SourceDiskID or SourceArchiveID")
    77  		}
    78  
    79  		if disk.SourceDiskID.IsEmpty() && disk.SourceArchiveID.IsEmpty() {
    80  			return nil, nil
    81  		}
    82  		if !disk.SourceDiskID.IsEmpty() {
    83  			return getPublicArchiveFromAncestors(ctx, zone, reader, disk.SourceDiskID)
    84  		}
    85  		if !disk.SourceArchiveID.IsEmpty() {
    86  			id = disk.SourceArchiveID
    87  		}
    88  	}
    89  
    90  	archive, err := reader.ArchiveReader.Read(ctx, zone, id)
    91  	if err != nil {
    92  		return nil, err
    93  	}
    94  
    95  	// 無限ループ予防
    96  	if archive.ID == archive.SourceDiskID || archive.ID == archive.SourceArchiveID {
    97  		return nil, errors.New("invalid state: archive has invalid ID or SourceDiskID or SourceArchiveID")
    98  	}
    99  
   100  	// BundleInfoがあれば編集不可
   101  	if archive.BundleInfo != nil && archive.BundleInfo.HostClass == bundleInfoWindowsHostClass {
   102  		// Windows
   103  		return nil, nil
   104  	}
   105  
   106  	// SophosUTMであれば編集不可
   107  	if archive.HasTag("pkg-sophosutm") || isSophosUTM(archive) {
   108  		return nil, nil
   109  	}
   110  	// OPNsenseであれば編集不可
   111  	if archive.HasTag("distro-opnsense") {
   112  		return nil, nil
   113  	}
   114  	// Netwiser VEであれば編集不可
   115  	if archive.HasTag("pkg-netwiserve") {
   116  		return nil, nil
   117  	}
   118  	// Juniper vSRXであれば編集不可
   119  	if archive.HasTag("pkg-vsrx") {
   120  		return nil, nil
   121  	}
   122  
   123  	for _, t := range allowDiskEditTags {
   124  		if archive.HasTag(t) {
   125  			// 対応OSインストール済みディスク
   126  			return archive, nil
   127  		}
   128  	}
   129  
   130  	// ここまできても判定できないならソースに投げる
   131  	if !archive.SourceDiskID.IsEmpty() && archive.SourceDiskAvailability != types.Availabilities.Discontinued {
   132  		return getPublicArchiveFromAncestors(ctx, zone, reader, archive.SourceDiskID)
   133  	}
   134  	if !archive.SourceArchiveID.IsEmpty() && archive.SourceArchiveAvailability != types.Availabilities.Discontinued {
   135  		return getPublicArchiveFromAncestors(ctx, zone, reader, archive.SourceArchiveID)
   136  	}
   137  	return nil, nil
   138  }