Drupal 7 End-of-Life: una panoramica (e qualche suggerimento) per la migrazione a Drupal 9

Roberto Mariani
BMEME
Published in
11 min readFeb 9, 2022

Introduzione

Forse non tutti lo sanno, ma una delle conseguenze indirette del COVID-19 è stata quella di far “slittare” la data di End-of-Life di Drupal 7 di un anno.

Inizialmente prevista per novembre 2021 [PSA-2019–02–25], la data di
End-of-Life di Drupal 7 è stata schedulata al 28 novembre 2022 [PSA-2020–06–24].

…praticamente un “bonus” da “un anno (aggiuntivo)” per pianificare ed effettuare la migrazione a Drupal 9.

Perché “migrare” e non “aggiornare”?

La risposta è tanto semplice quanto spiazzante: perché non si può (come spiegato nella documentazione ufficiale).

Questo è uno dei motivi per cui ci troviamo in una situazione in cui Drupal 8 è già andato in End-of-Life, mentre Drupal 7, temporalmente più “anziano”, ci andrà tra quasi un anno.

Come si migra?

Drupal mette a disposizione il modulo core Migrate e le Migrate API per importare dati da una qualsiasi sorgente (anche non Drupal) a Drupal.

Nel caso di migrazione da Drupal a Drupal, possiamo avvantaggiarci anche dei seguenti moduli core:

  • Migrate Drupal fornisce le funzionalità per migrare dati da Drupal a Drupal
  • Migrate Drupal UI fornisce un’interfaccia grafica per il modulo Migrate Drupal

Tra i moduli contrib che estendono le funzionalità messe a disposizione dal core, i seguenti sono quelli più utili/indispensabili:

mentre i seguenti risultano essere “strategici” in base al tipo di migrazione che si deve effettuare:

In linea puramente teorica, la migrazione da Drupal 7 a Drupal 9 potrebbe avvenire in modo del tutto automatico grazie agli upgrade path, ma nella realtà dei fatti questo non avviene mai.
A meno di non avere un sito sorgente veramente semplice e con pochissimi moduli contrib, sarà sempre necessario scrivere delle migrazioni custom.

Oltre al processo di migrazione dei dati, sarà necessario anche:

  • ricreare il tema (con l’introduzione di twig i vecchi temi non possono essere utilizzati)
  • ricreare le views (anche se il modulo contrib Views Migration potrebbe velocizzare quest’operazione)
  • fare il porting dei moduli e delle logiche custom

Quanto effort sarà necessario?

Dipende.

Anche se la risposta “dipende” può sembrare evasiva, in realtà “dipende” veramente da molti fattori!
Il più semplice ovviamente è la complessità del sito “sorgente”, ma anche le scelte relative al sito di “destinazione” influiranno sull’approccio da seguire e, quindi, sull’effort necessario.

La migrazione di un qualsiasi sito, da un sistema ad un altro, preservando l’integrità del dato, è un processo complesso che difficilmente si può tradurre in una “tabellina” coprendo tutte le casistiche.

In quest’articolo non ho intenzione di avventurarmi in una tale impresa ma, parlando semplicemente della migrazione del dato e tralasciando quindi il theming e il porting dei moduli e delle logiche custom, questi due articoli potrebbero interessarvi:

anche se scritti bene, nessuno dei due articoli, per forza di cose, riesce a coprire tutte le variabili in gioco.

Quali sono le variabili in gioco?

Se avete letto gli articoli citati poco sopra, vi sarete già resi conto che la migrazione da Drupal 7 a Drupal 8/9 richiede una buona pianificazione e, per quantificarne l’effort, sarà necessario avere un’idea abbastanza chiara della complessità del sito sorgente.

Parliamo di complessità, e non di numero di contenuti, perché l’effort necessario per lo sviluppo di una migrazione non è influenzato dal numero di contenuti presenti.

Ovviamente il numero di contenuti presenti aumenterà il tempo di esecuzione della migrazione (anche durante lo sviluppo), ma sono tempi in cui lavorerà la “macchina” e non lo sviluppatore.

La complessità del sito sorgente è data sicuramente dal:

  • numero di entità “standard” coinvolte (nodi, tassonomie) e dalla tipologia dei field che le compongono (standard/custom)
  • numero di views presenti (*)
  • numero di lingue
  • numero di entità “custom”
  • numero di file type

la lista non è sicuramente esaustiva perché il sito sorgente potrebbe:

  • utilizzare i gruppi (OG), i paragraphs, le field collection
  • avere dei workflow editoriali
  • utilizzare concetti di “country” (quindi non soltanto multi-lingua, ma anche multi-country)
  • fare uso delle revisioni
  • popolare contenuti da fonti esterne (ad es. utilizzando il modulo feeds) (*)
  • esporre contenuti tramite servizi (*)
  • utilizzare moduli contrib non presenti per Drupal 9

