2018-06-11 13:13:19 +00:00
package registries
import (
2023-10-23 20:24:09 +00:00
"fmt"
2018-06-11 13:13:19 +00:00
"net/http"
2021-02-23 03:21:39 +00:00
portainer "github.com/portainer/portainer/api"
2021-07-14 09:15:21 +00:00
httperrors "github.com/portainer/portainer/api/http/errors"
"github.com/portainer/portainer/api/http/security"
2023-10-23 20:24:09 +00:00
"github.com/portainer/portainer/api/pendingactions"
2023-09-01 22:27:02 +00:00
httperror "github.com/portainer/portainer/pkg/libhttp/error"
"github.com/portainer/portainer/pkg/libhttp/request"
"github.com/portainer/portainer/pkg/libhttp/response"
2023-10-23 20:24:09 +00:00
"github.com/rs/zerolog/log"
2018-06-11 13:13:19 +00:00
)
2021-02-23 03:21:39 +00:00
// @id RegistryDelete
// @summary Remove a registry
// @description Remove a registry
2021-10-11 23:12:08 +00:00
// @description **Access policy**: restricted
2021-02-23 03:21:39 +00:00
// @tags registries
2021-11-30 02:31:16 +00:00
// @security ApiKeyAuth
2021-02-23 03:21:39 +00:00
// @security jwt
// @param id path int true "Registry identifier"
// @success 204 "Success"
// @failure 400 "Invalid request"
// @failure 404 "Registry not found"
// @failure 500 "Server error"
// @router /registries/{id} [delete]
2018-06-11 13:13:19 +00:00
func ( handler * Handler ) registryDelete ( w http . ResponseWriter , r * http . Request ) * httperror . HandlerError {
2021-07-14 09:15:21 +00:00
securityContext , err := security . RetrieveRestrictedRequestContext ( r )
if err != nil {
2022-09-14 23:42:39 +00:00
return httperror . InternalServerError ( "Unable to retrieve info from request context" , err )
2021-07-14 09:15:21 +00:00
}
if ! securityContext . IsAdmin {
2022-09-14 23:42:39 +00:00
return httperror . Forbidden ( "Permission denied to delete registry" , httperrors . ErrResourceAccessDenied )
2021-07-14 09:15:21 +00:00
}
2018-06-11 13:13:19 +00:00
registryID , err := request . RetrieveNumericRouteVariableValue ( r , "id" )
if err != nil {
2022-09-14 23:42:39 +00:00
return httperror . BadRequest ( "Invalid registry identifier route variable" , err )
2018-06-11 13:13:19 +00:00
}
2023-10-23 20:24:09 +00:00
registry , err := handler . DataStore . Registry ( ) . Read ( portainer . RegistryID ( registryID ) )
if err != nil {
return httperror . InternalServerError ( fmt . Sprintf ( "Unable to load registry %q from the database" , registry . Name ) , err )
2018-06-11 13:13:19 +00:00
}
2023-06-22 21:28:07 +00:00
err = handler . DataStore . Registry ( ) . Delete ( portainer . RegistryID ( registryID ) )
2018-06-11 13:13:19 +00:00
if err != nil {
2022-09-14 23:42:39 +00:00
return httperror . InternalServerError ( "Unable to remove the registry from the database" , err )
2018-06-11 13:13:19 +00:00
}
2023-10-23 20:24:09 +00:00
err = handler . deleteKubernetesSecrets ( registry )
if err != nil {
return httperror . InternalServerError ( "Unable to delete registry secrets" , err )
}
2018-06-11 13:13:19 +00:00
return response . Empty ( w )
}
2023-10-23 20:24:09 +00:00
func ( handler * Handler ) deleteKubernetesSecrets ( registry * portainer . Registry ) error {
for endpointId , access := range registry . RegistryAccesses {
if access . Namespaces != nil {
// Obtain a kubeclient for the endpoint
endpoint , err := handler . DataStore . Endpoint ( ) . Endpoint ( endpointId )
if err != nil {
// Skip environments that can't be loaded from the DB
log . Warn ( ) . Err ( err ) . Msgf ( "Unable to load the environment with id %d from the database" , endpointId )
continue
}
cli , err := handler . K8sClientFactory . GetKubeClient ( endpoint )
if err != nil {
// Skip environments that can't get a kubeclient from
log . Warn ( ) . Err ( err ) . Msgf ( "Unable to get kubernetes client for environment %d" , endpointId )
continue
}
failedNamespaces := make ( [ ] string , 0 )
for _ , ns := range access . Namespaces {
err = cli . DeleteRegistrySecret ( registry . ID , ns )
if err != nil {
failedNamespaces = append ( failedNamespaces , ns )
log . Warn ( ) . Err ( err ) . Msgf ( "Unable to delete registry secret %q from namespace %q for environment %d. Retrying offline" , cli . RegistrySecretName ( registry . ID ) , ns , endpointId )
}
}
if len ( failedNamespaces ) > 0 {
handler . PendingActionsService . Create ( portainer . PendingActions {
EndpointID : endpointId ,
Action : pendingactions . DeletePortainerK8sRegistrySecrets ,
// When extracting the data, this is the type we need to pull out
// i.e. pendingactions.DeletePortainerK8sRegistrySecretsData
ActionData : pendingactions . DeletePortainerK8sRegistrySecretsData {
RegistryID : registry . ID ,
Namespaces : failedNamespaces ,
} ,
} )
}
}
}
return nil
}