47
Dani Gutiérrez Porset [email protected] para el Grupo SOPRA Vitoria-Gasteiz, Dic-2013 Curso de Puppet: Curso de Puppet: Lenguaje de configuración (2/2) Lenguaje de configuración (2/2)

Curso puppet lenguaje_2

Embed Size (px)

Citation preview

Page 1: Curso puppet lenguaje_2

Dani Gutiérrez [email protected]

para el Grupo SOPRA

Vitoria-Gasteiz, Dic-2013

Curso de Puppet:Curso de Puppet:Lenguaje de configuración (2/2)Lenguaje de configuración (2/2)

Page 2: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración2

Licencia y ReferenciasLicencia y Referencias

● Autor: Dani Gutiérrez

● Licencia: Copyright

● Imágenes referenciadas o diseñadas por el autor. Logotipos y marcas pertenecientes a sus respectivas organizaciones

● Esta presentación se ha realizado gracias al software libre GNU/Linux, KDE, LibreOffice, Firefox, Chromium, Inkscape, Gimp, Gwenview, Ksnapshot

● Referencias:● Libro "Pro Puppet" de James Turnbull y Jeffrey McCune – Ed.

2011● http://puppetlabs.com

Page 3: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración3

ÍndiceÍndice

● Resumen de elementos de configuraciones

● Manifiestos y Catálogos

● Nodos

● Módulos

● Clases. Herencia. Definición y declaración

● Recursos. Recursos por defecto. Referencias a recursos. Dependencias entre recursos. Tipos de recursos definidos. Tipos de recursos custom. Recursos virtuales. Recolectores de recursos. Recursos exportados

● Etiquetas

Page 4: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración4

Resumen de ElementosResumen de Elementospara definir configuracionespara definir configuraciones

● Elementos de lenguaje:

● Recursos: elementos básicos de configuración● Clases: conjuntos de recursos relacionados● Nodos: especificación de la configuración de cada

nodo● Ficheros y directorios:

● Módulos: colecciones portables de manifests● Ficheros: se envían a los agentes● Plantillas: ficheros que se usan para generar otros

ficheros

Page 5: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración5

ManifiestosManifiestos

● Son ficheros de código fuente con extensión .pp

● Formato:

● Es recomendable que lleven codificación UTF8● Saltos de línea con LF o CR LF

● Pueden incluir otros ficheros de $confdir/manifests/:import 'nombrefichero_con_o_sin_punto_pp'import 'carpeta/*'

Page 6: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración6

CatálogosCatálogos

● Un catálogo es uno o varios manifiestos compilados. Manifestos y catálogos contienen recursos y relaciones

● Cada catálogo es válido para un nodo

● En los agentes se quedan cacheados

● Físicamente es un documento que no tiene una especificación de formato concreta, pero puede estar:

● En memoria, como un objeto Ruby● En la red en formato JSON● En el disco duro en formato YAML

Page 7: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración7

NodosNodos

● El tratamiento de un host o nodo se realiza asociando código proveniente de dos orígenes:

● De la definición del nodo● De código externo

● El elemento nodo establece un nuevo ámbito en el que se pueden sobreescribir variables y valores por defecto del ámbito superior

● Un nodo puede heredar de otros nodos, de forma idéntica a las clases, pero no se recomienda

Page 8: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración8

Nodos y fichero site.ppNodos y fichero site.pp● Definición en fichero site.pp:

