Skip to content

Commit 8ef8b46

Browse files
shwstpprDaan Hoogland
authored and
Daan Hoogland
committed
cks: create separate service account in project
A separate service account will be created and added in the project, if not exist already, when a Kubernetes cluster is deployed in a project. This account will have a role with limited API access. Cleanup clusters on owner account cleanup, delete service account if needed When the owner account of k8s clusters is deleted, while its node VMs get expunged, the cluster entry in DB remain present. This fixes the issue by cleaning up all clusters for the account deleted. Project k8s service account will be deleted on account cleanup or when there is no active k8s cluster remaining Signed-off-by: Abhishek Kumar <[email protected]>
1 parent 4d1f912 commit 8ef8b46

File tree

9 files changed

+307
-49
lines changed

9 files changed

+307
-49
lines changed

api/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelper.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,13 @@
1818

1919
import org.apache.cloudstack.acl.ControlledEntity;
2020

21+
import com.cloud.user.Account;
2122
import com.cloud.uservm.UserVm;
2223
import com.cloud.utils.component.Adapter;
2324

2425
public interface KubernetesServiceHelper extends Adapter {
2526

2627
ControlledEntity findByUuid(String uuid);
2728
void checkVmCanBeDestroyed(UserVm userVm);
29+
void cleanupForAccount(Account account);
2830
}

engine/schema/src/main/java/com/cloud/user/dao/AccountDao.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,23 +16,25 @@
1616
// under the License.
1717
package com.cloud.user.dao;
1818

19+
import java.util.Date;
20+
import java.util.List;
21+
1922
import com.cloud.user.Account;
2023
import com.cloud.user.AccountVO;
2124
import com.cloud.user.User;
2225
import com.cloud.utils.Pair;
2326
import com.cloud.utils.db.Filter;
2427
import com.cloud.utils.db.GenericDao;
2528

