In dit artikel gaan we kijken naar een recente toegevoegde feature in Bamboo. Bamboo is een CD tool van Atlassian. In de zomer van 2018 is de Specs functionaliteit toegevoegd. Dit houdt in dat je (bijna) alles wat je in de GUI kan definiëren ook in code kan definiëren. Dit is in de basis vergelijkbaar met Jenkins pipelines die je in Groovy schrijft.

Wat Bamboo Specs (hierna Specs genoemd) onderscheidt, is dat je de Specs in Java of ieder andere JVM taal kunt schrijven, zoals bijvoorbeeld Kotlin, Groovy of Scala. Daarnaast kun je Specs ook in Yaml definiëren, net zoals in Gitlab CI of Travis CI. De Yaml Specs behandel ik in dit artikel kort, omdat deze variant niet herbruikbaar is, zoals de Java variant. Met herbruikbaar wordt hier bedoeld dat je in staat bent om CD definities te hergebruiken voor verschillende projecten. Zo hoef je in de optimale situatie alleen project specifieke details op te geven wanneer je een nieuw project start. In de praktijk ‘copy pasten’ we vaak een project om daarna deze te tweaken voor het nieuwe project. Dit hoeft niet als je gebruik maakt van Bamboo Specs. Ook komt beheerbaarheid goed van pas als je project overstijgende aanpassingen moet doen, daar wil je liever ook niet tientallen of honderden CD definities met de hand aanpassen. Om van Bamboo specs gebruik te maken, heb je Bamboo 6.0.0 of hoger nodig.

Na wat Bamboo terminologie gaan we kort de Yaml versie beschrijven en de verschillen met de Java variant. Daarna gaan we een, voor een enterprise scenario, mogelijke aanpak behandelen. Als laatste behandel ik een aantal haken en ogen waar je rekening mee dient te houden als je Bamboo Specs wilt gebruiken.

Bamboo terminologie

Bamboo heeft een CD specifiek domein. Alles start binnen Bamboo met een Project. Een project heeft één of meerdere plans en dient ook als centraal dashboard voor de plans die het bevat.

Plan’s bevatten Stages, Jobs en Tasks en maken doorgaans gebruik van een Repository. Daarnaast kan een Plan ook één of meerdere Artifacts opleveren. Een Stage is een container die één of meerdere Jobs bevat. Jobs worden parallel uitgevoerd, desgewenst op meerdere Bamboo agents. Jobs bevatten Tasks. Tasks worden sequentieel uitgevoerd in de volgorde zoals deze in de Job gedefinieerd staan.

Een Repository, zoals de naam doet vermoeden, bevat repository metadata die noodzakelijk is om hiermee te verbinden. Een Artifact is een optionele output definitie waarbij je aan kan geven wat je van de Plan bewaard wilt hebben zodat deze beschikbaar wordt voor een andere Plan. Een simpel voorbeeld zou kunnen zijn dat je de Jar uit de target folder als Artifact definieert, zodat je deze weer gebruikt in een Deployment Project.

Deployment projects maken onder andere gebruik van Artifacts en Environments en definiëren Deployments in de breedste zin. Environments definiëren één of meerdere servers die logisch bij elkaar horen. Naast deze Bamboo domeinobjecten zijn er nog een aantal andere domeinobjecten waarbij je onder andere variabelen, triggers en permissies kunt instellen. Deze kun je in de documentatie terugvinden. In afbeelding 1 zie je een grafische weergave van het Bamboo core domein.

Afbeelding 1

 

Yaml

Om te beginnen met Specs gaan we een simpel Maven project definiëren in Yaml waarbij we mvn package willen uitvoeren en de resulterende Jar als Artifact beschikbaar willen stellen. Hiervoor hebben we nodig:

  • een Project;
  • een Repository;
  • een Stage;
  • een Job;
  • een aantal Tasks;
  • een Artifact.

Listing 1

 

Listing 2

 

