Norbert Eder: Bootstrap 4: Ersatz für die Glyphicons

Mit Version 4 wurde in Bootstrap ordentlich aufgeräumt. Unter anderem werden die Glyphicons nicht mehr mitgeliefert. Diese müssen nun ab sofort manuell eingebunden werden. Als Alternative bieten sich auch andere Icon Fonts an.

Weit verbreitet und auch von mir immer wieder gerne benutzt ist Font Awesome. Sehr cool an Font Awesome ist:

Font Awesome is fully open source and is GPL friendly. You can use it for commercial projects, open source projects, or really just about whatever you want.

Auch eine Nennung ist nicht notwendig – ist aber nur fair.

Ich verwende Bootstrap nun zusammen mit Angular. Damit Font Awesome genutzt werden kann, sind diese zwei Abhängigkeiten im package.json einzutragen:

"font-awesome": "^4.7.0",
"angular-font-awesome": "^3.0.3"

Nach der Installation der der Pakete via npm install muss das Angular-Modul bekannt gemacht werden. Für die nachfolgende Variante muss Angular-CLI verwendet werden.

import { AngularFontAwesomeModule } from 'angular-font-awesome';

@NgModule({
  ...
  imports: [
    ...
    AngularFontAwesomeModule,
    ...
  ]
})

In der Datei angular-cli.json ist nun noch das Style-Sheet einzutragen:

"styles": [
  ...
  "../node_modules/font-awesome/css/font-awesome.min.css"
]

Nun noch ng serve neu starten und schon kann Font-Awesome verwendet werden.

Wer Bootstrap auf Version 4 migrieren möchte, bekommt hier ausführliche Informationen. Für ausführliche Informationen zu angular-font-awesome empfehle ich einen Blick ins README.

Happy Coding!

The post Bootstrap 4: Ersatz für die Glyphicons appeared first on Norbert Eder.

AIT: Letzter Beitrag im alten Gewand

Liebe Leserschaft,

im Rahmen der Erneuerung unserer Firmenwebseite www.aitgmbh.de wurde unser Blog www.tfsblog.de in die neue Webseite integriert:

Dies hat zur Folge, dass der bestehende RSS Feed nicht mehr weitergepflegt wird.

Im neuen Blog gibt es jedoch wieder die Möglichkeit verschiedenen Themenschwerpunkte zu abonnieren:

Weiter haben wir die bestehenden Userdaten (z.B. zum Download unserer kostenfreien TFS Tools oder unserer Fachartikel) aufgrund der geänderten Datenschutzbestimmungen nicht einfach für die neue Webseite übernommen. Wir bitten daher jeden Leser sich bei Bedarf einen neuen Account einmalig anzulegen.

Abschließend möchten wir uns für die langjährige Treue bei Ihnen bedanken und freuen uns auf viele weitere spannende Jahre.

Herzliche Grüße aus Stuttgart,

Das Team der AIT

Golo Roden: Einführung in React, Folge 4: Der Komponenten-Lebenszyklus

Komponenten in React durchlaufen einen komplexen Lebenszyklus, der es ermöglicht, das Verhalten einer Komponente zu verschiedenen Zeitpunkten detailliert zu steuern. Wie funktioniert das, und worauf gilt es dabei zu achten?

MSDN Team Blog AT [MS]: News von der österreichischen PowerShell Community

Auch wenn der Experts Live Country Event mit über 100 Besuchern den Großteil der Zeit in Anspruch nahm, so war doch auch am Powershell Blog einiges los:

Euer Team der PS Usergroup Austria

MSDN Team Blog AT [MS]: Docker Roadshow in Frankfurt & München

Einladung zur Docker MTA Roadshow Warum Sie traditionelle Applikationen modernisieren sollten.

IT-Organisationen geben weiterhin 80% ihres Budgets aus um ihre bestehenden Applikationen Aufrecht zu erhalten und nur 20% des Budgets für neue Innovationen. Gemeinsam zeigen Docker und HPE wie sie mit dem Programm „Modernisierung von traditionellen Applikationen“ dazu beitragen können, diese 80% zu eliminieren und Ihnen somit ermöglicht wird mehr auf Innovationen setzen zu können. Dieses schlüsselfertige Programm garantiert mehr als 50% Einsparungen bei den gesamten IT-Kosten und bietet gleichzeitig moderne Sicherheits-, Portabilitätseigenschaften und einen Weg zu Hybrid IT & DevOps.

Was können Sie erwarten?
·         Informative Sessions, Demos, praktische Tips und nützliche Tools - von den vertrauenswürdigsten Namen im Geschäft.

·         Gewinnen Sie Einblick in das MTA-Programm und wie Sie loslegen können.

·         Eauchen Sie in die ROI-Analyse ein und wie man einen Business Case macht.

Wer sollte teilnehmen?

IT-Operations - und IT-Infrastruktur-Manager, IT-Direktoren, CIOs und CTOs, die daran interessiert sind, zu verstehen, wie Docker dazu beitragen kann, ältere Anwendungen zu verwandeln und bestehende Anwendungen zu modernisieren.

Agenda

Vormittag

·         08:00 - 09:00 Breakfast & Networking

·         09:00 - 09:05 Welcome & Opening

·         09:05 - 09:35 What is Docker & Why MTA

·         09:35 - 09:50 Q&A

·         09:50 - 10:00 Break

·         10:00 - 12:00 Hands-On Demo - Specific MTA Use Case

·         12:00 - 13:00 Lunch & Networking

Nachmittag

·         13:00 - 13:30 Partner presentation

·         13:30 - 13:45 Partner presentation Q&A

·         13:45 - 14:15 How to measure and track progress during MTA

·         14:15 - 14:30 Break

·         14:30 - 16:00 Hands-On Demo - Expand & Growth

·         16:00 - 16:15 Day review

·         16:15 - 17:00 Q&A & Mingle

Docker Roadshow Frankfurt

Hier registrieren »

Datum: 28. November 2017 08:00 - 17:00
Tagungsort: Radisson Blu Hotel Franklinstraße 65, 60486 Frankfurt am Main

 

Docker Roadshow Munich

Hier registrieren »

Datum: 30. November 2017 08:00 - 17:00
Tagungsort: Le Méridien Bayerstraße 41, 80335 München

Stefan Henneken: IEC 61131-3: Unit-Tests

Unit-Tests sind ein unentbehrliches Hilfsmittel für jeden Programmierer, um die Funktionsfähigkeit seiner Software sicherzustellen. Programmfehler kosten Zeit und Geld, daher benötigt man eine automatisierte Lösung, um diesen Fehlern auf die Spur zu kommen – und zwar möglichst bevor die Software zum Einsatz kommt. Unit-Tests sollten überall dort eingesetzt werden, wo professionell Software entwickelt wird. Dieser Artikel soll einen schnellen Einstieg und ein Verständnis für den Nutzen der Unit-Tests ermöglichen.

Motivation

Häufig werden für das Testen von Funktionsblöcken separate Testprogramme geschrieben. In solch einem Testprogramm wird eine Instanz des gewünschten Funktionsblock angelegt und aufgerufen. Dabei werden die Ausgangsvariablen beobachtet und manuell auf Korrektheit geprüft. Stimmen diese nicht mit den erwarteten Werte überein, so wird der Funktionsblock solange angepasst, bis der Funktionsblock das gewünschte Verhalten aufweist.

Doch mit dem einmaligen Testen von Software ist es nicht getan. So führen Änderungen oder Erweiterungen an einem Programm immer wieder dazu, dass Funktionen oder Funktionsblöcke, die zuvor ausgetestet wurden und fehlerfrei funktionierten, plötzlich nicht mehr korrekt arbeiten. Auch kommt es vor, dass sich die Behebung von Programmfehlern auch auf andere Programmteile auswirkt und somit an anderen Stellen im Code zu Fehlfunktionen führen kann. Die zuvor ausgeführten und abgeschlossenen Tests müssen somit manuell wiederholt werden.

Ein mögliche Herangehensweise für eine Verbesserung dieser Arbeitsweise besteht darin, die Tests zu automatisieren. Dazu wird ein Test-Programm entwickelt, welches die Funktionalität des zu testenden Programms aufruft und die Rückgabewerte überprüft. Ein einmal geschriebenes Testprogramm bietet eine Reihe von Vorteilen:

– Die Tests sind automatisiert und mit gleichen Rahmenbedingung (Timings, ..)  somit jederzeit wiederholbar.

– Einmal geschriebene Tests bleiben auch für andere Mitglieder des Teams erhalten.

Unit-Tests

Ein Unit-Test prüft einen sehr kleinen und autarken Teil (Unit) einer Software. In der IEC 61131-3 ist dieses ein einzelner Funktionsblock oder eine Funktion. Bei jedem Test wird die zu testende Einheit (Funktionsblock, Methode oder Funktion) mit Testdaten (Parametern) aufgerufen und deren Reaktion auf diese Testdaten geprüft. Stimmt das gelieferte Ergebnis mit dem erwarteten Ergebnis überein, so gilt der Test als bestanden. Ein Test besteht im Allgemeinen aus einer ganzen Reihe von Testfällen, die nicht nur ein Soll-Ist-Paar prüft, sondern gleich mehrere.

Welche Test-Szenarien der Entwickler implementiert, bleibt ihm überlassen. Sinnvoll ist es aber mit Werten zu testen, die typischerweise auch bei deren Aufruf in der Praxis auftreten. Auch die Betrachtung von Grenzwerten (extrem große oder kleine Werte) oder besonderen Werten (Null-Zeiger, Leerstring), ist sinnvoll. Liefern all diese Testszenarien erwartungsgemäß die korrekten Werte, so kann der Entwickler davon ausgehen, dass seine Implementierung korrekt ist.

Ein positiver Nebeneffekt ist der, dass es dem Entwickler weniger Kopfschmerzen bereitet komplexe Änderungen an seinem Code vorzunehmen. Schließlich kann er nach derartigen Änderungen das System jederzeit überprüfen. Treten also nach einer solchen Änderung keine Fehler auf, so ist sie höchstwahrscheinlich geglückt.

Man darf dabei allerdings die Gefahr einer schlechten Implementierung der Tests nicht außer Acht lassen. Sind diese unzureichend oder gar falsch, liefern aber ein positives Ergebnis, so führt diese trügerische Sicherheit früher oder später zu großen Problemen.

Das Unit-Test Framework TcUnit

Unit-Test Frameworks bieten die notwendigen Funktionalitäten an, um Unit-Tests schnell und effektiv zu erstellen. Durch ergeben sich weitere Vorteile:

– Jeder aus dem Team kann die Tests schnell und einfach erweitern.

– Jeder ist in der Lage die Tests zu starten und das Ergebnis der Tests auf Korrektheit zu überprüfen.

Im Rahmen eines Projektes ist das Unit-Test Framework TcUnit entstanden. Genaugenommen handelt es sich um eine SPS-Bibliothek, welche Methoden zur Verifizierung von Variablen bereit hält (Assert-Methoden). War eine Überprüfung nicht erfolgreich, so wird eine Statusmeldung in das Ausgabefenster ausgegeben. Enthalten sind die Assert-Methoden in dem Funktionsblock FB_Assert.

Je Datentyp gibt es eine Methode, wobei der Aufbau immer ähnlich ist. Es gibt immer einen Parameter der den Istwert enthält und einen Parameter für den Sollwert. Stimmen beide überein, gibt die Methode TRUE zurück, ansonsten FALSE. Der Parameter sMessage gibt den Ausgabetext vor, der im Falle eines Fehlers ausgegeben wird. Dadurch lassen sich die Meldungen den einzelnen Testfällen zuordnen. Die Namen der Assert-Methoden beginnen immer mit AreEqual.

Hier als Beispiel die Methode um eine Variable vom Typ Integer auf Gültigkeit zu überprüfen.

Pic01

Manche Methode enthalten noch zusätzliche Parameter.

Pic02

Für alle Standarddatentypen (BOOL, BYTE, INT, WORD, STRING, TIME, …) sind entsprechende Assert-Methoden vorhanden. Aber auch einige spezielle Datentypen, wie z.B. AreEqualMEM zur Prüfung eines Speicherbereichs oder AreEqualGIUD, werden unterstützt.

Ein erstes Beispiel

Unit-Tests werden dazu verwendet einzelne Funktionsblöcke unabhängig von anderen Komponenten zu überprüfen. Diese Funktionsblöcke können sich in einer SPS-Bibliothek oder in einem SPS-Projekt befinden.

Für das erste Beispiel soll sich der zu testende FB in einem SPS-Projekt befinden. Es handelt sich hierbei um den Funktionsblock FB_Foo.

Pic03
Definiert die Zeit, die der Ausgang bOut gesetzt bleibt, falls keine weiteren positiven Flanken an bSwitch angelegt werden.

bSwitch Durch eine positive Flanke wird der Ausgang bOut auf TRUE gesetzt. Dieser bleibt für die Zeit tDuration aktiv. Ist der Ausgang schon gesetzt, so wird die Zeit tDuration neu gestartet.
bOff Der Ausgang bOut wird durch eine positive Flanke unmittelbar zurückgesetzt.
tDuration Definiert die Zeit, die der Ausgang bOut gesetzt bleibt, falls keine weiteren positiven Flanken an bSwitch angelegt werden.

Durch Unit-Tests soll bewiesen werden, dass sich der Funktionsblock FB_Foo wie erwartet verhält. Den Code zum Testen wird hierbei direkt in dem TwinCAT Projekt implementieren.

Projektaufbau

Um den Test-Code von der Applikation zu trennen, wird der Ordner TcUnit_Tests angelegt. In diesem Ordner wird der POU P_Unit_Tests abgelegt von dem aus die jeweiligen Testfälle aufgerufen werden.

Für jeden FB wird ein entsprechender Test-FB angelegt. Dieser hat den gleichen Namen plus den Postfix _Tests. Für unser Beispiel ergibt sich der Name FB_Foo_Tests.

Pic04

In P_Unit_Tests wird eine Instanz von FB_Foo_Tests angelegt und aufgerufen.

PROGRAM P_Unit_Tests
VAR
  fbFoo_Tests : FB_Foo_Tests;
END_VAR

fbFoo_Tests();

In FB_Foo_Tests befindet sich der gesamte Test-Code zur Überprüfung von FB_Foo. Hierzu werden in FB_Foo_Tests jeweils pro Testfall eine Instanz von FB_Foo angelegt. Diese werden mit unterschiedlichen Parametern aufgerufen und die Rückgabewerte werden mit Hilfe der Assert-Methoden validiert.

Die Abarbeitung der einzelnen Testfälle geschieht in einer Statemachine, die auch von der SPS-Bibliothek TcUnit verwaltet wird. Dadurch wird z.B. der Test automatisch beendet, sobald ein Fehler erkannt wurde.

Definition der Testfälle

Zuvor müssen die einzelnen Testfälle definiert werden. Jeder Testfall belegt in der Statemachine einen bestimmten Bereich.

Für die Benennung der einzelnen Testfälle haben sich einige Benennungsregeln bewährt, die helfen, den Test-Aufbau übersichtlicher zu gestalten.

Bei den Testfällen, die einen Eingang von FB_Foo prüfen sollen, setzt sich der Name zusammen aus: [Name des Eingangs]_[Testbedingung]_[erwartetes Verhalten]. Analog dazu werden Testfälle benannt, die Methoden von FB_Foo testen, also [Name der Methode]_[Testbedingung]_[erwartetes Verhalten].

Nach diesem Schema werden folgende Testfälle festgelegt:

Switch_RisingEdgeAndDuration1s_OutIsTrueFor1s

Testet, ob durch eine positive Flanke an bSwitch der Ausgang bOut für 1 s gesetzt wird, wenn tDuration auf t#1s gesetzt wurde.

Switch_RisingEdgeAndDuration1s_OutIsFalseAfter1100ms

Testet, ob durch eine positive Flanke an bSwitch der Ausgang bOut nach 1100 ms wieder FALSE wird, wenn tDuration auf t#1s gesetzt wurde.

Switch_RetriggerSwitch_OutKeepsTrue

Testet, ob durch eine erneute positive Flanke an bSwitch die Zeit tDuration neu gestartet wird.

Off_RisingEdgeAndOutIsTrue_OutIsFalse

Testet, ob durch eine positive Flanke an bOff der gesetzt Ausgang bOut auf FALSE geht.

Implementierung der Testfälle

Jeder Testfall belegt in der Statemachine mindestens einen Schritt. In diesem Beispiel wurde als Schrittweite zwischen den einzelnen Testfällen 16#0100 gewählt. Der 1. Testfall beginnt bei 16#0100, der zweite bei 16#0200, usw. In Schritt 16#0000 werden Initialisierungen durchgeführt werden, während der Schritt 16#FFFF vorhanden sein muss, da dieser von der Statemachine angesprungen wird, sobald eine Assert-Methode einen Fehler festgestellt hat. Läuft der Test fehlerfrei durch, so wird in 16#FF00 eine Meldung ausgegeben und der Unit-Test für FB_Foo ist beendet.

Das Pragma region ist hierbei sehr hilfreich, um die Navigation im Quellcode zu vereinfachen.

FUNCTION_BLOCK FB_Foo_Tests
VAR_INPUT
END_VAR
VAR_OUTPUT
  bError : BOOL;
  bDone : BOOL;
END_VAR
VAR
  Assert : FB_ASSERT('FB_Foo');
  fbFoo_0100 : FB_Foo;
  fbFoo_0200 : FB_Foo;
  fbFoo_0300 : FB_Foo;
  fbFoo_0400 : FB_Foo;
