diff options
Diffstat (limited to 'clover/spinnaker')
-rw-r--r-- | clover/spinnaker/__init__.py | 0 | ||||
-rwxr-xr-x | clover/spinnaker/halyard.py | 120 | ||||
-rw-r--r-- | clover/spinnaker/halyard_sample.py | 41 | ||||
-rw-r--r-- | clover/spinnaker/install/quick-install-spinnaker.yml | 376 | ||||
-rw-r--r-- | clover/spinnaker/lib/__init__.py | 0 | ||||
-rwxr-xr-x | clover/spinnaker/lib/halyard_base.py | 157 |
6 files changed, 694 insertions, 0 deletions
diff --git a/clover/spinnaker/__init__.py b/clover/spinnaker/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/clover/spinnaker/__init__.py diff --git a/clover/spinnaker/halyard.py b/clover/spinnaker/halyard.py new file mode 100755 index 0000000..20c0f4b --- /dev/null +++ b/clover/spinnaker/halyard.py @@ -0,0 +1,120 @@ +#!/bin/python + +import lib.halyard_base as base +import time +from clover.orchestration.kube_client import KubeClient + +namespace = 'spinnaker' +client = KubeClient() + +def list_accounts(provider): + account_list = base.list_accounts(provider) + return account_list + +def delete_account(provider, accountname): + result = base.delete_account(provider, accountname) + if result != "SUCCEEDED": + print "Delete account failed" + return result + + apply_result = base.apply_deploy() + if apply_result == "SUCCEEDED": + print "Delete account successfully" + else: + print "Delete account failed" + + return apply_result + +def add_k8s_account(accountname, kubeconfigfile, + providerversion=None, registries=[]): + # Note: if providerversion is V1, must provider registries. + if base.is_account_exist("kubernetes",accountname): + return "FAILED" + if providerversion == None or providerversion == 'V1': + providerversion = None + if 0 == len(registries) or isinstance(registries, list) == False: + print "please provider docker registries or the type of registries is not list" + return "FAILED" + # Copy kubectl file to halyard pod + hal_kubeconfigfile = "/home/spinnaker/config" + \ + time.strftime("%Y-%m-%d-%H-%M-%S", time.localtime()) + spinnaker_pods = client.find_pod_by_namespace(namespace) + for pod in spinnaker_pods: + if pod.find("spin-halyard") == 0: + client.copy_file_to_pod(kubeconfigfile, + hal_kubeconfigfile, + pod, namespace) + dockerRegistries = [] + for registry in registries: + if not base.is_account_exist("dockerRegistry",registry): + print ("Please add docker registry: %s" %registry) + return "FAILED" + docker_dict = {"accountName":registry, "namespaces":[]} + dockerRegistries.append(docker_dict) + + data = { + "name": accountname, + "requiredGroupMembership": [], + "providerVersion": providerversion, + "permissions": {}, + "dockerRegistries": dockerRegistries, + "context": None, + "cluster": None, + "user": None, + "configureImagePullSecrets": "true", + "serviceAccount": None, + "cacheThreads": 1, + "namespaces": [], + "omitNamespaces": [], + "kinds": [], + "omitKinds": [], + "customResources": [], + "cachingPolicies": [], + "kubeconfigFile": hal_kubeconfigfile, + "kubeconfigContents": None, + "kubectlPath": None, + "namingStrategy": None, + "skin": None, + "debug": None, + "oauthScopes": [], + "oauthServiceAccount": None, + "oAuthServiceAccount": None, + "oAuthScopes": [] + } +# print data + result = base.add_account("kubernetes",data) + return result + +def add_docker_account(address, accountname, repositories=[], + username=None, password=None, validate='true'): + + if base.is_account_exist("dockerRegistry",accountname): + return "FAILED" + + data = { + "name": accountname, + "requiredGroupMembership": [], + "providerVersion": None, + "permissions": {}, + "address": address, + "username": username, + "password": password, + "email": "fake.email@spinnaker.io", + "cacheIntervalSeconds": 30, + "clientTimeoutMillis": 60000, + "cacheThreads": 1, + "paginateSize": 100, + "sortTagsByDate": False, + "trackDigests": False, + "insecureRegistry": False, + "repositories": repositories, + "passwordFile": None, + "dockerconfigFile": None + } + result = base.add_account("dockerRegistry",data) + if result == "SUCCEEDED": + print "Add account successfully" + else: + print "Add account failed" + return result + diff --git a/clover/spinnaker/halyard_sample.py b/clover/spinnaker/halyard_sample.py new file mode 100644 index 0000000..b78be9b --- /dev/null +++ b/clover/spinnaker/halyard_sample.py @@ -0,0 +1,41 @@ +# Copyright (c) Authors of Clover +# +# All rights reserved. This program and the accompanying materials +# are made available under the terms of the Apache License, Version 2.0 +# which accompanies this distribution, and is available at +# http://www.apache.org/licenses/LICENSE-2.0 + +import halyard + + +# please install the spinnaker useing the spinnaker/install/quick-install-spinnaker.yml first +print "######## add docker provider ##########" +address = "https://index.docker.io" +repositories = ['wtwde/onap', 'wtwde/spinnaker', 'library/nginx'] +add_docker = halyard.add_docker_account(address, "docker-test", repositories) +print "######## result ##########" +print add_docker + +print "######## add kubernetes provider ##########" +add_k8s = halyard.add_k8s_account('my-k8s-v1-t11561', "/root/config.115", "V1", ['dockerhub']) +print "######## result ##########" +print add_k8s + +print "######## k8s account list ##########" +k8s_list = halyard.list_accounts('kubernetes') +print "####### result ##########" +print k8s_list + +print "######## docker account list ##########" +docker_list = halyard.list_accounts('dockerRegistry') +print "####### result ##########" +print docker_list + +print "######## delete kubernetes provider ##########" +del_k8s = halyard.delete_account('kubernetes','my-k8s-v1-t11561') +print "######## result ##########" + +print "######## delete docker registry provider ##########" +del_docker = halyard.delete_account('dockerRegistry','docker-test') +print "######## result ##########" +print del_docker diff --git a/clover/spinnaker/install/quick-install-spinnaker.yml b/clover/spinnaker/install/quick-install-spinnaker.yml new file mode 100644 index 0000000..c935453 --- /dev/null +++ b/clover/spinnaker/install/quick-install-spinnaker.yml @@ -0,0 +1,376 @@ +apiVersion: v1 +kind: Namespace +metadata: + name: spinnaker + +--- + +apiVersion: rbac.authorization.k8s.io/v1 +kind: ClusterRoleBinding +metadata: + name: spinnaker-admin +roleRef: + apiGroup: rbac.authorization.k8s.io + kind: ClusterRole + name: cluster-admin +subjects: +- kind: ServiceAccount + name: default + namespace: spinnaker + +--- + +apiVersion: v1 +kind: Pod +metadata: + name: spin-halyard + namespace: spinnaker + labels: + app: spin + stack: halyard +spec: + containers: + - name: halyard-daemon + # todo - make :stable or digest of :stable + image: gcr.io/spinnaker-marketplace/halyard:stable + imagePullPolicy: Always + command: + - /bin/sh + args: + - -c + # when the configmap is mounted directly at /home/spinnaker/.hal the halyard daemon + # isn't able to replace the contents of the mount with user modifications. + # so instead we mount the configmap elsewhere and copy the files into + # place when the container starts. + - "cp -R /home/spinnaker/staging/.hal /home/spinnaker/.hal && /opt/halyard/bin/halyard" + readinessProbe: + exec: + command: + - wget + - -q + - --spider + - http://localhost:8064/health + ports: + - containerPort: 8064 + volumeMounts: + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/config + subPath: config + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/default/service-settings/deck.yml + subPath: deck.yml + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/default/service-settings/gate.yml + subPath: gate.yml + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/default/service-settings/igor.yml + subPath: igor.yml + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/default/service-settings/fiat.yml + subPath: fiat.yml + - name: halconfig + mountPath: /home/spinnaker/staging/.hal/default/profiles/front50-local.yml + subPath: front50-local.yml + volumes: + - name: halconfig + configMap: + name: halconfig +--- + +apiVersion: v1 +kind: Service +metadata: + name: spin-halyard + namespace: spinnaker +spec: + ports: + - port: 8064 + targetPort: 8064 + protocol: TCP + selector: + app: spin + stack: halyard + +--- + +apiVersion: v1 +kind: ConfigMap +metadata: + name: halconfig + namespace: spinnaker +data: + igor.yml: | + enabled: true + fiat.yml: | + enabled: false + skipLifeCycleManagement: true + front50-local.yml: | + spinnaker.s3.versioning: false + gate.yml: | + host: 0.0.0.0 + deck.yml: | + host: 0.0.0.0 + env: + API_HOST: http://spin-gate.spinnaker:8084/ + config: | + currentDeployment: default + deploymentConfigurations: + - name: default + version: 1.7.0 + providers: + appengine: + enabled: false + accounts: [] + aws: + enabled: false + accounts: [] + defaultKeyPairTemplate: '{{name}}-keypair' + defaultRegions: + - name: us-west-2 + defaults: + iamRole: BaseIAMRole + azure: + enabled: false + accounts: [] + bakeryDefaults: + templateFile: azure-linux.json + baseImages: [] + dcos: + enabled: false + accounts: [] + clusters: [] + dockerRegistry: + enabled: true + accounts: + - name: dockerhub + address: https://index.docker.io + repositories: + - opnfv/clover + google: + enabled: false + accounts: [] + bakeryDefaults: + templateFile: gce.json + baseImages: [] + zone: us-central1-f + network: default + useInternalIp: false + kubernetes: + enabled: true + accounts: + - name: my-kubernetes-account + requiredGroupMembership: [] + providerVersion: V2 + dockerRegistries: [] + configureImagePullSecrets: true + serviceAccount: true + namespaces: [] + omitNamespaces: [] + kinds: [] + omitKinds: [] + customResources: [] + oauthScopes: [] + oAuthScopes: [] + primaryAccount: my-kubernetes-account + openstack: + enabled: false + accounts: [] + bakeryDefaults: + baseImages: [] + oraclebmcs: + enabled: false + accounts: [] + deploymentEnvironment: + size: SMALL + type: Distributed + accountName: my-kubernetes-account + updateVersions: true + consul: + enabled: false + vault: + enabled: false + customSizing: {} + gitConfig: + upstreamUser: spinnaker + persistentStorage: + persistentStoreType: s3 + azs: {} + gcs: + rootFolder: front50 + redis: {} + s3: + bucket: spinnaker-artifacts + rootFolder: front50 + endpoint: http://minio-service.spinnaker:9000 + accessKeyId: dont-use-this + secretAccessKey: for-production + oraclebmcs: {} + features: + auth: false + fiat: false + chaos: false + entityTags: false + jobs: false + metricStores: + datadog: + enabled: false + prometheus: + enabled: false + add_source_metalabels: true + stackdriver: + enabled: false + period: 30 + enabled: false + notifications: + slack: + enabled: false + timezone: America/Los_Angeles + ci: + jenkins: + enabled: true + masters: [] + travis: + enabled: false + masters: [] + security: + apiSecurity: + ssl: + enabled: false + overrideBaseUrl: /gate + uiSecurity: + ssl: + enabled: false + authn: + oauth2: + enabled: false + client: {} + resource: {} + userInfoMapping: {} + saml: + enabled: false + ldap: + enabled: false + x509: + enabled: false + enabled: false + authz: + groupMembership: + service: EXTERNAL + google: + roleProviderType: GOOGLE + github: + roleProviderType: GITHUB + file: + roleProviderType: FILE + enabled: false + artifacts: + gcs: + enabled: false + accounts: [] + github: + enabled: false + accounts: [] + http: + enabled: false + accounts: [] + pubsub: + google: + enabled: false + subscriptions: [] + +--- + +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: minio-pv-claim + namespace: spinnaker + labels: + app: minio-storage-claim +spec: + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi + storageClassName: standard + +--- + +apiVersion: apps/v1beta1 +kind: Deployment +metadata: + # This name uniquely identifies the Deployment + name: minio-deployment + namespace: spinnaker +spec: + strategy: + type: Recreate + template: + metadata: + labels: + app: minio + spec: + volumes: + - name: storage + persistentVolumeClaim: + claimName: minio-pv-claim + containers: + - name: minio + image: minio/minio + args: + - server + - /storage + env: + - name: MINIO_ACCESS_KEY + value: "dont-use-this" + - name: MINIO_SECRET_KEY + value: "for-production" + ports: + - containerPort: 9000 + volumeMounts: + - name: storage + mountPath: /storage + +--- + +apiVersion: v1 +kind: Service +metadata: + name: minio-service + namespace: spinnaker +spec: + ports: + - port: 9000 + targetPort: 9000 + protocol: TCP + selector: + app: minio + +--- + +apiVersion: batch/v1 +kind: Job +metadata: + name: hal-deploy-apply + namespace: spinnaker + labels: + app: job + stack: hal-deploy +spec: + template: + metadata: + labels: + app: job + stack: hal-deploy + spec: + restartPolicy: OnFailure + containers: + - name: hal-deploy-apply + # todo use a custom image + image: gcr.io/spinnaker-marketplace/halyard:stable + command: + - /bin/sh + args: + - -c + - "hal deploy apply --daemon-endpoint http://spin-halyard.spinnaker:8064" diff --git a/clover/spinnaker/lib/__init__.py b/clover/spinnaker/lib/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/clover/spinnaker/lib/__init__.py diff --git a/clover/spinnaker/lib/halyard_base.py b/clover/spinnaker/lib/halyard_base.py new file mode 100755 index 0000000..7245d6a --- /dev/null +++ b/clover/spinnaker/lib/halyard_base.py @@ -0,0 +1,157 @@ +#!/bin/python + + +import requests +import json +import time + +base_url="http://spin-halyard.spinnaker:8064/v1" +namespace= 'spinnaker' +headers = {'content-type': 'application/json; charset=UTF-8'} +debug = False + +def get(url): + result = requests.get(url) + return result.json() + +def post(url, data = None, headers = None): + result = requests.post(url, data=data, headers=headers) + return result.json() + +def put(url, data = None, headers = None): + result = requests.put(url, data=data, headers=headers) + return result.json() + +def delete(url): + result = requests.delete(url) + return result.json() + +def print_dict_info(dict_info, debug = False): + if dict_info == None: + return None + + if debug == True: + for v,k in dict_info.items(): + print('{v}:{k}'.format(v = v, k = k)) + else: + print dict_info.get('name') + print dict_info.get('state') + +def is_account_exist(provider, accountname): + exist_accounts = list_accounts(provider) + if accountname in exist_accounts: + print "account exists" + return True + print "account doesn't exist" + return False + +def get_task_info(uuid): + if uuid == None: + return None + url = base_url + "/tasks/" + uuid + "/" + result = get(url) + return result + +def wait_task_successful(uuid): + flag = "" + while True: + resp = get_task_info(uuid) + state = resp.get('state') + if flag != state: + print_dict_info(resp, debug) + flag = state + if state == "SUCCEEDED": + return "SUCCEEDED", resp + if state == "FAILED": + return "FAILED", resp + if resp.get('timedOut'): + return "TimeOut", resp + +def get_current_deployment(): + '''get the current deployment and check the state''' + + url = base_url + "/config/currentDeployment" + result = get(url) + uuid = result.get('uuid') + task_info = get_task_info(uuid) + print_dict_info(task_info, debug) + + return task_info + +def apply_deploy(): + """ + after using api to config halyard, it need ruan apply deploy. + """ + prep_url = base_url + "/config/deployments/default/prep/?validate=true" + deploy_url = base_url + "/config/deployments/default/deploy/?validate=false" + data='""' + result = post(prep_url, data=data, headers=headers) + uuid = result.get('uuid') + result, task_info = wait_task_successful(uuid) + if result != "SUCCEEDED": + return result + result = post(deploy_url, data=data, headers=headers) + uuid = result.get('uuid') + result, task_info = wait_task_successful(uuid) + return result + +def list_accounts(provider): + """ + According to the provider, list all accounts + """ + url = base_url + "/config/deployments/default/providers/" + \ + provider + "/?validate=true" + resp = get(url) + uuid = resp.get('uuid') + result, task_info = wait_task_successful(uuid) + if result != "SUCCEEDED": + print "Get account failed" + return None + accounts = task_info.get('response').get('responseBody').get('accounts') + account_list = [] + for account in accounts: + account_name = account.get('name') + account_list.append(account_name) + return account_list + +def enable_provider(provider, data='true'): + """ + if needs to add a provider, it is necessary to enable the provider + """ + url = base_url + "/config/deployments/default/providers/" + \ + provider + "/enabled/?validate=true" + resp = put(url,data=data,headers=headers) + uuid = resp.get('uuid') + result, task_info = wait_task_successful(uuid) + return result + +def add_account(provider, data): + url = base_url + "/config/deployments/default/providers/" + \ + provider + "/accounts/?validate=true" + + enable_provider(provider) + + resp = post(url, data=json.dumps(data), headers=headers) + uuid = resp.get('uuid') + result, task_info = wait_task_successful(uuid) + if result != "SUCCEEDED": + print "Add account failed" + return result + apply_result = apply_deploy() + if apply_result == "SUCCEEDED": + print "Deployment successful" + else: + print "Deployment failed" + return apply_result + +def delete_account(provider, accountname): + if not is_account_exist(provider, accountname): + return "FAILED" + url = base_url + "/config/deployments/default/providers/" + \ + provider + "/accounts/account/" + accountname + "/?validate=true" + resp = delete(url) + uuid = resp.get('uuid') + result, task_info = wait_task_successful(uuid) + + return result + |