In listing 1 zie je hoe dit is gedefinieerd in Yaml formaat. De Java variant van ditzelfde scenario vind je in listing 2. Zoals je in beide listings kunt zien, is het wanneer je het Bamboo domein beheerst erg eenvoudig om dit project te definiëren, zowel in Yaml als  in Java. Helaas zal je opgevallen zijn dat de Tasks altijd van het type ‘scripts’ zijn in de Yaml variant. Bijna alle voordelen vallen weg als je gebruik maakt van Yaml. Je heb geen type safety, geen overerving, geen mogelijkheid tot testen. Ook is niet het hele Bamboo domein te definiëren in Yaml, maar een kleine subset daarvan. Uit de documentatie en research op onder andere Stackoverflow en de Atlassian support forums zie je dat Atlassian je verwijst naar de Java variant wanneer je iets niet voor elkaar krijgt in de Yaml variant.

Java variant

In de Java variant hebben we wel dit simpele scenario volledig kunnen definiëren en daarnaast kan de definitie hergebruikt worden (uiteraard niet zoals in listing 2, alles zit voor leesbaarheid in de main methode) en kunnen we dit ook testen voordat we de definitie uploaden naar de Bamboo server. We hebben zelfs plan branch management. In Bamboo maakt een plan standaard gebruik van de default branch. Maar je kun ook plan branch management inschakelen. Hiermee koppelt Bamboo je plan aan iedere branch in de repository. Natuurlijk kun je dit ook niet gebruiken of het automatisch aanmaken van de branch plans aan je wensen aanpassen. Het grote voordeel wat we hier zien, is dat een plan universeel te gebruiken is, branch onafhankelijk.

De documentatie van de Yaml en Java Specs zijn redelijk gedocumenteerd. Naast de referentie documentatie heb je voor de Java variant ook nog de Javadocs.

Wat we weggelaten hebben in de Java variant, is de Maven configuratie. Bamboo biedt hier een Archetype die je helpt om snel een CD project op te zetten. Doordat het een Maven project betreft, kan je ook zelf dependencies toevoegen en kun je de definities ook geautomatiseerd testen. Ook kun je libraries ontwikkelen die project overstijgend zijn en hergebruiken in projecten.

Met de Java variant is het dus mogelijk om herbruikbaarheid en de beheersbaarheid te promoten. Zo zou je dus met Java alleen al shared libraries kunnen ontwikkelen met project overstijgende defaults. Mogelijke Specs domein objecten zouden kunnen zijn:

  • environment;
  • environmentPermission;
  • plan;
  • planpermission;
  • variable.

Permisson en Variable

Eerst een korte uitleg over Permission en Variable. Deze hebben we immers nog niet behandeld. De permissions stellen je in staat om toegang en gebruik te beperken tot gebruikers en groepen. Met de Variable kun je waardes delen binnen Bamboo. Variables kunnen hebben een scope, zo kun je variabelen op systeem, Bamboo server en planniveau definiëren. De systeem scope definieer je niet zelf, maar zijn een alias die je automatisch kunt gebruiken. Bijvoorbeeld als je een systeemvariabele genaamd MYVAR hebt, dan kun je deze in Bamboo gebruiken met de alias ‘system.MYVAR’.

Met Environment objecten zou je definities kunnen opstellen voor Systeem, Acceptatie en Productie omgevingen. Voor toegang zou je deze kunnen complementeren met Environment permissies.

Plans en Planpermissions

Hetzelfde geldt ook voor Plans en Planpermissions. Naast het Java hergebruik, bieden de Specs ook nog het concept van Parent Plans. Met deze constructie kun je (abstracte) Plans definiëren waar Child plans van overerven. Zo zou je dus omgevingsbrede plans kunnen definiëren waar de omgevingsafhankelijke definities zijn opgenomen waarbij in Child plans de projectdefinities zijn opgenomen. Dit is heel krachtig en levert direct twee grote voordelen op. Enerzijds het sneller opzetten van Plans en anderzijds een betere beheerbaarheid van alle plans, doordat omgevingswijzigingen nu op Parent plans kunnen worden toegepast en beschikbaar zijn voor de Child plans zonder deze aan te passen. Let op, hier zitten een paar haken en ogen aan, dit behandel ik verderop in het artikel.

Optimaal gebruik

