def _create_namespaced_account_objects(self): namespace = self.get_user_namespace() account = self.service_account if not account: self.log.info("No service account defined.") return (None, None, None) md = client.V1ObjectMeta(name=account) svcacct = client.V1ServiceAccount(metadata=md) rules = [ client.V1PolicyRule( api_groups=[""], resources=["pods", "services"], verbs=["get", "list", "watch", "create", "delete"]), client.V1PolicyRule(api_groups=[""], resources=["pods/log"], verbs=["get", "list"]), ] role = client.V1Role(rules=rules, metadata=md) rolebinding = client.V1RoleBinding( metadata=md, role_ref=client.V1RoleRef(api_group="rbac.authorization.k8s.io", kind="Role", name=account), subjects=[ client.V1Subject(kind="ServiceAccount", name=account, namespace=namespace) ]) return svcacct, role, rolebinding
def create_k8s_svca(namespace: str, name: str): """ Create a Kubernetes service account in a namespace in the cluster. An existing service account with this name in this namespace leads to a no-op. This operation is performed by portal backend admins, which may not have enough permissions. It is also non-destructive, so we run it with portal permissions. Returns the new service account. """ core_v1 = get_portal_core_v1() try: k8s_svca = client.V1ServiceAccount( api_version="v1", kind="ServiceAccount", metadata=client.V1ObjectMeta(name=name)) core_v1.create_namespaced_service_account(namespace=namespace, body=k8s_svca) logger.info(f"Created Kubernetes service account '{namespace}:{name}'") except client.rest.ApiException as e: # Race condition or earlier sync error - the K8S namespace is already there if e.status == 409: logger.warning( f"Tried to create already existing Kubernetes service account '{namespace}:{name}'. Skipping the creation and using the existing one." ) else: raise e return core_v1.read_namespaced_service_account(namespace=namespace, name=name)
def simple_serviceaccount(): """Return the Kubernetes config matching the simple-serviceaccount.yaml manifest.""" return client.V1ServiceAccount( api_version="v1", kind="ServiceAccount", metadata=client.V1ObjectMeta(name="build-robot"), )
def create_or_update_service_account(module): """ creates or patches the k8s ServiceAccount object. :param module: :return: V1ServiceAccount Dict returned from k8s API """ results = dict() namespace = module.params.get('namespace') name = module.params.get('name') labels = module.params.get('labels') api = client.CoreV1Api() try: api_service_account_response = _read_service_account(name, namespace) if _check_service_account_changed(api_service_account_response, module): try: results = api.patch_namespaced_service_account( client.V1ServiceAccount(metadata=client.V1ObjectMeta( name=namespace, labels=labels))) changed = True except ApiException as e: module.fail_json( msg="Unable to patch k8s ServiceAccount: {0}".format( to_native(e)), exception=traceback.format_exc()) else: results = api_service_account_response changed = False except ApiException as e: if e.status == 404: try: results = api.create_namespaced_service_account( client.V1ServiceAccount(metadata=client.V1ObjectMeta( name=namespace, labels=labels))) changed = True except ApiException as e: module.fail_json( msg="Unable to create k8s ServiceAccount: {0}".format( to_native(e)), exception=traceback.format_exc()) return changed, results
def create_quick_sa_definition(saName, saNamespace, annotationsDict={}): serviceaccount = client.V1ServiceAccount(api_version="v1", kind="ServiceAccount", metadata=client.V1ObjectMeta( name=saName, namespace=saNamespace, annotations=annotationsDict)) return serviceaccount
def _service_account(self): return client.V1ServiceAccount( api_version='v1', kind='ServiceAccount', metadata=metadata( name=self.name, namespace=self.namespace, ) )
def _service_account(self): return client.V1ServiceAccount( api_version='v1', kind='ServiceAccount', metadata=metadata( name=self.name, namespace=self.namespace, annotations=dict({'eks.amazonaws.com/role-arn': self.role_arn}) ) )
def _mock_vault_functionality(self): secret_dict = {key: "secret" for key in self.vault_secrets} VaultStore.get_secrets = unittest.mock.Mock(return_value=secret_dict) object_meta = client.V1ObjectMeta(name="test-service-account", namespace=self.namespace) secret = client.V1ObjectReference(name=self.vault_secret_name, namespace=self.namespace) service_account = client.V1ServiceAccount(metadata=object_meta, secrets=[secret]) get_k8s().v1api.read_namespaced_service_account = unittest.mock.Mock( return_value=service_account)
def create_serviceaccount(cli, name, ns=DEFAULT_SA_NAMESPACE): print("create_serviceaccount", name) api = k8c.CoreV1Api(cli) meta = k8c.V1ObjectMeta(name=name) body = k8c.V1ServiceAccount(metadata=meta) try: rsp = api.create_namespaced_service_account(namespace=ns, body=body) api.list_namespaced_service_account return rsp except ApiException as e: current_app.logger.error(e) return None
def define_service_account(): """ Create Service Account body """ sa_body = k_client.V1ServiceAccount(metadata={ "name": "cw-svc", "labels": { "app": "chamberlain" } }) return sa_body
def setup_job_and_deployment_service_accounts(namespace: str) -> None: """Setup a jobs-and-deployments service-account with required roles. :param namespace: Namespace in which the service-account will be placed. """ service_account_object = k8s.V1ServiceAccount( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_JOBS_DEPLOYMENTS_SERVICE_ACCOUNT ) ) k8s.CoreV1Api().create_namespaced_service_account( namespace=namespace, body=service_account_object ) role_object = k8s.V1Role( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_JOBS_DEPLOYMENTS_SERVICE_ACCOUNT ), rules=[ k8s.V1PolicyRule( api_groups=[""], resources=["secrets", "configmaps"], verbs=["get", "list"], ) ], ) k8s.RbacAuthorizationV1Api().create_namespaced_role( namespace=namespace, body=role_object ) role_binding_object = k8s.V1RoleBinding( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_JOBS_DEPLOYMENTS_SERVICE_ACCOUNT ), role_ref=k8s.V1RoleRef( kind="Role", name=BODYWORK_JOBS_DEPLOYMENTS_SERVICE_ACCOUNT, api_group="rbac.authorization.k8s.io", ), subjects=[ k8s.V1Subject( kind="ServiceAccount", name=BODYWORK_JOBS_DEPLOYMENTS_SERVICE_ACCOUNT, namespace=namespace, ) ], ) k8s.RbacAuthorizationV1Api().create_namespaced_role_binding( namespace=namespace, body=role_binding_object )
def create_project_service_account(self, project, service_account, namespace=""): namespace = self.resolve_namespace(namespace) k8s_service_account = client.V1ServiceAccount() labels = {"mlrun/project": project} k8s_service_account.metadata = client.V1ObjectMeta( name=service_account, namespace=namespace, labels=labels ) try: api_response = self.v1api.create_namespaced_service_account( namespace, k8s_service_account, ) return api_response except ApiException as exc: logger.error(f"failed to create service account: {exc}") raise exc
def patch_service_account(secret_name, namespace, sa_name): 'Patch namespaced service account to attach with created secret.' try: client.CoreV1Api().patch_namespaced_service_account( sa_name, namespace, client.V1ServiceAccount(secrets=[ client.V1ObjectReference(kind='Secret', name=secret_name) ])) except client.rest.ApiException as e: raise RuntimeError( "Exception when calling CoreV1Api->patch_namespaced_service_account: %s\n" % e) logger.info('Pacthed Service account: %s in namespace %s', sa_name, namespace)
def create_namespaced_service_account(self, name, namespace="default"): """Create service account using name in namespace""" body = client.V1ServiceAccount() metadata = client.V1ObjectMeta() metadata.name = name body.metadata = metadata try: self.core_cli.create_namespaced_service_account( namespace=namespace, body=body) logger.info('Created serviceaccount {} in namespace'.format( name, namespace)) return except client.rest.ApiException as e: self.check_create_error_and_response(e, "ServiceAccount", name) return False
def create_serviceaccount(self, api_instance, namespace, name, image_pull_secret_name=None): body = client.V1ServiceAccount( api_version='v1', kind='ServiceAccount', metadata=client.V1ObjectMeta(name=name, namespace=namespace), automount_service_account_token=True, image_pull_secrets=image_pull_secret_name if image_pull_secret_name is None else [client.V1LocalObjectReference(name=image_pull_secret_name)]) result = api_instance.create_namespaced_service_account( namespace, body) return result
def create_service_account(secret_name, namespace, sa_name): 'Create namespaced service account, and return the service account name' try: client.CoreV1Api().create_namespaced_service_account( namespace, client.V1ServiceAccount(metadata=client.V1ObjectMeta(name=sa_name), secrets=[ client.V1ObjectReference( kind='Secret', name=secret_name) ])) except client.rest.ApiException as e: raise RuntimeError( "Exception when calling CoreV1Api->create_namespaced_service_account: %s\n" % e) logger.info('Created Service account: %s in namespace %s', sa_name, namespace)
def add_svca_to_kubernetes(request, portal_svca, portal_ns): logger.info("Creating Kubernetes service account '{0}:{1}'".format( portal_ns.name, portal_svca.name)) k8s_svca = client.V1ServiceAccount( api_version="v1", kind="ServiceAccount", metadata=client.V1ObjectMeta(name=portal_svca.name)) core_v1.create_namespaced_service_account(namespace=portal_ns.name, body=k8s_svca) # Fetch UID and store it in portal record created_k8s_svca = core_v1.read_namespaced_service_account( name=portal_svca.name, namespace=portal_ns.name) portal_svca.uid = created_k8s_svca.metadata.uid portal_svca.save() messages.success( request, "Created service account '{0}:{1}' in Kubernetes.".format( portal_ns.name, portal_svca.name))
def create_service_account(): """ Create IBM Spectrum Scale CSI Operator ServiceAccount in Operator namespace Args: None Returns: None Raises: Raises an exception on kubernetes client api failure and asserts """ pretty = True service_account_api_instance = client.CoreV1Api() service_account_labels = { "app.kubernetes.io/instance": "ibm-spectrum-scale-csi-operator", "app.kubernetes.io/managed-by": "ibm-spectrum-scale-csi-operator", "app.kubernetes.io/name": "ibm-spectrum-scale-csi-operator", "product": "ibm-spectrum-scale-csi", "release": "ibm-spectrum-scale-csi-operator" } service_account_metadata = client.V1ObjectMeta( name="ibm-spectrum-scale-csi-operator", namespace=namespace_value, labels=service_account_labels) service_account_body = client.V1ServiceAccount( api_version="v1", kind="ServiceAccount", metadata=service_account_metadata) try: LOGGER.info("Creating ibm-spectrum-scale-csi-operator ServiceAccount") service_account_api_response = service_account_api_instance.create_namespaced_service_account( namespace=namespace_value, body=service_account_body, pretty=pretty) LOGGER.debug(str(service_account_api_response)) except ApiException as e: LOGGER.error( f"Exception when calling CoreV1Api->create_namespaced_service_account: {e}" ) assert False
def create_service_account(self): """ kubectl -n ${SERVICE_ACCOUNT_NAMESPACE} create serviceaccount ${SERVICE_ACCOUNT_NAME} --dry-run=client -o yaml | kubectl apply -f - """ print("Create service account...") try: meta_obj = k8s_client.V1ObjectMeta(name=self.sa_name) body = k8s_client.V1ServiceAccount(metadata=meta_obj) api_response = self.k8s.create_namespaced_service_account(namespace=self.sa_namespace, body=body) except ApiException as e: error_body = json.loads(e.body) message = error_body['message'] reason = error_body['reason'] if reason == 'AlreadyExists': print(f"---> {message} for namespace {self.sa_namespace}") else: raise
def setup_workflow_service_account(namespace: str) -> None: """Setup a workflow controller service-account with required roles. :param namespace: Namespace in which the service-account will be placed. """ service_account_object = k8s.V1ServiceAccount( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT ) ) k8s.CoreV1Api().create_namespaced_service_account( namespace=namespace, body=service_account_object ) role_object = k8s.V1Role( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT ), rules=[ k8s.V1PolicyRule(api_groups=[""], resources=["*"], verbs=["*"]), k8s.V1PolicyRule( api_groups=["apps", "batch"], resources=["*"], verbs=["*"] ), k8s.V1PolicyRule( api_groups=["extensions"], resources=["ingresses"], verbs=["*"] ), ], ) k8s.RbacAuthorizationV1Api().create_namespaced_role( namespace=namespace, body=role_object ) role_binding_object = k8s.V1RoleBinding( metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT ), role_ref=k8s.V1RoleRef( kind="Role", name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, api_group="rbac.authorization.k8s.io", ), subjects=[ k8s.V1Subject( kind="ServiceAccount", name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, namespace=namespace, ) ], ) k8s.RbacAuthorizationV1Api().create_namespaced_role_binding( namespace=namespace, body=role_binding_object ) if not cluster_role_exists(BODYWORK_WORKFLOW_CLUSTER_ROLE): cluster_role_object = k8s.V1ClusterRole( metadata=k8s.V1ObjectMeta(name=BODYWORK_WORKFLOW_CLUSTER_ROLE), rules=[ k8s.V1PolicyRule( api_groups=[""], resources=["namespaces"], verbs=["get", "list"] ), k8s.V1PolicyRule( api_groups=["rbac.authorization.k8s.io"], resources=["clusterrolebindings"], verbs=["get", "list"], ), ], ) k8s.RbacAuthorizationV1Api().create_cluster_role(body=cluster_role_object) if not cluster_role_binding_exists(workflow_cluster_role_binding_name(namespace)): cluster_role_binding_object = k8s.V1ClusterRoleBinding( metadata=k8s.V1ObjectMeta( name=workflow_cluster_role_binding_name(namespace), namespace=namespace ), role_ref=k8s.V1RoleRef( kind="ClusterRole", name=BODYWORK_WORKFLOW_CLUSTER_ROLE, api_group="rbac.authorization.k8s.io", ), subjects=[ k8s.V1Subject( kind="ServiceAccount", name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, namespace=namespace, ) ], ) k8s.RbacAuthorizationV1Api().create_cluster_role_binding( body=cluster_role_binding_object )
def def_namespaced_account_objects(self): '''Define K8s objects for things we need in the namespace. ''' with start_action(action_type="define_namespaced_account_objects"): namespace = self.namespace username = self.parent.user.escaped_name account = "{}-svcacct".format(username) self.service_account = account acd = 'argocd.argoproj.io/' md = client.V1ObjectMeta( name=account, labels={acd + 'instance': 'nublado-users'}, annotations={ acd + 'compare-options': 'IgnoreExtraneous', acd + 'sync-options': 'Prune=false', }) svcacct = client.V1ServiceAccount(metadata=md) # These rules let us manipulate Dask pods, Argo Workflows, and # Multus CNI interfaces rules = [ client.V1PolicyRule( api_groups=["argoproj.io"], resources=["workflows", "workflows/finalizers"], verbs=[ "get", "list", "watch", "update", "patch", "create", "delete" ]), client.V1PolicyRule( api_groups=["argoproj.io"], resources=[ "workflowtemplates", "workflowtemplates/finalizers" ], verbs=["get", "list", "watch"], ), client.V1PolicyRule(api_groups=[""], resources=["secrets"], verbs=["get"]), client.V1PolicyRule( api_groups=[""], resources=["pods", "pods/exec", "services", "configmaps"], verbs=[ "get", "list", "watch", "create", "delete", "update", "patch" ]), client.V1PolicyRule(api_groups=[""], resources=["pods/log", "serviceaccounts"], verbs=["get", "list", "watch"]), ] role = client.V1Role(rules=rules, metadata=md) rbstr = 'rbac.authorization.k8s.io' rolebinding = client.V1RoleBinding( metadata=md, role_ref=client.V1RoleRef(api_group=rbstr, kind="Role", name=account), subjects=[ client.V1Subject(kind="ServiceAccount", name=account, namespace=namespace) ]) return svcacct, role, rolebinding
def def_namespaced_account_objects(self): """Define K8s objects for things we need in the namespace.""" with start_action(action_type="define_namespaced_account_objects"): namespace = self.namespace username = self.parent.user.escaped_name cfg = self.parent.config psnm = cfg.pull_secret_name pull_secret = get_pull_secret(pull_secret_name=psnm, api=self.parent.api, log=self.log) pull_secret_ref = get_pull_secret_reflist(pull_secret_name=psnm) account = "{}-svcacct".format(username) self.service_account = account acd = "argocd.argoproj.io/" md = client.V1ObjectMeta( name=account, labels={acd + "instance": "nublado-users"}, annotations={ acd + "compare-options": "IgnoreExtraneous", acd + "sync-options": "Prune=false", }, ) svcacct = client.V1ServiceAccount( metadata=md, image_pull_secrets=pull_secret_ref) # These rules let us manipulate Dask pods, Argo Workflows, and # Multus CNI interfaces rules = [ client.V1PolicyRule( api_groups=["argoproj.io"], resources=["workflows", "workflows/finalizers"], verbs=[ "get", "list", "watch", "update", "patch", "create", "delete", ], ), client.V1PolicyRule( api_groups=["argoproj.io"], resources=[ "workflowtemplates", "workflowtemplates/finalizers", ], verbs=["get", "list", "watch"], ), client.V1PolicyRule(api_groups=[""], resources=["secrets"], verbs=["get"]), client.V1PolicyRule( api_groups=[""], resources=["pods", "pods/exec", "services", "configmaps"], verbs=[ "get", "list", "watch", "create", "delete", "update", "patch", ], ), client.V1PolicyRule( api_groups=[""], resources=["pods/log", "serviceaccounts"], verbs=["get", "list", "watch"], ), ] role = client.V1Role(rules=rules, metadata=md) rbstr = "rbac.authorization.k8s.io" rolebinding = client.V1RoleBinding( metadata=md, role_ref=client.V1RoleRef(api_group=rbstr, kind="Role", name=account), subjects=[ client.V1Subject( kind="ServiceAccount", name=account, namespace=namespace, ) ], ) return pull_secret, svcacct, role, rolebinding
def setup_workflow_service_account(namespace: str) -> None: """Setup a workflow controller service-account with required roles. :param namespace: Namespace in which the service-account will be placed. """ service_account_object = k8s.V1ServiceAccount(metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT)) k8s.CoreV1Api().create_namespaced_service_account( namespace=namespace, body=service_account_object) role_object = k8s.V1Role(metadata=k8s.V1ObjectMeta( namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT), rules=[ k8s.V1PolicyRule(api_groups=[''], resources=['*'], verbs=['*']), k8s.V1PolicyRule(api_groups=['apps', 'batch'], resources=['*'], verbs=['*']) ]) k8s.RbacAuthorizationV1Api().create_namespaced_role(namespace=namespace, body=role_object) role_binding_object = k8s.V1RoleBinding( metadata=k8s.V1ObjectMeta(namespace=namespace, name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT), role_ref=k8s.V1RoleRef(kind='Role', name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, api_group='rbac.authorization.k8s.io'), subjects=[ k8s.V1Subject(kind='ServiceAccount', name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, namespace=namespace) ]) k8s.RbacAuthorizationV1Api().create_namespaced_role_binding( namespace=namespace, body=role_binding_object) if not cluster_role_exists(BODYWORK_WORKFLOW_CLUSTER_ROLE): cluster_role_object = k8s.V1ClusterRole( metadata=k8s.V1ObjectMeta(name=BODYWORK_WORKFLOW_CLUSTER_ROLE), rules=[ k8s.V1PolicyRule(api_groups=[''], resources=['namespaces'], verbs=['get', 'list']), k8s.V1PolicyRule(api_groups=['rbac.authorization.k8s.io'], resources=['clusterrolebindings'], verbs=['get', 'list']) ]) k8s.RbacAuthorizationV1Api().create_cluster_role( body=cluster_role_object) if not cluster_role_binding_exists( workflow_cluster_role_binding_name(namespace)): cluster_role_binding_object = k8s.V1ClusterRoleBinding( metadata=k8s.V1ObjectMeta( name=workflow_cluster_role_binding_name(namespace), namespace=namespace), role_ref=k8s.V1RoleRef(kind='ClusterRole', name=BODYWORK_WORKFLOW_CLUSTER_ROLE, api_group='rbac.authorization.k8s.io'), subjects=[ k8s.V1Subject(kind='ServiceAccount', name=BODYWORK_WORKFLOW_SERVICE_ACCOUNT, namespace=namespace) ]) k8s.RbacAuthorizationV1Api().create_cluster_role_binding( body=cluster_role_binding_object)
namespace = "test-dev001" # Configs can be set in Configuration class directly or using helper utility config.load_kube_config('./kube-config') v1 = client.CoreV1Api() # create K8s namespace ret = v1.create_namespace( client.V1Namespace(metadata=client.V1ObjectMeta(name=namespace))) print("create K8s namespace :" + namespace) # create K8s service account ret = v1.create_namespaced_service_account( "account", client.V1ServiceAccount(metadata=client.V1ObjectMeta(name="dev001"))) print("create K8s service account 'dev001'") # delete K8s service account # delete_namespaced_service_account("ServerAccount","Namespace") ret = v1.delete_namespaced_service_account("dev001", "account") print("delete K8s namespace 'account' / service account 'dev001'") # create K8s ResourceQuota resource_quota = client.V1ResourceQuota(spec=client.V1ResourceQuotaSpec( hard={ "cpu": "10", "memory": "10G", "pods": "20", "persistentvolumeclaims": "0", "resourcequotas": "10",
def _sync_svcaccounts(request, v1): # K8S svc accounts -> portal svc accounts success_count_pull = 0 ignored_missing_ns = [] k8s_svca_uids = [] k8s_svca_list = None try: k8s_svca_list = v1.list_service_account_for_all_namespaces() except Exception as e: logger.error("Exception: {0}".format(e)) messages.error( request, "Sync failed, error while fetching list of service accounts: {0}.". format(e)) return for k8s_svca in k8s_svca_list.items: try: # remember for later use k8s_svca_uids.append(k8s_svca.metadata.uid) # Not finding the namespace record for this namespace name # means inconsistency - re-sync is needed anyway, so stopping # here is fine try: portal_ns = KubernetesNamespace.objects.get( name=k8s_svca.metadata.namespace) except Exception: logger.warning( "Skipping Kubernetes service account {0}:{1}, namespace does not exist." .format(k8s_svca.metadata.namespace, k8s_svca.metadata.name)) ignored_missing_ns.append( (k8s_svca.metadata.namespace, k8s_svca.metadata.name)) continue portal_svca, created = KubernetesServiceAccount.objects.get_or_create( name=k8s_svca.metadata.name, uid=k8s_svca.metadata.uid, namespace=portal_ns) if created: # Create missing service account record logger.info( "Creating record for Kubernetes service account '{0}:{1}'". format(k8s_svca.metadata.namespace, k8s_svca.metadata.name)) portal_svca.save() messages.info( request, "Found new Kubernetes service account '{0}:{1}'.".format( k8s_svca.metadata.namespace, k8s_svca.metadata.name)) else: # No action needed logger.info( "Found existing record for Kubernetes service account '{0}:{1}'" .format(k8s_svca.metadata.namespace, k8s_svca.metadata.name)) success_count_pull += 1 except Exception as e: logger.error("Exception: {0}".format(e)) messages.error( request, "Sync from Kubernetes for service account {0} failed: {1}.". format(k8s_svca.metadata.name, e)) if len(ignored_missing_ns) > 0: names = ["{0}:{1}".format(a, b) for a, b in ignored_missing_ns] messages.warning( request, "Skipping service accounts with non-existent namespaces: {0}". format(names)) # portal service accounts -> K8S service accounts success_count_push = 0 for portal_svca in KubernetesServiceAccount.objects.all(): try: portal_ns = portal_svca.namespace if portal_svca.uid: # Portal service account records with UID must be given in K8S, or they are # stale und should be deleted if portal_svca.uid in k8s_svca_uids: # No action needed logger.info( "Found existing Kubernetes service account for record '{0}:{1}'" .format(portal_ns.name, portal_svca.name)) success_count_push += 1 else: # Remove stale record logger.warning( "Removing stale record for Kubernetes service account '{0}:{1}'" .format(portal_ns.name, portal_svca.name)) portal_svca.delete() messages.info( request, "Service account '{0}:{1}' no longer exists in Kubernetes and was removed." .format(portal_ns.name, portal_svca.name)) else: # Portal service accounts without UID are new and should be created in K8S logger.info( "Creating Kubernetes service account '{0}:{1}'".format( portal_ns.name, portal_svca.name)) k8s_svca = client.V1ServiceAccount( api_version="v1", kind="ServiceAccount", metadata=client.V1ObjectMeta(name=portal_svca.name)) v1.create_namespaced_service_account(namespace=portal_ns.name, body=k8s_svca) # Fetch UID and store it in portal record created_k8s_svca = v1.read_namespaced_service_account( name=portal_svca.name, namespace=portal_ns.name) portal_svca.uid = created_k8s_svca.metadata.uid portal_svca.save() messages.success( request, "Created service account '{0}:{1}' in Kubernetes.".format( portal_ns.name, portal_svca.name)) except Exception as e: logger.error("Exception: {0}".format(e)) messages.error( request, "Sync to Kubernetes for service account {0} failed: {1}.". format(portal_ns.name, e)) if success_count_push == success_count_pull: messages.success(request, "All valid service accounts are in sync.")