(*) non influiscono sulla migrazione del dato, ma sono comunque (funzionalità) da ricreare nella nuova istanza di Drupal 9

L’effort necessario dipenderà anche dall’esistenza o meno degli “upgrade path” nei moduli contrib utilizzati, dalla necessità di gestire o meno i redirect e, non dimentichiamocelo, dalle scelte che si faranno relative al sito di destinazione.

Già… il sito di destinazione.

Spesso si tende ad approfittare della migrazione per apportare modifiche alla struttura del sito, al “model” dei contenuti, alla home page e ad altre piccole cose che sembrano “ininfluenti”, ma che potrebbero complicare (di molto) il processo di migrazione del dato.

Prima di ampliare il discorso relativo al sito di destinazione, un piccolo consiglio: lasciatevi aiutare dal modulo Migrate Upgrade.

Esiste un modulo per velocizzare le lavorazioni?

Come accennato all’inizio dell’articolo, il modulo Migrate Upgrade risulta essere “strategico” per facilitare e velocizzare l’implementazione delle migrazioni da Drupal 7 a Drupal 9.

Il modulo mette a disposizione due nuovi comandi per Drush:

  • migrate-upgrade esegue un’importazione automatica delle configurazioni e dei contenuti dal database sorgente al sito di destinazione (sfruttando gli upgrade path presenti).
  • migrate-upgrade-rollback rimuove i contenuti e le configurazioni (non tutte) importate precedentemente con il comando migrate-upgrade.

Anche se le premesse sono buone, questo non significa che basta lanciare il comando migrate-upgrade su un’istanza pulita di Drupal 9 per effettuare una migrazione corretta dal sito sorgente al sito di destinazione (a meno di non avere un sito sorgente veramente semplice).

Nella quasi totalità dei casi sarà necessario apportare delle modifiche/integrazioni alle migrazioni effettuate tramite gli upgrade path e, lanciando semplicemente il comando migrate-upgrade, questo non è possibile.

Fortunatamente il comando migrate-upgrade mette a disposizione il parametro --configure-only che genera le configurazioni delle migrazioni senza eseguirle. Questo ci permette di esportarle e di personalizzarle.

Per l’utilizzo del modulo Migrate Upgrade rimando alla pagina Upgrade using Drush e al README del progetto.

Nel README è presente un ipotetico flusso di lavoro con 8 punti da seguire.

Nel punto 1, secondo me, non risalta abbastanza l’importanza di installare e abilitare i moduli per i quali si desidera migrare i dati.

È importante installare ed abilitare (senza ulteriori configurazioni) tutti i moduli contrib che erano presenti sul sito sorgente e che saranno necessari sul sito di destinazione perché, se siete fortunati, qualche modulo contrib potrebbe aver implementato gli upgrade path e il comando migrate-upgrade, utilizzandoli, vi esporterà migrazioni aggiuntive e/o più complete.

Per quanto riguarda il punto 5, vi consiglio di copiare le configurazioni delle migrazioni generate da migrate-upgrade dentro la directory:

my_module/artifacts/migration_template

questo eviterà di importare, indistintamente, tutte le configurazioni delle migrazioni all’abilitazione del modulo my_module (punto 8 del README).

Le configurazioni delle migrazioni generate da
migrate-upgrade --configure-only possono essere divise in due gruppi:

  • migrazioni di configurazioni (nell’array migration_tags riportano la voce - Configuration)
  • migrazioni di contenuti (nell’array migration_tags riportano la voce
    - Content)

il mio consiglio è quello di gestire i due gruppi in modo differente.

Migrazioni di configurazioni

Queste migrazioni possono essere spostate “in bulk” dentro la directory my_module/config/install.

Sono migrazioni che verranno lanciate soltanto una volta perché generano “configurazioni alla Drupal”.

Un ipotetico flusso di lavoro potrebbe essere questo:

  1. spostare tutte le configurazioni delle migrazioni “taggate” con
    - Configuration dentro la directory my_module/config/install
  2. abilitare il modulo my_module
  3. lanciare una migrazione completa tramite drush mim --all (dando per scontato che stiamo lavorando su un’istanza pulita di Drupal 9)
  4. esportare le configurazioni tramite un drush cex
  5. fare un commit sul repository con i nuovi file esportati

arrivati a questo punto, dovreste ritrovarvi con un sito dove è stato fatto “automaticamente” il building di content type, media type, tassonomie, ruoli, impostazioni di sistema (come nome sito, email sito, template email per gli utenti), etc…

