diff --git a/lib/modules/versioning/distro.spec.ts b/lib/modules/versioning/distro.spec.ts
new file mode 100644
index 0000000000000000000000000000000000000000..d0dd67db08eab6aa48c943daa80019b0759fa900
--- /dev/null
+++ b/lib/modules/versioning/distro.spec.ts
@@ -0,0 +1,146 @@
+import { DistroInfo } from './distro';
+
+describe('modules/versioning/distro', () => {
+  const di = new DistroInfo('data/ubuntu-distro-info.json');
+
+  it.each`
+    version            | expected
+    ${'jammy'}         | ${true}
+    ${'impish'}        | ${true}
+    ${'hirsute'}       | ${true}
+    ${'groovy'}        | ${true}
+    ${'focal'}         | ${true}
+    ${'eoan'}          | ${true}
+    ${'Wily Werewolf'} | ${false}
+    ${'asdf'}          | ${false}
+    ${'Yakkety'}       | ${false}
+  `('isCodename("$version") === $expected', ({ version, expected }) => {
+    expect(di.isCodename(version)).toBe(expected);
+  });
+
+  it.each`
+    version      | expected
+    ${'jammy'}   | ${'22.04'}
+    ${'impish'}  | ${'21.10'}
+    ${'hirsute'} | ${'21.04'}
+    ${'groovy'}  | ${'20.10'}
+    ${'focal'}   | ${'20.04'}
+    ${'eoan'}    | ${'19.10'}
+    ${'asd'}     | ${'asd'}
+    ${'16.06'}   | ${'16.06'}
+  `(
+    'getVersionByCodename("$version") === $expected',
+    ({ version, expected }) => {
+      expect(di.getVersionByCodename(version)).toBe(expected);
+    }
+  );
+
+  it.each`
+    version    | expected
+    ${'22.04'} | ${'jammy'}
+    ${'21.10'} | ${'impish'}
+    ${'21.04'} | ${'hirsute'}
+    ${'20.10'} | ${'groovy'}
+    ${'20.04'} | ${'focal'}
+    ${'19.10'} | ${'eoan'}
+    ${'asd'}   | ${'asd'}
+    ${'16.06'} | ${'16.06'}
+  `(
+    'getCodenameByVersion("$version") === $expected',
+    ({ version, expected }) => {
+      expect(di.getCodenameByVersion(version)).toBe(expected);
+    }
+  );
+
+  it.each`
+    version            | expected
+    ${'jammy'}         | ${true}
+    ${'impish'}        | ${true}
+    ${'hirsute'}       | ${true}
+    ${'groovy'}        | ${true}
+    ${'focal'}         | ${true}
+    ${'Wily Werewolf'} | ${false}
+    ${'22.04'}         | ${true}
+    ${'21.10'}         | ${true}
+    ${'21.04'}         | ${true}
+    ${'20.10'}         | ${true}
+    ${'Wily Werewolf'} | ${false}
+    ${'asdf'}          | ${false}
+    ${'Jellyfish'}     | ${false}
+  `('exists("$version") === $expected', ({ version, expected }) => {
+    expect(di.exists(version)).toBe(expected);
+  });
+
+  it.each`
+    version      | expected
+    ${'focal'}   | ${false}
+    ${'groovy'}  | ${true}
+    ${'hirsute'} | ${true}
+    ${'impish'}  | ${false}
+    ${'jammy'}   | ${false}
+    ${'20.04'}   | ${false}
+    ${'20.10'}   | ${true}
+    ${'21.04'}   | ${true}
+    ${'21.10'}   | ${false}
+    ${'22.04'}   | ${false}
+  `('isEolLts("$version") === $expected', ({ version, expected }) => {
+    expect(di.isEolLts(version)).toBe(expected);
+  });
+
+  it('retrieves most recent release schedule with version', () => {
+    expect(di.getNLatest(0)).toEqual({
+      codename: 'Jammy Jellyfish',
+      created: '2021-10-14',
+      eol: '2027-04-21',
+      eol_esm: '2032-04-21',
+      eol_server: '2027-04-21',
+      release: '2022-04-21',
+      series: 'jammy',
+      version: '22.04',
+    });
+  });
+
+  it('sends an out of bound argument', () => {
+    expect(di.getNLatest(-1)).toBeNull();
+  });
+
+  it('sends a float as an argument', () => {
+    expect(di.getNLatest(0.1)).toEqual({
+      codename: 'Jammy Jellyfish',
+      created: '2021-10-14',
+      eol: '2027-04-21',
+      eol_esm: '2032-04-21',
+      eol_server: '2027-04-21',
+      release: '2022-04-21',
+      series: 'jammy',
+      version: '22.04',
+    });
+  });
+
+  it('retrieves before most recent release schedule with version', () => {
+    expect(di.getNLatest(1)).toEqual({
+      codename: 'Impish Indri',
+      series: 'impish',
+      created: '2021-04-22',
+      release: '2021-10-14',
+      eol: '2022-07-14',
+      version: '21.10',
+    });
+  });
+
+  it('retrieves focal release schedule', () => {
+    expect(di.getSchedule('20.04')).toEqual({
+      codename: 'Focal Fossa',
+      created: '2019-10-17',
+      eol: '2025-04-23',
+      eol_esm: '2030-04-23',
+      eol_server: '2025-04-23',
+      release: '2020-04-23',
+      series: 'focal',
+    });
+  });
+
+  it('retrieves non-existent release schedule', () => {
+    expect(di.getSchedule('20.06')).toBeNull();
+  });
+});
diff --git a/lib/modules/versioning/distro.ts b/lib/modules/versioning/distro.ts
index 075c2adea6b2307235aadc4f6ffae03cf0cb37de..bb250a7b728a965ef9a8817bb9a63b04ca9f06dd 100644
--- a/lib/modules/versioning/distro.ts
+++ b/lib/modules/versioning/distro.ts
@@ -1,3 +1,4 @@
+import { DateTime } from 'luxon';
 import dataFiles, { DataFile } from '../../data-files.generated';
 
 interface DistroSchedule {
@@ -12,7 +13,7 @@ interface DistroSchedule {
   eol_elts?: string;
 }
 
-type DistroDataFile = 'data/ubuntu-distro-info.json';
+export type DistroDataFile = 'data/ubuntu-distro-info.json';
 
 export type DistroInfoRecord = Record<string, DistroSchedule>;
 
@@ -23,6 +24,9 @@ export class DistroInfo {
     string,
     DistroInfoRecordWithVersion
   >();
+
+  private readonly _sortedInfo: DistroInfoRecordWithVersion[] = [];
+
   private readonly _distroInfo: DistroInfoRecord;
 
   constructor(distroJsonKey: DistroDataFile) {
@@ -35,12 +39,45 @@ export class DistroInfo {
       const schedule = this._distroInfo[version];
       this._codenameToVersion.set(schedule.series, { version, ...schedule });
     }
+
+    const arr = Object.keys(this._distroInfo).sort(
+      (a, b) => parseFloat(a) - parseFloat(b)
+    );
+
+    for (const v of arr) {
+      const obj = { version: v, ...this._distroInfo[v.toString()] };
+      if (!obj.eol) {
+        // istanbul ignore next
+        continue;
+      }
+      this._sortedInfo.push(obj);
+    }
   }
 
+  /**
+   * Check if input is a valid release codename
+   * @param input A codename
+   * @returns true if input is a codename, false otherwise
+   */
   public isCodename(input: string): boolean {
     return this._codenameToVersion.has(input);
   }
 
+  /**
+   * Checks if given input string is a valid release version
+   * @param input A codename/semVer
+   * @returns true if release exists, false otherwise
+   */
+  public exists(input: string): boolean {
+    const ver = this.getVersionByCodename(input);
+    return !!this._distroInfo[ver];
+  }
+
+  /**
+   * Get semVer representation of a given codename
+   * @param input A codename
+   * @returns A semVer if exists, otherwise input string is returned
+   */
   public getVersionByCodename(input: string): string {
     const schedule = this._codenameToVersion.get(input);
     if (schedule) {
@@ -49,6 +86,11 @@ export class DistroInfo {
     return input;
   }
 
+  /**
+   * Get codename representation of a given semVer
+   * @param input A semVer
+   * @returns A codename if exists, otherwise input string is returned
+   */
   public getCodenameByVersion(input: string): string {
     const di = this._distroInfo[input];
     if (di) {
@@ -58,7 +100,58 @@ export class DistroInfo {
     return input;
   }
 
-  public getSchedule(input: string): DistroSchedule {
-    return this._distroInfo[input];
+  /**
+   * Get schedule of a given release
+   * @param input A codename/semVer
+   * @returns A schedule if available, otherwise undefined
+   */
+  public getSchedule(input: string): DistroSchedule | null {
+    const ver = this.getVersionByCodename(input);
+    return this._distroInfo[ver] ?? null;
+  }
+
+  /**
+   * Check if a given release has passed its EOL
+   * @param input A codename/semVer
+   * @returns false if still supported, true otherwise
+   */
+  public isEolLts(input: string): boolean {
+    const ver = this.getVersionByCodename(input);
+    const schedule = this.getSchedule(ver);
+    const endLts = schedule?.eol ?? null;
+    let end = schedule?.eol_lts ?? null;
+
+    // ubuntu: does not have eol_lts
+    // debian: only "Stable" has no eol_lts, old and oldold has both
+    if (!end) {
+      end = endLts;
+    }
+
+    if (end) {
+      const now = DateTime.now();
+      const eol = DateTime.fromISO(end);
+      return eol < now;
+    }
+
+    // istanbul ignore next
+    return true;
+  }
+
+  /**
+   * Get distro info for the release that has N other newer releases.
+   * Example: n=0 corresponds to the latest available release, n=1 the release before, etc.
+   * In Debian terms: N = 0 -> stable, N = 1 -> oldstable, N = 2 -> oldoldstalbe
+   * @param n
+   * @returns Distro info of the Nth latest release
+   */
+  public getNLatest(n: number): DistroInfoRecordWithVersion | null {
+    const len = this._sortedInfo.length - 1;
+    const i = len - Math.floor(n);
+
+    if (len >= i && i >= 0) {
+      return this._sortedInfo[i];
+    }
+
+    return null;
   }
 }
diff --git a/lib/modules/versioning/ubuntu/index.spec.ts b/lib/modules/versioning/ubuntu/index.spec.ts
index 1d286adfabc33bffeba6d73aa31adebe707adcd3..065d1bda9d143e53c9178169d8360fc90fcf049d 100644
--- a/lib/modules/versioning/ubuntu/index.spec.ts
+++ b/lib/modules/versioning/ubuntu/index.spec.ts
@@ -79,7 +79,7 @@ describe('modules/versioning/ubuntu/index', () => {
     ${'impish'}    | ${true}
     ${'jammy'}     | ${true}
   `('isValid("$version") === $expected', ({ version, expected }) => {
-    expect(!!ubuntu.isValid(version)).toBe(expected);
+    expect(ubuntu.isValid(version)).toBe(expected);
   });
 
   test.each`
@@ -94,8 +94,7 @@ describe('modules/versioning/ubuntu/index', () => {
   `(
     'isCompatible("$version") === $expected',
     ({ version, range, expected }) => {
-      const res = ubuntu.isCompatible(version, range);
-      expect(!!res).toBe(expected);
+      expect(ubuntu.isCompatible(version, range)).toBe(expected);
     }
   );
 
@@ -107,7 +106,7 @@ describe('modules/versioning/ubuntu/index', () => {
     ${'20.04'}   | ${true}
     ${'>=20.04'} | ${false}
   `('isSingleVersion("$version") === $expected', ({ version, expected }) => {
-    expect(!!ubuntu.isSingleVersion(version)).toBe(expected);
+    expect(ubuntu.isSingleVersion(version)).toBe(expected);
   });
 
   test.each`
@@ -198,8 +197,7 @@ describe('modules/versioning/ubuntu/index', () => {
     ${'impish'}   | ${false}
     ${'jammy'}    | ${false}
   `('isStable("$version") === $expected', ({ version, expected }) => {
-    const res = !!ubuntu.isStable(version);
-    expect(res).toBe(expected);
+    expect(ubuntu.isStable(version)).toBe(expected);
   });
 
   test.each`
@@ -252,7 +250,7 @@ describe('modules/versioning/ubuntu/index', () => {
     ${'impish-'} | ${false}
     ${'JAMMY'}   | ${false}
   `('isVersion("$version") === $expected', ({ version, expected }) => {
-    expect(!!ubuntu.isVersion(version)).toBe(expected);
+    expect(ubuntu.isVersion(version)).toBe(expected);
   });
 
   test.each`