Skip to content

Commit 19d6b97

Browse files
shwstpprPearl1594
authored andcommitted
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 9cf9966 commit 19d6b97

File tree

9 files changed

+306
-51
lines changed

9 files changed

+306
-51
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,6 +18,7 @@
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

@@ -26,4 +27,5 @@ public interface KubernetesServiceHelper extends Adapter {
2627
ControlledEntity findByUuid(String uuid);
2728
ControlledEntity findByVmId(long vmId);
2829
void checkVmCanBeDestroyed(UserVm userVm);
30+
void cleanupForAccount(Account account);
2931
}

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: 18 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,14 @@
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.springframework.stereotype.Component;
26+
1927
import com.cloud.user.Account;
2028
import com.cloud.user.Account.State;
2129
import com.cloud.user.AccountVO;
@@ -30,14 +38,7 @@
3038
import com.cloud.utils.db.SearchCriteria;
3139
import com.cloud.utils.db.SearchCriteria.Func;
3240
import com.cloud.utils.db.SearchCriteria.Op;
33-
import org.apache.commons.lang3.StringUtils;
3441
import com.cloud.utils.db.TransactionLegacy;
35-
import org.springframework.stereotype.Component;
36-
37-
import java.sql.PreparedStatement;
38-
import java.sql.ResultSet;
39-
import java.util.Date;
40-
import java.util.List;
4142

4243
@Component
4344
public class AccountDaoImpl extends GenericDaoBase<AccountVO, Long> implements AccountDao {
@@ -190,6 +191,16 @@ public Pair<List<AccountVO>, Integer> findAccountsLike(String accountName, Filte
190191
return searchAndCount(sc, filter);
191192
}
192193

194+
@Override
195+
public List<AccountVO> findAccountsByName(String accountName) {
196+
SearchBuilder<AccountVO> sb = createSearchBuilder();
197+
sb.and("accountName", sb.entity().getAccountName(), SearchCriteria.Op.EQ);
198+
sb.done();
199+
SearchCriteria<AccountVO> sc = sb.create();
200+
sc.setParameters("accountName", accountName);
201+
return search(sc, null);
202+
}
203+
193204
@Override
194205
public Account findEnabledAccount(String accountName, Long domainId) {
195206
SearchCriteria<AccountVO> sc = AllFieldsSearch.create("accountName", accountName);

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

Lines changed: 226 additions & 30 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;
@@ -34,16 +36,16 @@
3436
import org.apache.cloudstack.framework.config.Configurable;
3537

3638
import com.cloud.network.Network;
39+
import com.cloud.user.Account;
3740
import com.cloud.utils.component.PluggableService;
3841
import com.cloud.utils.exception.CloudRuntimeException;
3942

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

4850
static final ConfigKey<Boolean> KubernetesServiceEnabled = new ConfigKey<Boolean>("Advanced", Boolean.class,
4951
"cloud.kubernetes.service.enabled",
@@ -125,4 +127,6 @@ public interface KubernetesClusterService extends PluggableService, Configurable
125127
List<RemoveVirtualMachinesFromKubernetesClusterResponse> removeVmsFromCluster(RemoveVirtualMachinesFromKubernetesClusterCmd cmd);
126128

127129
boolean isDirectAccess(Network network);
130+
131+
void cleanupForAccount(Account account);
128132
}

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
@@ -32,6 +32,7 @@
3232
import com.cloud.kubernetes.cluster.dao.KubernetesClusterVmMapDao;
3333
import com.cloud.kubernetes.version.KubernetesSupportedVersion;
3434
import com.cloud.kubernetes.version.KubernetesVersionEventTypes;
35+
import com.cloud.user.Account;
3536
import com.cloud.uservm.UserVm;
3637
import com.cloud.utils.component.AdapterBase;
3738
import com.cloud.utils.exception.CloudRuntimeException;
@@ -50,6 +51,8 @@ public class KubernetesServiceHelperImpl extends AdapterBase implements Kubernet
5051
private KubernetesClusterDao kubernetesClusterDao;
5152
@Inject
5253
private KubernetesClusterVmMapDao kubernetesClusterVmMapDao;
54+
@Inject
55+
KubernetesClusterService kubernetesClusterService;
5356

5457
protected void setEventTypeEntityDetails(Class<?> eventTypeDefinedClass, Class<?> entityClass) {
5558
Field[] declaredFields = eventTypeDefinedClass.getDeclaredFields();
@@ -106,6 +109,11 @@ public void checkVmCanBeDestroyed(UserVm userVm) {
106109
throw new CloudRuntimeException(msg);
107110
}
108111

112+
@Override
113+
public void cleanupForAccount(Account account) {
114+
kubernetesClusterService.cleanupForAccount(account);
115+
}
116+
109117
@Override
110118
public String getConfigComponentName() {
111119
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: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -120,6 +120,7 @@
120120
import com.cloud.exception.PermissionDeniedException;
121121
import com.cloud.exception.ResourceUnavailableException;
122122
import com.cloud.host.dao.HostDao;
123+
import com.cloud.kubernetes.cluster.KubernetesServiceHelper;
123124
import com.cloud.network.IpAddress;
124125
import com.cloud.network.IpAddressManager;
125126
import com.cloud.network.Network;
@@ -887,6 +888,16 @@ public boolean deleteAccount(AccountVO account, long callerUserId, Account calle
887888
return cleanupAccount(account, callerUserId, caller);
888889
}
889890

891+
protected void cleanupPluginsResourcesIfNeeded(Account account) {
892+
try {
893+
KubernetesServiceHelper kubernetesServiceHelper =
894+
ComponentContext.getDelegateComponentOfType(KubernetesServiceHelper.class);
895+
kubernetesServiceHelper.cleanupForAccount(account);
896+
} catch (NoSuchBeanDefinitionException ignored) {
897+
logger.debug("No KubernetesServiceHelper bean found");
898+
}
899+
}
900+
890901
protected boolean cleanupAccount(AccountVO account, long callerUserId, Account caller) {
891902
long accountId = account.getId();
892903
boolean accountCleanupNeeded = false;
@@ -968,6 +979,8 @@ protected boolean cleanupAccount(AccountVO account, long callerUserId, Account c
968979
}
969980
}
970981

982+
cleanupPluginsResourcesIfNeeded(account);
983+
971984
// Destroy the account's VMs
972985
List<UserVmVO> vms = _userVmDao.listByAccountId(accountId);
973986
if (logger.isDebugEnabled()) {

0 commit comments

Comments
 (0)