138 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			138 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			Python
		
	
	
		
			Executable File
		
	
	
	
	
#!/usr/bin/env python
 | 
						|
 | 
						|
# Copyright 2019 The Kubernetes Authors.
 | 
						|
#
 | 
						|
# Licensed under the Apache License, Version 2.0 (the "License");
 | 
						|
# you may not use this file except in compliance with the License.
 | 
						|
# You may obtain a copy of the License at
 | 
						|
#
 | 
						|
#     http://www.apache.org/licenses/LICENSE-2.0
 | 
						|
#
 | 
						|
# Unless required by applicable law or agreed to in writing, software
 | 
						|
# distributed under the License is distributed on an "AS IS" BASIS,
 | 
						|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 | 
						|
# See the License for the specific language governing permissions and
 | 
						|
# limitations under the License.
 | 
						|
 | 
						|
################################################################################
 | 
						|
# usage: image-upload.py [FLAGS] ARGS
 | 
						|
#  This program uploads an OVA created from a Packer build
 | 
						|
################################################################################
 | 
						|
 | 
						|
import argparse
 | 
						|
import atexit
 | 
						|
import hashlib
 | 
						|
import json
 | 
						|
import os
 | 
						|
import re
 | 
						|
import requests
 | 
						|
import subprocess
 | 
						|
import string
 | 
						|
import sys
 | 
						|
 | 
						|
 | 
						|
def main():
 | 
						|
    parser = argparse.ArgumentParser(
 | 
						|
        description="Uploads an OVA created from a Packer build")
 | 
						|
    parser.add_argument(dest='build_dir',
 | 
						|
                        nargs='?',
 | 
						|
                        metavar='BUILD_DIR',
 | 
						|
                        default='.',
 | 
						|
                        help='The Packer build directory')
 | 
						|
    parser.add_argument('--key-file',
 | 
						|
                        dest='key_file',
 | 
						|
                        required=True,
 | 
						|
                        nargs='?',
 | 
						|
                        metavar='KEY_FILE',
 | 
						|
                        help='The GCS key file')
 | 
						|
    args = parser.parse_args()
 | 
						|
 | 
						|
    # Get the absolute path to the GCS key file.
 | 
						|
    key_file = os.path.abspath(args.key_file)
 | 
						|
 | 
						|
    # Change the working directory if one is specified.
 | 
						|
    os.chdir(args.build_dir)
 | 
						|
    print("image-upload-ova: cd %s" % args.build_dir)
 | 
						|
 | 
						|
    # Load the packer manifest JSON
 | 
						|
    data = None
 | 
						|
    with open('packer-manifest.json', 'r') as f:
 | 
						|
        data = json.load(f)
 | 
						|
 | 
						|
    # Get the first build.
 | 
						|
    build = data['builds'][0]
 | 
						|
    build_data = build['custom_data']
 | 
						|
 | 
						|
    version = build_data['kubernetes_semver']
 | 
						|
    build_name = "%s-kube-%s" % (build_data['build_name'], version)
 | 
						|
    print("image-upload-ova: loaded %s" % build_name)
 | 
						|
 | 
						|
    # Get the OVA and its checksum.
 | 
						|
    ova = "%s.ova" % build_name
 | 
						|
    ova_sum = "%s.sha256" % ova
 | 
						|
 | 
						|
    # Determine whether or not this is a release or CI image.
 | 
						|
    upload_dir = 'ci'
 | 
						|
    if re.match(r'^v?\d+\.\d+\.\d+(-\d+)?$', version):
 | 
						|
        upload_dir = 'release'
 | 
						|
 | 
						|
    # Get the path to the GCS OVA and its checksum.
 | 
						|
    gcs_ova = "gs://capv-images/%s/%s/%s" % (
 | 
						|
        upload_dir, version, ova)
 | 
						|
    gcs_ova_sum = "%s.sha256" % gcs_ova
 | 
						|
 | 
						|
    # Get the URL of the OVA and its checksum.
 | 
						|
    url_ova = string.replace(gcs_ova, "gs://", "http://storage.googleapis.com/")
 | 
						|
    url_ova_sum = "%s.sha256" % url_ova
 | 
						|
 | 
						|
    # Compare the remote checksum with the local checksum.
 | 
						|
    lcl_ova_sum_val = get_local_checksum(ova_sum)
 | 
						|
    print("image-upload-ova:  local sha256 %s" % lcl_ova_sum_val)
 | 
						|
    rem_ova_sum_val = get_remote_checksum(url_ova_sum)
 | 
						|
    print("image-upload-ova: remote sha256 %s" % rem_ova_sum_val)
 | 
						|
    if lcl_ova_sum_val == rem_ova_sum_val:
 | 
						|
        print("image-upload-ova: skipping upload")
 | 
						|
        print("image-upload-ova: download from %s" % url_ova)
 | 
						|
        return
 | 
						|
 | 
						|
    # Activate the GCS service account.
 | 
						|
    activate_service_account(key_file)
 | 
						|
    atexit.register(deactivate_service_account)
 | 
						|
 | 
						|
    # Upload the OVA and its checksum.
 | 
						|
    print("image-upload-ova: upload %s" % gcs_ova)
 | 
						|
    subprocess.check_call(['gsutil', 'cp', ova, gcs_ova])
 | 
						|
    print("image-upload-ova: upload %s" % gcs_ova_sum)
 | 
						|
    subprocess.check_call(['gsutil', 'cp', ova_sum, gcs_ova_sum])
 | 
						|
 | 
						|
    print("image-upload-ova: download from %s" % url_ova)
 | 
						|
 | 
						|
 | 
						|
def activate_service_account(path):
 | 
						|
    args = [
 | 
						|
        "gcloud", "auth",
 | 
						|
        "activate-service-account",
 | 
						|
        "--key-file", path,
 | 
						|
    ]
 | 
						|
    subprocess.check_call(args)
 | 
						|
 | 
						|
 | 
						|
def deactivate_service_account():
 | 
						|
    subprocess.call(["gcloud", "auth", "revoke"])
 | 
						|
 | 
						|
 | 
						|
def get_remote_checksum(url):
 | 
						|
    r = requests.get(url)
 | 
						|
    if r.status_code >= 200 and r.status_code <= 299:
 | 
						|
        return r.text.strip()
 | 
						|
    return None
 | 
						|
 | 
						|
 | 
						|
def get_local_checksum(path):
 | 
						|
    with open(path, 'r') as f:
 | 
						|
        return f.readline().strip()
 | 
						|
 | 
						|
 | 
						|
if __name__ == "__main__":
 | 
						|
    main()
 |