END_VAR

CASE Assert.State OF
{region 'start'}
16#0000:
  bError := FALSE;
  bDone := FALSE;
  Assert.State := 16#0100;
{endregion}

{region 'Switch_RisingEdgeAndDuration1s_OutIsTrueFor1s'}
16#0100:
  fbFoo_0100(...
  ...
  Assert.State := 16#0200;
{endregion}

{region 'Switch_RisingEdgeAndDuration1s_OutIsFalseAfter1100ms'}
16#0200:
  fbFoo_0200(...
  ...
  Assert.State := 16#0300;
{endregion}

{region 'Switch_RetriggerSwitch_OutKeepsTrue'}
16#0300:
  fbFoo_0300(...
  ...
  Assert.State := 16#0400;
{endregion}

{region 'Off_RisingEdgeAndOutIsTrue_OutIsFalse'}
16#0400:
  fbFoo_0400(...
  ...
  Assert.State := 16#FF00;
{endregion}

{region 'done'}
16#FF00:
  Assert.PrintPassed('Done');
  Assert.State := 16#FF10;

16#FF10:
  bDone := TRUE;

{endregion}

{region 'error'}
16#FFFF:
  bError := TRUE;
{endregion}

ELSE
  Assert.StateMachineError();
END_CASE

Für jeden Testfall gibt es eine separate Instanz von FB_Foo. Dadurch wird sichergestellt, dass jeder Testfall mit einer neu initialisierten Instanz von FB_Foo arbeitet. Eine gegenseitig Beeinflussung der Testfälle wird dadurch vermieden.

Im einfachsten Fall, besteht ein Testfall aus nur einen Schritt:

16#0100:
  fbFoo_0100(bSwitch := TRUE, tDuration := T#1S);
  Assert.AreEqualBOOL(TRUE, fbFoo_0100.bOut, 'Switch_RisingEdgeAndDuration1s_OutIsTrueFor1s');
  tonDelay(IN := TRUE, PT := T#900MS);
  IF (tonDelay.Q) THEN
    tonDelay(IN := FALSE);
    Assert.State := 16#0200;
  END_IF

Der zu testende Baustein wird für 900 ms aufgerufen. Während dieser Zeit muss bOut TRUE sein, da bSwitch auf TRUE gesetzt wurde und tDuration 1 s beträgt. Die Assert-Methode AreEqualBOOL prüft den Ausgang bOut. Hat dieser nicht den erwarteten Zustand, so wird eine Fehlermeldung ausgegeben. Nach 900 ms wird durch Setzen der Eigenschaft State von FB_Assert in den nächsten Testfall gewechselt

Ein Testfall kann auch aus mehreren Schritten bestehen:

16#0300:
  fbFoo_0300(bSwitch := TRUE, tDuration := T#500MS);
  Assert.AreEqualBOOL(TRUE, fbFoo_0300.bOut, 'Switch_RetriggerSwitch_OutKeepsTrue');
  tonDelay(IN := TRUE, PT := T#400MS);
  IF (tonDelay.Q) THEN
    tonDelay(IN := FALSE);
    fbFoo_0300(bSwitch := FALSE);
    Assert.State := 16#0310;
  END_IF

16#0310:
  fbFoo_0300(bSwitch := TRUE, tDuration := T#500MS);
  Assert.AreEqualBOOL(TRUE, fbFoo_0300.bOut, 'Switch_RetriggerSwitch_OutKeepsTrue');
  tonDelay(IN := TRUE, PT := T#400MS);
  IF (tonDelay.Q) THEN
    tonDelay(IN := FALSE);
    Assert.State := 16#0400;
  END_IF

Das Triggern von bSwitch wird in Zeile 7 und in Zeile 12 durchgeführt. In den Zeile 3 und 13 wird geprüft ob der Ausgang gesetzt bleibt.

Ausgabe der Meldungen

Nach Ausführung aller Testfälle für FB_Foo wird eine Meldung ausgegeben (Schritt 16#FF00).

Pic05

Sollte der Fall eintreten, dass eine Assert-Methode einen Fehler erkennt, so wird dieses ebenfalls als Meldung ausgegeben.

Pic06

Ist die Eigenschaft AbortAfterFail von FB_Assert auf TRUE gesetzt, so wird bei einem Fehler der Schritt 16#FFFF angesprungen und somit der Test beendet.

Die Assert-Methoden verhindert, dass in einem Schritt die gleiche Meldung mehrfach hintereinander ausgegeben wird. Die mehrfache Ausgabe der gleichen Meldung, z.B. in einer Schleife, wird somit unterdrückt. Durch Setzen der Eigenschaft MultipleLog auf TRUE wird dieser Filter deaktiviert und jede Meldung kommt zur Ausgabe.

Durch den oben gezeigten Aufbau sind die Unit-Tests klar von der eigentlichen Applikation getrennt. FB_Foo bleibt vollständig unverändert.

Diese TwinCAT-Solution wird gemeinsam mit der TwinCAT Solution für die SPS-Bibliothek in die Quellcodeverwaltung (wie z.B. TFS oder Git) abgelegt. Somit steht allen Team-Mitgliedern eines Projektes die Tests zur Verfügung. Durch das Unit-Test Framework können Tests auch von jedem erweitert und vorhandene Tests gestartet und einfach ausgewertet werden.

Auch wenn der Begriff Unit-Test Framework für die SPS-Bibliothek TcUnit etwas hochgegriffen ist, so zeigt sich doch das mit wenigen Hilfsmitteln automatisierte Tests auch mit der IEC 61131-3 möglich sind. Kommerzielle Unit-Test Framework gehen deutlich über das hinaus, was eine SPS-Bibliothek leisten kann. So enthalten diese entsprechende Dialoge um die Tests zu starten und das Ergebnis anzuzeigen. Auch werden häufig die Bereiche im Quellcode markiert, die von den einzelnen Testfällen durchlaufen wurden.

Bibliothek TcUnit (TwinCAT 3.1.4022) auf GitHub

Beispiel (TwinCAT 3.1.4022) auf GitHub

Tips

Die größte Hürde bei Unit-Tests ist häufig der innere Schweinehund. Ist dieser erst überwunden, schreiben sich die Unit-Tests fast von alleine. Die zweite Hürde stellt sich durch die Frage nach den zu testenden Teilen der Software. Es ist wenig sinnvoll, alles testen zu wollen. Vielmehr sollte man sich auf wesentliche Bereiche der Software konzentrieren und die Funktionsblöcke, welche die Basis der Anwendung ausmachen, gut testen.

Im Grunde gilt ein Unit-Test als einigermaßen qualitativ, wenn bei der Ausführung möglichst viele Zweige durchlaufen werden. Beim Schreiben der Unit-Tests sollten die Testfälle so gewählt werden, dass möglichst alle Zweige des Funktionsblocks durchlaufen werden.

Treten dann doch noch Fehler in der Praxis auf, so kann es von Vorteil sein, wenn für diesen Fehlerfall Tests geschrieben werden. Damit wird sichergestellt, dass ein Fehler, der einmal aufgetreten ist, nicht ein weiteres Mal auftritt.

Allein das zwei oder mehrere Funktionsblöcke korrekt arbeiten und dieses durch Unit-Tests bewiesen wird, bedeutet noch nicht, dass eine Anwendung diese Funktionsblöcke auch korrekt anwendet. Unit-Tests ersetzen somit in keinster Weise Integrations- und Akzeptanztests. Derartige Testmethoden validieren das Gesamtsystem und bewerten somit das große Ganze. Es ist auch unter Verwendung von Unit-Tests nötig, weiterhin das Gesamtwerk zu testen. Allerdings wird ein nicht unwesentlicher Teil potentieller Fehler schon im Vorfeld durch Unit-Tests ausgeschaltet, was im Endeffekt Aufwand für das Testen und somit Zeit und Geld spart.

Weitere Informationen

Während der Vorbereitung zu diesem Post, hat Jakob Sagatowski in seinem Blog AllTwinCAT den ersten Teil einer Artikel-Serie über Test driven development in TwinCAT veröffentlicht. Für alle die tiefer in das Thema einsteigen wollen, kann ich den Blog sehr empfehlen. Es ist erfreulich, dass auch andere SPS-Programmierer sich mit dem Testen ihrer Software auseinander setzen. Auch das Buch The Art of Unit Testing von Roy Osherove ist ein guter Einstieg in das Thema. Auch wenn das Buch nicht für die IEC 61131-3 geschrieben wurde, so enthält es doch einige interessante Ansätze, die sich ohne Probleme auch in der SPS umsetzen lassen.

Abschließend will ich mich noch bei meinen Kollegen Birger Evenburg und Nils Johannsen bedanken. Als Grundlage für diesen Post diente eine SPS-Bibliothek, die mir freundlicherweise von beiden zur Verfügung gestellt wurde.


Holger Schwichtenberg: .NET 4.7.1 erkennen

Mit dem Erscheinen von .NET Framework 4.7.1 am 19. Oktober 2017 ist eine neue .NET-Version hinzugekommen.

MSDN Team Blog AT [MS]: Einladung: Mobile Industry Solutions

AIT: Neu in TFS 2018: Neues für Build und Release Extensions

Extensions bieten die Möglichkeiten den TFS um weitere Funktionalität an vordefinierten Stellen, sogenannten Extension Points, zu erweitern. Im Build- und Releasemanagement gibt es hierfür einige Anwendungsfälle: zusätzliche Menüeinträge an Build- und Release Definitionen, eigene Tasks, zusätzliche Informationen in Build- und Release Zusammenfassungen (Build- und Release Summary), u.v.m.

In vorhergehenden Beiträgen unserer Blogserie “Neu in TFS 2018” wurden bereits einige spannende Neuerungen für das Build- und Releasemanagement für die neueste Major Version des TFS, wie z.B. Task Groups, beschrieben. Mit diesem Blogbeitrag möchten wir Ihnen nun die Neuigkeiten für Extension-Entwickler(innen) in diesem Bereich näherbringen sowie zwei Neuerungen für server-seitige Tasks im Release Management.

Build

Bereits seit Einführung des JSON-Buildsystems existieren Build Templates, welche häufig verwendete Tasks für bestimmte Szenarien wie z.B. das Bauen einer .NET Desktop Anwendung zusammenfassen. Diese können als Ausgangspunkt für Buildprozesse verwendet werden und z.B. durch Hinzufügen und Entfernen von Tasks für eigene Zwecke weiter angepasst werden.

Vor allem in größeren Firmen existieren oftmals standardisierte Abläufe, welche sich in mehreren Buildprozessen wiederspiegeln jedoch durch die vorgegebenen Build Templates nicht abgedeckt werden. Hierfür ist es hilfreich diese Abläufe mittels eigener Build Templates abbilden und zur Verfügung stellen zu können.  TFS 2018 bietet nun erstmals die Möglichkeit eigene Templates auch über VSTS Marketplace Erweiterungen (VSIX Dateien) zu verteilen. In den Erweiterungs-Metadaten ist hierzu ein neuer Extension Point ms.vss-build.template (vgl. Snippet 1)  eingeführt worden. Ein vollständiges Beispiel für solch eine Extension ist in GitHub zu finden.

{  "id": "AIT Build Template", 
   "type": "ms.vss-build.template", 
   "targets": [ "ms.vss-build.templates" ], 
   "properties": { "name": "AIT Build Template" } 
}

            Snippet 1: Auszug aus der Definition eines Custom Build Templates

Eine weitere Neuerung im Bereich der Build Erweiterungen ist die Möglichkeit eigens definierte Abschnitte in Build Zusammenfassungen ein- und auszublenden. Bisher wurden solche Abschnitte immer angezeigt, unabhängig davon ob die Tasks, welche die Informationen dafür zur Verfügung stellen, ausgeführt wurden oder nicht. Im letzteren Fall wurde also ggf. ein leerer Abschnitt in der Build Zusammenfassung angezeigt.

TFS 2018 stellt nun die neue Methode setSectionVisibility (vgl. Snippet 2) zur Verfügung. Diese kann im Quellcode einer Extension, welche den Abschnitt der Build Zusammenfassung definiert, verwendet werden um situationsabhängig die gewünschten Informationen und Abschnitte ein- und auszublenden. Für ein vollständiges Beispiel sei an dieser Stelle ebenfalls auf GitHub verwiesen.

VSS.getConfiguration().setSectionVisibility("$(publisherId).$(extensionId).$(sectionId)", true);

            Snippet 2: Einblenden von Custom Build Summary Sections

Release

Tasks in Release Definitionen können in verschiedenartigen Phasen ausgeführt werden. Eine Ausprägung davon ist die sogenannte Agentless Phase. Diese benötigt weder einen Agenten noch sonstige Zielmaschinen. Für Tasks, welche in solch einer Agentless Phase ausgeführt werden, sogenannte server-seitige Tasks, bringt TFS 2018 zwei Neuerungen:

Der neue Task Invoke REST API erlaubt es einen HTTP REST API-Aufruf aus dem Release heraus auszuführen (vgl. Abbildung 1). Hierzu ist es notwendig, im Vorhinein einen Generic Endpoint zu definieren, gegen welchen der Aufruf dann ausgeführt wird.

Der neue Task findet beispielsweise in folgendem Szenario Verwendung: Ein externer Dienst generiert anhand der ID eines Releases die zugehörigen Release Notes auf Basis der enthaltenen Work Items. Dieser Dienst kann mittels des Invoke Rest API-Tasks aus dem Release heraus ausgerufen werden und bis zur Fertigstellung der Release Notes gewartet werden.

Abbildung 1: Neuer server-seitiger Task Invoke REST API

Die zweite Neuerung bringt den Konfigurationsabschnitt Control Options nun auch für server-seitige Tasks. Die bereits bekannten Optionen Enabled, Continue on error, Always run sowie die Definition eines Timeouts steht damit nun auch für Tasks in Agentless Phasen zur Verfügung (vgl. Abbildung 2) und ermöglichen somit auch hier eine genauere Steuerung der Ausführung.

image

Abbildung 2: Control options

Build und Release

Eine Neuerung, welche sich sowohl im Build- als auch Releasemanagement wiederfindet, ist die Möglichkeit eigene Build Tasks als veraltet (Deprecated) zu kennzeichnen. Um Nutzern den Umstieg auf neuere Task-Versionen zu erleichtern, ist es empfehlenswert einen entsprechenden Hinweis in der Beschreibung der Tasks zu vermerken.

Um einen eigenen Task als veraltet zu markieren, muss das entsprechende Attribut in der Task Definition gesetzt werden:

"deprecated": true

Alle Deprecated Tasks werden im Task Katalog am Ende der Liste in einem eigenen Abschnitt Deprecated tasks zusammengefasst. Sowohl im Task Katalog als auch in Build- und Releasedefinition werden die Tasks zusätzlich als Deprecated gekennzeichnet (vgl. Abbildung 3).

image

Abbildung 3: Deprecated tasks im Task Katalog

Fazit

Auch im Bereich der Erweiterungen zeigt sich wieder einmal: das „neue alte“ Build- und Releasesystem wird erwachsen! Mit der Verteilung von eigenen Build Templates über VSTS- / TFS-Erweiterungen, der Möglichkeit eigene Tasks als veraltet zu markieren etc. geht Microsoft weitere Schritte um den Nutzern und Entwicklern von Erweiterungen das Leben leichter zu machen.

Bleiben Sie dran und begleiten Sie uns auch weiter bei der Entdeckung spannender Neuigkeiten in TFS 2018 in den Folgebeiträgen unserer Blogserie.

Holger Schwichtenberg: Neues Buch zu Windows PowerShell 5.1 und PowerShell Core 6.0

Die Neuauflage von Holger Schwichtenbergs Fachbuch zur PowerShell behandelt nun neben der Windows PowerShell auch die plattformunabhängige PowerShell Core.

Golo Roden: Einführung in React, Folge 3: Eingaben verarbeiten

Mit React Eingaben zu verarbeiten ist auf den ersten Blick gar nicht so einfach, denn React kennt zwei Arten von Komponenten, deren Zustandsverwaltung voneinander abweicht. Außerdem gilt es zu steuern, wie Events verteilt werden. Wie funktioniert das?

MSDN Team Blog AT [MS]: Herbst Update der österreichischen PowerShell Community

Hallo PowerShell Gemeinde!

Auch im letzten Monat war einiges los bei uns

Künftige Veranstaltungen

Vergangene Veranstaltungen

Wir hatten 2 sehr spannende und gut besuchte Veranstaltungen. Eine in Wien bei ETC und eine in Linz/Leondig bei Cubido.

Newsletter - die "Schnipseljagd"

Unsere wöchentlichen PowerShell Newsletter kamen regelmäßig raus und beinhalteten folgende Themen:

Hoffe es  war für dich etwas dabei!
Die PowerShell UserGroup Austria
www.powershell.co.at

Code-Inside Blog: Introducing Electron.NET - building Electron Desktop Apps with ASP.NET Core

x

The last couple of weeks I worked with my buddy Gregor Biswanger on a new project called Electron.NET.

As you might already guess: It is some sort of bridge between the well known Electron and .NET.

If you don’t know what Electron is: It helps to build desktop apps written in HTML/CSS/Javascript

The idea

Gregor asked me a while ago if it is possible to build desktop apps with ASP.NET Core (or .NET Core in general) and - indeed - there are some ideas how to make it, but unfortunatly there is no “official” UI stack available for .NET Core. After a little chat we agreed that the best bet would be to use Electron as is and somehow “embed” ASP.NET Core in it.

I went to bed, but Gregor was keen on to build a prototyp and he did it: He was able to launch the ASP.NET Core application inside the electron app and invoke some Electron APIs from the .NET World.

First steps done, yeah! In the following weeks Gregor was able to “bridge” most Electron APIs and I could help him with the tooling via our dotnet-extension.

Overview

The basic functionality is not too complex:

  • We ship a “standard” (more or less blank) Electron app
  • Inside the Electron part two free ports are searched:
    • The first free port is used inside the Electron app itself
    • The second free port is used for the ASP.NET Core process
  • The app launches the .NET Core process with ASP.NET Core port (e.g. localhost:8002) and injects the first port as parameter
  • Now we have a Socket.IO based linked between the launched ASP.NET Core app and the Electron app itself - this is our communication bridge!

At this point you can write your Standard ASP.NET Core Code and can communicate via our Electron.API wrapper to the Electron app.

Gregor did a fabulous blogpost with a great example.

Interested? This way!

If you are interested, maybe take a look at the ElectronNET-Org on GitHub. The complete code is OSS and there are two demo repositories.

No way - this is a stupid idea!

The last days were quite intersting. We got some nice comments about the project and (of course) there were some critics.

As far as I know the current “this is bad, because… “-list is like this:

  • We still need node.js and Electron.NET is just a wrapper around Electron: Yes, it is.
  • Perf will suck: Well… to be honest - the current startup time does really suck, because we not only launch the Electron stuff, but we also need to start the .NET Core based WebHost - maybe we will find a solution
  • Starting a web server inside the app is bad on multiple levels because of security and perf: I agree, there are some ideas how to fix it, but this might take some time.

There are lots of issues open and the project is pretty young, maybe we will find a solution for the above problems, maybe not.

Final thoughts

The interesting point for me is, that we seem to hit a nerf with this project: There is demand to write X-Plat desktop applications.

We are looking for feedback - please share your opinion on the ElectronNET-GitHub-Repo or try it out :)

Desktop is dead, long live the desktop!

Holger Schwichtenberg: Zeichen in Microsoft SQL Server ersetzen

Während man für mehrere Zeichenersetzungen bisher mehrere verschachtelte Aufrufe der Replace()-Funktion brauchte, geht es seit Microsoft SQL Server 2017 effizienter mit der neuen Translate()-Funktion.

Manfred Steyer: Generating Custom Code with the Angular CLI and Schematics

Since some versions, the Angular CLI uses a library called Schematics to scaffold building blocks like components or services. One of the best things about this is that Schematics allows to create own code generators too. Using this extension mechanism, we can modify the way the CLI generates code. But we can also provide custom collections with code generators and publish them as npm packages. A good example for this is Nrwl's Nx which allows to generated boilerplate code for Ngrx or upgrading an existing application from AngularJS 1.x to Angular.

These code generators are called Schematics and can not only create new files but also modify existing ones. For instance, the CLI uses the latter to register generated components with existing modules.

In this post, I'm showing how to create a collection with a custom Schematic from scratch and how to use it with an Angular project. The sources can be found here.

In addition to this, you'll find a nice video with Mike Brocchi from the CLI-Team explaining the basics and ideas behind Schematics here.

The public API of Schematics is currently experimental and can change in future.
Angular Labs

Goal

To demonstrate how to write a simple Schematic from scratch, I will build a code generator for a Bootstrap based side menu. With an respective template like the free ones at Creative Tim the result could look like this:

Solution

Before creating a generator it is a good idea to have an existing solution that contains the code you want to generate in all variations.

In our case, the component is quite simple:

import { Component, OnInit } from '@angular/core';

@Component({
    selector: 'menu',
    templateUrl: 'menu.component.html'
})
export class MenuComponent {
}

In addition to that, the template for this component is just a bunch of html tags with the right Bootstrap based classes -- something I cannot learn by heart what's the reason a generator seems to be a good idea:

<div class="sidebar-wrapper">
    <div class="logo">
        <a class="simple-text">
            AppTitle
        </a>
    </div>
    <ul class="nav">

        <li>
            <a>
                <i class="ti-home"></i>
                <p>Home</p>
            </a>
        </li>

        <!-- add here some other items as shown before -->
    </ul>
</div>

In addition to the code shown before, I want also have the possibility to create a more dynamic version of this side menu. This version uses an interface MenuItem to represent the items to display:

export interface MenuItem {
    title: string;
    iconClass: string;
}

A MenuService is providing instances of MenuItem:

import { MenuItem } from './menu-item';

export class MenuService {

    public items: MenuItem[] = [
        { title: 'Home', iconClass: 'ti-home' },
        { title: 'Other Menu Item', iconClass: 'ti-arrow-top-right' },
        { title: 'Further Menu Item', iconClass: 'ti-shopping-cart'},
        { title: 'Yet another one', iconClass: 'ti-close'}
    ];

}

The component gets an instance of the service by the means of dependency injection:

import { Component, OnInit } from '@angular/core';
import { menuItem } from './menu-item';
import { menuService } from './menu.service';

@Component({
    selector: 'menu',
    templateUrl: './menu.component.html',
    providers:[MenuService]
})
export class MenuComponent {

    items: MenuItem[];

    constructor(service: MenuService) {
        this.items = service.items;
    }
}

After fetching the MenuItems from the service the component iterates over them using *ngFor and creates the needed markup:

<div class="sidebar-wrapper">
    <div class="logo">
        <a class="simple-text">
            AppTitle
        </a>
    </div>
    <ul class="nav">
        <li *ngFor="let item of items">
            <a href="#">
                <i class="{{item.iconClass}}"></i>
                <p>{{item.title}}</p>
            </a>
        </li>
    </ul>
</div>

Even though this example is quite easy it provides enough stuff to demonstrate the basics of Schematics.

Scaffolding a Collection for Schematics ... with Schematics

To provide a project structure for an npm package with a Schematics Collection, we can leverage Schematics itself. The reason is that the product team provides a "meta schematic" for this. To get everything up and running we need to install the following npm packages:

  • @angular-devkit/schematics for executing Schematics
  • @schematics/schematics for scaffolding a Collection
  • ```rxjs`` which is a needed transitive dependency

For the sake of simplicity, I've installed them globally:

npm i -g @angular-devkit/schematics
npm i -g @schematics/schematics
npm i -g rxjs

In order to get our collection scaffolded we just need to type in the following command:

schematics @schematics/schematics:schematic --name nav

The parameter @schematics/schematics:schematic consists of two parts. The first part -- @schematics/schematics -- is the name of the collection, or to be more precise, the npm package with the collection. The second part -- schematic -- is the name of the Schematic we want to use for generating code.

After executing this command we get an npm package with a collection that holds three demo schematics:

npm package with collection

The file collection.json contains metadata about the collection and points to the schematics in the three sub folders. Each schematic has meta data of its own describing the command line arguments it supports as well as generator code. Usually, they also contain template files with placeholders used for generating code. But more about this in the following sections.

Before we can start, we need to npm install the dependencies the generated package.json points to. In addition to that, it is a good idea to rename its section dependencies to devDependencies because we don't want to install them when we load the npm package into a project:

{
  "name": "nav",
  "version": "0.0.0",
  "description": "A schematics",
  "scripts": {
    "build": "tsc -p tsconfig.json",
    "test": "npm run build && jasmine **/*_spec.js"
  },
  "keywords": [
    "schematics"
  ],
  "author": "",
  "license": "MIT",
  "schematics": "./src/collection.json",
  "devDependencies": {
    "@angular-devkit/core": "^0.0.15",
    "@angular-devkit/schematics": "^0.0.25",
    "@types/jasmine": "^2.6.0",
    "@types/node": "^8.0.31",
    "jasmine": "^2.8.0",
    "typescript": "^2.5.2"
  }
}

As you saw in the last listing, the packages.json contains a field schematics which is pointing to the file collection.json to inform about the metadata.

Adding an custom Schematic

The three generated schematics contain comments that describe quite well how Schematics works. It is a good idea to have a look at them. For this tutorial, I've deleted them to concentrate on my own schematic. For this, I'm using the following structure:

Structure for custom Schematics

The new folder menu contains the custom schematic. It's command line arguments are described by the file schema.json using a json schema. The described data structure can also be found as an interface within the file schema.ts. Normally it would be a good idea to generate this interface out of the schema but for this easy case I've just handwritten it.

The index.ts contains the so called factory for the schematic. This is a function that generates a rule (containing other rules) which describes how the code can be scaffolded. The templates used for this are located in the files folder. We will have a look at them later.

First of all, let's update the collection.json to make it point to our menu schematic:

{
    "schematics": {
      "menu": {
        "aliases": [ "mnu" ],
        "factory": "./menu",
        "description": "Generates a menu component",
        "schema": "./menu/schema.json"
      }
    }
}

Here we have an property menu for the menu schematic. This is also the name we reference when calling it. The array aliases contains other possible names to use and factory points to the file with the schematic's factory. Here, it points to ./menu which is just a folder. That's why the factory is looked up in the file ./menu/index.js.

In addition to that, the collection.json also points to the schema with the command line arguments. This file describes a property for each possible argument:

{
    "$schema": "http://json-schema.org/schema",
    "id": "SchemanticsForMenu",
    "title": "Menu Schema",
    "type": "object",
    "properties": {
      "name": {
        "type": "string",
        "default": "name"
      },
      "path": {
        "type": "string",
        "default": "app"
      },
      "appRoot": {
        "type": "string"
      },
      "sourceDir": {
        "type": "string",
        "default": "src"
      },
      "menuService": {
        "type": "boolean",
        "default": false,
        "description": "Flag to indicate whether an menu service should be generated.",
        "alias": "ms"
      }
    }
  }

The argument name holds the name of the menu component, its path as well as the path of the app (appRoot) and the src folder (sourceDir). These parameters are usually used by all schematics the CLI provides. In addition to that, I've defined a property menuService to indicate, whether the above mentioned service class should be generated too.

The interface for the schema within schema.ts is called MenuOptions:

export interface MenuOptions {
    name: string;
    appRoot: string;
    path: string;
    sourceDir: string;
    menuService: boolean;
}

Schematic Factory

To tell Schematics how to generated the requested code files, we need to provide a factory. This function describes the necessary steps with a rule which normally makes use of further rules:

import { MenuOptions } from './schema';
import { Rule, [...] } from '@angular-devkit/schematics';
[...]
export default function (options: MenuOptions): Rule {
    [...]
}

For this factory, I've defined two helper constructs at the top of the file:

import { dasherize, classify } from '@angular-devkit/core';
import { MenuOptions } from './schema';
import { filter, Rule, [...] } from '@angular-devkit/schematics';

[...]

const stringUtils = { dasherize, classify };

function filterTemplates(options: MenuOptions): Rule {
  if (!options.menuService) {
    return filter(path => !path.match(/\.service\.ts$/) && !path.match(/-item\.ts$/) && !path.match(/\.bak$/));
  }
  return filter(path => !path.match(/\.bak$/));
}

[...]

The first one is the object stringUtils which just groups some functions we will need later within the templates: The function dasherize transforms a name into its kebab case equivalent which can be used as a file name (e. g. SideMenu to side-menu) and classify transforms into Pascal case for class names (e. g. side-menu to SideMenu).

The function filterTemplates creates a Rule that filters the templates within the folder files. For this, it delegates to the existing filter rule. Depending on whether the user requested a menu service, more or less template files are used. To make testing and debugging easier, I'm excluding .bak in each case.

Now let's have a look at the factory function:

import { chain, mergeWith } from '@angular-devkit/schematics';
import { dasherize, classify } from '@angular-devkit/core';
import { MenuOptions } from './schema';
import { apply, filter, move, Rule, template, url, branchAndMerge } from '@angular-devkit/schematics';
import { normalize } from '@angular-devkit/core';

[...]

export default function (options: MenuOptions): Rule {

    options.path = options.path ? normalize(options.path) : options.path;
    
    const templateSource = apply(url('./files'), [
        filterTemplates(options),
        template({
          ...stringUtils,
          ...options
        }),
        move(options.sourceDir)
      ]);
      
      return chain([
          mergeWith(templateSource)
      ]);

}

At the beginning, the factory normalizes the path the caller passed in. This means that it deals with the conventions of different operating systems, e. g. using different path separators (e. g. / vs. \).

Then, it uses apply to apply all templates within the files folder to the passed rules. After filtering the available templates they are executed with the rule returned by template. The passed properties are used within the templates. This creates a virtual folder structure with generated files that is moved to the sourceDir.

The resulting templateSource is a Source instance. It's responsibility is creating a Tree object that represents a file tree which can be either virtual or physical. Schematics uses virtual file trees as a staging area. Only when everything worked, it is merged with the physical file tree on your disk. You can also think about this as committing a transaction.

At the end, the factory returns a rule created with the chain function (which is a rule too). It creates a new rule by chaining the passed ones. In this example we are just using the rule mergeWith but the enclosing chain makes it extendable.

As the name implies, mergeWith merges the Tree represented by templateSource with the tree which represents the current Angular project.

Templates

Now it's time to look at our templates within the files folder:

Folder with Templates

The nice thing about this is that the file names are templates too. For instance __x__ would be replaced with the contents of the variable x which is passed to the template rule. You can even call functions to transform these variables. In our case, we are using __name@dasherize__ which passes the variable name to the function dasherize which in turn is passed to template too.

The easiest one is the template for the item class which represents a menu item:

export interface <%= classify(name) %>Item {
    title: string;
    iconClass: string;
}

Like in other known template languages (e. g. PHP), we can execute code for the generation within the delimiters <% and %>. Here, we are using the short form <%=value%> to write a value to the generated file. This value is just the name the caller passed transformed with classify to be used as a class name.

The template for the menu service is build in a similar way:

import { <%= classify(name) %>Item } from './<%=dasherize(name)%>-item';

export class <%= classify(name) %>Service {

    public items: <%= classify(name) %>Item[] = [
        { title: 'Home', iconClass: 'ti-home' },
        { title: 'Other Menu Item', iconClass: 'ti-arrow-top-right' },
        { title: 'Further Menu Item', iconClass: 'ti-shopping-cart'},
        { title: 'Yet another one', iconClass: 'ti-close'}
    ];
}

In addition to that, the component template contains some if statements that check whether a menu service should be used:

import { Component, OnInit } from '@angular/core';
<% if (menuService) { %>
import { <%= classify(name) %>Item } from './<%=dasherize(name)%>-item';
import { <%= classify(name) %>Service } from './<%=dasherize(name)%>.service';
<% } %>

@Component({
    selector: '<%=dasherize(name)%>',
    templateUrl: '<%=dasherize(name)%>.component.html',
    <% if (menuService) { %>
        providers: [<%= classify(name) %>Service]
    <% } %>
})
export class <%= classify(name) %>Component {

<% if (menuService) { %>
    items: <%= classify(name) %>Item[];

    constructor(service: <%= classify(name) %>Service) {
        this.items = service.items;
    }
<% } %>

}

The same is the case for the component's template. When the caller requested a menu service, it's using it; otherwise it just gets hardcoded sample items:

<div class="sidebar-wrapper">
    <div class="logo">
        <a class="simple-text">
            AppTitle
        </a>
    </div>
    <ul class="nav">

<% if (menuService) { %>
    <li *ngFor="let item of items">
        <a>
            <i class="{{item.iconClass}}"></i>
            <p>{{item.title}}</p>
        </a>
    </li>

<% } else { %>
        <li>
            <a>
                <i class="ti-home"></i>
                <p>Home</p>
            </a>
        </li>

        <li>
            <a>
                <i class="ti-arrow-top-right"></i>
                <p>Other Menu Item</p>
            </a>
        </li>

		<li>
			<a>
				<i class="ti-shopping-cart"></i>
				<p>Further Menu Item</p>
			</a>
		</li>

		<li>
			<a>
				<i class="ti-close"></i>
				<p>Yet another one</p>
			</a>
		</li>
        <% } %>
    </ul>
</div>

Building and Testing with an Sample Application

To build the npm package, we just need to call npm run build which is just triggering the TypeScript compiler.

For testing it, we need a sample application that can be created with the CLI. Please make sure to use Angular CLI version 1.5 RC.4 or higher.

For me, the easiest way to test the collection was to copy the whole package into the sample application's node_module folder so that everything ended up within node_modules/nav. Please make sure to exclude the collection's node_modules folder, so that there is no folder node_modules/nav/node_modules.

Instead of this, pointing to a relative folder with the collection should work too. In my experiments, I did with a release candidate, this wasn't the case (at least not in any case).

After this, we can use the CLI to scaffold our side menu:

ng g menu side-menu --menuService --collection nav

Here, menu is the name of the schematic, side-menu the file name we are passing and nav the name of the npm package.

Using the Schematic

After this, we need to register the generated component with the AppModule:

import { SideMenuComponent } from './side-menu/side-menu.component';
import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent,
    SideMenuComponent
  ],
  imports: [
    BrowserModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

In an other post, I will show how to even automate this task with Schematics.

After this, we can call the component in our AppModule. The following sample also contains some boiler blade for the Bootstrap Theme used in the initial screen shot.

<div class="wrapper">
  <div class="sidebar" data-background-color="white" data-active-color="danger">

      <side-menu></side-menu>
  
  </div>
  <div class="main-panel">
      <div class="content">
        <div class="card">
          <div class="header">
            <h1 class="title">Hello World</h1>
          </div>
          <div class="content">
            <div style="padding:7px">
             Lorem ipsum ...
            </div>
          </div>
        </div>
      </div>
  </div>
</div>

To get Bootstrap and the Bootstrap Theme, you can download the free version of the paper theme and copy it to your assets folder. Also reference the necessary files within the file .angular-cli.json to make sure they are copied to the output folder:

[...]
"styles": [
  "styles.css",
  "assets/css/bootstrap.min.css",
  "assets/css/paper-dashboard.css",
  "assets/css/demo.css",
  "assets/css/themify-icons.css"
],
[...]

After this, we can finally run our application: ng serve.

AIT: Neu in TFS 2018: Erweiterungen der Pull Requests

Damit der Code einer Software eine hohe Qualität aufweist sind regelmäßige Reviews Pflicht. Pull Requests (PR) bieten für Reviews eine tolle Plattform. Sie stellen eine Art Benachrichtigung dar, in der ein Verantwortlicher Anton eine andere Entwicklerin Berta darum bittet den neuen Code in den bestehenden zu integrieren. Entwicklerin Berta kann nun Feedback liefern und eine Diskussion beginnen, woraufhin Anton den Code wieder ändert, um schlussendlich wiederum von Berta abgesegnet zu werden. Feedback zu Code wird dabei in Form von Kommentaren hinterlassen.  Auch bei den bereits vorgestellten Git Forks, welche nun neu in TFS 2018 dazu gekommen sind, kommen Pull Requests zum Einsatz um bspw. Erweiterungen von außen in das Projekt zu integrieren.

Mit TFS 2018 kommen nun einige Neuerungen in den Bereich der Pull Requests, welche die Benutzbarkeit dieser deutlich erhöhen. Wir stellen Ihnen die Wichtigsten vor.

Zuordnung von Kommentaren

Ein großes Problem mit Pull Requests im TFS war bisher, dass Kommentare nach einem Update des Codes oftmals nun an einer falschen Stelle sichtbar waren, da Kommentare lediglich einer Zeile zugewiesen sind. Dadurch konnte es durchaus vorkommen, dass der Kommentar in Kombination mit dem neuen Code keinerlei Sinn mehr ergab oder im schlimmsten Fall sogar zu Feedback welches im Zusammenhang mit dem neuen Code falsch verstanden werden kann. Hier wurde im TFS 2018 deutlich nachgebessert.
In der Übersicht eines Pull Requests gibt es nun die Möglichkeit bei Kommentaren das originale Diff des Codes zu betrachten. Hierzu wurde ein Button zur Verfügung gestellt, welcher es ermöglicht zwischen dem aktuellen und dem originalen Diff hin- und herzuwechseln.

Filterung

Auch im Bereich der Übersichtlichkeit wurde nachgelegt. Es besteht nun die Möglichkeit Kommentare sowie Dateien zu filtern. Kommentare lassen sich im Reiter Overview praktisch nach ihrem Zustand (Active, Resolved) oder ihrer Aktualität filtern.

Im Bereich Files lassen sich diese sogar gänzlich ausblenden um mehr Übersicht über den Code zu erhalten. Dabei bleibt jedoch neben der kommentierten Zeile das Profilbild des Reviewers erhalten und über eine Quickinfo erhält man einen Ausschnitt des Kommentars. Nach einem Klick auf das Profilbild lässt sich außerdem der gesamte Kommentar öffnen.

Bei einer Vielzahl an Änderungen konnte es im Files Bereich schnell unübersichtlich werden wodurch das Auffinden einer Datei unnötig Zeit kosten konnte. Hier wurde dem TFS 2018 eine Sucheingabe spendiert, welche nicht nur nach Dateinamen, sondern auch nach Ordnernamen, partiellen Pfaden sowie Erweiterungen filtern lässt. Was wir leider vermissen ist das Filtern mit Pattern wie bspw. „/folder/*.test“.

Aufgabenlisten

Häufig kann es vorkommen, dass innerhalb eines PRs bestimmte Arbeiten abgearbeitet werden sollen. So muss beispielsweise sichergestellt werden, dass die Versionsnummer aktualisiert wird, ein Unit Test bei gefixtem Bug hinzugefügt wird oder einfach etwas getestet werden soll.

Mit dem TFS 2018 gibt es nun die Möglichkeit Aufgabenlisten in die Beschreibung eines Pull Requests oder in einen Kommentar zu integrieren. Die über Markdown eingefügten Kontrollkästchen können nun ohne extra die Beschreibung ändern zu müssen komfortabel abgehakt werden.

Zurücksetzen von Votings

Bei einem Push innerhalb eines Pull Requests ist es wahrscheinlich, dass sich nicht nur Kleinigkeiten ändern. Daher könnte es fatal sein, wenn der Reviewer bereits für ein Approved gestimmt hat, sich nun aber nun grundlegendes verändert hat. Bisher wurde das Approved gespeichert, mit dem TFS 2018 kann es nach einem neuen Push oder mit einer neuen Iteration automatisch zurückgesetzt werden, sodass die Annahme erneut manuell gesetzt werden muss. So können fälschlich abgeschlossene Pull Requests reduziert werden.

Diese Option muss über die Branch Policies im Reiter Versionskontrolle des eingestellt werden.

Abschließen von Work Items mit Abschließen des Pull Requests

Auch im Bereich des Abschließens eines Pull Requests hat Microsoft nachgebessert und Vorgänge automatisiert. Im Kontext eines Projektes beinhaltet ein Pull Request im TFS meist ein Feature, einen Bugfix oder einzelne Tasks. Zwar lassen sich die Work Items mit dem PR verknüpfen, müssen aber nach Abschluss dessen zusätzlich manuell abgeschlossen werden. Auch hier bietet der TFS 2018 eine komfortable Lösung, indem er bei Abschluss des Pull Requests neben bekannten Optionen, wie das Löschen des Branches, die Möglichkeit bietet alle verknüpften Work Items automatisch zu schließen.

Die Standardeinstellung hierzu kann, ähnlich wie beim Zurücksetzen der Votings, über die Optionen eines Repositorys gesetzt werden.

Fazit

Der TFS 2018 bessert im Bereich der Pull Requests an den richtigen Stellen nach. Kommentare sind nun endlich korrekt zuordenbar und kleine, aber feine Erweiterungen vereinfachen den Workflow mit diesem Instrument deutlich.

 

AIT: Neu in TFS 2018: Jetzt auch mit Git-Forks

Mit dem neuen Update halten Git-Forks im TFS 2018 Einzug. Egal ob es der Student oder der Kollege aus einer anderen Abteilung ist, welcher eine neue Funktion implementieren möchte und deshalb Zugriff auf mein Repository benötigt. Mögliche Anwendungsfälle für Git-Forks innerhalb von der TFS-Umgebung gibt es reichlich.

Ich, als Besitzer eines Repository möchte nicht, dass Personen, welche nur einen temporären Zugriff auf mein Repository benötigen, schreibend auf mein Repository einwirken können. Ein Grund dafür ist die erhöhte Administration dieser Benutzer. Zugriff geben und dann wieder nehmen, wenn die Zeit abgelaufen ist, erhöht den Administrationsaufwand.
Eine Lösung des Problems sind Git-Forks. Damit kann ich Personen, welche nur Leserechte auf mein Repository besitzen, an meinem Projekt mitwirken lassen. Jede Person, welche einen Fork erstellen möchte, muss das Recht besitzen Repositories im TFS anzulegen und benötigt Leserecht auf das gewünschte Projekt. Über einen Pull Request kann der Besitzer des Repositories die Änderungen aus dem Git-Fork übernommen werden.
Dadurch bleibt mein Repository übersichtlich und ich genieße trotzdem den Vorzug einer offenen Community innerhalb ihrer TFS Umgebung. Außerdem wird die Administration erleichtert.

Beispiel:

Im Folgenden zeige ich, wie ein Fork angelegt wird und wie Änderungen über einen Pull Request an das ursprüngliche Repository zurückgegeben werden.

Voraussetzung:
Der Benutzer muss mindestens das Recht besitzen sich eigene Repository in seinem Team Projekt (Studenten) anzulegen (Abbildung 1) und lesend auf das gewünschte Repository (CMMI) zugreifen zu können (Abbildung 2).


Abbildung 1: Rechte, auf das „Ziel“ Repository im eigenem Team Projekt

Abbildung 2: Ausschließlich Leserecht auf das „orginal“ Repository.

 

Über die Schaltfläche „Fork“ im Hub „Code“ wird ein neuer Fork erstellt.


Abbildung 3: Schaltfläche „Fork“ unter Code

 

Im folgenden Popup muss jetzt ein Name für das neue Repository (HelloWorldNewFork) und das Projekt (Studenten) ausgewählt werden.


Abbildung 4+5: Anlegen eines neuen Fork.

 

Wird das Team Projekt nicht geändert, so bekommt der Benutzer den Fehler, dass er keine ausreichenden Rechte im ausgewählten Projekt hat.

Nachdem ein neuer Name für das Repository festgelegt und ein Projekt zugewiesen werden konnte, kann damit wie gewohnt gearbeitet werden. Jetzt befindet sich eine Kopie des „orginal“ Repository im Projekt des Benutzers.


Abbildung 6: Neues Repository

 

Über einen Pull Request werden die Änderung wieder in das Team Projekt CMMI übernommen.



Abbildung 7 + 8: Pull Request nachdem Commit erstellen.

 

Der Pull Request verhält sich, wie es der Benutzer vom TFS bereits gewohnt ist.

Fazit

Mit Git-Forks genießt man den Vorzug einer offenen Community innerhalb einer geschlossenen TFS Umgebung.

 

 

Weitere Schritte auf diesem Weg stellen wir Ihnen auch in nachfolgenden Beiträgen unserer Blogserie vor. Bleiben Sie also dran und freuen Sie sich aufspannende Neuerungen mit TFS 2018.

Jürgen Gutsch: GraphiQL for ASP.​NET Core

One nice thing about blogging is the feedback from the readers. I got some nice kudos, but also great new ideas. One idea was born out of a question about a "graphi" UI for the GraphQL Middleware I wrote some months ago. I never heard about "graphi", which actually is "GraphiQL", a generic HTML UI over a GraphQL endpoint. It seemed to be something like a Swagger UI, but just for GraphQL. That sounds nice and I did some research about that.

What is GraphiQL?

Actually it is absolutely not the same as Swagger and not as detailed as Swagger, but it provides a simple and easy to use UI to play around with your GraphQL end-point. So you cannot really compare it.

GraphiQL is a React component provided by the GraphQL creators, that can be used in your project. It basically provides an input area to write some GraphQL queries and a button to sent that query to your GrapgQL end-point. You'll than see the result or the error on the right side of the UI.

Additionally it provides some more nice features:

  • A history of sent queries, which appears on the left side, if you press the history-button. To reuse previously used queries.
  • It rewrites the URL to support linking to a specific query. It stores the query and the variables in the URL, to sent it to someone else, or to bookmark the query to test.
  • It actually creates a documentation out of the GraphQL end-point. By clicking at the "Docks" link it opens a documentation about the types used in this API. This is really magic, because it shows the documentation of a type I never requested:

Implementing GraphiQL

The first idea was to write something like this by my own. But it should be the same as the existing GraphiQL UI. Why not using the existing implementation? Thanks to Steve Sanderson, we have the Node Services for ASP.NET Core. Why not running the existing GraphiQL implementation in a Middleware using the NodeServices?

I tried it with the "apollo-server-module-graphiql" package. I called this small JavaScript to render the graphiql UI and return it back to C# via the NodeSerices:

var graphiql = require('apollo-server-module-graphiql');

module.exports = function (callback, options) {
    var data = {
        endpointURL: options.graphQlEndpoint
    };

    var result = graphiql.renderGraphiQL(data);
    callback(null, result);
};

The usage of that script inside the Middleware looks like this:

var file = _env.WebRootFileProvider.GetFileInfo("graphiql.js");
var result = await _nodeServices.InvokeAsync<string>(file.PhysicalPath, _options);
await httpCont

That works great, but has one problem. It wraps the GraphQL query in a JSON-Object that was posted to the GraphQL end-point. I would need to change the GraphQlMiddleware implementation, because of that. The current implementation expects the plain GraphQL query in the POST body.

What is the most useful approach? Wrapping the GraphQL query in a JSON object or sending the plain query? Any Ideas? What do you use? Please tell me by dropping a comment.

With this approach I'm pretty much dependent to the Apollo developers and need to change my implementation, whenever they change their implementations.

This is why I decided to use the same concept of generating the UI as the "apollo-server-module-graphiql" package but implemented in C#. This unfortunately doesn't need the NodeServices anymore.

I use exact the same generated code as this Node module, but changed the way the query is send to the server. Now the plain query will be sent to the server.

I started playing around with this and added it to the existing project, mentioned here: GraphQL end-point Middleware for ASP.NET Core.

Using the GraphiqlMiddleware

The result is as easy to use as the GraphQlMiddleware. Let's see how it looks to add the Middlewares:

if (env.IsDevelopment())
{
    app.UseDeveloperExceptionPage();
	// adding the GraphiQL UI
    app.UseGraphiql(options =>
    {
        options.GraphiqlPath = "/graphiql"; // default
        options.GraphQlEndpoint = "/graph"; // default
    });
}
// adding the GraphQL end point
app.UseGraphQl(options =>
{
    options.GraphApiUrl = "/graph"; // default
    options.RootGraphType = new BooksQuery(bookRepository);
    options.FormatOutput = true; // default: false
});

As you can see the second Middleware is bound to the first one by using the same path "/graph". I didn't create any hidden dependency between the both Middlewares, to make it ease to use it in various combinations. Maybe you want to use the GraphiQL UI only in the Development or Staging environment as shown in this example.

Now start the web using Visual Studio (press [F5]). The web starts with the default view or API. Add "graphiql" to the URL in the browsers address bar and see what happens. You should see a generated UI for your GraphQL endpoint, where you can now start playing around with our API, testing and debugging it with your current data. (See the screenshots on top.)

I'll create a separate NuGet package for the GraphiqlMiddleware. This will not have the GraphQlMiddleware as a dependency and could be used completely separate.

Conclusion

This was a lot easier to implement than expected. Currently there is still some refactoring needed:

  • I don't like to have the HMTL and JavaScript code in the C#. I'd like to load that from an embedded resource file, which actually is a HTML file.
  • I should add some more configuration options. E.g. to change the theme, as equal to the original Node implementation, to preload queries and results, etc.
  • Find a way to use it offline as well. Currently there's a connection to the internet needed to load the CSS and JavaScripts from the CDNs.

You wanna try it? Download, clone or fork the sources on GitHub.

What do you think about that? Could this be useful to you? Please leave a comment and tell me about your opinion.

Update [10/26/2017 21:03]

GraphiQL is much more powerful than expected. I was wondering how the GraphQL create IntelliSense support in the editor and how it creates the documentation. I had a deeper look into the traffic and found two more cool things about it:

First: GraphiQL sends a special query to the GraphQL to request for the GraphQL specific documentation. IN this case it looks like this:

  query IntrospectionQuery {
    __schema {
      queryType { name }
      mutationType { name }
      subscriptionType { name }
      types {
        ...FullType
      }
      directives {
        name
        description
        locations
        args {
          ...InputValue
        }
      }
    }
  }

  fragment FullType on __Type {
    kind
    name
    description
    fields(includeDeprecated: true) {
      name
      description
      args {
        ...InputValue
      }
      type {
        ...TypeRef
      }
      isDeprecated
      deprecationReason
    }
    inputFields {
      ...InputValue
    }
    interfaces {
      ...TypeRef
    }
    enumValues(includeDeprecated: true) {
      name
      description
      isDeprecated
      deprecationReason
    }
    possibleTypes {
      ...TypeRef
    }
  }

  fragment InputValue on __InputValue {
    name
    description
    type { ...TypeRef }
    defaultValue
  }

  fragment TypeRef on __Type {
    kind
    name
    ofType {
      kind
      name
      ofType {
        kind
        name
        ofType {
          kind
          name
          ofType {
            kind
            name
            ofType {
              kind
              name
              ofType {
                kind
                name
                ofType {
                  kind
                  name
                }
              }
            }
          }
        }
      }
    }
  }

Try this query and sent it to your GraphQL API using Postman or a similar tool and see what happens :)

Second: GraphQL for .NET knows how to answer that query and sent the full documentation about my data structure to the client like this:

{
    "data": {
        "__schema": {
            "queryType": {
                "name": "BooksQuery"
            },
            "mutationType": null,
            "subscriptionType": null,
            "types": [
                {
                    "kind": "SCALAR",
                    "name": "String",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "Boolean",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "Float",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "Int",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "ID",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "Date",
                    "description": "The `Date` scalar type represents a timestamp provided in UTC. `Date` expects timestamps to be formatted in accordance with the [ISO-8601](https://en.wikipedia.org/wiki/ISO_8601) standard.",
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
                {
                    "kind": "SCALAR",
                    "name": "Decimal",
                    "description": null,
                    "fields": null,
                    "inputFields": null,
                    "interfaces": null,
                    "enumValues": null,
                    "possibleTypes": null
                },
              	[ . . . ]
                // many more documentation from the server
        }
    }
}

This is really awesome. With GraphiQL I got a lot more stuff than expected. And it didn't take more than 5 hours to implement this middleware.

Christian Dennig [MS]: Deploy a hybrid Kubernetes Cluster to Azure Container Service

Lately, I have been working a lot with Kubernetes as one (of many) solutions to run Docker containers in the cloud. Microsoft therefore offers Azure Container Service (ACS), a service to create and (partly) manage a Kubernetes cluster on Azure.

You normally would deploy such a cluster via the Azure Portal or e.g. via the Azure Command Line Interface. Here is a sample command:

az acs create --orchestrator-type kubernetes 
  --resource-group k8s-rg --name myk8scluster --generate-ssh-keys

Unfortunately, you cannot customize all the properties of the Kubernetes deployment with this approach, e.g. if you want to place the cluster in an existing Azure Virtual Network (VNET) or if you want to run multiple node types within the cluster to be able to run Linux and Windows based images/pods in parallel.

To achieve this, you must use the ACS engine which is a kind of “translator” between cluster configurations (which are provided in JSON format) and Azure Resource Manager templates.

ACS Engine

The ACS engine provides a convenient way to generate an ARM template that creates a Kubernetes cluster for you in Azure. The nice thing about it is, that you can influence a lot more properties of the cluster than you can do via the portal or CLI. But more on this later…

If you execute the ACS engine, the resulting template created consists of all the resources, you need to run a cluster in Azure, e.g.:

  • Availability Sets for Master and Agent nodes
  • VMs / VM extensions
  • NICs / VNET configurations
  • Load Balancer
  • etc.

You can deploy the ARM template as you would deploy any other template to Azure by running a Powershell or CLI command, even via the portal.

But let’s get to our sample, creating a hybrid Windows/Linux cluster…

Hybrid Cluster With ACS Engine

We will start by creating a cluster definition file…

Some details on that:

  • First of all, we create the cluster configuration, setting the Kubernetes version to “1.8” (starting line 4)
  • the profile of the master node is set, giving it a name and a VM type  “Standard_D2_v2” (beginning line 8).
  • agent profiles are defined, setting up two profiles. One for Linux nodes, the other one for Windows nodes…also setting the VM size to “Standard_D2_v2” (lines 13 to 27)
  • next, the two profiles are configured, each with the corresponding access information (user name or ssh key), lines 28 to 41
  • the last step is to set the service principal (application id and password, lines 42 to 45), which is needed by Kubernetes to interact with Azure. E.g. when you define a service of type “LoadBalancer”, K8s reaches out to Azure to create an external IP at the Azure Load Balancer
  • the .env file has to be placed in the same folder as the JSON file

In case a SSH key has to be created, you can do this on Windows via PuttyGen or on Linux/Mac via ssh directly. The value of the public key must be specified in the definition file (keyData, line 37).

If no service principal already exists, you can create it using the following command:

az ad sp create-for-rbac 
  --role Contributor --scopes="/subscriptions/[YOUR_SUBSCRIPTION_ID]"

The values from “appId” and “password” must be stored in the corresponding properties of the cluster configuration (lines 43 and 44).

Generate The ARM Template

In order to create the ARM template from the cluster configuration, we first need the ACS-engine binary. You can download it from here. Unzip the contents and place the destination folder into the PATH environment variable, to be able to run it from anywhere on your machine.

Next, run the ACS engine with your configuration…

acs-engine generate .\k8s-hybrid.json

The ACS engine takes the JSON file and generates an _output directory with all the necessary artifacts (among other things, a rather large ARM template + parameters-file) to deploy the K8s cluster to Azure. Here’s a visual representation of the ARM template:

hybrid_cluster

ARMVIZ representation of the resulting template

Next, you simply deploy the template, as you would do it with other ARM templates. First, create a Azure Resource Group:

az group create -n k8scluster-rg -l westeurope

Afterwards, switch to the _output/[CLUSTERNAME] folder and deploy the template:

az group deployment create -g k8scluster-rg 
  --template-file .\azuredeploy.json 
  --parameters .\azuredeploy.parameters.json

After some time, the command returns, telling you that the cluster has been created successfully.

Connect To The Cluster

After creating the cluster, we want to connect to it via kubectl. Therefore we need the configuration of the cluster, which we have to copy by scp or pscp (from Putty) from the master node. To do this, execute this command (I’m on Windows, so I use pscp):

pscp -i [PATH_TO_PRIVATE_SSHKEY_FILE] 
  azureuser@[FQDN_OF_MASTER_NODE]:.kube/config .

If you want to, set the config file you just downloaded as the default file (environment variable KUBECONFIG), otherwise use the config by passing

--kubeconfig=".\config"

to each kubectl command.

So, let’s try to get the nodes of our cluster:

kubectl --kubeconfig=".\config" get nodes

Result:

get_nodes

That looks pretty good! Now let’s connect to the dashboard via…

kubectl --kubeconfig=".\config" proxy

…then open up a browser window and point to:

http://localhost:8001/api/v1/proxy/namespaces/kube-system/services/kubernetes-dashboard/

Now head over to the “Nodes” view and click on one of the “*acs90*” nodes:

dashboard

Nodes

windows_node

A Window node

As you can see, this node runs Windows (one of the node labels is “beta.kubernetes.io/os: windows“)…a Windows version of course, that can run Windows based containers!

Deploy Some Windows And Linux Containers

To test our cluster, we deploy the following template to Kubernetes:

What it will create:

The important part of the deployment file is the node selection for the pods/containers. In lines 25/26, the template defines to select Linux-based nodes to deploy the nginx containers:

nodeSelector:
        beta.kubernetes.io/os: linux

The same is done for the IIS deployment (lines 52/53):

nodeSelector:
        beta.kubernetes.io/os: windows

These properties tell the Kubernetes cluster to create the nginx pods only on Linux and the IIS pods on Windows nodes, magic!

After some time (give it a few “seconds”, the image of the IIS pods is about 5 GB!), you will be able to query the running pods and the services:

result

Et voilà, we are able to connect to the services via a browser…

svc_linux

Linux based container

svc_win

Windows based container

That’s what we wanted to achieve…Linux and Windows containers managed by the same cluster! 🙂

Wrap Up

I hope you could see, how easy it is to deploy a Kubernetes cluster to Azure. In this example, I only showed how to create a hybrid cluster, to be able to run Linux and Windows based containers/pods in parallel. Nevertheless, on the ACS Engine Github repository (where this sample is basically from) you can find many other examples, e.g. to place the cluster in an existing VNET, attach disks to nodes, create a Swarm cluster etc. Check it out, play with ACS…and have fun! 🙂


Holger Schwichtenberg: Buch "Moderne Datenzugriffslösungen mit Entity Framework Core 2.0: Datenbankprogrammierung mit .NET/.NET Core und C#"

Das Buch behandelt auf rund 460 Seiten alle wichtigen Szenarien des Datenbankzugriffs mit Entity Framework Core 2.0 sowie zahlreiche Praxislösungen und Tipps.

Johannes Renatus: Laden von 64Bit DLLs in 32Bit Anwendung mit Reflection

Da könnte man sich fragen wozu man sowas braucht. Aber es gibt immer einen guten Grund und in meinem Fall ging es darum, das ich in einem T4 Template 64Bit DLLs laden musste und diese nach Benutzerdefinierten Attributen zu durchsuchen um dann eine passende Ausgabe zu erstellen. Leider gibt es die Konsolenanwendung mit der VisualStudio […]

Jürgen Gutsch: .NET Core 2.0 and ASP.NET 2.0 Core are here and ready to use

Recently I did a overview talk about .NET Core, .NET Standard and ASP.NET Core at the Azure Meetup Freiburg. I told them about .NET Core 2.0, showed the dotnet CLI and the integration in Visual Studio. Explained the sense of .NET Standard and why developers should take care about it. I also showed them ASP.NET Core, how it works, how to host and explained the main differences to the ASP.NET 4.x versions.

BTW: This Meetup was really great. Well organized on a pretty nice and modern location. It was really fun to talk there. Thanks to Christian, Patrick and Nadine to organize this event :-)

After that talk they asked me some pretty interesting and important questions:

Question 1: "Should we start using ASP.NET Core and .NET Core?"

My answer is a pretty clear YES.

  • Use .NET Standard for your libraries, if you don't have dependencies to platform specific APIs (eg. Registry, drivers, etc.) even if you don't need to be x-plat. Why? Because it just works and you'll keep a door open to share your library to other platforms later on. Since .NET Standard 2.0 you are not really limited, you are able to do almost all with C# you can do with the full .NET Framework
  • Use ASP.NET Core for new web projects, if you don't need to do Web Forms. Because it is fast, lightweight and x-plat. Thanks to .NET standard you are able to reuse your older .NET Framework libraries, if you need to.
  • Use ASP.NET Core to use the new modern MVC framework with the tag helpers or the new lightweight razor pages
  • Use ASP.NET Core to host your application on various cloud providers. Not only on Azure, but also on Amazon and Google:
    • http://docs.aws.amazon.com/elasticbeanstalk/latest/dg/dotnet-core-tutorial.html
    • https://aws.amazon.com/blogs/developer/running-serverless-asp-net-core-web-apis-with-amazon-lambda/
    • https://codelabs.developers.google.com/codelabs/cloud-app-engine-aspnetcore/#0
    • https://codelabs.developers.google.com/codelabs/cloud-aspnetcore-cloudshell/#0
  • Use ASP.NET Core to write lightweight and fast Web API services running either self hosted, in Docker or on Linux, Mac or Windows
  • Use ASP.NET Core to create lightweight back-ends for Angular or React based SPA applications.
  • Use .NET Core to write tools for different platforms

As an library developer, there is almost no reason to not use the .NET Standard. Since .NET Standard 2.0 the full API of the .NET Framework is available and can be used to write libraries for .NET Core, Xamarin, UWP and the full .NET Framework. It also supports to reference full .NET Framework assemblies.

The .NET Standard is an API specification that need to be implemented by the platform specific Frameworks. The .NET Framework 4.6.2, .NET Core 2.0 and Xamarin are implementing the .NET Standard 2.0, which means they all uses the same API (namespaces names, class names, method names). Writing libraries against the .NET Standard 2.0 API will run on .NET Framework 2.0, on .NET Core 2.0, as well as on Xamarin and on every other platform specific Framework that supports that API.

Question 2: Do we need to migrate our existing web applications to ASP.NET Core?

My answer is: NO. You don't need to and I would propose to not do it if there's no good reason to do it.

There are a lot blog posts out there about migrating web applications to ASP.NET Core, but you don't need to, if you don't face any problems with your existing one. There are just a few reasons to migrate:

  • You want to go x-plat to host on Linux
  • You want to host on small devices
  • You want to host in linux based Docker containers
  • You want to use a faster framework
    • A faster framework is useless, if your code or your dependencies are slow ;-)
  • You want to use a modern framework
    • Note: ASP.NET 4.x is not outdated, still supported and still gets new features
  • You want to run your web on a Microsoft Nano Server

Depending on the level of customizing you did in your existing application, the migration could be a lot of effort. Someone needs to pay for the effort, that's why I would propose not to migrate to ASP.NET Core, if you don't have any problems or a real need to do it.

Conclusion

I would use ASP.NET Core for every new web project and .NET Standard for every library I need to write. Because it is almost mature and really usable since the versions 2.0. You can do almost all the stuff, you can do with the full .NET framework.

BTW: Rick Strahl also just wrote an article about that. Please read it. It's great, as almost all of his posts: https://weblog.west-wind.com/posts/2017/Oct/22/NET-Core-20-and-ASPNET-20-Core-are-finally-here

BTW: The slides off that talk are on SlideShare. If you want me to do that talk in your meetup or in your user group, just ping me on twitter or drop me an email

André Krämer: Hilfe! Xamarin iOS Simulator startet nicht und stürzt mit Fehler: 'A fatal error occured when trying to start the server' ab

Ein schönes Feature der Enterprise Edition von Visual Studio ist die Darstellung des iOS Simulators unter Windows. Während man zum Debugging einer Xamarin iOS App den Simulator normalerweise auf dem Mac bedienen muss, auch wenn man das Debugging unter Windows gestartet hat, erlaubt die Enterprise Edition von Visual Studio die Bedienung des Simulators direkt unter Windows. Hat man sich einmal an diese Arbeitsweise gewöhnt, möchte man sie eigentlich nicht mehr missen.

Holger Schwichtenberg: Überflüssige Leerzeichen in Microsoft SQL Server abschneiden

Mit SQL Server 2017 führt Microsoft endlich die Trim()-Funktion ein, mit der man Leerzeichen am Beginn und am Ende einer Zeichenkette entfernen kann.

Christina Hirth : 10 Jahre Open Space – meine Retrospektive

Workshop-Tag:

Seit ein paar Jahren gibt es die Möglichkeit, den Open Space um ein Tag Workshop zu erweitern – wenn einem die zwei Tage Nerdtalk nicht reichen  😉

Ich habe mich diesmal für Tensorflow: Programming Neural Networks mit Sören Stelzer entschieden – und es war großartig. Obwohl ein sehr schwieriges Thema (das Wort Voodoo ist öfter gefallen), ich weiß jetzt genug über Machine Learning und Neuronale Netze, um mit dem Thema gut starten zu können. Ich formuliere es mal so: ich weiß jetzt, was ich weiß und vor allem, was ich nicht weiß und wie wir weiter machen müssen. Und mehr kann man von einem Workshop nicht erwarten. Zusätzlich finde ich, dass Sören eine sehr große Bereicherung für unsere Community ist, die sich genauso weiterentwickeln muss, wie die IT-Welt da draußen. Vielen Dank für dein Engagement!

Eigentlich ein fetten Dank an alle Trainer, die sich bei Community-Events engagieren!!

Erkenntnisse der nächsten 48 Stunden – geclustert:

Agile datengetriebene Entwicklung – war meine eigene Session (das heißt, ich habe das Thema vorgeschlagen, war Themen-Owner aber das war’s dann auch mit den Pflichten).

Ich wollte Tipps und Ideen dazu hören, wie man seine Arbeit nach scrum organisieren kann wenn man Themen beackert, wie Reporting, wo die Features auf große Menge Daten basieren. Es ist eine Sache, ein Testsetup für 2 möglichen Situationen zu schreiben und es ist eine ganz andere, die vielfalt der Situationen in Reporting zu beschreiben.

Take-aways:

  • wir werden damit leben müssen, dass unsere Features, Tests, Erwartungen eventual consistent sind  😀 Wichtig ist, dass wir Annahmen treffen, die wir für den Anfang als “die Wahrheit” betrachten.
  • User labs beauftragen.
  • Measurements weit vor ihre Auswertung einzubauen ist ok, bricht nicht mit dem Konzept “Jedes Feature muss Business Value haben” – auch wenn der echte Business Value erst in 2 Jahren auswertbar ist.
  • Aha-Effekt: In der Welt von Business Teams gibt es keine Fachabteilung. Ich bin in dem Reporting-Team ergo ich bin die Fachabteilung. (finde ich gut, häßliches Wort  😎 )

Stolperfallen mit React

  • unser Internationalisierungskonzept ist richtig (Texte aufteilen nach Modulen/Bereiche/o.ä., ein common Bereich, alles via API in den State laden)
  • Package-Empfehlung: react-intl
  • das Thema so früh, wie möglich berücksichtigen, später kann es richtig weh tun.
  • DevTool-Empfehlung: https://github.com/crysislinux/chrome-react-perf um die Performance der einzelnen React-Componenten zu sehen.
  • (es)Linting Empfehlung um zirkuläre Referenzen zu vermeiden:  “import/no-internal-modules” (Danke @kjiellski)

Wann kann Scrum funktionieren

  • wenn die Möglichkeit besteht, auf Feedback zu reagieren, sprich die Entwickler sind keine Resourcen sondern kreative Menschen.
  • das Team, in dem ich die Ehre habe, unser Produkt mitzugestallten, und @cleverbridge ist führend was agiles Arbeiten betrifft.

Menschen

  • man kann bei Trinkspielen mitmachen, ohne zu trinken
  • nachts träumen, dass der Partner einen enttäuscht hat und danach den ganzen Tag sauer auf ihn sein, ist eine Frauen-Sache (bestätigt von @AHirschmueller und @timur_zanagar) 😀

Nachtrag: fast vergessen, dass

  • wir dank @agross eine super wertvolle Session über dotfiles hatten
  • DDD wird gerade durch Zertifizierung kaputt gemacht, Serverless durch Hype
  • mit der Session von @a_mirmohammadi über/zu den Anonymen Abnehmer ist der @devopenspace eindeutig in die Kategorie “es gibt nichts, was nicht geht” angekommen

AIT: WiX Heat XSL Transformation

Mit Hilfe von Heat lässt sich die Fragmenterzeugung, welche ein Hauptbestandteil eines WiX Installers ist, automatisieren. Dies wurde bereits im Beitrag Automatische Fragmenterzeugung mit Heat gezeigt. Was aber, wenn die ein oder andere Datei im Installationsvorgang nicht kopiert werden soll oder der Component bzw. dem File noch Attribute hinzugefügt werden müssen? Das erzeugte Fragment manuell zu verändern ist nicht sehr ratsam, da dies bei jedem Durchlauf von Heat überschrieben wird.
Hier kommen XSL Transformationen zum Einsatz, welche dem Heat Vorgang angehängt werden können. Mit Hilfe einer solchen Transformation lässt sich die automatisierte Fragment Datei abschließend bearbeiten.

Im oben genannten Beitrag wurde bereits die Möglichkeit der Filterung kurz angesprochen. Mit Hilfe von XSL Transformationen können jedoch nicht nur Filter realisiert werden, sondern, wie der Name bereits sagt, auch ganze Transformationen vollzogen werden. Um jedoch Filterdateien selbst erzeugen zu können, bedarf es weiterer Erklärung.

XSLT, Extensible Stylesheet Language Transformation, ist um XML-Dokumente zu transformieren. Zwar besitzen die von Heat erzeugten Dateien die Endung .wxs sind aber gewöhnliche XML-Dokumente und können daher mit Hilfe von XSLT transformiert werden. Aber Vorsicht! WiX unterstützt leider nur XSL Version 1.0.

Im Folgenden werden Transformationen anhand von zwei Beispielen erläutert, um noch tiefer in die Thematik einzusteigen empfiehlt es sich die offizielle Dokumentation von XSLT 1.0 anzusehen. Das ganze Beispiel kann unter https://github.com/JohBa/WiXSamples/tree/master/HeatTransformation eingesehen werden.

Um eine Transformation anzuwenden erzeugen wir zunächst eine einfache XML Datei, die wir transform nennen. Um nicht nur eine leere XML Datei zu erzeugen, wird als erstes ein sogenannter identity transform angewendet, um die Sourcedaten in unsere Zieldaten zu übertragen. Dazu wird folgender Code benutzt.

Identity Transform

Zunächst wenden wir template match an und übergeben @*|* um jedes Attribut (@*) und jedes Element (*) zu matchen. Innerhalb dieses templates wird copy auf die Attribute und Elemente angewendet, wodurch zunächst der komplette Inhalt kopiert wird. Um Einrückungen für die Lesbarkeit zu erhalten wird das output Element mit Attributen indent und method verwendet.

Dateien herausfiltern

Nun können wir beginnen einzelne Dateien herauszufiltern. Um ein File mit seiner Component aus dem Fragment zu entfernen sind im Grunde drei Zeilen notwendig.

Datei filtern

In der ersten Zeile wird ein Key erzeugt, der einen match auf unser File durchführt. Dazu suchen wir in unseren Components, gehen tiefer in das File Element und suchen letztendlich im Source Attribut nach einem Teilstring (contains). Dieser ist im vorliegenden Beispiel unnecessary.xml. Mit use=“@Id“ speichern wir die Id des Files zwischen. Nun wollen wir die Component entfernen, dazu wird ein einfaches template angewendet. Im match Attribut suchen wir nun in den Komponenten nach dem zuvor gesicherten Key mit der entsprechenden Id. Da, im durch Heat erzeugten Fragment, jeweils ein Component sowie ein ComponentRef erzeugt werden, muss das selbe Template auf die ComponentRef Elemente angewendet werden.

Sollen mehrere Dateien ignoriert werden können wahlweise alle drei Zeilen kopiert und angepasst werden oder lediglich das key Element. Hierbei muss das match Attribut angepasst werden, das name Attribut des Keys muss jedoch identisch bleiben.

Im Beispiel wird contains verwendet, da es für viele Fälle ausreicht. Jedoch reicht diese Funktion in manchen Fällen nicht mehr, bspw. bei Dateien wie myApp.exe.config. Soll nun mit Hilfe von contains myApp.exe gefiltert werden, wird gleichzeitig auch myApp.exe.config gefiltert, da hier auch der Teilstring vorhanden ist. Hier wäre die Funktion ends-with hilfreich, leider gibt es diese in XSL 1.0 jedoch noch nicht. Wir können aber die Funktion substring verwenden um dies zu realisieren.

Ends with in XSL 1.0

Mit Substring extrahieren wir einen Teilstring aus dem Source Attribut. Dazu subtrahieren wir von der Gesamtlänge unseres Source Strings unseren gesuchten String und addieren 1.

Attribute hinzufügen

Gelegentlich kann es vorkommen, dass ein Attribut einem File Element hinzugefügt werden muss. Soll bspw. eine bestimmte Datei nur als Read-Only Datei installiert werden, kann dies ebenfalls realisiert werden.

Read Only Attribut hinzufügen

Zunächst verwenden wir wieder ein template mit match auf alle File Elemente und filtern hier mit Hilfe von contains das Source Attribut auf die Files welche im Source den Wert readonly.txt besitzen.

Um das Element zu erhalten, wird, ähnlich wie beim identity transform, copy in Verbindung mit apply-templates verwendet. Nun haben wir das betreffende Elemente zunächst lediglich kopiert. Um dem Knoten noch ein Attribut hinzuzufügen verwenden wir das XSL attribute Element. Über das name Attribut geben wir den Namen des hinzuzufügenden Attributs hinzu und können anschließend den Wert bestimmen.

Das beispielhafte Resultat ist im Folgenden zu sehen.

Read Only Resultat

 

Fazit

Manchmal reichen einfache Heat Vorgänge nicht mehr aus, um Fragmente für WiX Installationsroutinen zu erzeugen. Mit XSL Transformationen besitzt man jedoch die Möglichkeit die Automatisierung beizubehalten und gleichzeitig individuelle Modifikationen auf das erzeugte Fragment auszuführen.

Uli Armbruster: Workshop: Conquer your Codebase – Bewährter Clean Code aus der Praxis (Materialien)

Einen herzlichen Dank an alle Teilnehmer des Workshops am vergangenen Freitag beim Developer Open Space 2017. Trotz des völlig unterschiedlichen Backgrounds – von Ruby, über PHP, zu Java oder gar nicht objektorientierte Sprachen wie JavaScript – war ebenso alles vertreten wie vom Azubi bis hin zum Entwickler mit 20-jähriger Berufserfahrung.

IMG_20171013_132904

Einer von vielen mutigen Freiwilligen

Den Code zur Super Mario Kata gibt es hier. Beachtet die neuen Anforderungen (9-12), die ich auf dem Heimweg im Zug noch hinzugefügt habe. Damit einhergehend habe ich noch ein Refactoring des Konzepts ‚Leben‘ durchgeführt, sodass keine Actions bzw. Funcs mehr an die Methoden übergeben werden müssen. Gleichfalls fällt das Branching-Statement raus und es ergibt sich eine nahezu völlig flexible Möglichkeit zur Erstellung von Spielmodi. Die Tests sind nun ebenfalls alle umgesetzt, was wir gegen Ende hin aufgrund von Zeitmangel ausgelassen haben. Eine Testmethode hat in der Regel eine Zeile und wie schon im Workshop erwähnt: Was gut zu testen ist, ist in der Regel auch eine saubere Lösung.

IMG_20171013_132938

20 Teilnehmer mit unterschiedlichen Backgrounds

Derjenige, der noch eine Lösung mit dem Command-Pattern umsetzt und dadurch das Anpassen bestehender Klassen völlständig vermeidet, erhält von mir einen Gutschein für unsere Trainings. Damit kann er kostenlos an jedem beliebigen 3-tägigen Workshop in unseren Karlsruher Büros teilnehmen (Fahrt- und Übernachtungskosten sind ausgeschlossen).

Alle, die über den Workshop bloggen oder twittern, erhalten darüber hinaus noch einen 30% Rabattcode. Einfach Link schicken, dann kriegt er diesen per Mail.

tweet-workshop

Ein Teilnehmer versucht sich in einer Lösung mit Java statt C#

Weiterführende Links

  • Das erwähnte Video zu Enumeration mit Verhalten könnt ihr hier anschauen.
  • Danke an Tim für den Link zum Case Converter für Visual Studio.
  • Außerdem lege ich euch die Reactive Extensions ans Herz, die es für unterschiedliche, gängige Programmiersprachen gibt.
  • Git Snippet
  • Wer noch ein wenig üben möchte, kann dies mit der erweiterten FizzBuzz Kata tun.
  • Blog Post über die Migration von NHibernate zu EntityFramework in 3 Tagen.

 

Demnächst geht ein Video mit dem theoretischen Teil (Why-How-What) online, in dem ich nochmal die Zusammenhänge zw. „schlechtem Code“ und den Gründen dafür erläutere. Wer automatisch informiert werden will, wenn es veröffentlich wird, abonniert einfach meinen Blog oder schickt mir eine Nachricht.

 

 


Einsortiert unter:Architecture, Development, Events, German Tagged: Clean Code, Open Space, Workshop

Golo Roden: DDD und wolkenkit - live!

In dieser Woche finden verschiedene Veranstaltungen wie Meetups und Konferenzen statt, auf denen es um Domain-Driven Design und das wolkenkit geht. Im Folgenden ein kurzer Überblick für alle Interessierten.

AIT: Neu in TFS 2018: Variable Groups für das Release Management

Wer für große Umgebungen im Release Management bereits Variablen verwalten musste, weiß wie umfangreich diese werden können. Auch kann es vorkommen, dass Variablen über verschiedene Release Definitionen wiederverwendet werden. Dafür gibt es jetzt mit TFS 2018 Abhilfe in Form von Variable Groups. Eine Variable Group enthält dabei verschiedene Variablen. Diese können entweder im Klartext oder verschlüsselt abgelegt werden, wie man es aus einer Release Definition gewohnt ist. Somit erhält man eine Sammlung von Variablen, die später in einer Release Definition verwendet werden können.

Der Vorteil ist, dass man bei Änderung der Werte nur die Variable Group an einer zentralen Stellen anpassen muss (siehe Abbildung 1). Auch das Thema Sicherheit spielt hier eine wichtige Rolle. Denn wer eine Release Definition anlegt, hat noch lange nicht Zugriff auf die Passwörter und andere verschlüsselte Daten. In dem Fall können ausgewählte Personen mit Administrators-Berechtigung die Variable Group anpassen, Passwörter hinterlegen und Personen mit Users-Berechtigung können die Variable Group in ihren Release Definitionen verwenden. Somit kann ein neuer Releaseprozess einfach aufgesetzt werden, ohne dass der Ersteller direkt Zugriff auf alle Schlüssel und Passwörter haben muss.

image

Abbildung 1: Variable Group Web Dev

Verknüpfen einer Release Definition mit einer Variable Group

Um einer Release Definition eine oder mehrere Variable Groups hinzuzufügen, können ab TFS 2018 im Reiter Variables, zusätzlich zu den eigenen Variablen, jetzt auch Variable Groups verknüpft werden (siehe Abbildung 2). Durch die Verknüpfung werden automatisch alle Änderungen in der Variable Group auch mit in die Variablen der Release Definition übertragen und alle Variablen der Variable Group können innerhalb der Release Definition verwendet werden. Die Variablen sind dann für alle Environments in der Release Definition verfügbar.

Durch die Möglichkeit beliebig viele Variable Groups zu verknüpfen, kann man hier auch die Trennung der Variablen sehr feingranular definieren. Am Ende muss jedoch jeder für sich selbst entscheiden, welche Granularität für die Variable Groups angewendet wird, um möglichst eine große Wiederverwendbarkeit zu erreichen.

Wichtig ist, eine Konvention für die Namensgebung der Variablen festzulegen. Die Variablen gleich zu benennen in unterschiedlichen Variable Groups ergibt Sinn, wenn man sich für eine dieser Gruppen in der Release Definition entscheiden muss. Wenn Variable mit dem gleichen Namen in unterschiedlichen Variable Groups eingebunden werden, so entscheidet, die Reihenfolge, in welcher die Variable Groups verknüpft wurden.

Variable Groups mit einzelnen Environments zu verknüpfen, ist aktuell nicht möglich. Variable, die nur in einer bestimmten Umgebung Verwendung finden, können über ein Prefix oder Suffix erkenntlich gemacht werden. So kann man beispielsweise den Application Insights Key für alle Development-Umgebungen als AppInsightsKeyDev ablegen, um direkt zu erkennen, für welche Umgebung dieser gedacht ist.

image

Abbildung 2: Verknüpfen einer Variable Group mit einer Release Definition

Verknüpfen eines Azure Key Vault mit einer Variable Group

Ein kleiner Vorgeschmack was die Zukunft bringt, bietet das VSTS-Feature Link secrets from Azure key vault (siehe Abbildung 3). Mit dieser Option können in einer Variable Group Variable aus einem Azure Key Vault verknüpft werden. Dadurch liegen Passwörter nicht mehr im TFS oder in VSTS sondern werden in einem Azure Key Vault verwaltet. Die Vorteile hiervon sind die Sicherheit der abgelegten Passwörter und die Möglichkeit, die Verwendung der Passwörter zu überwachen.

Variable group with Azure key vault integration

Abbildung 3: Verknüpfen eines Azure Key Vault mit einer Variable Group

Holger Schwichtenberg: Video zur PowerShell Core 6.0 auf Windows, Linux und Mac

Die Aufzeichnung eines Dotnet-Doktor-Vortrags von der CIM Lingen 2017 gibt es bei YouTube zu sehen.

MSDN Team Blog AT [MS]: Microsoft Teams Envisioning Workshop mit dem Produktteam

Gemeinsam mit dem Produktteam aus den USA bieten wir Kunden und Partnern die Möglichkeit die Produktgruppe von Microsoft Teams persönlich in Wien kennenzulernen. Am Montag den 30. Oktober findet bei uns im Büro ein Microsoft Teams Envisioning Workshop statt wo sich interessierte Kunden und Partner über die Roadmap von Microsoft Teams erkundigen können.

Diese Ganztagsveranstaltung ist eine tolle Gelegenheit sich mit technischen Experten aus der Microsoft Teams Produktgruppe persönlich zu vernetzen, die Erweiterbarkeit von Microsoft Teams kennenzulernen und sich über Ressourcen zu bzw. die Roadmap von Microsoft Teams zu informieren.

Anmeldeseite: Anmeldung zum Microsoft Teams Envision Workshop

Wer sollte teilnehmen?

  • Technische Entscheidungsträger die in Ihrer Firma die technologische Roadmap definieren und die Richtung der Produktentwicklung bestimmen
  • Solution Architects welche die Möglichkeiten der Integration von Teams näher beleuchten wollen
  • Entwicklungsleiter die Teams kennenlernen und Ihre Entwicklerressourcen entsprechen planen wollen

Was Kunden und Partner aus der Veranstaltung mitnehmen können

  • Ein Verständnis für Microsoft Teams, wie es in die Office 365 Platform paßt und welchen Wert es für sie selber bzw. ihre Kunden bietet
  • Wissen über die Microsoft Teams Erweiterungsmöglichkeiten, und wie sie Ihre eigenen Anwendungen dafür entwickeln können.
  • Details zur Microsoft Teams Roadmap, insbesondere im Zusammenhang mit der “Skype for Business Ankündigung“
  • Einen persönlichen Kontakt zur Microsoft Teams Produktgruppe und den Ingenieuren / Entwicklern

Was Kunden und Partner von uns erwarten können:

  • Tiefgreifende Informationen: Wir helfen Ihnen das Potential von Microsoft Teams zu erkennen, welche Ressourcen Sie zum Entwickeln eigener Anwendungen benötigen und die Unterstützung, die wir Ihnen dabei geben können
  • In dieser Veranstaltung wird (noch) nicht geocoded. Es handelt sich hier um einen ersten Schritt in Richtung ihrer eigenen Anwendung.
    In weiterer Folge können wir mit Ihnen eine Lösung im Detail planen und danach auch gemeinsam mit Microsoft Software Ingenieuren ein Hackfest durchführen.

Was Kunden und Partner mitbringen sollten

  • Ihre Fragen und Interessen – Wie kommen Sie mit der Microsoft Teams Erweiterungs-Plattform zurecht?
  • Ihre Erfahrung – lassen Sie uns Ihre Einstellung zu Microsoft Teams und zur Erweiterungs-Plattform wissen.
  • Ehrlichkeit – Lassen Sie uns über alles reden. Was Ihnen gefällt und auch was nicht.

Agenda (Die Vorträge finden in englischer Sprache statt):

Mo. 30.10., 09:00 – 16:00

  • 09:00 - Eintreffen und Kennenlernen der Teilnehmer, Möglichkeit für individuelle Gespräche
  • 10:00 - Overview of the Teams platform
    • Teams background and customer value
    • Teams functionality (demo)
    • Teams/Skype for Business convergence
  • 11:00 – Overview of Teams extensibility options
    • Making your app shine on Teams via Tabs, Bots Connectors, Compose Extensions
    • Office store submission process
  • 12:00 – Real life cases
  • 13:00 – Mittagspause
  • 14:00 – Office 365 Developer Platform and Microsoft Graph
  • 15:00 – Next steps, resources available

Zusätzlich und Ergänzend zum Microsoft Teams Envisioning Workshop am Montag den 30. Oktober in Wien findet in Kooperation mit den deutschen Kollegen in der Woche vom 6. - 9. November ein Microsoft Teams Hackfest in München statt. Bei diesem Hackfest können Kunden und Partner gemeinsam mit dem Microsoft Ingenieuren Ihre eigenen Microsoft Teams Erweiterungen entwickeln und in den Store stellen.

Martin Richter: Sicherheitsupdates von Microsoft führen zu Problemen mit dem ODBC Export nach Excel

Eigentlich habe ich nichts gegen Sicherheitsupdates. Genaugenommen bin ich ein Verfechter, dass Sicherheitsupdates sofort und umgehend installiert werden sollen.

Eigentlich ging das die letzten Jahre bei unserer Software ziemlich gut. Aber heute hat es uns voll erwischt. Dazu auf allen Plattformen von Windows 7, Windows 8.1 bis Windows 10.

Es kommt jetzt beim Anlegen einer Excel Datei über ODBC zu einer Fehlermeldung in der Form:

Reservierter Fehler (-5016); es gibt keine Meldung für diesen Fehler.
Ungültiges Attribut für die Verbindungszeichenfolge. CREATE_DB
Ungültiges Attribut für die Verbindungszeichenfolge. CREATE_DB
Ungültiges Attribut für die Verbindungszeichenfolge. CREATE_DB
Ungültiges Attribut für die Verbindungszeichenfolge. CREATE_DB
Allgemeine Warnung Registrierungsschlüssel ‚Temporary (volatile) Jet DSN for process 0x2c44 Thread 0x37f4 DBC 0x5b84d54 Excel‘ kann nicht geöffnet werden.
Ungültiges Attribut für die Verbin

Aktuell kann ich die Ursache nur in den folgenden Windows Updates sehen:

Windows 7 KB4041681
Windows 8.1 KB40416393
Windows 10 KB4040724
KB4041676

Einen entsprechenden Anfrage an andere Entwickler habe ich über Stackoverflow gestellt.

Als exMVP oder rMVP hat man jedoch nicht mehr die schönen Kanäle von früher… <seufz/> 🙁

Ich frage mich, wie solche Fehler durch eine Qualitätskontrolle schlüpfen können…?


Copyright © 2017 Martin Richter
Dieser Feed ist nur für den persönlichen, nicht gewerblichen Gebrauch bestimmt. Eine Verwendung dieses Feeds bzw. der hier veröffentlichten Beiträge auf anderen Webseiten bedarf der ausdrücklichen Genehmigung des Autors.
(Digital Fingerprint: bdafe67664ea5aacaab71f8c0a581adf)

MSDN Team Blog AT [MS]: Connect(); 2017

Neben der BUILD Konferenz ist die Connect(); die zweite wichtige Konferenz für Cloud & Software Entwicklungsthemen bei Microsoft.

Die Connect(); 2017 wird von 15. bis 17 November stattfinden - nehmen Sie online Teil und erfahren Sie direkt vom Microsoft Azure und Visual Studio Produktteam die neuesten Entwicklungen und Industrietrends.

"Save the Date" für Ihren Kalender.

AIT: Neu in TFS 2018: Secure Files Library

In unserer Blog-Serie Neu in TFS 2018 wurden bereits Änderungen und auch Neuerungen präsentiert. In die Kategorie neuer Features reiht sich die Secure Files Library ein.

Secure Files Library

Bisher ließen sich im Build-Prozess ausschließlich die hinterlegten Variablen wie z.B. Passwörter verschlüsselt ablegen und waren ausschließlich im Build- und Release-Prozess verfügbar. Mit der Einführung vom TFS 2018 gibt es nun die Möglichkeit, dies auch um verschlüsselte Dateien zu erweitern. Das bietet den Vorteil, dass u.a. Signierungszertifikate und Provisierungsprofile nicht mehr in der Quellcodeverwaltung vorgehalten werden müssen.

Secure Files Library

 

Build Tasks mit Secure Files

Die hinterlegten Dateien lassen sich nun direkt in den Build-Prozess integrieren. Hierzu gibt es die zwei neuen Build Tasks: „Install Apple Certificate“ und „Install Apple Provisioning Profile“. Für die Integration in eigene Custom Build Tasks gibt es hierfür nun den neuen Input Typ secureFile.

Build Task mit Secure Files

 

Hinweis

Zu beachten gilt, dass der hinterlegte Build Agent mindestens in der Version 2.116.0 laufen muss. Zudem ist der Upload von Dateien auf 10 MB je Datei begrenzt.

André Krämer: Speicherplatz auf dem Mac optimieren für Xamarin Entwickler

Wer eine Weile auf dem Mac mit Xamarin gearbeitet hat, wird irgendwann feststellen, dass der Festplattenplatz knapp wird. Dann heißt es natürlich Aufräumen. Die Frage ist nur: Was kann weg? Bei mir war es gestern mal wieder so weit. Um herauszufinden, welche Dateien und Verzeichnisse besonders viel Platz benötigen, habe ich Daisy Disk genutzt. Das kleine Tool, das aktuell ca. 11 € kostet, zeigt übersichtlich an, welche Ordner und Dateien besonders speicherhungrig sind.

Golo Roden: DDD & Co., Teil 10: Hallo wolkenkit

Seit der vergangenen Folge ist der fachliche Code für TodoMVC vollständig. Allerdings fehlt der gesamte technische Rahmen, der die Funktionalität über eine REST- und WebSocket-API anbietet, die fachlichen Ereignisse persistiert und die Anwendung bei Bedarf skaliert. Das Open-Source-Framework wolkenkit schafft Abhilfe.

Manfred Steyer: Meine Unterlagen von den Angular Days in Berlin, Oktober 2016

Diese Woche habe ich drei Workshops auf den Angular Days in Berlin gemacht. Nachfolgend finden sich die Unterlagen dazu:

AIT: Neu in TFS 2018: Task Groups für Build und Release

Mit TFS 2015 wurde ein komplett neues Build- und Releasemanagement-System eingeführt. Über einen Teil der enthaltenen Neuerungen, wie z.B. das Importieren und Exportieren von Builddefinitionen konnten Sie bereits in vorhergehenden Beiträgen unserer Blogserie lesen. In diesem Blogpost möchten wir Ihnen nun einen weiteren großen Schritt vorstellen, den Microsoft im Ausbau des neuen Systems geht: Task Groups.

Jede Build- und jede Releasedefinition besteht aus einer Menge an Tasks, welche nacheinander ausgeführt werden. Jeder dieser Tasks definiert dabei eine auszuführende Aktion, wie z.B. das Bauen einer Anwendung, das Ausführen von Tests, u.v.m. In vielen Fällen wird die gleiche Abfolge an Tasks in mehreren Build- oder Releasedefinitionen verwendet um z.B. firmenspezifische Abläufe abzubilden, und unterscheidet sich dabei nur durch die Parameterwerte, welche als Input an den einzelnen Tasks spezifiziert werden. In diesem Fall bieten Task Groups eine einfache Möglichkeit, die Definition und Eigenschaften von solchen Abfolgen zentral zu verwalten. Task Groups fassen also eine Reihe von Tasks zusammen und stellen diese dann als einen einzigen, wiederverwendbaren Task den Build- und Releasedefinitionen zur Verfügung. Dies birgt folgende Vorteile:

  • Zentralisierung von wiederkehrenden Abläufen
  • Verringerung von Redundanzen
  • Änderungen an Task Groups werden auf alle Definitionen angewendet, welche die Task Group referenzieren

Um eine neue Task Group anzulegen, kann innerhalb einer Build- oder Releasedefinition eine Abfolge an Tasks ausgewählt werden und anschließend im Kontextmenü der Eintrag Create task group gewählt werden (vgl. Abb. 1).

SNAGHTML11d7c79f

Abbildung 1: Erstellen einer Task Group

Beim Anlegen sind folgende Punkte zu beachten:

  • Task Groups sind Team Projekt-spezifisch.
  • Für die zu erstellende Task Group muss ein Name spezifiziert werden (vgl. Abb. 2 (1)) sowie die Gruppe des Task Katalogs, in welchem die Task Group enthalten sein soll (vgl. Abb. 2 (3)). Des Weiteren kann eine Beschreibung angegeben werden. (vgl. Abb. 2 (2)).
  • Alle Parameterwerte, welche innerhalb der einzelnen Tasks verwendet werden und durch Variablen spezifiziert sind, werden automatisch auch als Variablen an der Task Group abgebildet. Der zugehörige Variablenwert wird als Default-Wert gesetzt, kann jedoch im Nachhinein noch geändert werden (vgl. Abb. 2 (4)).
  • Alle Parameterwerte, welche innerhalb der einzelnen Tasks verwendet werden und durch fest Werte (d.h. keine Variablen spezifiziert sind) werden auch als feste Werte für die Task Group übernommen. Diese fixen Werte können beim Referenzieren der Task Group nicht von außen angepasst werden.
  • Aus den beiden vorhergehenden Punkten folgt: Alle Parameterwerte, welche beim Referenzieren der Task Group veränderbar sein sollen, müssen als Variable in den enthaltenen Tasks definiert sein.

image

Abbildung 2: Eigenschaften beim Erstellen einer Task Group

Nach der Erstellung können Task Groups zentral im Task Groups-Tab des Build & Release-Hubs verwaltet und editiert werden. Jede Task Group verfügt darin vier Tabs:

  • In den Properties können die allgemeinen Eigenschaften Name, Description und Category angepasst werden. Darüber hinaus sind alle Task Group Variablen mitsamt ihrer Defaultwerte und Beschreibungen enthalten.
  • Der Tab Tasks enthält die Abfolge der Tasks. Hier können fixe Parameterwerte zu Variablen geändert werden, neue Tasks hinzugefügt werden, …
  • Im Tab History können alle Änderungen, welche an der Task Group vorgenommen wurden, nachverfolgt und untereinander verglichen werden (vgl. Abb. 3).
  • Der Tab References enthält die Liste alle Build- und Releasedefinitionen sowie alle Eltern-Task Groups, welche die Task Group referenzieren.

image

Abbildung 3: Änderungsnachverfolgung in Task Groups

Der History-Tab einer Task Group bietet schon einige Sicherheit bei Änderungen. Da sich Änderungen an einer Task Group jedoch sofort in allen Build- und Releasedefinitionen durchschlagen ist das Risiko von unerwünschten Effekten immer noch relativ hoch. Dies kann durch die Verwendung von Versionierung weiter reduziert werden: Änderungen an Task Groups können zunächst als Draft abgespeichert werden (vgl. Abb.4 (1)). Damit kann die letzte stabile Version zunächst weiter in den bestehenden Prozessen verwendet werden und die Änderungen nur in ausgewählten Definitionen getestet werden. Nach erfolgreichem Testen der Änderungen können diese dann in die ursprüngliche Task Group gepublished werden (vgl. Abb. 4 (2)). Änderungen, welche nicht abwärtskompatibel sind, können dabei als Preview gepublished werden. Dies erzeugt eine neue Version der Task Group. Damit können verschiedene Versionen einer Task Group zur selben Zeit im Einsatz sein. Die Preview-Version kann dann zu einem späteren Zeitpunkt wiederum als offizielle neue Version gepublished werden.

image

Abbildung 4: Versionierung von Task Groups via Drafts

Abgerundet wird das Konstrukt durch die Möglichkeit Task Groups zu exportieren (vgl. Abb. 5 (1)) und Importieren (vgl. Abb. 5 (2)). Oftmals werden Änderungen an Prozessen zunächst in einer separaten Testinstanz durchgeführt und getestet. Es existieren auch Build- und Releaseabläufe, welche über den Team Projekt-Kontext hinweg gleich sind. Durch den Export und Import von Task Groups entfällt in solchen Szenarien die Notwendigkeit dieselben Änderungen an verschiedenen Stellen machen zu müssen und eliminiert damit auch das Risiko von Fehlern beim manuellen Übertragen von Änderungen.

image

Abbildung 5: Export und Import von Task Groups

Fazit

Das Konzept von Task Groups bietet eine schöne und durchdachte Möglichkeit wiederkehrende Abfolgen in Build- und Releasedefinitionen zentral zu definieren und zu verwalten. Das mit TFS 2015 neu eingeführte System macht damit einen weiteren großen Schritt auf dem Weg zum Erwachsenwerden.

Weitere Schritte auf diesem Weg stellen wir Ihnen auch in nachfolgenden Beiträgen unserer Blogserie vor. Bleiben Sie also dran und freuen Sie sich auf spannende Neuerungen mit TFS 2018.

Golo Roden: Einführung in React, Folge 2: Ein tieferer Einblick

React basiert auf vielen Konzepten der funktionalen Programmierung. Besonders wichtig ist die Unveränderlichkeit von Datentypen, die in React die Grundlage für das effiziente Rendern der Anzeige bildet. Wie funktioniert das für eigenen Code, und worauf gilt es in JSX außerdem zu achten?

AIT: Berechtigungen für Fortgeschrittene – Berechtigungen in der Quellcode- verwaltung für Admins einschränken

Bei Entwicklungsteams, welche im stark regulierten Umfeld tätig sind, entstehen an das Berechtigungskonzept für die Quellcodeverwaltung aus diversen Gründen spezielle Anforderungen. Eine Anforderung aus diesen Umfeld lautet beispielsweise:

Ist es möglich einem Teil der TFS-Administratoren des Leserecht auf den Quellcode in einem besonders zu schützenden Bereich der Quellcodeverwaltung zu entziehen?

Die Kurzfassung der Antwort lautet: Ja, es ist möglich. Kommt noch der Faktor Revisionssicherheit der Lösung hinzu, dann müssen noch zusätzliche Schritte eingeplant werden.

Zu Beginn steht die Frage im Raum: Git oder Team Foundation Version Control (TFVC)? Für das beschriebene Szenario ist Git weniger gut geeignet, da hier nur eine Berechtigungsvergabe auf das komplette Repository möglich ist. TFVC hingegen unterstützt diverse Berechtigungsarten und eine feingranulare Steuerung bis auf Dateiebene herab.

Im Folgenden wird die Umsetzung der eingangs genannten Anforderung Schritt für Schritt auf Basis von TFVC beschrieben.

Um die Berechtigungen für den zu schützenden Quellcode-Ordner einzugrenzen, wird im ersten Schritt die einzugrenzende TFS‑Berechtigungsgruppe (z.B. TFS_Admins_Deny) hinzugefügt (siehe Screenshot 1).

Als nächster Schritt wird dieser Gruppe dann das Leserecht explizit verweigert (siehe Screenshot 2)

Mit einem „Verweigern“(Deny) werden den Mitgliedern einer Gruppe die Rechte explizit entzogen, auch wenn sie an anderer Stelle (z.B. durch eine andere Gruppe) gegeben wurden. Es gilt der Grundsatz: Verweigern ist stärker als zulassen.

Ein Sonderfall sind die Gruppen „Team Foundation Administrators“ und „Project Collection Administrators“. Diese Gruppen haben grundsätzlich automatisch überall in der Quellcodeverwaltung das Leserecht.

Für TFS Admin-Gruppen gilt das explizite Verweigern in den meisten Bereichen des TFS nicht. Es wird damit verhindert, dass sich Administratoren selbst aussperren können. Von dieser Regelung gibt es aber Ausnahmen. Eine dieser Ausnahmen betrifft die Quellcodeverwaltung. Es ist sozusagen die Ausnahme von der Ausnahme.

In version control permissions, explicit deny takes precedence over administrator group permissions.” Quelle: https://www.visualstudio.com/de-de/docs/setup-admin/permissions#tfvc-permissions-object-level

Die Folge ist deshalb, dass ein Administrator als Mitglieder der TFS Gruppe TFS_Admins_Deny kein Read-Recht auf den schützenswerten Quellcode-Ordner hat.

Im Fall von z.B. Anwendersupport, kann ihm aber das Leserecht auf den Quellcode, kurzfristig wieder gewährt werden. Eine Möglichkeit wäre, den Administrator temporär aus der Gruppe TFS_Admins_Deny zu entfernen.

Damit ist die Hälfte der Anforderung umgesetzt. TFS Administratoren können tatsächlich aus der Quellcodeverwaltung ausgeschlossen werden. Das ist aber noch nicht revisionssicher, da ein eingeschränkter Administrator jederzeit wieder der TFS-Gruppe das Read-Recht geben oder die Gruppenmitgliedschaft ändern kann.

Es gibt zwei Möglichkeiten die fehlende Anforderung umzusetzen. Die zwei Möglichkeiten sind in nachfolgender Tabelle dargestellt:

Legende:

  1. Bei der ersten Lösung werden alle Administratoren der TFS-Gruppe TFS_Admins_Deny hinzugefügt. Dieser Gruppe muss das Read-Recht auf den zu schützenden Quellcode verweigert werden.
  2. Bei der zweiten Lösung wird auch die Gruppe TFS_Admins_Deny erstellt, aber nur die Limited-Administrators hinzugefügt. Dieser Gruppe muss auch das Recht „Manage permissions“ verweigert werden. Es wird noch eine weitere Administratoren Gruppe benötigt, die TFS_Limited_Admins. Dieser Gruppe wird der entsprechende Personenkreis hinzugefügt und alle Rechte wie der originalen Gruppe Team Foundation Administrators gegeben, bis auf die Rechte „Edit collection-level information“ und „Edit project-level information“. Im Anschluss werden alle Benutzer der TFS_Limited_Admins aus der Gruppe Team Foundation Administrators entfernt. Mit dieser Lösung ist sichergestellt, dass beide Personenkreise die benötigten Berechtigungen für die tägliche Arbeit besitzen und mit minimalem Aufwand auch für den geschützten Quellcodebereich temporär berechtigt werden können.

Für die erste Lösung ist es unabdingbar, dass Berechtigungsänderungen und Änderungen der Gruppenmitgliedschaften protokolliert werden. Nur dann kann nachvollzogen werden, wer wann wem welches Recht eingeräumt hat. Dies lässt sich nicht mit Board-Mitteln bewerkstelligen. Für diese Anforderung ist es notwendig eine serverseitige TFS-Erweiterung zu entwickeln. Die Sicherheits-Events müssen am serverseitigen Eventhandler (TFS Requestfilter) über die TFS API revisionssicher in einer extra Datenbank protokolliert werden.
Bei der zweiten Lösung ist eine Protokollierung der Gruppenmitgliedschaften nicht zwingend erforderlich. „Echte“ Administratoren besitzen hier sowieso nur noch als einzige das Recht Berechtigungen ändern zu dürfen und verfügen aufgrund des TFS Designs sowieso über einen Vollzugriff auf alle TFS Daten.

Das besprochene Szenario kann man noch erweitern. Am Ende dieses Blogposts soll dies aber lediglich als Anregung dienen: Unabhängig ob die Lösung 1) oder 2) gewählt wurde bleibt noch die Frage offen:

Auf welche Teile des Quellcodes haben eingeschränkte Administratoren während ihres Anwendersupportfalls zugegriffen?

An diesen Stellen bietet sich auch wieder der Weg über die TFS API in Kombination mit serverseitigen Eventhandler (TFS Requestfilter) an, damit die entsprechenden Zugriffe protokolliert werden können. Dies ist hier schon fast zwingend notwendig, damit das ganze Szenario rund wird und die Protokollierung lückenlos und durchgängig ist.

Fazit

Es ist mit ein paar Handgriffen möglich Administratoren aus definierten Bereichen der Quellcodeverwaltung (TFVC) auszuschließen. Die notwendigen Zugriffe lassen sich sowohl bei der Rechtevergabe, als auch beim Zugriff der Quellcodeverwaltung protokollieren. Der Aufwand darf nicht unterschätzt werden, da für einige Teile der Lösung eigene Erweiterungen (serverseitiger TFSRequestfilter) geschrieben werden müssen.
Unabhängig von dem aktuellen Blog-Post sollte bei dieser extremen Art von Anpassungen immer kritisch hinterfragt werden, ob der Aufwand in einem angemessenen Verhältnis zum Schutzbedürfnis steht. Anpassungen können schnell zu neuen Problemen, erhöhten Aufwänden für andere Anpassungen (Bsp. Builds) und unnötigen Fehleranalysen führen.
Für ein umfassendes Sicherheitskonzept ist die Problemstellung aus diesen Blog-Post nur ein kleiner Baustein einer Sicherheitsarchitektur. Weitere Themenfelder für eine solche Architektur und ungewollte Zugriffe auf TFS Informationen sind exemplarisch: direkter Remotezugriff auf den Server via Remote Desktop, bekannte Servicekonten und -Passwörter oder direkter Datenbankzugriff.

Der Nutzen von einem Sicherheitstor bleibt schnell auf der Strecke, wenn links und rechts davon nur ein gewöhnlicher Gartenzaun um das Haus gebaut wurde.

Uli Armbruster: Workshop: Conquer your Codebase – Bewährter Clean Code aus der Praxis

Am Developer Open Space 2017 halt ich einen 1-tägigen Workshop zu obigem Thema. In reduzierter, kompakter Form werde ich dazu bewährte Inhalte aus meinem 3-tägigen Seminar nehmen und die Ursachen für folgende Probleme adressieren:

  • Unverständlicher bzw. schlecht wartbarer Code
  • Bugs
  • Skalierungsprobleme
  • Go Live Probleme
  • Verpasste Deadlines und lange Entwicklungszeiten

 

Wir werden uns anschauen wie es dazu kommen kann, z.B. weil

  • die Infrastruktur nicht wiederverwendbar ist,
  • die Domänenlogik nicht erweiterbar ist,
  • eine falsche Nutzung der API möglich ist,
  • der Code nicht ausdrucksstark ist,
  • oder starke Abhängigkeiten bestehen.

 

Wir werden das Open Closed Principle genauer besprechen und Seperation of Concerns am konkreten Beispiel umsetzen. Speziell für Freunde der Objektorientierung werde ich je nach verfügbare Zeit praktische Lösungen zur Vermeidung von If-Else-Zweigen und NULL-Checks zeigen.

 

Ein Laptop mit Visual Studio oder Visual Studio Code und .NET 4.6 wären wünschenswert. Prinzipiell ist der Workshop aber für alle Entwickler des objektorientierten Paradigmas geeignet, da bis auf Delegaten (Action/ Func) und Erweiterungsmethoden kaum Sprachspezifika verwendet werden. Darüber hinaus können Teilnehmer auch ohne Hardware beiwohnen, weil wir beim Live Coding am Präsentations-PC mit Code Monkey Runden arbeiten werden.

Gerne dürfen die Teilnehmer mir vorab Fragen und Probleme z.B. hier in Form von Kommentaren oder per E-Mail zukommen lassen.


Einsortiert unter:Architecture, Development, Events, German Tagged: Clean Code, Open Space, Workshop

Uli Armbruster: Git History Commit Redos für Workshops

Mit diesem Snippet, das ich in meinen Workshops verwende, könnt ihr die Commits eines Branches vom ersten bis zum letzten Interaktiv durchsteppen, um so jede Änderung mit den Teilnehmern zu besprechen. Das ist vor allem dann nützlich, wenn das Live Coding mehr ablenkt oder die Zeit ein wenig knapp ist:

 

Beim ersten Commit gibt es noch eine kleine Fehlermeldung, da versucht wird auf den vorherigen Commit zuzugreifen, den es beim 1 Commit logischerweise nicht geben kann.

Git History Commit Redo

Git History Commit Redo- First Commit

 

Ab dem zweiten Commit werden dann sowohl die Commit Message als auch alle alle geänderten Dateien angezeigt.

Git History Commit Redo

Git History Commit Redo – Next Commit

 

Am Schluss kommt noch diese Meldung.

Git History Commit Redo

Git History Tracking – Finished

 

Beachtet bitte, dass dies nur bei einer linearen Historie funktioniert, da es sich um einen Rebase handelt und dass ihr hierfür am besten einen Test-Branch abzweigt, um nicht ggf. Änderungen noch einzubauen, die dann im Master-Branch landen.


Einsortiert unter:Development, German Tagged: Git

Golo Roden: Ein nie vollendetes Spiel

Am vergangenen Wochenende begann auf der Webseite nevercompletedgame.com ein Spiel, das die Internet-Community über zahlreiche Stunden auf Trab hielt. Was hat es mit dem Spiel auf sich, und wie lässt es sich lösen?

Robert Meyer: Git: Add .gitignore after commit

I had created a new repository in GitHub and forgot to add the .gitignore file to ignore all my Visual Studio and debugging files. However, I did not realize it until after I created the first commit.

These are the steps to apply the gitignore file later:

  1. Create a .gitignore file in the root of your local repository.
  2. Run this command. This removes everything from the index:
    git rm -r --cached .
  3. Re-add all files. Now the files and folders from gitignore are ignored.
    git add .
  4. Then commit the changes again and push it to your GitHub repository
    git commit -m ".gitignore is now working" 
    git push

AIT: Neu in TFS 2018: Kleine aber feine Neuerungen im Test Management

In der Major Version 2017 des TFS waren eine Vielzahl neuer Features und wesentliche Prozess-Änderungen für den Bereich Testing enthalten. Im Gegensatz dazu konzentriert sich TFS 2018 eher auf kleinere Optimierungen und Neuerungen für bestehende Features. Diese möchten wir Ihnen nicht vorenthalten und laden Sie daher ein, in diesem Beitrag unserer Blogserie „Neu in TFS 2018“, diese kleinen aber feinen Neuerungen näher kennenzulernen. Zudem enthält TFS 2018 eine doch etwas größere Veränderung, die wir Ihnen gleich zu Beginn erläutern wollen.

 

Umbruch für Lab Management und Ausführung von automatisierten Tests

Zusätzlich zu den sonst eher kleineren Neuerungen für den Bereich Testing gibt es doch eine wesentliche Änderung mit TFS 2018. Diese stellt einen Breaking Change für die Verwaltung von Laborumgebungen und die Ausführung von automatisierten Tests dar.

Mit dem im Microsoft Test Manager (MTM) enthaltenen Lab Management können Testumgebungen aufgesetzt und verwaltet werden. Damit ist es möglich auch komplexe Szenarien, wie z.B. eine mehrstufige Anwendung mit verschiedenen Rollen (Desktopclient, Webserver, Datenbankserver, …) oder auch die Integration von SCVMM, abzubilden.

Mit bisherigen TFS-Versionen gab es weiterhin die Möglichkeit, Test Controller am TFS zu registrieren und mit deren Hilfe automatisierte Tests in den Testumgebungen des Lab Management auszuführen. Dies konnte manuell aus MTM oder auch aus einem XAML-Build heraus initiiert werden. Diese Integration von TFS und Lab Management bzw. automatisiertem Testen im MTM wird in TFS 2018 nicht länger unterstützt. Es können also keine neuen Test Controller am TFS angemeldet werden und auch bestehende Test Controller können zusammen mit TFS 2018 nicht mehr verwendet werden. Diese Änderung ist sehr eng verknüpft mit der Abkündigung des XAML-Buildsystems. In Konsequenz entfällt damit auch die Ausführung von automatisierten Tests über den vorher beschriebenen Weg.

Lassen Sie sich von diesem Umstand aber bitte nicht davon abschrecken auf TFS 2018 zu migrieren. Zwar entfällt der gewohnte Weg, jedoch bietet TFS 2018 alternative Wege, die bekannten Ziele weiterhin zu erreichen. So kann beispielsweise die Integration von TFS und SCVMM mit der SCVMM Integration-Extension erreicht werden und auch die Ausführung von automatisierten Tests während eines Builds ist natürlich weiterhin gegeben.

 

Die kleinen Helfer für Test Management und Ausführung

Wie Sie bereits im Beitrag Neu in TFS 2018: Neues für Work Item Tracking lesen konnten, erhält die Testfallverwaltung gemeinsam mit den Ansichten des Work Item Trackings (Backlogs etc.) einen neuen Anstrich in Bezug auf die Filterung. Somit ist es nun nicht nur wie bisher möglich nach Testfeldern wie z.B. dem Ergebnis zu filtern, sondern darüber hinaus auch nach allgemeinen Work Item Feldern wie beispielsweise dem Titel und dem Status (vgl. Abb. 1). Damit können Test Cases nun noch einfacher und schneller gefunden werden.

image

Abbildung 1: Filterung von Test Cases

Auch die weiteren Neuerungen stehen ganz im Zeichen der erhöhten Übersichtlichkeit und Nachverfolgbarkeit. So ist es nun möglich im Nachgang an die Testausführung Informationen in Kommentaren von Test Runs und Test Results mit Hilfe von Markdown besser aufzubereiten. Einstiegspunkt hierfür ist zum einen die Option Update comment für ganze Test Runs und zum anderen die Option Update analysis für einzelne Test Results (vgl Abb. 2).

image

Abbildung 2: Verwendung von Markdown im Kommentar eines Test Results

Darüber hinaus war es bisher nur im MTM möglich Dateien, wie z.B. Screenshots, als Anhänge zu Test Runs und Test Results hochzuladen. Diese Option steht nun auch im Web zur Verfügung (vgl. Abb. 3). Damit beseitigt Microsoft eine weitere Hürde im Bereich Testing für den vollständigen Umstieg vom MTM auf den TFS Web Access.

Abbildung 3: Anhängen einer Datei an einen Test Run

Eine weitere Hilfe ist die neue Möglichkeit fehlgeschlagene Tests mit einem bereits existierenden Bug zu verknüpfen. Somit kann nun auch die Verbindung von fehlgeschlagenen Tests zu bereits bekanntem und dokumentiertem Fehlverhalten hergestellt werden (vgl. Abb. 4).

Abbildung 4: Verlinkung von fehlgeschlagenen Tests mit existierenden Bug

 

Verbessertes Test Reporting durch Widgets

TFS 2018 setzt einen besonderen Fokus auf den Ausbau des Build- und Releasemanagements. Dieser Ausbau spiegelt sich auch im Testbereich wieder. Das in TFS 2017 eingeführte Test Results Trend-Widget, welches bisher nur den Verlauf der Testergebnisse ausgeführter Builds einer bestimmten Builddefinition visualisieren konnte, wird mit TFS 2018 um die Möglichkeit erweitert, auch Testergebnisse innerhalb von Releases darzustellen. Damit kann der jeweils aktuelle Teststatus von Umgebungen einer bestimmten Releasedefinition auf einen Blick angezeigt werden (vgl. Abb. 4).

image

Abbildung 4: Test Results Trend-Widget für Releasedefinition und –umgebung

Hinzu kommt außerdem das neue Widget Chart for Test Plans. Dieses ermöglicht, ähnlich wie beim Erstellen von Test Case oder Test Result Charts im Test-Hub, die Abbildung des aktuellen Testdesign- oder des Testausführungsstatus von Test Plänen und Suiten (vgl. Abb. 5). Im Vergleich zu den bekannten Charts, birgt das neue Widget den Vorteil, dass größere Datenmengen besser dargestellt werden können.

Abbildung 5: Chart for Test Plans-Widget

 

Fazit

TFS 2018 bringt keine weltbewegenden Neuerungen für das Testing mit sich. Nichtsdestotrotz bringen die kleinen aber feinen Erweiterungen für bereits existierende Features Vereinfachungen für den Projektalltag mit sich. Den Ausreißer bildet jedoch die Abkündigung der Integration von TFS und Lab Management Umgebungen im MTM. Dies stellt zwar ein Breaking Change dar, gibt damit aber auch den Anstoß, alte Pfade zu verlassen und die Vorzüge des neuen Build- und Releasemanagement-Systems auch für den Bereich Testing zu nutzen.

Golo Roden: Einführung in React, Folge 1.1: Release von React 16

Vor einigen Tagen hat Facebook eine neue Version von React veröffentlicht, die unter einer anderen Lizenz steht als die bisherigen Versionen. Außerdem wurde die zugrunde liegende Architektur vollständig überarbeitet. Was ist beim Umstieg zu beachten?

Dmitrij Doberstein: Convert all words first letter to upper case (RegEx & Notepad++)

From time to time we need to replace the first letter of many words to the upper case.

String: "word1" "word2" "word3 and/or word4"

Find part: "\b(\w)(\w+)"

Replace part: "\u$1\E$2"

Result: "Word1" "Word2" "Word3 And/Or Word4"


If we want to exclude any word, e.g and, or, so we can make this so:

String: "word1" "word2" "word3 and/or word4"

Find part: "\b(?!and|or)(\w)(\w+)"

Replace part: "\u$1\E$2"

Result: "Word1" "Word2" "Word3 and/or Word4"

Code-Inside Blog: dnSpy - a OSS IL decompiler and debugger

My colleague was fighting against a nasty bug, that only occures on one machine. Unfortunatly this machine was not a development machine (no VS installed) and we didn’t want to mess with VS remote debugging, because (AFAIK) his would need some additional setup but we were not allowed to install anything.

Soooo… he searched around and found this:

dnSpy - a .NET assembly editor, decompiler, and debugger

The title contains the major points. It is a decompiler, like IL Spy, but addionaly it has a super nice debugger and it looks like a small Visual Studio.

Some pictures how I just decompile Paint.NET and attach the debugger:

x

x

x

I think this is just awesome and it helped my colleague alot.

OSS & Free

The complete project is hosted on GitHub and is “Open Source (GPLv3) and Free Forever”

Checkout the GitHub project page - it contains a lot more information. The tool itself was just 18mb zipped and can be run everywhere.

Its a decompiler!

And just to make sure you keep this in mind: The debugging works with every .NET application (at least in theory), because it decompiles the .NET IL language to C#. It is not a 1:1 debugger, but maybe it can help you.

Check out the dnSpy GitHub Site

Robert Meyer: Self Hosted ASP.NET Core: TagHelper doesn’t work

I have implemented a simple TagHelper in a ASP.NET Core 2.0 Website, which replace the

My custom TimeTagHelper:

[HtmlTargetElement("time")]
public class TimeTagHelper : TagHelper
{
    public override async Task ProcessAsync(TagHelperContext context, TagHelperOutput output)
    {
        output.Content.SetHtmlContent($"<h1>{DateTime.Now.ToShortTimeString()}</h1>");
    }
}

If I start the website project directly, the TagHelper works without problems. Launched from the Console / Service, the

The solution: PreserveCompilationContext

These are the steps that helped me:

  1. Add the following ItemGroup definition to my Selhosted.Website.csproj
 <ItemGroup>
    <EmbeddedResource Include="wwwroot\**\*;Views\**\*;Areas\**\Views" />
  </ItemGroup>

 

  1. Add the PreserveCompilationContext property to the PropertyGroup in Selhosted.Website.csproj
 <PropertyGroup>
    <TargetFramework>netcoreapp2.0</TargetFramework>
    <AssemblyName>SelfHosted.Website</AssemblyName>
    <RootNamespace>SelfHosted.Website</RootNamespace>
    <TypeScriptToolsVersion>2.3</TypeScriptToolsVersion>
    <PreserveCompilationContext>true</PreserveCompilationContext>
  </PropertyGroup>

 

  1. Include the generated SelfHosted.Website.deps.json from the websites bin folder to the SelfHosted.Console project and set the Copy to Output Directory to Copy always.64fcb891c62c3a149c6ff350ebe0b1d3

You can find the sample project in my GitHub Repo: roeb/DotNetCoreSamples


André Krämer: Kostenfreier Xamarin Workshop in Koblenz

Seit einigen Jahren müssen Entwickler einer neuen Herausforderung begegnen. Während die eigene Anwendung in der Vergangenheit in der Regel nur auf einer Plattform, zum Beispiel dem Windows Desktop, oder dem Webbrowser ausgeführt werden musste, besteht heute häufig die die Anforderung auch Clients für mobile Endgeräte auf der Basis von Android, iOS oder Windows zu entwickeln. Dieser Herausforderung kann man mit verschiedenen Lösungsansätzen begegnen: Native Entwicklung mit den Hersteller SDKs, Werkzeugen und Programmiersprachen, also Objective C / Swift und Xcode für iOS, Java / Kotlin und Android Studio für Android und C# / VB.

Don't contact us via this (fleischfalle@alphasierrapapa.com) email address.