26-
import java.util.Date;
27-
import java.util.List;
28-
2929
public interface AccountDao extends GenericDao<AccountVO, Long> {
3030
Pair<User, Account> findUserAccountByApiKey(String apiKey);
3131

3232
List<AccountVO> findAccountsLike(String accountName);
3333

3434
Pair<List<AccountVO>, Integer> findAccountsLike(String accountName, Filter filter);
3535

36+
List<AccountVO> findAccountsByName(String accountName);
37+
3638
List<AccountVO> findActiveAccounts(Long maxAccountId, Filter filter);
3739

3840
List<AccountVO> findRecentlyDeletedAccounts(Long maxAccountId, Date earliestRemovedDate, Filter filter);

engine/schema/src/main/java/com/cloud/user/dao/AccountDaoImpl.java

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,15 @@
1616
// under the License.
1717
package com.cloud.user.dao;
1818

19+
import java.sql.PreparedStatement;
20+
import java.sql.ResultSet;
21+
import java.util.Date;
22+
import java.util.List;
23+
24+
import org.apache.commons.lang3.StringUtils;
25+
import org.apache.log4j.Logger;
26+
import org.springframework.stereotype.Component;
27+
1928
import com.cloud.user.Account;
2029
import com.cloud.user.Account.State;
2130
import com.cloud.user.AccountVO;
@@ -30,15 +39,7 @@
3039
import com.cloud.utils.db.SearchCriteria;
3140
import com.cloud.utils.db.SearchCriteria.Func;
3241
import com.cloud.utils.db.SearchCriteria.Op;
33-
import org.apache.commons.lang3.StringUtils;
3442
import com.cloud.utils.db.TransactionLegacy;
35-
import org.apache.log4j.Logger;
36-
import org.springframework.stereotype.Component;
37-
38-
import java.sql.PreparedStatement;
39-
import java.sql.ResultSet;
40-
import java.util.Date;
41-
import java.util.List;
4243

4344
@Component
4445
public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao {
@@ -180,6 +181,16 @@ public Pair<List<AccountVO>, Integer> findAccountsLike(String accountName, Filte
180181
return searchAndCount(sc, filter);
181182
}
182183

184+
@Override
185+
public List<AccountVO> findAccountsByName(String accountName) {
186+
SearchBuilder<AccountVO> sb = createSearchBuilder();
187+
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.EQ);
188+
sb.done();
189+
SearchCriteria<AccountVO> sc = sb.create();
190+
sc.setParameters("accountName", accountName);
191+
return search(sc, null);
192+
}
193+
183194
@Override
184195
public Account findEnabledAccount(String accountName, Long domainId) {
185196
SearchCriteria<AccountVO> sc = AllFieldsSearch.create("accountName", accountName);

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterManagerImpl.java

Lines changed: 224 additions & 27 deletions
Large diffs are not rendered by default.

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesClusterService.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@
1616
// under the License.
1717
package com.cloud.kubernetes.cluster;
1818

19+
import java.util.List;
20+
1921
import org.apache.cloudstack.api.command.user.kubernetes.cluster.AddVirtualMachinesToKubernetesClusterCmd;
2022
import org.apache.cloudstack.api.command.user.kubernetes.cluster.CreateKubernetesClusterCmd;
2123
import org.apache.cloudstack.api.command.user.kubernetes.cluster.DeleteKubernetesClusterCmd;
@@ -33,16 +35,16 @@
3335
import org.apache.cloudstack.framework.config.ConfigKey;
3436
import org.apache.cloudstack.framework.config.Configurable;
3537

38+
import com.cloud.user.Account;
3639
import com.cloud.utils.component.PluggableService;
3740
import com.cloud.utils.exception.CloudRuntimeException;
3841

39-
import java.util.List;
40-
4142
public interface KubernetesClusterService extends PluggableService, Configurable {
4243
static final String MIN_KUBERNETES_VERSION_HA_SUPPORT = "1.16.0";
4344
static final int MIN_KUBERNETES_CLUSTER_NODE_CPU = 2;
4445
static final int MIN_KUBERNETES_CLUSTER_NODE_RAM_SIZE = 2048;
4546
static final String KUBEADMIN_ACCOUNT_NAME = "kubeadmin";
47+
String PROJECT_KUBEADMIN_ACCOUNT_ROLE_NAME = "Project Kubernetes Service Role";
4648

4749
static final ConfigKey<Boolean> KubernetesServiceEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class,
4850
"cloud.kubernetes.service.enabled",
@@ -122,4 +124,6 @@ public interface KubernetesClusterService extends PluggableService, Configurable
122124
boolean addVmsToCluster(AddVirtualMachinesToKubernetesClusterCmd cmd);
123125

124126
List<RemoveVirtualMachinesFromKubernetesClusterResponse> removeVmsFromCluster(RemoveVirtualMachinesFromKubernetesClusterCmd cmd);
127+
128+
void cleanupForAccount(Account account);
125129
}

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/KubernetesServiceHelperImpl.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao;
3535
import com.cloud.kubernetes.version.KubernetesSupportedVersion;
3636
import com.cloud.kubernetes.version.KubernetesVersionEventTypes;
37+
import com.cloud.user.Account;
3738
import com.cloud.uservm.UserVm;
3839
import com.cloud.utils.component.AdapterBase;
3940
import com.cloud.utils.exception.CloudRuntimeException;
@@ -47,6 +48,8 @@ public class KubernetesServiceHelperImpl extends AdapterBase implements Kubernet
4748
private KubernetesClusterDao kubernetesClusterDao;
4849
@Inject
4950
private KubernetesClusterVmMapDao kubernetesClusterVmMapDao;
51+
@Inject
52+
KubernetesClusterService kubernetesClusterService;
5053

5154
protected void setEventTypeEntityDetails(Class<?> eventTypeDefinedClass, Class<?> entityClass) {
5255
Field[] declaredFields = eventTypeDefinedClass.getDeclaredFields();
@@ -94,6 +97,11 @@ public void checkVmCanBeDestroyed(UserVm userVm) {
9497
throw new CloudRuntimeException(msg);
9598
}
9699

100+
@Override
101+
public void cleanupForAccount(Account account) {
102+
kubernetesClusterService.cleanupForAccount(account);
103+
}
104+
97105
@Override
98106
public String getConfigComponentName() {
99107
return KubernetesServiceHelper.class.getSimpleName();

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterDao.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,8 @@
2525

2626
public interface KubernetesClusterDao extends GenericDao<KubernetesClusterVO, Long>,
2727
StateDao<KubernetesCluster.State, KubernetesCluster.Event, KubernetesCluster> {
28-
29-
List<KubernetesClusterVO> listByAccount(long accountId);
28+
List<KubernetesClusterVO> listForCleanupByAccount(long accountId);
29+
int countNotForGCByAccount(long accountId);
3030
List<KubernetesClusterVO> findKubernetesClustersToGarbageCollect();
3131
List<KubernetesClusterVO> findManagedKubernetesClustersInState(KubernetesCluster.State state);
3232
List<KubernetesClusterVO> listByNetworkId(long networkId);

plugins/integrations/kubernetes-service/src/main/java/com/cloud/kubernetes/cluster/dao/KubernetesClusterDaoImpl.java

Lines changed: 26 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -30,16 +30,25 @@
3030
@Component
3131
public class KubernetesClusterDaoImpl extends GenericDaoBase<KubernetesClusterVO, Long> implements KubernetesClusterDao {
3232

33-
private final SearchBuilder<KubernetesClusterVO> AccountIdSearch;
33+
private final SearchBuilder<KubernetesClusterVO> CleanupAccountIdSearch;
34+
private final SearchBuilder<KubernetesClusterVO> NotForGCByAccountIDCount;
3435
private final SearchBuilder<KubernetesClusterVO> GarbageCollectedSearch;
3536
private final SearchBuilder<KubernetesClusterVO> ManagedStateSearch;
3637
private final SearchBuilder<KubernetesClusterVO> SameNetworkSearch;
3738
private final SearchBuilder<KubernetesClusterVO> KubernetesVersionSearch;
3839

3940
public KubernetesClusterDaoImpl() {
40-
AccountIdSearch = createSearchBuilder();
41-
AccountIdSearch.and("account", AccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
42-
AccountIdSearch.done();
41+
CleanupAccountIdSearch = createSearchBuilder();
42+
CleanupAccountIdSearch.and("account", CleanupAccountIdSearch.entity().getAccountId(), SearchCriteria.Op.EQ);
43+
CleanupAccountIdSearch.and("cluster_type", CleanupAccountIdSearch.entity().getClusterType(), SearchCriteria.Op.EQ);
44+
CleanupAccountIdSearch.done();
45+
46+
NotForGCByAccountIDCount = createSearchBuilder();
47+
NotForGCByAccountIDCount.and("gc", NotForGCByAccountIDCount.entity().isCheckForGc(), SearchCriteria.Op.EQ);
48+
NotForGCByAccountIDCount.and("account", NotForGCByAccountIDCount.entity().getAccountId(), SearchCriteria.Op.EQ);
49+
NotForGCByAccountIDCount.and("cluster_type", NotForGCByAccountIDCount.entity().getClusterType(), SearchCriteria.Op.EQ);
50+
NotForGCByAccountIDCount.select(null, SearchCriteria.Func.COUNT, null);
51+
NotForGCByAccountIDCount.done();
4352

4453
GarbageCollectedSearch = createSearchBuilder();
4554
GarbageCollectedSearch.and("gc", GarbageCollectedSearch.entity().isCheckForGc(), SearchCriteria.Op.EQ);
@@ -62,10 +71,20 @@ public KubernetesClusterDaoImpl() {
6271
}
6372

6473
@Override
65-
public List<KubernetesClusterVO> listByAccount(long accountId) {
66-
SearchCriteria<KubernetesClusterVO> sc = AccountIdSearch.create();
74+
public List<KubernetesClusterVO> listForCleanupByAccount(long accountId) {
75+
SearchCriteria<KubernetesClusterVO> sc = CleanupAccountIdSearch.create();
76+
sc.setParameters("cluster_type", KubernetesCluster.ClusterType.CloudManaged);
77+
sc.setParameters("account", accountId);
78+
return listBy(sc);
79+
}
80+
81+
@Override
82+
public int countNotForGCByAccount(long accountId) {
83+
SearchCriteria<KubernetesClusterVO> sc = NotForGCByAccountIDCount.create();
84+
sc.setParameters("cluster_type", KubernetesCluster.ClusterType.CloudManaged);
6785
sc.setParameters("account", accountId);
68-
return listBy(sc, null);
86+
sc.setParameters("gc", false);
87+
return getCount(sc);
6988
}
7089

7190
@Override

server/src/main/java/com/cloud/user/AccountManagerImpl.java

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
import org.apache.commons.lang3.StringUtils;
8686
import org.apache.log4j.Logger;
8787
import org.jetbrains.annotations.NotNull;
88+
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
8889

8990
import com.cloud.api.ApiDBUtils;
9091
import com.cloud.api.auth.SetupUserTwoFactorAuthenticationCmd;
@@ -117,6 +118,7 @@
117118
import com.cloud.exception.OperationTimedoutException;
118119
import com.cloud.exception.PermissionDeniedException;
119120
import com.cloud.exception.ResourceUnavailableException;
121+
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
120122
import com.cloud.network.IpAddress;
121123
import com.cloud.network.IpAddressManager;
122124
import com.cloud.network.Network;
@@ -171,6 +173,7 @@
171173
import com.cloud.utils.NumbersUtil;
172174
import com.cloud.utils.Pair;
173175
import com.cloud.utils.Ternary;
176+
import com.cloud.utils.component.ComponentContext;
174177
import com.cloud.utils.component.Manager;
175178
import com.cloud.utils.component.ManagerBase;
176179
import com.cloud.utils.component.PluggableService;
@@ -859,6 +862,16 @@ public boolean deleteAccount(AccountVO account, long callerUserId, Account calle
859862
return cleanupAccount(account, callerUserId, caller);
860863
}
861864

865+
protected void cleanupPluginsResourcesIfNeeded(Account account) {
866+
try {
867+
KubernetesServiceHelper kubernetesServiceHelper =
868+
ComponentContext.getDelegateComponentOfType(KubernetesServiceHelper.class);
869+
kubernetesServiceHelper.cleanupForAccount(account);
870+
} catch (NoSuchBeanDefinitionException ignored) {
871+
s_logger.debug("No KubernetesServiceHelper bean found");
872+
}
873+
}
874+
862875
protected boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) {
863876
long accountId = account.getId();
864877
boolean accountCleanupNeeded = false;
@@ -940,6 +953,8 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c
940953
}
941954
}
942955

956+
cleanupPluginsResourcesIfNeeded(account);
957+
943958
// Destroy the account's VMs
944959
List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
945960
if (s_logger.isDebugEnabled()) {

0 commit comments

Comments
 (0)