● La definición de nodos ha de estar en site.pp pero desde éste se pueden importar, ej:import super_nodo.ppimport nodos/*.pp

● Si site.pp contiene alguna definición de nodo, entonces todos los nodos han de poder referenciarse desde dicho fichero. Útil para este caso: default

● Aunque el nombre de un nodo se encuentre en varias definiciones, sólo se aplica un único caso en este orden:

● Búsqueda del nombre exacto

● Primera expresión regular encontrada

● Si es un fqdn, se va eliminando cada zona desde la derecha

● Uso de la definición default

Page 9: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración9

Nodos: definiciónNodos: definición● Sintaxis:node 'identificador' {... # declaración de clases, variables,...}

● Se puede definir más de un nodo: node 'nodo1','nodo2',... {

● Notas sobre el identificador:

● Suele ser el fqdn, ej: nodo1.acme.com● Se admiten además:

– Sentencias regulares, ej: node /^www\d+$/ {...– default: aplica a los nodos para los que no se encuentra

identificador

Page 10: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración10

MódulosMódulos● Agrupación independiente de recursos, clases, definiciones, ficheros

y plantillas

● Todos los manifiestos pertenecen a algún nodo a excepción del site.pp que sería el global

● Los módulos se cargan de directorios indicados en la variable de configuración $modulepath

● Modulos de interés en https://forge.puppetlabs.com/

● Reglas sobre el nombre:

● Comienza con minúscula y puede contener minúsculas, números y _

● El nombre puede hacer referencia a espacios de nombres con ::Ej:espacio1::espacio2:: ... ::clase1

Page 11: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración11

Módulos:Módulos:Carpetas típicasCarpetas típicas

● Carpeta de módulo tiene debajo unos subdirectorios estándar

● files

● manifests

● templates

● lib: contiene plugins (ej. Facts y tipos de recurso customizados)

● tests: ejemplos sobre cómo declarar las clases y los tipos definidos de módulos

● spec: pruebas para los plugins de lib/

Page 12: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración12

Espacios de nombresEspacios de nombres

● Hace referencia a los subdirectorios bajo la carpeta de módulos en los que se encuentran las Clases y los Tipos definidos

● Se usa :: para separar de forma análoga al /

● Aplica también a las variables definidas en clases

● Ejs:class apache::mod::passenger {...}define apache::vhost {...}

● En la versión 3 hay alguna incompatibilidad con versiones anteriores. Ver http://docs.puppetlabs.com/puppet/3/reference/lang_namespaces.html

Page 13: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración13

Espacios de nombres:Espacios de nombres:casoscasos

● Si el nombre no incluye :: (esto es, no hay espacio de nombres) busca en<modulepath>/nombre/manifests/init.pp

● Si el nombre incluye una o más veces :: de la forma a::b::nombre (sí hay espacio de nombres) busca en<modulepath>/a/manifests/b/nombre.pp

● Ejs:class apache::mod::passenger {...}buscaría en<modulepath>/apache/manifests/mod/passenger.pp

Page 14: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración14

ClasesClases

● Son bloques de código, agrupables en módulos, para el tratamiento unificado de recursos semejantes o relacionados

● Distinción:● Definición: hace que esté disponible para un

uso posterior● Declaración: añade los recursos una clase a

un catálogo

Page 15: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración15

Clases: Definición (1)Clases: Definición (1)● Sintaxis sin parámetros:

class nombreclase { ... #declaración de recursos,...}

● Sintaxis con parámetros:class nombreclase ($param1, $param2=valor,...,$paramN) { ... #declaración de recursos,...}Puede haber , antes del paréntesis de cierreLos parámetros pueden llevar un valor por defecto (pero si falta y en ejecución no hay valor, da error)

Page 16: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración16

Clases: Definición (2)Clases: Definición (2)

● Reglas sobre el identificador:● Comienza con minúscula y puede contener minúsculas,

números y _● Puede hacer referencia a espacios de nombres con :: ej:espacio1::espacio2:: ... ::clase1

● Lugar de definición:● Preferentemente, en el directorio manifests/ de cada

módulo, con un fichero por cada clase● Otras opciones: en site.pp o en manifests importados● No recomendado: dentro de otra clase (anidamiento)

Page 17: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración17

Clases: DeclaraciónClases: Declaración

● Formas de declaración:

● "Include-Like":– Permite declarar una clase múltiples veces sin dar error

– No permite sobreescribir valores

● "Resource-Like":– Una clase sólo se puede declarar una vez

– Permite sobreescribir valores

● Lugar de declaración:● En definición de nodo● En site.pp● En otras clases o tipos definidos

Page 18: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración18

Clases:Clases:Declaraciones "Include-like"Declaraciones "Include-like"

● Principales:

● Función include: declara una o varias clases separadas por , o en array, ej:include base::linux, apache

● Función (no metaparámetro) require: declara una o más clases estableciendo dependencias, pero cuidado con las relaciones circulares

● Otras:

● contain: (v3.4): para incluir una clase en otra● hiera_include: para el plugin de datos jerárquicos Hiera

Page 19: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración19

Clases:Clases:Declaraciones "Resource-like"Declaraciones "Resource-like"

● Se declaran con class, sin o con sobreescritura:Ej:class {'base::linux':}class {'apache': version => '2.2.21', }

Page 20: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración20

Clases: HerenciaClases: Herencia

● Se permite la herencia simple (de una sola clase), siempre que la clase base no tenga parámetros.

● Sintaxis de definición con herencia:class nombreclase inherits nombreclasebase { ... #declaración de recursos,...}

● Se heredan variables y valores por defecto de recursos

● La clase derivada adquiere un nuevo ámbito: el de la clase base

● La declaración (no definición) de una clase derivada hace que automáticamente se declare antes la clase base

Page 21: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración21

Clases: Herencia:Clases: Herencia:SobreescrituraSobreescritura

● Se pueden sobrescribir (o eliminar con undef) atributos de recursos usando referencias a los recursos de la clase base

● Para añadir metaparámetros, la sintaxis en clases derivadas es mediante el operador +>ej:class apache::ssl inherits apache { Service['apache]{ require +> [ File['apache.pem'], File['httpd.conf'] ], }}

Page 22: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración22

RecursosRecursos

● Son el elemento básico para modelar configuraciones● Hay unos 50 tipos predefinidos (paquete, servicio,

fichero,...) y además se pueden definir nuevos tipos● Listados: puppet describe --list

http://docs.puppetlabs.com/references/stable/type.html

● Ayuda: puppet describe package | less● Llevan un identificador ("title")

Page 23: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración23

Recursos: AtributosRecursos: Atributos

● Cada recurso tiene unos atributos, según el tipo, que describen su estado, ej. si ha de estar instalado un paquete

● Cuando se aplica un catálogo, se compara el valor real de cada atributo con el declarado, para hacer o no cambios. Si se hacen, el orden es según dependencias y el más eficiente

● Los cambios se auditan quedando registrados en el log

Page 24: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración24

Recursos: Atributos especialesRecursos: Atributos especiales● Name o Namevar:

● Nombre que identifica al recurso en el sistema destino (ej. el path de un fichero)

● Es distinto del identificador para Puppet, pero a menudo coinciden. Ej: identificador ntp y nombre ntpd en Red Hat, ntp en Debian,...

● ensure: hace referencia a aspectos dependientes del tipo y del sistema, ej. asegurar que un servicio está en marcha. En general sus valores típicos son present y absent

● provider: implementación del recurso en un sistema. Es sobreescribible, ej. Instalación de librerías Ruby con apt-get o con gemas

● Metaparámetros

Page 25: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración25

Recursos: MetaparámetrosRecursos: Metaparámetros

● Son atributos especiales que pueden usarse en cualquier tipo de recurso (comunes al framework)

● No dan información sobre el estado sino cómo ha de actuar Puppet con el recurso

● Referencia:http://docs.puppetlabs.com/references/stable/metaparameter.html

● Ej:puppet describe package -m | grep -A 20 "Meta Parameters"

Page 26: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración26

Recursos: Metaparámetros (1)Recursos: Metaparámetros (1)● alias: vale para establecer dependencias, ej:

file { '/etc/ssh/sshd_config': ... alias => 'sshdcfg'}Uso:subscribe => File['sshdcfg']

● audit: marca un atributo, un array de atributos o todos (all) para auditar en el log y en informes de inspección

● loglevel: indica el nivel de log. Puede ser debug, info, notice, warning, err, alert, emerg, crit, verbose

● noop: si está definido a true no se hace ninguna operación con el recurso

Page 27: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración27

Recursos: Metaparámetros (2)Recursos: Metaparámetros (2)

● require: indica recursos requeridos o de los que depende el objeto actual, de modo que los indicados se aplican antes del actual

● before: referencia a otros objetos que dependen del actual, el cual se aplica antes que los demás.

● notify: idem que before pero refrescando los objetos dependientes cuando el objeto actual se modifica

● subscribe: opuesto a notify

Page 28: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración28

Recursos: Metaparámetros (3)Recursos: Metaparámetros (3)● schedule: indica la referencia a un objeto de tipo schedule, ej:

schedule { 'daily': period => daily, range => "2-4"}exec { "/usr/bin/apt-get update": schedule => 'daily'}

● stage: indica el entorno o etapa a la que corresponde una clase (no es aplicable en recursos). Útil si se definen otras etapas aparte de la main, ej:stage{['pre','post']}

● tag: añade etiquetas a un recurso, ej:file {'/etc/hosts': tag => ['importante', 'pendiente'],Para ej. aplicar filtrando por tags:puppet agent --test --tags pendiente

Page 29: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración29

Recursos: DeclaraciónRecursos: Declaración

● Declaración de recurso: bloque de código que hace que se incluya en un catálogo, para gestionar su estado en el agente

● Son independientes de ámbito: pueden ser referenciados desde donde sea

● Dónde se declaran y cuándo se compilan:● Si están en una clase, cuando se declara● Si están en un tipo de recurso definido, cuando se declara

su instancia● Si son un recurso virtual, cuando se materializa

Page 30: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración30

Recursos:Recursos:Declaración: Sintaxis (1)Declaración: Sintaxis (1)

● Sintaxis para un recurso:tipo_recurso { 'identificador': atributo1 => valor1, atributo2 => valor2, ...}

● Sintaxis para varios recursos, mediante array:tipo_recurso { ['id1','id2','id3',...]: atributo1 => valor1, atributo2 => valor2, ...}

● Sintaxis para varios recursos, mediante zonas de recurso:tipo_recurso { 'id1': atributo1.1 => valor1.1, ...; 'id2': atributo2.1 => valor2.1, ...;}

Page 31: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración31

Recursos:Recursos:Declaración: Sintaxis (2)Declaración: Sintaxis (2)

● El identificador ha de ser único para cada tipo de recurso

● Atributos:

● Muchos tienen un valor por defecto● Para los atributos que se declaren hay que asignarles

un valor● Si son multivalor, éstos se asignan con un array

● Antes de } puede haber una ,

Page 32: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración32

Recursos:Recursos:Modificación de atributosModificación de atributos

● Mediante referencia: permite añadir atributos, o modificarlos en el caso de clases heredadas, ej:file {'/etc/passwd': ensure => file, } File['/etc/passwd'] { owner => 'root', }

● Mediante recolector: File <| tag == 'superuser' |> { owner => 'root',}

Page 33: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración33

Recursos por defectoRecursos por defecto

● Especifican valores por defecto para determinados atributos en un tipo concreto de recursos. Una declaración de ese tipo usará los valores definidos

● En un ámbito dado se pueden sobreescribir los valores por defecto de ámbitos superiores

● Sintaxis de definición:Tipo_recurso { atributo1 => valor1 ...}Ej:Contexto1::Contexto2::File { group => 'all'}

Page 34: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración34

Referencias a recursosReferencias a recursos

● Identifican un recurso de configuración, según las sintaxis:Tipo['id1']Tipo['id2','id2',...,'idN']Ejs:File['/etc/sudoers']Package['ldap-utils','slapd']Espacio1::Package['sudo']

● La primera letra del nombre o nombres de espacio ha de ir en mayúscula

● Es un tipo de datos. Internamente en Ruby el tipo es un Puppet::Resource

Page 35: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración35

Dependencias entre Recursos:Dependencias entre Recursos:Metaparámetros de relaciones (1)Metaparámetros de relaciones (1)

● Válidos para relacionar recursos

● Aplicar un recurso después del aplicar el recurso destino: requireEj: Procesar el fichero /etc/sudoers después de instalar el paquete sudo:file {'/etc/sudoers':

...require => Package["sudo"],

}

● Idem que el anterior con notificación: subscribe

● Aplicar un recurso antes de aplicar el recurso destino: beforeEj: before => Exec["nagios-rebuid"]

● Idem que el anterior con notificación: notify

Page 36: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración36

Dependencias entre Recursos:Dependencias entre Recursos:Metaparámetros de relaciones (2)Metaparámetros de relaciones (2)

● Sintaxis:tipo_recurso {'recurso':

...metaparámetro => referencia_a_recurso_destino,

}Ejemplo:file {'/etc/sudoers':

...require => Package["sudo"],

}

● Sintaxis en clases derivadas: operador +>ej:class apache::ssl inherits apache { Service['apache]{ require +> [ File['apache.pem'], File['httpd.conf'] ], }}

Page 37: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración37

Dependencias entre Recursos:Dependencias entre Recursos:Otros métodosOtros métodos

● Para relacionar recursos, uso de flechas:

● recurso1 => recurso2Se aplica primero recurso1 y después recurso2Ej: File['/etc/ntp.conf'] => Service['ntpd']

● recurso1 ~> recurso2Se aplica primero recurso1 y después recurso2, y además se notifica a recurso2 si recurso1 ha cambiado

● Para relacionar clases, función require:

● Ej:class wordpress { require apache require mysql ...}

Page 38: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración38

Tipos de recursos definidosTipos de recursos definidos

● También llamados"Defined types" o "Defines"● Bloque de código que actúa como un nuevo

tipo de recurso● Al igual que en las clases, se distingue entre

definición y declaración. La declaración es la instancia concreta, el recurso en sí

● Admiten metaparámetros y valores por defecto

Page 39: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración39

Tipos de recursos definidos:Tipos de recursos definidos:DefiniciónDefinición

● Sintaxis sin parámetros:define nombretipo { ... #declaración de recursos,...}

● Sintaxis con parámetros:define nombretipo ($param1, $param2=valor,...,$paramN) { ... #declaración de recursos,...}

● Notas:

● Reglas para el nombre idem que para las clases

● Puede haber , antes del paréntesis de cierre

● Los parámetros pueden llevar un valor por defecto (si falta y en ejecución no hay valor, da error)

Page 40: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración40

Tipos de recursos definidos:Tipos de recursos definidos:DeclaraciónDeclaración

● Idem que un recurso normal. Se definen dentro de cada módulo (un fichero por tipo bajo el directorio manifests correspondiente) o bien en site.pp.

● Los parámetros que no tienen valores por defecto han de ser asignados con notación de atributos (operador => y no =), ej:tipo_recursoA {'identificadorA': param1=>valor1, ...}tipo_recursoB {'identificadorB':}

● El identificador puede ser una combinación de atributos mientras sea único, ej: file { "${vhost_dir}/${servername}.conf": ...

● Atributos extras, disponibles en la lista de parámetros de la definición

● $title: identificador de la instancia

● $name: por defecto el identificador, pero se puede especificar otro valor en la declaración

Page 41: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración41

Tipos de recursos CustomTipos de recursos Custom

● Semejantes a tipos definidos, pero con más complejidad por incluir proveedores

● Relacionan:● Tipo: parámetros, validación de entrada,

funcionalidades a proveer● Proveedores: implementación de funcionalidades en

operaciones específicas de cada sistema● Sintaxis: se usa newtype● Se escriben en Ruby

Page 42: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración42

Recursos virtualesRecursos virtuales

● Semejantes a recursos (identificador, tipo,...), establecen un estado deseado para un recurso sin añadirlo al catálogo. Posteriormente se puede añadir al catálogo incluyendo ("realize") el recurso virtual

● Se declaran una sola vez, y se pueden incluir múltiples veces

● Uso:

● Gestión de recursos dependiente de condiciones● Uso de un recursos que se solapan en varias clases

● Semejantes a clases. Diferencia: Se pueden gestionar con recolectores

Page 43: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración43

Recursos virtuales:Recursos virtuales:Sintaxis de declaración y usoSintaxis de declaración y uso

● Declaración:@tipo {'identificador': ...}Ej:@user { 'prueba': uid => 1000, tag => [desarrollo, pruebas], }

● Inclusión mediante realize:realize Tipo['identificador']Ej:realize User['desarrollo']

● Inclusión mediante un recolector:Tipo <| condición |>Ej:User <|tag==desarrollo|>

Page 44: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración44

Recolectores de recursosRecolectores de recursos

● Seleccionan recursos a partir de una búsqueda de atributos definidos en manifests (no según el estado del recurso en el destino).

● Utilidades:

● Listado de recursos● Usar recursos virtuales● Definir dependencias encadenadas

● Sintaxis: Tipo_recurso <| expresión_de_búsqueda |>Ej:User <| tag == 'local' |>

Page 45: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración45

Recursos exportadosRecursos exportados

● Permiten compartir información entre nodos● Especifica un estado deseado para un recurso,

no gestiona ese estado para el sistema destino, y publica el recurso para ser usado en otros nodos, los cuales pueden recoger el recurso exportado y gestionar una copia local

● Requieren PuppetDB

Page 46: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración46

EtiquetasEtiquetas

● Etiquetas o palabras clave a asignar a cada recurso

● Uso: obtener un conjunto de recursos con recolectores y en expresiones de comparación:

● En aplicación de catálogos, ej:sudo puppet agent --test --tags upgrade,holanda

● En informes, ej. de tipo "tagmail", para enviar mensajes cuando recursos con determinadas etiquetas hayan variado

Page 47: Curso puppet lenguaje_2

Curso de Puppet – Lenguaje de configuración47

Etiquetas:Etiquetas:AsignaciónAsignación

● Se asignan automáticamente etiquetas con:

● El tipo de recurso

● Para la clase o tipo definido correspondiente a la declaración del recurso, el nombre completo y cada identificador del espacio de nombresEj: si la clase es apache::ssl se crearían apache::ssl, apache, ssl

● Para hacer una asignación manual:

● Uso del metaparámetro tag Ej: tag => ['etiq1','etiq2']

● Uso de la función tag en una definición de clase o de tipo de recurso, para asignar la etiqueta a los recursos contenidos dentro. Ej:class usuario { tag 'importante', 'urgente' recurso ...