Papel
Quando usar: quando o produto tem perfis de usuário reconhecíveis ("leitor", "operador"). E, noutro sentido, quando o código precisa saber se esta release é a ativa.
"Papel" aparece em dois lugares diferentes na plataforma, e vale não confundir:
| Papel | O que é | Onde se decide |
|---|---|---|
| Papel do usuário | Agrupamento de permissões (viewer, operator, admin) | nnp/iam.yaml; o gateway expande |
| Papel da release | Se esta release está active ou standby | Arquivo de papel que o Module Manager escreve no pod |
1. Papel do usuário: agrupa, não autoriza
nnp/iam.yaml:
apiVersion: console.nnumbers.io/v1alpha3
kind: IamDescriptor
product: sample
permissions:
- {id: context.read, description: Ver o contexto verificado pelo serviço (whoami)}
- {id: item.read, description: Ver itens e o estado das varreduras}
- {id: item.create, description: Criar item}
- {id: item.delete, description: Apagar item}
- {id: item.scan, description: Iniciar a varredura assíncrona de um item}
roles:
viewer: {description: Leitura, permissions: [context.read, item.read]}
operator: {description: "Leitura, criação e varredura", permissions: [context.read, item.read, item.create, item.scan]}
admin: {description: Tudo do produto, permissions: ["*"]}
- O papel existe no realm como
nnc:<produto>:<papel>(aqui,nnc:sample:operator) e é atribuído a quem opera o módulo. Quem lê o realm e expande o papel é o gateway: na chamada, o serviço recebe as permissões já expandidas. - O serviço nunca decide por papel.
ServiceContext.roles()existe para mostrar ao cliente e para log, não para autorizar. Quem autoriza é a permissão da rota (veja Permissão). "*"vale todas as permissõestenantdo produto — não é poder de plataforma.- Papel novo é uma linha no descritor mais a atribuição no realm; nada de código.
2. Papel da release: ativa ou standby
Numa troca de release convivem N e N-1. O Module Manager diz a cada pod qual é o papel da release dele, e o SDK relê esse estado a cada consulta (não há cache para envelhecer):
@Component
@Profile("serve")
public class SampleService {
private final RoleWatcher role;
/** O texto do papel desta release: `active` ou `standby`. */
String roleText() {
return role.refresh().role().text();
}
/** Esta release é a ATIVA? */
public boolean activeRole() {
return role.refresh().role() == Role.ACTIVE;
}
}
O whoami publica o papel — é a forma mais rápida de saber, em produção, QUAL release respondeu:
@NnsRoute("whoami")
Views.WhoamiView whoami(ServiceContext sc, Introspection who) {
return Views.WhoamiView.of(who, sc, service.module.iam(), service.roleText(), SampleModule.MARKER, ScanEngine.ENGINE);
}
Em desenvolvimento (sem arquivo de papel) a release única se considera ativa; em produção, sem o arquivo do Module Manager, ela é standby — falha fechada.
3. O que só a release ativa faz
Trabalho de manutenção (reconciliar, expurgar, fechar o que ficou pela metade) roda numa release só,
senão duas releases se atropelam. A forma disso no SDK é @NnsPeriodic: o SDK relê o papel a cada
disparo e não chama o método na standby.
@Component
@Profile("serve")
static class Periodic {
private final SampleService service;
private final ActionReaper reaper;
Periodic(SampleService service, ActionReaper reaper) {
this.service = service;
this.reaper = reaper;
}
@NnsPeriodic(name = "scan-reconcile", every = "1m")
void scanReconcile(Ctx ctx) {
service.reconcileScans(ctx, Duration.ofMinutes(2));
}
@NnsPeriodic(name = "action-reaper", every = "1m")
void reap(Ctx ctx) {
reaper.reap(ctx);
}
}
O RoleState.live() (o conjunto de releases vivas, active + standby) é o que o Reaper usa para
saber quem pode assumir as Actions de uma release que saiu: ActionReaper.of(store, releaseId, () -> role.refresh().live()).
Como testar
O papel é estado de arquivo: o teste escreve o arquivo e confere o efeito.
@Test
void whoamiShowsTheVerifiedContextOfTheToken() {
String token = ctxToken(ctx("whoami", "sample.context.read"), "GET", "/v1/sample/whoami", null);
HttpResponse<String> r = call("GET", "/v1/sample/whoami", token, null);
// Sem arquivo de papel, em desenvolvimento, a release única é a ativa.
assertThat(body(r).get("role").asText()).isEqualTo("active");
}
E a tarefa que só a ativa roda tem teste pelo gancho do SDK, sem esperar o relógio (veja Tarefa periódica):
PeriodicTasks tasks = context.getBean(PeriodicTasks.class);
assertThat(tasks.names()).containsExactlyInAnyOrder("scan-reconcile", "action-reaper");
assertThat(tasks.runOnce("scan-reconcile")).isTrue();
assertThat(service.reconciled).hasValue(1);
Erros comuns
if (sc.roles().contains("admin"))no handler — autorização por papel. A permissão já chegou expandida; usesc.can(…).@Scheduledem vez de@NnsPeriodic— o agendador do Spring não conhece o papel: a standby também dispara, e as duas releases escrevem no mesmo lugar.- Usar
roleText()para decidir — compare comRole.ACTIVE(role.refresh().role()), que é enum; o texto é para o fio e para o log. - Guardar o papel num campo — a troca de release acontece com o pod no ar. Chame
refresh()a cada uso; é barato e é o que o SDK garante. - Achar que a standby não serve tráfego — serve: ela atende requisição normalmente; o que ela não faz é o trabalho de manutenção.
- Criar uma dependência entre papéis no mesmo módulo — a comunicação entre releases do mesmo módulo não existe: se precisa de coordenação, ela é feita pelo banco.
Esta página ajudou?
Reportar um problema nesta páginaNão envie senhas, chaves, tokens ou dados de clientes.