Migrazioni di contenuti

A differenza di quanto detto in precedenza, per ciò che riguarda le migrazioni di contenuto, ritengo sia preferibile gestirle singolarmente.

Un ipotetico flusso di lavoro potrebbe essere questo:

  1. decidere quale migrazione si vuole importare/modificare
  2. spostarla dalla directory my_module/artifacts/migration_template alla directory my_module/config/install
  3. apportare le modifiche (se necessarie)
  4. importare, tramite i comandi drush messi a disposizione da Config Devel, la configurazione modificata
  5. eseguire la migrazione appena importata
  6. controllare che la migrazione abbia importato correttamente i dati
  7. ripartire dal punto 1

Utilizzare la directory my_module/artifacts/migration_template vi permette di fare “cherry pick” delle migrazioni in modo da avere maggior controllo su cosa si andrà a migrare e cosa si è già migrato, permettendovi di poter scegliere la giusta strategia in base alle scelte fatte per il sito di destinazione.

In che modo le scelte fatte sul sito di destinazione influiranno sulla migrazione?

I modi per “complicarsi la vita” sono infiniti, ma cercherò di fare un paio di esempi per capire il concetto.

Esempio 1

Supponiamo di avere un sito sorgente in cui tutti i machine-name dei fields, dei content type e, in generale, delle entity type siano state scritte in italiano.

Buon senso (e best practices) richiederebbero una riscrittura dei machine-name in lingua inglese, ma questo comporterebbe il totale rifacimento del building, senza poter sfruttare l’automatismo messo a disposizione dalla migrazione delle configurazioni descritto poco sopra.

Oltre al tempo necessario per il building, dovrà essere tenuto in considerazione anche il tempo necessario per modificare il mapping dei fields presenti nelle migrazioni dei contenuti.

In base alla complessità del sito, questo potrebbe voler dire settimane di lavoro aggiuntivo, ma non sempre il budget a disposizione permette di effettuare questo tipo di cambiamenti.

Se questa è un’operazione che prima o poi dovrà essere fatta, ovviamente sarebbe meglio farla in questa occasione.

Se invece mantenere i machine-name in italiano non è un problema: potrebbe non valerne la pena.

Esempio 2

Supponiamo di voler approfittare dell’occasione per fare il rifacimento della homepage mostrando nuovi contenuti non presenti sul sito sorgente… che siano delle semplici immagini o dei contenuti veri e propri.

Oppure supponiamo di voler introdurre una nuova tassonomia con nuovi termini tassonomici per “decorare” contenuti esistenti o sfruttare le pagine tassonomiche per creare nuove sezioni.

Queste operazioni, apparentemente innocue e gestibili semplicemente tramite delle fixtures, nascondono dei side-effects che potrebbero variare di molto l’effort necessario per il processo di migrazione.

Nella documentazione ufficiale Preparing a site for upgrade to Drupal 9 c’è un paragrafo che riporto di seguito:

Do not create content on the Drupal site

The upgrade process maintains the unique identifiers from the source site. For example, if a user account had the unique ID 2 on the source site (thus was at the relative URI /user/2), after upgrade the same user account will be at /user/2 on the new site. If you were to create a user account on the new site beyond the default administrator account, it would be assigned user ID 2 — then, when running the upgrade process, the account from the source site with user ID 2 would overwrite it. This applies to user accounts, taxonomy terms, and node content, as well as pretty much any other kind of content with numeric IDs from your source site.

To avoid data loss, do not manually create anything on the Drupal site until all your source content has been fully imported.

come “caldamente consigliato” dalla documentazione ufficiale, sarebbe meglio non creare alcun contenuto “gestito” tramite ID numerici nel db fino a quando il sito sorgente non è stato completamente importato.

L’ultima parte potrebbe trarre in inganno… considerando che per la messa in produzione del nuovo sito si dovranno lanciare nuovamente le migrazioni in modo da importare anche gli ultimi contenuti creati, la frase corretta sarebbe dovuta essere quella di non creare nessun contenuto (non presente sul db sorgente) fino al rilascio in produzione.

Oltre al rischio di perdere dei dati, si può incorrere in problemi di conflitti (sugli ID) durante il processo finale di migrazione… bloccando di fatto la migrazione e il rilascio in produzione.

Ci sono vari modi di “aggirare” questo problema.

Il più semplice è quello di creare i contenuti sul sito sorgente, in modo da migrarli insieme agli altri contenuti.