Wil je optimaal gebruik maken van overerving en hergebruik, dan zal je initieel tijd moeten investeren in het modelleren van de omgeving, systemen en rollen die gelden binnen de organisatie. Daarna zou je de defaults die in elk project terugkomen, kunnen modelleren in Parent plans. Deze definities zou je in een Maven library kwijt kunnen waar elk project gebruik van zou kunnen maken als basis en daarnaast de parent plans publiceren op de Bamboo server. Een tip is dat -als je al gebruik maakt van Bamboo- je bestaande definities die je in de GUI gemaakt hebt in Java Specs kan zien. Hiervoor heb je een optie ‘View as Specs’. Deze functie genereert Java code voor het huidige project die dan als basis kan dienen. Ik heb deze functie ook gebruikt om ingewikkelde builds eerst in de GUI te definiëren, zodat ik Java code als basis had die ik dan verder alleen nog hoefde te tweaken.

Zoals je ziet, zijn grote voordelen te behalen om jouw CD omgeving door middel van Specs te modelleren. Ik heb niet alle domein objecten behandeld in dit artikel. Er bestaan nog veel meer! Denk hierbij aan o.a. het definiëren van triggers, afhankelijkheden en Utilities. De utilities zijn Specs helper klassen die hulpmiddelen bieden voor bijvoorbeeld het publiceren van Specs naar een Bamboo server en het omgaan met credentials.

Haken en ogen

Wel is het zo dat naast de voordelen ook een aantal haken en ogen bestaan waar je rekening mee dient te houden (op het moment van schrijven). Het eerste is dat de verantwoordelijken voor CD Java moeten beheersen. Voor ons Javanen natuurlijk geen probleem, maar hier dien je wel organisatorisch naar te kijken. Risico is dat er door manco aan goede basis Java kennis, voordelen wellicht niet behaald worden in termen van herbruikbaarheid en beheerbaarheid.

Wanneer je externe dependenties gebruikt, dan worden deze niet gebruikt op de server. De Bamboo server gebruikt zijn eigen pom wat betekent dat je toegevoegde dependencies niet gevonden worden. Hiervoor is een niet al te elegante workaround voor, namelijk de pom op de server aanpassen. Een andere verrassing die je tegen zal komen, is dat wanneer een parent Plan aangepast is de Child plans niet automatisch opnieuw gepubliceerd worden. De wijzigingen worden dus ook niet toegepast op de bestaande Childs! Ook hiervoor is een oplossing in de vorm van een community plug-in die dit wel in de gaten houdt en Child plans bijwerkt na een update van de Parent plan. Hoewel de documentatie wel aanwezig is op Object niveau, mis je documentatie om Specs effectief te gebruiken voor gehele CD flows. Vooral in het begin kost dit even tijd door middel van trial en error. Op dit vlak zou de documentatie veel beter kunnen.

Conclusie

Samenvattend hebben we een introductie gegeven over Bamboo Specs. Na een uitleg van de core Bamboo objecten hebben een voorbeeld behandeld van een Yaml en Java variant van Specs waarbij de nadelen van de Yaml varianten zichtbaar werden. Het kunnen gebruiken van Java biedt ons het voordeel van testbaarheid, hergebruik en beheerbaarheid. Ook hebben we een generieke aanpak besproken om efficiënt Specs te implementeren. Toen ik enkele maanden geleden in Bamboo Specs dook was het lastigste om het Bamboo domein te leren kennen. Als je voor jouw omgeving Specs zou willen gebruiken, dan lijkt de beste combinatie te bestaan uit iemand met veel Bamboo GUI ervaring gecombineerd met een Java developer. Geen probleem in een DevOps team lijkt mij. Wel is het goed om te kijken naar de complexiteit en grootte van de omgeving(en) en projecten. Als jouw team alleen in een geïsoleerde simpele omgeving bezig is en straight forward projecten bouwt, dan is Bamboo Specs mogelijk overkill.

Tot slot

Ik hoop je inzicht te hebben gegeven over de mogelijkheden van Bamboo Specs, wat het inhoud en welke mogelijkheden het biedt. Als laatste wil ik je nog meegeven dat een publieke Docker image bestaat met een Bamboo server waarbij je met Specs kunt spelen. De image naam is cptactionhank/atlassian-bamboo. Laat je niet afschrikken door het license scherm dat je ziet,. Een trial license van 90 dagen kun je eenvoudig aanvragen met een Atlassian account. De volledige documentatie is te vinden op https://docs.atlassian.com/bamboo-specs-docs/6.7.2/.

Vooral in het begin kost Specs even tijd door middel van trial en error.

De beste combinatie om Specs te leren, is door iemand met veel Bamboo GUI ervaring samen te voegen met een Java developer.