Un altro potrebbe essere quello di “barare” e creare delle fixtures che inseriscano i nuovi contenuti negli ID rimasti vuoti a causa dell’eliminazione di vecchi contenuti. Se i contenuti da inserire non sono molti, potrebbe essere una strada percorribile, ma comunque richiedono dell’effort aggiuntivo e un’attenzione “maniacale”.

Un’altra strada potrebbe essere quella di sviluppare le migrazioni non mantenendo gli ID del sito sorgente, sfruttando i migration_lookup. Anche se questa è una strada percorribile, il non mantenimento degli ID comporterà molte lavorazioni aggiuntive che nell’altro caso non sarebbero necessarie.

Quali sono i vantaggi di mantenere gli ID del sito sorgente?

I vantaggi sono molti, ma di seguito ne elencherò soltanto alcuni:

  • i “template” estratti da migration-upgrade, nella maggior parte dei casi, già funzionano in questo modo, quindi non sarà necessario fare modifiche (a quella parte)
  • non sarà necessario gestire le dipendenze tra migrazioni. Importando direttamente gli id, non utilizzeremo i migration_lookup, quindi a mano a mano che importiamo contenuti, le referenze si risolveranno da sole. (In alcuni casi sarà necessario aggiungere il no-stub: true per evitare che sia la migrazione a creare nuovi contenuti e ad occupare ID che potrebbero, successivamente, darci dei conflitti)
  • non utilizzando i migration_lookup, le migrazioni saranno più veloci
  • il building delle viste sarà più semplice.
    Alcune viste, ad esempio quelle che filtrano per un termine tassonomico, utilizzano gli ID del termine tassonomico. Se manteniamo gli ID, le viste funzioneranno sempre, mentre se non manteniamo gli ID, sarà necessario implementare le viste in modo differente (ad esempio introducendo i machine-name anche per i termini tassonomici) o andando a modificare le viste una volta in produzione (o ad ogni rilascio su un qualsiasi ambiente in cui girano le migrazioni, perché gli ID possono variare da migrazione a migrazione)
  • non sarà necessario gestire i link interni inseriti nei campi di testo (ad es. quelli inseriti tramite il modulo Linkit). Se un contenuto ha, nel suo body, un link al contenuto /node/12, quel link, mantenendo gli ID, continuerà ad essere corretto
  • la gestione/migrazione dei redirect sarà più semplice (anche se dovesse cambiare l’alias)

Come abbiamo visto, per non avere il problema di perdita del dato e/o di conflitti, non si dovrebbero inserire nuovi contenuti manualmente, ma questa è un operazione necessaria per testare l’esperienza utente e le varie funzionalità migrate/realizzate.

In questi casi vanno gestiti i rilasci sui vari ambienti di develop/test in modo che vengano creati partendo da un database di “seed” pulito… dove per “pulito” si intende un database aggiornato soltanto da migrazioni automatiche. In questo caso le modifiche fatte per testare le varie funzionalità verranno “eliminate” ad ogni rilascio.

Tutto qui?

No, in realtà no…

Ci sono casi in cui, anche non inserendo dei contenuti, si possono avere dei conflitti… e questi casi vanno gestiti.

Field Collection

Il modulo Field Collection per Drupal 9 non esiste. Questo tipo di entità deve essere gestito tramite il modulo Paragraphs.

Se il sito sorgente utilizza sia le Field Collection che i Paragraphs, allora si possono avere dei conflitti dovuti alla migrazione delle Field Collection nei Paragraphs.

In questo caso vi consiglio di estendere il plugin sorgente d7_field_collection_item ed aggiungere un offset sia all’item_id che al revision_id, in modo che, una volta importati, non possano dare noia agli id e alle revision_id dei paragraphs. Un valore “sicuro” da poter utilizzare come offset, può essere trovato soltanto guardando gli ID presenti nel sito sorgente, calcolando anche quelli che potrebbero venire creati prima della messa in produzione del nuovo sito.

Riassumendo

Quanto effort è necessario per migrare un sito da Drupal 7 a Drupal 9?

Dipende.

Dipende dalla complessità del sito sorgente e dalle scelte effettuate relative al sito di “destinazione”.

Nella maggior parte dei casi converrà aggiungere nuove funzionalità e nuovi contenuti dopo la messa in produzione del sito in Drupal 9, altre volte sarà possibile aggirare le criticità con dei piccoli “trucchi”.

Prima di concludere ritorno su un concetto presente nella parte alta dell’articolo:

La migrazione di un qualsiasi sito, da un sistema ad un altro, preservando l’integrità del dato, è un processo complesso

che voi siate il cliente o il fornitore, ricordate che l’importante è preservare l’integrità del dato!

Buona migrazione.

--

--